svg-path-simplify 0.4.4 → 0.4.6
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/CHANGELOG.md +19 -0
- package/README.md +9 -1
- package/dist/svg-path-simplify.esm.js +1649 -1205
- package/dist/svg-path-simplify.esm.min.js +2 -2
- package/dist/svg-path-simplify.js +1649 -1204
- package/dist/svg-path-simplify.min.js +2 -2
- package/dist/svg-path-simplify.pathdata.esm.js +301 -637
- package/dist/svg-path-simplify.pathdata.esm.min.js +2 -2
- package/dist/svg-path-simplify.poly.cjs +8 -9
- package/drawing.svg +62 -0
- package/index.html +13 -8
- package/package.json +1 -1
- package/src/index.js +3 -1
- package/src/pathData_get_intersections.js +777 -0
- package/src/pathData_offset.js +201 -0
- package/src/pathData_simplify_cubic.js +19 -21
- package/src/pathData_simplify_cubic_extrapolate.js +147 -8
- package/src/pathData_simplify_cubicsToArcs.js +65 -21
- package/src/pathSimplify-main.js +267 -64
- package/src/pathSimplify-presets.js +1 -1
- package/src/poly-fit-curve-schneider.js +171 -132
- package/src/poly-fit-curve-schneider_check_bulge.js +131 -0
- package/src/poly-offset.js +133 -0
- package/src/simplify_poly_RC.js +29 -7
- package/src/svg-getAttributes.js +1 -1
- package/src/svgii/geometry.js +130 -27
- package/src/svgii/geometry_bbox.js +1 -1
- package/src/svgii/geometry_length.js +1 -1
- package/src/svgii/pathData_analyze.js +6 -28
- package/src/svgii/pathData_convert.js +63 -15
- package/src/svgii/pathData_remove_collinear.js +32 -36
- package/src/svgii/pathData_reorder.js +3 -2
- package/src/svgii/pathData_simplify_refineExtremes.js +1 -3
- package/src/svgii/pathData_stringify.js +132 -6
- package/src/svgii/pathData_toPolygon.js +33 -23
- package/src/svgii/poly_analyze.js +272 -125
- package/src/svgii/poly_analyze_cleanup.js +311 -0
- package/src/svgii/poly_analyze_getTangents.js +125 -0
- package/src/svgii/poly_analyze_get_chunks.js +3 -1
- package/src/svgii/poly_normalize.js +21 -8
- package/src/svgii/poly_to_pathdata.js +477 -8
- package/src/svgii/rounding.js +35 -14
- package/src/svgii/svg_cleanup.js +44 -51
- package/src/svgii/svg_cleanup_convertPathLength.js +5 -0
- package/src/svgii/svg_cleanup_normalize_transforms.js +2 -2
- package/src/svgii/visualize.js +33 -2
- package/v/0.4.5/index.html +1040 -0
- package/v/0.4.5/svg-path-simplify.js +13227 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import { rad2Deg } from "../constants";
|
|
2
|
+
import { checkLineIntersection, getAngleFromDelta, getDistManhattan, interpolate } from "./geometry";
|
|
3
|
+
import { getPolygonArea } from "./geometry_area";
|
|
4
|
+
import { getPolyBBox } from "./geometry_bbox";
|
|
5
|
+
import { renderPoint, renderPoly } from "./visualize";
|
|
6
|
+
|
|
7
|
+
export function refineAdjacentPolyExtremes(pts = []) {
|
|
8
|
+
|
|
9
|
+
let l = pts.length;
|
|
10
|
+
|
|
11
|
+
let { x, y, width, height, top, bottom, left, right } = getPolyBBox(pts);
|
|
12
|
+
let threshShort = (width + height) * 0.05;
|
|
13
|
+
let thresh = (width + height) * 0.001;
|
|
14
|
+
|
|
15
|
+
let pt0 = pts[0];
|
|
16
|
+
let ptLast = pts[l - 1];
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* cleanup close path - almost vertical or horizontal
|
|
21
|
+
* average start and end extremes
|
|
22
|
+
*/
|
|
23
|
+
let dx = Math.abs(ptLast.x - pt0.x)
|
|
24
|
+
let dy = Math.abs(ptLast.y - pt0.y)
|
|
25
|
+
|
|
26
|
+
if (dy < threshShort || dx < threshShort) {
|
|
27
|
+
|
|
28
|
+
if (pt0.isExtreme && !pt0.isCorner) {
|
|
29
|
+
|
|
30
|
+
let xAv = (pt0.x + ptLast.x) * 0.5
|
|
31
|
+
let yAv = (pt0.y + ptLast.y) * 0.5
|
|
32
|
+
|
|
33
|
+
pt0.x = xAv
|
|
34
|
+
pt0.y = yAv
|
|
35
|
+
|
|
36
|
+
ptLast.x = xAv
|
|
37
|
+
ptLast.y = yAv
|
|
38
|
+
ptLast.isExtreme = true;
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if (dy < thresh) {
|
|
42
|
+
ptLast.tangentR.y = pt0.y
|
|
43
|
+
ptLast.tangentL.y = pt0.y
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
if (dx < thresh) {
|
|
47
|
+
ptLast.tangentR.x = pt0.x
|
|
48
|
+
ptLast.tangentL.x = pt0.x
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
for (let i = 1; i < l; i++) {
|
|
55
|
+
let p0 = i > 0 ? pts[i - 1] : pts[l - 1];
|
|
56
|
+
let p1 = pts[i];
|
|
57
|
+
let p2 = i < l - 1 ? pts[i + 1] : pts[l - 1];
|
|
58
|
+
let dist = getDistManhattan(p1, p2)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
let { isHorizontal, isVertical, isCorner, isLong, isExtreme, isSemiExtreme, isDirChange } = p1
|
|
62
|
+
let offset = 0;
|
|
63
|
+
|
|
64
|
+
let extremes = []
|
|
65
|
+
|
|
66
|
+
/*
|
|
67
|
+
if(isExtreme && p0.isCorner && !isLong && !isCorner){
|
|
68
|
+
isExtreme= false
|
|
69
|
+
p1.isExtreme = false
|
|
70
|
+
p1.isHorizontal = false
|
|
71
|
+
p1.isVertical = false
|
|
72
|
+
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
if(isExtreme && p2.isCorner && !isLong && !isCorner && dist<threshShort*0.5){
|
|
80
|
+
isExtreme= false
|
|
81
|
+
p1.isExtreme = false
|
|
82
|
+
p1.isHorizontal = false
|
|
83
|
+
p1.isVertical = false
|
|
84
|
+
|
|
85
|
+
if(isVertical){
|
|
86
|
+
p2.tangentL.x = p2.x
|
|
87
|
+
}
|
|
88
|
+
if(isHorizontal){
|
|
89
|
+
p2.tangentL.y = p2.y
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
if (isExtreme && !isCorner && p2.isExtreme) {
|
|
97
|
+
extremes.push(p1);
|
|
98
|
+
|
|
99
|
+
for (let j = i + 1; j < l; j++) {
|
|
100
|
+
let p2 = pts[j]
|
|
101
|
+
dist = getDistManhattan(p1, p2)
|
|
102
|
+
|
|
103
|
+
if (dist * 0.75 >= threshShort || p2.isCorner || p2.isDirChange) {
|
|
104
|
+
break
|
|
105
|
+
}
|
|
106
|
+
if (p2.isExtreme && !p2.isDirChange && !p2.isCorner) {
|
|
107
|
+
extremes.push(p2);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
//extremes = []
|
|
112
|
+
if (extremes.length > 1) {
|
|
113
|
+
|
|
114
|
+
//let ptPrev = pts[i - 2]
|
|
115
|
+
//let ptNext = pts[i + extremes.length]
|
|
116
|
+
|
|
117
|
+
//renderPoint(markers, ptPrev, 'orange', '2%')
|
|
118
|
+
//renderPoint(markers, ptNext, 'orange', '2%')
|
|
119
|
+
|
|
120
|
+
//let lenEx = extremes.length
|
|
121
|
+
//let idxM = Math.ceil(lenEx * 0.5)
|
|
122
|
+
//let extremeMid = extremes[idxM]
|
|
123
|
+
|
|
124
|
+
// find best extreme according to angle
|
|
125
|
+
let angleDiffMin = Infinity;
|
|
126
|
+
//let bestMatch = extremes[Math.floor(extremes.length*0.5)];
|
|
127
|
+
let bestMatch = extremes[0];
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
extremes.forEach(pt => {
|
|
131
|
+
//renderPoint(markers, pt, 'red', '3%')
|
|
132
|
+
let angle = Math.abs(getAngleFromDelta(pt.dx2, pt.dy2, false)) * rad2Deg
|
|
133
|
+
let angleDiff = angle > 160 ? Math.abs(180 - angle) : (angle > 60 ? Math.abs(90 - angle) : angle)
|
|
134
|
+
pt.angle = angle;
|
|
135
|
+
pt.angleDiff = angleDiff;
|
|
136
|
+
|
|
137
|
+
if (angleDiff < angleDiffMin) {
|
|
138
|
+
bestMatch = pt;
|
|
139
|
+
angleDiffMin = angleDiff
|
|
140
|
+
//if(!angleDiff) matches.push(pt)
|
|
141
|
+
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
//renderPoint(markers, bestMatch, 'red', '4.5%', '0.5')
|
|
146
|
+
//renderPoint(markers, bestMatch, 'blue', '4.5%', '0.5')
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
//console.log('matches', bestMatch, extremes);
|
|
150
|
+
|
|
151
|
+
let extremes2 = []
|
|
152
|
+
|
|
153
|
+
extremes.forEach((pt, i) => {
|
|
154
|
+
|
|
155
|
+
//let isBestMatch = pt.x === bestMatch.x && pt.y === bestMatch.y;
|
|
156
|
+
let isBestMatch = pt === bestMatch;
|
|
157
|
+
//renderPoint(markers, bestMatch, 'blue', '4.5%', '0.5')
|
|
158
|
+
|
|
159
|
+
if (isBestMatch) {
|
|
160
|
+
//extremes2.push(pt)
|
|
161
|
+
//renderPoint(markers, pt, 'red', '4.5%', '0.5')
|
|
162
|
+
|
|
163
|
+
if (pt.isHorizontal) {
|
|
164
|
+
pt.tangentL.y = pt.y
|
|
165
|
+
pt.tangentR.y = pt.y
|
|
166
|
+
}
|
|
167
|
+
if (pt.isVertical) {
|
|
168
|
+
pt.tangentL.x = pt.x
|
|
169
|
+
pt.tangentR.x = pt.x
|
|
170
|
+
}
|
|
171
|
+
//renderPoint(markers, extremes[0], 'brown', '2.5%', '0.5')
|
|
172
|
+
//renderPoint(markers, extremes[extremes.length - 1], 'magenta', '2.5%', '0.5')
|
|
173
|
+
// renderPoint(markers, pt, 'green', '3%', '0.5')
|
|
174
|
+
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
//console.log('bestMatch', bestMatch);
|
|
180
|
+
//renderPoint(markers, pt, 'blue', '4.5%', '0.5')
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if (bestMatch) {
|
|
184
|
+
|
|
185
|
+
if (!isBestMatch && (pt.x === bestMatch.x || pt.y === bestMatch.y)) {
|
|
186
|
+
extremes2.push(pt)
|
|
187
|
+
}
|
|
188
|
+
pt.isExtreme = false
|
|
189
|
+
pt.isHorizontal = false
|
|
190
|
+
pt.isVertical = false
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// average coordinates
|
|
199
|
+
if (extremes2.length) {
|
|
200
|
+
bestMatch.x = (extremes2[0].x + bestMatch.x) * 0.5
|
|
201
|
+
bestMatch.y = (extremes2[0].y + bestMatch.y) * 0.5
|
|
202
|
+
//pts.splice(extremes2[0].idx, 1)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
//console.log('extremes2', extremes2);
|
|
206
|
+
i += extremes.length
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function cleanupPolyKeypoints(pts = []) {
|
|
216
|
+
|
|
217
|
+
let l = pts.length;
|
|
218
|
+
|
|
219
|
+
let { x, y, width, height, top, bottom, left, right } = getPolyBBox(pts);
|
|
220
|
+
//let thresh0 = (width + height) * 0.025;
|
|
221
|
+
let thresh = (width + height) * 0.001;
|
|
222
|
+
|
|
223
|
+
let pt0 = pts[0];
|
|
224
|
+
//let ptLast = pts[l - 1];
|
|
225
|
+
let ptsClean = [pt0];
|
|
226
|
+
|
|
227
|
+
//renderPoint(markers, ptLast)
|
|
228
|
+
|
|
229
|
+
for (let i = 1; i < l; i++) {
|
|
230
|
+
let p0 = i > 0 ? pts[i - 1] : pts[l - 1];
|
|
231
|
+
let p1 = pts[i];
|
|
232
|
+
let p2 = i < l - 1 ? pts[i + 1] : pts[l - 1];
|
|
233
|
+
|
|
234
|
+
let { isHorizontal, isVertical, isCorner, isLong, isExtreme, isSemiExtreme, isDirChange } = p1
|
|
235
|
+
let offset = 0;
|
|
236
|
+
|
|
237
|
+
if (!isSemiExtreme){
|
|
238
|
+
//ptsClean.push(p1, p2)
|
|
239
|
+
continue
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (isSemiExtreme || isExtreme) {
|
|
243
|
+
let semiExtremes = isSemiExtreme ? [p1] : [];
|
|
244
|
+
let extremes = isExtreme ? [p1] : [];
|
|
245
|
+
|
|
246
|
+
for (let j = i + 1; j < l; j++) {
|
|
247
|
+
let p2 = pts[j]
|
|
248
|
+
|
|
249
|
+
if (!p2.isSemiExtreme || p2.isExtreme || p2.isCorner){
|
|
250
|
+
break
|
|
251
|
+
}
|
|
252
|
+
semiExtremes.push(p2)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (semiExtremes.length > 1) {
|
|
256
|
+
|
|
257
|
+
//interpolate
|
|
258
|
+
let semiExtremeMid = semiExtremes[Math.floor(semiExtremes.length*0.5)]
|
|
259
|
+
let p1_1 = semiExtremes[0]
|
|
260
|
+
let p2_1 = semiExtremes[semiExtremes.length - 1]
|
|
261
|
+
let ptI = checkLineIntersection(p1_1, p1_1.tangentR, p2_1, p2_1.tangentL, false, true)
|
|
262
|
+
//console.log(ptI);
|
|
263
|
+
//console.log('tangents', p1_1, p1_1.tangentR, p2_1, p2_1.tangentL);
|
|
264
|
+
|
|
265
|
+
//renderPoly(markers, [p1_1, p1_1.tangentR], 'red', '2%')
|
|
266
|
+
semiExtremes.forEach(pt=>{
|
|
267
|
+
pt.isSemiExtreme=false
|
|
268
|
+
})
|
|
269
|
+
semiExtremeMid.isSemiExtreme=true;
|
|
270
|
+
|
|
271
|
+
// interpolate mid point
|
|
272
|
+
if (ptI) {
|
|
273
|
+
let pI_1 = interpolate(p1_1, ptI, 0.5)
|
|
274
|
+
let pI_2 = interpolate(p2_1, ptI, 0.5)
|
|
275
|
+
let pI_3 = interpolate(pI_2, pI_1, 0.5)
|
|
276
|
+
//renderPoint(markers, pI_3, 'red', '2%')
|
|
277
|
+
|
|
278
|
+
semiExtremeMid.x = pI_3.x
|
|
279
|
+
semiExtremeMid.y = pI_3.y
|
|
280
|
+
semiExtremeMid.tangentL = pI_1
|
|
281
|
+
semiExtremeMid.tangentR = pI_2
|
|
282
|
+
//p1.idx=i
|
|
283
|
+
//offset += semiExtremes.length - 1
|
|
284
|
+
//ptsClean.push(p1)
|
|
285
|
+
|
|
286
|
+
i += offset
|
|
287
|
+
continue
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
//console.log('semiExtremes', semiExtremes);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
//p1.idx=i
|
|
295
|
+
ptsClean.push(p1)
|
|
296
|
+
// find significant of same type
|
|
297
|
+
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
/*
|
|
302
|
+
// update index
|
|
303
|
+
ptsClean.forEach((pt, i) => {
|
|
304
|
+
pt.idx = i
|
|
305
|
+
})
|
|
306
|
+
*/
|
|
307
|
+
//console.log('ptsClean', ptsClean);
|
|
308
|
+
//renderPoint(markers, ptsClean[0], 'green', '4%')
|
|
309
|
+
return pts;
|
|
310
|
+
//return ptsClean;
|
|
311
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { adjustTangentAngle } from "../poly-fit-curve-schneider_check_bulge";
|
|
2
|
+
import { getPolyBBox } from "./geometry_bbox";
|
|
3
|
+
import { renderPoint } from "./visualize";
|
|
4
|
+
|
|
5
|
+
export function getTangents(pts = [], {
|
|
6
|
+
x = 0,
|
|
7
|
+
y = 0,
|
|
8
|
+
width = 0,
|
|
9
|
+
height = 0,
|
|
10
|
+
debug = false,
|
|
11
|
+
closed=false,
|
|
12
|
+
} = {}) {
|
|
13
|
+
|
|
14
|
+
let l = pts.length;
|
|
15
|
+
|
|
16
|
+
// bounding box of this sub poly
|
|
17
|
+
if (!width || !height) {
|
|
18
|
+
({ x, y, width, height } = getPolyBBox(pts));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//console.log(polyArea);
|
|
22
|
+
let thresh = (width + height) * 0.01;
|
|
23
|
+
|
|
24
|
+
// threshold for horizontal or vertical detection
|
|
25
|
+
//let thresh2 = thresh * 0.5
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
for (let i = 0; i < l; i++) {
|
|
29
|
+
let p0 = i > 0 ? pts[i - 1] : pts[l - 1];
|
|
30
|
+
let p1 = pts[i];
|
|
31
|
+
let p2 = i < l - 1 ? pts[i + 1] : pts[l - 1];
|
|
32
|
+
let p3 = i < l - 1 ? pts[i + 2] : pts[l - 1];
|
|
33
|
+
|
|
34
|
+
let { isHorizontal, isVertical, isCorner, isLong, isExtreme, isSemiExtreme, isDirChange } = p1
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
// default
|
|
39
|
+
let tangentL = { x: p1.x - p1.dx2 * 0.5, y: p1.y - p1.dy2 * 0.5 }
|
|
40
|
+
let tangentR = { x: p1.x + p1.dx2 * 0.5, y: p1.y + p1.dy2 * 0.5 }
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
// average first tangent
|
|
44
|
+
if(i===0){
|
|
45
|
+
tangentR = adjustTangentAngle(p2, p1, p2, p3)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* add left and right tangents
|
|
51
|
+
* for later curve fitting
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
if (isHorizontal && !isCorner) {
|
|
55
|
+
tangentL = { x: p1.x - p1.dx2*0.5, y: p1.y }
|
|
56
|
+
tangentR = { x: p1.x + p1.dx2*0.5, y: p1.y }
|
|
57
|
+
}
|
|
58
|
+
else if (isVertical) {
|
|
59
|
+
tangentL = { x: p1.x , y: p1.y - p1.dy2*0.5 }
|
|
60
|
+
tangentR = { x: p1.x , y: p1.y + p1.dy2*0.5 }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
if (!isExtreme && p1.isLong) {
|
|
65
|
+
tangentL = { x: p1.x - p1.dx*0.5, y: p1.y - p1.dy*0.5 }
|
|
66
|
+
tangentR = { x: p1.x + p1.dx*0.5, y: p1.y + p1.dy*0.5 }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
//isDirChange && !isCorner && !isHorizontal && !isVertical
|
|
72
|
+
if (isDirChange && !isCorner && !isExtreme) {
|
|
73
|
+
p1.tangentL = { x: p1.x-p1.dx2*0.5, y: p1.y-p1.dy2*0.5 }
|
|
74
|
+
p1.tangentR = { x: p1.x+p1.dx2*0.5, y: p1.y+p1.dy2*0.5 }
|
|
75
|
+
}
|
|
76
|
+
*/
|
|
77
|
+
|
|
78
|
+
if (isCorner) {
|
|
79
|
+
|
|
80
|
+
tangentL = {x:p0.x, y:p0.y}
|
|
81
|
+
tangentR = {x:p2.x, y:p2.y}
|
|
82
|
+
|
|
83
|
+
//let p0_1 = pts[i - 2] ? pts[i - 2] : pts[l - 2]
|
|
84
|
+
let p0_1 = pts[i - 2] ? pts[i - 2] : pts[l - 1]
|
|
85
|
+
//let p2_1 = pts[i + 2] ? pts[i + 2] : pts[l - 2]
|
|
86
|
+
let p2_1 = pts[i + 2] ? pts[i + 2] : pts[1]
|
|
87
|
+
|
|
88
|
+
// adjust angle
|
|
89
|
+
if (!p0.isCorner) {
|
|
90
|
+
tangentL = adjustTangentAngle(p0, p1, p0, p0_1)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!p2.isCorner) {
|
|
94
|
+
tangentR = adjustTangentAngle(tangentR, p1, p2, p2_1)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/*
|
|
98
|
+
renderPoint(markers, p0, 'darkblue', '0.75%', '0.5')
|
|
99
|
+
// renderPoint(markers, p0_1, 'blue', '0.5%')
|
|
100
|
+
renderPoint(markers, tangentL, 'blue', '0.5%', '0.5')
|
|
101
|
+
renderPoint(markers, tangentR, 'blue', '0.5%', '0.5')
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
p1.tangentL = tangentL
|
|
107
|
+
p1.tangentR = tangentR
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
//console.log('t', p1.tangentL, p1.tangentR);
|
|
111
|
+
|
|
112
|
+
/*
|
|
113
|
+
debug = true
|
|
114
|
+
if(debug){
|
|
115
|
+
if (isCorner || isSemiExtreme || isDirChange || isExtreme) {
|
|
116
|
+
renderPoint(markers, p1.tangentL, 'darkred', '0.5%')
|
|
117
|
+
renderPoint(markers, p1.tangentR, 'darkblue', '0.5%')
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
}
|
|
@@ -27,7 +27,9 @@ export function getPolyChunks(pts,
|
|
|
27
27
|
|
|
28
28
|
// start new chunk
|
|
29
29
|
// keepInflections && p1.isDirChange
|
|
30
|
-
if ((keepExtremes && p1.isExtreme || keepCorners && p1.isCorner
|
|
30
|
+
if ((keepExtremes && p1.isExtreme || keepCorners && p1.isCorner ||
|
|
31
|
+
(keepInflections && p1.isDirChange && !p1.isExtreme && !p1.isCorner )
|
|
32
|
+
)) {
|
|
31
33
|
idx++
|
|
32
34
|
chunks.push([])
|
|
33
35
|
}
|
|
@@ -4,20 +4,33 @@ export function normalizePoly(pts, {
|
|
|
4
4
|
flatten = false
|
|
5
5
|
} = {}) {
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
// is stringified flat point attribute
|
|
8
|
-
if(typeof pts === 'string' && !isNaN(pts[0])){
|
|
9
|
+
if (typeof pts === 'string' && !isNaN(pts[0])) {
|
|
9
10
|
pts = toPointArray(pts.split(/,| /).filter(Boolean).map(Number));
|
|
10
11
|
return pts
|
|
11
12
|
}
|
|
12
13
|
|
|
14
|
+
if (pts.length && typeof pts[0] === 'string') {
|
|
15
|
+
pts = pts.map(pt => {
|
|
16
|
+
return toPointArray(pt.split(/,| /).filter(Boolean).map(Number))
|
|
17
|
+
});
|
|
18
|
+
pts = pts.flat(2)
|
|
19
|
+
//console.log(pts);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
13
23
|
if (flatten) pts = pts.flat(2);
|
|
24
|
+
|
|
25
|
+
|
|
14
26
|
let poly = toArray ? polyPtsToArray(pts) : polyArrayToObject(pts)
|
|
15
27
|
return poly
|
|
16
28
|
}
|
|
17
29
|
|
|
18
30
|
|
|
19
|
-
export function polyArrayToObject(pts) {
|
|
20
|
-
|
|
31
|
+
export function polyArrayToObject(pts = []) {
|
|
32
|
+
//console.log(pts);
|
|
33
|
+
if (!pts.length) return [];
|
|
21
34
|
// is point object array
|
|
22
35
|
if (pts[0].x !== undefined && pts[0].y !== undefined) return pts
|
|
23
36
|
|
|
@@ -35,7 +48,7 @@ export function polyArrayToObject(pts) {
|
|
|
35
48
|
return poly
|
|
36
49
|
}
|
|
37
50
|
|
|
38
|
-
else if(pts.length>3){
|
|
51
|
+
else if (pts.length > 3) {
|
|
39
52
|
pts = toPointArray(pts)
|
|
40
53
|
return pts
|
|
41
54
|
}
|
|
@@ -65,13 +78,13 @@ export function polyPtsToArray(pts) {
|
|
|
65
78
|
export function toPointArray(pts) {
|
|
66
79
|
let ptArr = [];
|
|
67
80
|
|
|
68
|
-
if(pts[0].length===2){
|
|
69
|
-
for (let i = 0, l = pts.length; i < l; i
|
|
81
|
+
if (pts[0].length === 2) {
|
|
82
|
+
for (let i = 0, l = pts.length; i < l; i++) {
|
|
70
83
|
let pt = pts[i]
|
|
71
|
-
ptArr.push({ x: pt[0], y:pt[1] });
|
|
84
|
+
ptArr.push({ x: pt[0], y: pt[1] });
|
|
72
85
|
}
|
|
73
86
|
|
|
74
|
-
}else{
|
|
87
|
+
} else {
|
|
75
88
|
for (let i = 1, l = pts.length; i < l; i += 2) {
|
|
76
89
|
ptArr.push({ x: pts[i - 1], y: pts[i] });
|
|
77
90
|
}
|