@giro3d/giro3d
Version:
A JS/WebGL framework for 3D geospatial data visualization
87 lines (70 loc) • 2.97 kB
text/typescript
/*
* Copyright (c) 2015-2018, IGN France.
* Copyright (c) 2018-2026, Giro3D team.
* SPDX-License-Identifier: MIT
*/
import type { WebGLRenderer, Vector3 } from 'three';
import type { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js';
import type { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js';
import { Line2 } from 'three/examples/jsm/lines/Line2.js';
import type SimpleGeometryMesh from './SimpleGeometryMesh';
import { type DefaultUserData } from './SimpleGeometryMesh';
export default class LineStringMesh<UserData extends DefaultUserData = DefaultUserData>
extends Line2
implements SimpleGeometryMesh<UserData>
{
public readonly isSimpleGeometryMesh = true as const;
public readonly isLineStringMesh = true as const;
public override readonly type = 'LineStringMesh' as const;
public geometryOrigin: Vector3 | undefined;
private _featureOpacity = 1;
private _styleOpacity = 1;
public override userData: Partial<UserData> = {};
public constructor(geometry: LineGeometry, material: LineMaterial, opacity: number) {
super(geometry, material);
this.matrixAutoUpdate = false;
this._styleOpacity = opacity;
}
public dispose(): void {
this.geometry.dispose();
// Don't dispose the material as it is not owned by this mesh.
// @ts-expect-error dispose is not known because the types for three.js
// "forget" to expose event map to subclasses.
this.dispatchEvent({ type: 'dispose' });
}
public update(options: {
material: LineMaterial | null;
opacity: number;
renderOrder: number;
}): void {
if (options.material) {
this.material = options.material;
this._styleOpacity = options.opacity;
this.updateOpacity();
this.visible = true;
} else {
this.visible = false;
}
this.renderOrder = options.renderOrder;
}
private updateOpacity(): void {
this.material.opacity = this._styleOpacity * this._featureOpacity;
this.material.transparent = this.material.opacity < 1;
}
public override onBeforeRender(renderer: WebGLRenderer): void {
// We have to specify the screen size to be able to properly render
// lines that have a width in pixels. Note that this should be automatically done
// by three.js in the future, but for now we have to do it manually.
const { width, height } = renderer.getRenderTarget() ?? renderer.getContext().canvas;
this.material.resolution.set(width, height);
}
public set opacity(opacity: number) {
this._featureOpacity = opacity;
this.updateOpacity();
}
}
export function isLineStringMesh<UserData extends DefaultUserData = DefaultUserData>(
obj: unknown,
): obj is LineStringMesh<UserData> {
return (obj as LineStringMesh)?.isLineStringMesh ?? false;
}