I need a way to construct a 2D-polygon with holes - algorithm

My object is constructed in a honeycomb grid. All objects are connected. The red lines represents the connection between each node. I heard Binary Space Partitioning (BSP) Trees is good with this type of problem, but not sure what is front and back in my case.
I've implemented the lookup using the honeycomb grid system as shown (x , y)
class Node {
Point position; //center position
Point grid; //honeycomb grid system
}
class MyObject {
Node lookup(Point grid);
}
I need a data structure that represent the graph as user add more nodes onto the scene and a way to quickly determine if a grid point is (against MyObject):
1. outside
2. inside
3. inside a hole

How big is the space you're working in?
Simulate the whole thing with a simple rectangular grid assuming even-rows are staggered right.
Any node has coordinates [x,y]
For (y%2 == 0) neighbor nodes are [x-1,y][x+1,y][x,y+1][x,y-1][x-1,y-1][x-1,y+1]
For (y%2 == 1) neighbor nodes are [x-1,y][x+1,y][x,y+1][x,y-1][x+1,y-1][x+1,y+1]
Each node can be full or empty and empty nodes can be checked or not checked. Originally all empty nodes are not checked.
Check if a node belongs to a hole by:
if node is full - it does not belong to hole, it belongs to the shape.
if a node is empty mark node as checked.
Iterate over all neighbor nodes:
Skip nodes marked as checked or full
recursively repeat the search for all nodes not checked.
If the recursion brings you into any x<0, y<0, x>MAX_X, y>MAX_Y, abort. The node is outside the shape
If the recursion ends without finding edges of the playfield, the node belongs to a hole.
Additionally, you may now repeat the procedure turning all checked nodes into outside or hole for later reference.
If you want to index all holes at start, it may be easier to find all not checked empty nodes at borders of the playfield (x==0, y==0, x==MAX_X, y==MAX_Y) and use the above algorithm to mark them as outside. All remaining empty nodes are holes.
Depending on your grid size, you may implement it as 2D array of structs/objects containing object state (or even chars, with status as bits of the number), sized [MAX_X+1][MAX_Y+1] if it's reasonably sized, or as a list (vector) of full nodes, each containing its coords, status and if you want this to be more speed-optimal, neighbors. In this case, search the shape, finding all empty neighbor nodes for potential holes. Edge nodes with extreme coords (lowest/highest x/y) belong to "outside". Follow their empty neighbors that have full neighbors, to find the outer edge of the shape. All remaining are inner edges and after following the algorithm starting with them you'll have all your "holes".

My suggestion:
Assign each tile a center position in a 2d cartesian space.
Build a binary search tree (BST) containing all center positions.
For a query point find the relative position to the nearest occupied tile using that BST.
Determine whether that position is inside or outside the tile using some geometric formula, e.g., as in here:
Is a point inside regular hexagon
Alternatively, work with an approximation using squares, e.g., as seen here:
Hexagonal Grids, how do you find which hexagon a point is in?

Related

Can a quad-tree be used to accurately determine the closest object to a point?

I have a list of coordinates and I need to find the closest coordinate to a specific point which I'll call P.
At first I tried to just calculate the distance from each coordinate to P, but this is too slow.
I then tried to store these coordinates as a quad-tree, find the leaf node that contains P, then find the closest coordinate in that leaf by comparing distances of every coordinate to P. This gives a good approximation for the closest coordinate, but can be wrong sometimes. (when a coordinate is outside the leaf node, but closer). I've also tried searching through the leaf node's parent, but while that makes the search more accurate, it doesn't make it perfect.
If it is possible for this to be done with a quad-tree, please let me know how, otherwise, what other methods/data structures could I used that are reasonably efficient, or is it even possible to do this perfectly in an efficient manner?
Try "loose quadtree". It does not have a fixed volume per node. So it can adjust each node's bounding volume to adapt to the items added.
If you don't like quadtree's traversing performance and if your objects are just points, adaptive-grid can perform fast or very close to O(N). But memory-wise, loose quadtree would be better.
There is an algorithm by Hjaltason and Samet described in their paper "Distance browsing in spatial databases". It can easily be applied to quadtrees, I have an implementation here.
Basically, you maintain a sorted list of object, the list is sorted by distance (closest first), and the objects are either point in your tree (you call the coordinates) or nodes in the tree (distance to closest corner, or distance=0 if they overlap with you search point).
You start adding all nodes that overlap with your search point, and add all points and subnodes in these points.
Then you simply return points from the top of the list until you have as many closest points as you want. If a node is at the top of the list, add points/subnodes from that node to the list and check the top of the list again. Repeat.
yes you can find the closest coordinate inside a quad-tree even when it is not directly inside the leaf. in order to do that, you can do the following search algorithm :
search the closest position inside the quad-tree.
take its distance from your initial position
search all the nodes inside this bounding box from your root node
return the closest node from all the nodes inside this bounding box
however, this is a very basic algorithm with no performance optimizations. among other things :
if the distance calculated in 2. is less than the distance to the border of the tree node, then you don't need to do 3 or 4. (or you can take a node that is not the root node)
also, 3 and 4 could be simplified into a single algorithm that only search inside the tree with the distance to the closest node as the bounding box.
And you could also sort the way you search for the nodes inside the bounding box by beginning to search for the nodes closest to your position first.
However, I have not made complexity calculation, but you should expect a worst case scenario on one node that is as bad if not worst than normal, but in general you should get a pretty decent speed up all the while being error free.

Tree that contains points - improvement needed

Currently, I'm making my own structure that holds points in 2D space. I know that there are many ready-made algorithms and kind of trees but I want to have something lightweight. So I have (x, y) point that is inside of each node, each node contains 4 children: topLeft, topRight, botLeft, botRight next node.
Inserting:
Every new node is inserted depends on its position.
If the tree is empty, insert the new node / If the tree is not empty, go to the first node and do:
1. Decide what is the position of the current node in regard of the new node.
2. If it is e. g. topLeft and it is not occupied then insert the new node.
3. If position topLeft is occupied go to this node and repeat.
Removing:
The structure I need does not need to have "removing particular node" function, so if the job is done the destructor deletes the whole tree recursively.
Check if the node is inside of particular area:
If the tree is not empty go the first node and then:
1. Check if given area's x is less than node's x and area's y is less than node's y if it is then go to the topLeft children node (if it exists).
2. The same for the topRight (check area's x + width position and y).
3. The same for botRight (check area's x + width and y + height).
4. The same for botLeft (check area's x and y + height).
5. Check if current node is inside of area if it is do stuff you want to do with a point. Recursively go back and repeat.
That's how my structure looks like, the image shows which bonds would be checked for particular area (orange color):
link
My question is, is there is a better algorithm? What Can I improve? I saw quadtree but it seems to be different and it contains more data. I need something that can easily hold moving objects in 2D. I appreciate your help.
What you have is basically a quadtree, but you use your data for doing splits instead of the typical middle.
You can improve the system a bit by switching to a KD tree. It's similar except at each point you split along a single dimension. The main difference is that you only have two pointers per node (instead of 4) so you save about half the memory.
Another thing is that you split your space until you get to 1 point. Because modern CPUs do really fancy things, for small values, linear search will be faster than traversing the tree. So I would only split a space when you have 50-100 points already in there. This will also save a bunch of pointers that don't need to stored at all.
If you know something about the distribution of your points you might be able to do something better. If the distribution is kinda uniform you can simply chunk your space into uniform cells and store the points in the associated cells. A rule of thumb says if you have N points you should have sqrt(N) cells, but you should try and see what works best.

Query points in circle areas

Here is a picture to illustrate the problem:
In the picture there are some feature points shown as blue crosses. I know the coordinate (x,y) for all of the features. Now I want to query which features are inside the circle area (green circle). In practice, there are around 500 features and 300 queries (300 different circles, different centers and radius). I know the parameters (position, radius) of circles. Is there any good algorithm which can do this task?
Current I have two ideas.
Most stupid one, just iterate through all of the features in each
query. This is slower.
A rough idea. Separate the whole picture to some sub-pictures. Put features into a tree structure according to sub-pictures, if features in the same sub-pictures, then put in the same leaf. In each query, find out which sub-picture are covered by the circle and check all of the feature in these sub-pictures.
Does anyone out there have any better ideas?
The most common way is to put the points into a K-D tree or similar: https://en.wikipedia.org/wiki/K-d_tree
To find the points within a circle, you get the list of points in order of increasing distance from the center, and stop when the distance exceeds the circle radius.
To get list of points in order of increasing distance, you can use a priority queue that can hold both points and internal nodes of the tree, which lets you remove them in order of distance.
For points (leaves), the distance is just the distance of the point from the center point. For internal nodes, the distance is the smallest distance from the center point to any point that could possibly be in that node.
To search, you just put the root of the tree in the priority queue, and repeat:
Remove the head of the priority queue;
If the head of the queue was a point, then it is the closest point in the tree that you have not yet returned. You know this, because if any internal node could possibly have a closer point, then it would have been returned first from the priority queue;
If the head of the queue was an internal node, then put its children back into the queue
This will produce all the points in the tree in order of increasing distance from the center point.

Nearest neighbour search in a constantly changing set of line segments

I have a set of line segments. I want to perform the following operations on them:
Insert a new line segment.
Find all line segments within radius R of a given point.
Find all points within radium R1 of a given point.
Given a line segment, find if it intersects any of the existing line segments. Exact intersection point is not necessary(though that probably doesnt simplify anything.)
The problem is algorithms like kd/bd tree or BSP trees is that they assume a static set of points, and in my case the points will constantly get augmented with new points, necessitating rebuilding the tree.
What data-structure/algorithms will be most suited for this situation ?
Edit: Accepted the answer that is the simplest and solves my problem. Thanks everyone!
Maintaining a dynamic tree might not be as bad as you think.
As you insert new points/lines etc into the collection it's clear that you'd need to refine the current tree, but I can't see why you'd have to re-build the whole tree from scratch every time a new entity was added, as you're suggesting.
With a dynamic tree approach you'd have a valid tree at all times, so you can then just use the fast range searches supported by your tree type to find the geometric entities you've mentioned.
For your particular problem:
You could setup a dynamic geometric tree, where the leaf elements
maintain a list of geometric entities (points and lines) associated
with that leaf.
When a line is inserted into the collection it should be pushed onto
the lists of all leaf elements that it intersects with. You can do
this efficiently by traversing the subset of the tree from the root
that intersects with the line.
To find all points/lines within a specified radial halo you first need
to find all leaves in this region. Again, this can be done by traversing
the subset of the tree from the root that is enclosed by, or that
intersects with the halo. Since there maybe some overlap, you need to
check that the entities associated with this set of leaf elements
actually lie within the halo.
Once you've inserted a line into a set of leaf elements, you can find
whether it intersects with another line by scanning all of the lines
associated with the subset of leaf boxes you've just found. You can then
do line-line intersection tests on this subset.
A potential dynamic tree refinement algorithm, based on an upper limit to the number of entities associated with each leaf in the tree, might work along these lines:
function insert(x, y)
find the tree leaf element enclosing the new entitiy at (x,y) based on whatever
fast search algorithm your tree supports
if (number of entities per leaf > max allowable) do
refine current leaf element (would typically either be a bisection
or quadrisection based on a 2D tree type)
push all entities from the old leaf element list onto the new child element
lists, based on the enclosing child element
else
push new entity onto list for leaf element
endif
This type of refinement strategy only makes local changes to the tree and is thus generally pretty fast in practice. If you're also deleting entities from the collection you can also support dynamic aggregation by imposing a minimum number of entities per leaf, and collapsing leaf elements to their parents when necessary.
I've used this type of approach a number of times with quadtrees/octrees, and I can't at this stage see why a similar approach wouldn't work with kd-trees etc.
Hope this helps.
One possibility is dividing your space into a grid of boxes - perhaps 10 in the y-axis and 10 in the x-axis for a total of 100.
Store these boxes in an array, so it's very easy/fast to determine neighboring boxes. Each box will hold a list vector of line segments that live in that box.
When you calculate line segments within R of one segment, you can check only the relevant neighboring boxes.
Of course, you can create multiple maps of differing granularities, maybe 100 by 100 smaller boxes. Simply consider space vs time and maintenance trade-offs in your design.
updating segment positions is cheap: just integer-divide by box sizes in the x and y directions. For example, if box-size is 20 in both directions and your new coordinate is 145,30. 145/20==7 and 30/20==1, so it goes into box(7,1), for a 0-based system.
While items 2 & 3 are relatively easy, using a simple linear search with distance checks as each line is inserted, item 4 is a bit more involved.
I'd tend to use a constrained triangulation to solve this, where all the input lines are treated as constraints, and the triangulation is balanced using a nearest neighbour rather than Delaunay criterion. This is covered pretty well in Triangulations and applications by Øyvind Hjelle, Morten Dæhlen and Joseph O'Rourkes Computational Geometry in C Both have source available, including getting sets of all intersections.
The approach I've taken to do this dynamically in the past is as follows;
Create a arbitrary triangulation (TIN) comprising of two triangles
surrounding the extents (current + future) of your data.
For each new line
Insert both points into the TIN. This can be done very quickly by
traversing triangles to find the insertion point, and replacing the
triangle found with three new triangles based on the new point and
old triangle.
Cut a section through the TIN based on the two end points, keeping a
list of points where the section cuts any previously inserted lined.
Add the intersection point details to a list stored against both
lines, and insert them into the TIN.
Force the inserted line as a constraint
Balance all pairs of adjacent triangles modified in the above process
using a nearest neighbour criterion, and repeat until all triangles
have been balanced.
This works better than a grid based method for poorly distributed data, but is more difficult to implement. Grouping end-point and lines into overlapping grids will probably be a good optimization for 2 & 3.
Note that I think using the term 'nearest neighbour' in your question is misleading, as this is not the same as 'all points within a given distance of a line', or 'all points within a given radius of another point'. Nearest neighbour typically implies a single result, and does not equate to 'within a given point to point or point to line distance'.
Instead of inserting and deleting into a tree you can calculate a curve that completely fills the plane. Such a curve reduce the 2d complexity to a 1d complexity and you would be able to find the nearest neighbor. You can find some example like z curve and hilbert curve. Here is a better description of my problem http://en.wikipedia.org/wiki/Closest_pair_of_points_problem.

Suggestions on speeding up edge selection

I am building a graph editor in C# where the user can place nodes and then connect them with either a directed or undirected edge. When finished, an A* pathfinding algorithm determines the best path between two nodes.
What I have: A Node class with an x, y, list of connected nodes and F, G and H scores.
An Edge class with a Start, Finish and whether or not it is directed.
A Graph class which contains a list of Nodes and Edges as well as the A* algorithm
Right now when a user wants to select a node or an edge, the mouse position gets recorded and I iterate through every node and edge to determine whether it should be selected. This is obviously slow. I was thinking I can implement a QuadTree for my nodes to speed it up however what can I do to speed up edge selection?
Since users are "drawing" these graphs I would assume they include a number of nodes and edges that humans would likely be able to generate (say 1-5k max?). Just store both in the same QuadTree (assuming you already have one written).
You can easily extend a classic QuadTree into a PMR QuadTree which adds splitting criteria based on the number of line segments crossing through them. I've written a hybrid PR/PMR QuadTree which supported bucketing both points and lines, and in reality it worked with a high enough performance for 10-50k moving objects (rebalancing buckets!).
So your problem is that the person has already drawn a set of nodes and edges, and you'd like to make the test to figure out which edge was clicked on much faster.
Well an edge is a line segment. For the purpose of filtering down to a small number of possible candidate edges, there is no harm in extending edges into lines. Even if you have a large number of edges, only a small number will pass close to a given point so iterating through those won't be bad.
Now divide edges into two groups. Vertical, and not vertical. You can store the vertical edges in a sorted datastructure and easily test which vertical lines are close to any given point.
The not vertical ones are more tricky. For them you can draw vertical boundaries to the left and right of the region where your nodes can be placed, and then store each line as the pair of heights at which the line intersects those lines. And you can store those pairs in a QuadTree. You can add to this QuadTree logic to be able to take a point, and search through the QuadTree for all lines passing within a certain distance of that point. (The idea is that at any point in the QuadTree you can construct a pair of bounding lines for all of the lines below that point. If your point is not between those lines, or close to them, you can skip that section of the tree.)
I think you have all the ingredients already.
Here's a suggestion:
Index all your edges in a spatial data structure (could be QuadTree, R-Tree etc.). Every edge should be indexed using its bounding box.
Record the mouse position.
Search for the most specific rectangle containing your mouse position.
This rectangle should have one or more edges/nodes; Iterate through them, according to the needed mode.
(The tricky part): If the user has not indicated any edge from the most specific rectangle, you should go up one level and iterate over the edges included in this level. Maybe you can do without this.
This should be faster.

Resources