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.
- package/README.md +25 -5
- package/dist/svg-path-simplify.esm.js +1250 -562
- package/dist/svg-path-simplify.esm.min.js +1 -1
- package/dist/svg-path-simplify.js +4756 -4068
- package/dist/svg-path-simplify.min.js +1 -1
- package/dist/svg-path-simplify.node.js +1250 -562
- package/dist/svg-path-simplify.node.min.js +1 -1
- package/index.html +89 -29
- package/package.json +5 -3
- package/src/detect_input.js +17 -10
- package/src/dom-polyfill.js +29 -0
- package/src/dom-polyfill_back.js +22 -0
- package/src/index.js +10 -1
- package/src/pathData_simplify_cubic.js +114 -143
- package/src/pathData_simplify_cubic_extrapolate.js +64 -35
- package/src/pathSimplify-main.js +113 -165
- package/src/svgii/geometry.js +8 -155
- package/src/svgii/geometry_flatness.js +94 -0
- package/src/svgii/pathData_analyze.js +15 -596
- 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 +245 -0
- package/src/svgii/pathData_remove_collinear.js +33 -28
- package/src/svgii/pathData_remove_orphaned.js +21 -0
- package/src/svgii/pathData_remove_zerolength.js +17 -3
- package/src/svgii/pathData_reorder.js +9 -3
- package/src/svgii/pathData_simplify_refineCorners.js +160 -0
- package/src/svgii/pathData_simplify_refineExtremes.js +208 -0
- package/src/svgii/pathData_split.js +43 -15
- package/src/svgii/pathData_stringify.js +3 -12
- package/src/svgii/rounding.js +35 -27
- package/src/svgii/svg_cleanup.js +4 -1
- package/testSVG.js +39 -0
- 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
|
@@ -5,88 +5,134 @@ import { renderPoint } from "./svgii/visualize";
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
8
|
+
export function simplifyPathDataCubic(pathData, {
|
|
9
|
+
keepExtremes = true,
|
|
10
|
+
keepInflections = true,
|
|
11
|
+
keepCorners = true,
|
|
12
|
+
extrapolateDominant = true,
|
|
13
|
+
tolerance = 1,
|
|
14
|
+
} = {}) {
|
|
15
|
+
|
|
16
|
+
let pathDataN = [pathData[0]];
|
|
17
|
+
let l = pathData.length;
|
|
18
|
+
|
|
19
|
+
for (let i = 2; l && i <= l; i++) {
|
|
20
|
+
let com = pathData[i - 1];
|
|
21
|
+
let comN = i < l ? pathData[i] : null;
|
|
22
|
+
let typeN = comN?.type || null;
|
|
23
|
+
//let isCornerN = comN?.corner || null;
|
|
24
|
+
//let isExtremeN = comN?.extreme || null;
|
|
25
|
+
let isDirChange = com?.directionChange || null;
|
|
26
|
+
let isDirChangeN = comN?.directionChange || null;
|
|
27
|
+
|
|
28
|
+
let { type, values, p0, p, cp1 = null, cp2 = null, extreme = false, corner = false, dimA = 0 } = com;
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
// next is also cubic
|
|
32
|
+
if (type === 'C' && typeN === 'C') {
|
|
33
|
+
|
|
34
|
+
// cannot be combined as crossing extremes or corners
|
|
35
|
+
if (
|
|
36
|
+
(keepInflections && isDirChangeN) ||
|
|
37
|
+
(keepCorners && corner) ||
|
|
38
|
+
(!isDirChange && keepExtremes && extreme)
|
|
39
|
+
) {
|
|
40
|
+
//renderPoint(markers, p, 'red', '1%')
|
|
41
|
+
pathDataN.push(com)
|
|
42
|
+
}
|
|
38
43
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
// try simplification
|
|
45
|
+
else {
|
|
46
|
+
//renderPoint(markers, p, 'magenta', '1%')
|
|
47
|
+
let combined = combineCubicPairs(com, comN, {tolerance})
|
|
48
|
+
let error = 0;
|
|
49
|
+
|
|
50
|
+
// combining successful! try next segment
|
|
51
|
+
if (combined.length === 1) {
|
|
52
|
+
com = combined[0]
|
|
53
|
+
let offset = 1;
|
|
54
|
+
|
|
55
|
+
// add cumulative error to prevent distortions
|
|
56
|
+
error += com.error;
|
|
57
|
+
//console.log('!error', error);
|
|
58
|
+
|
|
59
|
+
// find next candidates
|
|
60
|
+
//offset<2 &&
|
|
61
|
+
for (let n = i + 1; error < tolerance && n < l; n++) {
|
|
62
|
+
let comN = pathData[n]
|
|
63
|
+
if (comN.type !== 'C' ||
|
|
64
|
+
(
|
|
65
|
+
(keepInflections && comN.directionChange) ||
|
|
66
|
+
(keepCorners && com.corner) ||
|
|
67
|
+
(keepExtremes && com.extreme)
|
|
68
|
+
)
|
|
69
|
+
) {
|
|
70
|
+
break
|
|
71
|
+
}
|
|
72
|
+
|
|
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++
|
|
80
|
+
}
|
|
81
|
+
com = combined[0]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//com.opt = true
|
|
85
|
+
pathDataN.push(com)
|
|
86
|
+
|
|
87
|
+
if (i < l) {
|
|
88
|
+
i += offset
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
} else {
|
|
92
|
+
pathDataN.push(com)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
43
95
|
|
|
44
|
-
|
|
45
|
-
const R1_calc = interpolate(P1P2_mid, P2P3_mid, t);
|
|
96
|
+
} // end of bezier command
|
|
46
97
|
|
|
47
|
-
// Calculate errors
|
|
48
|
-
const errorQ2 = getDistance(Q2_calc, com1.cp2);
|
|
49
|
-
const errorR1 = getDistance(R1_calc, com2.cp1);
|
|
50
|
-
const totalError = errorQ2 + errorR1;
|
|
51
98
|
|
|
52
|
-
|
|
53
|
-
|
|
99
|
+
// other commands
|
|
100
|
+
else {
|
|
101
|
+
pathDataN.push(com)
|
|
54
102
|
}
|
|
55
103
|
|
|
56
|
-
|
|
57
|
-
t = t * 0.5 + 0.5 * (errorQ2 < errorR1 ? t + 0.01 : t - 0.01);
|
|
58
|
-
t = Math.max(0.001, Math.min(0.999, t));
|
|
59
|
-
}
|
|
104
|
+
} // end command loop
|
|
60
105
|
|
|
61
|
-
return
|
|
106
|
+
return pathDataN
|
|
62
107
|
}
|
|
63
108
|
|
|
64
109
|
|
|
65
110
|
|
|
66
|
-
|
|
111
|
+
|
|
112
|
+
export function combineCubicPairs(com1, com2, {
|
|
113
|
+
tolerance = 1
|
|
114
|
+
} = {}) {
|
|
67
115
|
|
|
68
116
|
let commands = [com1, com2];
|
|
69
|
-
let t = findSplitT(com1, com2);
|
|
70
117
|
|
|
71
|
-
//
|
|
118
|
+
// assume 2 segments are result of a segment split
|
|
119
|
+
let t = findSplitT(com1, com2);
|
|
72
120
|
|
|
73
121
|
let distAv1 = getDistAv(com1.p0, com1.p);
|
|
74
122
|
let distAv2 = getDistAv(com2.p0, com2.p);
|
|
75
|
-
let distMin = Math.min(distAv1, distAv2)
|
|
76
|
-
//let distMax = Math.max(distAv1, distAv2)
|
|
123
|
+
let distMin = Math.max(0, Math.min(distAv1, distAv2))
|
|
77
124
|
|
|
78
|
-
|
|
125
|
+
|
|
126
|
+
let distScale = 0.06
|
|
79
127
|
let maxDist = distMin * distScale * tolerance
|
|
80
|
-
//tolerance = distMax * threshold
|
|
81
128
|
|
|
82
|
-
|
|
129
|
+
// get hypothetical combined command
|
|
130
|
+
let comS = getExtrapolatedCommand(com1, com2, t)
|
|
83
131
|
|
|
84
|
-
// test
|
|
132
|
+
// test new point-at-t against original mid segment starting point
|
|
85
133
|
let pt = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t)
|
|
86
134
|
|
|
87
135
|
|
|
88
|
-
//let tolerance = Math.min(Math.max(com1.dimA, com2.dimA), Math.min(com1.dimA, com2.dimA)) * 0.05
|
|
89
|
-
|
|
90
136
|
let dist0 = getDistAv(com1.p, pt)
|
|
91
137
|
let dist1 = 0, dist2 = 0;
|
|
92
138
|
let close = dist0 < maxDist;
|
|
@@ -97,14 +143,6 @@ export function combineCubicPairs(com1, com2, extrapolateDominant = false, toler
|
|
|
97
143
|
|
|
98
144
|
|
|
99
145
|
|
|
100
|
-
/*
|
|
101
|
-
if (com2.directionChange) {
|
|
102
|
-
//renderPoint(markers, com2.p0)
|
|
103
|
-
}
|
|
104
|
-
*/
|
|
105
|
-
|
|
106
|
-
//console.log('tolerance', tolerance, close, dist0);
|
|
107
|
-
|
|
108
146
|
if (close) {
|
|
109
147
|
|
|
110
148
|
/**
|
|
@@ -159,44 +197,10 @@ export function combineCubicPairs(com1, com2, extrapolateDominant = false, toler
|
|
|
159
197
|
} // end 1st try
|
|
160
198
|
|
|
161
199
|
|
|
162
|
-
|
|
163
|
-
/*
|
|
164
|
-
if (extrapolateDominant && com2.extreme) {
|
|
165
|
-
renderPoint(markers, com2.p)
|
|
166
|
-
//renderPoint(markers, com1.p, 'cyan')
|
|
167
|
-
//extrapolateDominant = false;
|
|
168
|
-
}
|
|
169
|
-
*/
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
// try extrapolated dominant curve
|
|
175
|
-
//&& !com2.extreme
|
|
176
|
-
// && !com1.extreme
|
|
177
|
-
if (extrapolateDominant && !success ) {
|
|
178
|
-
|
|
179
|
-
let combinedEx = getCombinedByDominant(com1, com2, maxDist, tolerance);
|
|
180
|
-
|
|
181
|
-
//console.log('???combinedEx', combinedEx);
|
|
182
|
-
|
|
183
|
-
if(combinedEx.length===1){
|
|
184
|
-
success = true
|
|
185
|
-
comS = combinedEx[0]
|
|
186
|
-
error = comS.error
|
|
187
|
-
|
|
188
|
-
//console.log('!!!combinedEx', combinedEx);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
200
|
|
|
194
201
|
// add meta
|
|
195
202
|
if (success) {
|
|
196
203
|
|
|
197
|
-
//comS.dimA = (Math.abs(comS.p0.x - comS.p.x) + Math.abs(comS.p0.y - comS.p.y)) / 2
|
|
198
|
-
|
|
199
|
-
|
|
200
204
|
// correct to exact start and end points
|
|
201
205
|
comS.p0 = com1.p0
|
|
202
206
|
comS.p = com2.p
|
|
@@ -215,8 +219,6 @@ export function combineCubicPairs(com1, com2, extrapolateDominant = false, toler
|
|
|
215
219
|
//comS.p0 = com1.p0;
|
|
216
220
|
commands = [comS];
|
|
217
221
|
|
|
218
|
-
//console.log('commands combined', commands);
|
|
219
|
-
|
|
220
222
|
}
|
|
221
223
|
|
|
222
224
|
|
|
@@ -239,28 +241,23 @@ export function getError(com, area = 0, threshold = 0) {
|
|
|
239
241
|
}
|
|
240
242
|
|
|
241
243
|
|
|
242
|
-
export function getExtrapolatedCommand(com1, com2,
|
|
244
|
+
export function getExtrapolatedCommand(com1, com2, t = 0) {
|
|
243
245
|
|
|
244
246
|
let { p0, cp1 } = com1;
|
|
245
247
|
let { p, cp2 } = com2;
|
|
246
248
|
|
|
247
249
|
// extrapolate control points
|
|
248
|
-
|
|
249
|
-
x: (cp1.x - (1 -
|
|
250
|
-
y: (cp1.y - (1 -
|
|
250
|
+
cp1 = {
|
|
251
|
+
x: (cp1.x - (1 - t) * p0.x) / t,
|
|
252
|
+
y: (cp1.y - (1 - t) * p0.y) / t
|
|
251
253
|
};
|
|
252
254
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
y: (cp2.y - t2 * p.y) / (1 - t2)
|
|
255
|
+
cp2 = {
|
|
256
|
+
x: (cp2.x - t * p.x) / (1 - t),
|
|
257
|
+
y: (cp2.y - t * p.y) / (1 - t)
|
|
257
258
|
};
|
|
258
259
|
|
|
259
|
-
|
|
260
|
-
//let pt = pointAtT([p0, cp1_S, cp2_S, p], (t1 + t2) / 2);
|
|
261
|
-
|
|
262
|
-
return comS
|
|
263
|
-
|
|
260
|
+
return { p0, cp1, cp2, p };
|
|
264
261
|
}
|
|
265
262
|
|
|
266
263
|
|
|
@@ -281,40 +278,14 @@ export function getBezierCommandArea(commands = [com1, com2], absolute = true) {
|
|
|
281
278
|
}
|
|
282
279
|
|
|
283
280
|
|
|
284
|
-
function findSplitT(com1, com2) {
|
|
285
|
-
|
|
286
|
-
//let selfIntersecting = false
|
|
287
|
-
|
|
288
|
-
// control tangent intersection
|
|
289
|
-
let pt1 = checkLineIntersection(com1.p0, com1.cp1, com2.cp2, com2.p, false)
|
|
290
|
-
|
|
291
|
-
// intersection 2nd cp1 tangent and global tangent intersection
|
|
292
|
-
let ptI = checkLineIntersection(pt1, com2.p, com2.p0, com2.cp1, false)
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
let len1 = getDistance(pt1, com2.p)
|
|
296
|
-
let len2 = getDistance(ptI, com2.p)
|
|
297
|
-
|
|
298
|
-
//let t = !t3 ? 1-len2/len1 : (t3+len2/len1)*0.5
|
|
299
|
-
let t = 1 - len2 / len1
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
// check self intersections
|
|
303
|
-
//let ptI2 = checkLineIntersection(com1.cp1, com2.cp2, com1.p0, com2.p, true)
|
|
304
|
-
//let hasInfliction = ptI2!==null
|
|
305
|
-
|
|
281
|
+
export function findSplitT(com1, com2) {
|
|
306
282
|
|
|
307
283
|
let len3 = getDistance(com1.cp2, com1.p)
|
|
308
284
|
let len4 = getDistance(com1.cp2, com2.cp1)
|
|
309
285
|
|
|
310
|
-
|
|
311
|
-
t = Math.min(len3) / len4
|
|
312
|
-
|
|
313
|
-
//console.log('???selfIntersecting:', t, hasInfliction, ptI2)
|
|
286
|
+
let t = Math.min(len3) / len4
|
|
314
287
|
|
|
315
288
|
return t
|
|
316
|
-
|
|
317
|
-
|
|
318
289
|
}
|
|
319
290
|
|
|
320
291
|
|
|
@@ -3,7 +3,7 @@ import { getPathArea } from "./svgii/geometry_area";
|
|
|
3
3
|
import { pathDataToD } from "./svgii/pathData_stringify";
|
|
4
4
|
import { renderPath, renderPoint } from "./svgii/visualize";
|
|
5
5
|
|
|
6
|
-
export function getCombinedByDominant(com1, com2, maxDist = 0, tolerance = 1) {
|
|
6
|
+
export function getCombinedByDominant(com1, com2, maxDist = 0, tolerance = 1, debug = false) {
|
|
7
7
|
|
|
8
8
|
// cubic Bézier derivative
|
|
9
9
|
const cubicDerivative = (p0, p1, p2, p3, t) => {
|
|
@@ -21,18 +21,14 @@ export function getCombinedByDominant(com1, com2, maxDist = 0, tolerance = 1) {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
24
|
// if combining fails return original commands
|
|
27
25
|
let commands = [com1, com2]
|
|
28
26
|
|
|
29
27
|
// detect dominant
|
|
30
|
-
let dist1 =
|
|
31
|
-
let dist2 =
|
|
32
|
-
let reverse = dist1 > dist2;
|
|
28
|
+
let dist1 = getDistAv(com1.p0, com1.p)
|
|
29
|
+
let dist2 = getDistAv(com2.p0, com2.p)
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
//let ang2 = getAngle(com2.p, com1.cp2)
|
|
31
|
+
let reverse = dist1 > dist2;
|
|
36
32
|
|
|
37
33
|
// backup original commands
|
|
38
34
|
let com1_o = JSON.parse(JSON.stringify(com1))
|
|
@@ -42,6 +38,7 @@ export function getCombinedByDominant(com1, com2, maxDist = 0, tolerance = 1) {
|
|
|
42
38
|
|
|
43
39
|
if (!ptI) {
|
|
44
40
|
//renderPoint(markers, com1.p, 'purple')
|
|
41
|
+
//console.log('nope');
|
|
45
42
|
return commands
|
|
46
43
|
}
|
|
47
44
|
|
|
@@ -95,12 +92,10 @@ export function getCombinedByDominant(com1, com2, maxDist = 0, tolerance = 1) {
|
|
|
95
92
|
let r = sub(P, com1.p0);
|
|
96
93
|
|
|
97
94
|
//let t0_2 = t0 - dot(r, dP) / dot(dP, dP);
|
|
98
|
-
|
|
99
|
-
t0 -= dot(r, dP) / dot(dP, dP);
|
|
100
95
|
|
|
96
|
+
t0 -= dot(r, dP) / dot(dP, dP);
|
|
101
97
|
|
|
102
98
|
// construct merged cubic over [t0, 1]
|
|
103
|
-
|
|
104
99
|
let Q0 = pointAtT([com2.p0, com2.cp1, com2.cp2, com2.p], t0);
|
|
105
100
|
let Q3 = com2.p;
|
|
106
101
|
|
|
@@ -117,6 +112,7 @@ export function getCombinedByDominant(com1, com2, maxDist = 0, tolerance = 1) {
|
|
|
117
112
|
cp1: Q1,
|
|
118
113
|
cp2: Q2,
|
|
119
114
|
p: Q3,
|
|
115
|
+
t0
|
|
120
116
|
};
|
|
121
117
|
|
|
122
118
|
|
|
@@ -126,39 +122,46 @@ export function getCombinedByDominant(com1, com2, maxDist = 0, tolerance = 1) {
|
|
|
126
122
|
cp1: Q2,
|
|
127
123
|
cp2: Q1,
|
|
128
124
|
p: Q0,
|
|
125
|
+
t0
|
|
129
126
|
}
|
|
130
127
|
}
|
|
131
128
|
|
|
132
129
|
|
|
133
|
-
let tMid = (1 - t0)*0.5
|
|
130
|
+
let tMid = (1 - t0) * 0.5;
|
|
131
|
+
//tMid = (1 +t0) * 0.5;
|
|
132
|
+
let tSplit = t0 - 1;
|
|
134
133
|
//tMid = 0.5;
|
|
135
|
-
|
|
134
|
+
|
|
135
|
+
//console.log(1 - t0);
|
|
136
|
+
|
|
136
137
|
|
|
137
138
|
let ptM = pointAtT([result.p0, result.cp1, result.cp2, result.p], tMid, false, true)
|
|
138
139
|
let seg1_cp2 = ptM.cpts[2]
|
|
139
140
|
//let seg2_cp1 = ptM.cpts[3]
|
|
140
141
|
|
|
141
|
-
|
|
142
142
|
let ptI_1 = checkLineIntersection(ptM, seg1_cp2, result.p0, ptI, false)
|
|
143
143
|
let ptI_2 = checkLineIntersection(ptM, seg1_cp2, result.p, ptI, false)
|
|
144
144
|
|
|
145
145
|
|
|
146
|
-
let
|
|
147
|
-
|
|
146
|
+
//let tscale =(1 + t0)
|
|
147
|
+
//console.log('tscale', tscale);
|
|
148
|
+
let cp1_2 = interpolate(result.p0, ptI_1, 1.333 )
|
|
149
|
+
let cp2_2 = interpolate(result.p, ptI_2, 1.333 )
|
|
148
150
|
|
|
149
151
|
// test self intersections and exit
|
|
150
|
-
let cp_intersection = checkLineIntersection(com1_o.p0, cp1_2, com2_o.p, cp2_2, true
|
|
151
|
-
if(cp_intersection){
|
|
152
|
+
let cp_intersection = checkLineIntersection(com1_o.p0, cp1_2, com2_o.p, cp2_2, true)
|
|
153
|
+
if (cp_intersection) {
|
|
152
154
|
//renderPoint(markers, cp_intersection )
|
|
153
155
|
return commands;
|
|
154
156
|
}
|
|
155
157
|
|
|
158
|
+
if (debug) renderPoint(markers, ptM, 'purple')
|
|
156
159
|
|
|
157
160
|
result.cp1 = cp1_2
|
|
158
161
|
result.cp2 = cp2_2
|
|
159
162
|
|
|
160
|
-
// check distances
|
|
161
163
|
|
|
164
|
+
// check distances between original starting point and extrapolated
|
|
162
165
|
let dist3 = getDistAv(com1_o.p0, result.p0)
|
|
163
166
|
let dist4 = getDistAv(com2_o.p, result.p)
|
|
164
167
|
let dist5 = (dist3 + dist4)
|
|
@@ -170,13 +173,43 @@ export function getCombinedByDominant(com1, com2, maxDist = 0, tolerance = 1) {
|
|
|
170
173
|
result.corner = com2_o.corner
|
|
171
174
|
result.dimA = com2_o.dimA
|
|
172
175
|
result.directionChange = com2_o.directionChange
|
|
176
|
+
result.type = 'C'
|
|
173
177
|
result.values = [result.cp1.x, result.cp1.y, result.cp2.x, result.cp2.y, result.p.x, result.p.y]
|
|
174
178
|
|
|
175
179
|
|
|
176
|
-
|
|
177
|
-
// check if completely off
|
|
180
|
+
// extrapolated starting point is not completely off
|
|
178
181
|
if (dist5 < maxDist) {
|
|
179
182
|
|
|
183
|
+
/*
|
|
184
|
+
let tTotal = 1 + Math.abs(t0);
|
|
185
|
+
let tSplit = reverse ? 1 + t0 : Math.abs(t0);
|
|
186
|
+
//tSplit = reverse ? 1 + t0 : Math.abs(t0) / tTotal;
|
|
187
|
+
//console.log('t0', t0, tMid, 'tSplit', tSplit);
|
|
188
|
+
|
|
189
|
+
let pO = pointAtT([com2_o.p0, com2_o.cp1, com2_o.cp2, com2_o.p], t0);
|
|
190
|
+
*/
|
|
191
|
+
|
|
192
|
+
// split t to meet original mid segment start point
|
|
193
|
+
let tSplit = reverse ? 1 + t0 : Math.abs(t0);
|
|
194
|
+
|
|
195
|
+
let tTotal = 1 + Math.abs(t0);
|
|
196
|
+
tSplit = reverse ? 1 + t0 : Math.abs(t0) / tTotal;
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
//console.log('t0', t0, tMid, 'tSplit', tSplit);
|
|
200
|
+
|
|
201
|
+
let ptSplit = pointAtT([result.p0, result.cp1, result.cp2, result.p], tSplit);
|
|
202
|
+
let distSplit = getDistAv(ptSplit, com1.p)
|
|
203
|
+
//console.log('distS', distS, maxDist );
|
|
204
|
+
|
|
205
|
+
// not close enough - exit
|
|
206
|
+
if (distSplit > maxDist * tolerance ) {
|
|
207
|
+
//renderPoint(markers, ptSplit, 'cyan', '1%')
|
|
208
|
+
//renderPoint(markers, com1.p, 'red', '0.5%')
|
|
209
|
+
return commands;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
180
213
|
// compare combined with original area
|
|
181
214
|
let pathData0 = [
|
|
182
215
|
{ type: 'M', values: [com1_o.p0.x, com1_o.p0.y] },
|
|
@@ -193,28 +226,24 @@ export function getCombinedByDominant(com1, com2, maxDist = 0, tolerance = 1) {
|
|
|
193
226
|
let areaN = getPathArea(pathDataN)
|
|
194
227
|
let areaDiff = Math.abs(areaN / area0 - 1)
|
|
195
228
|
|
|
196
|
-
result.error = areaDiff *
|
|
229
|
+
result.error = areaDiff * 5 * tolerance;
|
|
197
230
|
//result.error = areaDiff + dist5;
|
|
198
231
|
|
|
199
|
-
|
|
232
|
+
//debug=true;
|
|
200
233
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
//renderPath(markers, d, 'orange')
|
|
205
|
-
//console.log('areaDiff', areaDiff);
|
|
206
|
-
|
|
207
|
-
} else {
|
|
208
|
-
// renderPath(markers, d, 'red')
|
|
209
|
-
// console.log('areaDiff', areaDiff);
|
|
234
|
+
if (debug) {
|
|
235
|
+
let d = pathDataToD(pathDataN)
|
|
236
|
+
renderPath(markers, d, 'orange')
|
|
210
237
|
}
|
|
211
238
|
|
|
212
|
-
|
|
213
|
-
|
|
239
|
+
// success!!!
|
|
240
|
+
if (areaDiff < 0.05 * tolerance) {
|
|
241
|
+
commands = [result];
|
|
242
|
+
//console.log('areaDiff', areaDiff);
|
|
243
|
+
}
|
|
214
244
|
}
|
|
215
245
|
|
|
216
246
|
|
|
217
|
-
|
|
218
247
|
//console.log(commands);
|
|
219
248
|
|
|
220
249
|
return commands
|