Jollywatt / typst-fletcher

Typst package for drawing diagrams with arrows, built on top of CeTZ.
MIT License
341 stars 6 forks source link

Sometimes edge seems not respecting `enclose` #24

Closed FlandiaYingman closed 4 months ago

FlandiaYingman commented 5 months ago

Please refer to the following image:

image

At (7, 0), (7, 3) and (12, 0), the edges do not respect the enclose property and directly go through the node.

This happens if the node spans over 3 or more distance units, only the - 2 units in the center will be regarded as node.

Source Code:

  diagram(
    node-stroke: 1pt,
    node-outset: 1mm,
    spacing: (5mm, 5mm,),
    debug: 100,
    {
      node((0, 0), [PC])

      node((2, 0), [Inst. Mem.])

      node([MUX], enclose: ((5, 2), (5, 3)))

      node([Reg. File], enclose: ((7, 0), (7, 1), (7, 2), (7, 3)))
      node((7, 4), [Sign Ext.])

      node([MUX], enclose: ((9, 1), (9, 2)))

      node([ALU], enclose: ((10, 0), (10, 1)))

      node([Data Mem.], enclose: (((12, 0), (12, 1), (12, 2), (12, 3))))
      node([MUX], enclose: ((12, 5), (12, 6)))

      edge((0, 0), "rr", "->")

      edge((2, 0), "r", "->")

      edge((3, 0), "rtrbrr", "->")
      edge((3, 0), "b,rrrr", "->")
      edge((3, 0), "bb,rr", "->")
      edge((3, 0), "bbb,rr", "->")
      edge((3, 0), "bbbb,rrrr", "->")

      edge((5, 2), "rr", "->")

      edge((7, 0), "rrr", "->")
      edge((7, 1), "rr", "->")
      edge((7, 4), "r,tt,r", "->")

      edge((9, 1), "r", "->")

      edge((10, 0), "rr", "->")

      edge((11, 0), "bbbb,rr,b,l", "->")
      edge((12, 0), "rr,bbbbbb,ll", "->")
      edge((12, 5), "llllll,tt,r", "->")
    }
  )

I am using the latest version of fletcher on the main branch.

FlandiaYingman commented 5 months ago

After reading the manual again, seems that the edge only respect pos but not enclose? Now I am not sure if it is a feature or bug.

Jollywatt commented 5 months ago

You can fix this by setting the snap-to argument of edge().

Usually, edges automatically snap to the nearest node, as long as it is within one unit. However, nodes which enclose many points are hard, because what if there are smaller nodes inside? Should the edge snap to the inner node or larger node? I couldn't decide, so instead added the snap-to argument as a manual override.

You can specify nodes in snap-to by giving the target node a name. In the example below, I gave the "Reg. File" a node name and set snap-to for all the edges that didn't snap automatically.

Instead of names, you can also give enclosing nodes a "position", which doesn't control the node's position, but still affects how edges snap to it. Notice for the "Data Mem." node I added (12, 0) as its center, so the two edges snap to it automatically.

Example fix ```typc diagram( node-stroke: 1pt, node-outset: 1mm, spacing: (5mm, 5mm,), debug: 100, { node((0, 0), [PC]) node((2, 0), [Inst. Mem.]) node([MUX], enclose: ((5, 2), (5, 3))) node([Reg. File], enclose: ((7, 0), (7, 1), (7, 2), (7, 3)), name: ) node((7, 4), [Sign Ext.]) node([MUX], enclose: ((9, 1), (9, 2))) node([ALU], enclose: ((10, 0), (10, 1))) node((12, 0), [Data Mem.], enclose: (((12, 0), (12, 1), (12, 2), (12, 3)))) node([MUX], enclose: ((12, 5), (12, 6))) edge((0, 0), "rr", "->") edge((2, 0), "r", "->") edge((3, 0), "rtrbrr", "->", snap-to: (auto, )) edge((3, 0), "b,rrrr", "->") edge((3, 0), "bb,rr", "->") edge((3, 0), "bbb,rr", "->") edge((3, 0), "bbbb,rrrr", "->") edge((5, 2), "rr", "->") edge((7, 0), "rrr", "->", snap-to: (, auto)) edge((7, 1), "rr", "->") edge((7, 4), "r,tt,r", "->") edge((9, 1), "r", "->") edge((10, 0), "rr", "->") edge((11, 0), "bbbb,rr,b,l", "->") edge((12, 0), "rr,bbbbbb,ll", "->") edge((12, 5), "llllll,tt,r", "->", snap-to: (auto, )) } ) ```
FlandiaYingman commented 5 months ago

That's great and it works!

IMO, the default snap-to for edges could be the outermost node, because, if there is a node that encloses many points, then:

and,

Jollywatt commented 5 months ago

Yeah, that's a good point. Maybe snapping to the wrong node is better than not snapping at all.