Forming Polygons Out of Edges - c#

I am currently working with a graph, modeling a network of streets. The graph consists of an array of edges, marking that two streets are connected. The edges are a simple data structure containing an array of two streets.
Using this, I am hoping to find a way to locate cycles within the map. Specifically, I am looking to create "lots" in areas completely surrounded by roads.
So far, I have found a lot of information regarding finding cycles in graphs, but nothing specific to my problem. Can I use a cyclical graph to solve my problem? If not, how should this problem be solved? Thank you!
Edit: Additional information about source data
The data consists of a custom class called RoadSegment, shown below.
Each RoadSegment consists of a start position, an end position, and a list of all of the other RoadSegments it is connected to. (The other variables are irrelevant for this task)
Every place in which two RoadSegments are connected is defined in a class called RoadEdge.
The program contains a list of all RoadEdges.

This is more of a computational geometry problem than graph theory. I would tackle it with this algorithm.
Calculate position of all intersections
LOOP over intersections
Select line segment starting at intersection and heading most closely east to west
Follow line segment to next intersection ( if none continue to next intersection )
Turn right
Follow line segment to next intersection ( if none continue to next intersection )
...
IF reached starting intersection then add to plot list
I have not received any response from you, so I have implemented this using some simplifying assumptions - that all valid plots have 4 sides and the roads are approximately orthogonal to each other.
Here is the C++ code
std::vector<std::vector<cxy>> cCity::plotfinder()
{
// vector of plots
std::vector<std::vector<cxy>> vplot;
// loop over intersections
for (auto &inter : myIntersection)
{
// check if this is the north east corner of a quadrilateral plot
std::vector<cxy> plot;
plot.push_back(inter.myLocation);
// find road from intersection going in approx east west direction
auto road = inter.EastToWest();
// find next intersection on road
cIntersection next1;
if (!nextIntersection(next1, inter, road))
continue; // intersection does not exist, so this is not a plot
// add to plot
plot.push_back(next1.myLocation);
// continue to check the remaining two plot edges, if they exist
road = next1.NorthToSouth();
cIntersection next2;
if (!nextIntersection(next2, next1, road))
continue;
plot.push_back(next2.myLocation);
road = next2.WestToEast();
cIntersection next3;
if (!nextIntersection(next3, next2, road))
continue;
plot.push_back(next3.myLocation);
// found a good plot, add to list
vplot.push_back(plot);
}
return vplot;
}
You can find this code and a complete test application at https://github.com/JamesBremner/CityPlotter
Output from a sample run
road from -100, 0 to 100, 0
road from -100, 10 to 100, 10
road from 0, 100 to 0, -100
road from 10, 100 to 10, -100
1 plots found
0 10, 10 10, 10 0, 0 0,

Related

Calculate depth of indentation in model using two points? [duplicate]

This question already has answers here:
Calculate depth of indentation in an model using three point system?
(2 answers)
Closed 4 years ago.
Via Raycasting one can select a point on an GameObjects Collider. In the short visual two points are represented with small spheres denoting user selection. The desire is to calculate the depth of any spot in an models indentation. Current thought is to use a system in which the user selects a point within the depth of the indentation and a point outside of it than calculating the depth using Vector math.
As of now, the information available to us is the two points (Vectors) in space and the distance between them. How do we use the aforementioned data to calculate a point perpendicular to the point in the depth? Thought being if this point is calculable than the depth would be the distance between those two points. How to go about this, and is it feasible?
Visual:
I don't think that 2 points are enough. You, seeing the whole scene, know the planes where both points lie so you can see the direction of the shortest distance (perpendicular) segment. But just for two points there are infinitely many other valid planes going through them. The only thing you can say is that the depth is bound by the distance between those two points.
Consider following example: one point A is (0,0,0) and B is (2,1,0). How deep is the indentation? The answer is: you don't know.
Assume first that the planes are (the plane a contains the point A and the plane b contains the point B):
a is X = 0 while b is X = 2. Then the indentation depth is clearly 2.
a is Y = 0 while b is Y = 1. Then the indentation depth is clearly 1.
finally if a is Z = 0 and b is Z = 0. Then the indentation depth is clearly 0.
Actually change the planes direction you can get any depth between 0 and the distance between A and B.
The only solution I see is to fix at least one of the two planes by selecting 3 points on that plane. And then the problem becomes trivial. Having 3 points you find the plane equation in a form of
a*x + b*y + c*z + d = 0
Then the distance from a point (x1,y1,z1) to that plane is
dist = (a*x1 + b*y1 + c*z1 + d)/sqrt(a^2+b^2+c^2)

Algorithm design - a better way of finding sets of triangles that share a vertex

I'm trying to calculate a Voronoi graph from a Delaunay Triangulation, I've got the triangulation data in the form of a collection of verticies (red circles on graph) and triangles (blue lines on graph):
I'm able to calculate the Voronoi graph verticies easily (the intersection of the red lines) by just getting the circumcenter of all the triangles.
However, I need to derive the 'cell' information for each red polygon. To do this, for each red vertices I need to find a set of triangles that share that same vertex. So for the circled vertex, I need the green triangles:
So my code looks like this (c#):
foreach (Vertex3 vertex in DelaunayVertices)
{
VoronoiCell cell = new VoronoiCell();
cell.Vertex = vertex;
//seach all triangles for the ones that match this.
foreach (Face3 face in DelaunayTriangles)
{
if (face.Vertices.Where(v => v.Equals(vertex)).Any())
{
//shares vertices, add it's circumcenter as an edge vertex of the cell
cell.EdgeVertices.Add(face.Circumcenter);
}
}
}
Which is of course, hugely inefficient, as it's searching everything. However, the collections of faces, or verities are completely unsorted (and I'm unsure exactly how to sort them, or if it would help). Just to be confusing, there are 3 dimensional vertex on the surface of a sphere.
The only thing I have to find adjacent vertexes or faces for each triangle I have it's Adjacency, so for the orange triangle below, I know the three green triangles:
I'm thinking it might be more efficient to traverse this graph, but I'm struggling to come up with an approach to an algorithm that will produce sets that share points.
You could try a space filling curve, i.e. sorting the vertexes along a hilbert curve. You could also try a point-in-polygon test but it's very difficult. You could also try to make a bitmap with brute force algorithm.
If you're willing to store a secondary vertex-to-triangle data-structure, you can first traverse the triangle list, pushing each triangle onto the adjacency lists associated with its three vertices:
for (all tria's ti)
for (all nodes ni in tria ti)
v2t[ni] <- ti
end for
end for
This is just an O(n) sweep.

Sorting and grouping points

I have a fairly simple object with shape defined by 12 vertices. When doing hidden lines calculation on this object(I am using Cad Control to do this) it returns collection of lines making up the shape which is usually much more than minimum count of lines to draw such a shape, please see attached picture:
Each segment between points is a line. I would like to remove points that are marked in red color leaving only minimum count (yellow cross) necessary to draw shape.
One approach would be to sort them clockwise and then loop through them checking if a cross product of three adjacent points in the list is zero and then deleting the middle one. Unfortunately, it is impossible to predict, how points will be sorted, therefore this is not an option.
Second approach would be to loop through the collection of lines offered by cad control and to find all points that are on the same line, sort them (pointsLineA, pointsLineB, pointsLineC, etc) From there it would be much easier.
So far I have accomplished that I loop through line collection (get each lines points) and in nested loop I loop through the same collection(copy of it) to check if the points of any random line in the collection lie on the same line as points from line from first loop. This involves two loops and modifying collections on the run. To make it short, it is a MESS. If you would like to see code sample, please let me know.
To make sure everything is clear - my first objective is to group points so that in each group would appear points only belonging to one line. Any suggestions?
With 12 vertices (or hundreds of vertices) I wouldn't do space partitioning (I'm thinking about adaptive quadtree, 2D-tree (kd-tree with k=2)).
I'd store for each vertex which lines it belongs to (it's easier to assign an ID to each vertex and line instead of comparing each time the coordinates of vertices).
vertex(1)=(2.5,3.97) <- vertex coordinates
vertex(2)=( 13.453 , 24.687 )
lines_for_Vertex(1)= {1,5} if vertex 1 is member of lines 1 and 5
lines_for_Vertex(3)={2,5,7} if vertex 3 is member of lines 2,5 and 7
lines_for_vertex(9)={4} if vertex 9 is member of line 4 (edge or segment not connected)
lines_for_vertex(3)={} if vertex 3 is not connected (not member of any segment)
(maybe some cases are impossible for you)
You can assign ID to lines with position inside your collection of lines.
In any case, if you do this changes or keep your collections of lines, inside the nested loops you have to collect information of point to be deleted without changing anything.
So instead of doing:
if vertices are aligned then remove the vertex in the middle
you fill a list 'to_remove' with this information:
to_remove.add(vertex in the middle) <- with the ID is easier
Then when the two loops end, you can remove all the vertices collected in the list. If you have the array 'lines_for_vertex' it's easy to find the two segments to be collapsed into one (eg. if vertex to remove is 1, the collapsing lines are 1 and 5).
If you build a structure even for lines, referring to ID of its vertices
e.g. line(5)={1,3} if line with ID=5 connects vertices 1 and 3
(compare with lines_for_vertex above), it's easier to know how to collapse lines.
You need to retrieve the topology of the polygon. The means to rearrange the vertices in a closed loop. By comparing the endpoint coordinates, you can find those that match and obtain a graph with edges between endpoints, and endpoints merged.
From this representation you can easily detect and remove the alignments.

Finder what point is to the left of a line/point after spinning it

I am currently trying to write a shader in unity that draws a triangular pattern around countries in a risk-styled game if both countries are not owned by the same player (visual aid to see your borders).
Right now, I'm having an issue with making the shader set the countries properly.
It always sets country 0 to the left, and country 1 to the right - country 0 and 1 are set programically.
The line, a border, can be between 0 and 359 degrees.
How I find the countries 0 and 1 is I draw 3 points to the left and right of the midpoint of the line, one .01f, one .1f and one 1f away from the midpoints in each direction, then spin them around the midpoint to the appropriate location.
After that I do an even-odd check to see if the points are inside or outside of each country, and compare the weight results (closest gets 3 points, mid gets 2, furthest gets 1, just in case someone builds a really screwed up country that flanks the other country).
In my test map, a close to equally sliced octagon, the borders showed up correctly (after I reversed the positions of country 0 and 1 in the event the angle was over 90 and less then or equal 180). Worked without a flaw, but in other maps it doesn't work very well.
Everything but the country allocation works well, so I'm curious if anyone knows of a better way to figure out which point is to the left or a spun line, or a better conceptual way to handle this.
That above is basically when I'm doing, red being left right being blue, then I'm just checking 3 different spots then weighing in the lefts and rights found with even/odding it into the appropriate countries (one at +/- .01, the other at +/- .1 and the third 1, in case of even/odd rounding issues with closeness).
I then flip them if I find that country A is to the right, as it is on the left according to the angles I had draw. (my shader renders left first and right second, hence why I do this).
which way is left/right on a line?
From last edit is this not your case. Why not use dot product?
So if the line goes in -x direction the result is negative and if in the +x direction then the result is positive. if the result is zero that means the line goes up or down only or it is juts a point. If you need specific direction instead of left/right then use appropriate a vector instead of x axis.
dot(a,b)=a.x*b.x+a.y*b.y in 2D
dot(a,b)=a.x*b.x+a.y*b.y+a.z*b.z in 3D
Image is relevant for cases where a vector is in unit size in that case the result of dot is perpendicular projection of b into a just like on image
on which side is some point?
I think this is what you need.
As you can see if you handle line (P0,P1) and point P you want to classify as triangle then its polygon winding determines also the side of the line. So for implicit axis directions:
CW(clockwise) polygon winding means right side of the line
CCW(counter-clockwise) polygon winding means left side of the line
How to get winding? ... simply compute normal vector and get its Z coordinate. Its polarity (sign) determines winding (CW/CCW or the other way around depends on the coordinate system).
normal vector is computed as cross product of the two vertices of triangle (P1-P0)x(P-P1)
No need to compute other axises just the z so:
normal.z = ((P1.x-P0.x)*(P.y-P1.y)) - ((P1.y-P0.y)*(P.x-P1.x))
Now just do if (normal.z<0) ... else ... it should never be zero unless you call it for point on the line or the line is a point ... look here at similar question: Determine rotation direction /toward/ variable point on a circle

How to merge two polygons (arrays of objects) programatically?

[edit: I tried to rewrote my question a bit because it seems, that nobody understands what I want... and I thought, that it is a hard algorithm only for me :) ]
Problem I am facing is joining of individual polygons. Each is a 4-point polygon. The final result is then a merge / union of two polygons.
Following image shows one version of possible result (results may vary, because that black filled part can be different for each result).
I start with something like:
Polygon one = [A,B,C,D]; // (A/B/C/D) might look like : new Point {x = 10, y = 15}
Polygon two = [E,F,G,H];
And I need an algorithm for calculating union of these two sets, so I will get result like:
Polygon total = [I,J,K,L,M,N]; // = new points
I don't have to visualize it (even when I do..), I just need the set of points defining new polygon (union of those two), because my final result will be a centroid of that merged polygon.
I already have algorithm to calculate centroid based on set of input points. But I need to get the right points first.
So far, I have found mentions about convex-hull algorithm, but I am afraid that it would generate following polygon (which is wrong):
EDIT:
So different way, how to look at this problem:
I have a program, that is able to work with objects, that are represented by 4 points. Each point has two attributes (x coordinate, y coordinate).
Then the program is able to draw lines between these points. These lines will then look like a square, rectangle or polygon.. this result depends on given coordinates, but I know, that I will be always using points, that will generate polygons. Once the points are connected, the program is able to fill this connected area. Once this is drawn, you can see following image:
BUT: The program doesn't know, that he just made a polygon. He only knows, that he got 4 points from me, he connected them and filled them.
Then I have second object (=polygon), which is defined by another set of points (different coordinates). Program again doesn't know that he's creating a filled polygon.. he just did some operations with 4 given points. Result in this case is another polygon:
Now, we just draw two polygons at display.. and we gave them such coordinates, that they overlap each other. The result looks like this (considering only the filled area):
My program just draw two polygons. Fine. You can see at your screen only one polygon (because there are two overlaping = they look like one piece) and I need to count the centroid of that ONE piece.
I already have an algorithm, that will accept a set of points (representing a points forming polygon) and counting a centroid from these points. But I can't use the algorithm now, because I can't give him the needed points, because I do not know them.
Here are the points, that I want as a result:
So my algorithm should start with points A,B,C,D,E,F,G,H and he should give me points I,J,K,L,M,N as a result.
Summary: I need to count a centroid of polygon which is result of union/merge of two individual polygons, that are overlapping.
And I thought, that union of two polygons would be enough to explain :)
Here http://www.codeproject.com/KB/recipes/Wykobi.aspx is a collection of Computational Geometry algorithms. At least you can start from there.

Categories