(I'm not 100% sure if the title is the best description, I'll edit if necessary)
I'm trying to create a voronoi region to do a split-screen effect in a game. I'm following the steps outlined in this PDF. As I understand them:
Find a line running along the midway point between players
Find the vertices of the intersections of each player's respective lines, bounded by the area in question
Create a region for each player using the convex hull of those vertices.
I found the algorithms for step 3, where I'm stuck is how to find the vertices of each region. Using this image as an example:
Looking at player C, I worked out that I need to find the intersection point of the A/C line, the B/C line and the D/C line. Easy enough. Where I'm stuck is that if a line hits an edge, then I have to find vertices for where it hits an edge, plus any corners in the region (like the bottom left in this image). But I can't just throw the sides of the region in as lines, because with more than 4 players, a region isn't guaranteed to touch the edge of the screen, so those points would need to be discarded and I'm not sure how to factor that into the process.
If it makes any difference, I'm doing this in C# / Unity.
I think it might be beneficial for you to take a look at the wiki article on
Voronoi_diagrams and their dual diagrams, called Delaunay triangulations.
If you can construct a Voronoi diagram, then you can construct its dual Delaunay triangulation and vice versa. The vertices of the Voronoi diagram are the centers of the circles circumscribed around the triangles of the Delaunay triangulation. As such, every Voronoi vertex is the intersection point of the three orthogonal bisectors of its corresponding dual triangle from the Delaunay triangulation.
Particularly, for some specific algorithms, you can check out:
Fortune's algorithm or the dual of Bowyer-Watson algorithm.
The image contour is a array points. I need to approach two points on each side to create four line segments.
Image contour
A possible approach.
Find the convex hull of these points.
Then find the two vertices which are the furthest apart. This gives a first diagonal.
Then find the two other vertices that are the farthest from the first diagonal. This gives a second diagonal.
Now you can just use the quadrilateral formed by these four vertices.
If you want a tighter fit, you can consider the subsets of points in the four quadrants defined by the diagonals, and compute best fit lines, for example by least squares.
Another one using convex hull too :
Find convex hull of points set
Compute convex hull arc length.
And finally compute an approximate polynomial contour with error equals to 10% of arc length (if more than 4 points increase percent of error)
CvInvoke.ApproxPolyDP(vec, vecApprox, 0.1 * arcLength, true);
This give good results and commonly used for licence plate détection wich is the same problem.
So I am attempting to make complex polygons from a set of randomly generated vertices in 2D. I would like to allow concave polygons to exist, as well as to assure that every vertex in the set is included in the boundary (so the algorithm must be able to handle convex AND concave hulls), and also assure that the lines created by the boundary never intersect. Every version of a concave hull generating algorithm has assumed that it is acceptable to have varying levels of concavity, and that some points may not be a part of the boundary.
I feel like this may be a much simpler problem than it seems to me, but I cant figure out how to make sure I can order the vertices in such a way that drawing a line between vertices having adjacent indices in the list makes a polygon conforming to those standards. For a convex hull it is easy to just find the centroid of the polygon and sort the vertices by their polar angle respective to it, but I am currently unaware of an equivalent idea for concave.
i had to come up with a solution to this problem with a twist.
I had to render a set of randomized points basically to a concave hull.
I used the marching cubes algorithm generating A concave hull!
Basically i just counted and weighed each point reveived, and computed edgeindeces for rendering them depending on my value grid.
https://stemkoski.github.io/Three.js/Marching-Cubes.html
i oriented my self on this implementation.... have fun :)
I have two points specified as lat/long(s) and would like to insert a new point in between them a certain distance (in meters) from point the initial point.
Presumably I convert the lat/longs to radians and then use a version of midpoint formula?
How can i accomplish this task?
I'm living in c# land btw.
TIA
The exact solution is not that simple (an approximate solution is just given by linear interpolation). You're not going to love it.
The trajectory follows a great circle, which is the intersection between the sphere and a plane through the center and the two given points.
First convert from spherical to Cartesian coordinates. Then by the cross product of the vectors from the center to the two points, determine the direction of the normal to the plane (normalize the vector). Then use the formula for 3D rotation around this axis and rotate the starting point. The rotation angle is given by the desired distance divided by the radius of the Earth. Finally, convert back to spherical coordinates.
I have 1 red polygon say and 50 randomly placed blue polygons - they are situated in geographical 2D space. What is the quickest/speediest algorithim to find the the shortest distance between a red polygon and its nearest blue polygon?
Bear in mind that it is not a simple case of taking the points that make up the vertices of the polygon as values to test for distance as they may not necessarily be the closest points.
So in the end - the answer should give back the closest blue polygon to the singular red one.
This is harder than it sounds!
I doubt there is better solution than calculating the distance between the red one and every blue one and sorting these by length.
Regarding sorting, usually QuickSort is hard to beat in performance (an optimized one, that cuts off recursion if size goes below 7 items and switches to something like InsertionSort, maybe ShellSort).
Thus I guess the question is how to quickly calculate the distance between two polygons, after all you need to make this computation 50 times.
The following approach will work for 3D as well, but is probably not the fastest one:
Minimum Polygon Distance in 2D Space
The question is, are you willing to trade accuracy for speed? E.g. you can pack all polygons into bounding boxes, where the sides of the boxes are parallel to the coordinate system axes. 3D games use this approach pretty often. Therefor you need to find the maximum and minimum values for every coordinate (x, y, z) to construct the virtual bounding box. Calculating the distances of these bounding boxes is then a pretty trivial task.
Here's an example image of more advanced bounding boxes, that are not parallel to the coordinate system axes:
Oriented Bounding Boxes - OBB
However, this makes the distance calculation less trivial. It is used for collision detection, as you don't need to know the distance for that, you only need to know if one edge of one bounding box lies within another bounding box.
The following image shows an axes aligned bounding box:
Axes Aligned Bounding Box - AABB
OOBs are more accurate, AABBs are faster. Maybe you'd like to read this article:
Advanced Collision Detection Techniques
This is always assuming, that you are willing to trade precision for speed. If precision is more important than speed, you may need a more advanced technique.
You might be able to reduce the problem, and then do an intensive search on a small set.
Process each polygon first by finding:
Center of polygon
Maximum radius of polygon (i.e., point on edge/surface/vertex of the polygon furthest from the defined center)
Now you can collect, say, the 5-10 closest polygons to the red one (find the distance center to center, subtract the radius, sort the list and take the top 5) and then do a much more exhaustive routine.
For polygon shapes with a reasonable number of boundary points such as in a GIS or games application it might be quicker easier to do a series of tests.
For each vertex in the red polygon compute the distance to each vertex in the blue polygons and find the closest (hint, compare distance^2 so you don't need the sqrt() )
Find the closest, then check the vertex on each side of the found red and blue vertex to decide which line segments are closest and then find the closest approach between two line segments.
See http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/ (it's easy to simply for the 2d case)
This screening technique is intended to reduce the number of distance computations you need to perform in the average case, without compromising the accuracy of the result. It works on convex and concave polygons.
Find the the minimum distance between each pair of vertexes such that one is a red vertex and one is a blue. Call it r. The distance between the polygons is at most r. Construct a new region from the red polygon where each line segment is moved outward by r and is joined to its neighbors by an arc of radius r is centered at the vertex. Find the distance from each vertex inside this region to every line segment of the opposite color that intersects this region.
Of course you could add an approximate method such as bounding boxes to quickly determine which of the blue polygons can't possibly intersect with the red region.
Maybe the Frechet Distance is what your looking for?
Computing the Fréchet distance between two polygonal curves
Computing the Fréchet Distance Between Simple Polygons
I know you said "the shortest distance" but you really meant the optimal solution or a "good/very good" solution is fine for your problem?
Because if you need to find the optimal solution, you have to calculate the distance between all of your source and destination poligon bounds (not only vertexes). If you are in 3D space then each bound is a plane. That can be a big problem (O(n^2)) depending on how many vertexes you have.
So if you have vertex count that makes that squares to a scarry number AND a "good/very good" solution is fine for you, go for a heuristic solution or approximation.
You might want to look at Voronoi Culling. Paper and video here:
http://www.cs.unc.edu/~geom/DVD/
I would start by bounding all the polygons by a bounding circle and then finding an upper bound of the minimal distance.
Then i would simply check the edges of all blue polygons whose lower bound of distance is lower than the upper bound of minimal distance against all the edges of the red polygon.
upper bound of min distance = min {distance(red's center, current blue's center) + current blue's radius}
for every blue polygon where distance(red's center, current blue's center) - current blue's radius < upper bound of min distance
check distance of edges and vertices
But it all depends on your data. If the blue polygons are relatively small compared to the distances between them and the red polygon, then this approach should work nicely, but if they are very close, you won't save anything (many of them will be close enough). And another thing -- If these polygons don't have many vertices (like if most of them were triangles), then it might be almost as fast to just check each red edge against each blue edge.
hope it helps
As others have mentioned using bounding areas (boxes, circles) may allow you to discard some polygon-polygon interactions. There are several strategies for this, e.g.
Pick any blue polygon and find the distance from the red one. Now pick any other polygon. If the minimum distance between the bounding areas is greater than the already found distance you can ignore this polygon. Continue for all polygons.
Find the minimum distance/centroid distance between the red polygon and all the blue polygons. Sort the distances and consider the smallest distance first. Calculate the actual minimum distance and continue through the sorted list until the maximum distance between the polygons is greater than the minimum distance found so far.
Your choice of circles/axially aligned boxes, or oriented boxes can have a great affect on performance of the algorithm, dependent on the actual layout of the input polygons.
For the actual minimum distance calculation you could use Yang et al's 'A new fast algorithm for computing the distance between two disjoint convex polygons based on Voronoi diagram' which is O(log n + log m).
Gotta run off to a funeral in a sec, but if you break your polygons down into convex subpolies, there are some optimizations you can do. You can do a binary searches on each poly to find the closest vertex, and then I believe the closest point should either be that vertex, or an adjacent edge. This means you should be able to do it in log(log m * n) where m is the average number of vertices on a poly, and n is the number of polies. This is kind of hastey, so it could be wrong. Will give more details later if wanted.
You could start by comparing the distance between the bounding boxes. Testing the distance between rectangles is easier than testing the distance between polygons, and you can immediately eliminate any polygons that are more than nearest_rect + its_diagonal away (possibly you can refine that even more). Then, you can test the remaining polygons to find the closest polygon.
There are algorithms for finding polygon proximity - I'm sure Wikipedia has a good review of them. If I recall correctly, those that only allow convex polygons are substantially faster.
I believe what you are looking for is the A* algorithm, its used in pathfinding.
The naive approach is to find the distance between the red and 50 blue objects -- so you're looking at 50 3d Pythagorean calculations + sorting to find the answer. That would only really work for finding the distance between center points though.
If you want arbitrary polygons, maybe your best best is a raytracing solution that emits rays from the surface of the red polygon with respect to the normal, and reports when another polygon is hit.
A hybrid might work -- we could find the distance from the center points, assuming we had some notion of the relative size of the blue polygons, we could cull the result set to the closest among those, then use raytracing to narrow down the truly closest polygon(s).