I have a map with a hex-grid on it. I'm trying to construct "groupings" of Hexagons in order to create sub regions. I've got actually constructing the regions down, but the problem is the order in which each point of the 'edge polygon' is determined. What I'm looking for is an algorithm that, given a set of points, can (hopefully) construct the proper shape of the outer hexagons. What's important is the order of the points as when I pass that to Dynmap to construct a polygonal region, it's done by point order.
Shape-wise I assume it's a bit like convex hull, I believe, but wherein I don't want a new shape to be constructed with lesser points. As an example, below is what I'm getting and is wrong:
Below is the desired result, so to speak:
Thanks guys!
This might not be terribly efficient, but it's the first thing that comes to mind.
First, forget about the edges and just draw the red background color for every hexagon.
Now you only want to draw exterior edges. That is, edges that are not adjacent to another hexagon. Create an Edge class with proper equals/hashcode (which is agnostic of the ordering of the points). For each hexagon, generate all its edges and collect them into a map which counts each edge. Now draw only the edges that have been counted once.
Map<Edge,Integer> counts = new HashMap<>();
for (Hexagon hexagon : hexagons)
for (Edge edge : edges(hexagon))
counts.merge(edge, 1, (x,y) -> x+y);
counts.forEach((edge,count) -> { if (count == 1) draw(edge); });
There is probably a more efficient way, but this has the benefit of being simple, and it's probably fast enough for your use case.
Related
I'm looking for a way to match a list of 2D coordinates (which are in drawing order) to a shape from a list of shapes, or to find if it doesn't match any shape.
I've had a look at this, but I'm not too sure how exactly I'd relate that to things like straight/bent lines.
One idea I've thought of is to determine all the corners of each shape from the list (in order), and then check if the points from the list of coordinates that are found to be corners match one of these shapes (in the same order), using something like this. This might be a bit too strict for what I want to do however, as I want there to be a decent amount of leeway in the detection.
I'm also not sure what exactly I should use to pull corners (or lines etc.) from the list of coordinates - would it be worth turning it into an image or should I just try to detect things straight from the coordinate list?
For example, a possible input could be:
And some shapes to match could be: or or
And in this case, it would match the L shape.
For context, the reason I'm doing this is for a game where you have to draw symbols in the air to cast a spell.
If there aren't too many distinct shapes, here is what I woud try:
turn the curves to a (length, angle) representation; the length can be estimated as the sums of segment lengths, and the angle as the direction of the segments;
to be able to compare two representations, normalize the total length to unit (this will make the comparison size-independent), and sample at regular distances; said differently, obtain a vector of N angles at points equally spaced along the curve;
now to recognize a curve, compute the sum of absolute differences with similar vectors obtained from reference model, and keep the smallest sum.
There is no need for strict accuracy.
Note that this representation is not rotation-invariant, on purpose. It is also sensitive to the drawing order (from one endpoint to the other, or conversely), this can be unwanted. Finally, beware of the closed paths (circles), that people might start anywhere.
In my application I work with OpenGL and large arrays of data.
One of the things I need to do is I receive multiple "simple" polygons that can be either convex or concave. By simply I mean geometrical definition - polygons without holes and intersecting edges.
I receive this poligons in the form of linked loop of points (vertices), where each Vi is connected to Vi-1 and Vi+1 points and nothing else. The last point is also connected to the first, giving us a loop as a result.
I will say right now that I figured out polygon triangulation, and it works like a charm (I used ear-clipping method for now).
But, I need to build LOTS of those polygons, millions of them. To minimize the load I decided to split my world into "chunks", squares like in Minecraft. I then use frustum culling and other optimizations methods to either render or discard/simplify these chunks and meshes in them.
So, what I want to do is: if the polygon I received lies in several different chunks - then I want to split it into meshes for each of those chunks. Basically, I want to create multiple polygons that are divided on chunk borders, and THEN triangulate them and create meshes for rendering.
As a result I want to have one (or several) contours that I can then triangulate.
here's a picture of my task:
I made an algorythm for splitting it myself that I thought would work, but I found that it only works if the contour in any given chunk doesn't break up, like you see in the example (in other words if there's only one figure in any given chunk).
I thought to ask here if anyone knows any good algorythms for that task? I'll probably come up with something myself, but practice shows that there's almost always a better and simpler ready-made solution out there. I'd really appreciated it if someone could give me a useful link or an article, if not with a solution itself, then something that could give ideas.
I'm not at work at the moment, because it's weekend, so I'll be trying/testing the things on Monday.
What I came up with at the moment, however, is a very simple solution.
test all points in the contour.
If point i and point i+1 don't belong to the same chunk (which I can test easily):
then find an intersection between chunk border and the line made by these two points.
add this new point to the contour between the original two points.
When every edge of the polygon was tested like that - triangulate it.
because we have points on the edges of the chunks - then during triangulation the triangles will fit exactly into chunk borders
for each triangle, decide which chunk it belongs to and generate the mesh in THAT chunk.
I won't go into details of some optimization ideas - like not needing to evaluate resulting triangles if the entire figure fits within the same chunk.
This is a stab in the dark at writing some pseudo code that may work. Feel free to implement it and select your own answer with the actual code if it works.
First, convert your vertex array to a double linked list that loops from the last element to the first element. Or it may be better to model it as an undirected graph instead, because a point may have missing neighbours.
Then apply the algorithm below for each quadrant, starting with the full polygon each time. You can cut down the size of that polygon by culling vertices that are outside of the quadrant and at least 1-neighbour away from edges that cross the cutting lines.
// We need to keep track of the points that we insert on the cutting lines
let LIX = List of X-Cut-Line Intersection Points
let LIY = List of Y-Cut-Line Intersection Points
foreach Edge AB in Poly where A is inside the quadrant, B outside
// Insert points into the polygon that intersect the X-Cut-Line
if AB Intersects X-Cut-Line
let Ix = Intersection Point
Insert Ix between AB so that A<->B becomes A<->Ix
B can be removed from the polygon now
Add Ix to LIX
// Insert points into the polygon that intersect the Y-Cut-Line
if AB.Intersects Y-Cut-Line
let Iy = Intersection Point
Insert Iy between AB so that A<->B becomes A<->Iy
B can be removed from the polygon now
Add Iy to LIY
// Then iterate pairs of points along each cutting line to join them
sort LIX by X Ascending
while (LIX.Length > 0)
let P0 = LIX[0]
let P1 = LIX[1]
Link P0 and P1
Remove P0 and P1 from LIX
sort LIY by Y Ascending
while (LIY.Length > 0)
let P0 = LIY[0]
let P1 = LIY[1]
Link P0 and P1
Remove P0 and P1 from LIY
Finally, you can look for cycles in the resulting linked list/graph to find the new polygons. Each cycle should in theory not contain points from the other cycles already detected so it is an individual polygon.
I have a collection of java.awt.Shape objects covering a two-dimensional plane with no overlap. These are from a data set of U.S. Counties, at a fairly low resolution. For an (x,y) latitude/longitude point, I want a quick way to identify the shape which county contains that point. What's an optimal way to index this?
Brute force would look like:
for (Shape eachShape : countyShapes) {
if (eachShape.contains(x, y)) {
return eachShape;
}
}
To optimize this, I can store the min/max bounds of the (possibly complex) shapes, and only call contains(x, y) on shapes whose rectangular bounds encompass a given x,y coordinate. What's the best way to build this index? A SortedMultiset would work for indexing on the x minima and maxima, but how to also include the y coordinates in the index?
For this specific implementation, doing a few seconds of up-front work to index the shapes is not a problem.
If possible you could try a bitmap with each shape in a different color. Then simply query the point and the color and lookup the shape.
This question is outside the scope of Stackoverflow but the answer is probably Binary Space Partitioning.
Roughly:
Divide the space in two either on the x coordinate or y coordinate using the mid-point of the range.
Create a list of counties on the two sides of that line (and divided by that line).
On each side of that line divide the collections again by the other dimension.
Continue recursively building a tree dividing alternately by x and y until you reach a satisfactory set of objects to examine by brute force.
The conventional algorithm actually divides the shapes lying across the boundary but that might not be necessary here.
A smart implementation might look for the most efficient line to divide on which is the one where the longest of the two lists is the smallest.
That involves more up front calculation but a more efficient and consistently performing partition.
You could use an existing GIS library like GeoTools and then all the hard work is already done.
Simply load your shapefile of counties and execute queries like
"the_geom" contains 'POINT(x y)
The quickstart tutorial will show you how to load the shapes, and the query tutorial will show you how to query them.
Having min an max values of coordinates of the bounds not guarantee that you can determine if one point is in or out in any situations. If you want achieve this by yourself you should implement some algorithm. There's a good one that is called "radial algorithm", I recommend that uses this, and it isn't so complicated to implement, there are sufficient bibliography and examples.
Hope this help.
I have an array with the coordinates of the center of small circles which have the same radius. I know how to find when the mouse is over a circle, but my array is big and I want the fastest way to calculate this operation.
Is there a way of finding if the mouse is over a circle without looping all the array for each movement of the mouse?
Initially, set up some 'zones' for quicker reference:
Separate the whole surface into a small number of rectangles that don't intersect.
For each of these rectangles, list all circles that are at least partially contained in it. (A circle may end up listed in multiple rectangles, but that's okay.)
Every time you want to check whether the mouse is over a circle, you won't have to go through the whole array of circles. Instead:
Figure out which rectangle you're in.
Check only the circles that are listed under that rectangle.
This looks like a problem of optimizing the boundary check for a large number of items. The approach of going linearly does not scale well for thousands of circles.
This is a good topic to read on the net. But first, without going there, I'll try to explain (as an exercise) what I would explore. I would create a binary tree and partition the space, then instead of using an array I would put the circle points in such a tree. Looking the tree elements that are closer to the actual X,Y location becomes a matter of doing a binary search on the tree. The you have the closest point as a result of that search and can check for collision on it. There is still more to be done to the algorithm, and further optimizations are needed. For example, how to check for more points and not only the final one? Potentially I need a tree for the X coordinate, and another for the Y coordinate, etc... But I would explore these ideas. I will come back to this post and expand my reply with an actual example and a more concrete solution.
What if you check the coordinates that are r(radius) distance from the mouse? Then you could narrow your search down in the array if it is ordered.
Say you have a collection of points with coordinates on a Cartesian coordinate system.
You want to plot another point, and you know its coordinates in the same Cartesian coordinate system.
However, the plot you're drawing on is distorted from the original. Imagine taking the original plane, printing it on a rubber sheet, and stretching it in some places and pinching it in others, in an asymmetrical way (no overlapping or anything complex).
(source)
You know the stretched and unstretched coordinates of each of your set of points, but not the underlying stretch function. You know the unstretched coordinates of a new point.
How can you estimate where to plot the new point in the stretched coordinates based on the stretched positions of nearby points? It doesn't need to be exact, since you can't determine the actual stretch function from a set of remapped points unless you have more information.
other possible keywords: warped distorted grid mesh plane coordinate unwarp
Ok, so this sounds like image warping. This is what you should do:
Create a Delaunay triangulation of your unwarped grid and use your knowledge of the correspondences between the warped and unwarped grid to create the triangulation for the warped grid. Now you know the corresponding triangles in each image and since there is no overlapping, you should be able to perform the next step without much difficulty.
Now, to find the corresponding point A, in the warped image:
Find the triangle A lies in and use the transformation between the triangle in the unwarped grid and the warped grid to figure out the new position.
This is explained explicitly in detail here.
Another (much more complicated) method is the Thin Plate Spline (which is also explained in the slides above).
I understood that you have one-to-one correspondence between the wrapped and unwrapped grid points. And I assume that the deformation is not so extreme that you might have intersecting grid lines (like the image you show).
The strategy is exactly what Jacob suggests: Triangulate the two grids such that there is a one-to-one correspondence between triangles, locate the point to be mapped in the triangulation and then use barycentric coordinates in the corresponding triangle to compute the new point location.
Preprocess
Generate the Delaunay triangulation of the points of the wrapped grid, let's call it WT.
For every triangle in WT add a triangle between the corresponding vertices in the unwrapped grid. This gives a triangulation UWT of the unwrapped points.
Map a point p into the wrapped grid
Find the triangle T(p1,p2,p3) in the UWT which contains p.
Compute the barycentric coordinates (b1,b2,b3) of p in T(p1,p2,p3)
Let Tw(q1,q2,q3) be the triangle in WT corresponding to T(p1,p2,p3). The new position is b1 * q1 + b2 * q2 + b3 * q3.
Remarks
This gives a deformation function as a linear spline. For smoother behavior one could use the same triangulation but do higher order approximation which would lead to a bit more complicated computation instead of the barycentric coordinates.
The other answers are great. The only thing I'd add is that you might want to take a look at Free form deformation as a way of describing the deformations.
If that's useful, then it's quite possible to fit a deformation grid/lattice to your known pairs, and then you have a very fast method of deforming future points.
A lot depends on how many existing points you have. If you have only one, there's not really much you can do with it -- you can offset the second point by the same amount in the same direction, but you don't have enough data to really do any better than that.
If you have a fair number of existing points, you can do a surface fit through those points, and use that to approximate the proper position of the new point. Given N points, you can always get a perfect fit using an order N polynomial, but you rarely want to do that -- instead, you usually guess that the stretch function is a fairly low-order function (e.g. quadratic or cubic) and fit a surface to the points on that basis. You then place your new point based on the function for your fitted surface.