GeotiefExplore/src/js/core/Map.ts
Arno Kaimbacher c60220d08d - LayerControl: topogrphy default of
- performance optimization for vendor file (only importing specific classes from three.js - not the whole library)
2021-09-02 13:20:56 +02:00

266 lines
No EOL
8.7 KiB
TypeScript

import { OrbitControls } from '../lib/OrbitControls';
import * as dom from './domUtil';
import { HomeButton } from '../controls/HomeButton';
import { ZoomControl } from '../controls/ZoomControl';
import { BoreholeControl } from '../controls/BoreholeControl';
import { BoreholePopup } from '../controls/BoreholePopup';
import * as util from './utilities';
import { TinLayer } from '../layer/TinLayer';
import { DemLayer } from '../layer/DemLayer';
import { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera';
import { Vector3 } from 'three/src/math/Vector3';
import { Group } from 'three/src/objects/Group';
import { Layer } from '../layer/Layer';
import { LayerService } from '../services/layer.service';
class Map extends OrbitControls {
private _layers;
private _controlContainer;
private _controlCorners;
private _controls;
public container: HTMLElement;
public size: number;
public camera: PerspectiveCamera;
public length: number;
public width: number;
public height: number;
public x; public y; public z;
public title: string;
public serviceUrl: string;
public basemaps: Object;
public baseExtent: Object;
public currentBasemap: Layer;
public contact: string;
public model_id: number;
private _modelNode: Group;
private _stencilNode: Group;
private _profileNode: Group;
constructor(x, y, z, scene, container, model_id) {
let size = Math.max(x.max - x.min, y.max - y.min, z.max - z.min);
let center = new Vector3((x.min + x.max) / 2, (y.min + y.max) / 2, 0);
let width, height;
if (container.clientWidth && container.clientHeight) {
width = container.clientWidth;
height = container.clientHeight;
} else {
width = window.innerWidth;
height = window.innerHeight;
}
let camera = new PerspectiveCamera(30, width / height, 100, 100000);
const camDirection = new Vector3(-0.5, -Math.SQRT1_2, 0.5);
// const camDirection = new Vector3(0, 0, 1);
const camOffset = camDirection.multiplyScalar(size * 2);
camera.position.copy(center);
camera.position.add(camOffset);
camera.near = size * 0.1;
camera.far = size * 25;
camera.updateProjectionMatrix();
// call parent constructor of OrbitControls
super(size, center, camera, scene, container);
this.model_id = model_id;
this.size = size;
this.camera = camera;
this.container = container;
this.scene = scene;
this.length = x.max - x.min;
this.width = y.max - y.min;
this.height = z.max - z.min;
this.x = x;
this.y = y;
this.z = z;
this.center = center;
this.baseExtent = {
x: x,
y: y
};
this._modelNode = new Group();
this._stencilNode = new Group();
this._profileNode = new Group();
this.scene.add(this._modelNode);
this.scene.add(this._stencilNode);
this.scene.add(this._profileNode);
//init the control corners
if (this._initControlPos) {
this._initControlPos();
}
// to do: initialize map title via serviceUrl:
// this.title = "Geological 3D model of Vienna";
// this.serviceUrl = serviceUrl;
this._layers = {};
this.basemaps = {
"currentVersion": 10.01,
"services": [
{ "name": "osm:wms", "type": "MapServer", 'image': 'background_osm_world_topography.png', 'title': 'OSM WMS' },
{ "name": "osm:gray-wms", "type": "MapServer", 'image': 'background_osm_gray_world_topography.png', 'title': 'OSM Gray WMS' },
// { "name": "esri:topograhy", "type": "MapServer", 'image': 'background_esri_world_topography.png', 'title': 'ESRI Topography' },
]
};
}
static async build(scene, container, serviceUrl, model_id) {
const modelData = await util.getMetadata(serviceUrl + model_id);
let modelarea = modelData.modelarea;
// do your async stuff here
// now instantiate and return a class
let map = new Map(modelarea.x, modelarea.y, modelarea.z, scene, container, model_id);
map._initDataLayers(modelData.mappedfeatures);
map._initControls();
map.title = modelData.model.model_name;
map.contact = modelData.model.model_point_of_contact;
return map;
}
get modelNode(): Group {
return this._modelNode;
}
get stencilNode(): Group {
return this._stencilNode;
}
get profileNode(): Group {
return this._profileNode;
}
get layers() {
return this._layers;
}
get controlCorners() {
return this._controlCorners;
}
async _initDataLayers(mappedFeatures) {
const callStack = [];
for (let i = 0; i < mappedFeatures.length; i++) {
let layerData = mappedFeatures[i];
let dxfLayer = new TinLayer({
featuregeom_id: layerData.featuregeom_id,
q: true,
type: "3dface",
name: layerData.preview.legend_text, //layerData.legend_description,
description: "test",
color: layerData.preview.legend_color, //layerData.color
citation: layerData.geologicdescription !== null ? layerData.geologicdescription.citation : null,
feature_type: layerData.geologicdescription !== null ? layerData.geologicdescription['feature type'] : null,
});
callStack.push(this.addLayer(dxfLayer));
// if (dxfLayer.name == "Topography") {
// this.currentBasemap = dxfLayer;
// }
}
if (this.model_id == 20) {
let layerService = new LayerService();
let demLayer = layerService.getDemLayer(this.center, this.baseExtent);
callStack.push(this.addLayer(demLayer));
this.currentBasemap = demLayer;
}
await Promise.all(callStack);
this.emit("ready");
}
private _initControlPos() {
let corners = this._controlCorners = {};
let l = 'gba-';
this._controlContainer =
dom.createDom("div", { "class": l + 'control-container' }, this.container);
let createCorner = (vSide: string, hSide: string): void => {
let className = l + vSide + ' ' + l + hSide;
corners[vSide + hSide] = dom.createDom("div", { "class": className }, this._controlContainer);
}
createCorner('top', 'left');
createCorner('top', 'right');
createCorner('bottom', 'left');
createCorner('bottom', 'right');
}
private _initControls() {
this._controls = this._controls || {};
// this._controls.homeControl = (new HomeButton()).addTo(this);
let homeControl = this._controls.homeControl = new HomeButton();
homeControl.addTo(this);
let zoomControl = this._controls.zoomControl = new ZoomControl();
zoomControl.addTo(this);
this._controls.maptoolControl = new BoreholeControl().addTo(this);
this._controls.boreholePopup = new BoreholePopup({ parentDiv: 'gba-borehole-control-parent-id' });
this._controls.boreholePopup.addTo(this);
}
public async addLayer(layer) {
let id = util.stamp(layer);
if (this._layers[id]) {
return this;
}
this._layers[id] = layer;
//layer._mapToAdd = this;
layer.index = id;
//if (layer.beforeAdd) {
// layer.beforeAdd(this);
//}
//this.whenReady(layer._layerAdd, layer);
await layer._layerAdd(this);
this.emit("change");
return this;
}
public removeLayer(layer) {
let id = util.stamp(layer);
if (!this._layers[id]) { return this; }
//if (this._loaded) {
// layer.onRemove(this);
//}
layer.onRemove(this);
this.emit("change");
//if (layer.getAttribution && this.attributionControl) {
// this.attributionControl.removeAttribution(layer.getAttribution());
//}
//if (layer.getEvents) {
// this.off(layer.getEvents(), layer);
//}
delete this._layers[id];
//if (this._loaded) {
// this.emit('layerremove', { layer: layer });
// layer.emit('remove');
//}
layer._map = layer._mapToAdd = null;
return this;
}
public hasLayer(layer) {
return !!layer && (util.stamp(layer) in this._layers);
}
public getCenter() { // (Boolean) -> LatLng
return this.target;
}
}
export { Map };