forked from HEL/circuiteria
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
beda61b9f4 | ||
|
|
2c6e5f44df |
No files matched your search
+24
-39
@@ -71,6 +71,30 @@ wire.wire("w4", ("p6","p7"), style: "guided",
|
|||||||
|
|
||||||
```, vertical: true)
|
```, vertical: true)
|
||||||
|
|
||||||
|
#let zigzag-at = example(
|
||||||
|
```
|
||||||
|
// `zigzag-at` places the middle bend of a zigzag wire
|
||||||
|
// on the axis of a referenced anchor, overriding
|
||||||
|
// `zigzag-ratio`.
|
||||||
|
element.block(x: 0, y: 0, w: 1.5, h: 1.5, id: "src",
|
||||||
|
ports: (east: ((id: "o", name: "O"),),))
|
||||||
|
element.block(x: 3, y: -1.2, w: 1, h: 1, id: "ref",
|
||||||
|
fill: util.colors.pink,
|
||||||
|
ports: (west: ((id: "p", name: "R"),),))
|
||||||
|
element.block(x: 5.5, y: -2, w: 1.5, h: 1.5, id: "dst",
|
||||||
|
ports: (west: ((id: "i", name: "I"),),))
|
||||||
|
// String form: anchor name of a port.
|
||||||
|
wire.wire("w1", ("src-port-o", "dst-port-i"),
|
||||||
|
style: "zigzag",
|
||||||
|
zigzag-at: "ref-port-p")
|
||||||
|
// Ergonomic offset: shift 8pt right of ref.east.
|
||||||
|
wire.wire("w2", ("src-port-o", "dst-port-i"),
|
||||||
|
style: "zigzag",
|
||||||
|
zigzag-at: (rel: 8pt, to: "ref.east"))
|
||||||
|
```,
|
||||||
|
vertical: true,
|
||||||
|
)
|
||||||
|
|
||||||
#let stub = example(```
|
#let stub = example(```
|
||||||
draw.circle((0, 0), radius: .1, name: "p")
|
draw.circle((0, 0), radius: .1, name: "p")
|
||||||
wire.stub("p", "north", name: "north", length: 1)
|
wire.stub("p", "north", name: "north", length: 1)
|
||||||
@@ -186,45 +210,6 @@ wire.wire("w2", ("b2-port-out", "b3-port-in2"),
|
|||||||
style: "zigzag")
|
style: "zigzag")
|
||||||
```)
|
```)
|
||||||
|
|
||||||
#let group-ports = example(```
|
|
||||||
// outside-port-names: true (default) — labels outside the border
|
|
||||||
element.group(
|
|
||||||
id: "g1", name: "outside (default)",
|
|
||||||
stroke: (dash: "dashed"),
|
|
||||||
fill: util.colors.blue.lighten(60%),
|
|
||||||
padding: 2em,
|
|
||||||
outside-port-names: true,
|
|
||||||
ports: (
|
|
||||||
west: ((id: "in", name: "D"),),
|
|
||||||
east: ((id: "out", name: "Q"),),
|
|
||||||
),
|
|
||||||
{ element.block(id: "b1", w: 2, h: 1.5, x: 0, y: 0,
|
|
||||||
fill: util.colors.green,
|
|
||||||
ports: (west: ((id: "d", name: "d"),),
|
|
||||||
east: ((id: "q", name: "q"),))) }
|
|
||||||
)
|
|
||||||
wire.wire("wG1in", ("g1-port-in", "b1-port-d"), directed: true)
|
|
||||||
wire.wire("wG1out", ("b1-port-q", "g1-port-out"), directed: true)
|
|
||||||
|
|
||||||
// outside-port-names: false — labels inside the border (block style)
|
|
||||||
element.group(
|
|
||||||
id: "g2", name: "inside",
|
|
||||||
stroke: (dash: "dashed"),
|
|
||||||
fill: util.colors.orange.lighten(60%),
|
|
||||||
padding: 2em,
|
|
||||||
outside-port-names: false,
|
|
||||||
ports: (
|
|
||||||
west: ((id: "in", name: "D"),),
|
|
||||||
east: ((id: "out", name: "Q"),),
|
|
||||||
),
|
|
||||||
{ element.block(id: "b2", w: 2, h: 1.5, x: 6, y: 0,
|
|
||||||
fill: util.colors.green,
|
|
||||||
ports: (west: ((id: "d"),), east: ((id: "q"),))) }
|
|
||||||
)
|
|
||||||
wire.stub("g2-port-in", "west")
|
|
||||||
wire.stub("g2-port-out", "east")
|
|
||||||
```, vertical: true)
|
|
||||||
|
|
||||||
#let intersection = example(```
|
#let intersection = example(```
|
||||||
wire.wire("w1", ((0, 0), (1, 1)), style: "zigzag")
|
wire.wire("w1", ((0, 0), (1, 1)), style: "zigzag")
|
||||||
wire.wire("w2", ((0, 0), (1, -.5)),
|
wire.wire("w2", ((0, 0), (1, -.5)),
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
@@ -1,84 +0,0 @@
|
|||||||
// Demonstrates ports on a group element.
|
|
||||||
// outside-port-names: true (default) — labels outside the group border
|
|
||||||
// outside-port-names: false — labels inside (block-style)
|
|
||||||
#import "/src/lib.typ": circuit, element, util, wire
|
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
|
||||||
|
|
||||||
#circuit({
|
|
||||||
// --- Group with port labels OUTSIDE (default) ---
|
|
||||||
element.group(
|
|
||||||
id: "cpu",
|
|
||||||
name: "CPU (labels outside)",
|
|
||||||
name-anchor: "north",
|
|
||||||
stroke: (dash: "dashed"),
|
|
||||||
fill: util.colors.yellow.lighten(60%),
|
|
||||||
padding: 1em,
|
|
||||||
outside-port-names: true,
|
|
||||||
ports: (
|
|
||||||
west: (
|
|
||||||
(id: "in1", name: "D1"),
|
|
||||||
(id: "in2", name: "D2"),
|
|
||||||
),
|
|
||||||
east: ((id: "out", name: "Q"),),
|
|
||||||
south: (
|
|
||||||
(id: "rst", name: "RST", vertical: true),
|
|
||||||
(id: "done", name: "DONE", vertical: true),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
{
|
|
||||||
element.block(
|
|
||||||
id: "reg2",
|
|
||||||
w: 2.5,
|
|
||||||
h: 3,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
fill: util.colors.green,
|
|
||||||
ports: (
|
|
||||||
west: ((id: "d1"), (id: "d2")),
|
|
||||||
east: ((id: "q"),),
|
|
||||||
north: ((id: "clk", clock: true),),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
// --- Group with port labels INSIDE (outside-port-names: false) ---
|
|
||||||
element.group(
|
|
||||||
id: "cpu2",
|
|
||||||
name: "CPU (labels inside)",
|
|
||||||
name-anchor: "north",
|
|
||||||
stroke: (dash: "dashed"),
|
|
||||||
fill: util.colors.yellow.lighten(60%),
|
|
||||||
padding: 4em,
|
|
||||||
outside-port-names: false,
|
|
||||||
ports: (
|
|
||||||
west: (
|
|
||||||
(id: "in1", name: "D1"),
|
|
||||||
(id: "in2", name: "D2"),
|
|
||||||
),
|
|
||||||
east: ((id: "out", name: "Q"),),
|
|
||||||
south: (
|
|
||||||
(id: "rst", name: "RST", vertical: true),
|
|
||||||
(id: "done", name: "DONE", vertical: true),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
{
|
|
||||||
element.block(
|
|
||||||
id: "reg2",
|
|
||||||
w: 2.5,
|
|
||||||
h: 3,
|
|
||||||
x: 10,
|
|
||||||
y: 0,
|
|
||||||
fill: util.colors.green,
|
|
||||||
ports: (
|
|
||||||
west: ((id: "d1"), (id: "d2")),
|
|
||||||
east: ((id: "q"),),
|
|
||||||
north: ((id: "clk", clock: true),),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
wire.stub("cpu2-port-in1", "west", name: "A")
|
|
||||||
wire.stub("cpu2-port-in2", "west", name: "B")
|
|
||||||
wire.stub("cpu2-port-out", "east", name: "Q")
|
|
||||||
})
|
|
||||||
+6691
-6817
File diff suppressed because it is too large.
Load diff
+1
-30
@@ -1,15 +1,9 @@
|
|||||||
#import "/src/cetz.typ": draw, coordinate
|
#import "/src/cetz.typ": draw, coordinate
|
||||||
#import "../util.typ"
|
#import "../util.typ"
|
||||||
#import "ports.typ": add-ports
|
|
||||||
|
|
||||||
/// Draws a group of elements
|
/// Draws a group of elements
|
||||||
///
|
///
|
||||||
/// #examples.group
|
/// #examples.group
|
||||||
///
|
|
||||||
/// Ports can also be defined on a group, just like on a block. By default
|
|
||||||
/// port labels are drawn *outside* the group border so they do not overlap
|
|
||||||
/// child elements. Set `outside-port-names: false` to draw them inside.
|
|
||||||
/// #examples.group-ports
|
|
||||||
/// - body (elements, function): Elements to group
|
/// - body (elements, function): Elements to group
|
||||||
/// - id (str): see #doc-ref("element.elmt")
|
/// - id (str): see #doc-ref("element.elmt")
|
||||||
/// - name (str): The group's name
|
/// - name (str): The group's name
|
||||||
@@ -22,10 +16,6 @@
|
|||||||
/// - array: either (`<all>`,), (`<vertical>`, `<horizontal>`) or (`<top>`, `<right>`, `<bottom>`, `<left>`)
|
/// - array: either (`<all>`,), (`<vertical>`, `<horizontal>`) or (`<top>`, `<right>`, `<bottom>`, `<left>`)
|
||||||
/// - dictionary: valid keys are "top", "right", "bottom" and "left"
|
/// - dictionary: valid keys are "top", "right", "bottom" and "left"
|
||||||
/// - radius (number): The corner radius
|
/// - radius (number): The corner radius
|
||||||
/// - ports (dictionary): see #doc-ref("element.elmt")
|
|
||||||
/// - ports-margins (dictionary): see #doc-ref("element.elmt")
|
|
||||||
/// - outside-port-names (bool): If `true` (default), port name labels are drawn outside the group border so they do not overlap child elements. Set to `false` to draw labels inside, matching the block behaviour
|
|
||||||
/// - debug (dictionary): see #doc-ref("element.elmt")
|
|
||||||
#let group(
|
#let group(
|
||||||
body,
|
body,
|
||||||
id: "",
|
id: "",
|
||||||
@@ -34,13 +24,7 @@
|
|||||||
fill: none,
|
fill: none,
|
||||||
stroke: black + 1pt,
|
stroke: black + 1pt,
|
||||||
padding: 0.5em,
|
padding: 0.5em,
|
||||||
radius: 0.5em,
|
radius: 0.5em
|
||||||
ports: (:),
|
|
||||||
ports-margins: (:),
|
|
||||||
outside-port-names: true,
|
|
||||||
debug: (
|
|
||||||
ports: false
|
|
||||||
)
|
|
||||||
) = {
|
) = {
|
||||||
let min-x = none
|
let min-x = none
|
||||||
let max-x = none
|
let max-x = none
|
||||||
@@ -84,19 +68,6 @@
|
|||||||
stroke: stroke,
|
stroke: stroke,
|
||||||
fill: fill
|
fill: fill
|
||||||
)
|
)
|
||||||
|
|
||||||
add-ports(
|
|
||||||
id,
|
|
||||||
id + ".north-west",
|
|
||||||
id + ".north-east",
|
|
||||||
id + ".south-east",
|
|
||||||
id + ".south-west",
|
|
||||||
ports,
|
|
||||||
ports-margins,
|
|
||||||
debug: debug.ports,
|
|
||||||
outside-name: outside-port-names,
|
|
||||||
)
|
|
||||||
|
|
||||||
if name != none {
|
if name != none {
|
||||||
draw.content(
|
draw.content(
|
||||||
id + "." + name-anchor,
|
id + "." + name-anchor,
|
||||||
|
|||||||
+5
-20
@@ -1,12 +1,11 @@
|
|||||||
#import "/src/cetz.typ": draw
|
#import "/src/cetz.typ": draw
|
||||||
#import "../util.typ": rotate-anchor, opposite-anchor
|
#import "../util.typ": rotate-anchor
|
||||||
|
|
||||||
#let add-port(
|
#let add-port(
|
||||||
elmt-id, side, port, pos,
|
elmt-id, side, port, pos,
|
||||||
prev: none,
|
prev: none,
|
||||||
next: none,
|
next: none,
|
||||||
debug: false,
|
debug: false
|
||||||
outside-name: false,
|
|
||||||
) = {
|
) = {
|
||||||
let name = port.at("name", default: "")
|
let name = port.at("name", default: "")
|
||||||
let name-rotate = port.at("vertical", default: false)
|
let name-rotate = port.at("vertical", default: false)
|
||||||
@@ -28,21 +27,9 @@
|
|||||||
// TODO: use context or vectors to have the height relative to the width
|
// TODO: use context or vectors to have the height relative to the width
|
||||||
draw.line(prev, pos1, next)
|
draw.line(prev, pos1, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
// When outside-name is true (e.g. for groups) the label is placed on the
|
|
||||||
// exterior of the element border so it does not overlap child elements.
|
|
||||||
// Horizontal labels: anchor = opposite of the side (e.g. east port → west-anchored text, outside).
|
|
||||||
// Vertical labels: same opposite side but rotated 90°, keeping text readable.
|
|
||||||
let name-anchor = if outside-name {
|
|
||||||
if name-rotate { rotate-anchor(opposite-anchor(side)) }
|
|
||||||
else { opposite-anchor(side) }
|
|
||||||
} else {
|
|
||||||
if name-rotate { rotate-anchor(side) } else { side }
|
|
||||||
}
|
|
||||||
|
|
||||||
draw.content(
|
draw.content(
|
||||||
pos,
|
pos,
|
||||||
anchor: name-anchor,
|
anchor: if name-rotate {rotate-anchor(side)} else {side},
|
||||||
padding: 2pt,
|
padding: 2pt,
|
||||||
angle: if name-rotate {90deg} else {0deg},
|
angle: if name-rotate {90deg} else {0deg},
|
||||||
name
|
name
|
||||||
@@ -73,8 +60,7 @@
|
|||||||
tl, tr, br, bl,
|
tl, tr, br, bl,
|
||||||
ports,
|
ports,
|
||||||
ports-margins,
|
ports-margins,
|
||||||
debug: false,
|
debug: false
|
||||||
outside-name: false,
|
|
||||||
) = {
|
) = {
|
||||||
let sides = (
|
let sides = (
|
||||||
"north": (tl, tr),
|
"north": (tl, tr),
|
||||||
@@ -123,8 +109,7 @@
|
|||||||
pos,
|
pos,
|
||||||
prev: pos-prev,
|
prev: pos-prev,
|
||||||
next: pos-next,
|
next: pos-next,
|
||||||
debug: debug,
|
debug: debug
|
||||||
outside-name: outside-name,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+152
-24
@@ -24,29 +24,123 @@
|
|||||||
return (pts, anchors)
|
return (pts, anchors)
|
||||||
}
|
}
|
||||||
|
|
||||||
#let get-zigzag-wire(pts, ratio, dir) = {
|
// Normalize an anchor-based placement value used by `zigzag-at`, `u-at`, and
|
||||||
|
// the `s-at-*` family.
|
||||||
|
//
|
||||||
|
// `axis` selects which cartesian component the offset applies to:
|
||||||
|
// - `"x"` → offset in x (used when the placement fixes an x coordinate, e.g.
|
||||||
|
// a vertical bend line for horizontal wire flow).
|
||||||
|
// - `"y"` → offset in y (used when the placement fixes a y coordinate).
|
||||||
|
//
|
||||||
|
// Accepted forms:
|
||||||
|
// - `none` → unset; caller falls back to
|
||||||
|
// depth/ratio-based placement.
|
||||||
|
// - `str` / tuple / native CeTZ dict → passed through as a CeTZ coordinate.
|
||||||
|
// - `(rel: <length>, to: <coord>)` with a *scalar* `rel`
|
||||||
|
// → ergonomic axial offset, rewritten
|
||||||
|
// to `(rel: (rel, 0), to: to)` for
|
||||||
|
// `axis == "x"` or
|
||||||
|
// `(rel: (0, rel), to: to)` for
|
||||||
|
// `axis == "y"`. If `rel` is already
|
||||||
|
// an array/tuple, the value is
|
||||||
|
// passed through unchanged.
|
||||||
|
#let normalize-scalar-offset(at, axis) = {
|
||||||
|
if at == none { return none }
|
||||||
|
if type(at) == dictionary and "rel" in at and "to" in at and type(at.rel) != array {
|
||||||
|
let r = at.rel
|
||||||
|
if axis == "x" {
|
||||||
|
return (rel: (r, 0), to: at.to)
|
||||||
|
} else {
|
||||||
|
return (rel: (0, r), to: at.to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return at
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backwards-compatible wrapper: translates the old `dir` vocabulary
|
||||||
|
// (`"vertical"` / `"horizontal"`) to the `axis` vocabulary used by
|
||||||
|
// `normalize-scalar-offset`.
|
||||||
|
#let normalize-zigzag-at(at, dir) = {
|
||||||
|
let axis = if dir == "vertical" { "x" } else { "y" }
|
||||||
|
return normalize-scalar-offset(at, axis)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to deduce the cardinal side a port anchor faces by comparing its
|
||||||
|
// position to the center of the element it belongs to. Returns none if the
|
||||||
|
// anchor is not a port-style anchor (i.e. does not contain "-port-") or if
|
||||||
|
// resolution fails.
|
||||||
|
#let detect-port-side(anchor, ctx) = {
|
||||||
|
if type(anchor) != str { return none }
|
||||||
|
let sep = "-port-"
|
||||||
|
if not anchor.contains(sep) { return none }
|
||||||
|
let elmt-id = anchor.split(sep).first()
|
||||||
|
let port-pos = none
|
||||||
|
let center-pos = none
|
||||||
|
// coordinate.resolve panics on unknown anchors; there is no try/catch in
|
||||||
|
// Typst, so we assume port anchors created by add-port always come with a
|
||||||
|
// matching group of the same name. If not, the user must set the relevant side parameter
|
||||||
|
// explicitly.
|
||||||
|
let (_, p1) = coordinate.resolve(ctx, anchor)
|
||||||
|
let (_, p2) = coordinate.resolve(ctx, elmt-id + ".center")
|
||||||
|
port-pos = p1
|
||||||
|
center-pos = p2
|
||||||
|
let dx = port-pos.at(0) - center-pos.at(0)
|
||||||
|
let dy = port-pos.at(1) - center-pos.at(1)
|
||||||
|
if calc.abs(dx) >= calc.abs(dy) {
|
||||||
|
return if dx >= 0 { "east" } else { "west" }
|
||||||
|
} else {
|
||||||
|
return if dy >= 0 { "north" } else { "south" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let get-zigzag-wire(pts, ratio, dir, at: none) = {
|
||||||
let start = pts.first()
|
let start = pts.first()
|
||||||
let end = pts.last()
|
let end = pts.last()
|
||||||
let mid = if dir == "vertical" {
|
|
||||||
(start, ratio, (horizontal: end, vertical: ()))
|
|
||||||
} else {
|
|
||||||
(start, ratio, (horizontal: (), vertical: end))
|
|
||||||
}
|
|
||||||
|
|
||||||
let points = if dir == "vertical" {
|
let points
|
||||||
(
|
if at == none {
|
||||||
start,
|
// Ratio-based placement (default).
|
||||||
(horizontal: mid, vertical: ()),
|
let mid = if dir == "vertical" {
|
||||||
(horizontal: (), vertical: end),
|
(start, ratio, (horizontal: end, vertical: ()))
|
||||||
end
|
} else {
|
||||||
)
|
(start, ratio, (horizontal: (), vertical: end))
|
||||||
|
}
|
||||||
|
|
||||||
|
points = if dir == "vertical" {
|
||||||
|
(
|
||||||
|
start,
|
||||||
|
(horizontal: mid, vertical: ()),
|
||||||
|
(horizontal: (), vertical: end),
|
||||||
|
end
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
start,
|
||||||
|
(horizontal: (), vertical: mid),
|
||||||
|
(horizontal: end, vertical: ()),
|
||||||
|
end
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(
|
// Anchor-based placement: the middle bend segment sits on the axis
|
||||||
start,
|
// extracted from `at` via CeTZ's perpendicular operator `|-`:
|
||||||
(horizontal: (), vertical: mid),
|
// - vertical: middle segment at x = at.x
|
||||||
(horizontal: end, vertical: ()),
|
// - horizontal: middle segment at y = at.y
|
||||||
end
|
points = if dir == "vertical" {
|
||||||
)
|
(
|
||||||
|
start,
|
||||||
|
(at, "|-", start),
|
||||||
|
(at, "|-", end),
|
||||||
|
end
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
start,
|
||||||
|
(start, "|-", at),
|
||||||
|
(end, "|-", at),
|
||||||
|
end
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let anchors = (
|
let anchors = (
|
||||||
"start": start,
|
"start": start,
|
||||||
@@ -204,8 +298,9 @@
|
|||||||
/// - reverse (bool): If true, the start and end points will be swapped (useful in cases where the start point depends on the end point, for example with perpendiculars)
|
/// - reverse (bool): If true, the start and end points will be swapped (useful in cases where the start point depends on the end point, for example with perpendiculars)
|
||||||
/// - directed (bool): If true, the wire will be directed, meaning an arrow will be drawn at the endpoint
|
/// - directed (bool): If true, the wire will be directed, meaning an arrow will be drawn at the endpoint
|
||||||
/// - rotate-name (bool): If true, the name will be rotated according to the wire's slope
|
/// - rotate-name (bool): If true, the name will be rotated according to the wire's slope
|
||||||
/// - zigzag-ratio (ratio): Position of the zigzag vertical relative to the horizontal span (only with style "zigzag")
|
/// - zigzag-ratio (auto, ratio): Position of the zigzag middle bend segment relative to the horizontal (or vertical) span, as a fraction between the two endpoints (only with style "zigzag"). Defaults to `auto`, which resolves to `50%`. Panics if combined with an explicitly set `zigzag-at`.
|
||||||
/// - zigzag-dir (str): The zigzag's direction. As either "vertical" or "horizontal" (only with dstyle "zigzag")
|
/// - zigzag-dir (auto, str): The zigzag's direction, as either "vertical" or "horizontal" (only with style "zigzag"). If `auto`, it is deduced from the endpoints when they are port anchors of the form `<elmt-id>-port-<port-id>` by comparing each port's position with its element's `.center` anchor: east/west-facing ports yield `"vertical"` (wire exits horizontally) and north/south-facing ports yield `"horizontal"`. If the direction cannot be deduced (no port anchor on either endpoint, or conflicting directions), it falls back to `"vertical"`.
|
||||||
|
/// - zigzag-at (none, str, array, dictionary): Optional. Anchor-based placement of the zigzag middle bend segment (only with style "zigzag"). When set, overrides `zigzag-ratio` (which must be left at its default `auto`). The middle segment sits on the axis extracted from the given coordinate: `x` for `zigzag-dir: "vertical"`, `y` for `"horizontal"`. Accepted forms: a raw CeTZ anchor name string (e.g. `"elmt.center"` or `"elmt-port-a"`); any native CeTZ coordinate (tuple, dict such as `(rel: (dx, dy), to: anchor)`); or the ergonomic scalar-offset form `(rel: <length>, to: <coord>)`, which is rewritten to a `(dx, 0)` offset for `"vertical"` and `(0, dy)` for `"horizontal"`. See #examples.zigzag-at
|
||||||
/// - dodge-y (number): Y position to dodge the wire to (only with style "dodge")
|
/// - dodge-y (number): Y position to dodge the wire to (only with style "dodge")
|
||||||
/// - dodge-sides (array): The start and end sides (going out of the connected element) of the wire (only with style "dodge")
|
/// - dodge-sides (array): The start and end sides (going out of the connected element) of the wire (only with style "dodge")
|
||||||
/// - dodge-margins (array): The start and end margins (i.e. space before dodging) of the wire (only with style "dodge")
|
/// - dodge-margins (array): The start and end margins (i.e. space before dodging) of the wire (only with style "dodge")
|
||||||
@@ -227,8 +322,9 @@
|
|||||||
guided-sides: ("east", "west"),
|
guided-sides: ("east", "west"),
|
||||||
directed: false,
|
directed: false,
|
||||||
rotate-name: true,
|
rotate-name: true,
|
||||||
zigzag-ratio: 50%,
|
zigzag-ratio: auto,
|
||||||
zigzag-dir: "vertical",
|
zigzag-dir: auto,
|
||||||
|
zigzag-at: none,
|
||||||
dodge-y: 0,
|
dodge-y: 0,
|
||||||
dodge-sides: ("east", "west"),
|
dodge-sides: ("east", "west"),
|
||||||
dodge-margins: (5%, 5%)
|
dodge-margins: (5%, 5%)
|
||||||
@@ -241,6 +337,19 @@
|
|||||||
panic("Wrong number of points (got " + str(pts.len()) + " instead of 2)")
|
panic("Wrong number of points (got " + str(pts.len()) + " instead of 2)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `zigzag-at` validation.
|
||||||
|
if zigzag-at != none {
|
||||||
|
if style != "zigzag" {
|
||||||
|
panic("wire '" + id + "': `zigzag-at` requires style: \"zigzag\" (got \""
|
||||||
|
+ style + "\")")
|
||||||
|
}
|
||||||
|
if zigzag-ratio != auto {
|
||||||
|
panic("wire '" + id
|
||||||
|
+ "': cannot combine `zigzag-at` with an explicit `zigzag-ratio`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let zigzag-ratio-effective = if zigzag-ratio == auto { 50% } else { zigzag-ratio }
|
||||||
|
|
||||||
// Normalize user-provided coordinates: (x, y) -> (x, y, 0)
|
// Normalize user-provided coordinates: (x, y) -> (x, y, 0)
|
||||||
let pts = pts.map(normalize-coord)
|
let pts = pts.map(normalize-coord)
|
||||||
|
|
||||||
@@ -259,7 +368,26 @@
|
|||||||
(points, anchors) = get-direct-wire(pts)
|
(points, anchors) = get-direct-wire(pts)
|
||||||
|
|
||||||
} else if style == "zigzag" {
|
} else if style == "zigzag" {
|
||||||
(points, anchors) = get-zigzag-wire(pts, zigzag-ratio, zigzag-dir)
|
let zz-dir = zigzag-dir
|
||||||
|
if zz-dir == auto {
|
||||||
|
let side-start = detect-port-side(pts.first(), ctx)
|
||||||
|
let side-end = detect-port-side(pts.last(), ctx)
|
||||||
|
let dir-from-side(s) = if s == none { none } else if s == "east" or s == "west" { "vertical" } else { "horizontal" }
|
||||||
|
let d-start = dir-from-side(side-start)
|
||||||
|
let d-end = dir-from-side(side-end)
|
||||||
|
// Fall back to "vertical" (the previous default) when the direction
|
||||||
|
// cannot be deduced (no port anchors, or conflicting endpoints).
|
||||||
|
if d-start != none and d-end != none and d-start != d-end { zz-dir = "vertical" }
|
||||||
|
else if d-start != none { zz-dir = d-start }
|
||||||
|
else if d-end != none { zz-dir = d-end }
|
||||||
|
else { zz-dir = "vertical" }
|
||||||
|
}
|
||||||
|
(points, anchors) = get-zigzag-wire(
|
||||||
|
pts,
|
||||||
|
zigzag-ratio-effective,
|
||||||
|
zz-dir,
|
||||||
|
at: normalize-zigzag-at(zigzag-at, zz-dir),
|
||||||
|
)
|
||||||
|
|
||||||
} else if style == "dodge" {
|
} else if style == "dodge" {
|
||||||
(points, anchors) = get-dodge-wire(
|
(points, anchors) = get-dodge-wire(
|
||||||
|
|||||||
Reference in new issue
Block a user