Skip to content

Commit

Permalink
angle: Update angle library
Browse files Browse the repository at this point in the history
  • Loading branch information
johannes-wolf committed Nov 12, 2023
1 parent 1dfca18 commit 2398740
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 97 deletions.
171 changes: 74 additions & 97 deletions src/lib/angle.typ
Original file line number Diff line number Diff line change
Expand Up @@ -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 = (
Expand All @@ -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,
Expand All @@ -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)
}
})
Binary file modified tests/angle/ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2398740

Please sign in to comment.