alchemyst/util/bresenham/bresenham.go

184 lines
3.7 KiB
Go

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)
}
}