Graphviz force specific edge length

Hi all,

i’m trying to force edge distance. does anyone know a way to make it work?
seems that weight and len ain’t helping me. i’ve also looked in past topic but none helped me.

in other words i’m trying to place nodes one below another but the other nodes are messing with the placement

can anyone help me?
i removed style=invis to visualize the edges

digraph G {
rankdir="LR"
compound=true;
ordering=out;
node [fontsize=10, shape=box, height=0.25]
edge [fontsize=10] 
  
  
  # rank same
  {rank = same; sdb1; sdc1; sdd1; sde1; sdf1; sdh1; sdj1; sdk1; sdm1; sdn1; sds1; sdr1; sdq1; sdp1; sdo1; dtoricoc3_truenas; }
  
  {rank = same; "/mnt/data-0K6A"; "/mnt/data-0FZJ"; "/mnt/data-N09G"; "/mnt/data-3PJS"; "/mnt/data-SC2C"; "/mnt/data-RL66"; "/mnt/data-RLBH"; "/mnt/data-Q7V6"; "/mnt/data-Q7W7"; "/mnt/data-BZDY"; "/mnt/data-KTRD"; "/mnt/data-c2744"; "/mnt/data-c3077"; "/mnt/data-BZLB";  }

  {rank = same; pool; pool000; "pool-cache"; }

  {rank = same; "poolB"; "/mnt/poolC"; dtoricoc3; }

  {rank = same; macmini11; lenovom70q; }

  {rank = same; hubA; hubB; hubC; }
  {rank = same; hubAport1; hubAport2; hubAport3; hubAport4; hubBport1; hubBport2; hubBport3; hubBport4; hubCport1; hubCport2; hubCport3; hubCport4; }
  {rank = same; macport1; macport2; macport3; macport4; }
  {rank = same; "orico5bay_bay1"; "orico5bay_bay2"; "orico5bay_bay3"; "orico5bay_bay4"; "orico5bay_bay5"; }
  {rank = same; "orico2bay_bay1"; "orico2bay_bay2"; }


  pool [ label=<
          <table cellspacing="0" border="0" cellborder="0">
              <tr>
                <td>/mnt/pool</td>
              </tr>
          </table>
      >
  ]

  pool000 [ label=<
          <table cellspacing="0" border="0" cellborder="0">
              <tr>
                <td>/mnt/pool000</td>
              </tr>
          </table>
      >
  ]

  "pool-cache" [ label=<
          <table cellspacing="0" border="0" cellborder="0">
              <tr>
                <td>/mnt/pool-cache</td>
              </tr>
          </table>
      >
  ]

  dtoricoc3_truenas [ label=<
          <table cellspacing="0" border="0" cellborder="0">
              <tr>
                <td colspan="2">\\\\\\\\192.168.0.100\\dtoricoc3</td>
              </tr>
              <tr>
                <td>truenas</td>
              </tr>
          </table>
      >
  ]
  dtoricoc3 [label="/mnt/dtoricoc3\nnfs"]

  # orico 2 bay
  orico2bay [label=<
    <table cellspacing="0" border="0" cellborder="0">
        <tr>
          <td>Orico 2 bay</td>
        </tr>
    </table>
  >]
  orico2bay_bay1 [label="bay1"]
  orico2bay_bay2 [label="bay2"]
  orico2bay -> orico2bay_bay1, orico2bay_bay2
  orico2bay_bay1 -> orico2bay_bay2 [style=invis]
  orico2bay_bay1 -> "/mnt/data-RLBH"
  orico2bay_bay1 -> "/mnt/data-RL66"

  # orico 5 bay
  orico5bay [label=<
    <table cellspacing="0" border="0" cellborder="0">
        <tr>
          <td>Orico 5 bay</td>
        </tr>
    </table>
  >]
  orico5bay_bay1 [label="bay1"]
  orico5bay_bay2 [label="bay2"]
  orico5bay_bay3 [label="bay3"]
  orico5bay_bay4 [label="bay4"]
  orico5bay_bay5 [label="bay5"]
  orico5bay_bay1 -> orico5bay_bay2 [weight=200;]
  orico5bay_bay2 -> orico5bay_bay3 [len=2]
  orico5bay_bay3 -> orico5bay_bay4 [weight=200;]
  orico5bay_bay4 -> orico5bay_bay5 [weight=200;]
  orico5bay -> orico5bay_bay1, orico5bay_bay2, orico5bay_bay3, orico5bay_bay4, orico5bay_bay5 
  orico5bay_bay1 -> "/mnt/6DH4"
  orico5bay_bay2 -> "/mnt/0ZXR"
  orico5bay_bay3 -> "/mnt/3RJT"
  orico5bay_bay4 -> "/mnt/86NA"
  orico5bay_bay5 -> "/mnt/P4XV"


  dtoricod [label=<
    <table cellspacing="0" border="0" cellborder="0">
        <tr>
          <td colspan="2">dtoricod</td>
        </tr>
        <tr>
          <td>zfs</td>
        </tr>
    </table>
  >]
    
  poolB [label="/mnt/poolB\nmergerfs"]

  lenovom70q [ label=<
          <table cellspacing="0" border="0" cellborder="0">
              <tr>
                  <td>lenovo-m70q</td>
              </tr>
          </table>
      >
  ]

  lenovom70q -> dtoricoc3_truenas
  macmini11 -> lenovom70q [style=invis]
  
  macmini11 [ label=<
          <table cellspacing="0" border="0" cellborder="0">
              <tr>
                  <td>macmini11</td>
              </tr>
          </table>
      >
  ]
  macport1 [label="usb1"]
  macport2 [label="usb2"]
  macport3 [label="usb3"]
  macport4 [label="usb4"]
  macmini11 -> macport1, macport2, macport3, macport4
  macport1 -> macport2 [style=invis]
  macport2 -> macport3 [style=invis]
  macport3 -> macport4 [style=invis]
  macport1 -> hubA
  macport2 -> hubC
  macport3 -> orico2bay
  macport4 -> hubB 

  hubA [ label=<
          <table cellspacing="0" border="0" cellborder="0">
              <tr>
                  <td>hubA</td>
              </tr>
          </table>
      >
  ]
  hubAport1 [label="usb1"]
  hubAport2 [label="usb2"]
  hubAport3 [label="usb3"]
  hubAport4 [label="usb4"]
  hubB [ label=<
          <table cellspacing="0" border="0" cellborder="0">
              <tr>
                  <td>hubB</td>
              </tr>
          </table>
      >
  ]
  hubBport1 [label="usb1"]
  hubBport2 [label="usb2"]
  hubBport3 [label="usb3"]
  hubBport4 [label="usb4"]
  hubC [ label=<
          <table cellspacing="0" border="0" cellborder="0">
              <tr>
                  <td>hubC</td>
              </tr>
          </table>
      >
  ]
  hubCport1 [label="usb1"]
  hubCport2 [label="usb2"]
  hubCport3 [label="usb3"]
  hubCport4 [label="usb4"]
  hubA -> hubAport1, hubAport2, hubAport3, hubAport4
  hubB -> hubBport1, hubBport2, hubBport3, hubBport4
  hubC -> hubCport1, hubCport2, hubCport3, hubCport4
  
  hubAport1 -> sdn1 [style=invis]
  hubAport1 -> hubAport2 [style=invis]
  hubAport2 -> hubAport3 [style=invis]
  hubAport3 -> hubAport4 [style=invis]
  
  
  hubBport1 -> sdc1 [style=invis]
  hubBport1 -> hubBport2 [style=invis]
  hubBport2 -> hubBport3 [style=invis]
  hubBport3 -> hubBport4 [style=invis;weight=20]

  hubBport4 -> hubCport1 [style=invis]

  hubCport1 -> hubCport2 [style=invis]
  hubCport2 -> hubCport3 [style=invis]
  hubCport3 -> hubCport4 [style=invis]
  
  hubAport1 -> "/mnt/data-0K6A"
  hubAport2 -> "/mnt/data-0FZJ"
  hubAport3 -> "/mnt/data-SC2C"
  hubAport4 -> "/mnt/data-3PJS"
  
  hubBport1 -> "/mnt/data-BZLB"
  hubBport2 -> "/mnt/data-c2744"
  hubBport3 -> "/mnt/data-c3077"
  hubBport4 -> orico5bay 

  hubCport1 -> "/mnt/data-BZDY"
  hubCport2 -> "/mnt/data-Q7V6"
  hubCport3 -> "/mnt/data-Q7W7"
  hubCport4 -> "/mnt/data-N09G"
  
  
  dtoricoc3_truenas -> dtoricoc3
  
  # devices
  
  sdb1 -> "/mnt/data-RL66"
  sdc1 -> "/mnt/data-RLBH"
  sdd1 -> "/mnt/data-BZDY"
  sde1 -> "/mnt/data-0K6A"
  sdf1 -> "/mnt/data-Q7V6"
  sdh1 -> "/mnt/data-0FZJ"
  
  sdj1 -> "/mnt/data-Q7W7"
  sdk1 -> "/mnt/data-SC2C"
  
  sdm1 -> "/mnt/data-N09G"
  sdn1 -> "/mnt/data-3PJS"
  
  # pool-cache
  
  "/mnt/data-c2744" -> "pool-cache"
  "/mnt/data-c3077" -> "pool-cache"
  
  # poolC
  
  "/mnt/data-BZDY" -> "/mnt/poolC"
  
  # dtoricod
  sds1 -> "/mnt/P4XV"
  sdr1 -> "/mnt/86NA"
  sdq1 -> "/mnt/3RJT"
  sdp1 -> "/mnt/0ZXR"
  sdo1 -> "/mnt/6DH4"
  
  "/mnt/P4XV" -> dtoricod
  "/mnt/86NA" -> dtoricod
  "/mnt/3RJT" -> dtoricod
  "/mnt/0ZXR" -> dtoricod
  "/mnt/6DH4" -> dtoricod
  
  dtoricod -> "/mnt/poolC"
  
  # poolB
  "/mnt/data-RL66" -> poolB
  "/mnt/data-RLBH" -> poolB
  "/mnt/data-Q7V6" -> poolB
  "/mnt/data-Q7W7" -> poolB
  
  # pool000
  poolB -> "pool000"
  "/mnt/poolC" -> "pool000"
  
  # pool
  poolB -> "pool"
  "/mnt/poolC" -> "pool"
  dtoricoc3 -> "pool"
  
  "/mnt/data-0FZJ" -> "pool"
  "/mnt/data-0K6A" -> "pool"
  "/mnt/data-N09G" -> "pool"
  "/mnt/data-KTRD" -> "pool"
  
  # died
  "/mnt/data-KTRD" [color=crimson]
  
}

like this

digraph G {
rankdir="LR"
compound=true;
ordering=out;
node [fontsize=10, shape=box, height=0.25]
edge [fontsize=10] 

oricobay5 -> bay1, bay2, bay3, bay4, bay5
  
}

Should the “bay*” nodes and the “sd*” nodes be in the same rank?

While you asked to force edge length, I think the tweak below accomplishes the larger goal of placing certain nodes “together” within a rank.
The only change is to place the two “bay*” groups within clusters. The change is so small, I am not including all the rest of the source.

  subgraph clusterO5 {
    //peripheries=0  // to remove surrounding box
    {rank = same; "orico5bay_bay1"; "orico5bay_bay2"; "orico5bay_bay3"; "orico5bay_bay4"; "orico5bay_bay5"; }
  }
  subgraph clusterO2 {
    //peripheries=0  // to remove surrounding box
    {rank = same; "orico2bay_bay1"; "orico2bay_bay2"; }
  }

Giving:

Note that peripheries=0 will remove the surrounding rectangles.

hi @steveroush, thank you for your reply

hmm… this would be great. I was also trying to place specific nodes in rank layer 1, 2, 3, and so on…
for example,
rank layer=2 sd*
rank layer=3 bay*

the subgraph worked! there’s one small thing. do you think it’s possible to properly order it?

hm… changing the order fixed it

// orico2bay_bay1 -> orico2bay_bay2 [style=invis]
orico2bay_bay2 -> orico2bay_bay1 [style=invis]

regards,c.

yea… the order gets messy when dealing with many nodes

edit:
if this is the solution

it looks so complex o.O

Here is another path to try. No clusters, one html table node that includes all the related usb nodes in the correct sequence. It uses side-less cells to space out the ports.

digraph "tree test" {
  rankdir=LR

	{rank=same             
        node [shape=plaintext] 

        a [label=<<table border="0" cellspacing="0" cellborder="1">
          <tr><td port="p1">usb1</td></tr>
	  <tr><td sides="t"> </td></tr>
	  <tr><td port="p3" >usb2</td></tr>
	  <tr><td  sides="t"> </td></tr>
	  <tr><td port="p5" >usb3</td></tr>
	  <tr><td  sides="t"> </td></tr>
	  <tr><td port="p7" >usb4</td></tr>
	  <tr><td sides="t"> </td></tr>
	  <tr><td port="p9" >usb5</td></tr>
          </table>>]
        }

       hubc -> a:p1
       hubc -> a:p3
       hubc -> a:p5
       hubc -> a:p7
       hubc -> a:p9

       a:p5 -> this
       a:p7 -> that       
}

Gives:
spacedTable

it worked! thank you so much @steveroush :grin: