Skip to content

Commit

Permalink
Improve arc anchors
Browse files Browse the repository at this point in the history
  • Loading branch information
fenjalien authored and johannes-wolf committed Oct 30, 2023
1 parent e7eba3e commit bd70dad
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 18 deletions.
37 changes: 21 additions & 16 deletions src/draw/shapes.typ
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@
return (ctx => {
let style = styles.resolve(ctx.style, style, root: "arc")
assert(style.mode in ("OPEN", "PIE", "CLOSE"))
let (ctx, position) = coordinate.resolve(ctx, position)
let (x, y, z) = position
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(
Expand All @@ -203,22 +203,23 @@
sector-center.at(1) + ry * calc.sin(stop-angle),
z
)
let chord-center = vector.lerp(position, arc-end, 0.5)
let chord-center = vector.lerp(arc-start, arc-end, 0.5)
let arc-center = (
sector-center.first() + rx * calc.cos((stop-angle + start-angle)/2),
sector-center.at(1) + ry * calc.sin((stop-angle + start-angle)/2),
z
)

// center is calculated based on observations of tikz's circular sector and semi circle shapes.
let center = if style.mode == "PIE" {
// A circular sector's anchor is placed half way between the sector-center and arc-center when the angle is 180deg. At 60deg it is placed 1/3 of the way between, this is mirrored at 300deg.
let center = if style.mode != "CLOSE" {
// A circular sector's center anchor is placed half way between the sector-center and arc-center when the angle is 180deg. At 60deg it is placed 1/3 of the way between, this is mirrored at 300deg.
vector.lerp(
arc-center,
sector-center,
if (stop-angle + start-angle) > 180deg { (stop-angle + start-angle) } else { (stop-angle + start-angle) + 180deg } / 720deg
)
} else {
// A semi circle's center anchor is placed half way between the sector-center and arc-center, so that is always `center` when the arc is closed. Otherwise the point at which compass anchors are calculated from will be outside the lines.
vector.lerp(
arc-center,
chord-center,
Expand All @@ -227,27 +228,31 @@
}

// compass anchors are placed on the shapes border in tikz so prototype version is setup for use here
let border = anchor_.border.with(center, 2*rx, 2*ry, path + if style.mode == "OPEN" {
(drawable.path(path-util.line-segment((position, arc-end))),)
})
let border = anchor_.border.with(
center,
2*rx, 2*ry,
path + if style.mode == "OPEN" {
(
drawable.path((
path-util.line-segment((position, sector-center)),
path-util.line-segment((sector-center, arc-end))
))
,)
}
)

let (transform, anchors) = anchor_.setup(
anchor => {
if anchor in anchor_.compass-angle {
return border(anchor_.compass-angle.at(anchor))
}
(
arc-start: position,
origin: sector-center,
arc-end: arc-end,
arc-center: arc-center,
chord-center: chord-center,
center: center,
north: border(90deg),
north-east: border(45deg),
east: border(0deg),
south-east: border(-45deg),
south: border(-90deg),
south-west: border(-135deg),
west: border(180deg),
north-west: border(135deg)
).at(anchor)
},
(
Expand Down
9 changes: 7 additions & 2 deletions tests/anchor/element-anchors/test.typ
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
let (_, nv) = coordinate.resolve(ctx, n)
let (x, y, ..) = nv
let anchor = (
(if y < 0 { "north" } else if y > 0 { "south" },) +
(if x < 0 { "east" } else if x > 0 { "west" },)).filter(p => p != none).join("-")
(if y < 0 { "north" } else if y > 0 { "south" },) + (if x < 0 { "east" } else if x > 0 { "west" },)
).filter(p => p != none).join("-")
if anchor == none {
anchor = "south"
}
Expand Down Expand Up @@ -49,6 +49,11 @@
display(arc, (0,0), start: 225deg, stop: 135deg, radius: 5, mode: "PIE")
}))

#box(stroke: 2pt + red, canvas(length: 1cm, {
import draw: *
display(arc, (0,0), start: 225deg, stop: 135deg, radius: 5, mode: "CLOSE")
}))

#box(stroke: 2pt + red, canvas(length: 1cm, {
import draw: *
display(line, (-1,0), (0,1), (1,0))
Expand Down

0 comments on commit bd70dad

Please sign in to comment.