Improve normal calculations
Soooo. It turns out that the bunch of smallish (~4-5% of runtime) loads associated with Len(), Unit(), Rotated(), and so on... Were actually more like 15% or more of computational effort. I first figured this out by creating: func (u Vec) Normal(v Vec) Vec which gives you a vector normal to u->v. That consumed a lot of CPU time, and was followed by .Unit().Scaled(imd.thickness / 2), which consumed a bit more CPU time. After some poking, and in the interests of avoiding UI cruft, the final selection is func (u Vec) Normal() Vec This returns the vector rotated 90 degrees, which turns out to be the most common problem.
This commit is contained in:
parent
678da34fc3
commit
daedc45ea9
13
geometry.go
13
geometry.go
|
@ -49,6 +49,11 @@ func (u Vec) XY() (x, y float64) {
|
|||
return u.X, u.Y
|
||||
}
|
||||
|
||||
// Normal returns a vector normal to u (rotated by math.pi/2)
|
||||
func (u Vec) Normal() Vec {
|
||||
return Vec{X: u.Y, Y: -u.X}
|
||||
}
|
||||
|
||||
// Add returns the sum of vectors u and v.
|
||||
func (u Vec) Add(v Vec) Vec {
|
||||
return Vec{
|
||||
|
@ -65,6 +70,14 @@ func (u Vec) Sub(v Vec) Vec {
|
|||
}
|
||||
}
|
||||
|
||||
// To returns the vector from vector u to vector v, equivalent to v.Sub(u).
|
||||
func (u Vec) To(v Vec) Vec {
|
||||
return Vec{
|
||||
v.X - u.X,
|
||||
v.Y - u.Y,
|
||||
}
|
||||
}
|
||||
|
||||
// Scaled returns the vector u multiplied by c.
|
||||
func (u Vec) Scaled(c float64) Vec {
|
||||
return Vec{u.X * c, u.Y * c}
|
||||
|
|
|
@ -495,12 +495,12 @@ func (imd *IMDraw) outlineEllipseArc(radius pixel.Vec, low, high, thickness floa
|
|||
thick := pixel.V(thickness/2, 0).Rotated(normalLow)
|
||||
imd.pushPt(lowCenter.Add(thick), pt)
|
||||
imd.pushPt(lowCenter.Sub(thick), pt)
|
||||
imd.pushPt(lowCenter.Sub(thick.Rotated(math.Pi/2*orientation)), pt)
|
||||
imd.pushPt(lowCenter.Sub(thick.Normal().Scaled(orientation)), pt)
|
||||
imd.fillPolygon()
|
||||
thick = pixel.V(thickness/2, 0).Rotated(normalHigh)
|
||||
imd.pushPt(highCenter.Add(thick), pt)
|
||||
imd.pushPt(highCenter.Sub(thick), pt)
|
||||
imd.pushPt(highCenter.Add(thick.Rotated(math.Pi/2*orientation)), pt)
|
||||
imd.pushPt(highCenter.Add(thick.Normal().Scaled(orientation)), pt)
|
||||
imd.fillPolygon()
|
||||
case RoundEndShape:
|
||||
imd.pushPt(lowCenter, pt)
|
||||
|
@ -528,7 +528,7 @@ func (imd *IMDraw) polyline(thickness float64, closed bool) {
|
|||
|
||||
// first point
|
||||
j, i := 0, 1
|
||||
ijNormal := points[1].pos.Sub(points[0].pos).Rotated(math.Pi / 2).Unit().Scaled(thickness / 2)
|
||||
ijNormal := points[0].pos.To(points[1].pos).Normal().Unit().Scaled(thickness / 2)
|
||||
|
||||
if !closed {
|
||||
switch points[j].endshape {
|
||||
|
@ -537,7 +537,7 @@ func (imd *IMDraw) polyline(thickness float64, closed bool) {
|
|||
case SharpEndShape:
|
||||
imd.pushPt(points[j].pos.Add(ijNormal), points[j])
|
||||
imd.pushPt(points[j].pos.Sub(ijNormal), points[j])
|
||||
imd.pushPt(points[j].pos.Add(ijNormal.Rotated(math.Pi/2)), points[j])
|
||||
imd.pushPt(points[j].pos.Add(ijNormal.Normal()), points[j])
|
||||
imd.fillPolygon()
|
||||
case RoundEndShape:
|
||||
imd.pushPt(points[j].pos, points[j])
|
||||
|
@ -549,7 +549,6 @@ func (imd *IMDraw) polyline(thickness float64, closed bool) {
|
|||
imd.pushPt(points[j].pos.Sub(ijNormal), points[j])
|
||||
|
||||
// middle points
|
||||
// compute "previous" normal:
|
||||
for i := 0; i < len(points); i++ {
|
||||
j, k := i+1, i+2
|
||||
|
||||
|
@ -565,7 +564,7 @@ func (imd *IMDraw) polyline(thickness float64, closed bool) {
|
|||
k %= len(points)
|
||||
}
|
||||
|
||||
jkNormal := points[k].pos.Sub(points[j].pos).Rotated(math.Pi / 2).Unit().Scaled(thickness / 2)
|
||||
jkNormal := points[j].pos.To(points[k].pos).Normal().Unit().Scaled(thickness / 2)
|
||||
|
||||
orientation := 1.0
|
||||
if ijNormal.Cross(jkNormal) > 0 {
|
||||
|
@ -601,7 +600,7 @@ func (imd *IMDraw) polyline(thickness float64, closed bool) {
|
|||
|
||||
// last point
|
||||
i, j = len(points)-2, len(points)-1
|
||||
ijNormal = points[j].pos.Sub(points[i].pos).Rotated(math.Pi / 2).Unit().Scaled(thickness / 2)
|
||||
ijNormal = points[i].pos.To(points[j].pos).Normal().Unit().Scaled(thickness / 2)
|
||||
|
||||
imd.pushPt(points[j].pos.Sub(ijNormal), points[j])
|
||||
imd.pushPt(points[j].pos.Add(ijNormal), points[j])
|
||||
|
@ -614,7 +613,7 @@ func (imd *IMDraw) polyline(thickness float64, closed bool) {
|
|||
case SharpEndShape:
|
||||
imd.pushPt(points[j].pos.Add(ijNormal), points[j])
|
||||
imd.pushPt(points[j].pos.Sub(ijNormal), points[j])
|
||||
imd.pushPt(points[j].pos.Add(ijNormal.Rotated(-math.Pi/2)), points[j])
|
||||
imd.pushPt(points[j].pos.Add(ijNormal.Normal().Scaled(-1)), points[j])
|
||||
imd.fillPolygon()
|
||||
case RoundEndShape:
|
||||
imd.pushPt(points[j].pos, points[j])
|
||||
|
|
Loading…
Reference in New Issue