Fletcher: How to add a node shape that looks like an arrow?

Hi,
I am trying to create a (fletcher) diagram that uses a node that looks like an arrow, like this:
bus|0x0

I have created a new node shape, which looks like this:

#import "@preview/fletcher:0.5.8": *
#let arrow(node, extrude) = {
        let (w,h) = node.size
        let x = w/2 * 1.5
        let y = h/2 * 1.5
        let a_width = h/3
        let a_len = w/2
        let obj = draw.line(
          (-x, 0pt),
          (-a_len, -y),
          (-a_len, -a_width),
          (+a_len, -a_width),
          (+a_len, -y),
          (+x, 0pt),
          (+x, 0pt),
          (+a_len, +y),
          (+a_len, +a_width),
          (-a_len, +a_width),
          (-a_len, +y),
          (-x, 0pt),
          close: true
        )
        draw.group(obj)
      },

This brings me to the following:

How do I get the edges to connect to the stroke of the arrow?

Full figure:

 #set page(width: auto, height: auto)

#import "@preview/fletcher:0.5.8": *
#diagram(
  node-stroke: 0.5pt,
  spacing: (1em, 1em),

  let arrow(node, extrude) = {
    let (w,h) = node.size
    let x = w/2 * 1.5
    let y = h/2 * 1.5
    let a_width = h/3
    let a_len = w/2
    let obj = draw.line(
      (-x, 0pt),
      (-a_len, -y),
      (-a_len, -a_width),
      (+a_len, -a_width),
      (+a_len, -y),
      (+x, 0pt),
      (+x, 0pt),
      (+a_len, +y),
      (+a_len, +a_width),
      (-a_len, +a_width),
      (-a_len, +y),
      (-x, 0pt),
      close: true
    )
    draw.group(obj)
  },

  node((0,-2), [node2], name: <node2>),
  edge(<node2.south>, <node1.north>, "O-@"),
  node(enclose: ((-5,0), (5,0)) , [node1], shape: arrow, name: <node1>),
)

1 Like

Hey. Please fix your code block, it’s clearly not correctly highlighted. The example doesn’t compile, as a fletcher import is missing, but even with it, the output doesn’t match the image.

How to post in the Questions category :

I don’t know if the south/north have to be exactly on the shape border. Without them it works as expected.

#import "@preview/fletcher:0.5.8": *

#let arrow(node, extrude, fit: 0.5) = {
  let (w, h) = node.size
  let x = w / 2 * 1.5
  let y = h / 2 * 1.5

  let φ = calc.atan2(w / 1pt, h / 1pt)
  let x = w / 2 * (1 + fit) + extrude / calc.sin(φ)
  let y = h / 2 * (1 + fit) + extrude / calc.cos(φ)

  let a-width = h / 4 * (1 + fit)
  let a-len = w / 3 * (1 + fit)
  let obj = draw.line(
    (-x, 0pt),
    (-a-len, -y),
    (-a-len, -a-width),
    (+a-len, -a-width),
    (+a-len, -y),
    (+x, 0pt),
    (+x, 0pt),
    (+a-len, +y),
    (+a-len, +a-width),
    (-a-len, +a-width),
    (-a-len, +y),
    (-x, 0pt),
    close: true,
  )
  draw.group(obj)
}

#diagram(node-stroke: 0.5pt, spacing: 1em, {
  node((0, -1))[node2]
  edge()
  node((0, 0), shape: arrow)[node1]
  edge()
  node((0, 1))[node2]
})

1 Like

I was focused on the second codeblock and overlooked that I was missing the # before the let. Sorry. The full figure however was actually matching the image (except that I changed the arrow marks). I added the import, sorry about that.

Thank you for the answer!

1 Like