5

Statement:

I'm creating a program that lets users lay out their own non-directional graph (nodes and edges). Once they press a specific button, I want to create a triangulated mesh out of each 'gap' in the graph. Here are two images that should give you an idea of what I'm after:

Graph Graph filled

There are a few caveats:

  • Since users have full control, I can get 3, 4, 5...n sided spaces
  • A user can create either convex or concave shapes
  • The application is being made in Unity with C#

My own attempts up to this point have been very inefficient and can fail in very unusual graph layouts. My general plan was to grab one node and follow the most acute angle around a cycle until I got back to the first node. This works in part, but I have no way of knowing if I've gotten every space. Additionally, I can end up with two identical meshes that cover the same space (albeit with a different node order).

I'd appreciate any help you can give me with this stumper. To help things along, I am already familiar with convex hull algorithms and triangulation.

Update:

I can't post any code because I'm under NDA for this project, but the data structures are pretty simple.

Nodes have a position (vector 3, but y is always 0) and a List of connected edges.

Edges have a first node, second node and a position (midpoint).

I want to generate a Mesh object for each gap. This mesh object has a static array of vertices (vector 3s) and a static array of triangles (which are ints and relate to vertex indices).

maxteneff
  • 1,523
  • 12
  • 28
ADaurio
  • 99
  • 7
  • Show us some code with the parameters/data structures that you would be passing in and expect to receive back. It's not obvious how these node+edges, and the resulting mesh should be represented. for your code/application. – RBarryYoung Sep 10 '16 at 16:58
  • See my edit above. – ADaurio Sep 12 '16 at 07:37
  • here is an article that covers a lot of this with a link to some JS code: https://blog.reactoweb.com/2012/04/algorithm-101-finding-all-polygons-in-an-undirected-graph/ This is an interesting question with lots of special cases (like polygons within other polygons, possibly disconnected edge-sets, distinguishing between the component polygons and "containing" polygons that wrap around all of the points). As I am not going to have time to work on it and I feel that it hasn't received enough attention, I am going to add a bounty. – RBarryYoung Sep 13 '16 at 13:12
  • Thanks RBarryYoung. Your bounty should help a lot! – ADaurio Sep 14 '16 at 19:41
  • Can we have the vertex and edges plotted in a hidden canvas and play with colors on that to get the answer ? – Mukul Varshney Sep 16 '16 at 17:17
  • Are you after a true triangularization or just a map coloring? The diagram above is just a coloring. – Charles Pehlivanian Sep 17 '16 at 15:38
  • Can 2 edges cross? What do you expect/want to happen then? – j_random_hacker Sep 19 '16 at 12:18

1 Answers1

2

Your approach is good one. There are few points to refine.

Let assume that graph is planar (if not than it is hard to define a face) and that there are no vertices with degree one. Vertices with degree one are not a problem, but it is easier to describe solution without them :-)

Note that each edge will be in two faces. So, if you follow face by most acute angle than you are following these edges only on one side. Solution is to create directed graph with same nodes and for every edge create two edges in both directions. In general same graph as initial graph but edges are doubled. Algorithm is:

take one (directed) edge
follow it in same way by smallest angle
make faces of that cycle
remove face (directed) edges from graph
repeat procedure until there are edges.

Same approach works for graphs with vertices of degree one, but face will have a 'cut' (edge in one direction than in opposite direction.)

If you do not want outer face than do not 'double' outer edges but only make one positive direction edge from each outer edge.

Update

Since each polygon and polygon edge is passed only once I think this is quite optimal solution. Just few possibilities.

Main step in algorithm is to choose next edge from last visited node. Simple implementation is to calculate angles of out-edges and take next one. Angle calculation can be done once, not every time edge visits node, and even mapping in-edge -> out-edge can be done for a node.

It is not needed to create new directed graph, it is enough to store direction data for each edge. Two boolean variables are enough, one for each direction. With this first step, choosing not visited edge to start new polygon, gets more complex. That can be covered if upper angle calculation is used by removing visited angles from a map and flagging node as visible if there are no more angles in a map.

Ante
  • 5,350
  • 6
  • 23
  • 46
  • Consider a regular 7/3-Heptagram (https://en.wikipedia.org/wiki/File:Regular_star_polygon_7-3.svg) with points at every intersection. How would your algorithm work on it? I am fairly sure that in many cases it will end up traversing the outer boundary enclosing some or all of the triangles it should have isolated as a separate polygon. As far as I can tell, the "enclosing polygon problem" is not simple and is not addressed by merely taking the smallest angle. – RBarryYoung Sep 14 '16 at 20:49
  • @RBarryYoung I am not sure that I completely understand your remark. Maybe problem is in my usage of term smallest angle, which is not clear. Edges are traversed in a way that when edge comes in a node, next edge is cuoosed from outgoing edges that is first in positive direction (counter clockwise). After edge is traversed it is removed from the graph. With that one angle can be used only once. – Ante Sep 14 '16 at 22:03
  • So wouldn't that trace the outer perimeter of a heptagram? Which would be incorrect because is an enclosing polygon (contains other polygons inside it) and not a "gap"? – RBarryYoung Sep 15 '16 at 00:10
  • @RBarryYoung Yes, with 'doubling' all edges, outer polygon will also be in the result. That is why I added remark at the end of the answer. One more remark: since finding outer face includes same traversing as finding any other face, I think it is simpler implementation first to find all faces and than remove outer from result. – Ante Sep 15 '16 at 07:09
  • This is technically a working solution (it's pretty much what I came up with), but I'm hoping there's a slightly more efficient method out there, since this could get pretty computationally expensive with a really massive graph. Just to clarify, when I say I take the most acute angle, I take the most acute (counter clockwise) angle based off of the angle (previous node -> current node -> potential next node) – ADaurio Sep 15 '16 at 14:42
  • @ADaurio I added an update with some remarks about efficiency. – Ante Sep 16 '16 at 07:03
  • I'm pretty much ready to mark this as correct. My only question is how you would detect the boundary edges. Are you theoretically using an alpha shape? – ADaurio Sep 19 '16 at 13:15
  • If we assume no crossings (just place a vertex at the crossings if you do) you have a planar graph and it seems like the [graph dual](https://en.wikipedia.org/wiki/Dual_graph) can help here. The graph dual places vertices in each face/region of the original planar graph, connecting vertices in different regions. The algos I've seen for creating the dual work with abstract graphs, and the resulting embedding may not match up or overlay on the original. So - is there a nice algo for creating the coordinates and edges of the dual graph for an embedded planar graph? – Charles Pehlivanian Sep 19 '16 at 15:20
  • @ADaurio It can be done simpler. Choose a node on a boundary. It is the simplest to take point on boundary box, e.g. node with max X coordinate. From node edges choose 'first' one (with smallest angle relative to boundary). For max X node edges have angle between pi/2 and 3*pi/2, and first is edge with the smallest angle. Outer face have that edge in negative direction (clockwise). So you can first extract outer face starting from that edge oriented pointing to max X node. Rest of faces are inner. – Ante Sep 19 '16 at 19:03
  • @CharlesPehlivanian Dual graph problem is quite similar to this but simpler. There is no geometry (positions, orientation) in dual graph problem. I think, even if we have dual graph for input graph, producing solution would of similar complexity as described solution. To extract oriented face we have to take dual node and adjacent edges connect in good order, which is similar work as described upper. – Ante Sep 19 '16 at 19:10
  • @Ante I think most dual graph algorithms allow us to extract the mapping : {vertex v' of dual} -> {vertices of original graph for which v' is an interior point}. I'm not sure but I *think* the Boost Graph Library does. In that case, it's easy, isn't it, even though we are dealing with the abstract graph rather than the embedding. – Charles Pehlivanian Sep 19 '16 at 19:15
  • @CharlesPehlivanian Probably, since it is byproduct of finding dual node (region). With list of vertices that surround a region, first we have to connect them in a ring to get a region. That can be done with edges between them, which is probably also output of dual algorithm. It is done simple but with (I think exactly the) same complexity as traversing face if angles are calculated and sorted. After that we have to check region orientation. If it is negatively oriented, region has to be inverted. With that, I think there is more with dual graph approach. – Ante Sep 19 '16 at 19:27