From 50c77477c92a3be6c08099c216b673c9fa0f3df7 Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Sat, 1 Feb 2020 16:21:00 +0100 Subject: [PATCH] another triangulation bugfix, points should be considered inside the polygon if they are on a line, with a small amount of tolerance --- paths.go | 9 +++++++++ triangulation.go | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/paths.go b/paths.go index 9cc8aa7..fc567b5 100644 --- a/paths.go +++ b/paths.go @@ -357,6 +357,15 @@ func lineIntersection(a0, a1, b0, b1 vec) (vec, float64, float64) { return a0.add(va.mulf(p)), p, q } +func linePointDistSqr(a, b, p vec) float64 { + v := b.sub(a) + vl := v.len() + vn := v.divf(vl) + d := p.sub(a).dot(vn) + c := a.add(vn.mulf(d)) + return p.sub(c).lenSqr() +} + // Fill fills the current path with the current FillStyle func (cv *Canvas) Fill() { cv.fillPath(&cv.path, matIdentity()) diff --git a/triangulation.go b/triangulation.go index 369e06f..ba20a9c 100644 --- a/triangulation.go +++ b/triangulation.go @@ -72,6 +72,13 @@ func triangleContainsPoint(a, b, c, p vec) bool { return count == 1 } +const parallelTolerance = 1e-10 + +func parallel(a1, b1, a2, b2 vec) bool { + ang := b1.sub(a1).angleTo(b2.sub(a2)) + return math.Abs(ang) < parallelTolerance || math.Abs(ang-math.Pi) < parallelTolerance +} + func polygonContainsLine(polygon []vec, ia, ib int, a, b vec) bool { for i := range polygon { if i == ia || i == ib { @@ -89,6 +96,8 @@ func polygonContainsLine(polygon []vec, ia, ib int, a, b vec) bool { return true } +const onLineToleranceSqr = 1e-20 + func polygonContainsPoint(polygon []vec, p vec) bool { a := polygon[len(polygon)-1] count := 0 @@ -96,6 +105,9 @@ func polygonContainsPoint(polygon []vec, p vec) bool { if r, _ := pointIsRightOfLine(a, b, p); r { count++ } + if linePointDistSqr(a, b, p) < onLineToleranceSqr { + return true + } a = b } return count%2 == 1 @@ -129,6 +141,9 @@ func triangulatePath(path []pathPoint, mat mat, target [][2]float64) [][2]float6 if !polygonContainsLine(polygon, i, ic, a, c) { continue } + if parallel(a, b, b, c) { + continue + } target = append(target, a, b, c) break }