From a7c6f10541f723225ee33975e767c9456969658c Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Sun, 11 Feb 2018 17:28:41 +0100 Subject: [PATCH] added some code to cut the intersections in self-intersecting polygons, but didn't activate it yet since it doesn't seem to work --- paths.go | 2 +- triangulation.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/paths.go b/paths.go index 5d33f48..b37fd73 100644 --- a/paths.go +++ b/paths.go @@ -350,10 +350,10 @@ func (cv *Canvas) Fill() { } path := cv.polyPath[lastMove:] - if len(path) < 3 { return } + //path = cv.cutIntersections(path) cv.activate() diff --git a/triangulation.go b/triangulation.go index e2d1581..65be320 100644 --- a/triangulation.go +++ b/triangulation.go @@ -1,6 +1,8 @@ package canvas import ( + "sort" + "github.com/tfriedel6/lm" ) @@ -95,3 +97,60 @@ func triangulatePath(path []pathPoint, target []float32) []float32 { } return target } + +func (cv *Canvas) cutIntersections(path []pathPoint) []pathPoint { + type cut struct { + from, to int + ratio float32 + point lm.Vec2 + } + + var cutBuf [50]cut + cuts := cutBuf[:0] + + for i := 0; i < len(cv.polyPath); i++ { + a0 := cv.polyPath[(i+len(cv.polyPath)-1)%len(cv.polyPath)].pos + a1 := cv.polyPath[i].pos + for j := i + 1; j < len(cv.polyPath); j++ { + b0 := cv.polyPath[(j+len(cv.polyPath)-1)%len(cv.polyPath)].pos + b1 := cv.polyPath[j].pos + p, r := lineIntersection(a0, a1, b0, b1) + if r <= 0 || r >= 1 { + continue + } + cuts = append(cuts, cut{ + from: (i + len(cv.polyPath) - 1) % len(cv.polyPath), + to: i, + ratio: r, + point: p, + }) + cuts = append(cuts, cut{ + from: (j + len(cv.polyPath) - 1) % len(cv.polyPath), + to: j, + ratio: p.Sub(b0).Len() / b1.Sub(b0).Len(), + point: p, + }) + } + } + + if len(cuts) == 0 { + return path + } + + sort.Slice(cuts, func(i, j int) bool { + a, b := cuts[i], cuts[j] + return a.to > b.to || (a.to == b.to && a.ratio > b.ratio) + }) + + newPath := make([]pathPoint, len(path)+len(cuts)) + copy(newPath[:len(path)], path) + + for _, cut := range cuts { + copy(newPath[cut.to+1:], newPath[cut.to:]) + newPath[cut.to].next = newPath[cut.to+1].tf + newPath[cut.to].pos = cut.point + newPath[cut.to].tf = cv.tf(cut.point) + } + + return newPath +}