Graphviz allow edge-node overlap - graphviz

I would like to use graphviz for a project and am unable to get the behaviour I want. I have a graph that I can draw with graphviz just fine, but I also have a version of the same graph that has some extra edges. I would like the second graph to be drawn with the nodes in the same positions as the first one and the edges in the same positions, but the new edges to be drawn without avoiding any overlap with nodes.
To get a better idea of what I want, imagine a Powerpoint slide with a graph and then on the next slide the same graph with these extra edges that appear on top of the first graph, wihtout modifying the look of the old parts of the graph. That is the effect I want.
I think the effect could be achieved by having some edges ignore any overlapping constraints. I could not figure out how to control the overlap between edges and nodes for particular edges (or even for all edges).
Any ideas?

You can get dot to output another .dot file, with positions assigned to all elements, via dot -Tdot (or maybe dot -Txdot). Add your additional edges to that file, and run it through dot again to produce your second graph.

Related

Adding cycles to a Minimum Spanning Tree without moving the points?

I am generating a dungeon layout for a video game. I have created the rooms, spaced them out using seperation steering, and created a fully connected weighted, undirected graph of the rooms. Then I calculated a MST using Prim's Algorithm, all using GML (GameMaker Language). I miss Python.
My intention is to add additional edges to reintroduce loops, so a player does not have to always return along a path, and to make layouts more interesting. The problem is, these edges cannot cross, and I would prefer not to have to move the points around. I had been given a recommendation to use Delaunay Triangulation, but if I am honest this is completely over my head, and may not be a viable solution in GML. I am asking for any suggestions on algorithms that I could use to identify edges that I could add that do not intersect previously created edges.
I have included an image of the MST (the lines connect to the corners of the red markers, even if the image shows they stop short)
If I'm understanding your question correctly, we're looking at more of a geometry problem than a graph theory problem. You have existing points and line segments with concrete locations in 2d space, and you want to add new line segments that will not intersect existing line segments.
For checking whether you can connect two nodes, node1 and node2, you can iterate through all existing edges and see whether the line segment node1---node2 would intersect the line segment edge.endpoint1 --- edge.endpoint2. The key function that checks whether two line segments intersect can be implemented with any of the solutions found here: How can I check if two segments intersect?.
That would take O(E) time and look something like
def canAddEdge(node1, node2):
canAdd = True
for edge in graph:
canAdd = canAdd and not doesIntersect([node1.location(),
node2.location(), edge.endpoint1.location(), edge.endpoint2.location()])
And you can get a list of valid edges to add in O(EV^2) with something like
def getListOfValidEdges(graph):
validEdges = []
for index,firstEndpointNode in enumerate(graph.nodes()):
for secondEndpointNode in graph.nodes()[index:]:
if (canAddEdge(firstEndpointNode, secondEndpointNode)):
validEdges.append([firstEndpointNode, secondEndpointNode])
return validEdges
Of course, you would need to recalculate the valid edges every time after adding a new edge.

Drawing small planar graphs with Graphviz

I drew a small planar graph with Graphviz but in one place there's an intersection of two edges. I read on SO that not all planar graphs can be drawn without intersections because it's an NP-hard problem. I also read that there aren't even implemented complex algorithms in Graphviz that do that. But that intersection is as easy to fix as possible so there probably is a way to get rid of it.
Here are the options I used:
overlap = false;
splines = curved;
nodesep = 0.5;
And here's the graph:
So, is there a way of fixing that one intersection (25-38 with 7-18) without changing the order of edges like I did here? Isn't there like at least O(n^2) algorithm that would swap two vertices and check if the intersection disappeared?
This is kind of a hotfix:
Add an invisible edge between nodes 7 and 25, ie 7 -- 25 [style="invis"];. This clause may be added to the end of the graph definition so it shouldn't interfere with any automatic generation.
It feels like cheating, however, at least the order of the payload edges in the graph definition file remains untouched.
I cannot give an explanation of why this works,unfortunately. In particular, adding edges between other nodes incident to the offending edges does not produce the desired result.
Graphviz version: 2.38.0 (20140413.2041)

GraphViz how to layout shapes evenly on a page

I have a graph with a lot of objects. A number of these objects have no links. GraphVis lays these out on one long horizontal line on the top of the diagram.
Is there anyway to make GraphViz have a maximum width, so unconnected objects go on the next "line" ?
Add invisible edges between them. This will force graphviz to layout these nodes like the ordinary ones.

Add a new edge while keeping existing graph fixed

Consider the manually drawn red arrow in this graph:
I want to tell graphviz to draw an arrow like that, although the particular path is not important. The important thing is that the existing graph not change at all. Essentially, I want to instruct graphviz to
Draw a certain graph
Keeping that graph fixed, add a new edge to it
Is this possible?
Yes, it should be possible.
If you have a certain graph (e.g. data.dot) and run this file through dot without specifying an output format, dot will output a dot file with added coordinates (attribute pos for nodes and edges). If you save this output (dot data.dot > data_pos.dot) you can add your new edge to it and you can generate your two output files.
You might have to enlarge the bounding box graph [bb="..."]; for the new edge not to mess with positions tho.

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