#CeTZ

1085 messages Β· Page 2 of 2 (latest)

spring wasp
#

Opened the release PR (0.5.2) including the fixes + lots of performance improvements + boolean path operations πŸ™‚

kindred ocean
#

oh yeah i saw!

#

thanks

#

is there typically like some time/process before it shows up in typst universe

spring wasp
#

It takes 1-3 days normally.

chilly hornet
#

does that mean you can do cropping in cetz now?

spring wasp
#

Yes.

north light
spring wasp
#

It is for computing intersection, union and difference paths.

#

Built-in cropping for groups is in the works by the author of the feature, as far as I know.

chilly hornet
#

Also I’m a bit confused by it erroring on non-closed paths. That makes it seem like it is only for Booleans of β€œsolids”. But is it really not possible to boolean a single line for example?

safe canopy
chilly hornet
#

Ah I guess I see. I was thinking it was possible to cut a stoke in two for example, but I guess that isn’t really expressible in svg/pdf

spring wasp
north light
#

I think this? As far as I know SVG needs a "stroke-to-path" conversion of the line first

#

actually, masking does allow you to do it without converting the line into a polygon

chilly hornet
#

yeah exactly that! But yeah I had concluded I needed the full paths. As for clipping, I was able to use a sort of wide frame, to subtract everything outside a rectangle. That worked well!

kindred ocean
#

how do i make this point unaffected by the projection (so not elliptical)

#

if i move it outside ortho its no longer at the rigth location

crystal nest
#

you could try placing an anchor there instead of a circle with anchor()

crystal nest
kindred ocean
#

this worked perfectly

#

ty

crystal nest
#

np

kindred ocean
#

the 3 bold curves are the catmulls

#

can i fill "between them"

spring wasp
kindred ocean
#

k thanks

safe canopy
# kindred ocean

Unrelated, but hobby typically looks a lot nicer than catmull πŸ™‚

kindred ocean
#

i’m trying to replicate the trajectories of latexes smooth plot

#

and i think it matches cat mull with .5

safe canopy
haughty canopy
#

?r

#import "@preview/cetz:0.5.2"


#let vertices = ((0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0))

#align(center)[
  #cetz.canvas(
    cetz.draw.ortho({
      import cetz.draw: *
      let area = ((0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0))
      line(..area, close: true, fill: red.transparentize(0%))
      line((1 / 2, 1 / 2, 0), (rel: (0, 0, 2)), mark: (end: ">>"))
    }),
  )
]


#align(center)[
  #cetz.canvas(
    cetz.draw.ortho({
      import cetz.draw: *
      let area = ((0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0))
      line(..area, close: true, fill: red.transparentize(0%))
      line((1 / 2, 1 / 2, 0), (rel: (0, 0, 2)))
    }),
  )
]

haughty canopy
#

When using cetz.draw.ortho, the layers should theoretically be arranged according to their position on the 3D model. However, I've found that if a line has a mark, its layer moves to the very back. How can I solve this problem?

#

It's very wierd

spring wasp
#

Seems to be a bug. You can disable the sorting by passing sorted: false.

kindred ocean
#

how do I make each | attached to the line, it seems disconnected

spring wasp
spring wasp
plush pasture
#

Is there a way to have the mark fill use the current stroke color, without having to spell it explicitly? I tried this:

#import "@preview/cetz:0.5.2"

#cetz.canvas({
  import cetz.draw: *
  set-style(stroke: red)

  line((0, 0), (1, 0), mark: (end: ">", fill: auto))
})

but it doesn't fill (or fills in white, I don't know)

#

I basically want to specify "filled mark" as a mark symbol, without having to know the stroke color

spring wasp
plush pasture
# spring wasp No, there is no such option currently.

Ok thanks. Thinking about it maybe true would be better than auto for this purpose since that's already used for something a bit different (auto meaning "inherit current value" when folding strokes for example)

spring wasp
safe canopy
#

What doesn't work exactly?

spring wasp
#

No builtin way, but you can just define let content(..args) = cetz.draw.content(anchor: "base", ..args) :).
(I suggest upgrading to 0.5.2.)

kindred ocean
#

I have the fill pattern, is there a way to do a fill between?

#

If I compound path them then its the complement of V that gets shaded instead

#

(on the left image)

vast crystal
safe canopy
#

Deepwiki is not reliable

crystal nest
safe canopy
crystal nest
#

oh ok

#

You almost made me think the boolean function was fake news

#

πŸ˜‚

safe canopy
chilly hornet
#

The boolean function is brilliant! It unlocked a bunch of things that I've been trying to draw!

kindred ocean
#

i js had to refresh the repository

#

?r

#import "@preview/cetz:0.5.2"
#cetz.canvas(length: 1cm, {
  import cetz.draw: *
  let lendpoint = (-1.5, -0.75)
  let rendpoint = (1.65, -1.35)
  let lendpoint-ext-ang = -150deg
  let rendpoint-ext-ang = -30deg
  let lendpoint-ext = (lendpoint, 10, lendpoint-ext-ang, (rel: lendpoint, to: (1, 0)))
  let rendpoint-ext = (rendpoint, 10, rendpoint-ext-ang, (rel: rendpoint, to: (1, 0)))
 
  catmull(
    (3.6, 0.9),
    (2.1, 2.55),
    (-1.2, 0.75),
    lendpoint,
    (-1.1, -1.3),
    (-0.75, -1.5),
    (0.5, -1.4),
    rendpoint,
    tension: 0.5,
    close: true,
    name: "Omega_2",
  )
  compound-path(
    {
      catmull(
        lendpoint,
        (-1.1, -0.4),
        (-0.6, -0.5),
        (-0.1, 0.2),
        (0.4, 0.5),
        (0.9, 0.1),
        (1.2, -0.2),
        rendpoint,
        tension: 0.5,
      )
      line(rendpoint, rendpoint-ext)
      line(rendpoint-ext, lendpoint-ext)
      line(lendpoint-ext, lendpoint)
    },
    name: "phi(V)-ext-testline",
  )


  boolean(
    "Omega_2",
    "phi(V)-ext-testline",
    op: "intersection",
    fill: blue,
    name: "phi(V)",
  )

  content((0.2, -0.5), text(size: 9pt)[$phi(V)$], anchor: "north")
  content((2.6, -0.8), text(size: 9pt)[$partial Omega_2$], anchor: "north")
})
shy ospreyBOT
kindred ocean
#

Why isn't the path closed? I explicitly tried to make it be closed

proper lava
#

two things: you're using compound-path instead of merge-path, and that one is also missing the close: true attribute
#bot-corner message

kindred ocean
#

?r

#import "@preview/cetz:0.5.2"
#cetz.canvas(length: 1cm, {
  import cetz.draw: *
  let lendpoint = (-1.5, -0.75)
  let rendpoint = (1.65, -1.35)
  let lendpoint-ext-ang = -150deg
  let rendpoint-ext-ang = -30deg
  let lendpoint-ext = (lendpoint, 6, lendpoint-ext-ang, (rel: lendpoint, to: (1, 0)))
  let rendpoint-ext = (rendpoint, 6, rendpoint-ext-ang, (rel: rendpoint, to: (1, 0)))

  catmull(
    (3.6, 0.9),
    (2.1, 2.55),
    (-1.2, 0.75),
    lendpoint,
    (-1.1, -1.3),
    (-0.75, -1.5),
    (0.5, -1.4),
    rendpoint,
    tension: 0.5,
    close: true,
    name: "Omega_2",
  )

  merge-path(
    {
      catmull(
        lendpoint,
        (-1.1, -0.4),
        (-0.6, -0.5),
        (-0.1, 0.2),
        (0.4, 0.5),
        (0.9, 0.1),
        (1.2, -0.2),
        rendpoint,
        tension: 0.5,
      )
      line(rendpoint, rendpoint-ext)
      line(rendpoint-ext, lendpoint-ext)
    },
    name: "phi(V)-ext-testline",
    close: true,
  )

  boolean(
    "Omega_2",
    "phi(V)-ext-testline",
    op: "intersection",
    fill: blue,
    name: "phi(V)",
  )

  content((0.2, -0.5), text(size: 9pt)[$phi(V)$], anchor: "north")
  content((2.6, -0.8), text(size: 9pt)[$partial Omega_2$], anchor: "north")
})
kindred ocean
#

is there a way to retain boolean shading while hiding the extension lines

#

the goal is to recreate this

#

edit: putting stroke: none in the merge path hides the lines but the spacing is still off

vast crystal
#

That's because you draw that shape, instead could say let phi-v-ext-testline = merge-path(...) and then boolean(phi-v-ext-testline, "Omega_2", ...). This way you don't render phi-v-ext-testline and only use it for computing the intersection with "Omega_2"

kindred ocean
#

?r

#import "@preview/cetz:0.5.2"
#cetz.canvas(length: 1cm, {
  import cetz.draw: *
  import cetz.draw: *
  set-style(mark: (fill: black))
  line((-.9, 0), (.9, 0), stroke: 3pt, name: "I")
  let x-max = 1.2
  hobby(
    (-0.6, 0.4),
    (-0.5, 0.6),
    (-0.4, 0.7),
    (0.1, 0.8),
    (0.3, 0.6),
    (0.9, 0),
    (0.5, -0.3),
    (0.2, -0.8),
    (-0.3, -0.7),
    (-0.6, -0.3),
    (-0.9, 0),
    close: true,
    name: "partial-N1",
    fill: black.transparentize(60%),
  )
  floating(
    merge-path(
      {
        line((-x-max, 0), (x-max, 0))
        line((x-max, 0), (x-max, -1.5))
        line((x-max, -1.5), (-x-max, -1.5))
      },
      close: true,
      stroke: white,
      name: "N1+-rect-testline",
    ),
  )
  boolean(
    "N1+-rect-testline",
    "partial-N1",
    op: "intersection",
    fill: white,
  )
})
shy ospreyBOT
kindred ocean
#

Does anyone know what might be wrong with this boolean

slow elk
#

v has two elements but it's trying to access the third, there's a lot going on though

#

I think there have been some recent bug fixes is this the newest version of cetz?

trail crown
#

0.5.2 should be the latest

this is inside same-z-plane, which is supposed to check that the path is actually flat before attempting to do a boolean operation with it. v.at(2) probably tries to access the z coordinate. If I replace the hobby with something else, it works. So I guess there is a bug/limitation with using hobby curves with boolean.

vast crystal
#

Found the issue, it's in hobby-to-cubic in hobby.typ, where the cubic bezier parts of the hobby curve get computed: The points are 3D (due to a previous coordinate.resolve call in shapes.typ) but the control points get computed using complex numbers and are thus 2D. This later gives the problem that a third coordinate is missing when doing computations between points and control points.
Quick fix for @kindred ocean would be to replace the return of hobby-to-cubic-closed in hobby.typ with
return range(n).map(i => (points.at(i), points.at(i+1), ca.at(i) + (0,), cb.at(i) + (0,)))
which simply adds a third coordinate to the control points (and the open variant too if needed)
Maybe there's also a way to tell cetz to resolve these coordinates to 2D only, but I don't know enough about that

plush pasture
#

It looks like transform-rotate-xz and trransform-rotate-ypr include a translation component:

#let transform-rotate-xz(x, z) = {
  (
    (cos(z), sin(z), 0, 0),
    (-cos(x) * sin(z), cos(x) * cos(z), -sin(x), 0),
    (sin(x) * sin(z), -sin(x) * cos(z), cos(x), 1),
    (0, 0, 0, 1),
  )
}
#let transform-rotate-ypr(a, b, c) = {
  (
    (cos(a) * cos(b), cos(a) * sin(b) * sin(c) - sin(a) * cos(c), cos(a) * sin(b) * cos(c) + sin(a) * sin(c), 0),
    (sin(a) * cos(b), sin(a) * sin(b) * sin(c) + cos(a) * cos(c), sin(a) * sin(b) * cos(c) - cos(a) * sin(c), 0),
    (-sin(b), cos(b) * sin(c), cos(b) * cos(c), 1),
    (0, 0, 0, 1),
  )
}

In both cases the third row has last value equal to 1 instead of 0

#

Is that intentional?

spring wasp