internal/stroke: tidy up ArcTransform

Fix comments and rename variables to avoid confusing
de facto ellipse constant names.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
This commit is contained in:
Pierre Curto
2021-11-24 22:29:43 +01:00
committed by Elias Naur
parent ebb7f40e9d
commit 321512d8a5
+15 -15
View File
@@ -543,7 +543,7 @@ func strokePathRoundCap(qs *StrokeQuads, hw float32, pivot, n0 f32.Point) {
// An electronic version may be found at:
// http://spaceroots.org/documents/ellipse/elliptical-arc.pdf
func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D {
c := f32.Point{
center := f32.Point{
X: 0.5 * (f1.X + f2.X),
Y: 0.5 * (f1.Y + f2.Y),
}
@@ -551,9 +551,9 @@ func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D
// 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)
f := dist(f1, c)
b := math.Sqrt(a*a - f*f)
// 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
switch {
@@ -567,21 +567,21 @@ func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D
var x float64
switch {
case f1 == c || f2 == c:
case f1 == f2:
// degenerate case of a circle.
alpha = 0
default:
switch {
case f1.X > c.X:
x = float64(f1.X - c.X)
alpha = math.Acos(x / f)
case f1.X < c.X:
x = float64(f2.X - c.X)
alpha = math.Acos(x / f)
case f1.X == c.X:
case f1.X > center.X:
x = float64(f1.X - center.X)
alpha = math.Acos(x / c)
case f1.X < center.X:
x = float64(f2.X - center.X)
alpha = math.Acos(x / c)
case f1.X == center.X:
// special case of a "vertical" ellipse.
alpha = math.Pi / 2
if f1.Y < c.Y {
if f1.Y < center.Y {
alpha = -alpha
}
}
@@ -593,14 +593,14 @@ func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D
rot f32.Affine2D // rotation matrix for each segment
inv f32.Affine2D // transform from ellipse-based frame to absolute one
)
ref = ref.Offset(f32.Point{}.Sub(c))
ref = ref.Offset(f32.Point{}.Sub(center))
ref = ref.Rotate(f32.Point{}, float32(-alpha))
ref = ref.Scale(f32.Point{}, f32.Point{
X: float32(1 / rx),
Y: float32(1 / ry),
})
inv = ref.Invert()
rot = rot.Rotate(f32.Point{}, float32(0.5*θ))
rot = rot.Rotate(f32.Point{}, 0.5*θ)
// Instead of invoking math.Sincos for every segment, compute a rotation
// matrix once and apply for each segment.