-
-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
arc: Add a function arc-through
#206
Comments
We could allow passing 3 positional arguments in the current |
I think overloading existing functions too much only brings complexity with no real benefit. I would favor having the extra |
what would be best is allowing dot access notation on the element function. for example |
Yes, if the dot syntax becomes available we can switch to that. |
Would you two be okay with it if I had a go at implementing this? I know you're in the middle of a rework, so I feel like I should ask before making a PR. I've already gotten the basics working using what CetZ provides out of the box. I would just need to convert it to the same style that the other functions use, where they return that fancy dictionary with #let arc-through(a, b, c, ..args) = cetz.draw.get-ctx(ctx => {
import cetz.vector
import cetz.coordinate
let a = coordinate.resolve(ctx, a)
let b = coordinate.resolve(ctx, b)
let c = coordinate.resolve(ctx, c)
let center = coordinate.util.calculate-circle-center-3pt(a, b, c)
let radius = vector.dist(center, a)
let start = {
let (x, y, ..) = vector.sub(a, center)
calc.atan2(x, y) // Typst's atan2 is (x,y) order!!
}
let delta = vector.angle(a, center, c)
cetz.draw.arc(a, ..args, start: start, delta: delta, radius: radius, anchor: "start")
}) Let me know what you think. I'll hold off if it should wait until the rework is complete. Related to arcs/curves, I'd also like to take a stab at #239 at some point, if that isn't going to be part of the rework, as well... It just so happens that my latest Algorithms assignment fits really well with drawing curved arrows 😅 |
Thank you for the work! There are some edge cases where your implementation did not work correctly. We have to check on which side of #import "@preview/cetz:0.1.2"
#set page(width: auto, height: auto)
#let side-on-line(a, b, pt) = {
let (x1, y1, ..) = a
let (x2, y2, ..) = b
let (x, y, ..) = pt
return (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1)
}
#let arc-through(a, b, c, ..args) = cetz.draw.get-ctx(ctx => {
import cetz.vector
import cetz.coordinate
let a = coordinate.resolve(ctx, a)
let b = coordinate.resolve(ctx, b)
let c = coordinate.resolve(ctx, c)
let center = coordinate.util.calculate-circle-center-3pt(a, b, c)
let radius = vector.dist(center, a)
let start = {
let (x, y, ..) = vector.sub(a, center)
calc.atan2(x, y) // Typst's atan2 is (x,y) order!!
}
let delta = vector.angle(a, center, c)
let center-is-left = side-on-line(a, c, center) < 0
let b-is-left = side-on-line(a, c, b) < 0
// If the center and point b are on the same side of a-c,
// the arcs delta must be > 180deg
if center-is-left == b-is-left {
delta = 360deg - delta
}
// If b is left of a-c, swap a-c to c-a by using a negative delta
if b-is-left {
delta *= -1
}
cetz.draw.content(center, [#delta])
cetz.draw.arc(a, ..args, start: start, delta: delta, radius: radius, anchor: "start")
})
#let test(a, b, c) = {
import cetz.draw: *
group({
anchor("default", (0,0))
circle(a, radius: .1, fill: green)
circle(b, radius: .1, fill: yellow)
circle(c, radius: .1, fill: red)
arc-through(a, b, c, name: "a")
}, name: "g", anchor: "left")
on-layer(-1, rect("g.bottom-left", "g.top-right", stroke: none, fill: gray.lighten(80%)))
set-origin((rel: (1,0), to: "g.right"))
}
#cetz.canvas({
import cetz.draw: *
test((0,0), (1,1), (2,0))
test((0,0), (1,-1), (2,0))
test((0,-1), (-1,0), (0,1))
test((0,-1), (1,0), (0,1))
test((0,0), (1,3), (4,0))
test((0,0), (1,3), (4,3))
test((1,0), (2,3), (0,3))
test((0,0), (1,-3), (4,0))
test((0,0), (1,-3), (4,3))
}) You can create a PR, but I would wait to merge it until the rework has been merged. |
Fixes #206. Thanks to @matthew-e-brown for the initial implementation!
That function should connect two points with an arc touching the third point (see circle-through).
The text was updated successfully, but these errors were encountered: