Fixed polygon filling
This commit is contained in:
parent
85b71a91a3
commit
5ca69d90e6
@ -6,14 +6,25 @@ import "image/png"
|
|||||||
import "git.tebibyte.media/tomo/ggfx"
|
import "git.tebibyte.media/tomo/ggfx"
|
||||||
|
|
||||||
func main () {
|
func main () {
|
||||||
img := image.NewRGBA(image.Rect(0, 0, 800, 600))
|
img := image.NewRGBA(image.Rect(0, 0, 300, 300))
|
||||||
canvas := ggfx.Image[uint8] {
|
canvas := ggfx.Image[uint8] {
|
||||||
Pix: img.Pix,
|
Pix: img.Pix,
|
||||||
Stride: img.Stride,
|
Stride: img.Stride,
|
||||||
Bounds: img.Rect,
|
Bounds: img.Rect,
|
||||||
Width: 4,
|
Width: 4,
|
||||||
}
|
}
|
||||||
canvas.FillRectangle([]uint8 { 255, 0, 0, 255 }, image.Rect(7, 4, 34, 78))
|
black := []uint8 { 0, 0, 0, 255 }
|
||||||
|
red := []uint8 { 255, 0, 0, 255 }
|
||||||
|
canvas.FillPolygon (
|
||||||
|
black,
|
||||||
|
image.Pt(10, 10),
|
||||||
|
image.Pt(70, 50),
|
||||||
|
image.Pt(20, 70))
|
||||||
|
canvas.StrokePolygon (
|
||||||
|
red, 1,
|
||||||
|
image.Pt(10, 10),
|
||||||
|
image.Pt(70, 50),
|
||||||
|
image.Pt(20, 70))
|
||||||
|
|
||||||
file, err := os.Create("TEST.png")
|
file, err := os.Create("TEST.png")
|
||||||
if err != nil { panic(err.Error()) }
|
if err != nil { panic(err.Error()) }
|
||||||
|
34
polygon.go
34
polygon.go
@ -14,10 +14,11 @@ func (this Image[T]) FillPolygon (fill []T, points ...image.Point) {
|
|||||||
for _, point := range points[1:] {
|
for _, point := range points[1:] {
|
||||||
if point.X < area.Min.X { area.Min.X = point.X }
|
if point.X < area.Min.X { area.Min.X = point.X }
|
||||||
if point.Y < area.Min.Y { area.Min.Y = point.Y }
|
if point.Y < area.Min.Y { area.Min.Y = point.Y }
|
||||||
if point.X < area.Max.X { area.Max.X = point.X }
|
if point.X > area.Max.X { area.Max.X = point.X }
|
||||||
if point.Y < area.Max.Y { area.Max.Y = point.Y }
|
if point.Y > area.Max.Y { area.Max.Y = point.Y }
|
||||||
}
|
}
|
||||||
area = this.Bounds.Intersect(area)
|
area = this.Bounds.Intersect(area)
|
||||||
|
if area.Empty() { return }
|
||||||
|
|
||||||
// this algorithm is adapted from:
|
// this algorithm is adapted from:
|
||||||
// https://www.alienryderflex.com/polygon_fill/
|
// https://www.alienryderflex.com/polygon_fill/
|
||||||
@ -28,30 +29,35 @@ func (this Image[T]) FillPolygon (fill []T, points ...image.Point) {
|
|||||||
boundaryCount := 0
|
boundaryCount := 0
|
||||||
prevPoint := points[len(points) - 1]
|
prevPoint := points[len(points) - 1]
|
||||||
for _, point := range points {
|
for _, point := range points {
|
||||||
|
fy := float64(y)
|
||||||
|
fPointX := float64(point.X)
|
||||||
|
fPointY := float64(point.Y)
|
||||||
|
fPrevX := float64(prevPoint.X)
|
||||||
|
fPrevY := float64(prevPoint.Y)
|
||||||
addboundary :=
|
addboundary :=
|
||||||
point.Y < y && prevPoint.Y >= y ||
|
(fPointY < fy && fPrevY >= fy) ||
|
||||||
prevPoint.Y < y && point.Y >= y
|
(fPrevY < fy && fPointY >= fy)
|
||||||
if addboundary {
|
if addboundary {
|
||||||
boundaries[boundaryCount] =
|
boundaries[boundaryCount] = int (
|
||||||
point.X +
|
fPointX +
|
||||||
(y - point.Y) /
|
(fy - fPointY) /
|
||||||
(prevPoint.Y - point.Y) *
|
(fPrevY - fPointY) *
|
||||||
(prevPoint.X - point.X)
|
(fPrevX - fPointX))
|
||||||
boundaryCount ++
|
boundaryCount ++
|
||||||
}
|
}
|
||||||
prevPoint = point
|
prevPoint = point
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort boundary list
|
// sort boundary list
|
||||||
boundaries = boundaries[:boundaryCount]
|
cutBoundaries := boundaries[:boundaryCount]
|
||||||
sort.Ints(boundaries)
|
sort.Ints(cutBoundaries)
|
||||||
|
|
||||||
// fill pixels between boundary pairs
|
// fill pixels between boundary pairs
|
||||||
min := area.Min.X
|
min := area.Min.X
|
||||||
max := area.Max.X
|
max := area.Max.X
|
||||||
for index := 0; index < len(boundaries); index ++ {
|
for index := 0; index < len(cutBoundaries); index += 2 {
|
||||||
left := boundaries[index]
|
left := cutBoundaries[index]
|
||||||
right := boundaries[index + 1]
|
right := cutBoundaries[index + 1]
|
||||||
|
|
||||||
// stop if we have exited the polygon
|
// stop if we have exited the polygon
|
||||||
if left >= max { break }
|
if left >= max { break }
|
||||||
|
Loading…
Reference in New Issue
Block a user