#CeTZ
1085 messages Β· Page 2 of 2 (latest)
oh yeah i saw!
thanks
is there typically like some time/process before it shows up in typst universe
It takes 1-3 days normally.
0.5.2 is available now.
does that mean you can do cropping in cetz now?
Yes.
I'm also a bit confused β is it for cropping paths (this is what I see in the docs), or can it also crop to a viewport (more like a masking)? I've not seen the latter, but I'd like to use it in gridcetz as it's the main discrepancy that remains: https://baptiste.codeberg.page/gridcetz/articles/ggplot-examples.html
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.
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?
What would that mean? Isn't it boolean operations on the interior of the curves?
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
Can you give an example? I don't get what you mean.
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
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!
dumb question but
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
you could try placing an anchor there instead of a circle with anchor()
and then doing circle("anchor", radius: ...) outside the ortho
np
Yes, you have to put them in a compound-path to make them a single path object to use the fill-rule.
k thanks
Unrelated, but hobby typically looks a lot nicer than catmull π
iβm trying to replicate the trajectories of latexes smooth plot
and i think it matches cat mull with .5
fair enough, I typically use hobby in latex as well
?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)))
}),
)
]
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
Seems to be a bug. You can disable the sorting by passing sorted: false.
how do I make each | attached to the line, it seems disconnected
It is a bug with using pos: it seems. I will create a ticket. You could try shorten-to: none to disable the path shortening, if that helps for your case.
Or pass inset: 0 which also works as a fix here.
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
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)
I think "stroke" (as string) would be better. Or maybe have a generic mechanism to "copy value from other style field" e.g. "copy:stroke".
What doesn't work exactly?
No builtin way, but you can just define let content(..args) = cetz.draw.content(anchor: "base", ..args) :).
(I suggest upgrading to 0.5.2.)
I'm trying to recreate this drawing (the dark background one is in cetz)
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)
Yes and I think that's quite a recent feature so you might have to check if you're using the latest version. You can do boolean(circle1, circle2, op: "intersection", fill: your-fill)
Deepwiki is not reliable
What was this referring to?
A message that was deleted
Maybe π€
The boolean function is brilliant! It unlocked a bunch of things that I've been trying to draw!
ive been using it for everything i didnt know so far lol
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")
})
An error occurred:
Error: assertion failed: boolean: every input subpath must be closed; got an open subpath
ββ[ @preview/cetz:0.5.2/src/draw/boolean.typ:90:5 ]
β
90 β assert(closed, message: "boolean: every input subpath must be closed; got an open subpath")
βββββ―
Why isn't the path closed? I explicitly tried to make it be closed
two things: you're using compound-path instead of merge-path, and that one is also missing the close: true attribute
#bot-corner message
?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")
})
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
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"
?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,
)
})
An error occurred:
Error: array index out of bounds (index: 2, len: 2) and no default value was specified
ββ[ @preview/cetz:0.5.2/src/path-util.typ:108:21 ]
β
108 β if calc.abs(v.at(2) - z0) > tol { return (z0, false) }
ββββββ―
Does anyone know what might be wrong with this boolean
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?
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.
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
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?
This seems to be a typo. Can you add this fix to your pr π Thank you!