#[Cetz] Trying to recreate this figure

32 messages · Page 1 of 1 (latest)

rancid steppe
#

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?

viral canyon
#

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

rancid steppe
#

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") )
}
}

viral canyon
#

?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
})

scenic dock
#

You can use on-layer(...) to draw the dashed lines behind, and the solid ones in front of the rect.

viral canyon
#

well that should be it for the AC one

#

the rest should be pretty straightforward

rancid steppe
scenic dock
rancid steppe
#

Will do!

viral canyon
#

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!

rancid steppe
#

Contribute by moving the rendering pipeline rust-side 😭😭

#

For those sweet memoized speed gains

scenic dock
#

Plotting moved to cetz-plot (a separate repo). So if you want to contribute, make sure to use that.

viral canyon
#

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$])
})
viral canyon
#

lol

#

whoops

#

ok nice

#

lol

#

i had some fun with this

rancid steppe