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.
- package/README.md +25 -5
- package/dist/svg-path-simplify.esm.js +576 -494
- package/dist/svg-path-simplify.esm.min.js +1 -1
- package/dist/svg-path-simplify.js +576 -494
- package/dist/svg-path-simplify.min.js +1 -1
- package/dist/svg-path-simplify.node.js +576 -494
- package/dist/svg-path-simplify.node.min.js +1 -1
- package/index.html +86 -29
- package/package.json +1 -1
- package/src/detect_input.js +17 -10
- package/src/index.js +3 -0
- package/src/pathData_simplify_cubic.js +113 -106
- package/src/pathData_simplify_cubic_extrapolate.js +25 -11
- package/src/pathSimplify-main.js +89 -182
- package/src/svgii/geometry_flatness.js +29 -36
- package/src/svgii/pathData_analyze.js +4 -0
- package/src/svgii/pathData_convert.js +26 -17
- package/src/svgii/pathData_interpolate.js +65 -0
- package/src/svgii/pathData_parse.js +25 -9
- package/src/svgii/pathData_parse_els.js +18 -12
- package/src/svgii/pathData_remove_collinear.js +31 -28
- package/src/svgii/pathData_remove_orphaned.js +5 -4
- package/src/svgii/pathData_remove_zerolength.js +8 -4
- package/src/svgii/pathData_reorder.js +6 -2
- package/src/svgii/pathData_simplify_refineCorners.js +160 -0
- package/src/svgii/{simplify_refineExtremes.js → pathData_simplify_refineExtremes.js} +78 -43
- package/src/svgii/pathData_split.js +42 -15
- package/src/svgii/pathData_stringify.js +3 -12
- package/src/svgii/rounding.js +16 -14
- package/src/svgii/svg_cleanup.js +1 -1
- package/src/pathData_simplify_cubic_arr.js +0 -50
- package/src/svgii/simplify.js +0 -248
- package/src/svgii/simplify_bezier.js +0 -470
- package/src/svgii/simplify_linetos.js +0 -93
|
@@ -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
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { findSplitT, getExtrapolatedCommand } from "../pathData_simplify_cubic";
|
|
1
2
|
import { getCombinedByDominant } from "../pathData_simplify_cubic_extrapolate";
|
|
2
3
|
import { getDistAv, interpolate } from "./geometry";
|
|
3
|
-
import { getPathArea } from "./geometry_area";
|
|
4
|
+
import { getPathArea, getPolygonArea } from "./geometry_area";
|
|
4
5
|
import { getPathDataBBox } from "./geometry_bbox";
|
|
5
|
-
import {
|
|
6
|
+
import { interpolatedPathData } from "./pathData_interpolate";
|
|
7
|
+
import { pathDataToD } from "./pathData_stringify";
|
|
8
|
+
import { renderPath, renderPoint } from "./visualize";
|
|
6
9
|
|
|
7
10
|
export function refineAdjacentExtremes(pathData, {
|
|
8
11
|
threshold = null, tolerance = 1
|
|
@@ -15,24 +18,65 @@ export function refineAdjacentExtremes(pathData, {
|
|
|
15
18
|
//console.log('new threshold', threshold);
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
//let bb = getPathDataBBox(pathData);
|
|
22
|
+
//threshold = (bb.width + bb.height) / 2 * 0.1
|
|
23
|
+
|
|
24
|
+
|
|
18
25
|
let l = pathData.length
|
|
19
26
|
|
|
20
27
|
for (let i = 0; i < l; i++) {
|
|
21
28
|
let com = pathData[i];
|
|
22
|
-
let { type, values, extreme, corner=false, dimA, p0, p } = com;
|
|
29
|
+
let { type, values, extreme, corner = false, dimA, p0, p } = com;
|
|
23
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;
|
|
24
40
|
|
|
25
41
|
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
if (comN && type === 'C' && comN.type === 'C' && extreme && !corner) {
|
|
42
|
+
// next is extreme
|
|
43
|
+
if (comN && type === 'C' && comN.type === 'C' && extreme && comN2 && comN2.extreme) {
|
|
29
44
|
|
|
30
|
-
// check dist
|
|
31
|
-
let diff = getDistAv(p, comN.p)
|
|
32
|
-
let isCose = diff < threshold;
|
|
33
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 ) {
|
|
34
76
|
|
|
35
77
|
if (isCose) {
|
|
78
|
+
|
|
79
|
+
//renderPoint(markers, com.p, 'cyan', '1%', '0.5')
|
|
36
80
|
//renderPoint(markers, comN.p, 'cyan', '1%', '0.5')
|
|
37
81
|
//console.log(comN);
|
|
38
82
|
//console.log(diff, threshold);
|
|
@@ -46,12 +90,25 @@ export function refineAdjacentExtremes(pathData, {
|
|
|
46
90
|
let ptI;
|
|
47
91
|
let t = 1;
|
|
48
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
|
+
|
|
49
104
|
if (comN.extreme) {
|
|
50
105
|
|
|
51
106
|
// extend cp2
|
|
52
107
|
if (horizontal) {
|
|
53
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)
|
|
54
110
|
//console.log('t', t);
|
|
111
|
+
|
|
55
112
|
ptI = interpolate(comN.p, com.cp2, 1 + t)
|
|
56
113
|
com.cp2.x = ptI.x
|
|
57
114
|
//renderPoint(markers, com.cp2, 'cyan', '1%', '0.5')
|
|
@@ -60,6 +117,9 @@ export function refineAdjacentExtremes(pathData, {
|
|
|
60
117
|
else {
|
|
61
118
|
//renderPoint(markers, comN.p0, 'cyan', '1%', '0.5')
|
|
62
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
|
+
|
|
63
123
|
ptI = interpolate(comN.p, com.cp2, 1 + t)
|
|
64
124
|
com.cp2.y = ptI.y
|
|
65
125
|
}
|
|
@@ -78,38 +138,13 @@ export function refineAdjacentExtremes(pathData, {
|
|
|
78
138
|
|
|
79
139
|
}
|
|
80
140
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
let comN2 = pathData[i + 2] ? pathData[i + 2] : null;
|
|
85
|
-
if (!comN2 && comN2.type !== 'C') continue
|
|
86
|
-
|
|
87
|
-
//continue
|
|
88
|
-
|
|
89
|
-
// extrapolate
|
|
90
|
-
let comEx = getCombinedByDominant(comN, comN2, threshold, tolerance, false)
|
|
91
|
-
//console.log('comEx', comEx);
|
|
92
|
-
|
|
93
|
-
if (comEx.length === 1) {
|
|
94
|
-
pathData[i + 1] = null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
95
143
|
|
|
96
|
-
|
|
144
|
+
/*
|
|
145
|
+
*/
|
|
97
146
|
|
|
98
|
-
pathData[i + 2].values = [comEx.cp1.x, comEx.cp1.y, comEx.cp2.x, comEx.cp2.y, comEx.p.x, comEx.p.y]
|
|
99
|
-
pathData[i + 2].cp1 = comEx.cp1
|
|
100
|
-
pathData[i + 2].cp2 = comEx.cp2
|
|
101
|
-
pathData[i + 2].p0 = comEx.p0
|
|
102
|
-
pathData[i + 2].p = comEx.p
|
|
103
|
-
pathData[i + 2].extreme = comEx.extreme
|
|
104
147
|
|
|
105
|
-
i++
|
|
106
|
-
continue
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
148
|
}
|
|
114
149
|
|
|
115
150
|
// remove commands
|
|
@@ -146,15 +181,15 @@ export function refineAdjacentExtremes(pathData, {
|
|
|
146
181
|
|
|
147
182
|
if (penultimateCom && penultimateCom.type === 'C' && isCose && isClosingTo && fistExt) {
|
|
148
183
|
|
|
149
|
-
let dx1 = Math.abs(fistExt.cp1.x - M.x)
|
|
150
|
-
let dy1 = Math.abs(fistExt.cp1.y - M.y)
|
|
184
|
+
//let dx1 = Math.abs(fistExt.cp1.x - M.x)
|
|
185
|
+
//let dy1 = Math.abs(fistExt.cp1.y - M.y)
|
|
151
186
|
|
|
152
|
-
let horizontal = dy1 < dx1;
|
|
187
|
+
//let horizontal = dy1 < dx1;
|
|
153
188
|
//console.log(dx1, dx2);
|
|
154
189
|
//console.log('isCose', isCose, diff, dimA);
|
|
155
190
|
|
|
156
191
|
let comEx = getCombinedByDominant(penultimateCom, lastCom, threshold, tolerance, false)
|
|
157
|
-
console.log('comEx', comEx);
|
|
192
|
+
//console.log('comEx', comEx);
|
|
158
193
|
|
|
159
194
|
if (comEx.length === 1) {
|
|
160
195
|
pathData[lastIdx - 1] = comEx[0];
|
|
@@ -162,7 +197,7 @@ export function refineAdjacentExtremes(pathData, {
|
|
|
162
197
|
pathData = pathData.filter(Boolean)
|
|
163
198
|
}
|
|
164
199
|
|
|
165
|
-
|
|
200
|
+
//console.log(pathData);
|
|
166
201
|
}
|
|
167
202
|
|
|
168
203
|
|
|
@@ -125,31 +125,58 @@ export function getPathDataPlusChunks(pathDataPlus = [], debug = false) {
|
|
|
125
125
|
* split compound paths into
|
|
126
126
|
* sub path data array
|
|
127
127
|
*/
|
|
128
|
-
export function splitSubpaths(pathData) {
|
|
129
128
|
|
|
129
|
+
export function splitSubpaths(pathData) {
|
|
130
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);
|
|
131
158
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
try{
|
|
135
|
-
let subPathIndices = pathData.map((com, i) => (com.type.toLowerCase() === 'm' ? i : -1)).filter(i => i !== -1);
|
|
159
|
+
if(!l) return [];
|
|
136
160
|
|
|
137
|
-
|
|
138
|
-
|
|
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)
|
|
139
165
|
}
|
|
166
|
+
//console.log(indices);
|
|
140
167
|
|
|
168
|
+
// only one sub path
|
|
169
|
+
let len = indices.length;
|
|
170
|
+
if(len===1) return [pathData];
|
|
141
171
|
|
|
142
|
-
let
|
|
143
|
-
//let subPathIndices = pathData.map((com, i) => (com.type === 'M' ? i : -1)).filter(i => i !== -1);
|
|
172
|
+
let subPathArr = new Array(len);
|
|
144
173
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
174
|
+
for(let i=0; i<len; i++){
|
|
175
|
+
let idx = indices[i]
|
|
176
|
+
subPathArr[i] = pathData.slice(idx, indices[i + 1]);
|
|
148
177
|
}
|
|
149
|
-
subPathIndices.forEach((index, i) => {
|
|
150
|
-
subPathArr.push(pathData.slice(index, subPathIndices[i + 1]));
|
|
151
|
-
});
|
|
152
178
|
|
|
179
|
+
//console.log(subPathArr);
|
|
153
180
|
return subPathArr;
|
|
154
181
|
}
|
|
155
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'
|
|
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
|
package/src/svgii/rounding.js
CHANGED
|
@@ -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++) {
|
|
@@ -36,7 +37,7 @@ export function detectAccuracy(pathData) {
|
|
|
36
37
|
//let dimA = +getDistAv(p0, p).toFixed(8)
|
|
37
38
|
//console.log('dimA', dimA, com.dimA, type);
|
|
38
39
|
|
|
39
|
-
if (dimA) dims.
|
|
40
|
+
if (dimA) dims.push(dimA);
|
|
40
41
|
|
|
41
42
|
if (dimA && dimA < minDim) minDim = dimA;
|
|
42
43
|
if (dimA && dimA > maxDim) maxDim = dimA;
|
|
@@ -49,7 +50,7 @@ export function detectAccuracy(pathData) {
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
|
|
52
|
-
let dim_min =
|
|
53
|
+
let dim_min = dims.sort()
|
|
53
54
|
|
|
54
55
|
/*
|
|
55
56
|
let minVal = dim_min.length > 15 ?
|
|
@@ -147,22 +148,23 @@ export function detectAccuracy_back(pathData) {
|
|
|
147
148
|
* based on suggested accuracy in path data
|
|
148
149
|
*/
|
|
149
150
|
export function roundPathData(pathData, decimals = -1) {
|
|
150
|
-
// has recommended decimals
|
|
151
|
-
let hasDecimal = decimals == 'auto' && pathData[0].hasOwnProperty('decimals') ? true : false;
|
|
152
|
-
//console.log('decimals', decimals, hasDecimal);
|
|
153
151
|
|
|
154
|
-
|
|
155
|
-
let com = pathData[c];
|
|
156
|
-
let { type, values } = com
|
|
152
|
+
let len = pathData.length;
|
|
157
153
|
|
|
158
|
-
|
|
159
|
-
|
|
154
|
+
for (let c = 0; c < len; c++) {
|
|
155
|
+
//let com = pathData[c];
|
|
156
|
+
let values = pathData[c].values
|
|
157
|
+
let valLen = values.length;
|
|
160
158
|
|
|
159
|
+
if (valLen && (decimals > -1) ) {
|
|
161
160
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
+
}
|
|
165
165
|
}
|
|
166
166
|
};
|
|
167
|
+
|
|
168
|
+
//console.log(pathData);
|
|
167
169
|
return pathData;
|
|
168
170
|
}
|
package/src/svgii/svg_cleanup.js
CHANGED
|
@@ -25,7 +25,7 @@ export function cleanUpSVG(svgMarkup, {
|
|
|
25
25
|
.querySelector("svg");
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
let allowed=['viewBox', 'xmlns', 'width', 'height', 'id', 'class', 'fill', 'stroke', 'stroke-width'];
|
|
28
|
+
let allowed=['viewBox', 'xmlns', 'width', 'height', 'id', 'class', 'fill', 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin'];
|
|
29
29
|
removeExcludedAttribues(svg, allowed)
|
|
30
30
|
|
|
31
31
|
let removeEls = ['metadata', 'script']
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { getDistance, getSquareDistance, checkLineIntersection, pointAtT, getDistAv } from "./svgii/geometry";
|
|
2
|
-
import { getBezierArea, getPolygonArea } from "./svgii/geometry_area";
|
|
3
|
-
import { renderPoint } from "./svgii/visualize";
|
|
4
|
-
|
|
5
|
-
export function combineCubicArray(commands = [], threshold = 0.05) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let [comF, comM, comE] = commands;
|
|
9
|
-
|
|
10
|
-
commands.forEach(com => {
|
|
11
|
-
let area = getBezierArea([com.p0, com.cp1, com.cp2, com.p], true)
|
|
12
|
-
com.area = area
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
// sort by area
|
|
16
|
-
let commandsFiltered = JSON.parse(JSON.stringify(commands)).sort((a,b)=>b.area-a.area )
|
|
17
|
-
|
|
18
|
-
let comL = commandsFiltered[0]
|
|
19
|
-
|
|
20
|
-
// find largest segment
|
|
21
|
-
//let area2 = getBezierArea(comF)
|
|
22
|
-
|
|
23
|
-
console.log('area1', commands, commandsFiltered);
|
|
24
|
-
|
|
25
|
-
// largest segment
|
|
26
|
-
comM = commandsFiltered[0]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
//let segLargest =
|
|
30
|
-
let pt_mid = pointAtT([comM.p0, comM.cp1, comM.cp2, comM.p], 0.5, false, true)
|
|
31
|
-
|
|
32
|
-
let seg1_cp2 = pt_mid.cpts[2]
|
|
33
|
-
let seg2_cp1 = pt_mid.cpts[3]
|
|
34
|
-
renderPoint(markers, seg1_cp2, 'orange')
|
|
35
|
-
renderPoint(markers, seg2_cp1, 'cyan')
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
console.log('comM', pt_mid);
|
|
39
|
-
|
|
40
|
-
renderPoint(markers, comF.p0, 'green')
|
|
41
|
-
renderPoint(markers, comL.p, 'purple')
|
|
42
|
-
//renderPoint(markers, comE.cp2, 'orange')
|
|
43
|
-
|
|
44
|
-
renderPoint(markers, pt_mid, 'magenta')
|
|
45
|
-
//let ptI_1 = checkLineIntersection(comF)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return commands;
|
|
49
|
-
}
|
|
50
|
-
|