Could you please help to use fletcher/cetz to draw this picture?
I agree with How to draw bagua with fletcher/CeTZ? - #2 by nleanba, but just for fun:
Code
#let r = 10pt
#set page(height: auto, width: auto, margin: 2 * r)
// Debug:
// #set grid(stroke: green + 0.5pt)
#let span-x(n, fill: white) = grid(
columns: n,
column-gutter: r,
row-gutter: -2 * r,
grid.cell(colspan: n, box(height: 2 * r, line(length: n * 3 * r - r))),
..range(n).map(_ => circle(radius: r, fill: fill, stroke: black)),
)
#let span-y(n, fill: white) = grid(
columns: 2,
column-gutter: -2 * r,
box(width: 2 * r, line(length: n * 3 * r - r, angle: 90deg)),
grid(
columns: 1,
row-gutter: r,
..range(n).map(_ => circle(radius: r, fill: fill, stroke: black)),
),
)
#let the-center = box(
stroke: black,
inset: -r,
{
set align(center)
set par(spacing: 0pt)
span-x(5, fill: black)
v(2 * r)
span-y(3)
v(-5 * r)
span-x(3)
v(5 * r)
span-x(5, fill: black)
},
)
#grid(
columns: (1, 1, 7, 1, 1).map(x => x * 2 * r),
align: center + horizon,
column-gutter: 2 * r,
grid.cell(colspan: 1, {}),
grid.cell(colspan: 3, span-x(7)),
grid.cell(colspan: 1, {}),
grid.cell(colspan: 5, v(2 * r)),
grid.cell(colspan: 2, {}),
span-x(2, fill: black),
grid.cell(colspan: 2, {}),
span-y(8, fill: black),
span-y(3),
the-center,
span-y(4, fill: black),
span-y(9),
grid.cell(colspan: 2, {}),
span-x(1),
grid.cell(colspan: 2, {}),
grid.cell(colspan: 5, v(2 * r)),
grid.cell(colspan: 1, {}),
grid.cell(colspan: 3, span-x(6, fill: black)),
grid.cell(colspan: 1, {}),
)
I use grids instead of CeTZ, because itโs easier to align items without calculating coordinates. The following is a debug version showing green strokes of the grids.
4 Likes
If you want to use CeTZ this might be a good start:
#import "@preview/cetz:0.4.1": *
#set page(width: auto, height: auto)
#canvas(length: 1cm, {
// Import all drawing functions from the draw module
import draw: *
// Define a function to draw a line of circles between two points.
// If 'filled' is true, the circles are black; otherwise, they are white.
let circle-line(start, stop, filled: false) = {
// Check if the line is vertical (x-coordinates are equal)
if (start.at(0) == stop.at(0)) {
// Find the minimum y-coordinate to start from
let start-y = calc.min(start.at(1), stop.at(1))
// Calculate the number of steps (distance between y-coordinates)
let steps = calc.abs(start.at(1) - stop.at(1))
// Draw the main line between start and stop
line(start, stop)
// Draw circles at each integer y-position along the line
for i in range(steps + 1) {
circle(
(start.at(0), start-y + i),
radius: 0.33cm,
fill: if filled { black } else { white }
)
}
} else {
// The line is horizontal (y-coordinates are equal)
// Find the minimum x-coordinate to start from
let start-x = calc.min(start.at(0), stop.at(0))
// Calculate the number of steps (distance between x-coordinates)
let steps = calc.abs(start.at(0) - stop.at(0))
// Draw the main line between start and stop
line(start, stop)
// Draw circles at each integer x-position along the line
for i in range(steps + 1) {
circle(
(start-x + i, start.at(1)),
radius: 0.33cm,
fill: if filled { black } else { white }
)
}
}
}
circle-line((-1, 0), (1, 0))
circle-line((0, -1), (0, 1))
circle-line((-2, 3), (2, 3), filled: true)
circle-line((-2, -3), (2, -3), filled: true)
line((-2, 3), (-2, -3))
line((2, 3), (2, -3))
})
2 Likes
Super cool! Thank you!
1 Like