svg-path-simplify 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +10 -0
  2. package/dist/svg-path-simplify.esm.js +3935 -1441
  3. package/dist/svg-path-simplify.esm.min.js +13 -1
  4. package/dist/svg-path-simplify.js +3953 -1459
  5. package/dist/svg-path-simplify.min.js +13 -1
  6. package/dist/svg-path-simplify.min.js.gz +0 -0
  7. package/dist/svg-path-simplify.poly.cjs +0 -1
  8. package/index.html +69 -31
  9. package/package.json +5 -9
  10. package/src/constants.js +3 -0
  11. package/src/index-node.js +0 -1
  12. package/src/index-poly.js +0 -1
  13. package/src/index.js +26 -0
  14. package/src/pathData_simplify_cubic.js +75 -46
  15. package/src/pathData_simplify_cubicsToArcs.js +566 -0
  16. package/src/pathData_simplify_harmonize_cpts.js +170 -0
  17. package/src/pathData_simplify_revertToquadratics.js +21 -0
  18. package/src/pathSimplify-main.js +274 -61
  19. package/src/poly-fit-curve-schneider.js +570 -0
  20. package/src/simplify_poly_RDP.js +146 -0
  21. package/src/simplify_poly_radial_distance.js +100 -0
  22. package/src/svg_getViewbox.js +28 -15
  23. package/src/svgii/geometry.js +389 -63
  24. package/src/svgii/geometry_area.js +2 -1
  25. package/src/svgii/pathData_analyze.js +259 -212
  26. package/src/svgii/pathData_convert.js +91 -663
  27. package/src/svgii/pathData_fromPoly.js +12 -0
  28. package/src/svgii/pathData_parse.js +90 -89
  29. package/src/svgii/pathData_parse_els.js +3 -0
  30. package/src/svgii/pathData_parse_fontello.js +449 -0
  31. package/src/svgii/pathData_remove_collinear.js +44 -37
  32. package/src/svgii/pathData_reorder.js +2 -1
  33. package/src/svgii/pathData_simplify_redraw.js +343 -0
  34. package/src/svgii/pathData_simplify_refineCorners.js +18 -9
  35. package/src/svgii/pathData_simplify_refineExtremes.js +19 -78
  36. package/src/svgii/pathData_split.js +42 -45
  37. package/src/svgii/pathData_toPolygon.js +130 -4
  38. package/src/svgii/pathData_transform_scale.js +51 -0
  39. package/src/svgii/poly_analyze.js +470 -14
  40. package/src/svgii/poly_to_pathdata.js +224 -19
  41. package/src/svgii/rounding.js +55 -112
  42. package/src/svgii/svg_cleanup.js +13 -1
  43. package/src/svgii/visualize.js +8 -3
  44. package/{debug.cjs → tests/debug.cjs} +3 -0
  45. package/{testSVG.js → tests/testSVG.js} +1 -1
  46. /package/{test.js → tests/test.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { getCombinedByDominant } from "./pathData_simplify_cubic_extrapolate";
2
- import { getDistance, getSquareDistance, checkLineIntersection, pointAtT, getDistAv, interpolate } from "./svgii/geometry";
2
+ import { getDistance, getSquareDistance, checkLineIntersection, pointAtT, interpolate, getDistManhattan } from "./svgii/geometry";
3
3
  import { getBezierArea, getPolygonArea } from "./svgii/geometry_area";
4
4
  import { renderPoint } from "./svgii/visualize";
5
5
 
@@ -22,10 +22,11 @@ export function simplifyPathDataCubic(pathData, {
22
22
  let typeN = comN?.type || null;
23
23
  //let isCornerN = comN?.corner || null;
24
24
  //let isExtremeN = comN?.extreme || null;
25
- let isDirChange = com?.directionChange || null;
26
- let isDirChangeN = comN?.directionChange || null;
27
25
 
28
- let { type, values, p0, p, cp1 = null, cp2 = null, extreme = false, corner = false, dimA = 0 } = com;
26
+ let { type, values, p0, p, cp1 = null, cp2 = null, extreme = false, directionChange = false, corner = false, dimA = 0 } = com;
27
+
28
+ //let isDirChange = com?.directionChange || null;
29
+ //let isDirChangeN = comN?.directionChange || null;
29
30
 
30
31
 
31
32
  // next is also cubic
@@ -33,9 +34,10 @@ export function simplifyPathDataCubic(pathData, {
33
34
 
34
35
  // cannot be combined as crossing extremes or corners
35
36
  if (
36
- (keepInflections && isDirChangeN) ||
37
+ //(keepInflections && isDirChangeN) ||
37
38
  (keepCorners && corner) ||
38
- (!isDirChange && keepExtremes && extreme)
39
+ //(!isDirChange && keepExtremes && extreme)
40
+ (keepExtremes && extreme)
39
41
  ) {
40
42
  //renderPoint(markers, p, 'red', '1%')
41
43
  pathDataN.push(com)
@@ -44,9 +46,12 @@ export function simplifyPathDataCubic(pathData, {
44
46
  // try simplification
45
47
  else {
46
48
  //renderPoint(markers, p, 'magenta', '1%')
47
- let combined = combineCubicPairs(com, comN, {tolerance})
49
+ let combined = combineCubicPairs(com, comN, { tolerance })
48
50
  let error = 0;
49
51
 
52
+ //!count simplification success or failure - just for debugging
53
+ //let log = [];
54
+
50
55
  // combining successful! try next segment
51
56
  if (combined.length === 1) {
52
57
  com = combined[0]
@@ -54,15 +59,16 @@ export function simplifyPathDataCubic(pathData, {
54
59
 
55
60
  // add cumulative error to prevent distortions
56
61
  error += com.error;
57
- //console.log('!error', error);
62
+
63
+ //!log.push(`success1: ${i} and ${i + 1}`)
58
64
 
59
65
  // find next candidates
60
- //offset<2 &&
61
66
  for (let n = i + 1; error < tolerance && n < l; n++) {
62
67
  let comN = pathData[n]
68
+
63
69
  if (comN.type !== 'C' ||
64
70
  (
65
- (keepInflections && comN.directionChange) ||
71
+ (keepInflections && com.directionChange) ||
66
72
  (keepCorners && com.corner) ||
67
73
  (keepExtremes && com.extreme)
68
74
  )
@@ -70,20 +76,33 @@ export function simplifyPathDataCubic(pathData, {
70
76
  break
71
77
  }
72
78
 
73
- let combined = combineCubicPairs(com, comN, {tolerance})
74
- if (combined.length === 1) {
75
- // add cumulative error to prevent distortions
76
- //console.log('combined', combined);
77
- error += combined[0].error * 0.5;
78
- //error += combined[0].error * 1;
79
- offset++
79
+ let combined = combineCubicPairs(com, comN, { tolerance })
80
+
81
+ // failure - could not be combined - exit loop
82
+ if (combined.length > 1) {
83
+ //log.push(`fail: ${i} and ${n}`)
84
+ break
80
85
  }
86
+
87
+ /**
88
+ * success
89
+ * add cumulative error to prevent distortions
90
+ */
91
+ error += combined[0].error * 0.5;
92
+ offset++
93
+
94
+ //!log.push(`success2: ${i} and ${n}`)
95
+
96
+ // return combined
81
97
  com = combined[0]
82
98
  }
83
99
 
100
+ //console.log('tests', log, offset);
101
+
84
102
  //com.opt = true
85
103
  pathDataN.push(com)
86
104
 
105
+ // skip to next candidates
87
106
  if (i < l) {
88
107
  i += offset
89
108
  }
@@ -118,12 +137,15 @@ export function combineCubicPairs(com1, com2, {
118
137
  // assume 2 segments are result of a segment split
119
138
  let t = findSplitT(com1, com2);
120
139
 
121
- let distAv1 = getDistAv(com1.p0, com1.p);
122
- let distAv2 = getDistAv(com2.p0, com2.p);
140
+ // quit if t is start
141
+ if (!t) return commands;
142
+
143
+ let distAv1 = getDistManhattan(com1.p0, com1.p);
144
+ let distAv2 = getDistManhattan(com2.p0, com2.p);
123
145
  let distMin = Math.max(0, Math.min(distAv1, distAv2))
124
146
 
125
147
 
126
- let distScale = 0.06
148
+ let distScale = 0.08
127
149
  let maxDist = distMin * distScale * tolerance
128
150
 
129
151
  // get hypothetical combined command
@@ -133,7 +155,7 @@ export function combineCubicPairs(com1, com2, {
133
155
  let pt = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t)
134
156
 
135
157
 
136
- let dist0 = getDistAv(com1.p, pt)
158
+ let dist0 = getDistManhattan(com1.p, pt)
137
159
  let dist1 = 0, dist2 = 0;
138
160
  let close = dist0 < maxDist;
139
161
  let success = false;
@@ -142,7 +164,6 @@ export function combineCubicPairs(com1, com2, {
142
164
  let error = dist0;
143
165
 
144
166
 
145
-
146
167
  if (close) {
147
168
 
148
169
  /**
@@ -156,15 +177,10 @@ export function combineCubicPairs(com1, com2, {
156
177
  // simplified path
157
178
  let t3 = (1 + t) * 0.5;
158
179
  let ptS_2 = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t3)
159
- dist1 = getDistAv(pt_2, ptS_2)
180
+ dist1 = getDistManhattan(pt_2, ptS_2)
160
181
 
161
182
  error += dist1;
162
183
 
163
-
164
- // quit - paths not congruent
165
- //if (dist2 > tolerance) return commands;
166
-
167
-
168
184
  if (dist1 < maxDist) {
169
185
 
170
186
  //renderPoint(markers, pt_2, 'magenta')
@@ -175,22 +191,11 @@ export function combineCubicPairs(com1, com2, {
175
191
 
176
192
  let t2 = t * 0.5;
177
193
  let ptS_1 = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t2)
178
- dist2 = getDistAv(pt_1, ptS_1)
179
-
180
- /*
181
- if(dist1>tolerance){
182
- renderPoint(markers, pt_1, 'blue')
183
- renderPoint(markers, ptS_1, 'orange', '0.5%')
184
- }
185
- */
194
+ dist2 = getDistManhattan(pt_1, ptS_1)
186
195
 
187
- // quit - paths not congruent
188
- if (dist1 + dist2 < maxDist) success = true;
189
-
190
- // collect error data
191
196
  error += dist2;
192
197
 
193
- //console.log('simpl1');
198
+ if (error < maxDist) success = true;
194
199
 
195
200
  }
196
201
 
@@ -205,10 +210,11 @@ export function combineCubicPairs(com1, com2, {
205
210
  comS.p0 = com1.p0
206
211
  comS.p = com2.p
207
212
 
208
- comS.dimA = getDistAv(comS.p0, comS.p);
213
+ comS.dimA = getDistManhattan(comS.p0, comS.p);
209
214
  comS.type = 'C';
210
215
  comS.extreme = com2.extreme;
211
216
  comS.directionChange = com2.directionChange;
217
+ //comS.directionChange = com1.directionChange ? true : (com2.directionChange);
212
218
  comS.corner = com2.corner;
213
219
 
214
220
  comS.values = [comS.cp1.x, comS.cp1.y, comS.cp2.x, comS.cp2.y, comS.p.x, comS.p.y]
@@ -278,14 +284,35 @@ export function getBezierCommandArea(commands = [com1, com2], absolute = true) {
278
284
  }
279
285
 
280
286
 
287
+
281
288
  export function findSplitT(com1, com2) {
289
+ // distances between 1st and 2nd segment cpt to mid point
290
+ let l1 = getDistManhattan(com1.cp2, com1.p)
282
291
 
283
- let len3 = getDistance(com1.cp2, com1.p)
284
- let len4 = getDistance(com1.cp2, com2.cp1)
292
+ // exit for zero length control point vectors
293
+ if (l1 === 0) {
294
+ //console.log('!quit1');
295
+ return 0;
296
+ }
285
297
 
286
- let t = Math.min(len3) / len4
298
+ let l2 = getDistManhattan(com1.p, com2.cp1)
299
+ if (l2 === 0) {
300
+ //console.log('!quit2');
301
+ return 0;
302
+ }
303
+
304
+ // dist between both segments' control points
305
+ let l3 = getDistManhattan(com1.cp2, com2.cp1)
306
+
307
+ /*
308
+ // exit for zero length control point vectors
309
+ if(l1===0 || l2===0 || l1===l3 || l2===l3) {
310
+ console.log('!quit');
311
+ return 0;
312
+ }
313
+ */
287
314
 
288
- return t
315
+ return l1 / l3
289
316
  }
290
317
 
291
318
 
@@ -293,3 +320,5 @@ export function findSplitT(com1, com2) {
293
320
 
294
321
 
295
322
 
323
+
324
+