From 23987405c64196b271157a2a04761bdfb02c74a3 Mon Sep 17 00:00:00 2001 From: johannes-wolf Date: Sun, 12 Nov 2023 05:22:56 +0100 Subject: [PATCH] angle: Update angle library --- src/lib/angle.typ | 171 +++++++++++++++++++------------------------- tests/angle/ref.png | Bin 178994 -> 178994 bytes 2 files changed, 74 insertions(+), 97 deletions(-) diff --git a/src/lib/angle.typ b/src/lib/angle.typ index c36a99f8..ea10f56f 100644 --- a/src/lib/angle.typ +++ b/src/lib/angle.typ @@ -4,6 +4,7 @@ #import "../util.typ" #import "../coordinate.typ" #import "../anchor.typ" as anchor_ +#import "/src/draw.typ" // Angle default-style #let default-style = ( @@ -14,6 +15,29 @@ mark: styles.default.mark, ) +/// Draw an angle between `a` and `b` through origin `origin` +/// +/// *Style Root:* `angle` +/// +/// *Anchors* +/// / `"a"`: Point a +/// / `"b"`: Point b +/// / `"origin"`: Origin +/// / `"label"`: Label center +/// / `"start"`: Arc start +/// / `"end"`: Arc end +/// +/// You can use the `radius` and `label-radius` style-keys to set +/// the angle and label radius. +/// +/// - origin (coordinate): Angle origin +/// - a (coordinate): Coordinate of side a +/// - b (coordinate): Coordinate of side b +/// - inner (bool): Draw the smaller (inner) angle +/// - label (none,content,function): Draw a label at the angles "label" anchor. +/// If label is a function, it gets the angle value passed as argument. +/// - name: (none,string): Element value +/// - ..style (style): Style #let angle( origin, a, @@ -22,112 +46,65 @@ label: none, name: none, ..style -) = { - let style = style.named() +) = draw.group(name: name, ctx => { + let style = styles.resolve(ctx.style, style.named(), base: default-style, root: "angle") + let (ctx, origin, a, b) = coordinate.resolve(ctx, origin, a, b) - return (ctx => { - let style = styles.resolve(ctx.style, style, root: "angle", base: default-style) - let (ctx, origin, a, b) = coordinate.resolve(ctx, origin, a, b) - assert( - origin.at(2, default: 0) == 0 and - a.at(2, default: 0) == 0 and - b.at(2, default: 0) == 0, - message: "FIXME: Angle only works for 2D coordinates." - ) - let (s, e, ss) = { - let s = vector.angle2(origin, a) * -1 - if s < 0deg { s += 360deg } - let e = vector.angle2(origin, b) * -1 - if e < 0deg { e += 360deg } + assert(origin.at(2) == a.at(2) and a.at(2) == b.at(2), + message: "Angle z coordinates of all three points must be equal") - if s > e { - (s, e) = (e, s) - } + let (s, e, ss) = { + let s = vector.angle2(origin, a) * -1 + if s < 0deg { s += 360deg } + let e = vector.angle2(origin, b) * -1 + if e < 0deg { e += 360deg } + + if s > e { + (s, e) = (e, s) + } - if inner == true { - let d = vector.angle(a, origin, b) - if e - s > 180deg { - (s, e) = (e, e + d) - } else { - (s, e) = (s, s + d) - } - } else if inner == false { - if e - s < 180deg { - let d = 360deg - vector.angle(a, origin, b) - (s, e) = (e, e + d) - } + if inner == true { + let d = vector.angle(a, origin, b) + if e - s > 180deg { + (s, e) = (e, e + d) + } else { + (s, e) = (s, s + d) + } + } else if inner == false { + if e - s < 180deg { + let d = 360deg - vector.angle(a, origin, b) + (s, e) = (e, e + d) } - (s, e, (s + e) / 2) } - let (x, y, z) = origin - let (r, _) = util.resolve-radius(style.radius).map(util.resolve-number.with(ctx)) - let (ra, _) = util.resolve-radius(style.label-radius).map(util.resolve-number.with(ctx)) - let start = (x + r * calc.cos(s), y + r * calc.sin(s), z) - let end = (x + r * calc.cos(e), y + r * calc.sin(e), z) - let pt-label = (x + ra * calc.cos(ss), y + ra * calc.sin(ss), z) + (s, e, (s + e) / 2) + } - let drawables = () + let (r, _) = util.resolve-radius(style.radius).map(util.resolve-number.with(ctx)) + let (ra, _) = util.resolve-radius(style.label-radius).map(util.resolve-number.with(ctx)) - let (marks, draw-pt, draw-s, draw-e) = if style.mark != none { - import "/src/mark.typ" as mark_ - mark_.place-marks-along-arc(ctx, s, e, start, r, r, style, style.mark) - } else { - (none, start, s, e) - } + let label-pt = vector.add(origin, (calc.cos(ss) * ra, calc.sin(ss) * ra, 0)) + let start-pt = vector.add(origin, (calc.cos(s) * r, calc.sin(s) * r, 0)) + let end-pt = vector.add(origin, (calc.cos(e) * r, calc.sin(e) * r, 0)) + draw.anchor("origin", origin) + draw.anchor("label", label-pt) + draw.anchor("start", start-pt) + draw.anchor("end", end-pt) + draw.anchor("a", a) + draw.anchor("b", b) + + if s != e { if style.fill != none { - drawables.push( - drawable.arc(..draw-pt, draw-s, draw-e, r, r, mode: "PIE", fill: style.fill, stroke: none) - ) + draw.arc(origin, start: s, stop: e, anchor: "origin", + name: "arc", ..style, radius: r, mode: "PIE", mark: none, stroke: none) } if style.stroke != none { - drawables.push( - drawable.arc(..draw-pt, draw-s, draw-e, r, r, mode: "OPEN", fill: none, stroke: style.stroke) - ) - } - if marks != none { - drawables += marks + draw.arc(origin, start: s, stop: e, anchor: "origin", + name: "arc", ..style, radius: r, fill: none) } + } - let (x, y, z) = start - let label = if type(label) == function { label(e - s) } else { label } - if label != none { - let (lx, ly, ..) = pt-label - let (w, h) = util.measure(ctx, label) - drawables.push( - drawable.content( - (lx, ly, 0), - w, - h, - label - ) - ) - } - - let (transform, anchors) = anchor_.setup( - anchor => { - ( - origin: origin, - a: a, - b: b, - start: start, - end: end, - label: pt-label - ).at(anchor) - }, - ("origin", "a", "b", "start", "end", "label"), - transform: ctx.transform, - name: name, - default: "label" - ) - - return ( - ctx: ctx, - name: name, - anchors: anchors, - drawables: drawable.apply-transform( - transform, - drawables - ) - ) - },) -} + let label = if type(label) == function { label(e - s) } else { label } + if label != none { + draw.content(label-pt, label) + } +}) diff --git a/tests/angle/ref.png b/tests/angle/ref.png index 31522bd594f2a934994c749b8d76c6e4c810c470..87cb25235cf56869ec40b7e47ac2353760f761aa 100644 GIT binary patch delta 128 zcmV-`0Du3o_6oB03b4f835R^hhw$fr{^zsJ-9Q2fyT0qY@`FG4gR>Uk2?7ai-}Y^J z>6d$m0|-r*gyJmee#2?u`Q2l8#- i_HBb<=C@(y0lw4|-x}-|@p!ZV0000