fix angle consistency in IMDraw.FillEllipseArc

This commit is contained in:
faiface 2017-03-16 12:53:52 +01:00
parent 1f6d186539
commit 3ed1d0ab78
1 changed files with 28 additions and 25 deletions

View File

@ -73,9 +73,9 @@ type IMDraw struct {
opts point opts point
matrix Matrix matrix Matrix
mask NRGBA mask NRGBA
tri *TrianglesData tri *TrianglesData
batch *Batch batch *Batch
tmp []Vec
} }
var _ BasicTarget = (*IMDraw)(nil) var _ BasicTarget = (*IMDraw)(nil)
@ -139,14 +139,18 @@ func (imd *IMDraw) Draw(t Target) {
// Push adds some points to the IM queue. All Pushed points will have the same properties except for // Push adds some points to the IM queue. All Pushed points will have the same properties except for
// the position. // the position.
func (imd *IMDraw) Push(pts ...Vec) { func (imd *IMDraw) Push(pts ...Vec) {
point := imd.opts
for _, pt := range pts { for _, pt := range pts {
point.pos = imd.matrix.Project(pt) imd.pushPt(pt)
point.col = imd.mask.Mul(imd.opts.col)
imd.points = append(imd.points, point)
} }
} }
func (imd *IMDraw) pushPt(pt Vec) {
point := imd.opts
point.pos = imd.matrix.Project(pt)
point.col = imd.mask.Mul(point.col)
imd.points = append(imd.points, point)
}
// Color sets the color of the next Pushed points. // Color sets the color of the next Pushed points.
func (imd *IMDraw) Color(color color.Color) { func (imd *IMDraw) Color(color color.Color) {
imd.opts.col = NRGBAModel.Convert(color).(NRGBA) imd.opts.col = NRGBAModel.Convert(color).(NRGBA)
@ -174,9 +178,6 @@ func (imd *IMDraw) Width(w float64) {
// It is the number of segments per 360 degrees. // It is the number of segments per 360 degrees.
func (imd *IMDraw) Precision(p int) { func (imd *IMDraw) Precision(p int) {
imd.opts.precision = p imd.opts.precision = p
if p+1 > len(imd.tmp) {
imd.tmp = append(imd.tmp, make([]Vec, p+1-len(imd.tmp))...)
}
} }
// EndShape sets the endshape of the next Pushed points. // EndShape sets the endshape of the next Pushed points.
@ -224,10 +225,10 @@ func (imd *IMDraw) FillConvexPolygon() {
imd.tri.SetLen(imd.tri.Len() + 3*(len(points)-2)) imd.tri.SetLen(imd.tri.Len() + 3*(len(points)-2))
for j := 1; j+1 < len(points); j++ { for j := 1; j+1 < len(points); j++ {
(*imd.tri)[i].Position = points[0].pos (*imd.tri)[i+0].Position = points[0].pos
(*imd.tri)[i].Color = points[0].col (*imd.tri)[i+0].Color = points[0].col
(*imd.tri)[i].Picture = points[0].pic (*imd.tri)[i+0].Picture = points[0].pic
(*imd.tri)[i].Intensity = points[0].in (*imd.tri)[i+0].Intensity = points[0].in
(*imd.tri)[i+1].Position = points[j].pos (*imd.tri)[i+1].Position = points[j].pos
(*imd.tri)[i+1].Color = points[j].col (*imd.tri)[i+1].Color = points[j].col
@ -262,30 +263,32 @@ func (imd *IMDraw) FillEllipse(radius Vec) {
// FillEllipseArc draws a filled ellipse arc around each point in the IM's queue. Low and high // FillEllipseArc draws a filled ellipse arc around each point in the IM's queue. Low and high
// angles are in radians. // angles are in radians.
//
// The arc is drawn starting at the low angle continuing to the high angle. If the high angle is
// numerically greater than the low angle, the arc will be drawn counterclockwise, otherwise it will
// be drawn clockwise.
//
// The angles are not normalized by any means. This will rotate four times in a full circle:
//
// imd.FillEllipseArc(pixel.V(100, 100), 0, 8*math.Pi)
func (imd *IMDraw) FillEllipseArc(radius Vec, low, high float64) { func (imd *IMDraw) FillEllipseArc(radius Vec, low, high float64) {
points := imd.points points := imd.points
imd.points = nil imd.points = nil
// normalize high
if math.Abs(high-low) > 2*math.Pi {
high = low + math.Mod(high-low, 2*math.Pi)
}
for _, pt := range points { for _, pt := range points {
imd.Push(pt.pos) // center imd.pushPt(pt.pos) // center
num := math.Ceil(math.Abs(high-low) / (2 * math.Pi) * float64(pt.precision)) num := math.Ceil(math.Abs(high-low) / (2 * math.Pi) * float64(pt.precision))
delta := (high - low) / num delta := (high - low) / num
for i := range imd.tmp[:int(num)+1] { for i := 0.0; i <= num; i++ {
angle := low + float64(i)*delta angle := low + i*delta
sin, cos := math.Sincos(angle) sin, cos := math.Sincos(angle)
imd.tmp[i] = pt.pos + V( imd.pushPt(pt.pos + V(
radius.X()*cos, radius.X()*cos,
radius.Y()*sin, radius.Y()*sin,
) ))
} }
imd.Push(imd.tmp[:int(num)+1]...)
imd.FillConvexPolygon() imd.FillConvexPolygon()
} }
} }