@math.gl/polygon 3.5.6 → 3.6.0-alpha.1

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.
Files changed (80) hide show
  1. package/dist/cut-by-grid.d.ts +20 -0
  2. package/dist/cut-by-grid.d.ts.map +1 -0
  3. package/dist/cut-by-grid.js +216 -0
  4. package/dist/cut-by-mercator-bounds.d.ts +16 -0
  5. package/dist/cut-by-mercator-bounds.d.ts.map +1 -0
  6. package/dist/cut-by-mercator-bounds.js +145 -0
  7. package/dist/{esm/earcut.d.ts → earcut.d.ts} +4 -2
  8. package/dist/earcut.d.ts.map +1 -0
  9. package/dist/earcut.js +611 -0
  10. package/dist/es5/cut-by-grid.js +70 -79
  11. package/dist/es5/cut-by-grid.js.map +1 -1
  12. package/dist/es5/cut-by-mercator-bounds.js +55 -87
  13. package/dist/es5/cut-by-mercator-bounds.js.map +1 -1
  14. package/dist/es5/earcut.js +97 -102
  15. package/dist/es5/earcut.js.map +1 -1
  16. package/dist/es5/index.js +14 -14
  17. package/dist/es5/index.js.map +1 -1
  18. package/dist/es5/lineclip.js +38 -41
  19. package/dist/es5/lineclip.js.map +1 -1
  20. package/dist/es5/polygon-utils.js +61 -69
  21. package/dist/es5/polygon-utils.js.map +1 -1
  22. package/dist/es5/polygon.js +35 -43
  23. package/dist/es5/polygon.js.map +1 -1
  24. package/dist/es5/utils.js +11 -12
  25. package/dist/es5/utils.js.map +1 -1
  26. package/dist/esm/cut-by-grid.js +4 -4
  27. package/dist/esm/cut-by-grid.js.map +1 -1
  28. package/dist/esm/cut-by-mercator-bounds.js +5 -5
  29. package/dist/esm/cut-by-mercator-bounds.js.map +1 -1
  30. package/dist/esm/earcut.js +9 -10
  31. package/dist/esm/earcut.js.map +1 -1
  32. package/dist/esm/index.js.map +1 -1
  33. package/dist/esm/lineclip.js +5 -5
  34. package/dist/esm/lineclip.js.map +1 -1
  35. package/dist/esm/polygon-utils.js +7 -4
  36. package/dist/esm/polygon-utils.js.map +1 -1
  37. package/dist/esm/polygon.js +7 -0
  38. package/dist/esm/polygon.js.map +1 -1
  39. package/dist/esm/utils.js.map +1 -1
  40. package/dist/index.d.ts +8 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +8 -0
  43. package/dist/lineclip.d.ts +31 -0
  44. package/dist/lineclip.d.ts.map +1 -0
  45. package/dist/lineclip.js +178 -0
  46. package/dist/{es5/polygon-utils.d.ts → polygon-utils.d.ts} +28 -64
  47. package/dist/polygon-utils.d.ts.map +1 -0
  48. package/dist/polygon-utils.js +140 -0
  49. package/dist/polygon.d.ts +40 -0
  50. package/dist/polygon.d.ts.map +1 -0
  51. package/dist/polygon.js +67 -0
  52. package/dist/utils.d.ts +4 -0
  53. package/dist/utils.d.ts.map +1 -0
  54. package/dist/utils.js +34 -0
  55. package/package.json +4 -3
  56. package/src/{cut-by-grid.js → cut-by-grid.ts} +32 -4
  57. package/src/{cut-by-mercator-bounds.js → cut-by-mercator-bounds.ts} +26 -7
  58. package/src/{earcut.js → earcut.ts} +25 -13
  59. package/src/{index.js → index.ts} +0 -0
  60. package/src/{lineclip.js → lineclip.ts} +48 -20
  61. package/src/polygon-utils.ts +225 -0
  62. package/src/{polygon.js → polygon.ts} +40 -9
  63. package/src/{utils.js → utils.ts} +0 -0
  64. package/dist/es5/cut-by-grid.d.ts +0 -24
  65. package/dist/es5/cut-by-mercator-bounds.d.ts +0 -23
  66. package/dist/es5/earcut.d.ts +0 -9
  67. package/dist/es5/lineclip.d.ts +0 -25
  68. package/dist/es5/polygon.d.ts +0 -36
  69. package/dist/esm/cut-by-grid.d.ts +0 -24
  70. package/dist/esm/cut-by-mercator-bounds.d.ts +0 -23
  71. package/dist/esm/lineclip.d.ts +0 -25
  72. package/dist/esm/polygon-utils.d.ts +0 -117
  73. package/dist/esm/polygon.d.ts +0 -36
  74. package/src/cut-by-grid.d.ts +0 -24
  75. package/src/cut-by-mercator-bounds.d.ts +0 -23
  76. package/src/earcut.d.ts +0 -9
  77. package/src/lineclip.d.ts +0 -25
  78. package/src/polygon-utils.d.ts +0 -117
  79. package/src/polygon-utils.js +0 -127
  80. package/src/polygon.d.ts +0 -36
@@ -0,0 +1,140 @@
1
+ /* eslint-disable max-statements, max-depth, complexity, no-unused-expressions */
2
+ import { equals } from '@math.gl/core';
3
+ export var WINDING;
4
+ (function (WINDING) {
5
+ WINDING[WINDING["CLOCKWISE"] = 1] = "CLOCKWISE";
6
+ WINDING[WINDING["COUNTER_CLOCKWISE"] = -1] = "COUNTER_CLOCKWISE";
7
+ })(WINDING || (WINDING = {}));
8
+ /**
9
+ * Checks winding direction of the polygon and reverses the polygon in case of opposite winding direction.
10
+ * Note: points are modified in-place.
11
+ * @param points An array that represents points of the polygon.
12
+ * @param direction Requested winding direction. 1 is for clockwise, -1 for counterclockwise winding direction.
13
+ * @param options Parameters of the polygon.
14
+ * @return Returns true if the winding direction was changed.
15
+ */
16
+ export function modifyPolygonWindingDirection(points, direction, options = {}) {
17
+ const windingDirection = getPolygonWindingDirection(points, options);
18
+ if (windingDirection !== direction) {
19
+ reversePolygon(points, options);
20
+ return true;
21
+ }
22
+ return false;
23
+ }
24
+ /**
25
+ * Returns winding direction of the polygon.
26
+ * @param points An array that represents points of the polygon.
27
+ * @param options Parameters of the polygon.
28
+ * @returns Winding direction of the polygon.
29
+ */
30
+ export function getPolygonWindingDirection(points, options = {}) {
31
+ return Math.sign(getPolygonSignedArea(points, options));
32
+ }
33
+ /**
34
+ * Returns signed area of the polygon.
35
+ * @param points An array that represents points of the polygon.
36
+ * @param options Parameters of the polygon.
37
+ * @returns Signed area of the polygon.
38
+ * https://en.wikipedia.org/wiki/Shoelace_formula
39
+ */
40
+ export function getPolygonSignedArea(points, options = {}) {
41
+ const { start = 0, end = points.length } = options;
42
+ const dim = options.size || 2;
43
+ let area = 0;
44
+ for (let i = start, j = end - dim; i < end; i += dim) {
45
+ area += (points[i] - points[j]) * (points[i + 1] + points[j + 1]);
46
+ j = i;
47
+ }
48
+ return area / 2;
49
+ }
50
+ /**
51
+ * Calls the visitor callback for each segment in the polygon.
52
+ * @param points An array that represents points of the polygon
53
+ * @param visitor A callback to call for each segment.
54
+ * @param options Parameters of the polygon.
55
+ */
56
+ export function forEachSegmentInPolygon(points, visitor, options = {}) {
57
+ const { start = 0, end = points.length, size = 2, isClosed } = options;
58
+ const numPoints = (end - start) / size;
59
+ for (let i = 0; i < numPoints - 1; ++i) {
60
+ visitor(points[start + i * size], points[start + i * size + 1], points[start + (i + 1) * size], points[start + (i + 1) * size + 1], i, i + 1);
61
+ }
62
+ const endPointIndex = start + (numPoints - 1) * size;
63
+ const isClosedEx = isClosed ||
64
+ (equals(points[start], points[endPointIndex]) &&
65
+ equals(points[start + 1], points[endPointIndex + 1]));
66
+ if (!isClosedEx) {
67
+ visitor(points[endPointIndex], points[endPointIndex + 1], points[start], points[start + 1], numPoints - 1, 0);
68
+ }
69
+ }
70
+ function reversePolygon(points, options) {
71
+ const { start = 0, end = points.length, size = 2 } = options;
72
+ const numPoints = (end - start) / size;
73
+ const numSwaps = Math.floor(numPoints / 2);
74
+ for (let i = 0; i < numSwaps; ++i) {
75
+ const b1 = start + i * size;
76
+ const b2 = start + (numPoints - 1 - i) * size;
77
+ for (let j = 0; j < size; ++j) {
78
+ const tmp = points[b1 + j];
79
+ points[b1 + j] = points[b2 + j];
80
+ points[b2 + j] = tmp;
81
+ }
82
+ }
83
+ }
84
+ /**
85
+ * Checks winding direction of the polygon and reverses the polygon in case of opposite winding direction.
86
+ * Note: points are modified in-place.
87
+ * @param points Array of points that represent the polygon.
88
+ * @param direction Requested winding direction. 1 is for clockwise, -1 for counterclockwise winding direction.
89
+ * @param options Parameters of the polygon.
90
+ * @return Returns true if the winding direction was changed.
91
+ */
92
+ export function modifyPolygonWindingDirectionPoints(points, direction, options = {}) {
93
+ const currentDirection = getPolygonWindingDirectionPoints(points, options);
94
+ if (currentDirection !== direction) {
95
+ points.reverse();
96
+ return true;
97
+ }
98
+ return false;
99
+ }
100
+ /**
101
+ * Returns winding direction of the polygon.
102
+ * @param points Array of points that represent the polygon.
103
+ * @param options Parameters of the polygon.
104
+ * @returns Winding direction of the polygon.
105
+ */
106
+ export function getPolygonWindingDirectionPoints(points, options = {}) {
107
+ return Math.sign(getPolygonSignedAreaPoints(points, options));
108
+ }
109
+ /**
110
+ * Returns signed area of the polygon.
111
+ * @param points Array of points that represent the polygon.
112
+ * @param options Parameters of the polygon.
113
+ * @returns Signed area of the polygon.
114
+ */
115
+ export function getPolygonSignedAreaPoints(points, options = {}) {
116
+ // https://en.wikipedia.org/wiki/Shoelace_formula
117
+ const { start = 0, end = points.length } = options;
118
+ let area = 0;
119
+ for (let i = start, j = end - 1; i < end; ++i) {
120
+ area += (points[i][0] - points[j][0]) * (points[i][1] + points[j][1]);
121
+ j = i;
122
+ }
123
+ return area / 2;
124
+ }
125
+ /**
126
+ * Calls visitor callback for each segment in the polygon.
127
+ * @param points Array of points that represent the polygon.
128
+ * @param visitor A callback to call for each segment.
129
+ * @param options Parameters of the polygon.
130
+ */
131
+ export function forEachSegmentInPolygonPoints(points, visitor, options = {}) {
132
+ const { start = 0, end = points.length, isClosed } = options;
133
+ for (let i = start; i < end - 1; ++i) {
134
+ visitor(points[i], points[i + 1], i, i + 1);
135
+ }
136
+ const isClosedEx = isClosed || equals(points[end - 1], points[0]);
137
+ if (!isClosedEx) {
138
+ visitor(points[end - 1], points[0], end - 1, 0);
139
+ }
140
+ }
@@ -0,0 +1,40 @@
1
+ import type { SegmentVisitorPoints } from './polygon-utils';
2
+ export declare type PolygonOptions = {
3
+ start?: number;
4
+ end?: number;
5
+ size?: number;
6
+ isClosed?: boolean;
7
+ };
8
+ export default class Polygon {
9
+ points: any;
10
+ isFlatArray: boolean;
11
+ options: PolygonOptions;
12
+ constructor(points: any, options?: PolygonOptions);
13
+ /**
14
+ * Returns signed area of the polygon.
15
+ * @returns Signed area of the polygon.
16
+ */
17
+ getSignedArea(): number;
18
+ /**
19
+ * Returns absolute area of the polygon.
20
+ * @returns Absolute area of the polygon.
21
+ */
22
+ getArea(): number;
23
+ /**
24
+ * Returns winding direction of the polygon.
25
+ * @returns Winding direction of the polygon. 1 is for clockwise, -1 for counterclockwise winding direction.
26
+ */
27
+ getWindingDirection(): number;
28
+ /**
29
+ * Calls the visitor callback for each segment in the polygon.
30
+ * @param visitor A callback to call for each segment.
31
+ */
32
+ forEachSegment(visitor: SegmentVisitorPoints): void;
33
+ /**
34
+ * Checks winding direction of the polygon and reverses the polygon in case of opposite winding direction.
35
+ * @param direction Requested winding direction. 1 is for clockwise, -1 for counterclockwise winding direction.
36
+ * @return Returns true if the winding direction was changed.
37
+ */
38
+ modifyWindingDirection(direction: number): boolean;
39
+ }
40
+ //# sourceMappingURL=polygon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polygon.d.ts","sourceRoot":"","sources":["../src/polygon.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,iBAAiB,CAAC;AAW1D,oBAAY,cAAc,GAAG;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,OAAO;IAC1B,MAAM,MAAC;IACP,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,cAAc,CAAC;gBAEZ,MAAM,KAAA,EAAmB,OAAO,GAAE,cAAmB;IAcjE;;;OAGG;IACH,aAAa,IAAI,MAAM;IAMvB;;;OAGG;IACH,OAAO,IAAI,MAAM;IAIjB;;;OAGG;IACH,mBAAmB,IAAI,MAAM;IAI7B;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAgBnD;;;;OAIG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;CAMnD"}
@@ -0,0 +1,67 @@
1
+ /* eslint-disable no-undef, no-console */
2
+ import { isArray } from '@math.gl/core';
3
+ import { getPolygonSignedArea, forEachSegmentInPolygon, modifyPolygonWindingDirection, getPolygonSignedAreaPoints, forEachSegmentInPolygonPoints, modifyPolygonWindingDirectionPoints } from './polygon-utils';
4
+ export default class Polygon {
5
+ constructor(points /* : number[] */, options = {}) {
6
+ this.points = points;
7
+ this.isFlatArray = !isArray(points[0]);
8
+ this.options = {
9
+ start: options.start || 0,
10
+ end: options.end || points.length,
11
+ size: options.size || 2,
12
+ isClosed: options.isClosed
13
+ };
14
+ Object.freeze(this);
15
+ }
16
+ /**
17
+ * Returns signed area of the polygon.
18
+ * @returns Signed area of the polygon.
19
+ */
20
+ getSignedArea() {
21
+ if (this.isFlatArray)
22
+ return getPolygonSignedArea(this.points, this.options);
23
+ return getPolygonSignedAreaPoints(this.points, this.options);
24
+ }
25
+ /**
26
+ * Returns absolute area of the polygon.
27
+ * @returns Absolute area of the polygon.
28
+ */
29
+ getArea() {
30
+ return Math.abs(this.getSignedArea());
31
+ }
32
+ /**
33
+ * Returns winding direction of the polygon.
34
+ * @returns Winding direction of the polygon. 1 is for clockwise, -1 for counterclockwise winding direction.
35
+ */
36
+ getWindingDirection() {
37
+ return Math.sign(this.getSignedArea());
38
+ }
39
+ /**
40
+ * Calls the visitor callback for each segment in the polygon.
41
+ * @param visitor A callback to call for each segment.
42
+ */
43
+ forEachSegment(visitor) {
44
+ if (this.isFlatArray) {
45
+ forEachSegmentInPolygon(this.points,
46
+ // eslint-disable-next-line max-params
47
+ (x1, y1, x2, y2, i1, i2) => {
48
+ // TODO @igorDykhta original visitor uses arrays for each point, but with flat arrays performance degrades if we allocate points for each segment
49
+ visitor([x1, y1], [x2, y2], i1, i2);
50
+ }, this.options);
51
+ }
52
+ else {
53
+ forEachSegmentInPolygonPoints(this.points, visitor, this.options);
54
+ }
55
+ }
56
+ /**
57
+ * Checks winding direction of the polygon and reverses the polygon in case of opposite winding direction.
58
+ * @param direction Requested winding direction. 1 is for clockwise, -1 for counterclockwise winding direction.
59
+ * @return Returns true if the winding direction was changed.
60
+ */
61
+ modifyWindingDirection(direction) {
62
+ if (this.isFlatArray) {
63
+ return modifyPolygonWindingDirection(this.points, direction, this.options);
64
+ }
65
+ return modifyPolygonWindingDirectionPoints(this.points, direction, this.options);
66
+ }
67
+ }
@@ -0,0 +1,4 @@
1
+ export declare function push(target: any, source: any): boolean;
2
+ export declare function copy(target: any, source: any): void;
3
+ export declare function getPointAtIndex(positions: any, index: any, size: any, offset: any, out?: any[]): any[];
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,IAAI,CAAC,MAAM,KAAA,EAAE,MAAM,KAAA,WAsBlC;AAED,wBAAgB,IAAI,CAAC,MAAM,KAAA,EAAE,MAAM,KAAA,QAKlC;AAED,wBAAgB,eAAe,CAAC,SAAS,KAAA,EAAE,KAAK,KAAA,EAAE,IAAI,KAAA,EAAE,MAAM,KAAA,EAAE,GAAG,QAAK,SAMvE"}
package/dist/utils.js ADDED
@@ -0,0 +1,34 @@
1
+ export function push(target, source) {
2
+ const size = source.length;
3
+ const startIndex = target.length;
4
+ // dedupe, if source is the same point as the last vertex
5
+ if (startIndex > 0) {
6
+ let isDuplicate = true;
7
+ for (let i = 0; i < size; i++) {
8
+ if (target[startIndex - size + i] !== source[i]) {
9
+ isDuplicate = false;
10
+ break;
11
+ }
12
+ }
13
+ if (isDuplicate) {
14
+ return false;
15
+ }
16
+ }
17
+ for (let i = 0; i < size; i++) {
18
+ target[startIndex + i] = source[i];
19
+ }
20
+ return true;
21
+ }
22
+ export function copy(target, source) {
23
+ const size = source.length;
24
+ for (let i = 0; i < size; i++) {
25
+ target[i] = source[i];
26
+ }
27
+ }
28
+ export function getPointAtIndex(positions, index, size, offset, out = []) {
29
+ const startI = offset + index * size;
30
+ for (let i = 0; i < size; i++) {
31
+ out[i] = positions[startI + i];
32
+ }
33
+ return out;
34
+ }
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
- "version": "3.5.6",
8
+ "version": "3.6.0-alpha.1",
9
9
  "keywords": [
10
10
  "webgl",
11
11
  "javascript",
@@ -17,6 +17,7 @@
17
17
  "type": "git",
18
18
  "url": "https://github.com/uber-web/math.gl.git"
19
19
  },
20
+ "types": "dist/index.d.ts",
20
21
  "main": "dist/es5/index.js",
21
22
  "module": "dist/esm/index.js",
22
23
  "files": [
@@ -24,7 +25,7 @@
24
25
  "src"
25
26
  ],
26
27
  "dependencies": {
27
- "@math.gl/core": "3.5.6"
28
+ "@math.gl/core": "3.6.0-alpha.1"
28
29
  },
29
- "gitHead": "0e69c70ff2e6373fed84d303cbf8198a6972944f"
30
+ "gitHead": "45386981340895bf201c2ebb76257c9bbffd8ff6"
30
31
  }
@@ -2,7 +2,23 @@
2
2
  import {bitCode, intersect} from './lineclip';
3
3
  import {getPointAtIndex, copy, push} from './utils';
4
4
 
5
- export function cutPolylineByGrid(positions, options = {}) {
5
+ export type Polygon = {
6
+ positions: Array<number>;
7
+ holeIndices?: Array<number>;
8
+ vertexTypes?: Array<number>;
9
+ };
10
+
11
+ export function cutPolylineByGrid(
12
+ positions: Array<number>,
13
+ options?: {
14
+ size?: number;
15
+ broken?: boolean;
16
+ gridResolution?: number;
17
+ gridOffset?: [number, number];
18
+ startIndex?: number;
19
+ endIndex?: number;
20
+ }
21
+ ): Array<number> | Array<Array<number>> {
6
22
  const {
7
23
  size = 2,
8
24
  broken = false,
@@ -10,7 +26,7 @@ export function cutPolylineByGrid(positions, options = {}) {
10
26
  gridOffset = [0, 0],
11
27
  startIndex = 0,
12
28
  endIndex = positions.length
13
- } = options;
29
+ } = options || {};
14
30
  const numPoints = (endIndex - startIndex) / size;
15
31
  let part = [];
16
32
  const result = [part];
@@ -64,12 +80,21 @@ function concatInPlace(arr1, arr2) {
64
80
  return arr1;
65
81
  }
66
82
 
67
- export function cutPolygonByGrid(positions, holeIndices, options = {}) {
83
+ export function cutPolygonByGrid(
84
+ positions: Array<number>,
85
+ holeIndices: Array<number> | null = null,
86
+ options?: {
87
+ size?: number;
88
+ gridResolution?: number;
89
+ gridOffset?: [number, number];
90
+ edgeTypes?: boolean;
91
+ }
92
+ ): Array<Polygon> {
68
93
  if (!positions.length) {
69
94
  // input is empty
70
95
  return [];
71
96
  }
72
- const {size = 2, gridResolution = 10, gridOffset = [0, 0], edgeTypes = false} = options;
97
+ const {size = 2, gridResolution = 10, gridOffset = [0, 0], edgeTypes = false} = options || {};
73
98
  const result = [];
74
99
  const queue = [
75
100
  {
@@ -88,6 +113,7 @@ export function cutPolygonByGrid(positions, holeIndices, options = {}) {
88
113
  // Get the bounding box of the outer polygon
89
114
  getBoundingBox(pos, size, holes[0] || pos.length, bbox);
90
115
  cell = getGridCell(bbox[0], gridResolution, gridOffset, cell);
116
+ // @ts-expect-error
91
117
  const code = bitCode(bbox[1], cell);
92
118
 
93
119
  if (code) {
@@ -120,9 +146,11 @@ export function cutPolygonByGrid(positions, holeIndices, options = {}) {
120
146
  // Polygon fits in a single cell, no more processing required
121
147
  const polygon = {positions: pos};
122
148
  if (edgeTypes) {
149
+ // @ts-expect-error
123
150
  polygon.edgeTypes = types;
124
151
  }
125
152
  if (holes.length) {
153
+ // @ts-expect-error
126
154
  polygon.holeIndices = holes;
127
155
  }
128
156
 
@@ -1,12 +1,21 @@
1
1
  import {cutPolylineByGrid, cutPolygonByGrid} from './cut-by-grid';
2
2
  import {getPointAtIndex, push} from './utils';
3
+ import type {Polygon} from './cut-by-grid';
3
4
 
4
5
  // https://en.wikipedia.org/wiki/Web_Mercator_projection
5
6
  const DEFAULT_MAX_LATITUDE = 85.051129;
6
7
 
7
- // https://user-images.githubusercontent.com/2059298/78465769-938b7a00-76ae-11ea-9b95-1f4c26425ab9.png
8
- export function cutPolylineByMercatorBounds(positions, options = {}) {
9
- const {size = 2, startIndex = 0, endIndex = positions.length, normalize = true} = options;
8
+ /** https://user-images.githubusercontent.com/2059298/78465769-938b7a00-76ae-11ea-9b95-1f4c26425ab9.png */
9
+ export function cutPolylineByMercatorBounds(
10
+ positions: Array<number>,
11
+ options?: {
12
+ size?: number;
13
+ startIndex?: number;
14
+ endIndex?: number;
15
+ normalize?: boolean;
16
+ }
17
+ ): Array<number> {
18
+ const {size = 2, startIndex = 0, endIndex = positions.length, normalize = true} = options || {};
10
19
 
11
20
  // Remap longitudes so that each segment takes the shorter path
12
21
  const newPositions = positions.slice(startIndex, endIndex);
@@ -26,12 +35,22 @@ export function cutPolylineByMercatorBounds(positions, options = {}) {
26
35
  shiftLongitudesIntoRange(part, size);
27
36
  }
28
37
  }
38
+ // @ts-expect-error
29
39
  return parts;
30
40
  }
31
41
 
32
- // https://user-images.githubusercontent.com/2059298/78465770-94241080-76ae-11ea-809a-6a8534dac1d9.png
33
- export function cutPolygonByMercatorBounds(positions, holeIndices, options = {}) {
34
- const {size = 2, normalize = true, edgeTypes = false} = options;
42
+ /** https://user-images.githubusercontent.com/2059298/78465770-94241080-76ae-11ea-809a-6a8534dac1d9.png */
43
+ export function cutPolygonByMercatorBounds(
44
+ positions: Array<number>,
45
+ holeIndices: Array<number> | null = null,
46
+ options?: {
47
+ size?: number;
48
+ normalize?: boolean;
49
+ maxLatitude?: number;
50
+ edgeTypes?: boolean;
51
+ }
52
+ ): Array<Polygon> {
53
+ const {size = 2, normalize = true, edgeTypes = false} = options || {};
35
54
  holeIndices = holeIndices || [];
36
55
  const newPositions = [];
37
56
  const newHoleIndices = [];
@@ -59,7 +78,7 @@ export function cutPolygonByMercatorBounds(positions, holeIndices, options = {})
59
78
  wrapLongitudesForShortestPath(newPositions, size, targetStartIndex, targetIndex);
60
79
 
61
80
  // Handle the case when the ring contains a pole
62
- insertPoleVertices(newPositions, size, targetStartIndex, targetIndex, options.maxLatitude);
81
+ insertPoleVertices(newPositions, size, targetStartIndex, targetIndex, options?.maxLatitude);
63
82
 
64
83
  srcStartIndex = srcEndIndex;
65
84
  newHoleIndices[ringIndex] = targetIndex;
@@ -26,12 +26,24 @@
26
26
 
27
27
  import {getPolygonSignedArea} from './polygon-utils';
28
28
 
29
- export function earcut(data, holeIndices, dim, areas) {
30
- dim = dim || 2;
31
-
29
+ /**
30
+ * Computes a triangulation of a polygon
31
+ * @param positions a flat array of the vertex positions that define the polygon.
32
+ * @param holeIndices an array of hole indices if any (e.g. [5, 8] for a 12-vertex input would mean one hole with vertices 5–7 and another with 8–11).
33
+ * @param dim the number of elements in each vertex. Size `2` will interpret `positions` as `[x0, y0, x1, y1, ...]` and size `3` will interpret `positions` as `[x0, y0, z0, x1, y1, z1, ...]`. Default `2`.
34
+ * @param areas areas of outer polygon and holes as computed by `getPolygonSignedArea()`. Can be optionally supplied to speed up triangulation
35
+ * @returns array of indices into the `positions` array that describes the triangulation of the polygon
36
+ * Adapted from https://github.com/mapbox/earcut
37
+ */
38
+ export function earcut(
39
+ positions: number[],
40
+ holeIndices?: number[],
41
+ dim: number = 2,
42
+ areas?: number[]
43
+ ): number[] {
32
44
  const hasHoles = holeIndices && holeIndices.length;
33
- const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
34
- let outerNode = linkedList(data, 0, outerLen, dim, true, areas && areas[0]);
45
+ const outerLen = hasHoles ? holeIndices[0] * dim : positions.length;
46
+ let outerNode = linkedList(positions, 0, outerLen, dim, true, areas && areas[0]);
35
47
  const triangles = [];
36
48
 
37
49
  if (!outerNode || outerNode.next === outerNode.prev) return triangles;
@@ -44,16 +56,16 @@ export function earcut(data, holeIndices, dim, areas) {
44
56
  let x;
45
57
  let y;
46
58
 
47
- if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim, areas);
59
+ if (hasHoles) outerNode = eliminateHoles(positions, holeIndices, outerNode, dim, areas);
48
60
 
49
61
  // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
50
- if (data.length > 80 * dim) {
51
- minX = maxX = data[0];
52
- minY = maxY = data[1];
62
+ if (positions.length > 80 * dim) {
63
+ minX = maxX = positions[0];
64
+ minY = maxY = positions[1];
53
65
 
54
66
  for (let i = dim; i < outerLen; i += dim) {
55
- x = data[i];
56
- y = data[i + 1];
67
+ x = positions[i];
68
+ y = positions[i + 1];
57
69
  if (x < minX) minX = x;
58
70
  if (y < minY) minY = y;
59
71
  if (x > maxX) maxX = x;
@@ -96,7 +108,7 @@ function linkedList(data, start, end, dim, clockwise, area) {
96
108
  }
97
109
 
98
110
  // eliminate colinear or duplicate points
99
- function filterPoints(start, end) {
111
+ function filterPoints(start, end?) {
100
112
  if (!start) return start;
101
113
  if (!end) end = start;
102
114
 
@@ -119,7 +131,7 @@ function filterPoints(start, end) {
119
131
  }
120
132
 
121
133
  // main ear slicing loop which triangulates a polygon (given as a linked list)
122
- function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
134
+ function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass?) {
123
135
  if (!ear) return;
124
136
 
125
137
  // interlink polygon nodes in z-order
File without changes
@@ -20,14 +20,26 @@
20
20
 
21
21
  */
22
22
 
23
- /* eslint-disable max-statements, max-depth */
23
+ /* eslint-disable max-statements, max-depth, complexity */
24
24
 
25
25
  import {push, copy, getPointAtIndex} from './utils';
26
26
 
27
- // Cohen-Sutherland line clipping algorithm, adapted to efficiently
28
- // handle polylines rather than just segments
29
- export function clipPolyline(positions, bbox, options = {}) {
30
- const {size = 2, startIndex = 0, endIndex = positions.length} = options;
27
+ type BoundingBox = [number, number, number, number];
28
+
29
+ /**
30
+ * Cohen-Sutherland line clipping algorithm, adapted to efficiently
31
+ * handle polylines rather than just segments
32
+ */
33
+ export function clipPolyline(
34
+ positions: number[],
35
+ bbox: BoundingBox,
36
+ options?: {
37
+ size?: number;
38
+ startIndex?: number;
39
+ endIndex?: number;
40
+ }
41
+ ): number[][] {
42
+ const {size = 2, startIndex = 0, endIndex = positions.length} = options || {};
31
43
  const numPoints = (endIndex - startIndex) / size;
32
44
  const result = [];
33
45
  let part = [];
@@ -86,11 +98,21 @@ export function clipPolyline(positions, bbox, options = {}) {
86
98
  return result;
87
99
  }
88
100
 
89
- // Sutherland-Hodgeman polygon clipping algorithm
90
- // polygon must be closed (first vertex == last vertex)
91
- export function clipPolygon(positions, bbox, options = {}) {
92
- const {size = 2, endIndex = positions.length} = options;
93
- let {startIndex = 0} = options;
101
+ /**
102
+ * Sutherland-Hodgeman polygon clipping algorithm
103
+ * polygon must be closed (first vertex == last vertex)
104
+ */
105
+ export function clipPolygon(
106
+ positions: number[],
107
+ bbox: BoundingBox,
108
+ options?: {
109
+ size?: number;
110
+ startIndex?: number;
111
+ endIndex?: number;
112
+ }
113
+ ): number[] {
114
+ const {size = 2, endIndex = positions.length} = options || {};
115
+ let {startIndex = 0} = options || {};
94
116
  let numPoints = (endIndex - startIndex) / size;
95
117
  let result;
96
118
  let p;
@@ -128,9 +150,15 @@ export function clipPolygon(positions, bbox, options = {}) {
128
150
  return result;
129
151
  }
130
152
 
131
- // intersect a segment against one of the 4 lines that make up the bbox
153
+ /** intersect a segment against one of the 4 lines that make up the bbox */
132
154
 
133
- export function intersect(a, b, edge, bbox, out = []) {
155
+ export function intersect(
156
+ a: number[],
157
+ b: number[],
158
+ edge: number,
159
+ bbox: BoundingBox,
160
+ out: number[] = []
161
+ ): number[] {
134
162
  let t;
135
163
  // Forces out[snapI] to be on the bbox edge
136
164
  // Interpolation introduces precision issue which may cause lineclip to be
@@ -161,14 +189,14 @@ export function intersect(a, b, edge, bbox, out = []) {
161
189
  return out;
162
190
  }
163
191
 
164
- // bit code reflects the point position relative to the bbox:
165
-
166
- // left mid right
167
- // top 1001 1000 1010
168
- // mid 0001 0000 0010
169
- // bottom 0101 0100 0110
170
-
171
- export function bitCode(p, bbox) {
192
+ /**
193
+ * bit code reflects the point position relative to the bbox:
194
+ * left mid right
195
+ * top 1001 1000 1010
196
+ * mid 0001 0000 0010
197
+ * bottom 0101 0100 0110
198
+ */
199
+ export function bitCode(p: number[], bbox: BoundingBox): number {
172
200
  let code = 0;
173
201
 
174
202
  if (p[0] < bbox[0]) code |= 1;