- new DemLayer.js and DemBlock.js classes for BaseLayer

- MobileDialog.js and BasemapControl.js controls for selecting esir baselayers
- npm updates
- browser.js: new function for testing if browser is IE
- Modifications in BoxLayer.js (for scaling and setting visibility)
- modifications in main.js_ for showing projected and unprojected data
This commit is contained in:
Arno Kaimbacher 2021-01-18 11:51:07 +01:00
parent 7c50b75099
commit 50daeebd7e
17 changed files with 1446 additions and 341 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -55,7 +55,7 @@
</a> </a>
</div> </div>
<ul class="menu main-navigation nine columns"> <ul class="menu main-navigation nine columns">
<li><a href="#home">Home</a></li> <li><a id="menu-map-icon" href="#map">Map</a></li>
</ul> </ul>
</div> </div>
</nav> </nav>

679
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
.gba_basemap_img {
width: 80px;
height: 80px;
-moz-border-radius: 1px;
-webkit-border-radius: 1px;
border-radius: 1px;
-webkit-box-shadow: 0 0 0 6px white, 0 0 0 7px black;
-moz-box-shadow: 0 0 0 6px white, 0 0 0 7px black;
box-shadow: 0 0 0 6px white, 0 0 0 7px black;
}
.gba_basemap_option {
color: black;
text-decoration: none;
font-size: .8em;
text-align: center;
display: inline-block;
margin: 10px 15px 10px 15px;
}
.gba_basemap_option label {
display: block;
margin-top: 5px;
}

View File

@ -0,0 +1,112 @@
import { Control } from "./Control";
import { MobileDialog } from "./MobileDialog";
import * as dom from '../core/domUtil';
import * as util from '../core/utilities';
import * as domEvent from '../core/domEvent';
import './BasemapControl.css';
export class BasemapControl extends MobileDialog {
defaultTitle = '3DViewer';
constructor(title, options) {
super(title, options);
util.setOptions(this, options);
// for (var i in baseLayers) {
// this._addLayer(baseLayers[i], i);
// }
}
onAdd(map) {
super.onAdd(map);
let basemaps = this.basemaps = map.basemaps;
this._initBasemapHtml(basemaps.services);
}
// onAdd(map) {
// this._mainMap = map;
// let basemaps = this.basemaps = map.basemaps;
// let className = "gba-basemap-control";
// let container;
// let toggleable = false;
// if (this.options.parentDiv) {
// container = this._container = document.getElementById(this.options.parentDiv);
// dom.addClass(container, className);
// toggleable = false;
// } else {
// container = this._container = dom.createDom("div", { "class": className });
// toggleable = true;
// }
// domEvent.on(container, 'click', domEvent.stopPropagation);
// this._initBasemapHtml(basemaps.services);
// if (!this.options.parentDiv) {
// return container;
// }
// }
_initBasemapHtml(basemapServices) {
for (let i = 0; i < basemapServices.length; i++) {
let basemap = basemapServices[i];
if (basemap.type === 'MapServer') {
//code += "<a href='#' data-name='" + basemap.name + "' class='fm_basemap_option' >"
// + "<img src='images/basemap/" + basemap.image + "' class='fm_basemap_image' />"
// + "<label>" + basemap.title + "</label>";
//+ "</a>";
var btnLink = dom.createDom('a', {
'class': 'gba_basemap_option'
}, this.popupcontent);
btnLink.dataset.name = basemap.name;
let image = dom.createDom('img', {
'class': 'gba_basemap_img',
}, btnLink);
//image.setAttribute('src', "images/basemap/" + basemap.image);
let imagePath = "images/";
image.setAttribute('src', imagePath + "basemap/" + basemap.image);
dom.createDom('label', { innerHTML: basemap.title }, btnLink);
domEvent.on(btnLink, 'click', function (e) {
e.preventDefault();
let name = e.currentTarget.getAttribute('data-name');
this.setBasemap(name);
// this.hide();
return false;
}, this);
}
}
}
setBasemap(name) {
for (let i = 0; i < this.basemaps.services.length; i++) {
if (this.basemaps.services[i].name === name) {
let basemap = this.basemaps.services[i];
if (this._map.currentBasemap) {
//this.map.removeLayer(this.map.currentBasemap);
this._map.currentBasemap.changeImage(i);
}
//var curentBaseMap = this.map.currentBasemap = new esri.layers.ArcGISTiledMapServiceLayer(getBasemapUrl(basemaps.services[i]), {
// id: 'basemap'
//});
//this.map.addLayer(currentBasemap);
return true;
}
}
}
}

View File

@ -63,7 +63,7 @@ export class Coordinates extends Control {
let x = (xClickedOnCanvas / width) * 2 - 1; let x = (xClickedOnCanvas / width) * 2 - 1;
let y = -(yClickedonCanvas / height) * 2 + 1; let y = -(yClickedonCanvas / height) * 2 + 1;
let mouse = new Vector3(x, y); let mouse = new Vector3(x, y, 1);
mouse.unproject(this.options.camera); mouse.unproject(this.options.camera);
// vector.sub(this.options.camera.position); // vector.sub(this.options.camera.position);
// vector.normalize(); // vector.normalize();
@ -75,6 +75,7 @@ export class Coordinates extends Control {
let koordx = this._dec2sex(point84.x, 'X'); let koordx = this._dec2sex(point84.x, 'X');
let koordy = this._dec2sex(point84.y, 'y'); let koordy = this._dec2sex(point84.y, 'y');
this._container.innerHTML = "LON: " + koordx + ", " + "LAT: " + koordy; this._container.innerHTML = "LON: " + koordx + ", " + "LAT: " + koordy;
// this._container.innerHTML = "x: " + mouse.x + ", " + "y: " + mouse.y;
} }
_getOffset(element) { _getOffset(element) {

View File

@ -0,0 +1,155 @@
.popup_close {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH3AgBFSI5w7714wAAAYlJREFUSMfd1c9KFWEYBvCfJz15NI8RoRnpLohuILyMll1CG0taibhqERkJQWFBixbZpkSwlRs3kdfhBYgaBHU4h8bNGwzTfDNzIgh8YWBmeL7n/TPP8w7/MUb+BbaVeD+NO+g0IG9hEVeaVtPFGjK8wIUa/KPAvsVsHfk0VuNAhh420E7gl/Eth39TlWQsV02GX7kkzzBeGMtDnOawv/GbqdF28A79kkM/8CSSjGAJxyW4DPsxidJoR5uDksM/8TgqP0qQf8bluu/QwetEJ4PcfZF8B1ebKmkSLxNJyp4/YWZYo3VDpt9zRMWrjw+Y+1s3X8dBRYJD3K5zYSpGcRfzNV3ew8SwlbfwoEKKRXU9LfikNpZwkiAvS9LDenRdG8sV5Fsh4V6ik+dVY29jJbdbiuQfcQ1TIeFBopNXIfM/4mLIsox8uyDFbhCV+WQPl1JdLOB9YdY7CRNNxmLr57BfQraVP6sbMesMuzX2H4/dleErbjVV0QLuN3ToREj65rBeGB0CO+bcxhlxQrBXIUNRlQAAAABJRU5ErkJggg==')/*icons/close.png*/
no-repeat;
}
/* anything but phone */
@media all and (min-width: 768px) {
.touch .popup_close {
width: 20px;
height: 20px;
/*margin: 5px;*/
background-size: 20px 20px;
float: right;
cursor: pointer;
z-index: 800;
}
.touch .fm_overlay {
top: 10em;
left: 30%;
max-width: 480px;
min-width: 300px;
/*max-height: 90%;*/
max-height: 500px;
overflow: auto;
}
.touch .popupcontent {
width: 100%;
}
}
/* only phone - bigger buttons */
@media all and (max-width: 767px) {
.touch .popup_close {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH3AcXFyot5RvgagAAAbdJREFUaN7t2DFOAkEUxvE/6AFMUBMoIDExHsMDqJVgZ+KJKIyFBSjGxCN4DbUSC6XRys5GZDXYMAkh7rLz5s0smPmSLXnDj2Hhm4WYmJiYlFSAG2DTw+wS0AZ2fSOqQB8YA09ATXF2GbiczB4CeyEQY2VMGbiYmT0E9kMgtDB/IbxgahkIV0wWQhWTByHF5EGY68sFY4OwxdggpjEHEsit5ULmegDW5/zEnglnfwAbtpA68CxcsJ+yM2WgK5w5Ag6lXy9NjCui6XrD14EXB0x1ERAm28Cr8I3cA+fC134Dx9p/ii47I7kSzZ0oCuMVEQoTBGHS8IQJivCFKQShjUmAVtEnxgYwWHaE6U7XDpCBpD9pR9JibbpZMERX8WYvBKONKATjCzFbNJcaEQQTCuEVUwJOHar4u8MRoLIIO2Fqh8bhzBnRUepOhWE0ERqYRymmLVzwBzjJmLsDvAln3wFrtpDW5JP1UQClrfkKWJHsig3GtsXaYnpShEkzB0ZaxfMeAXqTe9Y5WZgEOPJ4nlFDZGFcEfMw6ohpzEgZkYbxhpjGfCojZjHeESZbnp8BrBITExPzr/MLneElMzKD908AAAAASUVORK5CYII=')/*mobile_icons/close.png*/
no-repeat;
width: 25px;
height: 25px;
background-size: 25px 25px;
float: right;
cursor: pointer;
z-index: 800;
}
.touch .fm_overlay {
bottom: 4em;
left: 20px;
right: 20px;
max-height: 70%;
overflow-y: auto;
}
/*.touch .fm_basemap_list{ max-height: 80%; overflow-y: auto;}*/
}
.popup .fm_overlay {
position: fixed;
width: 300px;
left: 50%;
margin-left: -150px;
top: 50%;
margin-top: -150px;
/* display: none; */
z-index: 9999;
padding: 10px;
background-color: #ffffff;
border: solid gray;
border-width: 1px 2px 2px;
border-radius: 3px;
}
.touch .popup .fm_overlay {
/* display: none; */
position: absolute;
background-color: white;
z-index: 9999;
padding: 10px;
border-radius: 1px;
box-shadow: 0 0 0 10px rgba(34, 34, 34, .6);
}
.popup .fm_overlay.show {
opacity: 1;
transition: opacity 1000ms;
}
.popup .fm_overlay.hide {
opacity: 0;
transition: opacity 1000ms;
}
.popupbar {
background: dimgray;
color: white;
padding-left: 4px;
height: 20px;
}
.touch .popupbar {
background: dimgray;
color: white;
padding-left: 4px;
height: 25px;
}
.touch .popup_close {
float: right;
cursor: pointer;
z-index: 800;
}
.popup_close {
color: rgb(220, 220, 220);
border: 1px solid darkgray;
border-radius: 4px;
font-size: 16px;
font-weight: bold;
width: 16px;
height: 16px;
text-align: center;
float: right;
cursor: pointer;
background-size: 16px 16px;
}
.fm_overlay {
background-color: white;
padding: 2px 5px 2px;
max-height: 500px;
overflow: auto;
font-size: 14px;
}
.pageinfo {
font-size: small;
}
.pageinfo h1 {
background-color: gray;
color: white;
font-size: small;
font-weight: normal;
margin-top: 5px;
margin-bottom: 3px;
padding: 1px;
padding-left: 6px;
}
.license {
font-size: xx-small;
}
.star {
padding: 5px;
text-align: left;
}

View File

@ -0,0 +1,118 @@
import { Control } from "./Control";
import * as dom from '../core/domUtil';
import * as domEvent from '../core/domEvent';
import './MobileDialog.css';
export class MobileDialog extends Control {
defaultTitle = '3DViewer';
declaredClass = "MobileDialog";
defaultOptions = {};
constructor(title, options) {
super(options);
this.title = title ? title : this.defaultTitle;
this.options = options || this.defaultOptions;
}
onAdd(map) {
this.map = map;
let className = "gba-basemap-control";
let container;
let toggleable = false;
if (this.options.position) {
container = this._container = dom.createDom("div", { "class": className });
toggleable = true;
} else {
container = this._container = this.map.container
dom.addClass(container, className);
toggleable = false;
}
this.domNode = dom.createDom("div", { class: "popup" }, container);
this.dialogDiv = dom.createDom("div", {
//class: "fm_basemap_list fm_overlay",
//class: "fm_about fm_overlay",
class: this.options.klass + " fm_overlay hide"
}, this.domNode);
//popupbar
this.popupbar = dom.createDom("div", { 'class': "popupbar" }, this.dialogDiv);
this.popuptitle = dom.createDom("b", { 'class': "popuptitle" }, this.popupbar);
let popup_close = dom.createDom("div", { 'class': "popup_close" }, this.popupbar);
this.popuptitle.innerHTML = this.title;
//popupcontent
this.popupcontent = dom.createDom("div", { 'class': "fm_handle" }, this.dialogDiv);
//additional info div
this.pageinfo = dom.createDom("div", {
'class': "pageinfo"
}, this.dialogDiv);
domEvent.on(popup_close, 'click', domEvent.preventDefault);
domEvent.on(popup_close, 'click', domEvent.stopPropagation);
domEvent.on(popup_close, 'click', this.hide, this);
if (this.options.position) {
return container;
}
}
hide(e) {
this.dialogDiv.classList.add('hide');
this.dialogDiv.classList.remove('show');
}
show() {
// let isHelp = html === undefined ? true : false;
// if (html === undefined) {
// html = this._help();
// }
// if (html instanceof HTMLElement) {
// this.popupcontent.innerHTML = "";
// this.popupcontent.appendChild(html);
// }
// else {
// this.popupcontent.innerHTML = html;
// }
// this.domNode.getElementsByClassName("popuptitle")[0].innerHTML = title || this.title;
// if (!isHelp) {
// //document.getElementById("pageinfo").style.display = "none";
// this.pageinfo.style.display = "none";
// }
// else {
// //document.getElementById("pageinfo").style.display = "block";
// this.pageinfo.style.display = "block";
// }
this.dialogDiv.classList.add('show');
this.dialogDiv.classList.remove('hide');
}
_help() {
let html = "";
//var imagePath = $UrlHelper.resolve('~') + "content/img/";
let imagePath = "content/img/";
let list = '<ul><li id="leftMouse"><img src=' + imagePath + 'leftMouse.png> Rotate 3D Model</li>' +
'<li id="middleMouse"><img src=' + imagePath + 'middleMouse.png> Zoom 3D Model</li>' +
'<li id="rightMouse"><img src=' + imagePath + 'rightMouse.png> Pan 3D Model</li></ul>';
html += list;
return html;
}
}

View File

@ -25,6 +25,14 @@ class Map extends OrbitControls {
} }
this._layers = {}; this._layers = {};
this.initControls(); this.initControls();
this.basemaps = {
"currentVersion": 10.01,
"services": [
{ "name": "esri:topograhy", "type": "MapServer", 'image': 'background_esri_world_topography.png', 'title': 'ESRI Topograhy' },
{ "name": "esri:imagery", "type": "MapServer", 'image': 'background_esri_world_imagery.png', 'title': 'ESRI Imagery' },
]
};
} }
get layers() { get layers() {

View File

@ -15,3 +15,6 @@ export var mobile = typeof orientation !== 'undefined' || userAgentContains('mob
function userAgentContains(str) { function userAgentContains(str) {
return navigator.userAgent.toLowerCase().indexOf(str) >= 0; return navigator.userAgent.toLowerCase().indexOf(str) >= 0;
} }
// @property ie: Boolean; `true` for all Internet Explorer versions (not Edge).
export var ie = 'ActiveXObject' in window;

View File

@ -5,15 +5,28 @@ import { Layer } from './Layer'
class BoxLayer extends Layer { class BoxLayer extends Layer {
constructor(size) { constructor(params) {
super(); super();
this.geometry = new BoxGeometry(size.width, size.height, size.depth); this.visible = true;
this.name = params.name;
this.color = params.color;
this.geometry = new BoxGeometry(params.width, params.height, params.depth);
this.material = new MeshBasicMaterial({ this.material = new MeshBasicMaterial({
color: 800080 color: this.color
}); });
this.materials = [];
this.materials.push(this.material);
this.mesh = new Mesh(this.geometry, this.material); this.mesh = new Mesh(this.geometry, this.material);
this.mesh.position.x = 4282010;
this.mesh.position.y = 2302070;
this.mesh.position.z = -13616.3;
}
setVisible(visible) {
this.visible = visible;
this.mesh.visible = visible;
this.emit('visibility-change');
} }
onAdd(map) { onAdd(map) {
@ -30,6 +43,19 @@ class BoxLayer extends Layer {
getMesh() { getMesh() {
return this.mesh; return this.mesh;
} }
scaleZ(z) {
this.mesh.scale.z = z;
//this.objectGroup.scale.z = z;
}
setWireframeMode(wireframe) {
this.materials.forEach(function (mat) {
//if (m.w) return;
//m.mat.wireframe = wireframe;
mat.wireframe = wireframe;
});
}
} }
export { BoxLayer }; export { BoxLayer };

208
src/js/layer/DemBlock.js Normal file
View File

@ -0,0 +1,208 @@
import { BufferGeometry } from 'three/src/core/BufferGeometry';
import { BufferAttribute, Float32BufferAttribute, Uint16BufferAttribute } from 'three/src/core/BufferAttribute';
import { Mesh } from 'three/src/objects/Mesh';
// import { PlaneBufferGeometry } from 'three/src/geometries/PlaneBufferGeometry';
export class DemBlock {
constructor(params) {
//properties
for (var k in params) {
this[k] = params[k];
}
this.aObjs = [];
//eventuell wieder löschen:
this.mIndex = 0;
this.materialsArray = [];
}
build(layer) {
let xPixel = this.width;
let widthSegments = xPixel - 1; //this.width = xPixel
let yPixel = this.height;
let heightSegments = yPixel - 1;
//appSettings.Options.exportMode = true;
// let PlaneGeometry = (appSettings.Options.exportMode) ? THREE.PlaneGeometry : THREE.PlaneBufferGeometry;
//var geom = layer.mainGeometry = new PlaneGeometry(this.plane.width, this.plane.height, widthSegments, heightSegments);
let geom = layer.mainGeometry = this.buildPlaneBufferGeometry(this.plane.width, this.plane.height, widthSegments, heightSegments);// new THREE.PlaneBufferGeometry(this.plane.width, this.plane.height, 11, 7);
// let geom = layer.mainGeometry = new PlaneBufferGeometry( 10, 5, 20, 20 );
//let geom = layer.mainGeometry = planeGeometry.toNonIndexed();
this.layer.features = geom.attributes.position.array;
this.layer.idx = geom.getIndex() !== null ? geom.getIndex().array : null;
var dem_data = this.dem_values;
////// Filling of the DEM plane
//var vertices = geom.attributes.position.array;
//for (var i = 0, j = 0, l = vertices.length; i < l; i++, j += 3) {
// // x
// //vertices[i] = defaultVertices[i] + (rand(-opts.variance.x, opts.variance.x));
// // y
// //vertices[i + 1] =
// //z
// vertices[j + 2] = dem_data[i];
//}
let i, j, l;
let exportMode = false;
if (exportMode == true) { //PlaneGeometry
if (dem_data.length > 0) {
for (i = 0, l = geom.vertices.length; i < l; i++) {
geom.vertices[i].z = dem_data[i];
}
}
else {
for (i = 0, l = geom.vertices.length; i < l; i++) {
geom.vertices[i].z = layer.materialParameter[0].bottomZ;
}
}
} else { //Plane PlaneBufferGeometry
var vertices = geom.attributes.position.array;
if (dem_data.length > 0) {
for (i = 0, j = 0, l = vertices.length; i < l; i++, j += 3) {
//z
var hoehenwert = !isNaN(dem_data[i]) ? dem_data[i] : 5;
vertices[j + 2] = hoehenwert;//dem_data[i];
}
}
else {
for (i = 0, j = 0, l = vertices.length; i < l; i++, j += 3) {
//z
vertices[j + 2] = layer.materialParameter[0].bottomZ; //Math.random() * 0.1;//layer.materialParameter[0].bottomZ;
}
}
// var bufferAttribute = layer.mainGeometry.getAttribute('position');
// bufferAttribute.setDynamic(true);
// layer.positions = bufferAttribute.clone().array;
// //defaultVertices = planeGeometry.attributes.position.clone().array;
}
// Calculate normals
//if (layer.shading) {
// //geom.computeFaceNormals();obsolete
// geom.computeVertexNormals();
//}
geom.computeBoundingBox();//for building border geometry
//var material = new THREE.MeshPhongMaterial({ color: 0x223322, wireframe: true });
//var mesh = new THREE.Mesh(geom, material);
//var wireframe_material = new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: true, wireframe_linewidth: 10 });
//var materials = [layer.materials[this.mIndex].mat, wireframe_material];
//var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, materials);
var mesh = layer.mainMesh = new Mesh(geom, layer.material); //layer.materials[this.mIndex].mat);
//mesh.name = "Oberkante";
//mesh.matrixAutoUpdate = true;
//var egh = new THREE.EdgesHelper(mesh, 0x00ffff);
//egh.material.linewidth = 2;
//layer.addObject(egh);
if (this.plane.offsetX != 0) mesh.position.x = this.plane.offsetX;
if (this.plane.offsetY != 0) mesh.position.y = this.plane.offsetY;
// mesh.position.z = -13616.3;
mesh.userData.layerId = layer.index;
this.obj = mesh;
layer.addObject(mesh);
//layer.mainMesh = mesh;
}
buildPlaneBufferGeometry(width, height, widthSegments, heightSegments) {
let geometry = new BufferGeometry();
//geometry.dynamic = true;
let width_half = width / 2;
let height_half = height / 2;
let gridX = widthSegments || 1;
var gridY = heightSegments || 1;
let gridX1 = gridX + 1;
let gridY1 = gridY + 1;
let segment_width = width / gridX;
let segment_height = height / gridY;
//var vertices = this.layer.positions = new Float32Array(gridX1 * gridY1 * 3);
let vertices = new Float32Array(gridX1 * gridY1 * 3);
let normals = new Float32Array(gridX1 * gridY1 * 3);
let uvs = new Float32Array(gridX1 * gridY1 * 2);
let offset = 0;
let offset2 = 0;
for (let iy = 0; iy < gridY1; iy++) {
let y = iy * segment_height - height_half;
for (let ix = 0; ix < gridX1; ix++) {
let x = ix * segment_width - width_half;
vertices[offset] = x;
vertices[offset + 1] = -y;
vertices[offset + 2] = 0; //this.layer.materialParameter[0].bottomZ;
normals[offset + 2] = 1;
uvs[offset2] = ix / gridX;
uvs[offset2 + 1] = 1 - (iy / gridY);
offset += 3;
offset2 += 2;
}
}
let position = new Float32BufferAttribute(vertices, 3);//.setDynamic(true);
position.needsUpdate = true;
geometry.setAttribute('position', position);
offset = 0;
//var indices = this.layer.indices = new Uint16Array(gridX * gridY * 6);
let indices = new Uint16Array(gridX * gridY * 6);
for (let iy = 0; iy < gridY; iy++) {
for (let ix = 0; ix < gridX; ix++) {
let a = ix + gridX1 * iy;
let b = ix + gridX1 * (iy + 1);
let c = (ix + 1) + gridX1 * (iy + 1);
let d = (ix + 1) + gridX1 * iy;
indices[offset] = a;
indices[offset + 1] = b;
indices[offset + 2] = d;
indices[offset + 3] = b;
indices[offset + 4] = c;
indices[offset + 5] = d;
offset += 6;
}
}
//geometry.attributes['index'] = { array: indices, itemSize: 1 };
//geometry.setIndex(new THREE.BufferAttribute(indices, 1).setDynamic(true));
//geometry.addAttribute('index', new THREE.BufferAttribute(indices, 1));
let index = new BufferAttribute(indices, 1);//setDynamic(true);
geometry.setIndex(index);
geometry.setAttribute('normal', new BufferAttribute(normals, 3));
geometry.setAttribute('uv', new BufferAttribute(uvs, 2));
//geometry.attributes['normal'] = { array: normals, itemSize: 3 };
//geometry.attributes['uv'] = { array: uvs, itemSize: 2 };
return geometry;
}
}

336
src/js/layer/DemLayer.js Normal file
View File

@ -0,0 +1,336 @@
import { Group } from 'three/src/objects/Group';
// import { BufferGeometry } from 'three/src/core/BufferGeometry';
// import { Float32BufferAttribute, Uint16BufferAttribute } from 'three/src/core/BufferAttribute';
// import { MeshStandardMaterial } from 'three/src/materials/MeshStandardMaterial';
// import { Mesh } from 'three/src/objects/Mesh';
import { Layer } from './Layer';
import { DemBlock } from './DemBlock';
import { MeshStandardMaterial } from 'three/src/materials/MeshStandardMaterial';
import { MeshLambertMaterial } from 'three/src/materials/MeshLambertMaterial';
import { DoubleSide, FlatShading, LinearFilter } from 'three/src/constants';
import * as browser from '../core/browser';
import { Texture } from 'three/src/textures/Texture';
import { TextureLoader } from 'three/src/loaders/TextureLoader';
export class DemLayer extends Layer {
images = [{
"width": 1154,
"url": "https://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer/export",
"height": 907,
"bboxSR": 3034
}, {
"width": 1154,
"url": "https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/export",
"height": 907,
"bboxSR": 3034
}
];
constructor(params) {
super();
//this.features = [];
this.visible = true;
this.opacity = 1;
this.material;
this.materialParameter = [];
this.materials = [];
for (var k in params) {
this[k] = params[k];
}
this.objectGroup = new Group();
this.queryableObjects = [];
this.borderVisible = false;
this.blocks = [];
// this.material = new MeshStandardMaterial({
// color: 16382457,
// metalness: 0.1,
// roughness: 0.75,
// flatShading: true,
// side: DoubleSide
// });
// this.materialsArray.push(this.material);
// this.initMaterials();
}
async initMaterials() {
if (this.materialParameter.length === 0) return;
// this.xLocalPlane = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 50);
// //this.addObject(this.xLocalPlane, false);
// this.yLocalPlane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 39);
let sum_opacity = 0;
this.material;
for (let i = 0, l = this.materialParameter.length; i < l; i++) {
let m = this.materialParameter[i];
let opt = {};
//if (m.ds && !Gba3D.isIE) opt.side = THREE.DoubleSide;
if (m.ds && !browser.ie) opt.side = DoubleSide;
if (m.flat) opt.shading = FlatShading;
//m.i = 1;
if (m.i !== undefined) {
let image = this.images[m.i];
if (image.texture === undefined) {
if (image.src !== undefined) {
image.texture = THREE.ImageUtils._loadTexture(image.src);
}
else {
// image.texture = this._loadTextureData(image.data);
let data = await this.requestImage(image.url, image);
// image.texture = await new TextureLoader().load(data.href);
image.texture = await this.loadTexture(data.href);
}
}
opt.map = image.texture;
}
if (m.o !== undefined && m.o < 1) {
opt.opacity = m.o;
opt.transparent = true;
}
if (m.t) opt.transparent = true;
if (m.w) opt.wireframe = true;
//opt.wireframe = true;
// // Clipping setup:
// opt.clippingPlanes = [this.xLocalPlane, this.yLocalPlane];
// opt.clipIntersection = false;
// opt.clipShadows = true;
let MaterialType = { MeshLambert: 0, MeshPhong: 1, LineBasic: 2, Sprite: 3, Unknown: -1 };
if (m.materialtypee === MaterialType.MeshLambert) {
//if (m.color !== undefined) opt.color = opt.ambient = m.color;
if (m.color !== undefined) opt.color = m.color;
//opt.skinning = true;
this.material = new MeshLambertMaterial(opt);
}
// else if (m.materialtype === MaterialType.MeshPhong) {
// if (m.color !== undefined) opt.color = opt.ambient = m.color;
// mat = new THREE.MeshPhongMaterial(opt);
// }
// else if (m.materialtype === MaterialType.LineBasic) {
// opt.color = m.color;
// mat = new THREE.LineBasicMaterial(opt);
// }
else {
if (m.color !== undefined) opt.color = m.color;
this.material = new MeshStandardMaterial(opt);
}
m.mat = this.material;
//if (m.side !== undefined) {
// m.
//}
this.materials.push(this.material);
sum_opacity += this.material.opacity;
}
// layer opacity is the average opacity of materials
this.opacity = sum_opacity / this.materials.length;
}
scaleZ(z) {
// this.mainMesh.scale.z = z;
this.objectGroup.scale.z = z;
}
setVisible(visible) {
this.visible = visible;
this.objectGroup.visible = visible;
// this.mainMesh.visible = visible;
//Q3D.application.queryObjNeedsUpdate = true;
this.emit('visibility-change');
}
addBlock(params, clipped = false) {
let BlockClass = clipped ? ClippedDEMBlock : DemBlock;
var block = new BlockClass(params);
block.layer = this;
this.blocks.push(block);
return block;
}
setWireframeMode(wireframe) {
this.materials.forEach(function (mat) {
//if (m.w) return;
//m.mat.wireframe = wireframe;
mat.wireframe = wireframe;
});
}
async changeImage(i) {
//this.mainMesh.material.map = THREE.ImageUtils.loadTexture(src);
let image = this.images[i];
if (image.texture === undefined) {
// image.texture = this._loadTextureData(image.data);
//image.texture = await this.loadTextureData(image.data);
let data = await this.requestImage(image.url, image);
// image.texture = new TextureLoader().load(data.href);
image.texture = await this.loadTexture(data.href);
}
//configure the material now that we have all of the data
this.mainMesh.material.map = image.texture;
this.mainMesh.material.needsUpdate = true;
if (this.visible === false) {
this.setVisible(true);
}
this._map.update();
}
//helper function to load in the texture
async loadTexture(texturePath) {
const textureLoader = new TextureLoader();
return new Promise((resolve, reject) => {
textureLoader.load(
texturePath,
(texture) => resolve(texture),
undefined,
err => reject(err)
);
});
}
async onAdd(map) {
//this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;
await this.initMaterials();
this.build(this.getScene());
map.update();
this.emit('add');
}
build(app_scene) {
//var opt = Gba3D.Options;
this.blocks.forEach(function (block) {
block.build(this);
//// build sides, bottom and frame
////if (block.sides) {
//// material
//var opacity = this.materials[block.mIndex].o;
//if (opacity === undefined) {
// opacity = 1;
//}
//var sidecolor = this.materials[block.mIndex].side.color;
//var mat = new THREE.MeshLambertMaterial({
// color: sidecolor, //opt.side.color,
// ambient: sidecolor,//opt.side.color,
// opacity: opacity,
// transparent: (opacity < 1),
// side: THREE.DoubleSide //neu dazu
//});
//this.materials.push({ type: Gba3D.MaterialType.MeshLambert, m: mat });
//if (block.bottomData) {
// //block.extrudePlane(this, mat, opt.side.bottomZ);
// block.extrudePlane(this, mat, opt.side.bottomZ);
//}
//else {
// //var sidecolor = this.materials[block.mIndex].side.color;
// var bottomZ = this.materials[block.mIndex].side.bottomZ;
// block.extrudeBottomPlane(this, mat, bottomZ);
//}
//this.sideVisible = true;
////}
}, this);
if (app_scene) {
app_scene.add(this.objectGroup);
}
}
addObject(object, queryable) {
if (queryable === undefined) {
queryable = this.q;
}
this.objectGroup.add(object);
if (queryable) {
this._addQueryableObject(object);
}
}
_addQueryableObject(object) {
this.queryableObjects.push(object);
//for (var i = 0, l = object.children.length; i < l; i++) {
// this._addQueryableObject(object.children[i]);
//}
}
removeObject(object, queryable) {
if (queryable === undefined) {
queryable = this.q;
}
this.objectGroup.remove(object);
if (queryable) {
var index = this.queryableObjects.indexOf(object);
index !== -1 && this.queryableObjects.splice(index, 1);
}
}
async requestImage(url, imageParameter) {
let params = {
"width": imageParameter.width,
"height": imageParameter.height,
"bboxSR": imageParameter.bboxSR,
"bbox": "3955850,2183600,4527300,2502700",
"format": "png",
"f": "pjson"
};
let query = Object.keys(params)
.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
.join('&');
url = url + '?' + query;
const response = await fetch(url);
if (response.ok) {
return response.json();
} else {
throw new Error("HTTP error, status = " + response.status);
}
}
async loadTextureData(imageData) {
let texture;
let elem = document.createElement('img');
return new Promise((resolve, reject) => {
elem.onload = () => {
console.log('image completely read');
// resolve(elem);
texture = new Texture(elem);
texture.minFilter = LinearFilter;
texture.needsUpdate = true;
resolve(texture);
}
elem.onerror = reject;
elem.src = imageData;
});
}
_loadTextureData(imageData) {
let texture;
let image = document.createElement('img');
image.src = imageData;
image.onload = () => {
console.log('file completely read');
texture.needsUpdate = true;
};
// image.src = imageData;
texture = new Texture(image);
texture.minFilter = LinearFilter;
return texture;
}
}

View File

@ -2,7 +2,7 @@
import { BufferGeometry } from 'three/src/core/BufferGeometry'; import { BufferGeometry } from 'three/src/core/BufferGeometry';
import { Float32BufferAttribute, Uint16BufferAttribute } from 'three/src/core/BufferAttribute'; import { Float32BufferAttribute, Uint16BufferAttribute } from 'three/src/core/BufferAttribute';
import { MeshStandardMaterial } from 'three/src/materials/MeshStandardMaterial'; import { MeshStandardMaterial } from 'three/src/materials/MeshStandardMaterial';
import { DoubleSide } from 'three/src/constants' import { DoubleSide } from 'three/src/constants';
import { Mesh } from 'three/src/objects/Mesh'; import { Mesh } from 'three/src/objects/Mesh';
import { Layer } from './Layer'; import { Layer } from './Layer';
import { BitStream } from '../lib/bitstream'; import { BitStream } from '../lib/bitstream';

View File

@ -96,6 +96,7 @@ class OrbitControls extends EventEmitter {
// Limits to how far you can dolly in and out // Limits to how far you can dolly in and out
// this.minDistance = 0; // this.minDistance = 0;
// this.maxDistance = Infinity; // this.maxDistance = Infinity;
this.minDistance = size*0.75; this.minDistance = size*0.75;
this.maxDistance = size*15; this.maxDistance = size*15;
@ -397,8 +398,10 @@ class OrbitControls extends EventEmitter {
reset() { reset() {
state = STATE.NONE; state = STATE.NONE;
this.target.copy(this.target0);//0 0 0 this.target.copy(this.target0);//0 0 0
this.object.position.copy(this.position0); this.object.position.copy(this.position0);
// this.object.position.set(0, 0, 180); // this.object.position.set(0, 0, 180);
this.update(); this.update();
} }

View File

@ -5,16 +5,22 @@ import { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera';
import { Scene } from 'three/src/scenes/Scene'; import { Scene } from 'three/src/scenes/Scene';
import { Vector3 } from 'three/src/math/Vector3'; import { Vector3 } from 'three/src/math/Vector3';
import { TinLayer } from './layer/TinLayer'; import { TinLayer } from './layer/TinLayer';
import { DemLayer } from './layer/DemLayer';
import { Map } from './core/Map'; import { Map } from './core/Map';
import * as domEvent from './core/domEvent'; import * as domEvent from './core/domEvent';
import { Coordinates } from './controls/Coordinates'; import { Coordinates } from './controls/Coordinates';
import { NortArrow } from './controls/NorthArrow'; import { NortArrow } from './controls/NorthArrow';
import { LayerControl } from './controls/LayerControl'; import { LayerControl } from './controls/LayerControl';
import { MobileDialog } from './controls/MobileDialog';
import { BasemapControl } from './controls/BasemapControl';
import { SliderControl } from './controls/SliderControl'; import { SliderControl } from './controls/SliderControl';
import { Mesh } from 'three/src/objects/Mesh'; import { Mesh } from 'three/src/objects/Mesh';
import { SphereGeometry } from 'three/src/geometries/SphereGeometry'; import { SphereGeometry } from 'three/src/geometries/SphereGeometry';
import { MeshLambertMaterial } from 'three/src/materials/MeshLambertMaterial'; import { MeshLambertMaterial } from 'three/src/materials/MeshLambertMaterial';
import * as util from './core/utilities'; import * as util from './core/utilities';
import * as browser from './core/browser';
import * as domUtil from './core/domUtil';
import { BoxLayer } from './layer/BoxLayer';
import '../css/page.css'; /* style loader will import it */ import '../css/page.css'; /* style loader will import it */
@ -49,18 +55,30 @@ class Application {
this.navigation = document.getElementsByClassName('navigation')[0]; this.navigation = document.getElementsByClassName('navigation')[0];
// this.addEventListeners(); // this.addEventListeners();
this.mapIcon = document.querySelector('#menu-map-icon');
this.createScene(); this.createScene();
this.addEventListeners(); this.addEventListeners();
} }
createScene() { createScene() {
let opt = { r: 200, c: 0x38eeff, o: 0.8 }; var dirNode = document.getElementsByTagName("body")[0];
if (browser.touch == true) {
//dirNode.setAttribute("dir", "ltr");
domUtil.addClass(dirNode, "touch");
} else {
domUtil.addClass(dirNode, "notouch");
}
// let opt = { r: 200, c: 0x38eeff, o: 0.8 };
var opt = { r: 5, c: 0xffff00, o: 1 };
this.queryMarker = new Mesh(new SphereGeometry(opt.r), this.queryMarker = new Mesh(new SphereGeometry(opt.r),
new MeshLambertMaterial({ color: opt.c, opacity: opt.o, transparent: false })); new MeshLambertMaterial({ color: opt.c, opacity: opt.o, transparent: (opt.o < 1) }));
this.queryMarker.visible = true; this.queryMarker.visible = true;
this.queryMarker.position.set(4282010, 2302070, -13616.3); // this.queryMarker.position.set(4282010, 2302070, -13616.3);
/* Renderer */ /* Renderer */
// var bgcolor = 0xfdfdfd; // var bgcolor = 0xfdfdfd;
let bgcolor = 0xfdfdfd; let bgcolor = 0xfdfdfd;
@ -97,15 +115,17 @@ class Application {
this.camera = new PerspectiveCamera(30, this.width / this.height, 100, 100000); this.camera = new PerspectiveCamera(30, this.width / this.height, 100, 100000);
const dirLight = new DirectionalLight(0xffffff, 1); // const dirLight = new DirectionalLight(0xffffff, 1);
dirLight.position.set(585000 + 10000, 6135000 + 10000, -500 + 5000); // dirLight.position.set(585000 + 10000, 6135000 + 10000, -500 + 5000);
this.camera.add(dirLight); // this.camera.add(dirLight);
let x = { min: 3955850, max: 4527300, avg: 4282010 }; let x = { min: 3955850, max: 4527300, avg: 4282010 };
let y = { min: 2183600, max: 2502700, avg: 2302070 }; let y = { min: 2183600, max: 2502700, avg: 2302070 };
let z = { min: -60066, max: 3574.94, avg: -13616.3 }; let z = { min: -60066, max: 3574.94, avg: -13616.3 };
const center = new Vector3(x.avg, y.avg, 1000); const center = new Vector3 ( (x.min + x.max) / 2, (y.min + y.max) / 2, z.avg );
// const center = new Vector3(x.avg, y.avg, z.avg);
const size = Math.max(x.max - x.min, y.max - y.min, z.max - z.min); const size = Math.max(x.max - x.min, y.max - y.min, z.max - z.min);
const camDirection = new Vector3(-0.5, -Math.SQRT1_2, 0.5); const camDirection = new Vector3(-0.5, -Math.SQRT1_2, 0.5);
const camOffset = camDirection.multiplyScalar(size * 2); const camOffset = camDirection.multiplyScalar(size * 2);
this.camera.position.copy(center); this.camera.position.copy(center);
@ -115,15 +135,32 @@ class Application {
this.camera.far = size * 25; this.camera.far = size * 25;
this.camera.updateProjectionMatrix(); this.camera.updateProjectionMatrix();
/* Camera */
// // const center = new Vector3();
// var angle = 45;
// var aspect = this.width / this.height;
// var near = 0.1; //This is the distance at which the camera will start rendering scene objects
// var far = 2000; //Anything beyond this distance will not be rendered
// this.camera = new PerspectiveCamera(angle, aspect, near, far);
// this.camera.position.set(0, -0.1, 150);
// this.camera.lookAt(new Vector3(0, 0, 0));
// create map // create map
this.map = new Map(size, center, this.camera, this.scene, this.renderer.domElement, this.container); this.map = new Map(size, center, this.camera, this.scene, this.renderer.domElement, this.container);
// this.map.minDistance = size*0.75; // this.map.minDistance = size*0.75;
// this.map.maxDistance = size*15; // this.map.maxDistance = size*15;
// let boxLayer = new BoxLayer({
// width: 10000, height: 10000, depth: 10000, name: 'test-box', color: 800080
// });
// this.map.addLayer(boxLayer);
//add map controls: //add map controls:
if (util.hasTouch() == false) { if (util.hasTouch() == false) {
let coordinates = new Coordinates({ camera: this.camera, crs: "EPSG:3034" }).addTo(this.map); let coordinates = new Coordinates({ camera: this.camera, crs: "EPSG:3034" }).addTo(this.map);
// coordinates.addListener('onPoint', (vector) => { // coordinates.addListener('onPoint', (args) => {
// let vector = args[0];
// this.queryMarker.position.set(vector.x, vector.y, vector.z); // this.queryMarker.position.set(vector.x, vector.y, vector.z);
// // this.queryMarker.updateMatrixWorld(); // // this.queryMarker.updateMatrixWorld();
// this.animate(); // this.animate();
@ -131,6 +168,35 @@ class Application {
} }
this.northArrow = new NortArrow({ headLength: 1, headWidth: 1 }).addTo(this.map); this.northArrow = new NortArrow({ headLength: 1, headWidth: 1 }).addTo(this.map);
// this.dialog = new MobileDialog("Help", { klass: "fm_about", parentDiv: 'basemap-control-parent' }).addTo(this.map);
let demLayer = new DemLayer({
q: 0, shading: true, type: 'dem', name: 'DEM Layer', color: 16382457,
"materialParameter": [{
"i": 0,
"materialtypee": 0,
"ds": 1,
"bottomZ": 3000, //-18.70583629319634
}]
});
demLayer.addBlock({
"width": 226,
"plane": {
"width": x.max - x.min, //100.0,
// "offsetX": 0,
// "offsetY": 0,
// "offsetX" : x.avg,
// "offsetY" : y.avg,
"offsetX" : center.x,
"offsetY" : center.y,
"height": y.max - y.min, //78.59618717504333
},
"dem_values": [],
"height": 178
});
this.map.addLayer(demLayer);
this.map.currentBasemap = demLayer;
let dxf134Layer = new TinLayer({ let dxf134Layer = new TinLayer({
geomId: 134, q: true, type: "3dface", name: "South Alpine Superunit", description: "test", color: "907A5C" geomId: 134, q: true, type: "3dface", name: "South Alpine Superunit", description: "test", color: "907A5C"
}); });
@ -166,6 +232,10 @@ class Application {
parentDiv: 'layer-control-parent-id' parentDiv: 'layer-control-parent-id'
}).addTo(this.map); }).addTo(this.map);
this.basemapControl = new BasemapControl('Baselayer', {
parentDiv: 'basemap-control-parent'
}).addTo(this.map);
//slider for scaling z value //slider for scaling z value
this.slider = new SliderControl({ layers: this.map.layers }).addTo(this.map); this.slider = new SliderControl({ layers: this.map.layers }).addTo(this.map);
@ -260,6 +330,10 @@ class Application {
addEventListeners() { addEventListeners() {
domEvent.on(this.mapIcon, 'click', () => {
this.basemapControl.show();
}, this);
domEvent.on(window, 'resize', this.onWindowResize, this); domEvent.on(window, 'resize', this.onWindowResize, this);
domEvent.on(window, 'keydown', this.keydown, this); domEvent.on(window, 'keydown', this.keydown, this);