How can I save a coordinate in Cetz?

I would like to achieve the equivalent of “coordinate” in Tikz. My goal is to save a coordinate (Eg. (5,0)) to a string (Eg. “my-cooord”) and use it later in the same canvas (Eg: line(“my-coord”, (rel: (0,2))). I’ve seen anchors, but to use them I have to use a group or at least a line end then I have to use dot notation (.start o .end) to retrieve the point. Thanks a lot!

1 Like

I have no idea about Tikz, but based on your description I think you’re looking for variables let var-name = ....

#cetz.canvas({
  import cetz.draw: *
  let my-coord = (5,0)
  line(my-coord, (rel: (0,2)))
})

I want to save it in the context of the Cetz canvas, to use it later beacase I’m building a complex library, and I would like to rely on Cetz context instead of using states. Thanks anyway.

I see 2 way to solve this:

#import "@preview/cetz:0.3.4"
#cetz.canvas({
  import cetz.draw: *
  let my-coord = (0, 0)
  circle(my-coord)
  line(my-coord, (rel: (1, 2)), mark: (end: ">"))

  circle((5, 5), name: "c")
  line("c", (rel: (1, 2)), mark: (end: ">"))
})

Not sure what you mean by “save a coordinate to a string”.

I guess you can do this:

#import "@preview/cetz:0.3.4"
#cetz.canvas({
  import cetz.draw: *
  set-ctx(ctx => ctx + (my-coords: ("my-coord": (0, 0))))
  get-ctx(ctx => {
    let my-coord = ctx.my-coords.my-coord
    circle(my-coord)
    line(my-coord, (rel: (1, 2)), mark: (end: ">"))
  })

  circle((5, 5), name: "c")
  line("c", (rel: (1, 2)), mark: (end: ">"))
})

I mean, to assign a string label to a point, like you have done in the circle with the attribute “name”. Something that I can use later, like you have done in line. Maybe I can use a circle with radius zero as a workaround or use your solution that seems valid. Thanks a lot!

You can’t assign “a string label” to a raw point, because there are no labels and cetz doesn’t provide a way to “save a raw point”, unless you use the set-ctx() function, which I assume is basically the same as saving your stuff in tikz. You can however save object (shapes, groups, intersections) position by using the name argument. Then you can reference it, which defaults to the .center anchor. Or use the variables, which is also sometimes very useful, but I don’t think I use them.

Thanks, you gave me the idea to assign a name to a point.

cetz.draw.circle(point, radius: 0, name: coordinate-name)

This works and emulate the “coordinate” function of Tikz.

Actually, I was wrong, you can use the anchor() function for this:

#import "@preview/cetz:0.3.4"
#cetz.canvas({
  import cetz.draw: *
  anchor("a", (0, 0))
  anchor("b", (1, 1))
  rect("a", "b")
})

I remembered this, probably because using a non-drawing circle to create a point is definitely not how you’re supposed to use the library, though you can.

3 Likes