Skip to content
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

Allow enclosing nodes to be enclosed #45

Open
cooki35 opened this issue Aug 5, 2024 · 5 comments
Open

Allow enclosing nodes to be enclosed #45

cooki35 opened this issue Aug 5, 2024 · 5 comments
Labels
enhancement New feature or request wontfix This will not be worked on

Comments

@cooki35
Copy link

cooki35 commented Aug 5, 2024

Thank you for the great package!

While upgrading from 0.5.0 to 0.5.1 I noticed a problem.

In 0.5.0 it is possible to enclose a node by name which already encloses coordinates with another coordinate:

#import "@preview/fletcher:0.5.0" as fletcher: node, edge
#fletcher.diagram(
    node(name:<nodeenclosingcoordinates>, enclose: ((0,1),(0,2),)),
    node(name:<thisnodeistheproblem>, enclose: (<nodeenclosingcoordinates>, (0,3),)),
)

Doing the same with 0.5.1 results in an error:

#import "@preview/fletcher:0.5.1" as fletcher: node, edge
#fletcher.diagram(
    node(name:<nodeenclosingcoordinates>, enclose: ((0,1),(0,2),)),
    node(name:<thisnodeistheproblem>, enclose: (<nodeenclosingcoordinates>, (0,3),)),
)
compiled with errors

error: cannot compare length and float
    ┌─ @preview/fletcher:0.5.1/src/utils.typ:191:20
    │
191 │   let p1 = (calc.min(..xs), calc.min(..ys))
    │                      ^^^^

help: error occurred in this call of function `bounding-rect`
    ┌─ @preview/fletcher:0.5.1/src/node.typ:422:23
    │
422 │     let (center, size) = bounding-rect(enclosed-vertices)
    │                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

help: error occurred in this call of function `map`
    ┌─ @preview/fletcher:0.5.1/src/node.typ:397:13
    │
397 │     let nodes = nodes.map(node => {
    │ ╭───────────────^
398 │ │     if node.enclose.len() == 0 { return node }
399 │ │
400 │ │     let enclosed-vertices = node.enclose.map(key => {
    · │
432 │ │     node
433 │ │   })
    │ ╰────^

help: error occurred in this call of function `resolve-node-enclosures`
    ┌─ @preview/fletcher:0.5.1/src/diagram.typ:527:31
    │
527 │     let (extra-anchors, nodes) = resolve-node-enclosures(nodes, ctx-with-xyz-anchors)
    │                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If the first node does not enclose coordinates there is no problem:

#import "@preview/fletcher:0.5.1" as fletcher: node, edge
#fletcher.diagram(
    node(name:<thenode>, (0,1)),
    node(name:<thisnodeistheproblem>, enclose: (<thenode>, (0,3),)),
)
@Jollywatt
Copy link
Owner

Hmm. I'm actually surprised that it worked in 0.5.0 at all. Officially, nested enclosed nodes aren't supported - nodes can only enclose other "normal" nodes.

Even though no error is produced with 0.5.0, nesting enclosed nodes doesn't work correctly in general. For example:

#import "@preview/fletcher:0.5.0" as fletcher: node, edge
#fletcher.diagram(
    node(enclose: ((0,0), (1,1)), stroke: red, name:<nodeenclosingcoordinates>)[Inner],
    node(name:<thisnodeistheproblem>, stroke: blue, enclose: (<nodeenclosingcoordinates>, (0,3),))[Outer],
)

To support nested enclose nodes, I suppose fletcher would need to resolve a dependency graph controlling the order in which nodes should be placed and sized. This is more complicated than what it does currently, which is to just place all normal nodes first and then all enclose nodes.

Before considering adding such a feature, it's probably worth asking: what kind of diagram are you wanting to create that could use nesting like this? I'm interested in what users really get up to!:)

@cooki35
Copy link
Author

cooki35 commented Aug 5, 2024

Thanks for the quick reply.
It happens when I make a diagram where I want to have some stacked nodes and then I want to enclose or highlight some part of it. Is there a better way to do this?

#import "@preview/fletcher:0.5.0" as fletcher: node, edge
#fletcher.diagram(
    node-stroke: 1pt,
    spacing: (0.5em, 1em),

    node((0,1), height:2em, width:3.5em, corner-radius:8pt, "Library"),
    node((1,1), height:2em, width:3.5em, corner-radius:8pt, "Library"),
    node((2,1), height:2em, width:3.5em, corner-radius:8pt, "Library"),
    node(name:<code>, height:2em, width:3.5em, corner-radius:8pt, enclose: ((0,0),(1,0),(2,0)), "Code"),

    node(stroke: blue, enclose: (<code>, (0,1),(2,1)),),
    node((1,-1), stroke:none, "Application")
)

image

@Jollywatt
Copy link
Owner

Well, one trick that sometimes works is to have the inner nodes in their own diagram, which is then used as the node label in an outer diagram. Like this:

#import "@preview/fletcher:0.5.0" as fletcher: node, edge
#let inner = fletcher.diagram(
  node-stroke: 1pt,
  spacing: (0.5em, 1em),
  {
    let row(y) = (
      node((0,y), height:2em, width:3.5em, corner-radius:8pt, "Library"),
      node((1,y), height:2em, width:3.5em, corner-radius:8pt, "Library"),
      node((2,y), height:2em, width:3.5em, corner-radius:8pt, "Library"),
    )
    row(0).map(fletcher.hide).join()
    row(1).join()

    node(name:<code>, height:2em, width:3.5em, corner-radius:8pt, inset: 0pt,enclose: ((0,0),(1,0),(2,0)), "Code")
  },
)
#fletcher.diagram(
  spacing: 10pt,
  node((0,-1))[Application],
  edge("->"),
  node((0,0), inner, stroke: blue),
)
Screenshot 2024-08-05 at 22 18 09

I also made the "Code" node enclose some invisible copies of the "Library" nodes below to make the width right.

@aWeinzierl
Copy link

Before considering adding such a feature, it's probably worth asking: what kind of diagram are you wanting to create that could use nesting like this? I'm interested in what users really get up to!:)

I wanted to create a diagram showing a software architecture and needed 4 levels of nesting, so I had to resort to draw.io.

Consider the following diagram as an example for such a diagram:
UML-component-diagram-of-the-system-architecture

It's probably also desirable to be able to code the nodes in a nested way.

@Jollywatt Jollywatt changed the title Nested enclose not working in 0.5.1 Feature request: allow enclosing nodes to be enclosed Nov 30, 2024
@Jollywatt Jollywatt changed the title Feature request: allow enclosing nodes to be enclosed Allow enclosing nodes to be enclosed Nov 30, 2024
@Jollywatt Jollywatt added enhancement New feature or request wontfix This will not be worked on labels Nov 30, 2024
@Jollywatt
Copy link
Owner

I'm not sure how hard it would be to allow recursively enclosed nodes, and probably won't prioritise it, but will leave this issue open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

3 participants