Skip to content

Commit 736e8c3

Browse files
authored
earcut worker (#20)
* earcut worker * fix type * bump version
1 parent cbfac73 commit 736e8c3

File tree

11 files changed

+684
-192
lines changed

11 files changed

+684
-192
lines changed

package.json

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@geoarrow/geoarrow-js",
3-
"version": "0.2.0",
3+
"version": "0.3.0-beta.1",
44
"description": "TypeScript implementation of GeoArrow",
55
"source": "src/index.ts",
66
"umd:main": "dist/geoarrow.umd.js",
@@ -26,7 +26,9 @@
2626
"license": "MIT",
2727
"type": "module",
2828
"scripts": {
29-
"build": "rollup -c rollup.config.js",
29+
"build:rollup": "rollup -c rollup.config.js",
30+
"build:workers": "node ./worker-build.mjs",
31+
"build": "yarn build:rollup && yarn build:workers",
3032
"clean": "rimraf dist",
3133
"docs:build": "typedoc",
3234
"docs:publish": "gh-pages -d docs_build",
@@ -50,6 +52,7 @@
5052
"@types/node": "^20.9.3",
5153
"@types/proj4": "^2",
5254
"apache-arrow": "^14",
55+
"esbuild": "^0.19.8",
5356
"gh-pages": "^6.1.0",
5457
"prettier": "^3.1.0",
5558
"rimraf": "^5.0.5",
@@ -66,6 +69,7 @@
6669
},
6770
"dependencies": {
6871
"@math.gl/polygon": "^4.0.0",
69-
"proj4": "^2.9.2"
72+
"proj4": "^2.9.2",
73+
"threads": "^1.7.0"
7074
}
7175
}

src/child.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,37 @@
22
* Strongly typed accessors for children, since arrow.Data.children[] is untyped
33
*/
44

5-
import * as arrow from "apache-arrow";
5+
import { Data } from "apache-arrow/data";
6+
import { Vector } from "apache-arrow/vector";
7+
import { Float } from "apache-arrow/type";
68
import {
79
LineStringData,
810
MultiLineStringData,
911
MultiPointData,
1012
MultiPolygonData,
1113
PointData,
1214
PolygonData,
13-
} from "./data.js";
15+
} from "./data";
1416
import {
1517
LineStringVector,
1618
MultiLineStringVector,
1719
MultiPointVector,
1820
MultiPolygonVector,
1921
PointVector,
2022
PolygonVector,
21-
} from "./vector.js";
23+
} from "./vector";
2224

23-
export function getPointChild(input: PointData): arrow.Data<arrow.Float>;
24-
export function getPointChild(input: PointVector): arrow.Vector<arrow.Float>;
25+
export function getPointChild(input: PointData): Data<Float>;
26+
export function getPointChild(input: PointVector): Vector<Float>;
2527

2628
export function getPointChild(
2729
input: PointData | PointVector,
28-
): arrow.Data<arrow.Float> | arrow.Vector<arrow.Float> {
30+
): Data<Float> | Vector<Float> {
2931
if ("data" in input) {
3032
return input.getChildAt(0)!;
3133
}
3234

33-
return input.children[0] as arrow.Data<arrow.Float>;
35+
return input.children[0] as Data<Float>;
3436
}
3537

3638
export function getLineStringChild(input: LineStringData): PointData;

src/data.ts

+14-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as arrow from "apache-arrow";
1+
import { Data } from "apache-arrow/data";
22
import {
33
Point,
44
LineString,
@@ -12,14 +12,14 @@ import {
1212
isMultiPoint,
1313
isMultiLineString,
1414
isMultiPolygon,
15-
} from "./type.js";
15+
} from "./type";
1616

17-
export type PointData = arrow.Data<Point>;
18-
export type LineStringData = arrow.Data<LineString>;
19-
export type PolygonData = arrow.Data<Polygon>;
20-
export type MultiPointData = arrow.Data<MultiPoint>;
21-
export type MultiLineStringData = arrow.Data<MultiLineString>;
22-
export type MultiPolygonData = arrow.Data<MultiPolygon>;
17+
export type PointData = Data<Point>;
18+
export type LineStringData = Data<LineString>;
19+
export type PolygonData = Data<Polygon>;
20+
export type MultiPointData = Data<MultiPoint>;
21+
export type MultiLineStringData = Data<MultiLineString>;
22+
export type MultiPolygonData = Data<MultiPolygon>;
2323
export type GeoArrowData =
2424
| PointData
2525
| LineStringData
@@ -28,28 +28,26 @@ export type GeoArrowData =
2828
| MultiLineStringData
2929
| MultiPolygonData;
3030

31-
export function isPointData(data: arrow.Data): data is PointData {
31+
export function isPointData(data: Data): data is PointData {
3232
return isPoint(data.type);
3333
}
3434

35-
export function isLineStringData(data: arrow.Data): data is LineStringData {
35+
export function isLineStringData(data: Data): data is LineStringData {
3636
return isLineString(data.type);
3737
}
3838

39-
export function isPolygonData(data: arrow.Data): data is PolygonData {
39+
export function isPolygonData(data: Data): data is PolygonData {
4040
return isPolygon(data.type);
4141
}
4242

43-
export function isMultiPointData(data: arrow.Data): data is MultiPointData {
43+
export function isMultiPointData(data: Data): data is MultiPointData {
4444
return isMultiPoint(data.type);
4545
}
4646

47-
export function isMultiLineStringData(
48-
data: arrow.Data,
49-
): data is MultiLineStringData {
47+
export function isMultiLineStringData(data: Data): data is MultiLineStringData {
5048
return isMultiLineString(data.type);
5149
}
5250

53-
export function isMultiPolygonData(data: arrow.Data): data is MultiPolygonData {
51+
export function isMultiPolygonData(data: Data): data is MultiPolygonData {
5452
return isMultiPolygon(data.type);
5553
}

src/type.ts

+31-27
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
1-
import * as arrow from "apache-arrow";
1+
import {
2+
Struct,
3+
Float,
4+
List,
5+
FixedSizeList,
6+
DataType,
7+
} from "apache-arrow/type";
28

39
// Note: this apparently has to be arrow.Float and not arrow.Float64 to ensure
410
// that recreating a data instance with arrow.makeData type checks using the
511
// input's data type.
6-
export type InterleavedCoord = arrow.FixedSizeList<arrow.Float>;
7-
export type SeparatedCoord = arrow.Struct<{
8-
x: arrow.Float;
9-
y: arrow.Float;
12+
export type InterleavedCoord = FixedSizeList<Float>;
13+
export type SeparatedCoord = Struct<{
14+
x: Float;
15+
y: Float;
1016
}>;
1117
// TODO: support separated coords
1218
export type Coord = InterleavedCoord; // | SeparatedCoord;
1319
export type Point = Coord;
14-
export type LineString = arrow.List<Coord>;
15-
export type Polygon = arrow.List<arrow.List<Coord>>;
16-
export type MultiPoint = arrow.List<Coord>;
17-
export type MultiLineString = arrow.List<arrow.List<Coord>>;
18-
export type MultiPolygon = arrow.List<arrow.List<arrow.List<Coord>>>;
20+
export type LineString = List<Coord>;
21+
export type Polygon = List<List<Coord>>;
22+
export type MultiPoint = List<Coord>;
23+
export type MultiLineString = List<List<Coord>>;
24+
export type MultiPolygon = List<List<List<Coord>>>;
1925
export type GeoArrowType =
2026
| Point
2127
| LineString
@@ -25,22 +31,22 @@ export type GeoArrowType =
2531
| MultiPolygon;
2632

2733
/** Check that the given type is a Point data type */
28-
export function isPoint(type: arrow.DataType): type is Point {
29-
if (arrow.DataType.isFixedSizeList(type)) {
34+
export function isPoint(type: DataType): type is Point {
35+
if (DataType.isFixedSizeList(type)) {
3036
// Check list size
3137
if (![2, 3, 4].includes(type.listSize)) {
3238
return false;
3339
}
3440

3541
// Check child of FixedSizeList is floating type
36-
if (!arrow.DataType.isFloat(type.children[0])) {
42+
if (!DataType.isFloat(type.children[0])) {
3743
return false;
3844
}
3945

4046
return true;
4147
}
4248

43-
if (arrow.DataType.isStruct(type)) {
49+
if (DataType.isStruct(type)) {
4450
// Check number of children
4551
if (![2, 3, 4].includes(type.children.length)) {
4652
return false;
@@ -53,7 +59,7 @@ export function isPoint(type: arrow.DataType): type is Point {
5359
return false;
5460
}
5561

56-
if (!type.children.every((field) => arrow.DataType.isFloat(field))) {
62+
if (!type.children.every((field) => DataType.isFloat(field))) {
5763
return false;
5864
}
5965

@@ -63,9 +69,9 @@ export function isPoint(type: arrow.DataType): type is Point {
6369
return false;
6470
}
6571

66-
export function isLineString(type: arrow.DataType): type is LineString {
72+
export function isLineString(type: DataType): type is LineString {
6773
// Check the outer type is a List
68-
if (!arrow.DataType.isList(type)) {
74+
if (!DataType.isList(type)) {
6975
return false;
7076
}
7177

@@ -77,9 +83,9 @@ export function isLineString(type: arrow.DataType): type is LineString {
7783
return true;
7884
}
7985

80-
export function isPolygon(type: arrow.DataType): type is Polygon {
86+
export function isPolygon(type: DataType): type is Polygon {
8187
// Check the outer vector is a List
82-
if (!arrow.DataType.isList(type)) {
88+
if (!DataType.isList(type)) {
8389
return false;
8490
}
8591

@@ -91,9 +97,9 @@ export function isPolygon(type: arrow.DataType): type is Polygon {
9197
return true;
9298
}
9399

94-
export function isMultiPoint(type: arrow.DataType): type is MultiPoint {
100+
export function isMultiPoint(type: DataType): type is MultiPoint {
95101
// Check the outer vector is a List
96-
if (!arrow.DataType.isList(type)) {
102+
if (!DataType.isList(type)) {
97103
return false;
98104
}
99105

@@ -105,11 +111,9 @@ export function isMultiPoint(type: arrow.DataType): type is MultiPoint {
105111
return true;
106112
}
107113

108-
export function isMultiLineString(
109-
type: arrow.DataType,
110-
): type is MultiLineString {
114+
export function isMultiLineString(type: DataType): type is MultiLineString {
111115
// Check the outer vector is a List
112-
if (!arrow.DataType.isList(type)) {
116+
if (!DataType.isList(type)) {
113117
return false;
114118
}
115119

@@ -121,9 +125,9 @@ export function isMultiLineString(
121125
return true;
122126
}
123127

124-
export function isMultiPolygon(type: arrow.DataType): type is MultiPolygon {
128+
export function isMultiPolygon(type: DataType): type is MultiPolygon {
125129
// Check the outer vector is a List
126-
if (!arrow.DataType.isList(type)) {
130+
if (!DataType.isList(type)) {
127131
return false;
128132
}
129133

src/vector.ts

+14-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as arrow from "apache-arrow";
1+
import { Vector } from "apache-arrow/vector";
22
import {
33
Point,
44
LineString,
@@ -12,14 +12,14 @@ import {
1212
isMultiPoint,
1313
isMultiLineString,
1414
isMultiPolygon,
15-
} from "./type.js";
15+
} from "./type";
1616

17-
export type PointVector = arrow.Vector<Point>;
18-
export type LineStringVector = arrow.Vector<LineString>;
19-
export type PolygonVector = arrow.Vector<Polygon>;
20-
export type MultiPointVector = arrow.Vector<MultiPoint>;
21-
export type MultiLineStringVector = arrow.Vector<MultiLineString>;
22-
export type MultiPolygonVector = arrow.Vector<MultiPolygon>;
17+
export type PointVector = Vector<Point>;
18+
export type LineStringVector = Vector<LineString>;
19+
export type PolygonVector = Vector<Polygon>;
20+
export type MultiPointVector = Vector<MultiPoint>;
21+
export type MultiLineStringVector = Vector<MultiLineString>;
22+
export type MultiPolygonVector = Vector<MultiPolygon>;
2323
export type GeoArrowVector =
2424
| PointVector
2525
| LineStringVector
@@ -28,34 +28,30 @@ export type GeoArrowVector =
2828
| MultiLineStringVector
2929
| MultiPolygonVector;
3030

31-
export function isPointVector(vector: arrow.Vector): vector is PointVector {
31+
export function isPointVector(vector: Vector): vector is PointVector {
3232
return isPoint(vector.type);
3333
}
3434

35-
export function isLineStringVector(
36-
vector: arrow.Vector,
37-
): vector is LineStringVector {
35+
export function isLineStringVector(vector: Vector): vector is LineStringVector {
3836
return isLineString(vector.type);
3937
}
4038

41-
export function isPolygonVector(vector: arrow.Vector): vector is PolygonVector {
39+
export function isPolygonVector(vector: Vector): vector is PolygonVector {
4240
return isPolygon(vector.type);
4341
}
4442

45-
export function isMultiPointVector(
46-
vector: arrow.Vector,
47-
): vector is MultiPointVector {
43+
export function isMultiPointVector(vector: Vector): vector is MultiPointVector {
4844
return isMultiPoint(vector.type);
4945
}
5046

5147
export function isMultiLineStringVector(
52-
vector: arrow.Vector,
48+
vector: Vector,
5349
): vector is MultiLineStringVector {
5450
return isMultiLineString(vector.type);
5551
}
5652

5753
export function isMultiPolygonVector(
58-
vector: arrow.Vector,
54+
vector: Vector,
5955
): vector is MultiPolygonVector {
6056
return isMultiPolygon(vector.type);
6157
}

src/worker-bundle/earcut.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { TransferDescriptor } from "threads";
2+
import { expose, Transfer } from "threads/worker";
3+
import { PolygonData } from "../data";
4+
import { earcut } from "../algorithm/earcut";
5+
6+
function earcutWorker(polygonData: PolygonData): TransferDescriptor {
7+
// NOTE!! Here we don't reconstruct a full arrow.Data instance to save on
8+
// bundle size! We rely on the fact that nothing in the `earcut` function uses
9+
// any class methods, which is not an ideal/easy assumption. Ideally we'll
10+
// have functions in the future to validate geometry `Data` instances and
11+
// construct Data and Vector instances without bringing in all of Arrow JS.
12+
13+
// const rehydratedData = rehydratePolygonData(polygonData);
14+
const earcutTriangles = earcut(polygonData);
15+
return Transfer(earcutTriangles, [earcutTriangles.buffer]);
16+
}
17+
18+
export type EarcutOnWorker = typeof earcutWorker;
19+
20+
expose(earcutWorker);

0 commit comments

Comments
 (0)