svg-path-simplify 0.2.7 → 0.3.4

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.
@@ -3,7 +3,105 @@ import { getPolyBBox } from "./svgii/geometry_bbox";
3
3
  import { renderPoint } from "./svgii/visualize";
4
4
 
5
5
 
6
- export function simplifyRDP(pts, {
6
+ export function simplifyPolyRDP(pts, {quality = 0.9, width = 0, height = 0}={}) {
7
+
8
+ /**
9
+ * switch between absolute or
10
+ * quality based relative thresholds
11
+ */
12
+ let isAbsolute = false;
13
+
14
+ if (typeof quality === 'string') {
15
+ isAbsolute = true;
16
+ quality = parseFloat(quality);
17
+ }
18
+
19
+ if (pts.length < 4 || (!isAbsolute && quality) >= 1) return pts;
20
+
21
+ // convert quality to squaredistance tolerance
22
+ let tolerance = quality;
23
+ //console.log('simplifyRDP', tolerance);
24
+
25
+ if (!isAbsolute) {
26
+
27
+ tolerance = 1 - quality;
28
+
29
+ // adjust for higher qualities
30
+ if (quality > 0.5) tolerance /= 2;
31
+
32
+ /**
33
+ * approximate dimensions
34
+ * adjust tolerance for
35
+ * very small polygons e.g geodata
36
+ */
37
+ if (!width && !height) {
38
+ let polyS = reducePoints(pts, 12);
39
+ ({ width, height } = getPolyBBox(polyS));
40
+ }
41
+
42
+ // average side lengths
43
+ let dimAvg = (width + height) / 2;
44
+ let scale = dimAvg / 100;
45
+ tolerance = (tolerance * (scale)) ** 2
46
+ }
47
+
48
+
49
+ // Square distance from point to segment
50
+ const segmentSquareDistance = (p, p1, p2) => {
51
+ let x = p1.x, y = p1.y;
52
+ let dx = p2.x - x, dy = p2.y - y;
53
+
54
+ if (dx !== 0 || dy !== 0) {
55
+ let t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
56
+ if (t > 1) {
57
+ x = p2.x;
58
+ y = p2.y;
59
+ } else if (t > 0) {
60
+ x += dx * t;
61
+ y += dy * t;
62
+ }
63
+ }
64
+
65
+ return (p.x - x) ** 2 + (p.y - y) ** 2;
66
+ };
67
+
68
+
69
+ // start collecting ptsSmp polyline
70
+ let ptsSmp = [pts[0]];
71
+
72
+ // create processing stack
73
+ let stack = [];
74
+ stack.push([0, pts.length - 1]);
75
+
76
+ while (stack.length > 0) {
77
+ let [first, last] = stack.pop();
78
+ let maxDist = tolerance;
79
+ let index = -1;
80
+
81
+ // Find point with maximum distance
82
+ for (let i = first + 1; i < last; i++) {
83
+ let currentDist = segmentSquareDistance(pts[i], pts[first], pts[last]);
84
+ if (currentDist > maxDist) {
85
+ index = i;
86
+ maxDist = currentDist;
87
+ }
88
+ }
89
+
90
+ // If max distance > tolerance, split and process
91
+ if (maxDist > tolerance) {
92
+ stack.push([index, last]);
93
+ stack.push([first, index]);
94
+ } else {
95
+ ptsSmp.push(pts[last]);
96
+ }
97
+
98
+ }
99
+
100
+ return ptsSmp;
101
+ }
102
+
103
+
104
+ export function simplifyPolyRDP__(pts, {
7
105
  quality = 0.9,
8
106
  width = 0,
9
107
  height = 0,
@@ -28,6 +126,8 @@ export function simplifyRDP(pts, {
28
126
  quality = parseFloat(quality);
29
127
  }
30
128
 
129
+ if(absolute && quality===0) return pts;
130
+
31
131
  if (pts.length < 4 || (!absolute && quality) >= 1) return pts;
32
132
 
33
133
  // convert quality to squaredistance or manhattan tolerance
@@ -8,7 +8,87 @@ import { getDistManhattan, getSquareDistance, reducePoints } from "./svgii/geome
8
8
  import { getPolyBBox } from "./svgii/geometry_bbox";
9
9
  import { renderPoint } from "./svgii/visualize";
10
10
 
11
- export function simplifyRD(pts, {
11
+
12
+
13
+ /**
14
+ * radialDistance simplification
15
+ * sloppy but fast
16
+ */
17
+
18
+ export function simplifyPolyRD(pts, {quality = 0.9, width = 0, height = 0}={}) {
19
+
20
+
21
+ /**
22
+ * switch between absolute or
23
+ * quality based relative thresholds
24
+ */
25
+ let isAbsolute = false;
26
+
27
+ if (typeof quality === 'string') {
28
+ let value = parseFloat(quality);
29
+ isAbsolute = true;
30
+ quality = value;
31
+ }
32
+
33
+ // nothing to do - exit
34
+ if (pts.length < 4 || (!isAbsolute && quality) >= 1) return pts;
35
+
36
+ let p0 = pts[0];
37
+ let pt;
38
+ let ptsSmp = [p0];
39
+
40
+ // convert quality to squaredistance tolerance
41
+ let tolerance = quality;
42
+
43
+ if (!isAbsolute) {
44
+
45
+ // quality to tolerance
46
+ tolerance = 1 - quality;
47
+
48
+
49
+ /**
50
+ * approximate dimensions
51
+ * adjust tolerance for
52
+ * very small polygons e.g geodata
53
+ */
54
+
55
+ if (!width && !height) {
56
+ let polyS = reducePoints(pts, 12);
57
+ ({ width, height } = getPolyBBox(polyS));
58
+ }
59
+ // average side lengths
60
+ let dimAvg = (width + height) / 2;
61
+ let scale = dimAvg / 25;
62
+ tolerance = (tolerance * (scale)) ** 2
63
+
64
+ if (quality > 0.5) tolerance /= 10
65
+
66
+ }
67
+
68
+ //console.log('simplifyRD', tolerance);
69
+
70
+
71
+ for (let i = 1, l = pts.length; i < l; i++) {
72
+ pt = pts[i];
73
+ let dist = getSquareDistance(p0, pt)
74
+
75
+ if (dist > tolerance) {
76
+ ptsSmp.push(pt);
77
+ p0 = pt;
78
+ }
79
+ }
80
+
81
+ // add last point - if not coinciding with first point
82
+ if (p0.x !== pt.x && p0.y !== pt.y) {
83
+ ptsSmp.push(pt);
84
+ }
85
+
86
+ return ptsSmp;
87
+
88
+ }
89
+
90
+
91
+ export function simplifyPolyRD__(pts, {
12
92
  quality = 0.9,
13
93
  width = 0,
14
94
  height = 0,
@@ -24,11 +104,14 @@ export function simplifyRD(pts, {
24
104
  */
25
105
 
26
106
  if (typeof quality === 'string') {
27
- let value = parseFloat(quality);
107
+ let value = parseFloat(quality)**2;
28
108
  absolute = true;
29
109
  quality = value;
110
+ console.log(quality);
30
111
  }
31
112
 
113
+ if(absolute && quality===0) return pts;
114
+
32
115
  // nothing to do - exit
33
116
  if (pts.length < 4 || (!absolute && quality) >= 1) return pts;
34
117
 
@@ -1273,6 +1273,7 @@ export function intersectLines(p1, p2, p3, p4) {
1273
1273
  */
1274
1274
  export function getDistance(p1, p2, isArray = false) {
1275
1275
  //if(Array.isArray(p1)) isArray = true;
1276
+
1276
1277
  //console.log(p1, p2);
1277
1278
  let dx = isArray ? p2[0] - p1[0] : (p2.x - p1.x);
1278
1279
  let dy = isArray ? p2[1] - p1[1] : (p2.y - p1.y);
@@ -1,12 +1,27 @@
1
- export function pathDataFromPoly(pts, closed=true){
1
+ export function pathDataFromPoly(pts, closed = true) {
2
2
 
3
- let pathData = [
4
- { type: 'M', values: [pts[0].x, pts[0].y] },
5
- ...pts.slice(1).map(pt => { return { type: 'L', values: [pt.x, pt.y] } })
6
- ];
3
+ let pathData = []
4
+ let subPath = []
7
5
 
8
- if(closed) pathData.push({type:'Z', values:[]})
9
6
 
7
+ // complex polygon
8
+ if (Array.isArray(pts[0])) {
9
+ pts.forEach(sub => {
10
+ subPath = [
11
+ { type: 'M', values: [sub[0].x, sub[0].y] },
12
+ ...sub.slice(1).map(pt => { return { type: 'L', values: [pt.x, pt.y] } })
13
+ ];
14
+ pathData.push(...subPath)
15
+ })
16
+ }else{
17
+ pathData = [
18
+ { type: 'M', values: [pts[0].x, pts[0].y] },
19
+ ...pts.slice(1).map(pt => { return { type: 'L', values: [pt.x, pt.y] } })
20
+ ];
21
+ }
22
+
23
+ if (closed) pathData.push({ type: 'Z', values: [] })
10
24
  return pathData
11
25
 
12
- }
26
+ }
27
+