mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 10:25:37 +00:00
internal/stroke: separate more the circle special case in ArcTransform
Avoid calculations not relevant for a circle. Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
This commit is contained in:
+28
-34
@@ -543,47 +543,37 @@ func strokePathRoundCap(qs *StrokeQuads, hw float32, pivot, n0 f32.Point) {
|
|||||||
// An electronic version may be found at:
|
// An electronic version may be found at:
|
||||||
// http://spaceroots.org/documents/ellipse/elliptical-arc.pdf
|
// http://spaceroots.org/documents/ellipse/elliptical-arc.pdf
|
||||||
func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D {
|
func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D {
|
||||||
center := f32.Point{
|
|
||||||
X: 0.5 * (f1.X + f2.X),
|
|
||||||
Y: 0.5 * (f1.Y + f2.Y),
|
|
||||||
}
|
|
||||||
|
|
||||||
// semi-major axis: 2a = |PF1| + |PF2|
|
|
||||||
a := 0.5 * (dist(f1, p) + dist(f2, p))
|
|
||||||
|
|
||||||
// semi-minor axis: c^2 = a^2 - b^2 (c: focal distance)
|
|
||||||
c := dist(f1, center)
|
|
||||||
b := math.Sqrt(a*a - c*c)
|
|
||||||
|
|
||||||
var rx, ry, alpha float64
|
var rx, ry, alpha float64
|
||||||
switch {
|
if f1 == f2 {
|
||||||
case a > b:
|
|
||||||
rx = a
|
|
||||||
ry = b
|
|
||||||
default:
|
|
||||||
rx = b
|
|
||||||
ry = a
|
|
||||||
}
|
|
||||||
|
|
||||||
var x float64
|
|
||||||
switch {
|
|
||||||
case f1 == f2:
|
|
||||||
// degenerate case of a circle.
|
// degenerate case of a circle.
|
||||||
alpha = 0
|
rx = dist(f1, p)
|
||||||
default:
|
ry = rx
|
||||||
|
} else {
|
||||||
|
// semi-major axis: 2a = |PF1| + |PF2|
|
||||||
|
a := 0.5 * (dist(f1, p) + dist(f2, p))
|
||||||
|
// semi-minor axis: c^2 = a^2 - b^2 (c: focal distance)
|
||||||
|
c := dist(f1, f2) * 0.5
|
||||||
|
b := math.Sqrt(a*a - c*c)
|
||||||
switch {
|
switch {
|
||||||
case f1.X > center.X:
|
case a > b:
|
||||||
x = float64(f1.X - center.X)
|
rx = a
|
||||||
alpha = math.Acos(x / c)
|
ry = b
|
||||||
case f1.X < center.X:
|
default:
|
||||||
x = float64(f2.X - center.X)
|
rx = b
|
||||||
alpha = math.Acos(x / c)
|
ry = a
|
||||||
case f1.X == center.X:
|
}
|
||||||
|
if f1.X == f2.X {
|
||||||
// special case of a "vertical" ellipse.
|
// special case of a "vertical" ellipse.
|
||||||
alpha = math.Pi / 2
|
alpha = math.Pi / 2
|
||||||
if f1.Y < center.Y {
|
if f1.Y < f2.Y {
|
||||||
alpha = -alpha
|
alpha = -alpha
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
x := float64(f1.X-f2.X) * 0.5
|
||||||
|
if x < 0 {
|
||||||
|
x = -x
|
||||||
|
}
|
||||||
|
alpha = math.Acos(x / c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,6 +583,10 @@ func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D
|
|||||||
rot f32.Affine2D // rotation matrix for each segment
|
rot f32.Affine2D // rotation matrix for each segment
|
||||||
inv f32.Affine2D // transform from ellipse-based frame to absolute one
|
inv f32.Affine2D // transform from ellipse-based frame to absolute one
|
||||||
)
|
)
|
||||||
|
center := f32.Point{
|
||||||
|
X: 0.5 * (f1.X + f2.X),
|
||||||
|
Y: 0.5 * (f1.Y + f2.Y),
|
||||||
|
}
|
||||||
ref = ref.Offset(f32.Point{}.Sub(center))
|
ref = ref.Offset(f32.Point{}.Sub(center))
|
||||||
ref = ref.Rotate(f32.Point{}, float32(-alpha))
|
ref = ref.Rotate(f32.Point{}, float32(-alpha))
|
||||||
ref = ref.Scale(f32.Point{}, f32.Point{
|
ref = ref.Scale(f32.Point{}, f32.Point{
|
||||||
|
|||||||
Reference in New Issue
Block a user