svg-path-simplify 0.0.7 → 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 (38) hide show
  1. package/README.md +25 -5
  2. package/dist/svg-path-simplify.esm.js +1250 -562
  3. package/dist/svg-path-simplify.esm.min.js +1 -1
  4. package/dist/svg-path-simplify.js +4756 -4068
  5. package/dist/svg-path-simplify.min.js +1 -1
  6. package/dist/svg-path-simplify.node.js +1250 -562
  7. package/dist/svg-path-simplify.node.min.js +1 -1
  8. package/index.html +89 -29
  9. package/package.json +5 -3
  10. package/src/detect_input.js +17 -10
  11. package/src/dom-polyfill.js +29 -0
  12. package/src/dom-polyfill_back.js +22 -0
  13. package/src/index.js +10 -1
  14. package/src/pathData_simplify_cubic.js +114 -143
  15. package/src/pathData_simplify_cubic_extrapolate.js +64 -35
  16. package/src/pathSimplify-main.js +113 -165
  17. package/src/svgii/geometry.js +8 -155
  18. package/src/svgii/geometry_flatness.js +94 -0
  19. package/src/svgii/pathData_analyze.js +15 -596
  20. package/src/svgii/pathData_convert.js +26 -17
  21. package/src/svgii/pathData_interpolate.js +65 -0
  22. package/src/svgii/pathData_parse.js +25 -9
  23. package/src/svgii/pathData_parse_els.js +245 -0
  24. package/src/svgii/pathData_remove_collinear.js +33 -28
  25. package/src/svgii/pathData_remove_orphaned.js +21 -0
  26. package/src/svgii/pathData_remove_zerolength.js +17 -3
  27. package/src/svgii/pathData_reorder.js +9 -3
  28. package/src/svgii/pathData_simplify_refineCorners.js +160 -0
  29. package/src/svgii/pathData_simplify_refineExtremes.js +208 -0
  30. package/src/svgii/pathData_split.js +43 -15
  31. package/src/svgii/pathData_stringify.js +3 -12
  32. package/src/svgii/rounding.js +35 -27
  33. package/src/svgii/svg_cleanup.js +4 -1
  34. package/testSVG.js +39 -0
  35. package/src/pathData_simplify_cubic_arr.js +0 -50
  36. package/src/svgii/simplify.js +0 -248
  37. package/src/svgii/simplify_bezier.js +0 -470
  38. package/src/svgii/simplify_linetos.js +0 -93
@@ -1,10 +1,12 @@
1
1
  import { splitSubpaths, addExtemesToCommand } from './pathData_split.js';
2
- import { getComThresh, commandIsFlat, getPathDataVertices, getSquareDistance } from './geometry.js';
2
+ import { getComThresh, getPathDataVertices, getSquareDistance } from './geometry.js';
3
3
  import { getPolyBBox } from './geometry_bbox.js';
4
4
 
5
5
 
6
6
  import { renderPoint, renderPath } from './visualize.js';
7
7
  import { getPolygonArea } from './geometry_area.js';
8
+ import { checkBezierFlatness, commandIsFlat } from "./geometry_flatness.js";
9
+
8
10
 
9
11
 
10
12
  export function pathDataToTopLeft(pathData) {
@@ -12,6 +14,8 @@ export function pathDataToTopLeft(pathData) {
12
14
  let len = pathData.length;
13
15
  let isClosed = pathData[len - 1].type.toLowerCase() === 'z'
14
16
 
17
+ //return pathData;
18
+
15
19
  // we can't change starting point for non closed paths
16
20
  if (!isClosed) {
17
21
  return pathData
@@ -52,6 +56,8 @@ export function optimizeClosePath(pathData, removeFinalLineto = true, reorder =
52
56
 
53
57
  let linetos = pathData.filter(com => com.type === 'L')
54
58
 
59
+ //return pathData;
60
+
55
61
 
56
62
  // check if order is ideal
57
63
  let penultimateCom = pathData[len - 2];
@@ -105,7 +111,7 @@ export function optimizeClosePath(pathData, removeFinalLineto = true, reorder =
105
111
  }
106
112
  // use top most command
107
113
  else {
108
- indices = indices.sort((a, b) => +a.y.toFixed(1) - +b.y.toFixed(1) || a.x - b.x);
114
+ indices = indices.sort((a, b) => +a.y.toFixed(8) - +b.y.toFixed(8) || a.x - b.x);
109
115
  newIndex = indices[0].index
110
116
  }
111
117
 
@@ -114,7 +120,7 @@ export function optimizeClosePath(pathData, removeFinalLineto = true, reorder =
114
120
  }
115
121
 
116
122
 
117
- M = { x: +pathData[0].values[0].toFixed(8), y: +pathData[0].values[1].toFixed(7) }
123
+ M = { x: +pathData[0].values[0].toFixed(8), y: +pathData[0].values[1].toFixed(8) }
118
124
 
119
125
  len = pathData.length
120
126
 
@@ -0,0 +1,160 @@
1
+ import { checkLineIntersection, getDistAv, interpolate, pointAtT } from "./geometry";
2
+ import { getPolygonArea } from "./geometry_area";
3
+ import { commandIsFlat } from "./geometry_flatness";
4
+ import { renderPoint } from "./visualize";
5
+
6
+ export function refineRoundedCorners(pathData, {
7
+ threshold = 0,
8
+ tolerance = 1
9
+ } = {}) {
10
+
11
+ let l = pathData.length;
12
+
13
+ // add fist command
14
+ let pathDataN = [pathData[0]]
15
+
16
+ let isClosed = pathData[l - 1].type.toLowerCase() === 'z';
17
+ let lastOff = isClosed ? 2 : 1;
18
+
19
+ let comLast = pathData[l - lastOff];
20
+ let lastIsLine = comLast.type === 'L'
21
+ let lastIsBez = comLast.type === 'C'
22
+ let firstIsLine = pathData[1].type === 'L';
23
+ let firstIsBez = pathData[1].type === 'C';
24
+
25
+ //console.log('lastIsLine', lastIsLine, 'firstIsLine', firstIsLine, 'lastIsBez', lastIsBez, 'firstIsBez', firstIsBez, 'isClosed', isClosed, 'comLast1', comLast1);
26
+
27
+ let normalizeClose = isClosed && firstIsBez;
28
+ //console.log('normalizeClose', normalizeClose);
29
+
30
+ // normalize closepath to lineto
31
+ if (normalizeClose) {
32
+ pathData[l - 1].values = pathData[0].values
33
+ pathData[l - 1].type = 'L'
34
+ lastIsLine = true
35
+ }
36
+
37
+ for (let i = 1; i < l; i++) {
38
+ let com = pathData[i];
39
+ let { type } = com;
40
+ let comN = pathData[i + 1] ? pathData[i + 1] : null;
41
+
42
+ // search small cubic segments enclosed by linetos
43
+ if ((type === 'L' && comN && comN.type === 'C') ||
44
+ (type === 'C' && comN && comN.type === 'L')
45
+
46
+ ) {
47
+ let comL0 = com;
48
+ let comL1 = null;
49
+ let comBez = [];
50
+ let offset = 0;
51
+
52
+ // start to end
53
+ if (i === 1 && firstIsBez && lastIsLine) {
54
+ comBez = [pathData[1]]
55
+ comL0 = pathData[l - 1]
56
+ comL1 = comN
57
+ //renderPoint(markers, com.p, 'orange')
58
+ }
59
+
60
+ // closing corner to start
61
+ if (isClosed && lastIsBez && firstIsLine && i === l - lastOff - 1) {
62
+ comL1 = pathData[1]
63
+ comBez = [pathData[l - lastOff]]
64
+ //renderPoint(markers, com.p)
65
+ }
66
+
67
+ for (let j = i + 1; j < l; j++) {
68
+ let comN = pathData[j] ? pathData[j] : null;
69
+ let comPrev = pathData[j - 1];
70
+
71
+ if (comPrev.type === 'C') {
72
+ comBez.push(comPrev)
73
+ }
74
+
75
+ if (comN.type === 'L' && comPrev.type === 'C') {
76
+ comL1 = comN
77
+ break;
78
+ }
79
+ offset++
80
+ }
81
+
82
+ if (comL1) {
83
+
84
+ // linetos
85
+ let len1 = getDistAv(comL0.p0, comL0.p)
86
+ let len2 = getDistAv(comL1.p0, comL1.p)
87
+
88
+ // bezier
89
+ //comBez = comBez[0];
90
+ let comBezLen = comBez.length;
91
+ let len3 = getDistAv(comBez[0].p0, comBez[comBezLen - 1].p)
92
+
93
+ // check concaveness by area sign change
94
+ let area1 = getPolygonArea([comL0.p0, comL0.p, comL1.p0, comL1.p], false)
95
+ let area2 = getPolygonArea([comBez[0].p0, comBez[0].cp1, comBez[0].cp2, comBez[0].p], false)
96
+
97
+ let signChange = (area1 < 0 && area2 > 0) || (area1 > 0 && area2 < 0)
98
+
99
+ if (comBez && !signChange && len3 < threshold && len1 > len3 && len2 > len3) {
100
+
101
+ let ptQ = checkLineIntersection(comL0.p0, comL0.p, comL1.p0, comL1.p, false)
102
+ if (ptQ) {
103
+
104
+ /*
105
+ let dist1 = getDistAv(ptQ, comL0.p)
106
+ let dist2 = getDistAv(ptQ, comL1.p0)
107
+ let diff = Math.abs(dist1-dist2)
108
+ let rat = diff/Math.max(dist1, dist2)
109
+ console.log('rat', rat);
110
+ */
111
+
112
+ /*
113
+ // adjust curve start and end to meet original
114
+ let t = 1
115
+
116
+ let p0_2 = pointAtT([ptQ, comL0.p], t)
117
+ //renderPoint(markers, p0_2, 'cyan', '1%', '0.5')
118
+ comL0.p = p0_2
119
+ comL0.values = [p0_2.x, p0_2.y]
120
+
121
+ let p_2 = pointAtT([ptQ, comL1.p0], t)
122
+ //renderPoint(markers, p_2, 'orange', '1%', '0.5')
123
+ comL1.p0 = p_2
124
+
125
+ //renderPoint(markers, comL0.p, 'red', '1%', '0.5')
126
+ //renderPoint(markers, ptQ, 'magenta')
127
+ */
128
+
129
+
130
+ let comQ = { type: 'Q', values: [ptQ.x, ptQ.y, comL1.p0.x, comL1.p0.y] }
131
+ comQ.p0 = comL0.p;
132
+ comQ.cp1 = ptQ;
133
+ comQ.p = comL1.p0;
134
+
135
+ // add quadratic command
136
+ pathDataN.push(comL0, comQ);
137
+ i += offset;
138
+ continue;
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ // skip last lineto
145
+ if (normalizeClose && i === l - 1 && type === 'L') {
146
+ continue
147
+ }
148
+
149
+ pathDataN.push(com)
150
+
151
+ }
152
+
153
+ // revert close path normalization
154
+ if (normalizeClose) {
155
+ pathDataN.push({ type: 'Z', values: [] })
156
+ }
157
+
158
+ return pathDataN;
159
+
160
+ }
@@ -0,0 +1,208 @@
1
+ import { findSplitT, getExtrapolatedCommand } from "../pathData_simplify_cubic";
2
+ import { getCombinedByDominant } from "../pathData_simplify_cubic_extrapolate";
3
+ import { getDistAv, interpolate } from "./geometry";
4
+ import { getPathArea, getPolygonArea } from "./geometry_area";
5
+ import { getPathDataBBox } from "./geometry_bbox";
6
+ import { interpolatedPathData } from "./pathData_interpolate";
7
+ import { pathDataToD } from "./pathData_stringify";
8
+ import { renderPath, renderPoint } from "./visualize";
9
+
10
+ export function refineAdjacentExtremes(pathData, {
11
+ threshold = null, tolerance = 1
12
+ } = {}) {
13
+
14
+ //dimA = dimA ? dimA :
15
+ if (!threshold) {
16
+ let bb = getPathDataBBox(pathData);
17
+ threshold = (bb.width + bb.height) / 2 * 0.05
18
+ //console.log('new threshold', threshold);
19
+ }
20
+
21
+ //let bb = getPathDataBBox(pathData);
22
+ //threshold = (bb.width + bb.height) / 2 * 0.1
23
+
24
+
25
+ let l = pathData.length
26
+
27
+ for (let i = 0; i < l; i++) {
28
+ let com = pathData[i];
29
+ let { type, values, extreme, corner = false, dimA, p0, p } = com;
30
+ let comN = pathData[i + 1] ? pathData[i + 1] : null;
31
+ let comN2 = pathData[i + 2] ? pathData[i + 2] : null;
32
+
33
+
34
+ // check dist
35
+ let diff = comN ? getDistAv(p, comN.p) : Infinity;
36
+ let isCose = diff < threshold;
37
+
38
+ let diff2 = comN2 ? getDistAv(comN2.p, comN.p) : Infinity
39
+ let isCose2 = diff2 < threshold;
40
+
41
+
42
+ // next is extreme
43
+ if (comN && type === 'C' && comN.type === 'C' && extreme && comN2 && comN2.extreme) {
44
+
45
+
46
+ if (isCose2 || isCose) {
47
+
48
+ // extrapolate
49
+ let comEx = getCombinedByDominant(comN, comN2, threshold, tolerance, false)
50
+ //console.log('comEx', comEx);
51
+ //renderPoint(markers, comN.p)
52
+
53
+ if (comEx.length === 1) {
54
+
55
+ pathData[i + 1] = null;
56
+ comEx = comEx[0]
57
+
58
+ pathData[i + 2].values = [comEx.cp1.x, comEx.cp1.y, comEx.cp2.x, comEx.cp2.y, comEx.p.x, comEx.p.y]
59
+ pathData[i + 2].cp1 = comEx.cp1
60
+ pathData[i + 2].cp2 = comEx.cp2
61
+ pathData[i + 2].p0 = comEx.p0
62
+ pathData[i + 2].p = comEx.p
63
+ pathData[i + 2].extreme = comEx.extreme
64
+
65
+ i++
66
+ continue
67
+ }
68
+ }
69
+
70
+ }
71
+
72
+
73
+ // short after extreme
74
+
75
+ if (comN && type === 'C' && comN.type === 'C' && extreme ) {
76
+
77
+ if (isCose) {
78
+
79
+ //renderPoint(markers, com.p, 'cyan', '1%', '0.5')
80
+ //renderPoint(markers, comN.p, 'cyan', '1%', '0.5')
81
+ //console.log(comN);
82
+ //console.log(diff, threshold);
83
+
84
+ let dx1 = (com.cp1.x - comN.p0.x)
85
+ let dy1 = (com.cp1.y - comN.p0.y)
86
+
87
+ let horizontal = Math.abs(dy1) < Math.abs(dx1);
88
+
89
+ let pN = comN.p;
90
+ let ptI;
91
+ let t = 1;
92
+
93
+ let area0 = getPolygonArea([com.p0, com.p , comN.p])
94
+ // cpts area
95
+ let area1 = getPolygonArea([com.p0, com.cp1, com.cp2, com.p])
96
+
97
+ // sign change: is corner => skip
98
+ if ( (area0<0 && area1>0) || (area0>0 && area1<0)) {
99
+ //renderPoint(markers, com.p, 'orange', '1%', '0.5')
100
+ continue;
101
+ }
102
+
103
+
104
+ if (comN.extreme) {
105
+
106
+ // extend cp2
107
+ if (horizontal) {
108
+ t = Math.abs(Math.abs(comN.cp2.x - comN.p.x) / Math.abs(com.cp2.x - com.p.x))
109
+ t = Math.min(1, t)
110
+ //console.log('t', t);
111
+
112
+ ptI = interpolate(comN.p, com.cp2, 1 + t)
113
+ com.cp2.x = ptI.x
114
+ //renderPoint(markers, com.cp2, 'cyan', '1%', '0.5')
115
+ //renderPoint(markers, ptI, 'orange', '1%', '0.5')
116
+ }
117
+ else {
118
+ //renderPoint(markers, comN.p0, 'cyan', '1%', '0.5')
119
+ t = Math.abs(Math.abs(comN.cp2.y - comN.p.y) / Math.abs(com.cp2.y - com.p.y))
120
+ t = Math.min(1, t)
121
+ //console.log('t v', t);
122
+
123
+ ptI = interpolate(comN.p, com.cp2, 1 + t)
124
+ com.cp2.y = ptI.y
125
+ }
126
+
127
+ //merge commands
128
+ pathData[i + 1].values = [com.cp1.x, com.cp1.y, com.cp2.x, com.cp2.y, pN.x, pN.y]
129
+ pathData[i + 1].cp1 = com.cp1
130
+ pathData[i + 1].cp2 = com.cp2
131
+ pathData[i + 1].p0 = com.p0
132
+ pathData[i + 1].p = pN
133
+ pathData[i + 1].extreme = true
134
+
135
+ // nullify 1st
136
+ pathData[i] = null;
137
+ continue
138
+
139
+ }
140
+
141
+ }
142
+ }
143
+
144
+ /*
145
+ */
146
+
147
+
148
+ }
149
+
150
+ // remove commands
151
+ pathData = pathData.filter(Boolean)
152
+ l = pathData.length
153
+
154
+
155
+
156
+ /**
157
+ * refine closing commands
158
+ */
159
+
160
+ let closed = pathData[l - 1].type.toLowerCase() === 'z';
161
+ let lastIdx = closed ? l - 2 : l - 1;
162
+ let lastCom = pathData[lastIdx];
163
+ let penultimateCom = pathData[lastIdx - 1] || null;
164
+ let M = { x: pathData[0].values[0], y: pathData[0].values[1] }
165
+
166
+ let dec = 8
167
+ let lastVals = lastCom.values.slice(-2);
168
+ let isClosingTo = +lastVals[0].toFixed(dec) === +M.x.toFixed(dec) && +lastVals[1].toFixed(dec) === +M.y.toFixed(dec)
169
+ let fistExt = pathData[1].type === 'C' && pathData[1].extreme ? pathData[1] : null;
170
+
171
+
172
+ //renderPoint(markers, M, 'blue')
173
+ //renderPoint(markers, fistExt.cp1, 'blue')
174
+ //renderPoint(markers, fistExt.p0, 'blue')
175
+
176
+
177
+
178
+ let diff = getDistAv(lastCom.p0, lastCom.p)
179
+ let isCose = diff < threshold;
180
+
181
+
182
+ if (penultimateCom && penultimateCom.type === 'C' && isCose && isClosingTo && fistExt) {
183
+
184
+ //let dx1 = Math.abs(fistExt.cp1.x - M.x)
185
+ //let dy1 = Math.abs(fistExt.cp1.y - M.y)
186
+
187
+ //let horizontal = dy1 < dx1;
188
+ //console.log(dx1, dx2);
189
+ //console.log('isCose', isCose, diff, dimA);
190
+
191
+ let comEx = getCombinedByDominant(penultimateCom, lastCom, threshold, tolerance, false)
192
+ //console.log('comEx', comEx);
193
+
194
+ if (comEx.length === 1) {
195
+ pathData[lastIdx - 1] = comEx[0];
196
+ pathData[lastIdx] = null;
197
+ pathData = pathData.filter(Boolean)
198
+ }
199
+
200
+ //console.log(pathData);
201
+ }
202
+
203
+
204
+ //console.log('pathData ex', pathData);
205
+
206
+ return pathData
207
+
208
+ }
@@ -2,6 +2,7 @@ import { pointAtT, svgArcToCenterParam, getBezierExtremeT } from "./geometry";
2
2
  import { renderPoint, renderPath } from "./visualize";
3
3
 
4
4
 
5
+
5
6
  /**
6
7
  * split segments into chunks to
7
8
  * prevent simplification across
@@ -124,31 +125,58 @@ export function getPathDataPlusChunks(pathDataPlus = [], debug = false) {
124
125
  * split compound paths into
125
126
  * sub path data array
126
127
  */
127
- export function splitSubpaths(pathData) {
128
128
 
129
+ export function splitSubpaths(pathData) {
129
130
  let subPathArr = [];
131
+ let current = [pathData[0]];
132
+ let l = pathData.length;
133
+
134
+ for (let i = 1; i < l; i++) {
135
+ let com = pathData[i];
136
+
137
+ if (com.type === 'M' || com.type === 'm') {
138
+ subPathArr.push(current);
139
+ current = [];
140
+ }
141
+ current.push(com);
142
+ }
143
+
144
+ if (current.length) subPathArr.push(current);
145
+
146
+ //console.log(subPathArr);
147
+ return subPathArr;
148
+ }
149
+
150
+
151
+
152
+ export function splitSubpaths0(pathData) {
153
+
154
+ let indices = [0];
155
+ let l = pathData.length;
156
+ //let com
157
+ //console.log(pathData);
130
158
 
131
- //split segments after M command
132
-
133
- try{
134
- let subPathIndices = pathData.map((com, i) => (com.type.toLowerCase() === 'm' ? i : -1)).filter(i => i !== -1);
159
+ if(!l) return [];
135
160
 
136
- }catch{
137
- console.log('catch', pathData);
161
+ //find split segments indices introduced by M commands
162
+ for(let i=1; i<l; i++){
163
+ let type= pathData[i].type.toLowerCase();
164
+ if(type==='m') indices.push(i)
138
165
  }
166
+ //console.log(indices);
139
167
 
168
+ // only one sub path
169
+ let len = indices.length;
170
+ if(len===1) return [pathData];
140
171
 
141
- let subPathIndices = pathData.map((com, i) => (com.type.toLowerCase() === 'm' ? i : -1)).filter(i => i !== -1);
142
- //let subPathIndices = pathData.map((com, i) => (com.type === 'M' ? i : -1)).filter(i => i !== -1);
172
+ let subPathArr = new Array(len);
143
173
 
144
- // no compound path
145
- if (subPathIndices.length === 1) {
146
- return [pathData]
174
+ for(let i=0; i<len; i++){
175
+ let idx = indices[i]
176
+ subPathArr[i] = pathData.slice(idx, indices[i + 1]);
147
177
  }
148
- subPathIndices.forEach((index, i) => {
149
- subPathArr.push(pathData.slice(index, subPathIndices[i + 1]));
150
- });
151
178
 
179
+ //console.log(subPathArr);
152
180
  return subPathArr;
153
181
  }
154
182
 
@@ -9,17 +9,10 @@ export function pathDataToD(pathData, optimize = 0) {
9
9
  optimize = parseFloat(optimize)
10
10
 
11
11
 
12
-
13
12
  let len = pathData.length;
14
13
  let beautify = optimize > 1;
15
14
  let minify = beautify || optimize ? false : true;
16
15
 
17
- // Convert first "M" to "m" if followed by "l" (when minified)
18
- /*
19
- if (pathData[1].type === "l" && minify) {
20
- pathData[0].type = "m";
21
- }
22
- */
23
16
 
24
17
  let d = '';
25
18
  let separator_command = beautify ? `\n` : (minify ? '' : ' ');
@@ -43,13 +36,11 @@ export function pathDataToD(pathData, optimize = 0) {
43
36
  }
44
37
 
45
38
  // Omit type for repeated commands
46
- type = (com0.type === com.type && com.type.toLowerCase() !== 'm' && minify)
39
+ type = (minify && com0.type === com.type && com.type.toLowerCase() !== 'm' )
47
40
  ? " "
48
- : (
49
- (com0.type === "M" && com.type === "L")
50
- ) && minify
41
+ : (minify && com0.type === "M" && com.type === "L"
51
42
  ? " "
52
- : com.type;
43
+ : com.type);
53
44
 
54
45
 
55
46
  // concatenate subsequent floating point values
@@ -11,7 +11,7 @@ export function detectAccuracy(pathData) {
11
11
 
12
12
  // Reference first MoveTo command (M)
13
13
  let M = { x: pathData[0].values[0], y: pathData[0].values[1] };
14
- let p0 = M
14
+ let p0 = M
15
15
  let p = M
16
16
  pathData[0].decimals = 0
17
17
  let lastDec = 0;
@@ -21,7 +21,8 @@ export function detectAccuracy(pathData) {
21
21
 
22
22
  //console.log('detectAccuracy');
23
23
 
24
- let dims = new Set();
24
+ //let dims = new Set();
25
+ let dims = [];
25
26
 
26
27
  // add average distances
27
28
  for (let i = 0, len = pathData.length; i < len; i++) {
@@ -29,34 +30,40 @@ export function detectAccuracy(pathData) {
29
30
  let { type, values } = com;
30
31
 
31
32
  let lastVals = values.length ? values.slice(-2) : [M.x, M.y];
32
- p={x:lastVals[0], y:lastVals[1]}
33
+ p = { x: lastVals[0], y: lastVals[1] }
33
34
 
34
35
  // use existing averave dimension value or calculate
35
- let dimA = com.dimA ? +com.dimA.toFixed(8) : type!=='M' ? +getDistAv(p0, p).toFixed(8) : 0
36
+ let dimA = com.dimA ? +com.dimA.toFixed(8) : type !== 'M' ? +getDistAv(p0, p).toFixed(8) : 0
36
37
  //let dimA = +getDistAv(p0, p).toFixed(8)
37
38
  //console.log('dimA', dimA, com.dimA, type);
38
39
 
39
- if(dimA) dims.add(dimA);
40
+ if (dimA) dims.push(dimA);
41
+
42
+ if (dimA && dimA < minDim) minDim = dimA;
43
+ if (dimA && dimA > maxDim) maxDim = dimA;
40
44
 
41
- if(dimA && dimA<minDim) minDim = dimA;
42
- if(dimA && dimA>maxDim) maxDim = dimA;
43
-
44
45
 
45
- if(type==='M'){
46
- M=p;
46
+ if (type === 'M') {
47
+ M = p;
47
48
  }
48
49
  p0 = p;
49
50
  }
50
51
 
51
52
 
52
- let dim_min = Array.from(dims).sort()
53
- let sliceIdx = Math.ceil(dim_min.length/8);
54
- dim_min = dim_min.slice(0, sliceIdx );
53
+ let dim_min = dims.sort()
55
54
 
56
- let dimVal = dim_min.reduce((a,b)=>a+b, 0) / sliceIdx;
55
+ /*
56
+ let minVal = dim_min.length > 15 ?
57
+ (dim_min[0] + dim_min[2]) / 2 :
58
+ dim_min[0];
59
+ */
60
+
61
+ let sliceIdx = Math.ceil(dim_min.length / 10);
62
+ dim_min = dim_min.slice(0, sliceIdx);
63
+ let minVal = dim_min.reduce((a, b) => a + b, 0) / sliceIdx;
57
64
 
58
- let threshold = 50
59
- let decimalsAuto = dimVal > threshold ? 0 : Math.floor(threshold / dimVal).toString().length
65
+ let threshold = 40
66
+ let decimalsAuto = minVal > threshold*1.5 ? 0 : Math.floor(threshold / minVal).toString().length
60
67
 
61
68
  // clamp
62
69
  return Math.min(Math.max(0, decimalsAuto), 8)
@@ -141,22 +148,23 @@ export function detectAccuracy_back(pathData) {
141
148
  * based on suggested accuracy in path data
142
149
  */
143
150
  export function roundPathData(pathData, decimals = -1) {
144
- // has recommended decimals
145
- let hasDecimal = decimals == 'auto' && pathData[0].hasOwnProperty('decimals') ? true : false;
146
- //console.log('decimals', decimals, hasDecimal);
147
-
148
- for(let c=0, len=pathData.length; c<len; c++){
149
- let com=pathData[c];
150
- let {type, values} = com
151
151
 
152
- if (decimals >-1 || hasDecimal) {
153
- decimals = hasDecimal ? com.decimals : decimals;
152
+ let len = pathData.length;
154
153
 
154
+ for (let c = 0; c < len; c++) {
155
+ //let com = pathData[c];
156
+ let values = pathData[c].values
157
+ let valLen = values.length;
155
158
 
156
- //console.log('decimals', type, decimals);
157
- pathData[c].values = com.values.map(val=>{return val ? +val.toFixed(decimals) : val });
159
+ if (valLen && (decimals > -1) ) {
158
160
 
161
+ for(let v=0; v<valLen; v++){
162
+ //pathData[c].values[v] = values[v] ? +values[v].toFixed(decimals) : values[v];
163
+ pathData[c].values[v] = +values[v].toFixed(decimals);
164
+ }
159
165
  }
160
166
  };
167
+
168
+ //console.log(pathData);
161
169
  return pathData;
162
170
  }
@@ -1,3 +1,6 @@
1
+
2
+
3
+
1
4
  export function removeEmptySVGEls(svg) {
2
5
  let els = svg.querySelectorAll('g, defs');
3
6
  els.forEach(el => {
@@ -22,7 +25,7 @@ export function cleanUpSVG(svgMarkup, {
22
25
  .querySelector("svg");
23
26
 
24
27
 
25
- let allowed=['viewBox', 'xmlns', 'width', 'height', 'id', 'class'];
28
+ let allowed=['viewBox', 'xmlns', 'width', 'height', 'id', 'class', 'fill', 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin'];
26
29
  removeExcludedAttribues(svg, allowed)
27
30
 
28
31
  let removeEls = ['metadata', 'script']