@@ -123,13 +123,12 @@ class Path
123123 return @
124124
125125 -- Simplifies the number of path points
126- simplify : ( tolerance = 0.5 , highestQuality = true , recreateBezier = true , angleThreshold = 170 ) =>
127- @cleanContours !
126+ simplify : ( tolerance = 0.5 , filterNoise = true , recreateBezier = true , angleThreshold = 170 ) =>
128127 if @hasCurve
129128 @flatten !
130129 if recreateBezier
131130 @hasCurve = true
132- @path = Path . Simplifier @path , tolerance, highestQuality , recreateBezier, angleThreshold
131+ @path = Path . Simplifier @path , tolerance, filterNoise , recreateBezier, angleThreshold
133132 return @
134133
135134 -- Move the @path by specified distance
@@ -580,7 +579,8 @@ class Path
580579 offset : ( delta, join_type, end_type, miter_limit, arc_tolerance, preserve_collinear, reverse_solution) =>
581580 subj = @convertToClipper !
582581 subj = subj\ inflate delta, join_type, end_type, miter_limit, arc_tolerance, preserve_collinear, reverse_solution
583- @path = Path . convertFromClipper( subj) . path
582+ result = Path . convertFromClipper( subj) . path
583+ @path = Path . Simplifier result, 0.1 , true , false
584584 return @
585585
586586Path . RoundingPath = ( path, radius, inverted = false , cornerStyle = " Rounded" , rounding = " Absolute" ) ->
@@ -888,7 +888,7 @@ Path.RoundingPath = (path, radius, inverted = false, cornerStyle = "Rounded", ro
888888
889889 return newPath
890890
891- Path . Simplifier = ( points , tolerance = 0.1 , highestQuality , recreateBezier, angleThreshold) ->
891+ Path . Simplifier = ( paths , tolerance, filterNoise , recreateBezier, angleThreshold) ->
892892 simplifyRadialDist = ( points, sqTolerance) ->
893893 prevPoint = points[ 1 ]
894894 newPoints = { prevPoint}
@@ -1151,87 +1151,73 @@ Path.Simplifier = (points, tolerance = 0.1, highestQuality, recreateBezier, angl
11511151 tHat1 = computeLeftTangent( d, 1 )
11521152 tHat2 = computeRightTangent( d, nPts)
11531153 fitCubic( b, d, 1 , nPts, tHat1, tHat2, _error)
1154-
1155- getAngle = ( p1, p2, p3) ->
1156- x1, y1 = p1. x, p1. y
1157- x2, y2 = p2. x, p2. y
1158- x3, y3 = p3. x, p3. y
1159- angle = math.atan2 ( y3 - y2, x3 - x2) - math.atan2 ( y1 - y2, x1 - x2)
1160- return math.deg ( angle)
1161-
1162- elaborateSelected = ( selected, final, tolerance) ->
11631154
1164- if # selected <= 4
1165- for i = 1 , # selected
1166- insert final, selected[ i]
1167- return
1155+ elaborateSection = ( section, final, tolerance) ->
1156+ if # section <= 4
1157+ for i = 2 , # section
1158+ insert final, section[ i]
1159+ return { section[ # section]}
11681160
1169- b = { selected [ 1 ]}
1161+ b = { section [ 1 ]}
11701162
1171- fitCurve( b, selected , # selected , tolerance)
1163+ fitCurve( b, section , # section , tolerance)
11721164
1173- for i = 1 , # b
1165+ for i = 2 , # b
11741166 insert final, b[ i]
1167+
1168+ return { b[ # b]}
11751169
11761170 isInRange = ( cs, ls) ->
11771171 if not ( cs > ls * 2 ) and not ( cs < ls / 2 )
11781172 return true
11791173 return false
11801174
1181- simplify = ( points, tolerance, angleThreshold) ->
1175+ getAngle = ( p1, p2, p3) ->
1176+ x1, y1 = p1. x, p1. y
1177+ x2, y2 = p2. x, p2. y
1178+ x3, y3 = p3. x, p3. y
1179+ angle = math.atan2 ( y3 - y2, x3 - x2) - math.atan2 ( y1 - y2, x1 - x2)
1180+ return math.deg ( angle)
1181+
1182+ simplifyBezier = ( points, tolerance, angleThreshold) ->
11821183 at1, at2 = angleThreshold, 360 - angleThreshold
11831184 final = {}
11841185
1185- -- first and last points are duplicated for checks but ignored
11861186 insert points, 1 , points[ # points]
11871187 insert points, points[ 2 ]
11881188
1189- lastSegmentLength = 0
1190- selected = { points[ 1 ]}
1191- -- the current work around to remove duplicated points
1192- -- close the contour by duplicating the first point
1193- -- in this foor loop is possible to change to #points - 2
1194- -- if you want to have an open contour
1189+ lastSegmentLength = points[ 1 ] \ distance( points[ 2 ] )
1190+ section = { points[ 1 ]}
1191+
11951192 for i = 2 , # points - 1
1196-
1197- -- first point must not be a control point
1198- if i == 2
1199- lastSegmentLength = points[ 2 ] \ distance( points[ 3 ] )
1200- points[ i] . id = " l"
1201- selected = { points[ i]}
1202- continue
1203- insert selected, points[ i]
1193+ insert section, points[ i]
12041194
12051195 currSegmentLength = points[ i] \ distance( points[ i + 1 ] )
12061196 if not isInRange( currSegmentLength, lastSegmentLength)
1207- elaborateSelected( selected, final, tolerance)
1208- selected = {}
1197+ section = elaborateSection( section, final, tolerance)
12091198 lastSegmentLength = currSegmentLength
12101199 continue
12111200
12121201 ang = math.abs getAngle( points[ i- 1 ] , points[ i] , points[ i+ 1 ] )
12131202 if ang < at1 or ang > at2
1214- elaborateSelected( selected, final, tolerance)
1215- selected = {}
1203+ section = elaborateSection( section, final, tolerance)
12161204 lastSegmentLength = currSegmentLength
12171205 continue
12181206
12191207 lastSegmentLength = currSegmentLength
12201208
1221- elaborateSelected( selected, final, tolerance)
12221209 return final
12231210
1224- for i = 1 , # points
1211+ for i = 1 , # paths
1212+ if filterNoise
1213+ paths[ i] = simplifyRadialDist( paths[ i] , tolerance)
1214+
12251215 if recreateBezier
1226- points[ i] = simplifyRadialDist( points[ i] , 0.5 ) -- from 0.5 to 1
1227- points[ i] = simplify( points[ i] , tolerance, angleThreshold)
1216+ paths[ i] = simplifyBezier( paths[ i] , tolerance, angleThreshold)
12281217 else
12291218 sqTolerance = tolerance * tolerance
1230- if not highestQuality
1231- points[ i] = simplifyRadialDist( points[ i] , sqTolerance)
1232-
1233- points[ i] = simplifyDouglasPeucker( points[ i] , sqTolerance)
1234-
1235- return points
1219+ paths[ i] = simplifyDouglasPeucker( paths[ i] , sqTolerance)
1220+
1221+ return paths
12361222
12371223{ : Path }
0 commit comments