svg-path-simplify 0.0.8 → 0.0.9

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 (34) hide show
  1. package/README.md +25 -5
  2. package/dist/svg-path-simplify.esm.js +576 -494
  3. package/dist/svg-path-simplify.esm.min.js +1 -1
  4. package/dist/svg-path-simplify.js +576 -494
  5. package/dist/svg-path-simplify.min.js +1 -1
  6. package/dist/svg-path-simplify.node.js +576 -494
  7. package/dist/svg-path-simplify.node.min.js +1 -1
  8. package/index.html +86 -29
  9. package/package.json +1 -1
  10. package/src/detect_input.js +17 -10
  11. package/src/index.js +3 -0
  12. package/src/pathData_simplify_cubic.js +113 -106
  13. package/src/pathData_simplify_cubic_extrapolate.js +25 -11
  14. package/src/pathSimplify-main.js +89 -182
  15. package/src/svgii/geometry_flatness.js +29 -36
  16. package/src/svgii/pathData_analyze.js +4 -0
  17. package/src/svgii/pathData_convert.js +26 -17
  18. package/src/svgii/pathData_interpolate.js +65 -0
  19. package/src/svgii/pathData_parse.js +25 -9
  20. package/src/svgii/pathData_parse_els.js +18 -12
  21. package/src/svgii/pathData_remove_collinear.js +31 -28
  22. package/src/svgii/pathData_remove_orphaned.js +5 -4
  23. package/src/svgii/pathData_remove_zerolength.js +8 -4
  24. package/src/svgii/pathData_reorder.js +6 -2
  25. package/src/svgii/pathData_simplify_refineCorners.js +160 -0
  26. package/src/svgii/{simplify_refineExtremes.js → pathData_simplify_refineExtremes.js} +78 -43
  27. package/src/svgii/pathData_split.js +42 -15
  28. package/src/svgii/pathData_stringify.js +3 -12
  29. package/src/svgii/rounding.js +16 -14
  30. package/src/svgii/svg_cleanup.js +1 -1
  31. package/src/pathData_simplify_cubic_arr.js +0 -50
  32. package/src/svgii/simplify.js +0 -248
  33. package/src/svgii/simplify_bezier.js +0 -470
  34. package/src/svgii/simplify_linetos.js +0 -93
@@ -1,5 +1,5 @@
1
1
  import { detectInputType } from './detect_input';
2
- import { combineCubicPairs } from './pathData_simplify_cubic';
2
+ import { simplifyPathDataCubic } from './pathData_simplify_cubic';
3
3
  import { getPathDataVertices, pointAtT } from './svgii/geometry';
4
4
  import { getPolyBBox } from './svgii/geometry_bbox';
5
5
  import { analyzePathData } from './svgii/pathData_analyze';
@@ -17,9 +17,10 @@ import { pathDataToD } from './svgii/pathData_stringify';
17
17
  import { analyzePoly } from './svgii/poly_analyze';
18
18
  import { getCurvePathData } from './svgii/poly_to_pathdata';
19
19
  import { detectAccuracy } from './svgii/rounding';
20
- import { refineAdjacentExtremes } from './svgii/simplify_refineExtremes';
20
+ import { refineAdjacentExtremes } from './svgii/pathData_simplify_refineExtremes';
21
21
  import { cleanUpSVG, removeEmptySVGEls, stringifySVG } from './svgii/svg_cleanup';
22
22
  import { renderPoint } from './svgii/visualize';
23
+ import { refineRoundedCorners } from './svgii/pathData_simplify_refineCorners';
23
24
 
24
25
  export function svgPathSimplify(input = '', {
25
26
 
@@ -41,11 +42,14 @@ export function svgPathSimplify(input = '', {
41
42
 
42
43
  simplifyBezier = true,
43
44
  optimizeOrder = true,
45
+ removeZeroLength = true,
44
46
  removeColinear = true,
45
47
  flatBezierToLinetos = true,
46
48
  revertToQuadratics = true,
47
49
 
48
50
  refineExtremes = true,
51
+ refineCorners = false,
52
+
49
53
  keepExtremes = true,
50
54
  keepCorners = true,
51
55
  extrapolateDominant = true,
@@ -83,37 +87,49 @@ export function svgPathSimplify(input = '', {
83
87
  let report = {};
84
88
  let d = '';
85
89
  let mode = inputType === 'svgMarkup' ? 1 : 0;
90
+ //console.log(inputType);
86
91
 
87
92
  let paths = []
88
93
 
89
-
90
94
  /**
91
95
  * normalize input
92
96
  * switch mode
93
97
  */
94
98
 
95
99
  // original size
96
- svgSize = new Blob([input]).size;
100
+ //svgSize = new Blob([input]).size;
101
+ svgSize = input.length;
102
+
97
103
 
98
- // single path
104
+ // mode:0 – single path
99
105
  if (!mode) {
100
106
  if (inputType === 'pathDataString') {
101
107
  d = input
102
108
  } else if (inputType === 'polyString') {
103
109
  d = 'M' + input
104
110
  }
111
+ else if (inputType === 'pathData') {
112
+ d = input;
113
+
114
+ // stringify to compare lengths
115
+ //let dStr = pathDataToD(d);
116
+ let dStr = d.map(com=>{return `${com.type} ${com.values.join(' ')}`}).join(' ') ;
117
+ svgSize = dStr.length;
118
+
119
+ }
120
+
105
121
  paths.push({ d, el: null })
106
122
  }
107
- // process svg
123
+ // mode:1 – process complete svg DOM
108
124
  else {
109
125
  //sanitize
110
126
  let returnDom = true
111
127
  svg = cleanUpSVG(input, { returnDom, removeHidden, removeUnused }
112
128
  );
113
129
 
114
- if(shapesToPaths){
130
+ if (shapesToPaths) {
115
131
  let shapes = svg.querySelectorAll('polygon, polyline, line, rect, circle, ellipse');
116
- shapes.forEach(shape=>{
132
+ shapes.forEach(shape => {
117
133
  let path = shapeElToPath(shape);
118
134
  shape.replaceWith(path)
119
135
  })
@@ -126,11 +142,11 @@ export function svgPathSimplify(input = '', {
126
142
  })
127
143
  }
128
144
 
129
- //console.log(paths);
130
- //console.log('inputType', inputType, 'mode', mode);
145
+
131
146
 
132
147
  /**
133
148
  * process all paths
149
+ * try simplifications and removals
134
150
  */
135
151
 
136
152
  // SVG optimization options
@@ -143,44 +159,43 @@ export function svgPathSimplify(input = '', {
143
159
  // combinded path data for SVGs with mergePaths enabled
144
160
  let pathData_merged = [];
145
161
 
146
- paths.forEach(path => {
162
+ for (let i = 0, l = paths.length; l && i < l; i++) {
163
+
164
+ let path = paths[i];
147
165
  let { d, el } = path;
148
166
 
149
- ///let t0 = performance.now()
150
- let pathDataO = parsePathDataNormalized(d, { quadraticToCubic, toAbsolute, arcToCubic });
151
- //console.log('pathDataO', pathDataO);
167
+ let pathData = parsePathDataNormalized(d, { quadraticToCubic, toAbsolute, arcToCubic });
152
168
 
153
169
  // count commands for evaluation
154
- let comCount = pathDataO.length
170
+ let comCount = pathData.length
155
171
 
156
172
 
157
- // create clone for fallback
158
- //let pathData = JSON.parse(JSON.stringify(pathDataO));
159
- let pathData = pathDataO;
160
- //let t1 = performance.now() - t0;
161
- //console.log('t1', t1);
162
-
163
-
164
- if(removeOrphanSubpaths) pathData = removeOrphanedM(pathData);
173
+ if (removeOrphanSubpaths) pathData = removeOrphanedM(pathData);
165
174
 
166
175
  /**
167
176
  * get sub paths
168
177
  */
169
178
  let subPathArr = splitSubpaths(pathData);
179
+ let lenSub = subPathArr.length;
180
+
170
181
 
171
182
  // cleaned up pathData
172
- let pathDataArrN = [];
183
+ //let pathDataArrN = new Array(lenSub);
184
+
185
+ // reset array
186
+ let pathDataFlat = []
187
+
188
+ for (let i = 0; i < lenSub; i++) {
173
189
 
174
- for (let i = 0, l = subPathArr.length; i < l; i++) {
175
190
 
176
191
  //let { pathData, bb } = subPathArr[i];
177
192
  let pathDataSub = subPathArr[i];
178
193
 
179
- // try simplification in reversed order
180
- if (reverse) pathDataSub = reversePathData(pathDataSub);
181
194
 
182
195
  // remove zero length linetos
183
- if (removeColinear) pathDataSub = removeZeroLengthLinetos(pathDataSub)
196
+ if (removeColinear || removeZeroLength) pathDataSub = removeZeroLengthLinetos(pathDataSub)
197
+ //console.log(removeColinear, removeZeroLength);
198
+
184
199
 
185
200
  // add extremes
186
201
  //let tMin=0.2, tMax=0.8;
@@ -191,8 +206,10 @@ export function svgPathSimplify(input = '', {
191
206
  // sort to top left
192
207
  if (optimizeOrder) pathDataSub = pathDataToTopLeft(pathDataSub);
193
208
 
194
- // remove colinear/flat
195
- if (removeColinear) pathDataSub = pathDataRemoveColinear(pathDataSub, tolerance, flatBezierToLinetos);
209
+
210
+ // Preprocessing: remove colinear - ignore flat beziers (removed later)
211
+ if (removeColinear) pathDataSub = pathDataRemoveColinear(pathDataSub, { tolerance, flatBezierToLinetos: false });
212
+
196
213
 
197
214
  // analyze pathdata to add info about signicant properties such as extremes, corners
198
215
  let pathDataPlus = analyzePathData(pathDataSub);
@@ -200,37 +217,29 @@ export function svgPathSimplify(input = '', {
200
217
 
201
218
  // simplify beziers
202
219
  let { pathData, bb, dimA } = pathDataPlus;
203
-
204
- //let pathDataN = pathData;
205
-
206
- //console.log(pathDataPlus);
207
- //let t0=performance.now()
208
220
  pathData = simplifyBezier ? simplifyPathDataCubic(pathData, { simplifyBezier, keepInflections, keepExtremes, keepCorners, extrapolateDominant, revertToQuadratics, tolerance, reverse }) : pathData;
209
- //let t1=performance.now() - t0;
210
- //console.log('t1', t1);
211
-
212
221
 
213
222
  // refine extremes
214
- if(refineExtremes){
223
+ if (refineExtremes) {
215
224
  let thresholdEx = (bb.width + bb.height) / 2 * 0.05
216
- pathData = refineAdjacentExtremes(pathData, {threshold:thresholdEx, tolerance})
225
+ pathData = refineAdjacentExtremes(pathData, { threshold: thresholdEx, tolerance })
217
226
  }
218
227
 
219
228
 
220
229
  // cubic to arcs
221
230
  if (cubicToArc) {
222
231
 
223
- let thresh = 3;
232
+ let thresh = 1;
224
233
 
225
- pathData.forEach((com, c) => {
234
+ for(let c=0, l=pathData.length; c<l; c++){
235
+ let com = pathData[c]
226
236
  let { type, values, p0, cp1 = null, cp2 = null, p = null } = com;
227
237
  if (type === 'C') {
228
238
  //console.log(com);
229
239
  let comA = cubicCommandToArc(p0, cp1, cp2, p, thresh)
230
240
  if (comA.isArc) pathData[c] = comA.com;
231
- //if (comQ.type === 'Q') pathDataN[c] = comQ
232
241
  }
233
- })
242
+ }
234
243
 
235
244
  // combine adjacent cubics
236
245
  pathData = combineArcs(pathData)
@@ -238,22 +247,30 @@ export function svgPathSimplify(input = '', {
238
247
  }
239
248
 
240
249
 
250
+ // post processing: remove flat beziers
251
+ if (removeColinear && flatBezierToLinetos) {
252
+ pathData = pathDataRemoveColinear(pathData, { tolerance, flatBezierToLinetos });
253
+ }
254
+
255
+
256
+ // refine corners
257
+ if(refineCorners){
258
+ let threshold = (bb.width + bb.height) / 2 * 0.1
259
+ pathData = refineRoundedCorners(pathData, { threshold, tolerance })
260
+ //console.log(refineCorners);
261
+ }
241
262
 
242
263
 
243
264
 
244
265
  // simplify to quadratics
245
266
  if (revertToQuadratics) {
246
- pathData.forEach((com, c) => {
267
+ for(let c=0, l=pathData.length; c<l; c++){
268
+ let com = pathData[c]
247
269
  let { type, values, p0, cp1 = null, cp2 = null, p = null } = com;
248
270
  if (type === 'C') {
249
271
  //console.log(com);
250
272
  let comQ = revertCubicQuadratic(p0, cp1, cp2, p)
251
273
  if (comQ.type === 'Q') {
252
- /*
253
- comQ.p0 = com.p0
254
- comQ.cp1 = {x:comQ.values[0], y:comQ.values[1]}
255
- comQ.p = com.p
256
- */
257
274
  comQ.extreme = com.extreme
258
275
  comQ.corner = com.corner
259
276
  comQ.dimA = com.dimA
@@ -261,26 +278,32 @@ export function svgPathSimplify(input = '', {
261
278
  pathData[c] = comQ
262
279
  }
263
280
  }
264
- })
281
+ }
265
282
  }
266
283
 
267
- //if (removeColinear) pathDataSub = pathDataRemoveColinear(pathDataSub, tolerance, flatBezierToLinetos);
268
-
269
284
 
270
285
  // optimize close path
271
286
  if (optimizeOrder) pathData = optimizeClosePath(pathData)
272
287
 
273
- // poly
274
- //let poly = pathDataToPolySingle(pathData, true)
275
- //console.log('poly', poly);
276
-
277
288
 
278
289
  // update
279
- pathDataArrN.push(pathData)
290
+ pathDataFlat.push(...pathData)
291
+ //pathDataArrN[i]=(pathData)
292
+
280
293
  }
281
294
 
295
+
282
296
  // flatten compound paths
283
- pathData = pathDataArrN.flat();
297
+ pathData = pathDataFlat;
298
+
299
+
300
+ //console.log('pathData', pathData);
301
+
302
+ if (autoAccuracy) {
303
+ decimals = detectAccuracy(pathData)
304
+ pathOptions.decimals = decimals
305
+ //console.log('!decimals', decimals);
306
+ }
284
307
 
285
308
 
286
309
  // collect for merged svg paths
@@ -290,17 +313,6 @@ export function svgPathSimplify(input = '', {
290
313
  // single output
291
314
  else {
292
315
 
293
- /**
294
- * detect accuracy
295
- */
296
- if (autoAccuracy) {
297
- decimals = detectAccuracy(pathData)
298
- pathOptions.decimals = decimals
299
- //console.log('!decimals', decimals);
300
- }
301
-
302
- //console.log('autoAccuracy', autoAccuracy, decimals);
303
-
304
316
  // optimize path data
305
317
  pathData = convertPathData(pathData, pathOptions)
306
318
 
@@ -311,9 +323,10 @@ export function svgPathSimplify(input = '', {
311
323
  let comCountS = pathData.length
312
324
 
313
325
  let dOpt = pathDataToD(pathData, minifyD)
314
- svgSizeOpt = new Blob([dOpt]).size;
315
- compression = +(100 / svgSize * (svgSizeOpt)).toFixed(2)
326
+ //svgSizeOpt = new Blob([dOpt]).size;
327
+ svgSizeOpt = dOpt.length
316
328
 
329
+ compression = +(100 / svgSize * (svgSizeOpt)).toFixed(2)
317
330
 
318
331
  path.d = dOpt
319
332
  path.report = {
@@ -328,7 +341,7 @@ export function svgPathSimplify(input = '', {
328
341
  // apply new path for svgs
329
342
  if (el) el.setAttribute('d', dOpt)
330
343
  }
331
- });
344
+ };
332
345
 
333
346
  /**
334
347
  * stringify new SVG
@@ -336,21 +349,19 @@ export function svgPathSimplify(input = '', {
336
349
  if (mode) {
337
350
 
338
351
  if (pathData_merged.length) {
352
+
339
353
  // optimize path data
340
354
  let pathData = convertPathData(pathData_merged, pathOptions)
341
355
 
342
356
  // remove zero-length segments introduced by rounding
343
- //pathData = removeZeroLengthLinetos_post(pathData);
344
357
  pathData = removeZeroLengthLinetos(pathData);
345
358
 
346
-
347
359
  let dOpt = pathDataToD(pathData, minifyD)
348
360
 
349
361
 
350
362
  // apply new path for svgs
351
363
  paths[0].el.setAttribute('d', dOpt)
352
364
 
353
-
354
365
  // remove other paths
355
366
  for (let i = 1; i < paths.length; i++) {
356
367
  let pathEl = paths[i].el
@@ -364,7 +375,8 @@ export function svgPathSimplify(input = '', {
364
375
 
365
376
 
366
377
  svg = stringifySVG(svg);
367
- svgSizeOpt = new Blob([svg]).size
378
+ //svgSizeOpt = new Blob([svg]).size
379
+ svgSizeOpt = svg.length;
368
380
  //compression = +(100/svgSize * (svgSize-svgSizeOpt)).toFixed(2)
369
381
  compression = +(100 / svgSize * (svgSizeOpt)).toFixed(2)
370
382
 
@@ -388,110 +400,5 @@ export function svgPathSimplify(input = '', {
388
400
 
389
401
 
390
402
 
391
- function simplifyPathDataCubic(pathData, {
392
- keepExtremes = true,
393
- keepInflections = true,
394
- keepCorners = true,
395
- extrapolateDominant = true,
396
- tolerance = 1,
397
- reverse = false
398
- } = {}) {
399
-
400
- let pathDataN = [pathData[0]];
401
-
402
- for (let i = 2, l = pathData.length; l && i <= l; i++) {
403
- let com = pathData[i - 1];
404
- let comN = i < l ? pathData[i] : null;
405
- let typeN = comN?.type || null;
406
- //let isCornerN = comN?.corner || null;
407
- //let isExtremeN = comN?.extreme || null;
408
- let isDirChange = com?.directionChange || null;
409
- let isDirChangeN = comN?.directionChange || null;
410
-
411
- let { type, values, p0, p, cp1 = null, cp2 = null, extreme = false, corner = false, dimA = 0 } = com;
412
-
413
- // count simplifications
414
- let success = 0;
415
-
416
- // next is also cubic
417
- if (type === 'C' && typeN === 'C') {
418
-
419
- // cannot be combined as crossing extremes or corners
420
- if (
421
- (keepInflections && isDirChangeN) ||
422
- (keepCorners && corner) ||
423
- (!isDirChange && keepExtremes && extreme)
424
- ) {
425
- //renderPoint(markers, p, 'red', '1%')
426
- pathDataN.push(com)
427
- }
428
-
429
- // try simplification
430
- else {
431
- //renderPoint(markers, p, 'magenta', '1%')
432
- let combined = combineCubicPairs(com, comN, extrapolateDominant, tolerance)
433
- let error = 0;
434
-
435
- // combining successful! try next segment
436
- if (combined.length === 1) {
437
- com = combined[0]
438
- let offset = 1;
439
-
440
- // add cumulative error to prevent distortions
441
- error += com.error;
442
- //console.log('!error', error);
443
-
444
- // find next candidates
445
- for (let n = i + 1; error < tolerance && n < l; n++) {
446
- let comN = pathData[n]
447
- if (comN.type !== 'C' ||
448
- (
449
- (keepInflections && comN.directionChange) ||
450
- (keepCorners && com.corner) ||
451
- (keepExtremes && com.extreme)
452
- )
453
- ) {
454
- break
455
- }
456
-
457
- let combined = combineCubicPairs(com, comN, extrapolateDominant, tolerance)
458
- if (combined.length === 1) {
459
- // add cumulative error to prevent distortions
460
- //console.log('combined', combined);
461
- error += combined[0].error * 0.5;
462
- //error += combined[0].error * 1;
463
- offset++
464
- }
465
- com = combined[0]
466
- }
467
-
468
- //com.opt = true
469
- pathDataN.push(com)
470
-
471
- if (i < l) {
472
- i += offset
473
- }
474
-
475
- } else {
476
- pathDataN.push(com)
477
- }
478
- }
479
-
480
- } // end of bezier command
481
-
482
-
483
- // other commands
484
- else {
485
- pathDataN.push(com)
486
- }
487
-
488
- } // end command loop
489
-
490
- // reverse back
491
- if (reverse) pathDataN = reversePathData(pathDataN)
492
-
493
- return pathDataN
494
- }
495
-
496
403
 
497
404
 
@@ -1,53 +1,46 @@
1
1
  import { getSquareDistance } from "./geometry";
2
2
  import { getPolygonArea } from "./geometry_area";
3
3
 
4
- export function commandIsFlat(points, tolerance = 0.025) {
4
+ export function commandIsFlat(points, {
5
+ tolerance = 1,
6
+ debug=false
7
+ } = {}) {
8
+
9
+ let isFlat=false;
10
+ let report = {
11
+ flat:true,
12
+ steepness:0
13
+ }
5
14
 
6
15
  let p0 = points[0];
7
16
  let p = points[points.length - 1];
8
17
 
9
- let xArr = points.map(pt => { return pt.x })
10
- let yArr = points.map(pt => { return pt.y })
11
-
12
- let xMin = Math.min(...xArr)
13
- let xMax = Math.max(...xArr)
14
- let yMin = Math.min(...yArr)
15
- let yMax = Math.max(...yArr)
16
- let w = xMax - xMin
17
- let h = yMax - yMin
18
+ let xSet = new Set([...points.map(pt => +pt.x.toFixed(8))])
19
+ let ySet = new Set([...points.map(pt => +pt.y.toFixed(8))])
18
20
 
19
21
 
20
- if (points.length < 3 || (w === 0 || h === 0)) {
21
- return { area: 0, flat: true, thresh: 0.0001, ratio: 0 };
22
- }
22
+ // must be flat
23
+ if(xSet.size===1 || ySet.size===1) return !debug ? true : report;
23
24
 
24
25
  let squareDist = getSquareDistance(p0, p)
25
- let squareDist1 = getSquareDistance(p0, points[0])
26
- let squareDist2 = points.length > 3 ? getSquareDistance(p, points[1]) : squareDist1;
27
- let squareDistAvg = (squareDist1 + squareDist2) / 2
28
-
29
- tolerance = 0.5;
30
- let thresh = (w + h) * 0.5 * tolerance;
31
-
32
- //let thresh = tolerance;
26
+ let threshold = squareDist / 1000 * tolerance
33
27
  let area = getPolygonArea(points, true)
34
28
 
29
+ // flat enough
30
+ if(area < threshold) isFlat = true;
35
31
 
36
- let diff = Math.abs(area - squareDist);
37
- let areaDiff = Math.abs(100 - (100 / area * (area + diff)))
38
- let areaThresh = 1000
39
-
40
- //let ratio = area / (squareDistAvg/areaThresh);
41
- let ratio = area / (squareDistAvg);
42
-
43
-
44
- let isFlat = area === 0 ? true : area < squareDistAvg / areaThresh;
45
-
32
+ if(debug){
33
+ report.flat = isFlat;
34
+ //report.steepness = area/threshold
35
+ report.steepness = area/squareDist*10
36
+ }
46
37
 
47
- return { area: area, flat: isFlat, thresh: thresh, ratio: ratio, squareDist: squareDist, areaThresh: squareDist / areaThresh };
38
+ return !debug ? isFlat : report;
48
39
  }
49
40
 
50
41
 
42
+
43
+ // deprecated
51
44
  export function checkBezierFlatness(p0, cpts, p) {
52
45
 
53
46
  let isFlat = false;
@@ -75,13 +68,13 @@ export function checkBezierFlatness(p0, cpts, p) {
75
68
 
76
69
  if (!cross0) return true
77
70
 
78
- let area = getPolygonArea([p0,...cpts, p], true)
71
+ let area = getPolygonArea([p0, ...cpts, p], true)
79
72
  let dist1 = getSquareDistance(p0, p)
80
- let thresh = dist1/200;
73
+ let thresh = dist1 / 200;
81
74
 
82
75
 
83
- // if(area<thresh) return true;
84
- isFlat = area<thresh;
76
+ // if(area<thresh) return true;
77
+ isFlat = area < thresh;
85
78
  //console.log('area', area, thresh, isFlat);
86
79
 
87
80
 
@@ -112,6 +112,7 @@ export function analyzePathData(pathData = []) {
112
112
  com.directionChange = false;
113
113
  com.closePath = false;
114
114
  com.dimA = 0;
115
+ //com.flat = false;
115
116
 
116
117
 
117
118
  /**
@@ -181,14 +182,17 @@ export function analyzePathData(pathData = []) {
181
182
  commandPts.push(p);
182
183
 
183
184
  /*
185
+ //let commandFlatness = commandIsFlat(commandPts);
184
186
  let commandFlatness = commandIsFlat(commandPts);
185
187
  isFlat = commandFlatness.flat;
186
188
  com.flat = isFlat;
187
189
 
188
190
  if (isFlat) {
189
191
  com.extreme = false;
192
+ //renderPoint(markers, p, 'red', '1%', '0.5')
190
193
  }
191
194
  */
195
+
192
196
  }
193
197
 
194
198
  /**