Skip to content

Commit b8cd17a

Browse files
authored
Earcut main thread fallback (#92)
* earcut main thread fallback * bump version
1 parent eb6f6cc commit b8cd17a

File tree

4 files changed

+59
-9
lines changed

4 files changed

+59
-9
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"examples/*"
55
],
66
"name": "@geoarrow/deck.gl-layers",
7-
"version": "0.3.0-beta.9",
7+
"version": "0.3.0-beta.10",
88
"type": "module",
99
"description": "",
1010
"source": "src/index.ts",

rollup.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export default [
5050
globals: {
5151
"@deck.gl/aggregation-layers/typed": "deck",
5252
"@deck.gl/core/typed": "deck",
53+
"@deck.gl/geo-layers/typed": "deck",
5354
"@deck.gl/layers/typed": "deck",
5455
"apache-arrow": "arrow",
5556
},

src/solid-polygon-layer.ts

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ type _GeoArrowSolidPolygonLayerProps = {
7272
* By default this loads from the jsdelivr CDN, but end users may want to host
7373
* this on their own domain.
7474
*/
75-
earcutWorkerUrl?: string | URL;
75+
earcutWorkerUrl?: string | URL | null;
7676

7777
/**
7878
* The number of workers used for the earcut thread pool.
@@ -130,27 +130,33 @@ export class GeoArrowSolidPolygonLayer<
130130
tableOffsets: Uint16Array | null;
131131
triangles: Uint32Array[] | null;
132132
earcutWorkerPool: Pool<FunctionThread> | null;
133-
earcutWorkerRequest: Promise<string>;
133+
earcutWorkerRequest: Promise<string> | null;
134134
};
135135

136136
initializeState(_context: LayerContext): void {
137137
this.state = {
138138
table: null,
139139
tableOffsets: null,
140140
triangles: null,
141-
earcutWorkerRequest: fetch(this.props.earcutWorkerUrl).then((resp) =>
142-
resp.text(),
143-
),
141+
earcutWorkerRequest:
142+
this.props.earcutWorkerUrl === null ||
143+
this.props.earcutWorkerUrl === undefined
144+
? null
145+
: fetch(this.props.earcutWorkerUrl).then((resp) => resp.text()),
144146
earcutWorkerPool: null,
145147
};
146148
}
147149

148150
// NOTE: I'm not 100% on the race condition implications of this; can we make
149151
// sure we never construct two pools?
150-
async initEarcutPool(): Promise<Pool<FunctionThread>> {
152+
async initEarcutPool(): Promise<Pool<FunctionThread> | null> {
151153
if (this.state.earcutWorkerPool) return this.state.earcutWorkerPool;
152154

153155
const workerText = await this.state.earcutWorkerRequest;
156+
if (!workerText) {
157+
return null;
158+
}
159+
154160
const pool = Pool<FunctionThread>(
155161
() => spawn(BlobWorker.fromText(workerText)),
156162
8,
@@ -205,6 +211,10 @@ export class GeoArrowSolidPolygonLayer<
205211
geometryColumn: ga.vector.PolygonVector,
206212
): Promise<Uint32Array[]> {
207213
const pool = await this.initEarcutPool();
214+
// Fallback if pool couldn't be created
215+
if (!pool) {
216+
return this._earcutPolygonVectorMainThread(geometryColumn);
217+
}
208218

209219
const result: Uint32Array[] = new Array(geometryColumn.data.length);
210220
console.time("earcut");
@@ -233,10 +243,31 @@ export class GeoArrowSolidPolygonLayer<
233243
return result;
234244
}
235245

246+
_earcutPolygonVectorMainThread(
247+
geometryColumn: ga.vector.PolygonVector,
248+
): Uint32Array[] {
249+
const result: Uint32Array[] = new Array(geometryColumn.data.length);
250+
251+
for (
252+
let recordBatchIdx = 0;
253+
recordBatchIdx < geometryColumn.data.length;
254+
recordBatchIdx++
255+
) {
256+
const polygonData = geometryColumn.data[recordBatchIdx];
257+
result[recordBatchIdx] = ga.algorithm.earcut(polygonData);
258+
}
259+
260+
return result;
261+
}
262+
236263
async _earcutMultiPolygonVector(
237264
geometryColumn: ga.vector.MultiPolygonVector,
238265
): Promise<Uint32Array[]> {
239266
const pool = await this.initEarcutPool();
267+
// Fallback if pool couldn't be created
268+
if (!pool) {
269+
return this._earcutMultiPolygonVectorMainThread(geometryColumn);
270+
}
240271

241272
const result: Uint32Array[] = new Array(geometryColumn.data.length);
242273
console.time("earcut");
@@ -266,6 +297,24 @@ export class GeoArrowSolidPolygonLayer<
266297
return result;
267298
}
268299

300+
_earcutMultiPolygonVectorMainThread(
301+
geometryColumn: ga.vector.MultiPolygonVector,
302+
): Uint32Array[] {
303+
const result: Uint32Array[] = new Array(geometryColumn.data.length);
304+
305+
for (
306+
let recordBatchIdx = 0;
307+
recordBatchIdx < geometryColumn.data.length;
308+
recordBatchIdx++
309+
) {
310+
const multiPolygonData = geometryColumn.data[recordBatchIdx];
311+
const polygonData = ga.child.getMultiPolygonChild(multiPolygonData);
312+
result[recordBatchIdx] = ga.algorithm.earcut(polygonData);
313+
}
314+
315+
return result;
316+
}
317+
269318
updateState({ props, changeFlags }: UpdateParameters<this>): void {
270319
if (changeFlags.dataChanged) {
271320
this.updateData();

0 commit comments

Comments
 (0)