forked from HEL/circuiteria
added logic gates
This commit is contained in:
127
src/elements/logic/gate.typ
Normal file
127
src/elements/logic/gate.typ
Normal file
@ -0,0 +1,127 @@
|
||||
#import "@preview/cetz:0.2.2": draw, coordinate
|
||||
#import "../ports.typ": add-ports, add-port
|
||||
#import "../element.typ"
|
||||
|
||||
#let default-draw-shape(id, tl, tr, br, bl, fill, stroke) = {
|
||||
let f = {draw.rect(tl, br, fill: fill, stroke: stroke)}
|
||||
return (f, tl, tr, br, bl)
|
||||
}
|
||||
|
||||
#let gate(
|
||||
draw-shape: default-draw-shape,
|
||||
x: none,
|
||||
y: none,
|
||||
w: none,
|
||||
h: none,
|
||||
inputs: 2,
|
||||
fill: none,
|
||||
stroke: black + 1pt,
|
||||
id: "",
|
||||
inverted: (),
|
||||
debug: (
|
||||
ports: false
|
||||
)
|
||||
) = draw.get-ctx(ctx => {
|
||||
let width = w
|
||||
let height = h
|
||||
|
||||
let x = x
|
||||
let y = y
|
||||
if x == none { panic("Parameter x must be set") }
|
||||
if y == none { panic("Parameter y must be set") }
|
||||
if w == none { panic("Parameter w must be set") }
|
||||
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)
|
||||
}
|
||||
|
||||
if (type(y) == dictionary) {
|
||||
let from = y.from
|
||||
let to = y.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 used-pct = 100% - margins.at(0) - margins.at(1)
|
||||
let used-height = height * used-pct / 100%
|
||||
let top-margin = height * margins.at(0) / 100%
|
||||
|
||||
let dy = used-height * (i + 1) / (ports.at(to-side).len() + 1)
|
||||
|
||||
let (ctx, from-pos) = coordinate.resolve(ctx, from)
|
||||
y = from-pos.at(1) + dy - height + top-margin
|
||||
}
|
||||
|
||||
let tl = (x, y + height)
|
||||
let tr = (x + width, y + height)
|
||||
let br = (x + width, y)
|
||||
let bl = (x, y)
|
||||
|
||||
// Workaround because CeTZ needs to have all draw functions in the body
|
||||
let func = {}
|
||||
(func, tl, tr, br, bl) = draw-shape(id, tl, tr, br, bl, fill, stroke)
|
||||
{
|
||||
//draw.rect(tl, br)
|
||||
func
|
||||
}
|
||||
|
||||
let space = 100% / (inputs + 1)
|
||||
for i in range(inputs) {
|
||||
let pct = (i + 1) * space
|
||||
let a = (tl, pct, bl)
|
||||
let b = (tr, pct, br)
|
||||
let int-name = id + "i" + str(i)
|
||||
draw.intersections(
|
||||
int-name,
|
||||
func,
|
||||
draw.hide(draw.line(a, b))
|
||||
)
|
||||
let port-name = "in" + str(i)
|
||||
let port-pos = int-name + ".0"
|
||||
if inverted == "all" or port-name in inverted {
|
||||
draw.circle(port-pos, radius: .2, anchor: "east", stroke: stroke)
|
||||
port-pos = (rel: (-.4, 0), to: port-pos)
|
||||
}
|
||||
add-port(
|
||||
id, "west",
|
||||
(id: port-name), port-pos,
|
||||
debug: debug.ports
|
||||
)
|
||||
}
|
||||
|
||||
let out-pos = id + ".east"
|
||||
if inverted == "all" or "out" in inverted {
|
||||
draw.circle(out-pos, radius: .2, anchor: "west", stroke: stroke)
|
||||
out-pos = (rel: (.4, 0), to: out-pos)
|
||||
}
|
||||
add-port(
|
||||
id, "east",
|
||||
(id: "out"), out-pos,
|
||||
debug: debug.ports
|
||||
)
|
||||
})
|
||||
/* {
|
||||
let ports = (west: (), east: ((id: "out"),))
|
||||
for i in range(inputs) {
|
||||
ports.west.push((id: "in"+str(i)))
|
||||
}
|
||||
|
||||
element.elmt(
|
||||
draw-shape: draw-shape,
|
||||
x: x,
|
||||
y: y,
|
||||
w: w,
|
||||
h: h,
|
||||
ports: ports,
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
id: id,
|
||||
auto-ports: true,
|
||||
debug: debug
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user