commit 79d7e1e43ddc27a68c5ee4f5caf56f8b42d185e9 from: Evan Burkey date: Tue May 17 16:20:48 2022 UTC init commit - /dev/null commit + 79d7e1e43ddc27a68c5ee4f5caf56f8b42d185e9 blob - /dev/null blob + 723ef36f4e4f32c4560383aa5987c575a30c6535 (mode 644) --- /dev/null +++ .gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file blob - /dev/null blob + 609adedb29f4a1a310a5cc107f2f27bf3160f308 (mode 644) --- /dev/null +++ LICENSE @@ -0,0 +1,13 @@ +Copyright 2022 Evan Burkey + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. blob - /dev/null blob + 5297241ab248929cb1c0c1930cd83d244f3676a6 (mode 644) --- /dev/null +++ README.md @@ -0,0 +1,7 @@ +# Bresenham + +A quick generic implementation of Bresenham's Line Algorithm. + +## Usage + +Arguments are constrained to signed types. The line is returned as a slice of type `Point[T]`, a type provided by the library. \ No newline at end of file blob - /dev/null blob + f57830b9274cfa165f56c88d362bea193f41a446 (mode 644) --- /dev/null +++ bresenham.go @@ -0,0 +1,58 @@ +// Package bresenham provides a generic implementation of +// Bresenham's Line Algorithm +package bresenham + +import "golang.org/x/exp/constraints" + +// Point is a generic struct holding two generic coordinates +// with a constraint of Signed +type Point[T constraints.Signed] struct { + X T + Y T +} + +func abs[T constraints.Signed](a T) T { + if a < 0 { + return -a + } + return a +} + +// Bresenham requires arguments of any signed type. The line is generated +// and returned as a slice of Point[T] +func Bresenham[T constraints.Signed](x0, y0, x1, y1 T) []Point[T] { + var line []Point[T] + var cx, cy, dx, dy, sx, sy, err T + cx = x0 + cy = y0 + dx = abs(x1 - x0) + dy = abs(y1 - y0) + + if cx < x1 { + sx = 1 + } else { + sx = -1 + } + if cy < y1 { + sy = 1 + } else { + sy = -1 + } + err = dx - dy + + for { + line = append(line, Point[T]{cx, cy}) + if cx == x1 && cy == y1 { + return line + } + e2 := 2 * err + if e2 > 0-dy { + err = err - dy + cx = cx + sx + } + if e2 < dx { + err = err + dx + cy = cy + sy + } + } +} blob - /dev/null blob + a1f813c5004ce9daeec4875e8e841411ae73fc19 (mode 644) --- /dev/null +++ bresenham_test.go @@ -0,0 +1,53 @@ +package bresenham + +import ( + "testing" +) + +func TestBresenhamInt(t *testing.T) { + var x0, y0, x1, y1 int + x0 = 1 + y0 = 1 + x1 = 3 + y1 = 4 + res := []Point[int]{ + {1, 1}, {2, 2}, {2, 3}, {3, 4}, + } + + line := Bresenham(x0, y0, x1, y1) + if line[0].X != res[0].X && line[0].Y != line[0].Y { + t.Errorf("Wanted %d,%d, got %d,%d", res[0].X, res[0].Y, line[0].X, line[0].Y) + } +} + +func TestBresenhamIntNegative(t *testing.T) { + var x0, y0, x1, y1 int + x0 = -1 + y0 = 2 + x1 = 3 + y1 = -4 + res := []Point[int]{ + {-1, 2}, {0, 1}, {0, 0}, {1, -1}, {2, -2}, {2, -3}, {3, -4}, + } + + line := Bresenham(x0, y0, x1, y1) + if line[0].X != res[0].X && line[0].Y != line[0].Y { + t.Errorf("Wanted %d,%d, got %d,%d", res[0].X, res[0].Y, line[0].X, line[0].Y) + } +} + +func TestBresenhamInt64(t *testing.T) { + var x0, y0, x1, y1 int64 + x0 = 1 + y0 = 1 + x1 = 3 + y1 = 4 + res := []Point[int64]{ + {1, 1}, {2, 2}, {2, 3}, {3, 4}, + } + + line := Bresenham(x0, y0, x1, y1) + if line[0].X != res[0].X && line[0].Y != line[0].Y { + t.Errorf("Wanted %d,%d, got %d,%d", res[0].X, res[0].Y, line[0].X, line[0].Y) + } +} blob - /dev/null blob + 1630c26a7cc419b67f3789ce9f571540d39a8435 (mode 644) --- /dev/null +++ go.mod @@ -0,0 +1,5 @@ +module bresenham + +go 1.18 + +require golang.org/x/exp v0.0.0-20220516143420-24438e51023a // indirect blob - /dev/null blob + 977085d7497f98cff2f8b22a1dbab1ff8de4393c (mode 644) --- /dev/null +++ go.sum @@ -0,0 +1,2 @@ +golang.org/x/exp v0.0.0-20220516143420-24438e51023a h1:tiLLxEjKNE6Hrah/Dp/cyHvsyjDLcMFSocOHO5XDmOM= +golang.org/x/exp v0.0.0-20220516143420-24438e51023a/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=