forked from HEL/circuiteria
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13e3fee913 |
No files matched your search
@@ -186,6 +186,45 @@ wire.wire("w2", ("b2-port-out", "b3-port-in2"),
|
||||
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(```
|
||||
wire.wire("w1", ((0, 0), (1, 1)), style: "zigzag")
|
||||
wire.wire("w2", ((0, 0), (1, -.5)),
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
@@ -0,0 +1,84 @@
|
||||
// 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")
|
||||
})
|
||||
@@ -1,30 +0,0 @@
|
||||
// Demonstrates the `(from: <anchor>, to: <port-id>)` port-alignment shorthand
|
||||
// for the `x` parameter (analogous to the existing shorthand for `y`).
|
||||
#import "/src/lib.typ": circuit, element, util, wire
|
||||
|
||||
#set page(width: auto, height: auto, margin: .5cm)
|
||||
|
||||
#circuit({
|
||||
// Anchor block: absolute placement, with a single "addr" port on its
|
||||
// north side (auto-centred horizontally by circuiteria).
|
||||
element.block(
|
||||
x: 0, y: 0, w: 2, h: 1.5,
|
||||
id: "vcemem",
|
||||
fill: util.colors.orange,
|
||||
ports: (north: ((id: "addr"),), east: ((id: "out"),))
|
||||
)
|
||||
|
||||
// This block's "addr" port (south side) is x-aligned with vcemem's "addr"
|
||||
// port (north side), even though B is wider than vcemem and not
|
||||
// horizontally aligned by default.
|
||||
element.block(
|
||||
x: (from: "vcemem-port-addr", to: "addr"),
|
||||
y: (rel: 2, to: "vcemem.north"),
|
||||
w: 4.5, h: 1,
|
||||
id: "fsm",
|
||||
fill: util.colors.yellow,
|
||||
ports: (south: ((id: "addr"),), east: ((id: "out"),))
|
||||
)
|
||||
|
||||
wire.wire("wAddr", ("vcemem-port-addr", "fsm-port-addr"), style: "zigzag")
|
||||
})
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.1 KiB |
@@ -1,46 +0,0 @@
|
||||
// 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")
|
||||
})
|
||||
+6919
-6989
File diff suppressed because it is too large.
Load diff
@@ -21,14 +21,10 @@
|
||||
/// - draw-shape (function): Draw function
|
||||
/// - x (number, dictionary): The x position (bottom-left corner).
|
||||
///
|
||||
/// If it is a dictionary, it can take one of two forms:
|
||||
/// - `(rel: number, to: str)`: `rel` is the x offset and `to` the base anchor
|
||||
/// - `(from: str, to: str)`: `from` is the base anchor and `to` is the id of the port to align with the anchor (analogous to `y`)
|
||||
/// 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 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
|
||||
/// 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
|
||||
/// - w (number): Width of the element
|
||||
/// - h (number): Height of the element
|
||||
/// - name (none, str): Optional name of the block
|
||||
@@ -43,7 +39,6 @@
|
||||
/// - stroke (stroke): Border stroke
|
||||
/// - id (str): The block id (for future reference)
|
||||
/// - auto-ports (bool): Whether to use auto port placements or not. If false, `draw-shape` is responsible for adding the appropiate ports
|
||||
/// - ports-x (dictionary): Dictionary of the ports x offsets (used with `auto-ports: false`)
|
||||
/// - ports-y (dictionary): Dictionary of the ports y offsets (used with `auto-ports: false`)
|
||||
/// - debug (dictionary): Dictionary of debug options.
|
||||
///
|
||||
@@ -63,7 +58,6 @@
|
||||
stroke: black + 1pt,
|
||||
id: "",
|
||||
auto-ports: true,
|
||||
ports-x: (:),
|
||||
ports-y: (:),
|
||||
debug: (
|
||||
ports: false
|
||||
@@ -79,45 +73,14 @@
|
||||
if w == none { panic("Parameter w must be set") }
|
||||
if h == none { panic("Parameter h must be set") }
|
||||
|
||||
if (type(x) == dictionary and "rel" in x) {
|
||||
x = util.resolve-rel-coord(ctx, x, 0)
|
||||
} else if (type(x) == dictionary) {
|
||||
let from = x.from
|
||||
if (type(x) == dictionary) {
|
||||
let offset = x.rel
|
||||
let to = x.to
|
||||
let (to-side, i) = find-port(ports, to)
|
||||
let margins = (0%, 0%)
|
||||
if to-side in ports-margins {
|
||||
margins = ports-margins.at(to-side)
|
||||
}
|
||||
|
||||
let dx
|
||||
let left-margin
|
||||
if to-side in ("north", "south") {
|
||||
let used-pct = 100% - margins.at(0) - margins.at(1)
|
||||
let used-width = width * used-pct / 100%
|
||||
left-margin = width * margins.at(0) / 100%
|
||||
|
||||
dx = used-width * (i + 1) / (ports.at(to-side).len() + 1)
|
||||
|
||||
if not auto-ports {
|
||||
left-margin = 0
|
||||
dx = ports-x.at(to)(width)
|
||||
}
|
||||
} else if to-side == "west" {
|
||||
dx = 0
|
||||
left-margin = 0
|
||||
} else if to-side == "east" {
|
||||
dx = width
|
||||
left-margin = 0
|
||||
}
|
||||
|
||||
let (ctx, from-pos) = coordinate.resolve(ctx, from)
|
||||
x = from-pos.at(0) + dx - width + left-margin
|
||||
let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0), to: to))
|
||||
x = to-pos.at(0)
|
||||
}
|
||||
|
||||
if (type(y) == dictionary and "rel" in y) {
|
||||
y = util.resolve-rel-coord(ctx, y, 1)
|
||||
} else if (type(y) == dictionary) {
|
||||
if (type(y) == dictionary) {
|
||||
let from = y.from
|
||||
let to = y.to
|
||||
let (to-side, i) = find-port(ports, to)
|
||||
|
||||
+30
-1
@@ -1,9 +1,15 @@
|
||||
#import "/src/cetz.typ": draw, coordinate
|
||||
#import "../util.typ"
|
||||
#import "ports.typ": add-ports
|
||||
|
||||
/// Draws a group of elements
|
||||
///
|
||||
/// #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
|
||||
/// - id (str): see #doc-ref("element.elmt")
|
||||
/// - name (str): The group's name
|
||||
@@ -16,6 +22,10 @@
|
||||
/// - array: either (`<all>`,), (`<vertical>`, `<horizontal>`) or (`<top>`, `<right>`, `<bottom>`, `<left>`)
|
||||
/// - dictionary: valid keys are "top", "right", "bottom" and "left"
|
||||
/// - 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(
|
||||
body,
|
||||
id: "",
|
||||
@@ -24,7 +34,13 @@
|
||||
fill: none,
|
||||
stroke: black + 1pt,
|
||||
padding: 0.5em,
|
||||
radius: 0.5em
|
||||
radius: 0.5em,
|
||||
ports: (:),
|
||||
ports-margins: (:),
|
||||
outside-port-names: true,
|
||||
debug: (
|
||||
ports: false
|
||||
)
|
||||
) = {
|
||||
let min-x = none
|
||||
let max-x = none
|
||||
@@ -68,6 +84,19 @@
|
||||
stroke: stroke,
|
||||
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 {
|
||||
draw.content(
|
||||
id + "." + name-anchor,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#import "/src/cetz.typ": draw, coordinate
|
||||
#import "/src/util.typ"
|
||||
#import "../ports.typ": add-ports, add-port
|
||||
#import "../element.typ"
|
||||
|
||||
@@ -50,12 +49,13 @@
|
||||
if h == none { panic("Parameter h must be set") }
|
||||
|
||||
if (type(x) == dictionary) {
|
||||
x = util.resolve-rel-coord(ctx, x, 0)
|
||||
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)
|
||||
}
|
||||
|
||||
if (type(y) == dictionary and "rel" in y) {
|
||||
y = util.resolve-rel-coord(ctx, y, 1)
|
||||
} else if (type(y) == dictionary) {
|
||||
if (type(y) == dictionary) {
|
||||
let from = y.from
|
||||
let to = y.to
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#import "/src/cetz.typ": draw, coordinate
|
||||
#import "/src/util.typ"
|
||||
#import "../ports.typ": add-ports, add-port
|
||||
#import "../element.typ"
|
||||
|
||||
@@ -61,12 +60,13 @@
|
||||
if h == none { panic("Parameter h must be set") }
|
||||
|
||||
if (type(x) == dictionary) {
|
||||
x = util.resolve-rel-coord(ctx, x, 0)
|
||||
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)
|
||||
}
|
||||
|
||||
if (type(y) == dictionary and "rel" in y) {
|
||||
y = util.resolve-rel-coord(ctx, y, 1)
|
||||
} else if (type(y) == dictionary) {
|
||||
if (type(y) == dictionary) {
|
||||
let from = y.from
|
||||
let to = y.to
|
||||
|
||||
|
||||
+20
-5
@@ -1,11 +1,12 @@
|
||||
#import "/src/cetz.typ": draw
|
||||
#import "../util.typ": rotate-anchor
|
||||
#import "../util.typ": rotate-anchor, opposite-anchor
|
||||
|
||||
#let add-port(
|
||||
elmt-id, side, port, pos,
|
||||
prev: none,
|
||||
next: none,
|
||||
debug: false
|
||||
debug: false,
|
||||
outside-name: false,
|
||||
) = {
|
||||
let name = port.at("name", default: "")
|
||||
let name-rotate = port.at("vertical", default: false)
|
||||
@@ -27,9 +28,21 @@
|
||||
// TODO: use context or vectors to have the height relative to the width
|
||||
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(
|
||||
pos,
|
||||
anchor: if name-rotate {rotate-anchor(side)} else {side},
|
||||
anchor: name-anchor,
|
||||
padding: 2pt,
|
||||
angle: if name-rotate {90deg} else {0deg},
|
||||
name
|
||||
@@ -60,7 +73,8 @@
|
||||
tl, tr, br, bl,
|
||||
ports,
|
||||
ports-margins,
|
||||
debug: false
|
||||
debug: false,
|
||||
outside-name: false,
|
||||
) = {
|
||||
let sides = (
|
||||
"north": (tl, tr),
|
||||
@@ -109,7 +123,8 @@
|
||||
pos,
|
||||
prev: pos-prev,
|
||||
next: pos-next,
|
||||
debug: debug
|
||||
debug: debug,
|
||||
outside-name: outside-name,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
#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)[
|
||||
|
||||
Reference in new issue
Block a user