How to draw complex plane contours in Cetz?

I apologize if the documentation for stuff like this is somewhere obvious, but I couldn’t find anything on filling in shapes made out of collections of curves. I am trying to convert over some of my old Tikz plots, and one of them was largely adapted from:

https://tex.stackexchange.com/questions/364646/how-do-you-create-a-keyhole-contour-not-centered-at-the-origin

How does one go about filling in a keyhole shaped contour? I know about cetz.angle.angle from one of the featured examples, but that would only get part of the contour.

https://cetz-package.github.io/docs/api/draw-functions/shapes/compound-path/
https://cetz-package.github.io/docs/api/draw-functions/shapes/merge-path

These two functions might help?

A 60% implementation
#set page(height: auto, width: auto, margin: 2em)

#import "@preview/cetz:0.4.0"
#cetz.canvas({
  import cetz.draw: *

  compound-path(
    group({
      circle((0, 0), radius: 3, fill: blue)
      circle((1, 1), radius: .5)

      rotate(-45deg)
      rect((-0.25, 1.8), (0.25, 3.1))
    }),
    fill: blue,
    fill-rule: "even-odd",
  )
})

100% - ε implementation:

#set page(height: auto, width: auto, margin: 2em)

#import "@preview/cetz:0.4.0"
#cetz.canvas({
  import cetz.draw: *

  let R = 3 // outer.radius
  let r = 0.5 // inner.radius
  let c = 1 // distance(origin, inner.center)
  let w = 1 / 4 // width of the hole

  intersections(
    "i",
    {
      hide(circle((0, 0), name: "outer", radius: R, fill: blue))
      hide(circle((45deg, c), name: "inner", radius: r))
      hide(group({
        rotate(-45deg)
        rect((-w / 2, c), (w / 2, R + r))
      }))
    },
  )

  // Debug:
  // for-each-anchor("i", name => content("i." + name, name))


  merge-path(
    {
      line("i.1", "i.3")
      arc-through("i.3", (45deg, c - r), "i.2")
      line("i.2", "i.0")
      arc-through("i.0", (0, -R), "i.1")
    },
    fill: blue,
  )
})
3 Likes

Ah, thank you, that looks wonderful.

I also didn’t realize much of the actual functionality of Cetz was explained in the API rather than the Docs.

1 Like