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

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 (79) hide show
  1. package/dist/cut-by-grid.d.ts +21 -0
  2. package/dist/cut-by-grid.d.ts.map +1 -0
  3. package/dist/cut-by-grid.js +214 -0
  4. package/dist/cut-by-mercator-bounds.d.ts +17 -0
  5. package/dist/cut-by-mercator-bounds.d.ts.map +1 -0
  6. package/dist/cut-by-mercator-bounds.js +144 -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 +29 -25
  11. package/dist/es5/cut-by-grid.js.map +1 -1
  12. package/dist/es5/cut-by-mercator-bounds.js +24 -19
  13. package/dist/es5/cut-by-mercator-bounds.js.map +1 -1
  14. package/dist/es5/earcut.js +11 -10
  15. package/dist/es5/earcut.js.map +1 -1
  16. package/dist/es5/index.js.map +1 -1
  17. package/dist/es5/lineclip.js +20 -16
  18. package/dist/es5/lineclip.js.map +1 -1
  19. package/dist/es5/polygon-utils.js +6 -4
  20. package/dist/es5/polygon-utils.js.map +1 -1
  21. package/dist/es5/polygon.js +5 -0
  22. package/dist/es5/polygon.js.map +1 -1
  23. package/dist/es5/utils.js.map +1 -1
  24. package/dist/esm/cut-by-grid.js +5 -5
  25. package/dist/esm/cut-by-grid.js.map +1 -1
  26. package/dist/esm/cut-by-mercator-bounds.js +5 -5
  27. package/dist/esm/cut-by-mercator-bounds.js.map +1 -1
  28. package/dist/esm/earcut.js +9 -10
  29. package/dist/esm/earcut.js.map +1 -1
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/lineclip.js +5 -5
  32. package/dist/esm/lineclip.js.map +1 -1
  33. package/dist/esm/polygon-utils.js +7 -4
  34. package/dist/esm/polygon-utils.js.map +1 -1
  35. package/dist/esm/polygon.js +7 -0
  36. package/dist/esm/polygon.js.map +1 -1
  37. package/dist/esm/utils.js.map +1 -1
  38. package/dist/index.d.ts +8 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +8 -0
  41. package/dist/lineclip.d.ts +30 -0
  42. package/dist/lineclip.d.ts.map +1 -0
  43. package/dist/lineclip.js +178 -0
  44. package/dist/{es5/polygon-utils.d.ts → polygon-utils.d.ts} +28 -64
  45. package/dist/polygon-utils.d.ts.map +1 -0
  46. package/dist/polygon-utils.js +140 -0
  47. package/dist/polygon.d.ts +41 -0
  48. package/dist/polygon.d.ts.map +1 -0
  49. package/dist/polygon.js +67 -0
  50. package/dist/utils.d.ts +5 -0
  51. package/dist/utils.d.ts.map +1 -0
  52. package/dist/utils.js +34 -0
  53. package/package.json +4 -3
  54. package/src/{cut-by-grid.js → cut-by-grid.ts} +79 -33
  55. package/src/{cut-by-mercator-bounds.js → cut-by-mercator-bounds.ts} +51 -22
  56. package/src/{earcut.js → earcut.ts} +26 -14
  57. package/src/{index.js → index.ts} +0 -0
  58. package/src/{lineclip.js → lineclip.ts} +61 -33
  59. package/src/polygon-utils.ts +228 -0
  60. package/src/polygon.ts +98 -0
  61. package/src/{utils.js → utils.ts} +11 -3
  62. package/dist/es5/cut-by-grid.d.ts +0 -24
  63. package/dist/es5/cut-by-mercator-bounds.d.ts +0 -23
  64. package/dist/es5/earcut.d.ts +0 -9
  65. package/dist/es5/lineclip.d.ts +0 -25
  66. package/dist/es5/polygon.d.ts +0 -36
  67. package/dist/esm/cut-by-grid.d.ts +0 -24
  68. package/dist/esm/cut-by-mercator-bounds.d.ts +0 -23
  69. package/dist/esm/lineclip.d.ts +0 -25
  70. package/dist/esm/polygon-utils.d.ts +0 -117
  71. package/dist/esm/polygon.d.ts +0 -36
  72. package/src/cut-by-grid.d.ts +0 -24
  73. package/src/cut-by-mercator-bounds.d.ts +0 -23
  74. package/src/earcut.d.ts +0 -9
  75. package/src/lineclip.d.ts +0 -25
  76. package/src/polygon-utils.d.ts +0 -117
  77. package/src/polygon-utils.js +0 -127
  78. package/src/polygon.d.ts +0 -36
  79. package/src/polygon.js +0 -66
@@ -1,8 +1,26 @@
1
1
  /* eslint-disable max-statements, max-depth, complexity, no-unused-expressions */
2
- import {bitCode, intersect} from './lineclip';
2
+ import {bitCode, intersect, BoundingBox} from './lineclip';
3
3
  import {getPointAtIndex, copy, push} from './utils';
4
4
 
5
- export function cutPolylineByGrid(positions, options = {}) {
5
+ import type {NumericArray} from '@math.gl/core';
6
+
7
+ export type Polygon = {
8
+ positions: number[];
9
+ holeIndices?: number[];
10
+ edgeTypes?: number[];
11
+ };
12
+
13
+ export function cutPolylineByGrid(
14
+ positions: NumericArray,
15
+ options?: {
16
+ size?: number;
17
+ broken?: boolean;
18
+ gridResolution?: number;
19
+ gridOffset?: [number, number];
20
+ startIndex?: number;
21
+ endIndex?: number;
22
+ }
23
+ ): number[] | number[][] {
6
24
  const {
7
25
  size = 2,
8
26
  broken = false,
@@ -10,15 +28,15 @@ export function cutPolylineByGrid(positions, options = {}) {
10
28
  gridOffset = [0, 0],
11
29
  startIndex = 0,
12
30
  endIndex = positions.length
13
- } = options;
31
+ } = options || {};
14
32
  const numPoints = (endIndex - startIndex) / size;
15
- let part = [];
16
- const result = [part];
17
- const a = getPointAtIndex(positions, 0, size, startIndex);
18
- let b;
19
- let codeB;
20
- const cell = getGridCell(a, gridResolution, gridOffset, []);
21
- const scratchPoint = [];
33
+ let part: number[] = [];
34
+ const result: number[][] = [part];
35
+ const a: number[] = getPointAtIndex(positions, 0, size, startIndex);
36
+ let b: number[];
37
+ let codeB: number;
38
+ const cell: BoundingBox = getGridCell(a, gridResolution, gridOffset, []);
39
+ const scratchPoint: number[] = [];
22
40
  push(part, a);
23
41
 
24
42
  for (let i = 1; i < numPoints; i++) {
@@ -57,29 +75,39 @@ export function cutPolylineByGrid(positions, options = {}) {
57
75
  const TYPE_INSIDE = 0;
58
76
  const TYPE_BORDER = 1;
59
77
 
60
- function concatInPlace(arr1, arr2) {
78
+ function concatInPlace(arr1: number[], arr2: number[]): number[] {
61
79
  for (let i = 0; i < arr2.length; i++) {
62
80
  arr1.push(arr2[i]);
63
81
  }
64
82
  return arr1;
65
83
  }
66
84
 
67
- export function cutPolygonByGrid(positions, holeIndices, options = {}) {
85
+ export function cutPolygonByGrid(
86
+ positions: number[],
87
+ holeIndices: number[] | null = null,
88
+ options?: {
89
+ size?: number;
90
+ gridResolution?: number;
91
+ gridOffset?: [number, number];
92
+ edgeTypes?: boolean;
93
+ }
94
+ ): Polygon[] {
68
95
  if (!positions.length) {
69
96
  // input is empty
70
97
  return [];
71
98
  }
72
- const {size = 2, gridResolution = 10, gridOffset = [0, 0], edgeTypes = false} = options;
73
- const result = [];
74
- const queue = [
99
+ const {size = 2, gridResolution = 10, gridOffset = [0, 0], edgeTypes = false} = options || {};
100
+ const result: Polygon[] = [];
101
+ const queue: {pos: number[]; types: number[]; holes: number[]}[] = [
75
102
  {
76
103
  pos: positions,
77
- types: edgeTypes && new Array(positions.length / size).fill(TYPE_BORDER),
104
+ types: edgeTypes ? (new Array(positions.length / size).fill(TYPE_BORDER) as number[]) : null,
78
105
  holes: holeIndices || []
79
106
  }
80
107
  ];
81
- const bbox = [[], []];
82
- let cell = [];
108
+ const bbox: number[][] = [[], []];
109
+ // @ts-ignore
110
+ let cell: BoundingBox = [];
83
111
 
84
112
  // Recursively bisect polygon until every part fit in a single grid cell
85
113
  while (queue.length) {
@@ -118,7 +146,7 @@ export function cutPolygonByGrid(positions, holeIndices, options = {}) {
118
146
  }
119
147
  } else {
120
148
  // Polygon fits in a single cell, no more processing required
121
- const polygon = {positions: pos};
149
+ const polygon: Polygon = {positions: pos};
122
150
  if (edgeTypes) {
123
151
  polygon.edgeTypes = types;
124
152
  }
@@ -136,17 +164,25 @@ export function cutPolygonByGrid(positions, holeIndices, options = {}) {
136
164
  // TYPE_BORDER - edge from the original polygon
137
165
  // TYPE_INSIDE - inside the original polygon
138
166
  // eslint-disable-next-line max-params
139
- function bisectPolygon(positions, edgeTypes, size, startIndex, endIndex, bbox, edge) {
167
+ function bisectPolygon(
168
+ positions: NumericArray,
169
+ edgeTypes: number[] | undefined,
170
+ size: number,
171
+ startIndex: number,
172
+ endIndex: number,
173
+ bbox: BoundingBox,
174
+ edge: number
175
+ ) {
140
176
  const numPoints = (endIndex - startIndex) / size;
141
- const resultLow = [];
142
- const resultHigh = [];
143
- const typesLow = [];
144
- const typesHigh = [];
145
- const scratchPoint = [];
146
-
147
- let p;
148
- let side;
149
- let type;
177
+ const resultLow: number[] = [];
178
+ const resultHigh: number[] = [];
179
+ const typesLow: number[] = [];
180
+ const typesHigh: number[] = [];
181
+ const scratchPoint: number[] = [];
182
+
183
+ let p: number[];
184
+ let side: number;
185
+ let type: number;
150
186
  const prev = getPointAtIndex(positions, numPoints - 1, size, startIndex);
151
187
  let prevSide = Math.sign(edge & 8 ? prev[1] - bbox[3] : prev[0] - bbox[2]);
152
188
  let prevType = edgeTypes && edgeTypes[numPoints - 1];
@@ -189,7 +225,12 @@ function bisectPolygon(positions, edgeTypes, size, startIndex, endIndex, bbox, e
189
225
  ];
190
226
  }
191
227
 
192
- function getGridCell(p, gridResolution, gridOffset, out) {
228
+ function getGridCell(
229
+ p: number[],
230
+ gridResolution: number,
231
+ gridOffset: [number, number],
232
+ out: number[]
233
+ ): BoundingBox {
193
234
  const left = Math.floor((p[0] - gridOffset[0]) / gridResolution) * gridResolution + gridOffset[0];
194
235
  const bottom =
195
236
  Math.floor((p[1] - gridOffset[1]) / gridResolution) * gridResolution + gridOffset[1];
@@ -197,10 +238,10 @@ function getGridCell(p, gridResolution, gridOffset, out) {
197
238
  out[1] = bottom;
198
239
  out[2] = left + gridResolution;
199
240
  out[3] = bottom + gridResolution;
200
- return out;
241
+ return out as BoundingBox;
201
242
  }
202
243
 
203
- function moveToNeighborCell(cell, gridResolution, edge) {
244
+ function moveToNeighborCell(cell: number[], gridResolution: number, edge: number): void {
204
245
  if (edge & 8) {
205
246
  // top
206
247
  cell[1] += gridResolution;
@@ -220,7 +261,12 @@ function moveToNeighborCell(cell, gridResolution, edge) {
220
261
  }
221
262
  }
222
263
 
223
- function getBoundingBox(positions, size, endIndex, out) {
264
+ function getBoundingBox(
265
+ positions: NumericArray,
266
+ size: number,
267
+ endIndex: number,
268
+ out: number[][]
269
+ ): number[][] {
224
270
  let minX = Infinity;
225
271
  let maxX = -Infinity;
226
272
  let minY = Infinity;
@@ -1,12 +1,22 @@
1
1
  import {cutPolylineByGrid, cutPolygonByGrid} from './cut-by-grid';
2
2
  import {getPointAtIndex, push} from './utils';
3
+ import type {Polygon} from './cut-by-grid';
4
+ import type {NumericArray} from '@math.gl/core';
3
5
 
4
6
  // https://en.wikipedia.org/wiki/Web_Mercator_projection
5
7
  const DEFAULT_MAX_LATITUDE = 85.051129;
6
8
 
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;
9
+ /** https://user-images.githubusercontent.com/2059298/78465769-938b7a00-76ae-11ea-9b95-1f4c26425ab9.png */
10
+ export function cutPolylineByMercatorBounds(
11
+ positions: NumericArray,
12
+ options?: {
13
+ size?: number;
14
+ startIndex?: number;
15
+ endIndex?: number;
16
+ normalize?: boolean;
17
+ }
18
+ ): number[][] {
19
+ const {size = 2, startIndex = 0, endIndex = positions.length, normalize = true} = options || {};
10
20
 
11
21
  // Remap longitudes so that each segment takes the shorter path
12
22
  const newPositions = positions.slice(startIndex, endIndex);
@@ -17,7 +27,7 @@ export function cutPolylineByMercatorBounds(positions, options = {}) {
17
27
  broken: true,
18
28
  gridResolution: 360,
19
29
  gridOffset: [-180, -180]
20
- });
30
+ }) as number[][];
21
31
 
22
32
  if (normalize) {
23
33
  // Each part is guaranteed to be in a single copy of the world
@@ -29,12 +39,21 @@ export function cutPolylineByMercatorBounds(positions, options = {}) {
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: number[],
45
+ holeIndices: number[] | null = null,
46
+ options?: {
47
+ size?: number;
48
+ normalize?: boolean;
49
+ maxLatitude?: number;
50
+ edgeTypes?: boolean;
51
+ }
52
+ ): Polygon[] {
53
+ const {size = 2, normalize = true, edgeTypes = false} = options || {};
35
54
  holeIndices = holeIndices || [];
36
- const newPositions = [];
37
- const newHoleIndices = [];
55
+ const newPositions: number[] = [];
56
+ const newHoleIndices: number[] = [];
38
57
  let srcStartIndex = 0;
39
58
  let targetIndex = 0;
40
59
 
@@ -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;
@@ -86,7 +105,12 @@ export function cutPolygonByMercatorBounds(positions, holeIndices, options = {})
86
105
  /* Helpers */
87
106
 
88
107
  // See comments for insertPoleVertices
89
- function findSplitIndex(positions, size, startIndex, endIndex) {
108
+ function findSplitIndex(
109
+ positions: number[],
110
+ size: number,
111
+ startIndex: number,
112
+ endIndex: number
113
+ ): number {
90
114
  let maxLat = -1;
91
115
  let pointIndex = -1;
92
116
  for (let i = startIndex + 1; i < endIndex; i += size) {
@@ -109,12 +133,12 @@ function findSplitIndex(positions, size, startIndex, endIndex) {
109
133
  // intersect with the ring itself. This is ensured by findSplitIndex, which returns the
110
134
  // vertex closest to the pole.
111
135
  function insertPoleVertices(
112
- positions,
113
- size,
114
- startIndex,
115
- endIndex,
116
- maxLatitude = DEFAULT_MAX_LATITUDE
117
- ) {
136
+ positions: number[],
137
+ size: number,
138
+ startIndex: number,
139
+ endIndex: number,
140
+ maxLatitude: number = DEFAULT_MAX_LATITUDE
141
+ ): void {
118
142
  // Check if the ring contains a pole
119
143
  const firstLng = positions[startIndex];
120
144
  const lastLng = positions[endIndex - size];
@@ -134,9 +158,14 @@ function insertPoleVertices(
134
158
  }
135
159
  }
136
160
 
137
- function wrapLongitudesForShortestPath(positions, size, startIndex, endIndex) {
138
- let prevLng = positions[0];
139
- let lng;
161
+ function wrapLongitudesForShortestPath(
162
+ positions: NumericArray,
163
+ size: number,
164
+ startIndex: number,
165
+ endIndex: number
166
+ ): void {
167
+ let prevLng: number = positions[0];
168
+ let lng: number;
140
169
  for (let i = startIndex; i < endIndex; i += size) {
141
170
  lng = positions[i];
142
171
  const delta = lng - prevLng;
@@ -147,8 +176,8 @@ function wrapLongitudesForShortestPath(positions, size, startIndex, endIndex) {
147
176
  }
148
177
  }
149
178
 
150
- function shiftLongitudesIntoRange(positions, size) {
151
- let refLng;
179
+ function shiftLongitudesIntoRange(positions: NumericArray, size: number): void {
180
+ let refLng: number;
152
181
  const pointCount = positions.length / size;
153
182
 
154
183
  // Find a longitude that is not on the edge of a world
@@ -22,16 +22,28 @@
22
22
 
23
23
  */
24
24
 
25
- /* eslint-disable complexity, max-params, max-statements, max-depth, no-continue, no-shadow */
25
+ /* eslint-disable */
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,22 +20,34 @@
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
+ export 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
- const result = [];
33
- let part = [];
34
- let a;
35
- let b;
36
- let codeA = -1;
37
- let codeB;
38
- let lastCode;
44
+ const result: number[][] = [];
45
+ let part: number[] = [];
46
+ let a: number[];
47
+ let b: number[];
48
+ let codeA: number = -1;
49
+ let codeB: number;
50
+ let lastCode: number;
39
51
 
40
52
  for (let i = 1; i < numPoints; i++) {
41
53
  a = getPointAtIndex(positions, i - 1, size, startIndex, a);
@@ -86,17 +98,27 @@ 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
- let result;
96
- let p;
97
- let prev;
98
- let inside;
99
- let prevInside;
117
+ let result: number[];
118
+ let p: number[];
119
+ let prev: number[];
120
+ let inside: boolean;
121
+ let prevInside: boolean;
100
122
 
101
123
  // clip against each side of the clip rectangle
102
124
  for (let edge = 1; edge <= 8; edge *= 2) {
@@ -128,14 +150,20 @@ 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
137
165
  // stuck in an infinite loop
138
- let snap;
166
+ let snap: number;
139
167
  if (edge & 8) {
140
168
  // top
141
169
  t = (bbox[3] - a[1]) / (b[1] - a[1]);
@@ -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;