Add OSM topography

This commit is contained in:
Fuhrmann 2025-03-11 11:56:33 +01:00
parent c20b682d33
commit c414b9d2d6
10 changed files with 96 additions and 18 deletions

View file

@ -1,7 +1,7 @@
import { Group, Mesh, MeshStandardMaterial, Scene } from "three";
import { buildMeshes } from "./utils/build-meshes";
import { Extent, buildScene } from "./utils/build-scene";
import { getMetadata } from "./utils/utils";
import { getCenter3D, getMetadata, transform } from "./utils/utils";
import { MODEL_ID, SERVICE_URL } from "./config";
import {
Orientation,
@ -9,6 +9,7 @@ import {
} from "./utils/build-clipping-planes";
import { buildCoordinateGrid } from "./utils/build-coordinate-grid";
import { DragControls } from "three/examples/jsm/Addons.js";
import { MapView, OpenStreetMapsProvider } from "geo-three";
export class SceneView {
private _scene: Scene;
@ -88,6 +89,13 @@ export class SceneView {
}
}
}
toggleTopography() {
const topo = this._scene.getObjectByName("topography");
if (topo) {
topo.visible = !topo.visible;
}
}
}
async function init(container: HTMLElement, modelId = MODEL_ID) {
@ -95,13 +103,16 @@ async function init(container: HTMLElement, modelId = MODEL_ID) {
const mappedFeatures = modelData.mappedfeatures;
const modelarea = modelData.modelarea;
// Transfrom extent to EPSG 3857
const pmin = transform([modelarea.x.min, modelarea.y.min, modelarea.z.min]);
const pmax = transform([modelarea.x.max, modelarea.y.max, modelarea.z.max]);
const extent: Extent = {
xmin: modelarea.x.min,
xmax: modelarea.x.max,
ymin: modelarea.y.min,
ymax: modelarea.y.max,
zmin: modelarea.z.min,
zmax: modelarea.z.max,
xmin: pmin[0],
xmax: pmax[0],
ymin: pmin[1],
ymax: pmax[1],
zmin: pmin[2],
zmax: pmax[2],
};
const { renderer, scene, camera, controls } = buildScene(container, extent);
@ -133,10 +144,21 @@ async function init(container: HTMLElement, modelId = MODEL_ID) {
const annotationsGroup = new Group();
annotationsGroup.name = "coordinate-grid";
annotationsGroup.add(...annotations, gridHelper);
annotationsGroup.visible = false;
scene.add(annotationsGroup);
//const axesHelper = new AxesHelper(5);
//scene.add(axesHelper);
// Create a map tiles provider object
const provider = new OpenStreetMapsProvider();
// Create the map view of OSM topography
const map = new MapView(MapView.PLANAR, provider);
map.rotateX(Math.PI / 2);
// map.position.setComponent(2, -100);
map.name = "topography";
scene.add(map);
return { scene, model, dragControls };
}

View file

@ -82,7 +82,13 @@ function createLabel(
transparent: true,
});
const sprite = new Sprite(spriteMaterial);
sprite.position.set(position.x, position.y, position.z);
// Set position according to axis orientation
if (orientation === Orientation.Horizontal) {
sprite.position.set(position.x + 1000, position.y - 1500, position.z + 500);
} else {
sprite.position.set(position.x, position.y - 500, position.z + 500);
}
sprite.scale.set(5000, 2500, 1); // Scale the sprite to make the text readable
return sprite;
}
@ -101,7 +107,8 @@ function generateTextCanvas(text: string, orientation: Orientation) {
context.fillStyle = "black";
if (orientation === Orientation.Horizontal) {
context.fillText(text, 300, 160);
//context.fillText(text, 300, 160);
context.fillText(text, 100, 90);
} else {
context.fillText(text, 100, 90);
}

View file

@ -6,7 +6,7 @@ import {
MeshStandardMaterial,
} from "three";
import { fetchVertices, fetchTriangleIndices } from "./utils";
import { fetchVertices, fetchTriangleIndices, transform } from "./utils";
import { TRIANGLE_INDICES_URL, VERTICES_URL } from "../config";
interface MappedFeature {
@ -38,7 +38,14 @@ async function buildMesh(layerData: MappedFeature) {
const geometry = new BufferGeometry();
const vertices = await fetchVertices(VERTICES_URL, geomId);
const positions = new BufferAttribute(vertices, 3);
// Transform coordinates to EPSG 3857
const vertices3857 = new Float32Array(vertices.length);
for (let i = 0; i < vertices.length; i += 3) {
const vertex = Array.from(vertices.slice(i, i + 3));
vertices3857.set(transform(vertex), i);
}
const positions = new BufferAttribute(vertices3857, 3);
geometry.setAttribute("position", positions);
const indexArray = await fetchTriangleIndices(TRIANGLE_INDICES_URL, geomId);

View file

@ -64,7 +64,7 @@ export function buildScene(container: HTMLElement, extent: Extent) {
maxSize * 25
);
camera.position.set(center.x, center.y - 125000, extent.zmax + 100000);
camera.position.set(center.x, center.y - 200000, extent.zmax + 100000);
camera.up.set(0, 0, 1);
camera.lookAt(center);

View file

@ -1,6 +1,7 @@
import { Vector3 } from "three";
import { Extent } from "./build-scene";
import { unpackEdges, unpackVertices } from "./parsers";
import { unpackEdges, unpackVertices } from "./decoders";
import proj4 from "proj4";
export function getMaxSize(extent: Extent) {
return Math.max(
@ -54,3 +55,13 @@ export async function fetchVertices(pointUrl: string, geomId: string) {
const buffer = await request(url);
return unpackVertices(buffer);
}
// Transformation from EPSG 3034 to EPSG 3857
const SOURCE = "EPSG:3034";
const PROJ_STRING =
"+proj=lcc +lat_0=52 +lon_0=10 +lat_1=35 +lat_2=65 +x_0=4000000 +y_0=2800000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs";
const DEST = "EPSG:3857";
proj4.defs(SOURCE, PROJ_STRING);
export function transform(p: number[]) {
return proj4(SOURCE, DEST, p);
}