Determine when a polygon is closed by a new side - c#

My program has a List<Vector3> of unique points (A, B, C, ...) which are created each time a user draws a unique line (1, 2, 3, ...). Lines are stored in a List<int> where every two ints are the indices of each point to form a single line. No two lines can have the same two points, no points can occupy the same position, and stray lines are allowed.
Diagram
Points: {A, B, C, D, E} //Each letter represents a 2d or 3d position
Sides: {0,1,1,2,1,3,3,4,4,2} //(Each int is an index in Points, every pair is a side)
I am trying to find an efficient way of determining when a new line (Green, 5) closes a polygon with any number of sides. I have a way of doing this: iterating through each line connected to each side of the new line(and all subsequent lines) until they share a point (D).
Completed Polygon
My only problem here is that the more sides a polygon has, I need to do exponentially more checks (Every two additional sides on the polygon causes me to check one layer deeper on all attached sides).
Is there a way to reduce the number of checks I need to do in order to close the polygon?
Not exactly the same as Cycles in an Undirected Graph. This knows that at least one cycle is present and connected to a given side, and is looking for only the smallest cycle possible connected to that side. Other sides are irrelevant and it should avoid them.

It all depends on the level of optimization you need. For simple pictures (some what like < 10 - 100k lines) you can get away with running a BFS every time.
High level algorithm:
First you need something to store the graph using one of the Graph representation. Then whenever the user draws a line you take either of the two points and do a BFS on that point.
If you can reach the same point with your BFS and the path length is > 2 then you have a polygon.
The catch would be that since the graph is bidirectional you need to be careful when walking thru it. Do not re-visit nodes that you have already visited.

Related

Best approach for storing elements in C# that have within epsilon definition of equality

The program uses vertices in R^2 as nodes and there are edges between nodes, and ultimately more is built from there. There are a high number of circuitous ways that a point (x,y) in R^2 might be reached that may rely on layer after layer of trig functions. So it makes sense to define one vertex as the canonical vertex for all points in a square with side length 2*epsilon centered at the point. So various calculations happen, out comes a point (x,y) where I wish to put a vertex, a vertex factory checks to see if there is already vertex deemed as canonical that should be used for this point, if so it returns that vertex, if not a new vertex is created with the coordinates of the point and that vertex is now deemed canonical. I know this can lead to ambiguities given the possibility for overlap of the squares but that is immaterial for the moment, epsilon can be set to make the probability of such a case vanishingly small.
Clearly a list of canonical vertices must be kept.
I have working implementations using List<Vertex> and HashSet<Vertex>, however the vertex creation process seems to scale poorly when the number of vertices grows to over over 100,000 and incredibly poorly if the number gets anywhere near 1,000,000.
I have no idea how to efficiently implement the VertexFactory. Right now Vertex has method IsEquivalentTo(Vertex v) and returns true if v is contained in the square around the instance vertex calling it, false otherwise.
So the the vertex creation process looks like this:
Some point (x,y) get calculated and requests a new vertex from the vertex manager.
VertexManager creates a temporary vertex temp then uses a foreach to iterate over every vertex in the container using IsEquivalentTo(temp) to find a match and return it, if no match is found then add temp to the container and return it. I should state that if a match is found obviously it breaks out of the foreach loop.
I may be way off but my first guess would be put an order on the vertices such as
v1 < v2 iff ( (v1.X < v2.X) || ( (v1.X == v2.X) && (v1.Y < v2.Y) ) )
and then store the vertices in a sorted container. But to be honest I do not know enough about about the various containers to know which is the most appropriate for the purpose, standard C# best practices, etc
Edit:
I cannot mark the comment as an answer so thanks to GSerg whose comment guided me to kd-trees. This is exactly what I was looking for.
Thanks

Looking for an Algorithm for getting Polygons in List of open Pathes(Lists of Vector2d )

i´m wondering if there is an algorithm to all get the closed Polygons in a set of Pathes, like in the Image. I know there is the Intersection algorithm and als intesection of two closed Polygons, but I have just these vector of lines as an input. I´m working in C# and Unity. But of course this is a general question.
Thanks ahead
How about something like this:
Intersect each polyline with all others.
Split each polyline at the intersection points. Creating separate segments between each intersection point.
Put each segment in a structure representing a graph, with a node at each intersection, and edges to describe how nodes are connected.
Start any arbitrary segment
Traverse the graph, selecting the first clockwise edge at each node.
When the starting edge is reached, Output the traversed polygon
Mark each traversed edge.
Repeat from step 5, selecting the next un-marked edge.
There are multiple ways to describe a graph in this way. I would suggest using half-edge structure, where each edge is stored two times, in opposite directions. So the nodes would have a list of outgoing edges, and each edge would have a single target node. This makes it easier to mark traversed edges since you do not need to keep track of the direction you are traveling in.

Searching area enclosed by a path

I want to search areas enclosed by a complex path.
Input
var path = new []{new Point(X1,Y1),new Point(X2,Y2),new Point(X3,Y3),new Point(X4,Y4),new Point(X5,Y5)};
I want it.
(X2,Y2)-(X3,Y3)-(Xa,Ya)
(Xa,Ya)-(X4,Y4)-(Xb,Yb)
How do I search it?
there's a few steps to what you are doing here. You need to:
Perform line intersections between each of the line segments to find where your intersection points are.
Create centroid points at the average of the Start point A, Start point B, Collision point, (and then for each permutation of Start Point [A, B], end point [A, B] and collision point.
Perform a dotproduct or point in tris check to verify that your centroid point is inside a triangle and if so:
Calculate the area of the Tri using the standard area in triangle formula (I think it's 1/2 base times height off the top of my head)
Good luck!
you can use this approach in a few steps:
Break the lines where they meet other lines and create a new list of lines (or paths)
Eliminate lines with one free end (if a line doesn't meet another one at the start or the end)
Start from one point and go through lines to the other points and try to find the correct route back to the start point (if you pass a duplicate point, the route is wrong)
Save newly found closed route
Eliminate all points that are inside the newly found area and connected lines
Eliminate all points with just two connected lines and also these two lines
Eliminate all lines that their center point is inside the newly found area
Go to step 3 until there left no line in the list
Now you have a list of enclosed areas
Note: you can easily find a good approach for the calculation of the intersection point of two lines, the area of the enclosed part, the center point of a line, and Checking that a point is inside an area
Best wishes,

Tiling Algorithm/Data Structures?

I'm thinking of creating a program to let me play or solve slitherlink puzzles, like on krazydad.com. It consists of tiles of 4, 5, 6, 7 and 8 sides. All but the seven sided tiles seem to have sides with the same length, with the sides between two seven sided tiles (and therefore connecting five-sided tiles to 4 sided tiles) having sides of approximately 70% of the normal length. As you can see in the picture below, octagons are surrounded by alternating pentagons and hexagons. These are attached to others a by the far sides of the hexagons. Attached to the tips of the pentagons are smaller lines connecting to squares connecting to other groups. Around the squares are then formed seven-sided figures with two short sides. I think the outer edge is defined by just omitting tiles that are too far away from the center.
For a data structure I think I need a graph connecting all nodes. I can let the user click to place a solid line on the closest link, and I can check for loops or too many lines entering a node fairly easily. I'll also need to create tiles and associate lines to them, with inner lines being assigned to both tiles, but treated as one line.
As for setting it up, I am thinking of manually figuring out the points and defining the minimal set of repeated tiles (1 8, 4 5, 4 6, 4 7 and 1 4), then placing them next to each other. When placing, I would check for existing close points to each one I'm placing and combine them if found. Then I would need to check for duplicate lines and merge them as well.
Is there an easier or cleaner way to A) generate the tiling or B) merge the nodes and links when doing my tiling?
some observations that might help:
if you join the centres of neighbouring polygons you have a delaunay triangulation (1).
the dual (2) of the delaunay triangulation is the graph above (with slightly different edge lengths, but you can adjust that if necessary)
there's a discussion here (3) of how to generate graphs from delaunay triangulations
so, putting that together, you could:
generate the centres of the tiles (see below)
construct the delaunay triangulation from the tile centres (by joining neigbours).
find the dual to get the graph you want (the process of finding the dual should be supported by a good graph library)
to generate the pattern of tile centres, take the minimal set and start with the centre 8. for each 90 degree rotation about there, add the (rotated) minimal set (plus an 8 in addition to the one you're rotating around), removing duplicates. then do the same on the 8s that you have added (either recurse or use a stack).
once you have the centres, i'm not sure what the best way to connect neighbours would be - you want some efficient way of generating a set of candidates. but it's not a hard problem, just fiddly (a "fancy" solution would be quadtree or spatial hashes, but just a crude binning would probably be enough).

What's the best way to implement one-dimensional collision detection?

I'm writing a piece of simulation software, and need an efficient way to test for collisions along a line.
The simulation is of a train crossing several switches on a track. When a wheel comes within N inches of the switch, the switch turns on, then turns off when the wheel leaves. Since all wheels are the same size, and all switches are the same size, I can represent them as a single coordinate X along the track. Switch distances and wheel distances don't change in relation to each other, once set.
This is a fairly trivial problem when done through brute force by placing the X coordinates in lists, and traversing them, but I need a way to do so efficiently, because it needs to be extremely accurate, even when the train is moving at high speeds. There's a ton of tutorials on 2D collision detection, but I'm not sure the best way to go about this unique 1D scenario.
Apparently there's some confusion about what my data looks like.
I'm simulating a single site, not an entire region. The trains can be of any length, with different types of cars, but there is only ever one train. My train data is in the form {48,96,508,556,626,674,...}, indicating the distances from the front of the train (0) to the center of the axle.
(Train data will more likely come to me in the form of an ordered list of Car objects, each of which has a length and a list of integers representing axle distances from the front of that car, but it all gets aggregated into a single list, since all axles are the same to me.)
My switches are all within several hundred feet, and will often be entirely covered by the train, The switches can be at any interval from hundreds of feet to several inches apart, and is in the same form as the train: {0,8,512,520,...}, indicating the distances from the beginning of the site to the center of the switch.
Finally, I know the distance at which the wheel activates the switch, in inches.
For example, using the above sample data, and a an activation distance of 8 inches, the first switch at X=0 would activate when the train hits X=40, meaning the train is 40 inches into the site. When the train hits X=48, the switch at X=8 is also activated. At X=56, the first switch goes off, and at X=64, the second switch also goes off. Different axles are turning different switches on and off as it crosses the site.
The train is usually running at speeds under 10 mph, but can go much higher. (Right now our simulation is capped at 30 mph, but higher would be great.)
Have a sorted list of all the switches' coordinates and use binary search on the list to find the nearest switch. Then check to see how far it is and whether or not it's a collision.
O(log n)
Another option is to exploit the fact that the train moves along the track and can only ever come close to two switches, one behind and one ahead.
Construct a doubly-linked list of all the switches and position an extra node to represent the train in the correct location in the linked list. Then only check proximity to the switch the train is headed towards.
O(1)
To save memory, store the sorted coordinates in an array and simply keep track of which indexes the train is between.
Pre-process your switch locations and sensitivity range into a list of track segments. Each segment has a length, and between each segment a set of switch 'on' or 'off' events.
switch_on ( 0 ), ( length: 8 ), switch_on ( 1 ), // x = zero here
segment ( length: 8 ), switch_off ( 0 ),
segment ( length: 8 ), switch_off ( 1 ),
segment ( length: 488 ), switch_on ( 2 ),
segment ( length: 8 ), switch_on ( 3 ),
segment ( length: 8 ), switch_off ( 2 ),
segment ( length: 8 ), switch_off ( 3 ),
...
For each axle, have its current location also represented along with the track segment it is on.
If you're doing an event based simulation, the next event should be scheduled for the min value of the distance from an axle to the end of its current track segment. This is independent of the train speed, and accurate (you won't miss switches if the train goes faster). Store the events in a heap if necessary (it's often not worth it for less than 30 or so, profile the event scheduling if necessary).
Processing an event will be O(no-of-axles). Most steps will involve one or two switch state changes and a position update. At each event, one axle will cause one switch to go on or off (switches which would be simultaneous according to the data cause two events, zero time apart), and all axle times to the end of their segments need to be compared. You can either assume that all axles travel at the same speed or not; it doesn't matter as far as processing the events, it only makes the calculation of the time to reach the next switch specific to the axle in question.
If you're on a fixed time step simulation, then process all events which would have occurred up to the time at the end of the step, then one event to move the axles to the point they reach at the end of the step.
Store the switch list as a doubly-linked list as indicated by Ben.
Keep a pointer in the wheel object (or structure, assuming there is one) to the next switch and the previous switch relative to your current position. Intialize these as the wheel is placed on the track.
As you move over each switch, swap out the "next" and "previous" switches in your wheel object for the new "next" and "previous" that can be quickly obtained by examining the doubly-linked list.
This avoids all searches, except possibly initial placement of the wheel.
Additionally, the "switch" structure could be used to hold a proximity pointer back to all of the wheels that list it as "previous" or "next". (There's a mutex here, so be careful of who updates this.) This can provide a quick update of who's approaching any given switch and their distance from it.
Assuming that Axle-to-Axle distances are always larger the activation distance, and that routes don't change frequently after the train enters, you should be able to speed things up with pre-calculation. Basically, for each switch, calculate a list of train travel distances at which it will toggle, then walk through the lists as the train advances.
Pseudocode:
axles = {48,96,508,556,626,674,...}
switches ={0,8,512,520,...}
activate = 8
float toggledist[num_switches]
boolean switchState[num_switches]={false,false,false,...}
int idx[num_switches]
for (i in switches)
n = 0
for (a in axles)
toggledist[n++] = switches[i]+axles[a]-activate
toggledist[n++] = switches[i]+axles[a]+activate
travel= 0.0f;
each (cycle)
travel += TrainVelocity*time;
for (i in switches)
while (trigger>=toggledist[idx[i]])
switchState[i]=!switchState[i];
//additional processing for switch change here, if needed
idx[i]++;

Categories

Resources