diff --git a/examples/source_file_gpx_3d.html b/examples/source_file_gpx_3d.html index 2fed0f16f6..576bc0e1cf 100644 --- a/examples/source_file_gpx_3d.html +++ b/examples/source_file_gpx_3d.html @@ -44,7 +44,7 @@ var layer = new itowns.ElevationLayer(config.id, config); view.addLayer(layer); } - itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); + // itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // update the waypoint @@ -61,16 +61,19 @@ var waypointGeometry = new itowns.THREE.BoxGeometry(1, 1, 80); var waypointMaterial = new itowns.THREE.MeshBasicMaterial({ color: 0xffffff }); - // Listen for globe full initialisation event + const style = { - stroke: { - color: 'red', - width: 2, - }, - point: { - color: 'white', - } - }; + stroke: { + color: 'red', + width: 2, + base_alti: 500, + }, + point: { + color: 'white', + } + }; + + // Listen for globe full initialisation event view.addEventListener(itowns.GLOBE_VIEW_EVENTS.GLOBE_INITIALIZED, function () { console.info('Globe initialized'); itowns.Fetcher.xml('https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/ULTRA2009.gpx') diff --git a/examples/source_stream_wfs_25d.html b/examples/source_stream_wfs_25d.html index 01b691b686..d29ef5e1ca 100644 --- a/examples/source_stream_wfs_25d.html +++ b/examples/source_stream_wfs_25d.html @@ -262,6 +262,7 @@ style: { fill: { color: colorBuildings, + // base_altitude: altitudeLine, base_altitude: altitudeBuildings, extrusion_height: extrudeBuildings, } diff --git a/src/Converter/Feature2Mesh.js b/src/Converter/Feature2Mesh.js index d42b4c0796..f564c1e164 100644 --- a/src/Converter/Feature2Mesh.js +++ b/src/Converter/Feature2Mesh.js @@ -41,15 +41,6 @@ class FeatureMesh extends THREE.Group { this.#collection.quaternion.copy(collection.quaternion); this.#collection.position.copy(collection.position); - if (collection.crs == 'EPSG:4978') { - normal.copy(collection.center.geodesicNormal); - } else { - normal.set(0, 0, 1); - } - - normal.multiplyScalar(collection.center.z); - this.#collection.position.sub(normal); - this.#collection.scale.copy(collection.scale); this.#collection.updateMatrix(); @@ -208,18 +199,24 @@ function featureToPoint(feature, options) { normal.fromArray(feature.normals, v).multiply(inverseScale); } - coord.copy(context.setLocalCoordinatesFromArray(feature.vertices, v)); + const localCoord = context.setLocalCoordinatesFromArray(feature.vertices, v); userStyle.setContext(context); const { base_altitude, color, radius } = userStyle.point; - coord.z = 0; - if (!pointMaterialSize.includes(radius)) { - pointMaterialSize.push(radius); - } + coord.copy(localCoord) + .applyMatrix4(context.collection.matrixWorld) + .as('EPSG:4326', coord); // populate vertices - base.copy(normal).multiplyScalar(base_altitude).add(coord).toArray(vertices, v); + base.copy(normal) + .multiplyScalar(base_altitude - coord.z).add(localCoord) + .toArray(vertices, v); + toColor(color).multiplyScalar(255).toArray(colors, v); + + if (!pointMaterialSize.includes(radius)) { + pointMaterialSize.push(radius); + } batchIds[j] = id; } featureId++; @@ -250,7 +247,7 @@ function featureToLine(feature, options) { const vertices = new Float32Array(ptsIn.length); const geom = new THREE.BufferGeometry(); - geom.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); + // geom.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); const lineMaterialWidth = []; context.setFeature(feature); @@ -288,18 +285,24 @@ function featureToLine(feature, options) { normal.fromArray(feature.normals, v).multiply(inverseScale); } - coord.copy(context.setLocalCoordinatesFromArray(feature.vertices, v)); + const localCoord = context.setLocalCoordinatesFromArray(feature.vertices, v); userStyle.setContext(context); const { base_altitude, color, width } = userStyle.stroke; - coord.z = 0; + + coord.copy(localCoord) + .applyMatrix4(context.collection.matrixWorld) + .as('EPSG:4326', coord); + + // populate vertices + base.copy(normal) + .multiplyScalar(base_altitude - coord.z).add(localCoord) + .toArray(vertices, v); + + toColor(color).multiplyScalar(255).toArray(colors, v); if (!lineMaterialWidth.includes(width)) { lineMaterialWidth.push(width); } - - // populate geometry buffers - base.copy(normal).multiplyScalar(base_altitude).add(coord).toArray(vertices, v); - toColor(color).multiplyScalar(255).toArray(colors, v); batchIds[j] = id; } featureId++; @@ -309,9 +312,11 @@ function featureToLine(feature, options) { // TODO CREATE material for each feature console.warn('Too many differents stroke.width, only the first one will be used'); } + geom.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); geom.setAttribute('color', new THREE.BufferAttribute(colors, 3, true)); geom.setAttribute('batchId', new THREE.BufferAttribute(batchIds, 1)); geom.setIndex(new THREE.BufferAttribute(indices, 1)); + return new THREE.LineSegments(geom, options.lineMaterial); } @@ -349,17 +354,22 @@ function featureToPolygon(feature, options) { normal.fromArray(feature.normals, i).multiply(inverseScale); } - coord.copy(context.setLocalCoordinatesFromArray(feature.vertices, i)); + const localCoord = context.setLocalCoordinatesFromArray(feature.vertices, i); userStyle.setContext(context); const { base_altitude, color } = userStyle.fill; - coord.z = 0; + + coord.copy(localCoord) + .applyMatrix4(context.collection.matrixWorld) + .as('EPSG:4326', coord); // populate geometry buffers - base.copy(normal).multiplyScalar(base_altitude).add(coord).toArray(vertices, i); - batchIds[b] = id; + base.copy(normal) + .multiplyScalar(base_altitude - coord.z).add(localCoord) + .toArray(vertices, i); + toColor(color).multiplyScalar(255).toArray(colors, i); + batchIds[b] = id; } - featureId++; const geomVertices = vertices.slice(start * 3, end * 3); @@ -378,7 +388,6 @@ function featureToPolygon(feature, options) { geom.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); geom.setAttribute('color', new THREE.BufferAttribute(colors, 3, true)); geom.setAttribute('batchId', new THREE.BufferAttribute(batchIds, 1)); - geom.setIndex(new THREE.BufferAttribute(getIntArrayFromSize(indices, vertices.length / 3), 1)); return new THREE.Mesh(geom, options.polygonMaterial); @@ -434,18 +443,24 @@ function featureToExtrudedPolygon(feature, options) { normal.fromArray(feature.normals, i).multiply(inverseScale); } - coord.copy(context.setLocalCoordinatesFromArray(ptsIn, i)); - + const localCoord = context.setLocalCoordinatesFromArray(ptsIn, i); userStyle.setContext(context); const { base_altitude, extrusion_height, color } = userStyle.fill; - coord.z = 0; + + coord.copy(localCoord) + .applyMatrix4(context.collection.matrixWorld) + .as('EPSG:4326', coord); // populate base geometry buffers - base.copy(normal).multiplyScalar(base_altitude).add(coord).toArray(vertices, i); + base.copy(normal) + .multiplyScalar(base_altitude - coord.z).add(localCoord) + .toArray(vertices, i); batchIds[b] = id; // populate top geometry buffers - extrusion.copy(normal).multiplyScalar(extrusion_height).add(base).toArray(vertices, t); + extrusion.copy(normal) + .multiplyScalar(extrusion_height).add(base) + .toArray(vertices, t); batchIds[b + totalVertices] = id; // coloring base and top mesh diff --git a/src/Core/Feature.js b/src/Core/Feature.js index 197572b859..5d6b82ad3f 100644 --- a/src/Core/Feature.js +++ b/src/Core/Feature.js @@ -370,9 +370,11 @@ export class FeatureCollection extends THREE.Object3D { }; } else { this.extent = options.buildExtent ? defaultExtent(options.forcedExtentCrs || this.crs) : undefined; - this.#setLocalSystem = (center) => { + this.#setLocalSystem = /* center.crs == FC crs */ (center) => { // set local system center + // console.log(center); center.as('EPSG:4326', this.center); + // console.log(this.center); if (this.crs == 'EPSG:4978') { // align Z axe to geodesic normal. diff --git a/src/Core/Style.js b/src/Core/Style.js index d6dfb94240..4ca2290b04 100644 --- a/src/Core/Style.js +++ b/src/Core/Style.js @@ -17,7 +17,7 @@ const inv255 = 1 / 255; const canvas = (typeof document !== 'undefined') ? document.createElement('canvas') : {}; function baseAltitudeDefault(properties, ctx) { - return ctx?.coordinates?.z || ctx?.collection?.center?.z || 0; + return ctx?.coordinates?.z || 0; } export function readExpression(property, ctx) { diff --git a/src/Layer/FeatureGeometryLayer.js b/src/Layer/FeatureGeometryLayer.js index 21713db058..effe0d93ba 100644 --- a/src/Layer/FeatureGeometryLayer.js +++ b/src/Layer/FeatureGeometryLayer.js @@ -51,6 +51,7 @@ class FeatureGeometryLayer extends GeometryLayer { batchId: options.batchId, }); super(id, options.object3d || new Group(), options); + this.isFeatureGeometryLayer = true; this.accurate = options.accurate ?? true; this.buildExtent = !this.accurate; diff --git a/src/Layer/GeometryLayer.js b/src/Layer/GeometryLayer.js index 6217431f4a..eac023c517 100644 --- a/src/Layer/GeometryLayer.js +++ b/src/Layer/GeometryLayer.js @@ -60,7 +60,6 @@ class GeometryLayer extends Layer { // Remove this part when Object.assign(this, config) will be removed from Layer Constructor const visible = config.visible; delete config.visible; - super(id, config); this.isGeometryLayer = true; diff --git a/test/unit/featuregeometrylayererror.js b/test/unit/featuregeometrylayererror.js index d69037f4ba..ecfcc6ff36 100644 --- a/test/unit/featuregeometrylayererror.js +++ b/test/unit/featuregeometrylayererror.js @@ -68,11 +68,11 @@ files.forEach((geojson, i) => { layerProj4.whenReady .then(() => { tile.visible = true; - return layerProj4.update(context, layerProj4, tile) - .then(() => { - assert.equal(layerProj4.object3d.children.length, 1); - done(); - }); + return layerProj4.update(context, layerProj4, tile); + }) + .then(() => { + assert.equal(layerProj4.object3d.children.length, 1); + done(); }).catch(done); }); @@ -80,12 +80,11 @@ files.forEach((geojson, i) => { layerNoProj4.whenReady .then(() => { tile.visible = true; - context.layer = layerNoProj4; - return layerNoProj4.update(context, layerNoProj4, tile) - .then(() => { - assert.equal(layerNoProj4.object3d.children.length, 1); - done(); - }); + return layerNoProj4.update(context, layerNoProj4, tile); + }) + .then(() => { + assert.equal(layerNoProj4.object3d.children.length, 1); + done(); }).catch(done); }); @@ -116,7 +115,7 @@ files.forEach((geojson, i) => { error /= (array.length / 3); - assert.ok(error < max_error); + assert.ok(error < max_error, `error (${error}) sup. to ${max_error}`); done(); }).catch(done); }); diff --git a/test/unit/style.js b/test/unit/style.js index 5a0dd312cc..5f932f8fb3 100644 --- a/test/unit/style.js +++ b/test/unit/style.js @@ -1,5 +1,5 @@ -import Style from 'Core/Style'; import { FEATURE_TYPES } from 'Core/Feature'; +import Style from 'Core/Style'; import assert from 'assert'; import Fetcher from 'Provider/Fetcher'; import { TextureLoader } from 'three';