From 1f847e76cf16c65da3a226b709901af0513d70cf Mon Sep 17 00:00:00 2001 From: glenzli Date: Mon, 27 Apr 2020 00:28:34 +0800 Subject: [PATCH] fix null path error on offsetStroke --- demo/debug.js | 3 +++ demo/paperjs-offset.js | 34 ++++++++++++++++++------------ demo/paperjs-offset.min.js | 2 +- src/index.ts | 2 +- src/{Offset.ts => offset_core.ts} | 35 +++++++++++++++++++------------ 5 files changed, 48 insertions(+), 28 deletions(-) rename src/{Offset.ts => offset_core.ts} (95%) diff --git a/demo/debug.js b/demo/debug.js index a9d0f36..4026928 100644 --- a/demo/debug.js +++ b/demo/debug.js @@ -17,6 +17,9 @@ cc.translate(new paper.Point(-100, -100)); PaperOffset.offset(cc, 24); + + const c = new paper.Path({pathData: "M4,11L5,13", strokeColor: 'rgba(156, 104, 193, 0.5)', strokeWidth: 4}); + PaperOffset.offsetStroke(c, 10, {cap: "round", join: "round"}); } window.onload = DebugCase; diff --git a/demo/paperjs-offset.js b/demo/paperjs-offset.js index bea5a93..23bcbe8 100644 --- a/demo/paperjs-offset.js +++ b/demo/paperjs-offset.js @@ -177,17 +177,19 @@ } /** Remove self intersection when offset is negative by point direction dectection. */ function removeIntersection(path) { - var newPath = path.unite(path, { insert: false }); - if (newPath instanceof paper.CompoundPath) { - newPath.children.filter(function (c) { - if (c.segments.length > 1) { - return !isSameDirection(c, path); - } - else { - return true; - } - }).forEach(function (c) { return c.remove(); }); - return reduceSingleChildCompoundPath(newPath); + if (path.closed) { + var newPath = path.unite(path, { insert: false }); + if (newPath instanceof paper.CompoundPath) { + newPath.children.filter(function (c) { + if (c.segments.length > 1) { + return !isSameDirection(c, path); + } + else { + return true; + } + }).forEach(function (c) { return c.remove(); }); + return reduceSingleChildCompoundPath(newPath); + } } return path; } @@ -292,8 +294,14 @@ return final; } } + function getNonSelfItersectionPath(path) { + if (path.closed) { + return path.unite(path, { insert: false }); + } + return path; + } function offsetPath(path, offset, join, limit) { - var nonSIPath = path.unite(path, { insert: false }); + var nonSIPath = getNonSelfItersectionPath(path); var result = nonSIPath; if (nonSIPath instanceof paper.Path) { result = offsetSimpleShape(nonSIPath, offset, join, limit); @@ -329,7 +337,7 @@ return result; } function offsetStroke(path, offset, join, cap, limit) { - var nonSIPath = path.unite(path, { insert: false }); + var nonSIPath = getNonSelfItersectionPath(path); var result = nonSIPath; if (nonSIPath instanceof paper.Path) { result = offsetSimpleStroke(nonSIPath, offset, join, cap, limit); diff --git a/demo/paperjs-offset.min.js b/demo/paperjs-offset.min.js index 0cf9172..51a8ec0 100644 --- a/demo/paperjs-offset.min.js +++ b/demo/paperjs-offset.min.js @@ -1 +1 @@ -!function(S){"use strict";function g(e,t,n,r){var o=e.curve===t,i=t.getNormalAtTime(o?0:1).multiply(r),a=e.point.add(i),s=new S.Segment(a),c=o?"handleOut":"handleIn";return s[c]=e[c].add(n.subtract(i).divide(2)),s}function T(e,t){return e.x*t.y-e.y*t.x}function v(e,t,n,r,o,i){var a,s,c,u,f,l,d,h,p,m,g,v,w,P,b=new S.Curve(e[0],e[1]),k=new S.Curve(t[0],t[1]),C=b.getIntersections(k),y=e[1].point.getDistance(t[0].point);if(n.isSmooth())t[0].handleOut=t[0].handleOut.project(n.handleOut),t[0].handleIn=e[1].handleIn.project(n.handleIn),t[0].point=e[1].point.add(t[0].point).divide(2),e.pop();else if(0===C.length)if(y>.1*Math.abs(o))switch(r){case"miter":var A=(d=b.point2,h=b.point2.add(b.getTangentAtTime(1)),p=k.point1,m=k.point1.add(k.getTangentAtTime(0)),g=d.subtract(h),v=p.subtract(m),w=T(d,h),P=T(p,m),new S.Point(w*v.x-g.x*P,w*v.y-g.y*P).divide(T(g,v)));Math.max(A.getDistance(b.point2),A.getDistance(k.point1))s){var u=t.divideAtTime(.5);if(null!=u)return e(t,n).concat(e(u,n))}}return[o,i]}(e,t)}).flat(),f=[],l=0;l.1*Math.abs(o))switch(r){case"miter":var A=(d=b.point2,h=b.point2.add(b.getTangentAtTime(1)),p=k.point1,m=k.point1.add(k.getTangentAtTime(0)),g=d.subtract(h),v=p.subtract(m),w=T(d,h),P=T(p,m),new S.Point(w*v.x-g.x*P,w*v.y-g.y*P).divide(T(g,v)));Math.max(A.getDistance(b.point2),A.getDistance(k.point1))s){var u=t.divideAtTime(.5);if(null!=u)return e(t,n).concat(e(u,n))}}return[o,i]}(e,t)}).flat(),f=[],l=0;l { - if (c.segments.length > 1) { - return !isSameDirection(c, path); - } else { - return true; - } - }).forEach((c) => c.remove()); - return reduceSingleChildCompoundPath(newPath); + if (path.closed) { + const newPath = path.unite(path, { insert: false }) as PathType; + if (newPath instanceof paper.CompoundPath) { + (newPath.children as paper.Path[]).filter((c) => { + if (c.segments.length > 1) { + return !isSameDirection(c, path); + } else { + return true; + } + }).forEach((c) => c.remove()); + return reduceSingleChildCompoundPath(newPath); + } } return path; } @@ -306,8 +308,15 @@ function offsetSimpleStroke(path: paper.Path, offset: number, join: StrokeJoinTy } } +function getNonSelfItersectionPath(path: PathType) { + if (path.closed) { + return path.unite(path, { insert: false }) as PathType; + } + return path; +} + export function offsetPath(path: PathType, offset: number, join: StrokeJoinType, limit: number): PathType { - const nonSIPath = path.unite(path, { insert: false }) as PathType; + const nonSIPath = getNonSelfItersectionPath(path); let result = nonSIPath; if (nonSIPath instanceof paper.Path) { result = offsetSimpleShape(nonSIPath, offset, join, limit); @@ -341,8 +350,8 @@ export function offsetPath(path: PathType, offset: number, join: StrokeJoinType, } export function offsetStroke(path: PathType, offset: number, join: StrokeJoinType, cap: StrokeCapType, limit: number): PathType { - const nonSIPath = path.unite(path, { insert: false }) as PathType; - let result = nonSIPath as PathType; + const nonSIPath = getNonSelfItersectionPath(path); + let result = nonSIPath; if (nonSIPath instanceof paper.Path) { result = offsetSimpleStroke(nonSIPath, offset, join, cap, limit); } else {