I'm trying to recreate this figure using Cetz however its proving more difficult than I expected. I thought I'd start by placing named points at the vertices of a cube, but draw.mark appears to be directional, and draw.circle is transformed by the ortho projection into an ellipse. Is there an easy way of doing this that I've missed?
#[Cetz] Trying to recreate this figure
32 messages · Page 1 of 1 (latest)
in a pinch you can use merge-path with the lines
a 3D rect works
but i think it might require having the same z which would break it
This is what I have so far: ```#let cube-vertex = (
"000": (0,0,0),
"001": (0,0,1),
"010": (0,1,0),
"011": (0,1,1),
"100": (1,0,0),
"101": (1,0,1),
"110": (1,1,0),
"111": (1,1,1),
)
#let cube-edges = (
solid: (
("001", "011", "010", "110", "100", "101", "001"),
("111", "110"),
("111", "101"),
("111", "011"),
),
dashed: (
("000", "001"),
("000", "010"),
("000", "100"),
)
)
#let draw-cube = {
for entry in cube-edges.solid {
cetz.draw.line( ..entry.map(it=>cube-vertex.at(it)) )
}
for entry in cube-edges.dashed {
cetz.draw.line( ..entry.map(it=>cube-vertex.at(it)), stroke: stroke( thickness: 0.5pt, dash: "dashed") )
}
}
?r ```rs
#import "@preview/cetz:0.2.2"
#cetz.canvas({
let cube-vertex = (
"000": (0,0,0),
"001": (0,0,1),
"010": (0,1,0),
"011": (0,1,1),
"100": (1,0,0),
"101": (1,0,1),
"110": (1,1,0),
"111": (1,1,1),
)
let cube-edges = (
solid: (
("001", "011", "010", "110", "100", "101", "001"),
("111", "110"),
("111", "101"),
("111", "011"),
),
dashed: (
("000", "001"),
("000", "010"),
("000", "100"),
)
)
let draw-cube-front = {
for entry in cube-edges.solid {
cetz.draw.line( ..entry.map(it=>cube-vertex.at(it)) )
}
}
let draw-cube-back = {
for entry in cube-edges.dashed {
cetz.draw.line( ..entry.map(it=>cube-vertex.at(it)), stroke: stroke( thickness: 0.5pt, dash: "dashed") )
}
}
import cetz.draw: *
rotate(y: 90deg)
draw-cube-back
merge-path(fill: red.transparentize(50%), stroke: red.darken(20%), {
line((0, 0, 1), (0, 1, 0), (1, 1, 0), (1, 0, 1),)
})
merge-path(fill: blue.transparentize(50%), stroke: blue.darken(20%), {
line((1, 0, 0), (0, 0, 0), (0, 1, 1), (1, 1, 1))
})
draw-cube-front
})
You can use on-layer(...) to draw the dashed lines behind, and the solid ones in front of the rect.
Will look into it, thanks! Might do a pr this evening with a cetz.draw.cube function
Check out ortho to (maybe) support rotation.
Will do!
would be cool to eventually have support for more solids in 3d
and plot capabilities in general
i'd be willing to contribute there
though im kinda noob at computer graphics
;-;
but i can try!
Contribute by moving the rendering pipeline rust-side 😭😭
For those sweet memoized speed gains
Plotting moved to cetz-plot (a separate repo). So if you want to contribute, make sure to use that.
ive done some pretty ungodly things to make a cylinder lol
as well as axes
?r t=l
lemme see if it works here
#import "@preview/cetz:0.2.2"
#cetz.canvas({
import cetz.draw: *
rotate(x: -90deg)
let z0 = 2
let h = 2.5
let center = (3, 3)
let r0 = 1.5
circle((..center, z0), radius: r0, stroke: (paint: luma(40%)), fill: blue.transparentize(50%), name: "main")
circle((rel: (0, 0, h), to: "main"), radius: r0, fill: blue.transparentize(50%))
circle((..center, 0), radius: r0, stroke: (dash: "dashed"), fill: red.lighten(90%))
content((..center, z0), text(blue.darken(20%))[$mu_1(x, y)$])
content((..center, z0 + h), text(blue.darken(20%))[$mu_2(x, y)$])
let circle-rot(theta, r: 1, x0: 0, y0: 0) = {
let x = x0 + r * calc.cos(theta)
let y = y0 + r * calc.sin(theta)
(x, y)
}
let ccr = circle-rot.with(x0: center.first(), y0: center.last(), r: r0)
let all-samples = cetz.plot.sample-fn(
ccr,
// (-calc.pi / 6, 5 * calc.pi / 6),
(-25deg, 180deg - 25deg),
50
)
let top-samples = all-samples.map(x => (..x, z0 + h))
let bot-samples = all-samples.map(x => (..x, z0))
merge-path(fill: red.transparentize(75%), {
line(..top-samples, ..bot-samples.rev(), top-samples.first())
})
line((..ccr(-25deg), 0), (..ccr(-25deg), z0), stroke: (dash: "dashed"))
line((..ccr(180deg - 25deg), 0), (..ccr(180deg - 25deg), z0), stroke: (dash: "dashed"))
content((center.first(), center.last(), z0 + h / 2), text(red.darken(5%))[$E$])
content((..center, 0), text(red.darken(5%))[$D$])
})