65 lines
1.5 KiB
Go
65 lines
1.5 KiB
Go
|
package render
|
||
|
|
||
|
// MidpointEllipse implements an ellipse plotting algorithm.
|
||
|
func MidpointEllipse(center, radius Point) chan Point {
|
||
|
yield := make(chan Point)
|
||
|
go func() {
|
||
|
|
||
|
var (
|
||
|
pos = NewPoint(radius.X, 0)
|
||
|
delta = NewPoint(
|
||
|
2*radius.Y*radius.Y*pos.X,
|
||
|
2*radius.X*radius.X*pos.Y,
|
||
|
)
|
||
|
err = radius.X*radius.X -
|
||
|
radius.Y*radius.Y*radius.X +
|
||
|
(radius.Y*radius.Y)/4
|
||
|
)
|
||
|
|
||
|
for delta.Y < delta.X {
|
||
|
yield <- NewPoint(center.X+pos.X, center.Y+pos.Y)
|
||
|
yield <- NewPoint(center.X+pos.X, center.Y-pos.Y)
|
||
|
yield <- NewPoint(center.X-pos.X, center.Y+pos.Y)
|
||
|
yield <- NewPoint(center.X-pos.X, center.Y-pos.Y)
|
||
|
|
||
|
pos.Y++
|
||
|
|
||
|
if err < 0 {
|
||
|
delta.Y += 2 * radius.X * radius.X
|
||
|
err += delta.Y + radius.X*radius.X
|
||
|
} else {
|
||
|
pos.X--
|
||
|
delta.Y += 2 * radius.X * radius.X
|
||
|
delta.X -= 2 * radius.Y * radius.Y
|
||
|
err += delta.Y - delta.X + radius.X*radius.X
|
||
|
}
|
||
|
}
|
||
|
|
||
|
err = radius.X*radius.X*(pos.Y*pos.Y+pos.Y) +
|
||
|
radius.Y*radius.Y*(pos.X-1)*(pos.X-1) -
|
||
|
radius.Y*radius.Y*radius.X*radius.X
|
||
|
|
||
|
for pos.X >= 0 {
|
||
|
yield <- NewPoint(center.X+pos.X, center.Y+pos.Y)
|
||
|
yield <- NewPoint(center.X+pos.X, center.Y-pos.Y)
|
||
|
yield <- NewPoint(center.X-pos.X, center.Y+pos.Y)
|
||
|
yield <- NewPoint(center.X-pos.X, center.Y-pos.Y)
|
||
|
|
||
|
pos.X--
|
||
|
|
||
|
if err > 0 {
|
||
|
delta.X -= 2 * radius.Y * radius.Y
|
||
|
err += radius.Y*radius.Y - delta.X
|
||
|
} else {
|
||
|
pos.Y++
|
||
|
delta.Y += 2 * radius.X * radius.X
|
||
|
delta.X -= 2 * radius.Y * radius.Y
|
||
|
err += delta.Y - delta.X + radius.Y*radius.Y
|
||
|
}
|
||
|
}
|
||
|
|
||
|
close(yield)
|
||
|
}()
|
||
|
return yield
|
||
|
}
|