package bresenham import ( "lab.zaar.be/thefish/alchemyst-go/engine/types" ) // dx > dy; x1 < x2; y1 < y2 func BresenhamDxXRYD(canvas types.Putable, From, To types.Coords, symFunc func() interface{}) { dx, dy := To.X - From.X, 2*(To.Y - From.Y) e, slope := dx, 2*dx for ; dx != 0; dx-- { canvas.Put(From.X, From.Y, symFunc()) From.X++ e -= dy if e < 0 { From.Y++ e += slope } } } // dy > dx; x1 < x2; y1 < y2 func BresenhamDyXRYD(canvas types.Putable, From, To types.Coords, symFunc func() interface{}) { dx, dy := 2*(To.X - From.X), To.Y - From.Y e, slope := dy, 2*dy for ; dy != 0; dy-- { canvas.Put(From.X, From.Y, symFunc()) From.Y++ e -= dx if e < 0 { From.X++ e += slope } } } // dx > dy; x1 < x2; y1 > y2 func BresenhamDxXRYU(canvas types.Putable, From, To types.Coords, symFunc func() interface{}) { dx, dy := To.X - From.X, 2*(From.Y-To.Y) e, slope := dx, 2*dx for ; dx != 0; dx-- { canvas.Put(From.X, From.Y, symFunc()) From.X++ e -= dy if e < 0 { From.Y-- e += slope } } } func BresenhamDyXRYU(canvas types.Putable, From, To types.Coords, symFunc func() interface{}) { dx, dy := 2*(To.X - From.X), From.Y-To.Y e, slope := dy, 2*dy for ; dy != 0; dy-- { canvas.Put(From.X, From.Y, symFunc()) From.Y-- e -= dx if e < 0 { From.X++ e += slope } } } // Generalized with integer func Bresenham(canvas types.Putable, From, To types.Coords, symFunc func() interface{}) { var dx, dy, e, slope int // Because drawing p1 -> p2 is equivalent to draw p2 -> p1, // I sort points in x-axis order to handle only half of possible cases. if From.X > To.X { From.X, From.Y, To.X, To.Y = To.X, To.Y, From.X, From.Y } dx, dy = To.X - From.X, To.Y - From.Y // Because point is x-axis ordered, dx cannot be negative if dy < 0 { dy = -dy } switch { // Is line a point ? case From.X ==To.X && From.Y ==To.Y: canvas.Put(From.X, From.Y, symFunc()) // Is line an horizontal ? case From.Y ==To.Y: for ; dx != 0; dx-- { canvas.Put(From.X, From.Y, symFunc()) From.X++ } canvas.Put(From.X, From.Y, symFunc()) // Is line a vertical ? case From.X ==To.X: if From.Y > To.Y { From.Y, To.Y = To.Y, From.Y } for ; dy != 0; dy-- { canvas.Put(From.X, From.Y, symFunc()) From.Y++ } canvas.Put(From.X, From.Y, symFunc()) // Is line a diagonal ? case dx == dy: if From.Y < To.Y { for ; dx != 0; dx-- { canvas.Put(From.X, From.Y, symFunc()) From.X++ From.Y++ } } else { for ; dx != 0; dx-- { canvas.Put(From.X, From.Y, symFunc()) From.X++ From.Y-- } } canvas.Put(From.X, From.Y, symFunc()) // wider than high ? case dx > dy: if From.Y < To.Y { // BresenhamDxXRYD(img, x1, y1, x2, y2, col) dy, e, slope = 2*dy, dx, 2*dx for ; dx != 0; dx-- { canvas.Put(From.X, From.Y, symFunc()) From.X++ e -= dy if e < 0 { From.Y++ e += slope } } } else { // BresenhamDxXRYU(img, x1, y1, x2, y2, col) dy, e, slope = 2*dy, dx, 2*dx for ; dx != 0; dx-- { canvas.Put(From.X, From.Y, symFunc()) From.X++ e -= dy if e < 0 { From.Y-- e += slope } } } canvas.Put(To.X, To.Y, symFunc()) // higher than wide. default: if From.Y < To.Y { // BresenhamDyXRYD(img, x1, y1, x2, y2, col) dx, e, slope = 2*dx, dy, 2*dy for ; dy != 0; dy-- { canvas.Put(From.X, From.Y, symFunc()) From.Y++ e -= dx if e < 0 { From.X++ e += slope } } } else { // BresenhamDyXRYU(img, x1, y1, x2, y2, col) dx, e, slope = 2*dx, dy, 2*dy for ; dy != 0; dy-- { canvas.Put(From.X, From.Y, symFunc()) From.Y-- e -= dx if e < 0 { From.X++ e += slope } } } canvas.Put(To.X, To.Y, symFunc()) //img.Set(x2, y2, col) } }