Skip to content

Commit

Permalink
fix query rendered feature with layer filter
Browse files Browse the repository at this point in the history
refactor ray casting

Signed-off-by: Tim Deubler <[email protected]>
  • Loading branch information
TerminalTim committed Jul 11, 2024
1 parent e640a91 commit 4fdf983
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 28 deletions.
11 changes: 5 additions & 6 deletions packages/display/src/Map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ export class Map {

private _layerChangeListener(ev) {
// refresh render-data if layer is cleared
this.refresh(ev.type === 'clear'??ev.detail.layer);
this.refresh(ev.type === 'clear' ?? ev.detail.layer);
}

private initViewPort(): [number, number] {
Expand Down Expand Up @@ -776,12 +776,11 @@ export class Map {
if (!w && !h) {
// "pixel search"
skip3d = true;
layers = <TileLayer[]>(layers || this._layers);
const featureInfo = this._display.getRenderedFeatureAt(x, y, layers);
const featureInfo = this._display.getRenderedFeatureAt(x, y, <TileLayer[]>layers);

if (featureInfo.id != null) {
const layer = layers[featureInfo.layerIndex];
const provider = <FeatureProvider>layer.getProvider(this.getZoomlevel() ^ 0);
const {layer} = featureInfo;
const provider = layer.getProvider(this.getZoomlevel() ^ 0) as FeatureProvider;
const feature = provider?.search?.(featureInfo.id);

if (feature) {
Expand Down Expand Up @@ -1323,7 +1322,7 @@ export class Map {
*
* @param layers - the layer(s) that should be refreshed/re-rendered.
*/
refresh(layers?: TileLayer | Layer | (TileLayer|Layer)[]) {
refresh(layers?: TileLayer | Layer | (TileLayer | Layer)[]) {
if (!(layers instanceof Array)) {
layers = [layers];
}
Expand Down
2 changes: 1 addition & 1 deletion packages/display/src/displays/BasicDisplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ abstract class Display {
getRenderedFeatureAt(screenX: number, screenY: number, layers?: (TileLayer | CustomLayer)[]): {
id: number | string | null,
z?: number,
layerIndex?: number,
layer?: TileLayer,
pointWorld?: number[]
} {
return {id: null};
Expand Down
33 changes: 20 additions & 13 deletions packages/display/src/displays/webgl/Display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,18 @@ const stencilQuad = (quadkey: string, subQuadkey: string) => {
return [x, y];
};

type RendereFeatureResult = {
id: number | string | null;
z: number;
layer: TileLayer
};

export type TileBufferData = {
z: number;
tiled: true;
b: GeometryBuffer;
layerIndex: number;
// layerIndex: number;
layer: Layer,
data: {
tile: ScreenTile;
preview?: [string, number, number, number, number, number, number, number, number];
Expand Down Expand Up @@ -365,7 +371,8 @@ class WebGlDisplay extends BasicDisplay {
b: buffer,
z,
data,
layerIndex: layer.index,
layer,
// layerIndex: layer.index,
tiled
} as TileBufferData;
}
Expand Down Expand Up @@ -578,22 +585,20 @@ class WebGlDisplay extends BasicDisplay {
this.factory.destroy();
}

getRenderedFeatureAt(x: number, y: number, layers): {
id: number | string | null;
z: number;
layerIndex: number
} {
getRenderedFeatureAt(x: number, y: number, layers?: TileLayer[]): RendereFeatureResult {
// console.time('getRenderedFeatureAt');
this.rayCaster.init(x, y, this.w, this.h, this.s, 1 / this.groundResolution);

let intersectLayer: Layer = null;
const camWorldZ = this.rayCaster.origin[2] - 0.001;

const {tileBuffers, min3dZIndex} = this._zSortedTileBuffers;
let i = tileBuffers.length;
while (i--) {
let tileBuffer = tileBuffers[i];
if (!tileBuffer.tiled || !tileBuffer.b.pointerEvents) continue; // skip custom layers
let {b: buffer, z, data, tiled} = tileBuffer;
let {b: buffer, z, data, tiled, layer} = tileBuffer;

if (layers?.indexOf(layer.layer as TileLayer) == -1) continue;
let isOnTopOf3d = false;

if (buffer.flat) {
Expand All @@ -609,9 +614,10 @@ class WebGlDisplay extends BasicDisplay {
const hitTile = this.rayCaster.intersectAABBox(tileX, tileY, 0, tileX + size, tileY + size, camWorldZ);
if (!hitTile) continue;

const id = this.rayCaster.intersect(tileX, tileY, buffer, tileBuffer.layerIndex);
if (isOnTopOf3d && id != null) {
break;
const id = this.rayCaster.intersect(tileX, tileY, buffer);
if (id != null) {
intersectLayer = layer;
if (isOnTopOf3d) break;
}
}

Expand All @@ -638,7 +644,8 @@ class WebGlDisplay extends BasicDisplay {
// }
// }
// }
const result = this.rayCaster.getIntersectionTop();
const result = <RendereFeatureResult><unknown> this.rayCaster.getIntersectionTop();
result.layer = intersectLayer?.layer as TileLayer;
this.viewport(true);
return result;
}
Expand Down
13 changes: 5 additions & 8 deletions packages/display/src/displays/webgl/Raycaster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

import {add, cross, dot, normalize, scale, subtract, multiply, transformMat4} from 'gl-matrix/vec3';
import {GeometryBuffer} from './buffer/GeometryBuffer';
import {vec3} from '@here/xyz-maps-common';

export type Vec3 = [number, number, number];

type Result = { id: number | string; z: number; pointWorld: number[] }
class Raycaster {
private result: { id: number | string; z: number; layerIndex: number; pointWorld: number[] };
private result: Result;

// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
static rayIntersectsTriangle(
Expand Down Expand Up @@ -268,7 +268,7 @@ class Raycaster {
this.result = {
id: null,
z: Infinity,
layerIndex: null,
// layerIndex: null,
pointWorld: null
};
}
Expand All @@ -288,9 +288,8 @@ class Raycaster {
return (z - orgZ) / dirZ;
}

getIntersectionTop(): { id: number | string, z: number, layerIndex: number } {
getIntersectionTop(): Result {
const {result} = this;

if (result.z != Infinity) {
result.pointWorld = Raycaster.getPointAtRayLength(result.z, this.origin, this.direction);
}
Expand All @@ -300,8 +299,7 @@ class Raycaster {
intersect(
tileX: number,
tileY: number,
buffer: GeometryBuffer,
layerIndex: number
buffer: GeometryBuffer
) {
if (buffer.pointerEvents === false) return;

Expand All @@ -311,7 +309,6 @@ class Raycaster {

if (featureId != null) {
result.id = featureId;
result.layerIndex = layerIndex;
}
return featureId;
}
Expand Down

0 comments on commit 4fdf983

Please sign in to comment.