0

Here's an illustration of the steps taken thus far: Steps Taken

  1. Pseudo-random rectangle generation
  2. "Central node" insertion, rect separation, and final node selections
  3. Delaunay triangulation (shown with previously selected nodes)
  4. Rendering of triangle edges

At this point (Step 5), I would like to use this data to form a Minimum Spanning Tree, but there's a slight catch...

Somewhere in the graph (likely near the center, but not always) will be a node that requires between 3-5 connections to it from other unique nodes. This complicates things, since every other node should only contain a single connection, and the data structures being used make it difficult to determine "what's connected to what" in a solid, traversable format.

So, given an array of triangles in the above format, and a random vertex to use as the "root node", how could I properly traverse the network to create an MST where there are at least 3 connections to our "central node", but no more than 5 connections to it? Is this possible?

RectangleEquals
  • 1,825
  • 2
  • 25
  • 44
  • Forgot to mention. The weights are just simple euclidean distances between vertices. – RectangleEquals Oct 23 '17 at 00:33
  • How many candidate edges might the distinguished node have? – Davis Herring Oct 23 '17 at 01:14
  • @DavisHerring I've added an example image illustrating the steps taken from rect generation, all the way through triangulation. In that example, you can see that all nodes have a varying number of edges (since the graph is composed of triangles). But generation of the "central node" is guaranteed to have at least 3 edges. The next step is to pick a random node, and have it traverse to all other nodes, whilst somehow guaranteeing that the "central node" will have 3-5 connections. – RectangleEquals Oct 23 '17 at 04:40
  • And If it helps to visualize the goal, you could say that the top-right node is the "root node", but it doesn't really matter which one it is, as long as the "central node" has 3-5 connections to/from it in the final MST, and all other nodes have been visited no more than once – RectangleEquals Oct 23 '17 at 04:43
  • Obviously, if any nodes are not adjacent to the root there will be other nodes with more than one connection. I therefore ignored "every other node should only contain a single connection", thinking it just meant "there are no degree constraints on the other nodes". But do you really mean that the graph must just be 3-5 paths emanating from the root? That's a very special MST indeed if so, and it doesn't exist in general (though maybe it does for a convex triangulation). – Davis Herring Oct 23 '17 at 05:43
  • Well just to be clear about the end goal, here... This is for a dungeon generation algorithm, designed to suit 3-5 players at a time per map. You could think of the "central node" as a "boss room" of sorts. So the MST would be used to minimize corridors, and guarantee multiple paths to the "boss room". The MST would also guarantee that every node can be visited from at least one of those paths (step 6 would be to re-include a certain % of unused edges to form outer loops) – RectangleEquals Oct 23 '17 at 06:10
  • This is very much like the way that [TinyKeep](http://www.tinykeep.com) does [things](https://www.reddit.com/r/gamedev/comments/1dlwc4/procedural_dungeon_generation_algorithm_explained/). I've changed very little from the original algorithm. But the one thing I did change just so happens to be very difficult to do in practice. In theory, it's much easier lol – RectangleEquals Oct 23 '17 at 06:12

2 Answers2

1

Since it's rare to have a vertex in a Delaunay triangulation have much more than 6 edges, you can use brute force: there are only 20+15+6 ways to select 3, 4, or 5 edges out of 6 (respectively), so try all of them. For each of the 41 (up to 336 for degree 9) small trees (the root and a few edges) thus created, run either Kruskal's algorithm or Prim's algorithm starting with that tree already "found" to be part of the MST. (Ignore the root's other edges so as not to increase its degree further.) Then just pick the best one (including the cost of the seed tree).

As for the general neighbor information problem, it seems you just need to build a standard graph representation first. For example, you can make an adjacency list by scanning over all your Edge objects and storing each endpoint in a list associated with the other (in a map<Vector2<T>,vector<Vector2<T>>> or an equivalent based on whatever identifiers for your vertices).

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
  • Yeah, Prim's was originally on the brain before posting. But it got pretty confusing once you throw in a node that needs to have a specific range of connections to/from it. So you're saying to always start from the "central node", but how would we guarantee that it becomes the only one in the tree with multiple connections? Wouldn't the first iteration of Prim's possibly destroy the ability to go outward from that node again? Since there needs to be 3 "exits" from it, doesn't that mean there needs to be 3 adjacent, unvisited nodes? – RectangleEquals Oct 23 '17 at 05:16
  • Oh wait, maybe I'm misunderstanding what you mean when you say "small tree" and "ignore the edges not selected". Would I need to run prim's multiple times, using the same root, but different edge selection each time? – RectangleEquals Oct 23 '17 at 05:33
  • @RectangleEquals: I edited to clarify, but I also left a comment on the question because I may have misinterpreted it significantly. – Davis Herring Oct 23 '17 at 05:44
  • I'm gonna keep hacking away at this until I get something to work. It's more complex than your average MST, but I'm almost certain it can be done, even if it ends up taking exponentially longer time to execute – RectangleEquals Oct 23 '17 at 06:17
0

I've taken a workaround approach...

After step 3 of my algorithm, I simply remove all edges which connect to the "central node", keeping track of which edges form the "ring" (aka "edge loop") around it, and run the MST on all remaining edges.

For the MST, I went with the boost graph library. That made it easy to loop through the triangles I had, adding each of its three edges to an adjacency_list. Then a simple call to whichever boost-provided MST algorithm took care of the rest.

Finally, I readd the edges that were previously taken out. The shortest path is whatever it was in the previous step, plus the length of whichever readded edge that connects to another edge on the "ring" is shortest.

I can then add (or remove) an arbitrary number of previous edges to ensure there are between 3 to 5 edges connecting from the edge loop to the "central node".

Doing things in this order also allows me to know as soon as step 3 if we'll even have a valid number of edges, so we don't waste cycles running a MST.

RectangleEquals
  • 1,825
  • 2
  • 25
  • 44