ggfx/line.go

111 lines
1.9 KiB
Go

package ggfx
import "image"
func (this Image[T]) Line (
stroke []T,
weight int,
min image.Point,
max image.Point,
) {
// TODO: move this process to plottingContext.Plot, it might be more
// efficient there
this.assertWidth(stroke)
for offset, part := range stroke {
this.lineInternal(part, weight, min, max, offset)
}
}
func (this Image[T]) lineInternal (
stroke T,
weight int,
min image.Point,
max image.Point,
offset int,
) {
context := linePlottingContext[T] {
plottingContext: plottingContext[T] {
Image: this,
color: stroke,
weight: weight,
offset: offset,
},
min: min,
max: max,
}
if abs(max.Y - min.Y) < abs(max.X - min.X) {
if max.X < min.X { context.swap() }
context.lineLow()
} else {
if max.Y < min.Y { context.swap() }
context.lineHigh()
}
}
type linePlottingContext[T any] struct {
plottingContext[T]
min image.Point
max image.Point
}
func (context *linePlottingContext[T]) swap () {
temp := context.max
context.max = context.min
context.min = temp
}
func (context linePlottingContext[T]) lineLow () {
deltaX := context.max.X - context.min.X
deltaY := context.max.Y - context.min.Y
yi := 1
if deltaY < 0 {
yi = -1
deltaY *= -1
}
D := (2 * deltaY) - deltaX
point := context.min
for ; point.X < context.max.X; point.X ++ {
context.plot(point)
if D > 0 {
D += 2 * (deltaY - deltaX)
point.Y += yi
} else {
D += 2 * deltaY
}
}
}
func (context linePlottingContext[T]) lineHigh () {
deltaX := context.max.X - context.min.X
deltaY := context.max.Y - context.min.Y
xi := 1
if deltaX < 0 {
xi = -1
deltaX *= -1
}
D := (2 * deltaX) - deltaY
point := context.min
for ; point.Y < context.max.Y; point.Y ++ {
context.plot(point)
if D > 0 {
point.X += xi
D += 2 * (deltaX - deltaY)
} else {
D += 2 * deltaX
}
}
}
func abs (n int) int {
if n < 0 { n *= -1}
return n
}