Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
002db0e6f5 | ||
|
|
0fb4929aca | ||
|
|
23213fabca | ||
|
|
320318a25b | ||
|
|
9bcd91131c | ||
|
|
c9aa81af2e | ||
|
|
6871053810 | ||
|
|
73b7348eed
|
No files matched your search
@@ -3,7 +3,7 @@
|
||||
Circuiteria is a [Typst](https://typst.app) package for drawing block circuit diagrams using the [CeTZ](https://typst.app/universe/package/cetz) package.
|
||||
|
||||
<p align="center">
|
||||
<img src="./gallery/platypus.png" alt="Perry the platypus" alt="A platypus / Perry the Platypus meme made with colored rounded rectangles">
|
||||
<img src="./gallery/platypus.png" alt="A platypus / Perry the Platypus meme made with colored rounded rectangles">
|
||||
</p>
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -56,7 +56,7 @@ for i in range(3) {
|
||||
```)
|
||||
|
||||
#let wires = example(```
|
||||
for i in range(4) {
|
||||
for i in range(5) {
|
||||
draw.circle((i * 3, 0), radius: .1, name: "p" + str(i * 2))
|
||||
draw.circle((i * 3 + 2, 1), radius: .1, name: "p" + str(i * 2 + 1))
|
||||
draw.content((i * 3 + 1, -1), raw(wire.wire-styles.at(i)))
|
||||
@@ -68,6 +68,8 @@ wire.wire("w3", ("p4", "p5"), style: "dodge",
|
||||
wire.wire("w4", ("p6","p7"), style: "guided",
|
||||
guided-center:(20%, 40%), guided-margins: (90%,87%),
|
||||
guided-sides: ("north","south"))
|
||||
wire.wire("w5", ("p8", "p9"), style: "u-shape",
|
||||
u-side: "east", u-depth: 0.5)
|
||||
|
||||
```, vertical: true)
|
||||
|
||||
@@ -192,3 +194,45 @@ wire.wire("w2", ((0, 0), (1, -.5)),
|
||||
style: "zigzag", zigzag-ratio: 80%)
|
||||
wire.intersection("w1.zig")
|
||||
```)
|
||||
|
||||
#let u-shape-wire = example(```
|
||||
// east <-> east (u-side auto-detected)
|
||||
element.block(x: 0, y: 0, w: 1.5, h: 1.5, id: "eA",
|
||||
fill: util.colors.orange,
|
||||
ports: (east: ((id: "out"),)))
|
||||
element.block(x: 0.5, y: -2.5, w: 1.5, h: 1.5, id: "eB",
|
||||
fill: util.colors.orange,
|
||||
ports: (east: ((id: "out"),)))
|
||||
wire.wire("uEE", ("eA-port-out", "eB-port-out"),
|
||||
style: "u-shape", u-depth: 0.5)
|
||||
|
||||
// west <-> west (auto-detected)
|
||||
element.block(x: 6, y: 0, w: 1.5, h: 1.5, id: "wA",
|
||||
fill: util.colors.yellow,
|
||||
ports: (west: ((id: "in"),)))
|
||||
element.block(x: 6.5, y: -2.5, w: 1.5, h: 1.5, id: "wB",
|
||||
fill: util.colors.yellow,
|
||||
ports: (west: ((id: "in"),)))
|
||||
wire.wire("uWW", ("wA-port-in", "wB-port-in"),
|
||||
style: "u-shape", u-depth: 0.5)
|
||||
|
||||
// north <-> north (auto-detected)
|
||||
element.block(x: 10, y: -3, w: 1.5, h: 1.5, id: "nA",
|
||||
fill: util.colors.green,
|
||||
ports: (north: ((id: "out"),)))
|
||||
element.block(x: 12.5, y: -2.5, w: 1.5, h: 1.5, id: "nB",
|
||||
fill: util.colors.green,
|
||||
ports: (north: ((id: "out"),)))
|
||||
wire.wire("uNN", ("nA-port-out", "nB-port-out"),
|
||||
style: "u-shape", u-depth: 0.5)
|
||||
|
||||
// south <-> south with explicit u-side override
|
||||
element.block(x: 16, y: -3, w: 1.5, h: 1.5, id: "sA",
|
||||
fill: util.colors.pink,
|
||||
ports: (south: ((id: "out"),)))
|
||||
element.block(x: 18.5, y: -3.5, w: 1.5, h: 1.5, id: "sB",
|
||||
fill: util.colors.pink,
|
||||
ports: (south: ((id: "out"),)))
|
||||
wire.wire("uSS", ("sA-port-out", "sB-port-out"),
|
||||
style: "u-shape", u-side: "south", u-depth: 0.5)
|
||||
```, vertical: true)
|
||||
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
@@ -0,0 +1,53 @@
|
||||
// Demonstrates the u-shape wire style.
|
||||
// The u-side is auto-detected from the port anchors when both endpoints
|
||||
// belong to elements (deduced from the port position vs the element's
|
||||
// center anchor). It can also be set explicitly with u-side.
|
||||
#import "/src/lib.typ": circuit, element, util, wire
|
||||
|
||||
#set page(width: auto, height: auto, margin: .5cm)
|
||||
|
||||
#circuit({
|
||||
// ---- east <-> east (auto-detected) ----
|
||||
element.block(x: 0, y: 0, w: 1.5, h: 1.5, id: "eA",
|
||||
fill: util.colors.orange,
|
||||
ports: (east: ((id: "out"),)))
|
||||
element.block(x: 0.5, y: -2.5, w: 1.5, h: 1.5, id: "eB",
|
||||
fill: util.colors.orange,
|
||||
ports: (east: ((id: "out"),)))
|
||||
wire.wire("uEE", ("eA-port-out", "eB-port-out"),
|
||||
style: "u-shape", u-depth: 0.6,
|
||||
name: "E-E")
|
||||
|
||||
// ---- west <-> west (auto-detected) ----
|
||||
element.block(x: 6, y: 0, w: 1.5, h: 1.5, id: "wA",
|
||||
fill: util.colors.yellow,
|
||||
ports: (west: ((id: "in"),)))
|
||||
element.block(x: 6.5, y: -2.5, w: 1.5, h: 1.5, id: "wB",
|
||||
fill: util.colors.yellow,
|
||||
ports: (west: ((id: "in"),)))
|
||||
wire.wire("uWW", ("wA-port-in", "wB-port-in"),
|
||||
style: "u-shape", u-depth: 0.6,
|
||||
name: "W-W")
|
||||
|
||||
// ---- north <-> north (auto-detected) ----
|
||||
element.block(x: 10, y: -3, w: 1.5, h: 1.5, id: "nA",
|
||||
fill: util.colors.green,
|
||||
ports: (north: ((id: "out"),)))
|
||||
element.block(x: 12.5, y: -2.5, w: 1.5, h: 1.5, id: "nB",
|
||||
fill: util.colors.green,
|
||||
ports: (north: ((id: "out"),)))
|
||||
wire.wire("uNN", ("nA-port-out", "nB-port-out"),
|
||||
style: "u-shape", u-depth: 0.6,
|
||||
name: "N-N")
|
||||
|
||||
// ---- south <-> south (explicit u-side override) ----
|
||||
element.block(x: 16, y: 0, w: 1.5, h: 1.5, id: "sA",
|
||||
fill: util.colors.pink,
|
||||
ports: (south: ((id: "out"),)))
|
||||
element.block(x: 18.5, y: -0.5, w: 1.5, h: 1.5, id: "sB",
|
||||
fill: util.colors.pink,
|
||||
ports: (south: ((id: "out"),)))
|
||||
wire.wire("uSS", ("sA-port-out", "sB-port-out"),
|
||||
style: "u-shape", u-side: "south", u-depth: 0.6,
|
||||
name: "S-S")
|
||||
})
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
@@ -0,0 +1,46 @@
|
||||
// Demonstrates the `(rel: <number>, to: <anchor>)` shorthand for the `y`
|
||||
// parameter (analogous to the existing shorthand for `x`).
|
||||
#import "/src/lib.typ": circuit, element, util, wire
|
||||
|
||||
#set page(width: auto, height: auto, margin: .5cm)
|
||||
|
||||
#circuit({
|
||||
// Anchor block: absolute placement.
|
||||
element.block(
|
||||
x: 0, y: 0, w: 2, h: 1.5,
|
||||
id: "A",
|
||||
fill: util.colors.orange,
|
||||
ports: (east: ((id: "out"),))
|
||||
)
|
||||
|
||||
// X relative, Y absolute (existing feature).
|
||||
element.block(
|
||||
x: (rel: 1, to: "A.east"), y: 0, w: 2, h: 1.5,
|
||||
id: "B",
|
||||
fill: util.colors.yellow,
|
||||
ports: (west: ((id: "in"),), east: ((id: "out"),))
|
||||
)
|
||||
|
||||
// Both X and Y relative to another element's anchor (new feature).
|
||||
element.block(
|
||||
x: (rel: 1, to: "B.east"),
|
||||
y: (rel: 2, to: "B.south-west"),
|
||||
w: 2, h: 1.5,
|
||||
id: "C",
|
||||
fill: util.colors.green,
|
||||
ports: (west: ((id: "in"),))
|
||||
)
|
||||
|
||||
// Y relative only, X absolute.
|
||||
element.block(
|
||||
x: 0,
|
||||
y: (rel: -2.5, to: "A.south-west"),
|
||||
w: 2, h: 1.5,
|
||||
id: "D",
|
||||
fill: util.colors.blue,
|
||||
ports: (east: ((id: "out"),))
|
||||
)
|
||||
|
||||
wire.wire("wAB", ("A-port-out", "B-port-in"))
|
||||
wire.wire("wBC", ("B-port-out", "C-port-in"), style: "zigzag")
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
#import "@preview/tidy:0.4.1"
|
||||
#import "@preview/tidy:0.4.3"
|
||||
#import "/src/cetz.typ": draw, canvas
|
||||
#import "src/lib.typ"
|
||||
#import "doc/examples.typ"
|
||||
|
||||
@@ -1 +1 @@
|
||||
#import "@preview/cetz:0.3.4": *
|
||||
#import "@preview/cetz:0.5.2": *
|
||||
@@ -1,5 +1,5 @@
|
||||
#import "/src/cetz.typ": canvas
|
||||
#import "@preview/tidy:0.3.0"
|
||||
#import "@preview/tidy:0.4.3"
|
||||
|
||||
/// Draws a block circuit diagram
|
||||
///
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
/// If it is a dictionary, it should be in the format `(rel: number, to: str)`, where `rel` is the offset and `to` the base anchor
|
||||
/// - y (number, dictionary): The y position (bottom-left corner).
|
||||
///
|
||||
/// If it is a dictionary, it should be in the format `(from: str, to: str)`, where `from` is the base anchor and `to` is the id of the port to align with the anchor
|
||||
/// If it is a dictionary, it can take one of two forms:
|
||||
/// - `(rel: number, to: str)`: `rel` is the y offset and `to` the base anchor (analogous to `x`)
|
||||
/// - `(from: str, to: str)`: `from` is the base anchor and `to` is the id of the port to align with the anchor
|
||||
/// - w (number): Width of the element
|
||||
/// - h (number): Height of the element
|
||||
/// - name (none, str): Optional name of the block
|
||||
@@ -74,13 +76,12 @@
|
||||
if h == none { panic("Parameter h must be set") }
|
||||
|
||||
if (type(x) == dictionary) {
|
||||
let offset = x.rel
|
||||
let to = x.to
|
||||
let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0), to: to))
|
||||
x = to-pos.at(0)
|
||||
x = util.resolve-rel-coord(ctx, x, 0)
|
||||
}
|
||||
|
||||
if (type(y) == dictionary) {
|
||||
if (type(y) == dictionary and "rel" in y) {
|
||||
y = util.resolve-rel-coord(ctx, y, 1)
|
||||
} else if (type(y) == dictionary) {
|
||||
let from = y.from
|
||||
let to = y.to
|
||||
let (to-side, i) = find-port(ports, to)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#import "/src/cetz.typ": draw, coordinate
|
||||
#import "/src/util.typ"
|
||||
#import "../ports.typ": add-ports, add-port
|
||||
#import "../element.typ"
|
||||
|
||||
@@ -49,13 +50,12 @@
|
||||
if h == none { panic("Parameter h must be set") }
|
||||
|
||||
if (type(x) == dictionary) {
|
||||
let offset = x.rel
|
||||
let to = x.to
|
||||
let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0), to: to))
|
||||
x = to-pos.at(0)
|
||||
x = util.resolve-rel-coord(ctx, x, 0)
|
||||
}
|
||||
|
||||
if (type(y) == dictionary) {
|
||||
if (type(y) == dictionary and "rel" in y) {
|
||||
y = util.resolve-rel-coord(ctx, y, 1)
|
||||
} else if (type(y) == dictionary) {
|
||||
let from = y.from
|
||||
let to = y.to
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#import "/src/cetz.typ": draw, coordinate
|
||||
#import "/src/util.typ"
|
||||
#import "../ports.typ": add-ports, add-port
|
||||
#import "../element.typ"
|
||||
|
||||
@@ -60,13 +61,12 @@
|
||||
if h == none { panic("Parameter h must be set") }
|
||||
|
||||
if (type(x) == dictionary) {
|
||||
let offset = x.rel
|
||||
let to = x.to
|
||||
let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0), to: to))
|
||||
x = to-pos.at(0)
|
||||
x = util.resolve-rel-coord(ctx, x, 0)
|
||||
}
|
||||
|
||||
if (type(y) == dictionary) {
|
||||
if (type(y) == dictionary and "rel" in y) {
|
||||
y = util.resolve-rel-coord(ctx, y, 1)
|
||||
} else if (type(y) == dictionary) {
|
||||
let from = y.from
|
||||
let to = y.to
|
||||
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
#import "cetz.typ": coordinate
|
||||
|
||||
/// Resolves a relative coordinate shorthand of the form `(rel: <number>, to: <anchor>)`
|
||||
/// to a single scalar along the requested axis.
|
||||
///
|
||||
/// Used to implement the shared `(rel:, to:)` shorthand accepted by the `x` and
|
||||
/// `y` parameters of `elmt`, `gate` and `iec-gate`.
|
||||
///
|
||||
/// - ctx (dictionary): The current CeTZ context
|
||||
/// - val (dictionary): A dictionary with fields `rel` (number) and `to` (anchor)
|
||||
/// - axis (int): `0` for x, `1` for y
|
||||
/// -> number
|
||||
#let resolve-rel-coord(ctx, val, axis) = {
|
||||
let offset = val.rel
|
||||
let to = val.to
|
||||
let delta = if axis == 0 { (offset, 0) } else { (0, offset) }
|
||||
let (_, to-pos) = coordinate.resolve(ctx, (rel: delta, to: to))
|
||||
return to-pos.at(axis)
|
||||
}
|
||||
|
||||
/// Predefined color palette
|
||||
/// #let w = 4
|
||||
/// #box(width: 100%, align(center)[
|
||||
@@ -73,4 +93,45 @@
|
||||
#let valid-anchors = (
|
||||
"center", "north", "east", "west", "south",
|
||||
"north-east", "north-west", "south-east", "south-west"
|
||||
)
|
||||
)
|
||||
|
||||
/// Normalizes a coordinate so that 2D points (x, y) are padded
|
||||
/// to (x, y, 0) as required by CeTZ's coordinate resolver.
|
||||
/// Also handles function-based and dictionary-based coordinates
|
||||
/// recursively.
|
||||
///
|
||||
/// - coord (any): A CeTZ-compatible coordinate
|
||||
/// -> any
|
||||
#let normalize-coord(coord) = {
|
||||
if type(coord) == array {
|
||||
if coord.len() == 2 {
|
||||
let (a, b) = coord
|
||||
// Raw 2D point: (x, y) -> (x, y, 0)
|
||||
if type(a) in (int, float) and type(b) in (int, float) {
|
||||
return (a, b, 0)
|
||||
}
|
||||
// Function-based coordinate: (fn, point)
|
||||
if type(a) == function {
|
||||
let orig = a
|
||||
return (v => {
|
||||
let result = orig(v)
|
||||
if type(result) == array and result.len() == 2 {
|
||||
let (rx, ry) = result
|
||||
if type(rx) in (int, float) and type(ry) in (int, float) {
|
||||
return (rx, ry, 0)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
if type(coord) == dictionary {
|
||||
let result = (:)
|
||||
for (key, value) in coord {
|
||||
result.insert(key, normalize-coord(value))
|
||||
}
|
||||
return result
|
||||
}
|
||||
return coord
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
#import "/src/cetz.typ": draw, coordinate
|
||||
#import "util.typ": opposite-anchor
|
||||
#import "util.typ": opposite-anchor, normalize-coord
|
||||
|
||||
/// List of valid wire styles
|
||||
/// #examples.wires
|
||||
#let wire-styles = ("direct", "zigzag", "dodge", "guided")
|
||||
///
|
||||
/// The `"u-shape"` style connects two ports that face the same cardinal side.
|
||||
/// #examples.u-shape-wire
|
||||
#let wire-styles = ("direct", "zigzag", "dodge", "guided", "u-shape")
|
||||
#let signal-width = 1pt
|
||||
#let bus-width = 1.5pt
|
||||
|
||||
@@ -68,8 +71,8 @@
|
||||
|
||||
let (ctx, p0) = coordinate.resolve(ctx, start)
|
||||
let (ctx, p3) = coordinate.resolve(ctx, end)
|
||||
p0 = (x: p0.first(), y: p0.last())
|
||||
p3 = (x: p3.first(), y: p3.last())
|
||||
p0 = (x: p0.first(), y: p0.at(1))
|
||||
p3 = (x: p3.first(), y: p3.at(1))
|
||||
|
||||
let dx1 = margin-start
|
||||
let dx2 = margin-end
|
||||
@@ -86,13 +89,13 @@
|
||||
if side-end == "east" {
|
||||
dx2 *= -1
|
||||
}
|
||||
p1 = (p0.x + dx1, p0.y)
|
||||
p2 = (p3.x - dx2, p0.y)
|
||||
p1 = (p0.x + dx1, p0.y, 0)
|
||||
p2 = (p3.x - dx2, p0.y, 0)
|
||||
|
||||
let points = (
|
||||
start,
|
||||
(horizontal: p1, vertical: ()),
|
||||
(horizontal: (), vertical: (0, dodge-y)),
|
||||
(horizontal: (), vertical: (0, dodge-y, 0)),
|
||||
(horizontal: p2, vertical: ()),
|
||||
(horizontal: (), vertical: end),
|
||||
end
|
||||
@@ -109,6 +112,100 @@
|
||||
return (points, anchors)
|
||||
}
|
||||
|
||||
#let _u-valid-sides = ("east", "west", "north", "south")
|
||||
|
||||
// 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 _u-detect-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 u-side
|
||||
// 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-u-shape-wire(pts, u-depth, u-side, ctx) = {
|
||||
let start = pts.first()
|
||||
let end = pts.last()
|
||||
|
||||
// Resolve the (auto|explicit) side
|
||||
let side = u-side
|
||||
if side == auto {
|
||||
let side-start = _u-detect-side(start, ctx)
|
||||
let side-end = _u-detect-side(end, ctx)
|
||||
if side-start != none and side-end != none and side-start != side-end {
|
||||
panic(
|
||||
"u-shape: start port faces '" + side-start
|
||||
+ "' but end port faces '" + side-end
|
||||
+ "'; both must face the same side, or set u-side explicitly"
|
||||
)
|
||||
}
|
||||
if side-start != none { side = side-start }
|
||||
else if side-end != none { side = side-end }
|
||||
else {
|
||||
panic(
|
||||
"u-shape: could not auto-detect u-side (endpoints are not port anchors); "
|
||||
+ "please set u-side explicitly to one of " + repr(_u-valid-sides)
|
||||
)
|
||||
}
|
||||
}
|
||||
if not side in _u-valid-sides {
|
||||
panic("u-shape: invalid u-side '" + repr(side) + "'; must be one of " + repr(_u-valid-sides))
|
||||
}
|
||||
|
||||
let (ctx, s) = coordinate.resolve(ctx, start)
|
||||
let (ctx, e) = coordinate.resolve(ctx, end)
|
||||
let (sx, sy, ..) = s
|
||||
let (ex, ey, ..) = e
|
||||
|
||||
let p1
|
||||
let p2
|
||||
if side == "east" {
|
||||
let bx = calc.max(sx, ex) + u-depth
|
||||
p1 = (bx, sy, 0)
|
||||
p2 = (bx, ey, 0)
|
||||
} else if side == "west" {
|
||||
let bx = calc.min(sx, ex) - u-depth
|
||||
p1 = (bx, sy, 0)
|
||||
p2 = (bx, ey, 0)
|
||||
} else if side == "north" {
|
||||
let by = calc.max(sy, ey) + u-depth
|
||||
p1 = (sx, by, 0)
|
||||
p2 = (ex, by, 0)
|
||||
} else if side == "south" {
|
||||
let by = calc.min(sy, ey) - u-depth
|
||||
p1 = (sx, by, 0)
|
||||
p2 = (ex, by, 0)
|
||||
}
|
||||
|
||||
let points = (start, p1, p2, end)
|
||||
let anchors = (
|
||||
"start": start,
|
||||
"u-start": p1,
|
||||
"u-end": p2,
|
||||
"end": end
|
||||
)
|
||||
return (points, anchors)
|
||||
}
|
||||
|
||||
#let get-guided-wire(pts, margins, sides, center-guides, ctx) = {
|
||||
let start = pts.first()
|
||||
let end = pts.last()
|
||||
@@ -147,18 +244,18 @@
|
||||
|
||||
|
||||
// points that are closest to the edge points
|
||||
let p1 = (p0.x + dx1, p0.y + dy1)
|
||||
let p5 = (p6.x + dx2, p6.y + dy2)
|
||||
let p1 = (p0.x + dx1, p0.y + dy1, 0)
|
||||
let p5 = (p6.x + dx2, p6.y + dy2, 0)
|
||||
|
||||
|
||||
// middle point
|
||||
let center_x = p0.x + box_width * center_horizontal / 100%
|
||||
let center_y = p0.y + box_height * center_vertical / 100%
|
||||
let p3 = (center_x, center_y)
|
||||
let p3 = (center_x, center_y, 0)
|
||||
|
||||
// setting up the points for that touch the guides
|
||||
let p2 = (0,0)
|
||||
let p4 = (0,0)
|
||||
let p2 = (0, 0, 0)
|
||||
let p4 = (0, 0, 0)
|
||||
if side-start in ("north", "south") {
|
||||
p2 = (horizontal: p3, vertical: p1)
|
||||
} else {
|
||||
@@ -212,6 +309,8 @@
|
||||
/// - guided-center (array): the horizontal and vertical guides of the center guides (only with style "guided")
|
||||
/// - guided-margins (array): the start and end of guided margins of the wire (only with style "guided")
|
||||
/// - guided-sides (array): the side of start and end array (must be either "north", "south", "west", "east") (only work with style "guided")
|
||||
/// - u-side (auto, str): The cardinal side both endpoints face (one of "east", "west", "north", "south"). 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. Auto-detection panics if the two endpoints resolve to different sides, or if neither endpoint is a port anchor (only with style "u-shape")
|
||||
/// - u-depth (number): Distance between the outermost endpoint (in the `u-side` direction) and the U-bend line (only with style "u-shape")
|
||||
#let wire(
|
||||
id, pts,
|
||||
bus: false,
|
||||
@@ -231,7 +330,9 @@
|
||||
zigzag-dir: "vertical",
|
||||
dodge-y: 0,
|
||||
dodge-sides: ("east", "west"),
|
||||
dodge-margins: (5%, 5%)
|
||||
dodge-margins: (5%, 5%),
|
||||
u-side: auto,
|
||||
u-depth: 0.5,
|
||||
) = draw.get-ctx(ctx => {
|
||||
if not style in wire-styles {
|
||||
panic("Invalid wire style '" + style + "'")
|
||||
@@ -240,6 +341,9 @@
|
||||
if pts.len() != 2 {
|
||||
panic("Wrong number of points (got " + str(pts.len()) + " instead of 2)")
|
||||
}
|
||||
|
||||
// Normalize user-provided coordinates: (x, y) -> (x, y, 0)
|
||||
let pts = pts.map(normalize-coord)
|
||||
|
||||
let stroke = (
|
||||
paint: color,
|
||||
@@ -274,6 +378,13 @@
|
||||
guided-center,
|
||||
ctx
|
||||
)
|
||||
} else if style == "u-shape" {
|
||||
(points, anchors) = get-u-shape-wire(
|
||||
pts,
|
||||
u-depth,
|
||||
u-side,
|
||||
ctx
|
||||
)
|
||||
}
|
||||
|
||||
let mark = (fill: color)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "circuiteria"
|
||||
version = "0.2.1"
|
||||
compiler = "0.13.1"
|
||||
compiler = "0.15.0"
|
||||
repository = "https://git.kb28.ch/HEL/circuiteria"
|
||||
entrypoint = "src/lib.typ"
|
||||
authors = [
|
||||
|
||||