wireviz / WireViz

Easily document cables and wiring harnesses.
GNU General Public License v3.0
4.22k stars 219 forks source link

[feature] Add grouping for connectors to represent f.e. PCB with multiple connectors #325

Open Heenne opened 9 months ago

Heenne commented 9 months ago

Currently I am documenting the cable harness for my 3D-printer. In this printer is a controller board with over 20 connectors. If I add all these connectors they are not very well grouped to visualize that these connectors are all on one single PCB. Therefore, I would like to propose the following feature:

Add possibility to create a box with a name around a list of connectors to represent and better visualize a single component with multiple connectors.

Thank you for this awesome tool, it is real fun to work with it!

kvid commented 9 months ago

Thank you for sharing your use case. It is possible to group several connectors and/or cables and draw a frame around them with a title text by adding an entry in the tweak section. See an example in https://github.com/wireviz/WireViz/issues/276#issuecomment-1041898460 where one connector and one cable is grouped, but you can include many of each in the same group. Notice that connector/cable names need to be quoted when they contain certain characters, e.g space.

Heenne commented 9 months ago

Thank you very much for the quick response. The example you linked is exactly how I imagined it. If I got time, can I make a pull request to add a simple example for this to the other examples?

JarrettR commented 1 month ago

Also requesting this.

The linked example is a good workaround, but not quite production ready. The main issues are that it only groups connectors vertically, and (IMO) tweak should be avoided except in the edgiest edge cases.

Here's an example, trimmed down from a WIP of mine:


templates:
  - &molex_fan
    type: Molex KK 254
    subtype: female
    pinlabels: [GND, +12V, TACH, FAN]
    show_pincount: false
  - &ps_small
    type: Molex KK 254
    subtype: female
    pincount: 6
  - &ps_large
    type: Molex KK 254
    subtype: female
    pincount: 22
connectors:
  JB-J22:
    <<: *molex_fan
    notes: "Fan 1"
  JB-J23:
    <<: *molex_fan
    notes: "Fan 2"
  JB-J2:
    <<: *molex_fan
    notes: "Fan 3"
  JB-J24:
    <<: *molex_fan
    notes: "Fan 4"
  JB-J25:
    <<: *molex_fan
    notes: "Fan 5"
  JB-J18:
    <<: *ps_small
    notes: "PS L 1"
  PS-L-J18:
    <<: *ps_small
  JB-J19:
    <<: *ps_large
    notes: "PS L 2"
  PS-L-J19:
    <<: *ps_large
  Fan:
    type: 'Fan'
    pincount: 4
  PS-L-1:
    type: 'PS'
    pincount: 2

cables:
  W1:
    colors: [GN, BK, RD]
    gauge: 6 AWG
    show_wirenumbers: false
  W3:
    wirecount: 1
    show_wirecount: false
    show_wirenumbers: false
    length: 50 ft
  F:
    type: 'Fan Cable'
    colors: [BK, YE, GN, BU]
    show_wirecount: false
    category: bundle
  PSW-1:
    wirecount: 6
    show_wirecount: false
    show_wirenumbers: false
  PSW-2:
    wirecount: 22
    show_wirecount: false
    show_wirenumbers: false

connections:
  -
    - JB-J22: [1-4]
    - F.: [1-4]
    - Fan.: [1-4]
  -
    - JB-J23: [1-4]
    - F.: [1-4]
    - Fan.: [1-4]
  -
    - JB-J2: [1-4]
    - F.: [1-4]
    - Fan.: [1-4]
  -
    - JB-J24: [1-4]
    - F.: [1-4]
    - Fan.: [1-4]
  -
    - JB-J25: [1-4]
    - F.: [1-4]
    - Fan.: [1-4]
  -
    - PS-L-J18: [1-6]
    - PSW-1.PSW-L1:  [1-6]
    - JB-J18: [1-6]
  -
    - PS-L-J19: [1-22]
    - PSW-2.PSW-L2:  [1-22]
    - JB-J19: [1-22]
tweak:
  append: |
    subgraph cluster1 {
      label="PCB Assembly"
      style=dashed
      "JB-J22"
      "JB-J23"
      "JB-J2"
      "JB-J24"
      "JB-J25"
      "JB-J18"
      "JB-J19"
    }
    subgraph cluster2 {
      label="Power Supply Left"
      style=dashed
      "PS-L-J18"
      "PS-L-J19"
    }

Results in this:

wiring

Proposed ideal result:

The top two connectors of the PCB assembly should be moved to the left of the screen, with the dashed lines intact around the group. Excuse the poor image edit. image

The syntax could be fairly simple - Something like:

groups:
  -
     - "JB-J22"
     - "JB-J23"
     - "JB-J2"
     - "JB-J24"
     - "JB-J25"
     - "JB-J18"
     - "JB-J19"
  -
     - "PS-L-J18"
     - "PS-L-J19"

Right after I finish this post, I'll poke around in GV and see if there are tweak settings to do what I want, but it would be good to get this mainlined!

martinrieder commented 1 month ago

Another idea of grouping has been suggested in https://github.com/wireviz/WireViz/issues/268#issuecomment-1107926742.

The Graphviz "rankdir" is "LR", which creates WireViz diagrams with horizontal layouts. Any parts of the harness that are independent (unconnected) need to be stacked top-to-bottom, in order to achieve the least possible overall image width.

martinrieder commented 1 month ago

@JarrettR you can use the new connector-to-connector feature (creating arrows with "==" as a wire designator). This will cause Graphviz to align the boxes to the right. Then check the GV file what the auto-generated designators of the dashed edges are. You can hide them with a "style: invis" tweak in the overrides.

JarrettR commented 1 month ago

Thanks for the explanation, and that's a really good hack.

I'm having issues with figuring out the appropriate overrides, though.

For this simplified example:


connections:
  -
    - X1: [1-4]
    - ==
    - X3: [1-4]

Then the generated GraphViz section is just this, appended at the very end:

    edge [color="#000000:#000000" dir=none style=dashed]
    X1:e -- X3:w

Neither of these can be accessed through the key/value system that the tweak option checks for.

This does nothing useful, for example:


tweak:
    override:
        "X1:e -- X3:w":
            style: invis 
        edge:
            style: invis 

It actually hides all wires except for the one I want, ironically.

kvid commented 1 month ago

Instead of trying to override the arrow connections, I recommend adding the invisible edges you need in the tweak:append section.

JarrettR commented 1 month ago

Oh of course. That works perfectly.

Thanks for the tips, @martinrieder and @kvid

martinrieder commented 1 month ago

Instead of trying to override the arrow connections, I recommend adding the invisible edges you need in the tweak:append section.

That seems perfectly valid and allows for all kinds of nodes to be "tied together". The invisible edge can be added between two cables as well.

I would like to add that these invisible edges actually influence the ranking of nodes. The is also an attribute rank that can be set to either source or min vs. sink or max. It has a similar effect on grouping nodes, because independent nodes are stacked TB by default due to their rank=same.

kvid commented 1 month ago

@JarrettR wrote a couple of weeks ago:

[...]

  edge [color="#000000:#000000" dir=none style=dashed]
  X1:e -- X3:w

Neither of these can be accessed through the key/value system that the tweak option checks for.

This does nothing useful, for example:

tweak:
    override:
        "X1:e -- X3:w":
            style: invis 
        edge:
            style: invis 

It actually hides all wires except for the one I want, ironically.

martinrieder commented 2 weeks ago

Another possible solution to this issue could be found here, but this tool is intended for digraph: https://graphviz.org/docs/cli/unflatten/

However, there is another trick to achieve similar behavior using the ccomps and gvpack CLI tools. See the example provided here: https://graphviz.org/docs/cli/gvpack/

ccomps −x abc.gv | dot | gvpack | neato −s −n2 −Tps

This pipeline decomposes the graph in abc.gv into its connected components, lays out each using dot, packs them all together again, and produces the final drawing in PostScript. Of course, there is nothing to prevent one from using different layouts for each compo-nent.

ccomp also features sorting by size (of components):

ccomps decomposes graphs into their connected components, printing the components to standard output.

−x Only the connected components are printed, as separate graphs. −z Sort components by size, with the largest first. This is only effective if either -x or -X# is present.

gvpack has different layout patterns, which can itself also sort by size (of the graphs):

gvpack reads in a stream of graphs, combines the graphs into a single layout, and produces a single graph serving as the union of the input graphs. [...] By default, the packing is done at the cluster level. Thus, parts of one graph will not intrude into any top-level clusters or overlap any nodes or edges of another.

−array[_flags][n] Combines the graphs at the graph level, placing them in an array. By default, the layout is done in row-major order. The number of columns used is roughly the square root of the number of graphs.

  • If the optional integer n is supplied, this indicates the number of columns to use. [...] By default, the insertion order is determined by sorting the graphs by size, largest to smallest.
  • If the "u" flag is set, the graphs are sorted based on the non-negative integer sortv attribute attached to each graph.
  • The "i" flag indicates that no sorting is done, with the graphs inserted in input order.