-
Notifications
You must be signed in to change notification settings - Fork 227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Implementing banded colors #120
base: dev
Are you sure you want to change the base?
Conversation
So I asked in the graphviz forum if my findings are actually intended and got a very helpful tip about splitting graphviz calculation in multiple steps with specifying See https://graphviz.org/doc/info/output.html#d:dot I played around a little bit and this basically enables me to
Now the caveat: Unfortunately the underlying python library graphviz does not really support anything else than specifying and render the graph. Iterating and changing existing nodes / edges does not seem possible. Everything is directly translated into a dot style string. So it either comes to direct string manipulation or maybe we can have a look at something like the official graphviz python bindings gv.3python dot -Tdot ex10.gv -O
#do some hacking in the file
neato -Tsvg -Tpng -n2 hacked_ex10.gv.dot -O |
That looks impressive! Why not link to this PR in the GraphViz forum, maybe someone else wants to join in on the fun? 😎 |
Tested it with this example:
And it failed drawing the wires correctly. |
@X-Ryl669 Thanks for the test. I was suspecting, that the hack I used in the example would not work reliably and this seems to proof this. Anyway I'm working on a better solution, but I'm not finished to show it off for testing. |
The wires on the top are just perfect. It's a shame those of the bottom are so mangled out... 😢 |
A little bit progress information for @formatc1702: I've looked around a little bit and tried a few python libs working with graphviz and / or the dot language. I think for a clean implementation of the banded output it is necessary to use graphviz in two steps. This may enable us to implement other features that are not supported by graphviz in the future (I'm thinking stuff like drawing twisted pair wires 😁).
Problems to overcome when doing this:
Here two other libs I've tried: official python bindings: I've tried the "official" python binding that are included in the graphviz project. Here I can manipulate a graph directly without the intermediate dot language. The library has a clean interface and supports splitting layout generation and output, so that the positional arguments can be inspected / manipulated, but I have not yet found a way to overcome the reordering of the edges. However installing / using the bindings can be a hassle. In arch linux the bindings are part of the graphviz package. In ubuntu they are bundled seperatly. It is not installable via pip. pydot: Another package I've tried is pydot example: from pydot import graph_from_dot_data, Dot, Edge,Node
g = Dot()
g.set_type("graph")
g.set("rankdir", "LR")
n1 = Node('n1')
n2 = Node('n2', penwidth="3.0")
n3 = Node('n3')
g.add_node(n1)
g.add_node(n2)
g.add_node(n3)
e1 = Edge(n1,n2, color="red", penwidth="6.0", wv_reference="0", wv_id="0")
e2 = Edge(n1,n2, color="blue", penwidth="6.0", wv_reference="1", wv_id="0")
e3 = Edge(n2,n3, color="blue", penwidth="6.0", wv_reference="1", wv_id="1")
e4 = Edge(n1,n3, color="yellow", penwidth="6.0", wv_reference="2", wv_id="0")
g.add_edge(e1)
g.add_edge(e2)
g.add_edge(e3)
g.add_edge(e4)
g2 = graph_from_dot_data(g.create_dot(prog="dot", f="dot").decode('utf-8'))[0] #generating layout via the dot command and passing the output directly to the parser
print(g2) Also the output generation (calling dot, neato, ect. ) can be customized and piped into the parser without needing intermediate file system access. The problem with this package seems to be that the last commit is from 2018 and although there is a good amount of interest in the lib (issues, pull requests) I'm not sure if it's still in active development. But it can be easily installed with pip. For now this is the only lib that seems to have all features to easily implement the banded output and I've done some examples verifying that it is indeed possible 😄. I'll make a branch where I replace the use of But maybe you can state your opinion on changing the backend lib. Do you see this as an option or do you want to move forward with graphviz? There might be a possibility to still achieve the same goal. Maybe we can try to contact the graphviz python lib developer and see if there's plans to enable graph manipulation. |
The more I think about it the more I think we should just dismiss using As I understand the placement, we only have connectors even column (
Since the connectors' and wires' height are known beforehand the position of the connectors and wire can be layout easily. The technical difficulty is finding which connector is terminal but currently, one has to swap the connections in the yml file to get graphviz to draw correctly, so this shouldn't change much at first. I've thought about counting the connection to the connector and ordering them left to right from the most connected to the less connected (or top to bottom). So once the position of the nodes are found (with keeping a scale factor for letting some margin for edge routing), drawing the edges should be a bit harder to route but not too hard either, since we can take advantage of bus routing (all the cables should be parallel and horizontal while crossing a odd column) so it's mainly finding the vertical position they should be to touch the wires' node and then draw a nice and standard cubic spline (or, better, a 45° polyline) from their starting position to the ending position. The vertical bus routing is also quite standard. One thing I'm still puzzled at is how to deal with cable crossing's depth position. It can be random, but I'm not sure how to get the best result. This would also mean that the output will be a SVG file and use whatever renderer to convert it to a PNG file if required. |
Graphviz draws the edges in specified order so it's also just top to bottom. The reordering I was talking about only occurs on writing to dot format. |
I hacked a quick working example with using pydot instead of the graphviz python lib. you can find it here: https://github.com/SnowMB/WireViz/tree/banded_wires_pydot The examples and tutorials seem to work, the only thing I have to figure out is how I draw the splines for the wires if one or both connections are missing. (For example for the shield or in the file @X-Ryl669 provided) You can see in the commit history of that branch that changing the lib requires minimal changes. |
I am rebuilding a motorcycle wiring harness that uses banded wiring, so I've been following this PR with interest. @SnowMB I ran your branch using the following YAML file: Source
One thing I noticed while running this is that I'd get an exception from
Hopefully this is of some help to you. Looking forward to further developments and thank you @formatc1702 for this great tool and @SnowMB for working on this feature! |
@ericbhanson I looked at your example. You made a small mistake in your regex resulting in sometimes cutting the 2nd digit of a float number and mistake it for the y coordinate of the point. this causes the mess 😁 def stringToPoint(str):
split = re.split(r'(\d+\.?\d+)', str)
return tuple([float(split[1]), float(split[3])]) (notice the I made a new commit to my branch so you can try it out! You also have some unknown colors specified:
I guess I must admit that the output still looks fairly messy 😅 |
@SnowMB thanks - I had a feeling it was probably a typo on my part 😄 |
@SnowMB I've been reorganizing my configuration file based on some suggestions from @formatc1702 and noticed that I get an error if I do not use every connector in the
I suspect this might be why I'm getting an error when I attempt to use templates as well. |
Yeah the cable node is created but there seems to be a bug in the way the wires inside the cable are generated when they have no connection. Wireviz seems to generate empty rows there ( I'm not sure if I introduced a bug or if this is a general problem. I can't check this right now but maybe you can tell me if this works in the Here is the bugged section: "BL-SW-M" [height=0.5,
label=<<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<table border="0" cellspacing="0" cellpadding="3" cellborder="1">
<tr>
<td balign="left">BL-SW-M</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table border="0" cellspacing="0" cellpadding="3" cellborder="1">
<tr>
<td balign="left">Bullet</td>
<td balign="left">female</td>
<td balign="left">1-pin</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table border="0" cellspacing="0" cellpadding="3" cellborder="1">
<tr>
</tr>
</table>
</td>
</tr>
</table>> |
I gave a first shot to implementing #109. For now I threw the color stripe out. I will implement it back using the same technique with overlaying multiple edges later when we decide on how to distinguish the multicolor mode (stripe / banded) (on the wire / on the cable ?).
I used a dashed overlay for the edges which in the png looks nice, but the svg renderings on my machine do not look as good. Unfortunately for the wire table I have to predefine a number of color bands. Here I used 12 which should work up to 4 colors, but then the dashes on the edges are much shorter than the bands inside the table. Maybe we try a few values here. Or someone has a better idea. How much can the wire table grow in width?