package main import ( "math" ) // Draw a line using dumb func LineDumb(fb *Framebuffer, color uint, x0 uint, y0 uint, x1 uint, y1 uint) { var t float32 for t = 0; t < 1; t += 0.01 { // Very simple interpolation between x and y x := x0 + uint(float32(x1-x0)*t) y := y0 + uint(float32(y1-y0)*t) fb.Set(x, y, color) } } func LineDumb2(fb *Framebuffer, color uint, x0 uint, y0 uint, x1 uint, y1 uint) { for x := x0; x < x1; x++ { // For each pixel across, compute how far across we are and interpolate y t := float32(x-x0) / float32(x1-x0) y := uint(float32(y0)*(1-t) + float32(y1)*t) fb.Set(x, y, color) } } func LineDumb3(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { steep := false // This one makes sure that going pixel by pixel will not make holes in the // other direction by always moving in the less steep direction. if math.Abs(float64(x0-x1)) < math.Abs(float64(y0-y1)) { x0, y0 = y0, x0 x1, y1 = y1, x1 steep = true } // Don't let lines be invisible, always go left to right if x0 > x1 { // need to be left to right x0, x1 = x1, x0 y0, y1 = y1, y0 // Why are we swapping these? I guess because we're swapping the points... } // Same as dumb2, going across pixel by pixel. But "x" here might actually be y // because of the inverted direction for x := x0; x <= x1; x++ { t := float32(x-x0) / float32(x1-x0) y := uint(float32(y0)*(1-t) + float32(y1)*t) if steep { fb.Set(y, uint(x), color) } else { fb.Set(uint(x), y, color) } } } func LineDumb4(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { steep := false // This one makes sure that going pixel by pixel will not make holes in the // other direction by always moving in the less steep direction. if math.Abs(float64(x1-x0)) < math.Abs(float64(y1-y0)) { x0, y0 = y0, x0 x1, y1 = y1, x1 steep = true } // Don't let lines be invisible, always go left to right if x0 > x1 { // need to be left to right x0, x1 = x1, x0 y0, y1 = y1, y0 // Why are we swapping these? I guess because we're swapping the points... } dx := x1 - x0 // These MUST be POST calcs dy := y1 - y0 // Delta error or something? Basically, as we move in one direction, we get farther // and farther off course if we never move in the OTHER direction. This is the amount // of that per x direction. derror := math.Abs(float64(dy) / float64(dx)) y := uint(y0) var err float64 // Same as dumb2, going across pixel by pixel. But "x" here might actually be y // because of the inverted direction for x := x0; x <= x1; x++ { if steep { fb.Set(y, uint(x), color) } else { fb.Set(uint(x), y, color) } err += derror if err > 0.5 { if y1 > y0 { y += 1 } else { y = y - 1 } err -= 1 } } } // For not-steep lines func BresenhamLow(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { dx := x1 - x0 dy := y1 - y0 yi := 1 // This is the increment if dy < 0 { // Line moves in opposite vertical direction yi = -1 dy = -dy } d := 2*dy - dx // Why minus dx? if slope is 0 then d is -dx. If slope is 1 then d = dy. // I don't know... y := y0 x1u := uint(x1) for x := uint(x0); x <= x1u; x++ { fb.Set(x, uint(y), color) if d > 0 { y = y + yi d = d + 2*(dy-dx) } else { d = d + 2*dy } } } // For steep lines func BresenhamHigh(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { dx := x1 - x0 dy := y1 - y0 xi := 1 // This is the increment if dx < 0 { // Line moves in opposite vertical direction xi = -1 dx = -dx } d := 2*dx - dy // Why minus dx? if slope is 0 then d is -dx. If slope is 1 then d = dy. // I don't know... x := x0 y1u := uint(y1) for y := uint(y0); y <= y1u; y++ { fb.Set(uint(x), y, color) if d > 0 { x = x + xi d = d + 2*(dx-dy) } else { d = d + 2*dx } } } func Bresenham(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { if math.Abs(float64(y1-y0)) < math.Abs(float64(x1-x0)) { // This is a flatter line if x0 > x1 { // This line is backwards BresenhamLow(fb, color, x1, y1, x0, y0) } else { BresenhamLow(fb, color, x0, y0, x1, y1) } } else { // This is a steep line if y0 > y1 { // This line is backwards BresenhamHigh(fb, color, x1, y1, x0, y0) } else { BresenhamHigh(fb, color, x0, y0, x1, y1) } } } func Bresenham2(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { dx := int(math.Abs(float64(x1 - x0))) sx := -1 if x0 < x1 { sx = 1 } dy := -int(math.Abs(float64(y1 - y0))) sy := -1 if y0 < y1 { sy = 1 } err := dx + dy for { fb.SetSafe(uint(x0), uint(y0), color) if x0 == x1 && y0 == y1 { break } e2 := 2 * err if e2 >= dy { if x0 == x1 { break } err += dy x0 += sx } if e2 <= dx { if y0 == y1 { break } err += dx y0 += sy } } } func LineDumb5(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { steep := false // This one makes sure that going pixel by pixel will not make holes in the // other direction by always moving in the less steep direction. if math.Abs(float64(x1-x0)) < math.Abs(float64(y1-y0)) { x0, y0 = y0, x0 x1, y1 = y1, x1 steep = true } // Don't let lines be invisible, always go left to right if x0 > x1 { // need to be left to right x0, x1 = x1, x0 y0, y1 = y1, y0 // Why are we swapping these? I guess because we're swapping the points... } dx := x1 - x0 // These MUST be POST calcs dy := y1 - y0 derror2 := int(math.Abs(float64(dy))) * 2 error2 := 0 y := y0 sy := 1 if y1 <= y0 { sy = -1 } // Same as dumb2, going across pixel by pixel. But "x" here might actually be y // because of the inverted direction for x := x0; x <= x1; x++ { if steep { fb.Set(uint(y), uint(x), color) } else { fb.Set(uint(x), uint(y), color) } error2 += derror2 if error2 > dx { y = y + sy error2 -= dx * 2 } } }