diff --git a/src/lib/angle.typ b/src/lib/angle.typ index 7657f287..f1389c97 100644 --- a/src/lib/angle.typ +++ b/src/lib/angle.typ @@ -15,7 +15,7 @@ mark: auto, ) -/// Draw an angle between `a` and `b` through origin `origin` +/// Draw an angle counter-clock-wise between `a` and `b` through origin `origin` /// /// ```typc example /// line((0,0), (1,1.5), name: "a") @@ -25,13 +25,13 @@ /// cetz.angle.angle("a.start", "a.end", "b.end", label: $ alpha $, /// mark: (end: ">"), radius: 1.5) /// cetz.angle.angle("a.start", "b.end", "a.end", label: $ alpha' $, -/// radius: 50%, inner: false) +/// radius: 50%, direction: "cw") /// ``` /// /// - origin (coordinate): Angle origin /// - a (coordinate): Coordinate of side `a`, containing an angle between `origin` and `b`. /// - b (coordinate): Coordinate of side `b`, containing an angle between `origin` and `a`. -/// - inner (bool): Draw the smaller (inner) angle if true, otherwise the outer angle gets drawn. +/// - direction (string): Direction of the angle. Accepts "cw" (clockwise) and "ccw" (counter-clockwise), the latter being the default. /// - 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. The function must be of the format `angle => content`. /// - name (none,str): Element name, used for querying anchors. /// - ..style (style): Style key-value pairs. @@ -53,7 +53,7 @@ origin, a, b, - inner: true, + direction: "ccw", label: none, name: none, ..style @@ -65,32 +65,31 @@ 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") - let (s, e, ss) = { + assert(direction in ("cw", "ccw"), + message: "Invalid angle direction " + repr(direction)) + + let (start, delta, ccw) = { + let ccw = direction == "ccw" + let s = vector.angle2(origin, a) if s < 0deg { s += 360deg } + let e = vector.angle2(origin, b) if e < 0deg { e += 360deg } - if s > e { - (s, e) = (e, s) + if e < s { + e += 360deg } - 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 ccw { + (s, (e - s), ccw) + } else { + (s, -(360deg - (e - s)), ccw) } - (s, e, (s + e) / 2) } + let mid = start + delta / 2 + // Radius can be relative to the min-distance between origin-a and origin-b if type(style.radius) == ratio { style.radius = style.radius * calc.min(vector.dist(origin, a), vector.dist(origin, b)) / 100% @@ -103,9 +102,9 @@ } let (ra, _) = util.resolve-radius(style.label-radius).map(util.resolve-number.with(ctx)) - 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)) + let label-pt = vector.add(origin, (calc.cos(mid) * ra, calc.sin(mid) * ra, 0)) + let start-pt = vector.add(origin, (calc.cos(start) * r, calc.sin(start) * r, 0)) + let end-pt = vector.add(origin, (calc.cos(start + delta) * r, calc.sin(start + delta) * r, 0)) draw.anchor("origin", origin) draw.anchor("label", label-pt) draw.anchor("start", start-pt) @@ -113,18 +112,18 @@ draw.anchor("a", a) draw.anchor("b", b) - if s != e { + if delta != 0deg { if style.fill != none { - draw.arc(origin, start: s, stop: e, anchor: "origin", + draw.arc(origin, start: start, delta: delta, anchor: "origin", name: "arc", ..style, radius: r, mode: "PIE", mark: none, stroke: none) } if style.stroke != none { - draw.arc(origin, start: s, stop: e, anchor: "origin", + draw.arc(origin, start: start, delta: delta, anchor: "origin", name: "arc", ..style, radius: r, fill: none) } } - let label = if type(label) == function { label(e - s) } else { label } + let label = if type(label) == function { label(calc.abs(delta)) } else { label } if label != none { draw.content(label-pt, label) } diff --git a/tests/angle/ref/1.png b/tests/angle/ref/1.png index 1c3992bf..297d8424 100644 Binary files a/tests/angle/ref/1.png and b/tests/angle/ref/1.png differ diff --git a/tests/angle/test.typ b/tests/angle/test.typ index 37a2b48a..a26d1962 100644 --- a/tests/angle/test.typ +++ b/tests/angle/test.typ @@ -1,7 +1,8 @@ #set page(width: auto, height: auto) #import "/src/lib.typ": * +#import "/tests/helper.typ": * -#box(stroke: 2pt + red, canvas(length: 1cm, { +#test-case({ import draw: * import angle: angle @@ -11,12 +12,12 @@ group({ let (o, a, b) = ((0,0), (1,0), (calc.cos(a), calc.sin(a))) line(a, o, b) - angle(o, a, b, label: $alpha$, inner: true) + angle(o, a, b, label: $alpha$) }) } })) -#box(stroke: 2pt + red, canvas(length: 1cm, { +#test-case({ import draw: * import angle: angle @@ -26,12 +27,12 @@ group({ let (o, a, b) = ((0,0), (1,0), (calc.cos(a), calc.sin(a))) line(a, o, b) - angle(o, a, b, label: $alpha$, inner: false) + angle(o, a, b, label: $alpha$, direction: "cw") }) } })) -#box(stroke: 2pt + red, canvas(length: 1cm, { +#test-case({ import draw: * import angle: angle @@ -41,12 +42,12 @@ group({ let (o, a, b) = ((0,0), (calc.cos(a+90deg), calc.sin(a+90deg)), (calc.cos(a), calc.sin(a))) line(a, o, b) - angle(o, b, a, label: $alpha$, inner: true) + angle(o, b, a, label: $alpha$) }) } })) -#box(stroke: 2pt + red, canvas(length: 1cm, { +#test-case({ import draw: * import angle: angle @@ -56,12 +57,12 @@ group({ let (o, a, b) = ((0,0), (calc.cos(a+90deg), calc.sin(a+90deg)), (calc.cos(a), calc.sin(a))) line(a, o, b) - angle(o, b, a, label: $alpha$, inner: false) + angle(o, b, a, label: $alpha$, direction: "cw") }) } })) -#box(stroke: 2pt + red, canvas(length: 1cm, { +#test-case({ import draw: * import angle: angle @@ -69,16 +70,15 @@ line(a, b, c) set-style(angle: (stroke: red, label-radius: 1)) - angle(b, a, c, mark: (start: ">", end: ">"), - inner: true, label: $omega$) + angle(b, c, a, mark: (start: ">", end: ">"), label: $omega$) translate((2,0,0)) line(a, b, c) set-style(stroke: blue) set-style(angle: (stroke: auto, radius: 1, label-radius: .5)) - angle(b, c, a, mark: (start: ">", end: ">"), - inner: false, label: $alpha$, name: "alpha") + angle(b, c, a, mark: (start: "|", end: ">"), + direction: "cw", label: $alpha$, name: "alpha") set-style(stroke: black) circle("alpha.origin", radius: .15) @@ -86,3 +86,17 @@ circle("alpha.start", radius: .25) circle("alpha.end", radius: .25) })) + +#test-case({ + import draw: * + import angle: * + + angle((0,0), (1,0), (0,1), mark: (end: ">")) +}) + +#test-case({ + import draw: * + import angle: * + + angle((0,0), (1,0), (0,1), mark: (end: ">"), direction: "cw") +})