Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
pyshx committed Mar 15, 2024
1 parent 3858e3a commit 8a91379
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 25 deletions.
52 changes: 52 additions & 0 deletions src/RenderWorker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { type TransferDescriptor } from "threads";
import { expose } from "threads/worker";

import { RenderTileParams, Renderer, RendererOption } from "./renderer";

const tileRenderers = new Map<string, Renderer>();

function createTileRenderKey({ urlTemplate, maximumLevel }: RendererOption): string {
return `${urlTemplate}:${maximumLevel}`;
}

async function getTileRenderer(options: RendererOption): Promise<Renderer> {
const key = createTileRenderKey(options);
let tileRenderer = tileRenderers.get(key);
if (tileRenderer == null) {
tileRenderer = new Renderer(options);
tileRenderers.set(key, tileRenderer);
}
return tileRenderer;
}

expose({
renderTile: async ({
coords,
canvas,
scaleFactor,
...renderOptions
}: RenderTileParams): Promise<void> => {
const context = canvas.getContext("2d") as OffscreenCanvasRenderingContext2D;
if (!context) {
return;
}
const tileRenderer = await getTileRenderer(renderOptions);
console.log("TileRenderer: ", tileRenderer);

await tileRenderer.render(
context,
coords,
scaleFactor,
renderOptions.currentLayer,
renderOptions.updatedAt,
);

await new Promise(resolve => {
requestAnimationFrame(resolve);
});
},
});

export type RendererWorker = object & {
renderTile: (params: TransferDescriptor<RenderTileParams>) => void;
};
4 changes: 2 additions & 2 deletions src/featureSelect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { LineString, Polygon, Point } from "@turf/turf";
import { ImageryLayerFeatureInfo } from "cesium";

import { evalFeature } from "./styleEvaluator/evaluator";
import { Feature, Geometry, Layer } from "./styleEvaluator/types";
import { Feature, Geometry, LayerSimple } from "./styleEvaluator/types";
import { TileCoordinates } from "./types";
import { generateIDWithMD5 } from "./util";

export const onSelectFeature = (
mvtFeature: VectorTileFeature,
tile: TileCoordinates,
layer?: Layer,
layer?: LayerSimple,
) => {
if (!layer) {
return;
Expand Down
12 changes: 9 additions & 3 deletions src/handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Renderer, RendererOption } from "./renderer";
import { RenderHandler } from "./renderHandler";
import { Layer } from "./styleEvaluator/types";
import { LayerSimple } from "./styleEvaluator/types";
import { TileCoordinates } from "./types";

export class RenderMainHandler extends RenderHandler {
Expand All @@ -17,7 +17,7 @@ export class RenderMainHandler extends RenderHandler {
canvas: HTMLCanvasElement;
requestedTile: TileCoordinates;
scaleFactor: number;
currentLayer?: Layer;
currentLayer?: LayerSimple;
updatedAt?: number;
}) {
const ctx = options.canvas.getContext("2d");
Expand All @@ -33,12 +33,18 @@ export class RenderMainHandler extends RenderHandler {
);
}

async pick(options: { requestedTile: TileCoordinates; longitude: number; latitude: number }) {
async pick(options: {
requestedTile: TileCoordinates;
longitude: number;
latitude: number;
currentLayer?: LayerSimple;
}) {
return (
(await this.renderer?.pickFeatures(
options.requestedTile,
options.longitude,
options.latitude,
options.currentLayer,
)) ?? []
);
}
Expand Down
61 changes: 61 additions & 0 deletions src/imageryProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,22 @@ import {
ImageryLayerFeatureInfo,
} from "cesium";
import { LRUCache } from "lru-cache";
import { Transfer } from "threads";

import { RenderMainHandler } from "./handler";
import { RenderHandler } from "./renderHandler";
import { LayerSimple } from "./styleEvaluator/types";
import { CESIUM_CANVAS_SIZE, ImageryProviderOption, TileCoordinates } from "./types";
import { RenderWorkerHandler } from "./worker/handler";
import WorkerBlob from "./worker/receiver?worker&inline";
import { queue } from "./workerPool";

type ImageryProviderTrait = ImageryProvider;

export class MVTImageryProvider implements ImageryProviderTrait {
static maximumTasks = 50;
static maximumTasksPerImagery = 6;
// private taskCount = 0;

private readonly tileCache: LRUCache<string, HTMLCanvasElement> | undefined;

Expand All @@ -43,6 +46,7 @@ export class MVTImageryProvider implements ImageryProviderTrait {
private readonly _handler: RenderHandler;
private readonly _currentLayer?: LayerSimple;
private readonly _updatedAt?: number;
// private readonly _useWorker?: boolean;

constructor(options: ImageryProviderOption) {
this._minimumLevel = options.minimumLevel ?? 0;
Expand Down Expand Up @@ -72,6 +76,7 @@ export class MVTImageryProvider implements ImageryProviderTrait {
.then(() => true);
this._currentLayer = options.layer;
this._updatedAt = options.updatedAt;
// this._useWorker = options.worker ?? false;
}

get tileWidth() {
Expand Down Expand Up @@ -157,6 +162,13 @@ export class MVTImageryProvider implements ImageryProviderTrait {
level: number,
_request?: Request | undefined,
): Promise<ImageryTypes> | undefined {
// if (
// this.taskCount >= MVTImageryProvider.maximumTasksPerImagery ||
// !canQueue(MVTImageryProvider.maximumTasks)
// ) {
// return;
// }

const cacheKey = `${x}/${y}/${level}`;
if (this.tileCache?.has(cacheKey) === true) {
const canvas = this.tileCache.get(cacheKey);
Expand All @@ -175,6 +187,29 @@ export class MVTImageryProvider implements ImageryProviderTrait {
const currentLayer = this._currentLayer;
const updatedAt = this._updatedAt;

console.log("REACHED HERE!!!: ", currentLayer, updatedAt);

// const offscreen = canvas.transferControlToOffscreen();

// ++this.taskCount;

// if (this._useWorker) {
// return this.renderTile(requestedTile, offscreen, scaleFactor, currentLayer, updatedAt)
// .then(() => {
// this.tileCache?.set(cacheKey, canvas);
// return canvas;
// })
// .catch(error => {
// if (error instanceof Error && error.message.startsWith("Unimplemented type")) {
// return canvas;
// }
// throw error;
// })
// .finally(() => {
// // --this.taskCount;
// });
// }

return this.readyPromise.then(() => {
return this._handler
.render({
Expand All @@ -190,6 +225,29 @@ export class MVTImageryProvider implements ImageryProviderTrait {
});
}

async renderTile(
coords: TileCoordinates,
canvas: OffscreenCanvas,
scaleFactor: number,
currentLayer?: LayerSimple,
updatedAt?: number,
): Promise<void> {
await queue(async task => {
await task.renderTile(
Transfer(
{
canvas,
coords,
scaleFactor,
currentLayer,
updatedAt,
},
[canvas],
),
);
});
}

async pickFeatures(
x: number,
y: number,
Expand All @@ -203,10 +261,13 @@ export class MVTImageryProvider implements ImageryProviderTrait {
level: level,
};

const currentLayer = this._currentLayer;

return this._handler.pick({
requestedTile,
longitude,
latitude,
currentLayer,
});

// return (await this._pickFeaturesFromLayer(url, requestedTile, longitude, latitude)).flat();
Expand Down
1 change: 1 addition & 0 deletions src/renderHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export abstract class RenderHandler {
requestedTile: TileCoordinates;
longitude: number;
latitude: number;
currentLayer?: LayerSimple;
}): Promise<ImageryLayerFeatureInfo[]>;
abstract dispose(): void;
}
49 changes: 29 additions & 20 deletions src/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { WebMercatorTilingScheme } from "@cesium/engine";
import MPoint from "@mapbox/point-geometry";
import Point from "@mapbox/point-geometry";
import { VectorTile, VectorTileFeature, VectorTileLayer } from "@mapbox/vector-tile";
import { Cartesian2, Cartographic, ImageryLayerFeatureInfo } from "cesium";
import Pbf from "pbf";

import { onSelectFeature } from "./featureSelect";
import { evalStyle } from "./style";
import { Layer, LayerSimple } from "./styleEvaluator/types";
import { TileCoordinates, URLTemplate, CESIUM_CANVAS_SIZE, ImageryProviderOption } from "./types";
import { isFeatureClicked } from "./terria";
import { onSelectFeature } from "./featureSelect";
import { TileCoordinates, URLTemplate, CESIUM_CANVAS_SIZE, ImageryProviderOption } from "./types";

const defaultParseTile = async (url?: string) => {
const ab = await fetchResourceAsArrayBuffer(url);
Expand All @@ -33,7 +33,7 @@ const fetchResourceAsArrayBuffer = (url?: string) => {
?.catch(() => {});
};

let currentTime: number | undefined;
// let currentTime: number | undefined;

export type RendererOption = Pick<ImageryProviderOption, "urlTemplate" | "maximumLevel"> & {
layerNames: string[];
Expand All @@ -45,6 +45,7 @@ export interface RenderTileParams extends RendererOption {
canvas: OffscreenCanvas;
scaleFactor: number;
currentLayer?: LayerSimple;
updatedAt?: number;
}

export type RenderingContext2D = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
Expand Down Expand Up @@ -76,6 +77,7 @@ export class Renderer {
currentLayer?: Layer,
updatedAt?: number,
) {
console.log("RENDER IS CALLED!!!");
const url = buildURLWithTileCoordinates(this._urlTemplate, requestedTile);
await Promise.all(
this._layerNames.map(n =>
Expand All @@ -91,7 +93,7 @@ export class Renderer {
layerName: string,
scaleFactor: number,
currentLayer?: Layer,
updatedAt?: number,
_updatedAt?: number,
): Promise<void> {
if (!url) return;

Expand Down Expand Up @@ -127,10 +129,10 @@ export class Renderer {
for (let i = 0; i < layer.length; i++) {
const feature = layer.feature(i);

// Early return.
if (onRenderFeature(updatedAt)) {
continue;
}
// // Early return.
// if (onRenderFeature(updatedAt)) {
// continue;
// }

const style = evalStyle(feature, requestedTile, currentLayer);

Expand Down Expand Up @@ -237,16 +239,22 @@ export class Renderer {
context.stroke();
}

pickFeatures(requestedTile: TileCoordinates, longitude: number, latitude: number) {
pickFeatures(
requestedTile: TileCoordinates,
longitude: number,
latitude: number,
currentLayer?: LayerSimple,
) {
const url = buildURLWithTileCoordinates(this._urlTemplate, requestedTile);
return this._pickFeaturesFromLayer(url, requestedTile, longitude, latitude);
return this._pickFeaturesFromLayer(url, requestedTile, longitude, latitude, currentLayer);
}

async _pickFeaturesFromLayer(
url: string,
requestedTile: TileCoordinates,
longitude: number,
latitude: number,
currentLayer?: LayerSimple,
) {
const tile = await this._cachedTile(url);

Expand All @@ -256,7 +264,7 @@ export class Renderer {
if (!layer) {
return []; // return empty list of features for empty tile
}
const f = await this._pickFeatures(requestedTile, longitude, latitude, layer);
const f = await this._pickFeatures(requestedTile, longitude, latitude, layer, currentLayer);
if (f) {
return f;
}
Expand All @@ -272,6 +280,7 @@ export class Renderer {
longitude: number,
latitude: number,
layer: VectorTileLayer,
currentLayer?: LayerSimple,
): Promise<ImageryLayerFeatureInfo[]> {
const boundRect = this._tilingScheme.tileXYToNativeRectangle(
requestedTile.x,
Expand Down Expand Up @@ -314,15 +323,15 @@ export class Renderer {
vt_range,
vt_range,
);
const point = new MPoint(pos.x, pos.y);
const point = new Point(pos.x, pos.y);

for (let i = 0; i < layer.length; i++) {
const feature = layer.feature(i);
if (
VectorTileFeature.types[feature.type] === "Polygon" &&
isFeatureClicked(feature.loadGeometry(), point)
) {
const feat = onSelectFeature(feature, requestedTile);
const feat = onSelectFeature(feature, requestedTile, currentLayer);
if (feat) {
features.push(feat);
}
Expand Down Expand Up @@ -377,9 +386,9 @@ const buildURLWithTileCoordinates = (template: URLTemplate, tile: TileCoordinate
return y;
};

const onRenderFeature = (updatedAt?: number): boolean => {
if (!currentTime && !updatedAt) {
currentTime = updatedAt;
}
return currentTime === updatedAt;
};
// const onRenderFeature = (updatedAt?: number): boolean => {
// if (!currentTime && !updatedAt) {
// currentTime = updatedAt;
// }
// return currentTime === updatedAt;
// };
Loading

0 comments on commit 8a91379

Please sign in to comment.