Skip to content

Commit

Permalink
arc: Add mark support
Browse files Browse the repository at this point in the history
  • Loading branch information
johannes-wolf committed Nov 5, 2023
1 parent 3506fa9 commit db3e4e9
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 53 deletions.
24 changes: 15 additions & 9 deletions src/draw/shapes.typ
Original file line number Diff line number Diff line change
Expand Up @@ -180,27 +180,33 @@
let style = styles.resolve(ctx.style, style, root: "arc")
assert(style.mode in ("OPEN", "PIE", "CLOSE"))

let (marks, start-angle, stop-angle) = if style.mark != none {
mark_.place-marks-along-arc(ctx, start-angle, stop-angle, style, style.mark)
let (ctx, arc-start) = coordinate.resolve(ctx, position)
let (rx, ry) = util.resolve-radius(style.radius).map(util.resolve-number.with(ctx))

// Calculate marks and optimized angles
let (marks, draw-arc-start, draw-start-angle, draw-stop-angle) = if style.mark != none {
mark_.place-marks-along-arc(ctx, start-angle, stop-angle,
arc-start, rx, ry, style, style.mark)
} else {
(none, start-angle, stop-angle)
(none, arc-start, start-angle, stop-angle)
}

let (ctx, arc-start) = coordinate.resolve(ctx, position)
let (x, y, z) = arc-start
let (rx, ry) = util.resolve-radius(style.radius).map(util.resolve-number.with(ctx))

let path = (drawable.arc(
x, y, z,
start-angle,
stop-angle,
..draw-arc-start,
draw-start-angle,
draw-stop-angle,
rx,
ry,
stroke: style.stroke,
fill: style.fill,
mode: style.mode,
),)

if marks != none {
path += marks
}

let sector-center = (
x - rx * calc.cos(start-angle),
y - ry * calc.sin(start-angle),
Expand Down
46 changes: 11 additions & 35 deletions src/lib/angle.typ
Original file line number Diff line number Diff line change
Expand Up @@ -68,51 +68,27 @@

let drawables = ()

let (x, y, z) = start
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)
}
if style.fill != none {
drawables.push(
drawable.arc(x, y, z, s, e, r, r, mode: "PIE", fill: style.fill, stroke: none)
drawable.arc(..draw-pt, draw-s, draw-e, r, r, mode: "PIE", fill: style.fill, stroke: none)
)
}
if style.stroke != none {
drawables.push(
drawable.arc(x, y, z, s, e, r, r, mode: "OPEN", fill: none, stroke: style.stroke)
drawable.arc(..draw-pt, draw-s, draw-e, r, r, mode: "OPEN", fill: none, stroke: style.stroke)
)
}

if style.mark.start != none {
let f = vector.add(
vector.scale(
(
calc.cos(s + 90deg),
calc.sin(s + 90deg),
0
),
style.mark.length
),
start
)
drawables.push(
drawable.mark(f, start, style.mark.start, style.mark)
)
}
if style.mark.end != none {
let f = vector.add(
vector.scale(
(
calc.cos(e - 90deg),
calc.sin(e - 90deg),
0
),
style.mark.length
),
end
)
drawables.push(
drawable.mark(f, end, style.mark.end, style.mark)
)
if marks != none {
drawables += marks
}

let (x, y, z) = start
let label = if type(label) == function { label(e - s) } else { label }
if label != none {
let (lx, ly, ..) = pt-label
Expand Down
90 changes: 83 additions & 7 deletions src/mark.typ
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#import "bezier.typ"
#import "drawable.typ"
#import "vector.typ"
#import "util.typ"
#import "path-util.typ"

// Calculate offset for a triangular mark (triangle, harpoon, ..)
Expand Down Expand Up @@ -298,14 +299,89 @@
}
}

#let place-marks-along-arc(ctx, start, stop, style, marks) = {
let mode = style.mode
let adjust = style.mode == "OPEN"
#let place-marks-along-arc(ctx, start-angle, stop-angle, arc-start, rx, ry, style, marks) = {
let adjust = style.at("mode", default: "OPEN") == "OPEN"

// TODO: ...
if marks.start != none or marks.end != none {
panic("Arc marks are not implemented.")
let r-at(angle) = calc.sqrt(calc.pow(calc.cos(angle) * ry, 2) +
calc.pow(calc.sin(angle) * rx, 2))

let start = if type(marks.start) == str {
(marks.start,)
} else {
marks.start
}

// Offset start
if start != none and start.len() > 0 {
let off = calc-mark-offset(ctx, start.at(0), marks)

// Remember original start
let orig-start = start-angle

// Calc an optimized start angle
let r = r-at(start-angle)
start-angle -= (off * 360deg) / (2 * calc.pi * r)

// Reposition the arc
let diff = vector.sub((calc.cos(start-angle) * rx, calc.sin(start-angle) * ry),
(calc.cos(orig-start) * rx, calc.sin(orig-start) * ry))
arc-start = vector.add(arc-start, diff)
}

let end = if type(marks.end) == str {
(marks.end,)
} else {
marks.end
}

// Offset end
if end != none and end.len() > 0 {
let off = calc-mark-offset(ctx, end.at(0), marks)

let r = r-at(stop-angle)
stop-angle += (off * 360deg) / (2 * calc.pi * r)
}

let arc-center = vector.sub(arc-start, (calc.cos(start-angle) * rx,
calc.sin(start-angle) * ry))
let pt-at(angle) = vector.add(arc-center,
(calc.cos(angle) * rx, calc.sin(angle) * ry, 0))

let drawables = ()

// Draw start marks
if start != none {
let angle = start-angle
for m in start {
let length = mark-mid-length(m, marks)
let r = r-at(angle)
let angle-offset = (length * 360deg) / (2 * calc.pi * r)

let pt = pt-at(angle)
drawables.push(drawable.mark(
pt-at(angle + angle-offset), pt, m, marks))

let angle-offset = ((length + marks.sep) * 360deg) / (2 * calc.pi * r)
angle += angle-offset
}
}

// Draw end marks
if end != none {
let angle = stop-angle
for m in end {
let length = mark-mid-length(m, marks)
let r = r-at(angle)
let angle-offset = (length * 360deg) / (2 * calc.pi * r)

let pt = pt-at(angle)
drawables.push(drawable.mark(
pt-at(angle - angle-offset), pt, m, marks))

let angle-offset = ((length + marks.sep) * 360deg) / (2 * calc.pi * r)
angle -= angle-offset
}
}

return (none, start, stop)
return (drawables, arc-start, start-angle, stop-angle)
}
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.
2 changes: 1 addition & 1 deletion tests/angle/test.typ
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#set page(width: auto, height: auto)
#import "../../src/lib.typ": *
#import "/src/lib.typ": *

#box(stroke: 2pt + red, canvas(length: 1cm, {
import draw: *
Expand Down
Binary file modified tests/mark/multiple/ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion tests/mark/multiple/test.typ
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,19 @@
mark: (start: l, end: l, fill: red, stroke: blue, flex: true, scale: .05))
}))


#box(stroke: 2pt + red, canvas({
import draw: *
rect((1,-2), (2,2))
rect((-2,-2), (-1,2))
catmull((-1,-.5), (0,-.5), (0,1), (1,1),
mark: (start: l, end: l, fill: red, stroke: blue, flex: true))
}))

#box(stroke: 2pt + red, canvas({
import draw: *
line((-.5,1), (2.5,1))
arc((1,1), start: 0deg, stop: 180deg, anchor: "origin",
mark: (start: l, end: l, fill: red, stroke: blue))
arc((1,1), start: 180deg, stop: 360deg, anchor: "origin",
mark: (start: l, end: l, fill: red, stroke: blue))
}))

0 comments on commit db3e4e9

Please sign in to comment.