svg-path-simplify 0.0.5 → 0.0.7

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.
@@ -1,3 +1,19 @@
1
+
2
+ // remove zero-length segments introduced by rounding
3
+ export function removeZeroLengthLinetos_post(pathData) {
4
+ let pathDataOpt = []
5
+ pathData.forEach((com, i) => {
6
+ let { type, values } = com;
7
+ if (type === 'l' || type === 'v' || type === 'h') {
8
+ let hasLength = type === 'l' ? (values.join('') !== '00') : values[0] !== 0
9
+ if (hasLength) pathDataOpt.push(com)
10
+ } else {
11
+ pathDataOpt.push(com)
12
+ }
13
+ })
14
+ return pathDataOpt
15
+ }
16
+
1
17
  export function removeZeroLengthLinetos(pathData) {
2
18
 
3
19
  let M = { x: pathData[0].values[0], y: pathData[0].values[1] }
@@ -280,6 +280,8 @@ export function addExtemesToCommand(p0, values, tMin=0, tMax=1) {
280
280
 
281
281
  if(tArr.length){
282
282
  let commandsSplit = splitCommandAtTValues(p0, values, tArr)
283
+ //console.log('commandsSplit', commandsSplit);
284
+
283
285
  pathDataNew.push(...commandsSplit)
284
286
  extremeCount += commandsSplit.length;
285
287
  }else{
@@ -322,6 +324,8 @@ export function addExtremePoints(pathData, tMin=0, tMax=1) {
322
324
  // add extremes
323
325
  if (type === 'C' || type === 'Q') {
324
326
  let comExt = addExtemesToCommand(p0, values, tMin, tMax).pathData;
327
+ let comExt2 = com;
328
+ //comExt2.valu
325
329
  //console.log('comExt', comExt);
326
330
  pathDataNew.push(...comExt )
327
331
  }
@@ -1,12 +1,15 @@
1
- import { pointAtT } from "./geometry";
1
+ import { getDistAv, pointAtT } from "./geometry";
2
2
  import { getPolyBBox } from "./geometry_bbox";
3
3
  import { addDimensionData, analyzePathData } from "./pathData_analyze";
4
4
  import { addExtremePoints } from "./pathData_split";
5
+ import { pathDataToD } from "./pathData_stringify";
6
+ import { analyzePoly } from "./poly_analyze";
7
+ import { getCurvePathData } from "./poly_to_pathdata";
8
+ import { renderPoint } from "./visualize";
5
9
 
6
- export function pathDataToPolyPlus(pathDataArr = [], addExtremes=true) {
7
10
 
8
- // check if splitting sub paths is required
9
- pathDataArr = Object.hasOwnProperty(pathDataArr[0].type) ? splitSubpaths(pathDataArr) : pathDataArr;
11
+ export function pathDataToPolySingle(pathData, addExtremes = true) {
12
+
10
13
 
11
14
  let dimMin = Infinity;
12
15
  let dimMax = 0;
@@ -16,77 +19,125 @@ export function pathDataToPolyPlus(pathDataArr = [], addExtremes=true) {
16
19
  * add extremes to beziers
17
20
  * to reproduce the shape better
18
21
  */
19
- if(addExtremes){
20
- pathDataArr.forEach((pathData, i) => {
21
-
22
- //pathDataArr[i] = addExtremePoints(pathData)
23
- let pathDataE = addExtremePoints(pathData)
24
-
25
- //pathDataArr[i] = analyzePathData(pathDataE).pathData
26
- pathDataArr[i] = addDimensionData(pathDataE)
27
-
28
- })
22
+ if (addExtremes) {
23
+ pathData = addExtremePoints(pathData, 0.1, 0.9)
29
24
  }
30
25
 
26
+ //console.log(pathData);
27
+
28
+ let pathDataPlus = analyzePathData(pathData);
29
+ let { bb } = pathDataPlus;
30
+ let thresh = (bb.width + bb.height) / 2 / 50
31
+
32
+ pathData = pathDataPlus.pathData
33
+
31
34
 
32
35
  /**
33
36
  * approximate min and max segment sizes
34
37
  * for segment splitting
35
38
  */
36
- pathDataArr.forEach(pathData => {
37
-
38
- let dimArr = pathData.filter(com => com.dimA).sort((a, b) => a.dimA - b.DimA)
39
- let dimMinL = dimArr[0].dimA
40
- let dimMaxL = dimArr[dimArr.length - 1].dimA
41
- //console.log('dimArr', dimArr, dimMaxL);
42
- if (dimMinL && dimMinL < dimMin) dimMin = dimMinL;
43
- if (dimMaxL && dimMaxL > dimMax) dimMax = dimMaxL;
44
-
45
- })
39
+ let dimArr = pathData.filter(com => com.dimA).sort((a, b) => a.dimA - b.DimA)
40
+ let dimMinL = dimArr[0].dimA
41
+ let dimMaxL = dimArr[dimArr.length - 1].dimA
42
+ //console.log('dimArr', dimArr, dimMaxL);
43
+ if (dimMinL && dimMinL < dimMin) dimMin = dimMinL;
44
+ if (dimMaxL && dimMaxL > dimMax) dimMax = dimMaxL;
46
45
 
47
46
  //console.log(dimMin, dimMax);
48
47
 
49
48
  // find split point based on smallest point distance
50
- dimMin = (dimMin * 2 + dimMax) / 2 * 0.5
49
+ dimMin = (dimMin * 2 + dimMax) / 2 / 4
50
+ //dimMin = (bb.width + bb.height) / 2 / 8
51
51
 
52
52
  // collect vertices
53
53
  let polyArr = [];
54
54
 
55
+ let p0 = { x: pathData[0].p0.x, y: pathData[0].p0.y, extreme: pathData[0].extreme, corner: pathData[0].corner }
56
+ let poly = [p0];
57
+
58
+ for (let i = 1, l = pathData.length; i < l; i++) {
55
59
 
56
- pathDataArr.forEach(pathData => {
60
+ let com = pathData[i];
61
+ let { type, values, extreme = false, corner = false, dimA = null, p0, p, cp1 = null, cp2 = null } = com;
57
62
 
58
- let poly = [pathData[0].p0];
63
+ dimA = getDistAv(p0, p);
59
64
 
60
- pathData.forEach(com => {
61
65
 
62
- let { type, values, dimA = null, p0, p, cp1 = null, cp2 = null } = com;
63
- let split = type === 'C' && dimA ? Math.ceil(dimA / dimMin) : 0;
66
+ if(extreme){
67
+ //renderPoint(markers, p, 'cyan')
68
+ }
64
69
 
65
- if (type === 'C' && split) {
70
+ let split = (type === 'C' || type === 'Q') && dimA ? Math.ceil(dimA / dimMin) : 0;
66
71
 
67
- let splitT = 1 / split;
68
72
 
69
- for (let i = 1; i < split; i++) {
73
+ //console.log(com);
74
+ p.extreme = extreme
75
+ p.corner = corner
70
76
 
71
- let t = splitT * i;
72
- let ptI = pointAtT([p0, cp1, cp2, p], t)
73
- poly.push(ptI)
74
- }
77
+ //console.log(p);
75
78
 
79
+ if ((type === 'C' || type === 'Q') && split) {
80
+ let splitT = 1 / split;
81
+ for (let i = 1; i < split; i++) {
82
+ let t = splitT * i;
83
+ let cpts = type === 'C' ? [cp1, cp2] : [cp1];
84
+ let ptI = pointAtT([p0, ...cpts, p], t)
85
+ poly.push(ptI)
76
86
  }
77
- poly.push(p)
78
- })
87
+ }
88
+ poly.push(p)
89
+
90
+ }
91
+
92
+
93
+ // remove short
94
+ let remove = new Set([])
95
+ for (let i = 1, l = poly.length; i < l; i++) {
96
+ let p = poly[i - 1]
97
+ let pN = poly[i]
98
+
99
+ let dist1 = getDistAv(p, pN)
100
+ if (dist1 < thresh && pN.extreme) {
101
+ let pR = p.extreme ? pN : p
102
+ let idx = p.extreme ? i : i - 1
103
+ //console.log('remove', idx);
104
+ remove.add(idx)
105
+ }
106
+ }
107
+
79
108
 
80
- polyArr.push(poly)
109
+ remove = Array.from(remove).reverse();
110
+ //console.log(remove);
81
111
 
82
- /*
83
- let bb = getPolyBBox(poly);
84
- let dimAv = (bb.width+bb.height)/2
85
- console.log('dimAv', dimAv);
86
- */
112
+ for (let i = 0; i < remove.length; i++) {
113
+ let idx = remove[i];
114
+ //console.log('idx', idx);
115
+ poly.splice(idx, 1)
116
+ }
117
+
118
+ poly.splice(poly.length-1, poly.length)
119
+
120
+
121
+ let polyAtt = poly.map(pt => `${pt.x} ${pt.y} `).join(' ')
122
+ //console.log('polyAtt', polyAtt);
123
+
124
+ //markers.insertAdjacentHTML('beforeend', `<polygon points="${polyAtt}" stroke="red" fill="none"/>`)
125
+
126
+
127
+ poly = analyzePoly(poly, false)
128
+ let pathDataP = getCurvePathData(poly, 0.666, true)
129
+ let d = pathDataToD(pathDataP)
87
130
 
88
- })
131
+ console.log(d);
132
+ //markers.insertAdjacentHTML('beforeend', `<path d="${d}" stroke="green" fill="none" stroke-width="1%"/>`)
89
133
 
90
- return polyArr
134
+
135
+
136
+
137
+
138
+ return poly
91
139
 
92
140
  }
141
+
142
+
143
+
@@ -3,7 +3,7 @@ import { getPolygonArea } from "./geometry_area";
3
3
  import { getPolyBBox } from "./geometry_bbox";
4
4
  import { renderPoint } from "./visualize";
5
5
 
6
- export function analyzePoly(pts) {
6
+ export function analyzePoly(pts, debug=false) {
7
7
 
8
8
  let l = pts.length;
9
9
  let polyArea = getPolygonArea(pts, true)
@@ -75,22 +75,26 @@ export function analyzePoly(pts) {
75
75
  /*
76
76
  */
77
77
 
78
- if ((isExtreme && isCorner)) {
79
- isExtreme = false;
80
- directionChange = false;
81
- //isCorner = false;
82
- }
83
-
84
- if (isExtreme) {
85
- renderPoint(markers, pt1, 'cyan', '1%');
86
- }
87
-
88
- if (isCorner) {
89
- renderPoint(markers, pt1, 'purple', '0.5%');
90
- }
78
+ if(debug){
79
+
80
+ if ((isExtreme && isCorner)) {
81
+ isExtreme = false;
82
+ directionChange = false;
83
+ //isCorner = false;
84
+ }
85
+
86
+ if (isExtreme) {
87
+ renderPoint(markers, pt1, 'cyan', '1%');
88
+ }
89
+
90
+ if (isCorner) {
91
+ renderPoint(markers, pt1, 'purple', '0.5%');
92
+ }
93
+
94
+ if (directionChange) {
95
+ renderPoint(markers, pt1, 'orange', '1.5%', '0.5');
96
+ }
91
97
 
92
- if (directionChange) {
93
- renderPoint(markers, pt1, 'orange', '1.5%', '0.5');
94
98
  }
95
99
 
96
100
 
@@ -1,3 +1,12 @@
1
+ export function removeEmptySVGEls(svg) {
2
+ let els = svg.querySelectorAll('g, defs');
3
+ els.forEach(el => {
4
+ if (!el.children.length) el.remove()
5
+ })
6
+ }
7
+
8
+
9
+
1
10
  export function cleanUpSVG(svgMarkup, {
2
11
  returnDom=false,
3
12
  removeHidden=true,
@@ -74,7 +83,7 @@ function removeNameSpaceAtts(el) {
74
83
  });
75
84
  }
76
85
 
77
- function stringifySVG(svg){
86
+ export function stringifySVG(svg){
78
87
  let markup = new XMLSerializer().serializeToString(svg);
79
88
  markup = markup
80
89
  .replace(/\t/g, "")
package/test.js ADDED
@@ -0,0 +1,14 @@
1
+ import { svgPathSimplify } from 'svg-path-simplify';
2
+
3
+ let pathDataString =
4
+ `
5
+ M 57.13 15.5
6
+ c 13.28 0 24.53 8.67 28.42 20.65
7
+ c 0.94 2.91 1.45 6.01 1.45 9.23
8
+ `
9
+
10
+ // try to simplify
11
+ let pathDataOpt = svgPathSimplify(pathDataString);
12
+
13
+ // simplified pathData
14
+ console.log(pathDataOpt)