From 857e6c4e478403ee286bee6d691ab3d18ca91d55 Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Wed, 17 Apr 2019 11:31:53 +0200 Subject: [PATCH] IsPointInStroke implemented --- canvas.go | 6 ++++++ path2d.go | 27 +++++++++++++++++++++++++-- paths.go | 30 +++++++++++++++++++----------- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/canvas.go b/canvas.go index e0e8894..94cf189 100644 --- a/canvas.go +++ b/canvas.go @@ -460,3 +460,9 @@ func (cv *Canvas) SetShadowBlur(r float64) { func (cv *Canvas) IsPointInPath(x, y float64, rule pathRule) bool { return cv.path.IsPointInPath(x, y, rule) } + +// IsPointInStroke returns true if the point is in the current +// path stroke +func (cv *Canvas) IsPointInStroke(x, y float64) bool { + return cv.path.IsPointInStroke(x, y) +} diff --git a/path2d.go b/path2d.go index 1b3a26b..49e4668 100644 --- a/path2d.go +++ b/path2d.go @@ -5,6 +5,7 @@ import ( ) type Path2D struct { + cv *Canvas p []pathPoint move vec cwSum float64 @@ -28,8 +29,8 @@ const ( ) // NewPath2D creates a new Path2D and returns it -func NewPath2D() *Path2D { - return &Path2D{p: make([]pathPoint, 0, 20)} +func (cv *Canvas) NewPath2D() *Path2D { + return &Path2D{cv: cv, p: make([]pathPoint, 0, 20)} } // func (p *Path2D) AddPath(p2 *Path2D) { @@ -344,3 +345,25 @@ func (p *Path2D) IsPointInPath(x, y float64, rule pathRule) bool { }) return inside } + +// IsPointInStroke returns true if the point is in the stroke +func (p *Path2D) IsPointInStroke(x, y float64) bool { + if len(p.p) == 0 { + return false + } + + var triBuf [500][2]float64 + tris := p.cv.strokeTris(p, mat{}, false, triBuf[:0]) + + pt := vec{x, y} + + for i := 0; i < len(tris); i += 3 { + a := vec{tris[i][0], tris[i][1]} + b := vec{tris[i+1][0], tris[i+1][1]} + c := vec{tris[i+2][0], tris[i+2][1]} + if triangleContainsPoint(a, b, c, pt) { + return true + } + } + return false +} diff --git a/paths.go b/paths.go index a3be3d4..7570951 100644 --- a/paths.go +++ b/paths.go @@ -92,6 +92,20 @@ func (cv *Canvas) strokePath(path *Path2D, inv mat, doInv bool) { return } + var triBuf [500][2]float64 + tris := cv.strokeTris(path, inv, doInv, triBuf[:0]) + + cv.drawShadow2(tris, nil) + + stl := cv.backendFillStyle(&cv.state.stroke, 1) + cv.b.Fill(&stl, tris) +} + +func (cv *Canvas) strokeTris(path *Path2D, inv mat, doInv bool, target [][2]float64) [][2]float64 { + if len(path.p) == 0 { + return target + } + if doInv { for i, pt := range path.p { path.p[i].pos = pt.pos.mulMat(inv) @@ -101,9 +115,6 @@ func (cv *Canvas) strokePath(path *Path2D, inv mat, doInv bool) { dashedPath := cv.applyLineDash(path.p) - var triBuf [500][2]float64 - tris := triBuf[:0] - start := true var p0 vec for _, p := range dashedPath { @@ -131,7 +142,7 @@ func (cv *Canvas) strokePath(path *Path2D, inv mat, doInv bool) { lp0 = lp0.sub(v0) lp2 = lp2.sub(v0) case Round: - tris = cv.addCircleTris(p0, cv.state.lineWidth*0.5, tris) + target = cv.addCircleTris(p0, cv.state.lineWidth*0.5, target) } } @@ -143,24 +154,21 @@ func (cv *Canvas) strokePath(path *Path2D, inv mat, doInv bool) { lp1 = lp1.add(v0) lp3 = lp3.add(v0) case Round: - tris = cv.addCircleTris(p1, cv.state.lineWidth*0.5, tris) + target = cv.addCircleTris(p1, cv.state.lineWidth*0.5, target) } } - tris = append(tris, cv.tf(lp0), cv.tf(lp1), cv.tf(lp3), cv.tf(lp0), cv.tf(lp3), cv.tf(lp2)) + target = append(target, cv.tf(lp0), cv.tf(lp1), cv.tf(lp3), cv.tf(lp0), cv.tf(lp3), cv.tf(lp2)) if p.flags&pathAttach != 0 && cv.state.lineWidth > 1 { - tris = cv.lineJoint(p0, p1, p.next, lp0, lp1, lp2, lp3, tris) + target = cv.lineJoint(p0, p1, p.next, lp0, lp1, lp2, lp3, target) } p0 = p1 start = false } - cv.drawShadow2(tris, nil) - - stl := cv.backendFillStyle(&cv.state.stroke, 1) - cv.b.Fill(&stl, tris) + return target } func (cv *Canvas) applyLineDash(path []pathPoint) []pathPoint {