@@ -123,13 +123,12 @@ class Path
123
123
return @
124
124
125
125
-- 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 ) =>
128
127
if @hasCurve
129
128
@flatten !
130
129
if recreateBezier
131
130
@hasCurve = true
132
- @path = Path . Simplifier @path , tolerance, highestQuality , recreateBezier, angleThreshold
131
+ @path = Path . Simplifier @path , tolerance, filterNoise , recreateBezier, angleThreshold
133
132
return @
134
133
135
134
-- Move the @path by specified distance
@@ -580,7 +579,8 @@ class Path
580
579
offset : ( delta, join_type, end_type, miter_limit, arc_tolerance, preserve_collinear, reverse_solution) =>
581
580
subj = @convertToClipper !
582
581
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
584
584
return @
585
585
586
586
Path . RoundingPath = ( path, radius, inverted = false , cornerStyle = " Rounded" , rounding = " Absolute" ) ->
@@ -888,7 +888,7 @@ Path.RoundingPath = (path, radius, inverted = false, cornerStyle = "Rounded", ro
888
888
889
889
return newPath
890
890
891
- Path . Simplifier = ( points , tolerance = 0.1 , highestQuality , recreateBezier, angleThreshold) ->
891
+ Path . Simplifier = ( paths , tolerance, filterNoise , recreateBezier, angleThreshold) ->
892
892
simplifyRadialDist = ( points, sqTolerance) ->
893
893
prevPoint = points[ 1 ]
894
894
newPoints = { prevPoint}
@@ -1151,87 +1151,73 @@ Path.Simplifier = (points, tolerance = 0.1, highestQuality, recreateBezier, angl
1151
1151
tHat1 = computeLeftTangent( d, 1 )
1152
1152
tHat2 = computeRightTangent( d, nPts)
1153
1153
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) ->
1163
1154
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]}
1168
1160
1169
- b = { selected [ 1 ]}
1161
+ b = { section [ 1 ]}
1170
1162
1171
- fitCurve( b, selected , # selected , tolerance)
1163
+ fitCurve( b, section , # section , tolerance)
1172
1164
1173
- for i = 1 , # b
1165
+ for i = 2 , # b
1174
1166
insert final, b[ i]
1167
+
1168
+ return { b[ # b]}
1175
1169
1176
1170
isInRange = ( cs, ls) ->
1177
1171
if not ( cs > ls * 2 ) and not ( cs < ls / 2 )
1178
1172
return true
1179
1173
return false
1180
1174
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) ->
1182
1183
at1, at2 = angleThreshold, 360 - angleThreshold
1183
1184
final = {}
1184
1185
1185
- -- first and last points are duplicated for checks but ignored
1186
1186
insert points, 1 , points[ # points]
1187
1187
insert points, points[ 2 ]
1188
1188
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
+
1195
1192
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]
1204
1194
1205
1195
currSegmentLength = points[ i] \ distance( points[ i + 1 ] )
1206
1196
if not isInRange( currSegmentLength, lastSegmentLength)
1207
- elaborateSelected( selected, final, tolerance)
1208
- selected = {}
1197
+ section = elaborateSection( section, final, tolerance)
1209
1198
lastSegmentLength = currSegmentLength
1210
1199
continue
1211
1200
1212
1201
ang = math.abs getAngle( points[ i- 1 ] , points[ i] , points[ i+ 1 ] )
1213
1202
if ang < at1 or ang > at2
1214
- elaborateSelected( selected, final, tolerance)
1215
- selected = {}
1203
+ section = elaborateSection( section, final, tolerance)
1216
1204
lastSegmentLength = currSegmentLength
1217
1205
continue
1218
1206
1219
1207
lastSegmentLength = currSegmentLength
1220
1208
1221
- elaborateSelected( selected, final, tolerance)
1222
1209
return final
1223
1210
1224
- for i = 1 , # points
1211
+ for i = 1 , # paths
1212
+ if filterNoise
1213
+ paths[ i] = simplifyRadialDist( paths[ i] , tolerance)
1214
+
1225
1215
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)
1228
1217
else
1229
1218
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
1236
1222
1237
1223
{ : Path }
0 commit comments