@math.gl/polygon 3.6.0-alpha.1 → 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 (46) hide show
  1. package/dist/cut-by-grid.d.ts +8 -7
  2. package/dist/cut-by-grid.d.ts.map +1 -1
  3. package/dist/cut-by-grid.js +2 -4
  4. package/dist/cut-by-mercator-bounds.d.ts +5 -4
  5. package/dist/cut-by-mercator-bounds.d.ts.map +1 -1
  6. package/dist/cut-by-mercator-bounds.js +0 -1
  7. package/dist/earcut.js +1 -1
  8. package/dist/es5/cut-by-grid.js +83 -70
  9. package/dist/es5/cut-by-grid.js.map +1 -1
  10. package/dist/es5/cut-by-mercator-bounds.js +89 -52
  11. package/dist/es5/cut-by-mercator-bounds.js.map +1 -1
  12. package/dist/es5/earcut.js +95 -89
  13. package/dist/es5/earcut.js.map +1 -1
  14. package/dist/es5/index.js +14 -14
  15. package/dist/es5/lineclip.js +43 -36
  16. package/dist/es5/lineclip.js.map +1 -1
  17. package/dist/es5/polygon-utils.js +66 -56
  18. package/dist/es5/polygon-utils.js.map +1 -1
  19. package/dist/es5/polygon.js +44 -31
  20. package/dist/es5/polygon.js.map +1 -1
  21. package/dist/es5/utils.js +12 -11
  22. package/dist/es5/utils.js.map +1 -1
  23. package/dist/esm/cut-by-grid.js +1 -1
  24. package/dist/esm/cut-by-grid.js.map +1 -1
  25. package/dist/esm/cut-by-mercator-bounds.js.map +1 -1
  26. package/dist/esm/earcut.js.map +1 -1
  27. package/dist/esm/lineclip.js.map +1 -1
  28. package/dist/esm/polygon-utils.js.map +1 -1
  29. package/dist/esm/polygon.js.map +1 -1
  30. package/dist/esm/utils.js.map +1 -1
  31. package/dist/lineclip.d.ts +1 -2
  32. package/dist/lineclip.d.ts.map +1 -1
  33. package/dist/polygon-utils.d.ts.map +1 -1
  34. package/dist/polygon.d.ts +3 -2
  35. package/dist/polygon.d.ts.map +1 -1
  36. package/dist/polygon.js +1 -1
  37. package/dist/utils.d.ts +4 -3
  38. package/dist/utils.d.ts.map +1 -1
  39. package/package.json +3 -3
  40. package/src/cut-by-grid.ts +57 -39
  41. package/src/cut-by-mercator-bounds.ts +31 -21
  42. package/src/earcut.ts +1 -1
  43. package/src/lineclip.ts +14 -14
  44. package/src/polygon-utils.ts +4 -1
  45. package/src/polygon.ts +9 -8
  46. package/src/utils.ts +11 -3
@@ -1,15 +1,17 @@
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
+ import type {NumericArray} from '@math.gl/core';
6
+
5
7
  export type Polygon = {
6
- positions: Array<number>;
7
- holeIndices?: Array<number>;
8
- vertexTypes?: Array<number>;
8
+ positions: number[];
9
+ holeIndices?: number[];
10
+ edgeTypes?: number[];
9
11
  };
10
12
 
11
13
  export function cutPolylineByGrid(
12
- positions: Array<number>,
14
+ positions: NumericArray,
13
15
  options?: {
14
16
  size?: number;
15
17
  broken?: boolean;
@@ -18,7 +20,7 @@ export function cutPolylineByGrid(
18
20
  startIndex?: number;
19
21
  endIndex?: number;
20
22
  }
21
- ): Array<number> | Array<Array<number>> {
23
+ ): number[] | number[][] {
22
24
  const {
23
25
  size = 2,
24
26
  broken = false,
@@ -28,13 +30,13 @@ export function cutPolylineByGrid(
28
30
  endIndex = positions.length
29
31
  } = options || {};
30
32
  const numPoints = (endIndex - startIndex) / size;
31
- let part = [];
32
- const result = [part];
33
- const a = getPointAtIndex(positions, 0, size, startIndex);
34
- let b;
35
- let codeB;
36
- const cell = getGridCell(a, gridResolution, gridOffset, []);
37
- 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[] = [];
38
40
  push(part, a);
39
41
 
40
42
  for (let i = 1; i < numPoints; i++) {
@@ -73,7 +75,7 @@ export function cutPolylineByGrid(
73
75
  const TYPE_INSIDE = 0;
74
76
  const TYPE_BORDER = 1;
75
77
 
76
- function concatInPlace(arr1, arr2) {
78
+ function concatInPlace(arr1: number[], arr2: number[]): number[] {
77
79
  for (let i = 0; i < arr2.length; i++) {
78
80
  arr1.push(arr2[i]);
79
81
  }
@@ -81,30 +83,31 @@ function concatInPlace(arr1, arr2) {
81
83
  }
82
84
 
83
85
  export function cutPolygonByGrid(
84
- positions: Array<number>,
85
- holeIndices: Array<number> | null = null,
86
+ positions: number[],
87
+ holeIndices: number[] | null = null,
86
88
  options?: {
87
89
  size?: number;
88
90
  gridResolution?: number;
89
91
  gridOffset?: [number, number];
90
92
  edgeTypes?: boolean;
91
93
  }
92
- ): Array<Polygon> {
94
+ ): Polygon[] {
93
95
  if (!positions.length) {
94
96
  // input is empty
95
97
  return [];
96
98
  }
97
99
  const {size = 2, gridResolution = 10, gridOffset = [0, 0], edgeTypes = false} = options || {};
98
- const result = [];
99
- const queue = [
100
+ const result: Polygon[] = [];
101
+ const queue: {pos: number[]; types: number[]; holes: number[]}[] = [
100
102
  {
101
103
  pos: positions,
102
- types: edgeTypes && new Array(positions.length / size).fill(TYPE_BORDER),
104
+ types: edgeTypes ? (new Array(positions.length / size).fill(TYPE_BORDER) as number[]) : null,
103
105
  holes: holeIndices || []
104
106
  }
105
107
  ];
106
- const bbox = [[], []];
107
- let cell = [];
108
+ const bbox: number[][] = [[], []];
109
+ // @ts-ignore
110
+ let cell: BoundingBox = [];
108
111
 
109
112
  // Recursively bisect polygon until every part fit in a single grid cell
110
113
  while (queue.length) {
@@ -113,7 +116,6 @@ export function cutPolygonByGrid(
113
116
  // Get the bounding box of the outer polygon
114
117
  getBoundingBox(pos, size, holes[0] || pos.length, bbox);
115
118
  cell = getGridCell(bbox[0], gridResolution, gridOffset, cell);
116
- // @ts-expect-error
117
119
  const code = bitCode(bbox[1], cell);
118
120
 
119
121
  if (code) {
@@ -144,13 +146,11 @@ export function cutPolygonByGrid(
144
146
  }
145
147
  } else {
146
148
  // Polygon fits in a single cell, no more processing required
147
- const polygon = {positions: pos};
149
+ const polygon: Polygon = {positions: pos};
148
150
  if (edgeTypes) {
149
- // @ts-expect-error
150
151
  polygon.edgeTypes = types;
151
152
  }
152
153
  if (holes.length) {
153
- // @ts-expect-error
154
154
  polygon.holeIndices = holes;
155
155
  }
156
156
 
@@ -164,17 +164,25 @@ export function cutPolygonByGrid(
164
164
  // TYPE_BORDER - edge from the original polygon
165
165
  // TYPE_INSIDE - inside the original polygon
166
166
  // eslint-disable-next-line max-params
167
- 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
+ ) {
168
176
  const numPoints = (endIndex - startIndex) / size;
169
- const resultLow = [];
170
- const resultHigh = [];
171
- const typesLow = [];
172
- const typesHigh = [];
173
- const scratchPoint = [];
177
+ const resultLow: number[] = [];
178
+ const resultHigh: number[] = [];
179
+ const typesLow: number[] = [];
180
+ const typesHigh: number[] = [];
181
+ const scratchPoint: number[] = [];
174
182
 
175
- let p;
176
- let side;
177
- let type;
183
+ let p: number[];
184
+ let side: number;
185
+ let type: number;
178
186
  const prev = getPointAtIndex(positions, numPoints - 1, size, startIndex);
179
187
  let prevSide = Math.sign(edge & 8 ? prev[1] - bbox[3] : prev[0] - bbox[2]);
180
188
  let prevType = edgeTypes && edgeTypes[numPoints - 1];
@@ -217,7 +225,12 @@ function bisectPolygon(positions, edgeTypes, size, startIndex, endIndex, bbox, e
217
225
  ];
218
226
  }
219
227
 
220
- function getGridCell(p, gridResolution, gridOffset, out) {
228
+ function getGridCell(
229
+ p: number[],
230
+ gridResolution: number,
231
+ gridOffset: [number, number],
232
+ out: number[]
233
+ ): BoundingBox {
221
234
  const left = Math.floor((p[0] - gridOffset[0]) / gridResolution) * gridResolution + gridOffset[0];
222
235
  const bottom =
223
236
  Math.floor((p[1] - gridOffset[1]) / gridResolution) * gridResolution + gridOffset[1];
@@ -225,10 +238,10 @@ function getGridCell(p, gridResolution, gridOffset, out) {
225
238
  out[1] = bottom;
226
239
  out[2] = left + gridResolution;
227
240
  out[3] = bottom + gridResolution;
228
- return out;
241
+ return out as BoundingBox;
229
242
  }
230
243
 
231
- function moveToNeighborCell(cell, gridResolution, edge) {
244
+ function moveToNeighborCell(cell: number[], gridResolution: number, edge: number): void {
232
245
  if (edge & 8) {
233
246
  // top
234
247
  cell[1] += gridResolution;
@@ -248,7 +261,12 @@ function moveToNeighborCell(cell, gridResolution, edge) {
248
261
  }
249
262
  }
250
263
 
251
- function getBoundingBox(positions, size, endIndex, out) {
264
+ function getBoundingBox(
265
+ positions: NumericArray,
266
+ size: number,
267
+ endIndex: number,
268
+ out: number[][]
269
+ ): number[][] {
252
270
  let minX = Infinity;
253
271
  let maxX = -Infinity;
254
272
  let minY = Infinity;
@@ -1,20 +1,21 @@
1
1
  import {cutPolylineByGrid, cutPolygonByGrid} from './cut-by-grid';
2
2
  import {getPointAtIndex, push} from './utils';
3
3
  import type {Polygon} from './cut-by-grid';
4
+ import type {NumericArray} from '@math.gl/core';
4
5
 
5
6
  // https://en.wikipedia.org/wiki/Web_Mercator_projection
6
7
  const DEFAULT_MAX_LATITUDE = 85.051129;
7
8
 
8
9
  /** https://user-images.githubusercontent.com/2059298/78465769-938b7a00-76ae-11ea-9b95-1f4c26425ab9.png */
9
10
  export function cutPolylineByMercatorBounds(
10
- positions: Array<number>,
11
+ positions: NumericArray,
11
12
  options?: {
12
13
  size?: number;
13
14
  startIndex?: number;
14
15
  endIndex?: number;
15
16
  normalize?: boolean;
16
17
  }
17
- ): Array<number> {
18
+ ): number[][] {
18
19
  const {size = 2, startIndex = 0, endIndex = positions.length, normalize = true} = options || {};
19
20
 
20
21
  // Remap longitudes so that each segment takes the shorter path
@@ -26,7 +27,7 @@ export function cutPolylineByMercatorBounds(
26
27
  broken: true,
27
28
  gridResolution: 360,
28
29
  gridOffset: [-180, -180]
29
- });
30
+ }) as number[][];
30
31
 
31
32
  if (normalize) {
32
33
  // Each part is guaranteed to be in a single copy of the world
@@ -35,25 +36,24 @@ export function cutPolylineByMercatorBounds(
35
36
  shiftLongitudesIntoRange(part, size);
36
37
  }
37
38
  }
38
- // @ts-expect-error
39
39
  return parts;
40
40
  }
41
41
 
42
42
  /** https://user-images.githubusercontent.com/2059298/78465770-94241080-76ae-11ea-809a-6a8534dac1d9.png */
43
43
  export function cutPolygonByMercatorBounds(
44
- positions: Array<number>,
45
- holeIndices: Array<number> | null = null,
44
+ positions: number[],
45
+ holeIndices: number[] | null = null,
46
46
  options?: {
47
47
  size?: number;
48
48
  normalize?: boolean;
49
49
  maxLatitude?: number;
50
50
  edgeTypes?: boolean;
51
51
  }
52
- ): Array<Polygon> {
52
+ ): Polygon[] {
53
53
  const {size = 2, normalize = true, edgeTypes = false} = options || {};
54
54
  holeIndices = holeIndices || [];
55
- const newPositions = [];
56
- const newHoleIndices = [];
55
+ const newPositions: number[] = [];
56
+ const newHoleIndices: number[] = [];
57
57
  let srcStartIndex = 0;
58
58
  let targetIndex = 0;
59
59
 
@@ -105,7 +105,12 @@ export function cutPolygonByMercatorBounds(
105
105
  /* Helpers */
106
106
 
107
107
  // See comments for insertPoleVertices
108
- function findSplitIndex(positions, size, startIndex, endIndex) {
108
+ function findSplitIndex(
109
+ positions: number[],
110
+ size: number,
111
+ startIndex: number,
112
+ endIndex: number
113
+ ): number {
109
114
  let maxLat = -1;
110
115
  let pointIndex = -1;
111
116
  for (let i = startIndex + 1; i < endIndex; i += size) {
@@ -128,12 +133,12 @@ function findSplitIndex(positions, size, startIndex, endIndex) {
128
133
  // intersect with the ring itself. This is ensured by findSplitIndex, which returns the
129
134
  // vertex closest to the pole.
130
135
  function insertPoleVertices(
131
- positions,
132
- size,
133
- startIndex,
134
- endIndex,
135
- maxLatitude = DEFAULT_MAX_LATITUDE
136
- ) {
136
+ positions: number[],
137
+ size: number,
138
+ startIndex: number,
139
+ endIndex: number,
140
+ maxLatitude: number = DEFAULT_MAX_LATITUDE
141
+ ): void {
137
142
  // Check if the ring contains a pole
138
143
  const firstLng = positions[startIndex];
139
144
  const lastLng = positions[endIndex - size];
@@ -153,9 +158,14 @@ function insertPoleVertices(
153
158
  }
154
159
  }
155
160
 
156
- function wrapLongitudesForShortestPath(positions, size, startIndex, endIndex) {
157
- let prevLng = positions[0];
158
- 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;
159
169
  for (let i = startIndex; i < endIndex; i += size) {
160
170
  lng = positions[i];
161
171
  const delta = lng - prevLng;
@@ -166,8 +176,8 @@ function wrapLongitudesForShortestPath(positions, size, startIndex, endIndex) {
166
176
  }
167
177
  }
168
178
 
169
- function shiftLongitudesIntoRange(positions, size) {
170
- let refLng;
179
+ function shiftLongitudesIntoRange(positions: NumericArray, size: number): void {
180
+ let refLng: number;
171
181
  const pointCount = positions.length / size;
172
182
 
173
183
  // Find a longitude that is not on the edge of a world
package/src/earcut.ts CHANGED
@@ -22,7 +22,7 @@
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
 
package/src/lineclip.ts CHANGED
@@ -24,7 +24,7 @@
24
24
 
25
25
  import {push, copy, getPointAtIndex} from './utils';
26
26
 
27
- type BoundingBox = [number, number, number, number];
27
+ export type BoundingBox = [number, number, number, number];
28
28
 
29
29
  /**
30
30
  * Cohen-Sutherland line clipping algorithm, adapted to efficiently
@@ -41,13 +41,13 @@ export function clipPolyline(
41
41
  ): number[][] {
42
42
  const {size = 2, startIndex = 0, endIndex = positions.length} = options || {};
43
43
  const numPoints = (endIndex - startIndex) / size;
44
- const result = [];
45
- let part = [];
46
- let a;
47
- let b;
48
- let codeA = -1;
49
- let codeB;
50
- 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;
51
51
 
52
52
  for (let i = 1; i < numPoints; i++) {
53
53
  a = getPointAtIndex(positions, i - 1, size, startIndex, a);
@@ -114,11 +114,11 @@ export function clipPolygon(
114
114
  const {size = 2, endIndex = positions.length} = options || {};
115
115
  let {startIndex = 0} = options || {};
116
116
  let numPoints = (endIndex - startIndex) / size;
117
- let result;
118
- let p;
119
- let prev;
120
- let inside;
121
- let prevInside;
117
+ let result: number[];
118
+ let p: number[];
119
+ let prev: number[];
120
+ let inside: boolean;
121
+ let prevInside: boolean;
122
122
 
123
123
  // clip against each side of the clip rectangle
124
124
  for (let edge = 1; edge <= 8; edge *= 2) {
@@ -163,7 +163,7 @@ export function intersect(
163
163
  // Forces out[snapI] to be on the bbox edge
164
164
  // Interpolation introduces precision issue which may cause lineclip to be
165
165
  // stuck in an infinite loop
166
- let snap;
166
+ let snap: number;
167
167
  if (edge & 8) {
168
168
  // top
169
169
  t = (bbox[3] - a[1]) / (b[1] - a[1]);
@@ -132,7 +132,10 @@ export function forEachSegmentInPolygon(
132
132
  }
133
133
  }
134
134
 
135
- function reversePolygon(points, options) {
135
+ function reversePolygon(
136
+ points: NumericArray,
137
+ options: {start?: number; end?: number; size?: number}
138
+ ): void {
136
139
  const {start = 0, end = points.length, size = 2} = options;
137
140
 
138
141
  const numPoints = (end - start) / size;
package/src/polygon.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable no-undef, no-console */
2
2
  import {isArray} from '@math.gl/core';
3
3
  import type {SegmentVisitorPoints} from './polygon-utils';
4
+ import type {NumericArray} from '@math.gl/core';
4
5
 
5
6
  import {
6
7
  getPolygonSignedArea,
@@ -19,11 +20,11 @@ export type PolygonOptions = {
19
20
  };
20
21
 
21
22
  export default class Polygon {
22
- points; // : number[];
23
+ points: NumericArray | number[][];
23
24
  isFlatArray: boolean;
24
25
  options: PolygonOptions;
25
26
 
26
- constructor(points /* : number[] */, options: PolygonOptions = {}) {
27
+ constructor(points: NumericArray | number[][], options: PolygonOptions = {}) {
27
28
  this.points = points;
28
29
  this.isFlatArray = !isArray(points[0]);
29
30
 
@@ -42,9 +43,9 @@ export default class Polygon {
42
43
  * @returns Signed area of the polygon.
43
44
  */
44
45
  getSignedArea(): number {
45
- if (this.isFlatArray) return getPolygonSignedArea(this.points, this.options);
46
+ if (this.isFlatArray) return getPolygonSignedArea(this.points as NumericArray, this.options);
46
47
 
47
- return getPolygonSignedAreaPoints(this.points, this.options);
48
+ return getPolygonSignedAreaPoints(this.points as number[][], this.options);
48
49
  }
49
50
 
50
51
  /**
@@ -70,7 +71,7 @@ export default class Polygon {
70
71
  forEachSegment(visitor: SegmentVisitorPoints): void {
71
72
  if (this.isFlatArray) {
72
73
  forEachSegmentInPolygon(
73
- this.points,
74
+ this.points as NumericArray,
74
75
  // eslint-disable-next-line max-params
75
76
  (x1, y1, x2, y2, i1, i2) => {
76
77
  // TODO @igorDykhta original visitor uses arrays for each point, but with flat arrays performance degrades if we allocate points for each segment
@@ -79,7 +80,7 @@ export default class Polygon {
79
80
  this.options
80
81
  );
81
82
  } else {
82
- forEachSegmentInPolygonPoints(this.points, visitor, this.options);
83
+ forEachSegmentInPolygonPoints(this.points as number[][], visitor, this.options);
83
84
  }
84
85
  }
85
86
 
@@ -90,8 +91,8 @@ export default class Polygon {
90
91
  */
91
92
  modifyWindingDirection(direction: number): boolean {
92
93
  if (this.isFlatArray) {
93
- return modifyPolygonWindingDirection(this.points, direction, this.options);
94
+ return modifyPolygonWindingDirection(this.points as NumericArray, direction, this.options);
94
95
  }
95
- return modifyPolygonWindingDirectionPoints(this.points, direction, this.options);
96
+ return modifyPolygonWindingDirectionPoints(this.points as number[][], direction, this.options);
96
97
  }
97
98
  }
package/src/utils.ts CHANGED
@@ -1,4 +1,6 @@
1
- export function push(target, source) {
1
+ import type {NumericArray} from '@math.gl/core';
2
+
3
+ export function push(target: number[], source: number[]): boolean {
2
4
  const size = source.length;
3
5
  const startIndex = target.length;
4
6
 
@@ -22,14 +24,20 @@ export function push(target, source) {
22
24
  return true;
23
25
  }
24
26
 
25
- export function copy(target, source) {
27
+ export function copy(target: number[], source: Readonly<NumericArray>): void {
26
28
  const size = source.length;
27
29
  for (let i = 0; i < size; i++) {
28
30
  target[i] = source[i];
29
31
  }
30
32
  }
31
33
 
32
- export function getPointAtIndex(positions, index, size, offset, out = []) {
34
+ export function getPointAtIndex(
35
+ positions: NumericArray,
36
+ index: number,
37
+ size: number,
38
+ offset: number,
39
+ out: number[] = []
40
+ ): number[] {
33
41
  const startI = offset + index * size;
34
42
  for (let i = 0; i < size; i++) {
35
43
  out[i] = positions[startI + i];