Skip to content

Commit

Permalink
feature(Layer): add FeatureGeometryLayer.
Browse files Browse the repository at this point in the history
  • Loading branch information
gchoqueux committed Jun 17, 2021
1 parent f632308 commit 0961787
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 49 deletions.
44 changes: 24 additions & 20 deletions examples/js/plugins/DragNDrop.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,20 @@ var DragNDrop = (function _() {
data = new window.DOMParser().parseFromString(data, 'text/xml');
}

var crs = extension.mode == _GEOMETRY ? _view.referenceCrs : _view.tileLayer.extent.crs;

extension.parser(data, {
in: {
crs: 'EPSG:4326',
},
out: {
crs: (extension.mode == _GEOMETRY ? _view.referenceCrs : _view.tileLayer.extent.crs),
crs: crs,
buildExtent: true,
mergeFeatures: true,
structure: (extension.mode == _GEOMETRY ? '3d' : '2d'),
forcedExtentCrs: crs != 'EPSG:4978' ? crs : 'EPSG:4326',
},
}).then(function _(features) {
var dimensions = features.extent.dimensions();

var source = new itowns.FileSource({
features: features,
crs: 'EPSG:4326',
Expand All @@ -102,29 +103,32 @@ var DragNDrop = (function _() {
source: source,
});
} else if (extension.mode == _GEOMETRY) {
layer = new itowns.GeometryLayer(file.name, new itowns.THREE.Group(), {
update: itowns.FeatureProcessing.update,
convert: itowns.Feature2Mesh.convert({
color: new itowns.THREE.Color(randomColor),
// Set the extrusion according to the size of
// the extent containing the data; this quick
// formula is totally arbitrary.
extrude: dimensions.x * dimensions.y / 1e6,
}),
source: source,
opacity: 0.7,
});
layer = new itowns.FeatureGeometryLayer(
file.name,
{
style: new itowns.Style({
fill: {
color: 'red',
extrusion_height: 200,
},
}),
source: source,
opacity: 0.7,
});
} else {
throw new Error('Mode of file not supported, please add it using DragNDrop.register');
}

_view.addLayer(layer);

// Move the camera to the first vertex
itowns.CameraUtils.animateCameraToLookAtTarget(_view, _view.camera.camera3D, {
coord: new itowns.Coordinates(features.crs, features.features[0].vertices),
range: dimensions.x * dimensions.y * 1e6,
});
var extent = features.extent.clone();
// Transform local extent to data.crs projection.
if (extent.crs == features.crs) {
extent.applyMatrix4(features.matrixWorld);
}

// Move the camera
itowns.CameraUtils.transformCameraToLookAtTarget(_view, _view.camera.camera3D, extent);
});
};

Expand Down
2 changes: 1 addition & 1 deletion examples/js/plugins/FeatureToolTip.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* view.addLayer(wfsLayer);
*
* var fileSource = new itowns.FileSource(...);
* var fileLayer = new itowns.GeometryLayer('id_myFile', { source: fileSource});
* var fileLayer = new itowns.GeometryLayer('id_myFile', new THREE.Group(), { source: fileSource });
* view.addLayer(fileLayer);
*
* FeatureToolTip.addLayer(wfsLayer);
Expand Down
4 changes: 1 addition & 3 deletions examples/source_file_geojson_3d.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,13 @@
itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig);

// Add a geometry layer, which will contain the multipolygon to display
var marne = new itowns.GeometryLayer('Marne', new itowns.THREE.Group(), {
var marne = new itowns.FeatureGeometryLayer('Marne', {
// Use a FileSource to load a single file once
source: new itowns.FileSource({
url: 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/multipolygon.geojson',
crs: 'EPSG:4326',
format: 'application/json',
}),
update: itowns.FeatureProcessing.update,
convert: itowns.Feature2Mesh.convert(),
transparent: true,
opacity: 0.7,
zoom: { min: 10 },
Expand Down
11 changes: 3 additions & 8 deletions examples/source_stream_wfs_25d.html
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,7 @@
format: 'geojson',
});

var lyonTclBusLayer = new itowns.GeometryLayer('lyon_tcl_bus', new itowns.THREE.Group(), {
update: itowns.FeatureProcessing.update,
convert: itowns.Feature2Mesh.convert(),
var lyonTclBusLayer = new itowns.FeatureGeometryLayer('lyon_tcl_bus', {
filter: acceptFeatureBus,
source: lyonTclBusSource,
zoom: { min: 2 },
Expand Down Expand Up @@ -219,17 +217,14 @@
},
});

var wfsBuildingLayer = new itowns.GeometryLayer('wfsBuilding', new itowns.THREE.Group(), {
update: itowns.FeatureProcessing.update,
convert: itowns.Feature2Mesh.convert({
batchId: function (property, featureId) { return featureId; }
}),
var wfsBuildingLayer = new itowns.FeatureGeometryLayer('wfsBuilding', {
onMeshCreated: function scaleZ(mesh) {
mesh.children.forEach(c => {
c.scale.z = 0.01;
meshes.push(c);
})
},
batchId: function (property, featureId) { return featureId; },
filter: acceptFeature,
crs: 'EPSG:3946',
source: wfsBuildingSource,
Expand Down
11 changes: 3 additions & 8 deletions examples/source_stream_wfs_3d.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,8 @@
format: 'geojson',
});

var lyonTclBusLayer = new itowns.GeometryLayer('WFS Bus lines', new itowns.THREE.Group(), {
var lyonTclBusLayer = new itowns.FeatureGeometryLayer('WFS Bus lines',{
name: 'lyon_tcl_bus',
update: itowns.FeatureProcessing.update,
convert: itowns.Feature2Mesh.convert(),
filter: acceptFeatureBus,
source: lyonTclBusSource,
zoom: { min: 9 },
Expand Down Expand Up @@ -183,11 +181,8 @@
},
});

var wfsBuildingLayer = new itowns.GeometryLayer('WFS Building', new itowns.THREE.Group(), {
update: itowns.FeatureProcessing.update,
convert: itowns.Feature2Mesh.convert({
batchId: function (property, featureId) { return featureId; },
}),
var wfsBuildingLayer = new itowns.FeatureGeometryLayer('WFS Building',{
batchId: function (property, featureId) { return featureId; },
onMeshCreated: function scaleZ(mesh) {
mesh.children.forEach(c => {
c.scale.z = 0.01;
Expand Down
4 changes: 1 addition & 3 deletions examples/view_immersive.html
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,7 @@
});

// create geometry layer for the buildings
var wfsBuildingLayer = new itowns.GeometryLayer('Buildings', new itowns.THREE.Group(), {
update: itowns.FeatureProcessing.update,
convert: itowns.Feature2Mesh.convert(),
var wfsBuildingLayer = new itowns.FeatureGeometryLayer('Buildings', {
style: new itowns.Style({
fill: {
base_altitude: altitudeBuildings,
Expand Down
44 changes: 44 additions & 0 deletions src/Layer/FeatureGeometryLayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Group } from 'three';

import GeometryLayer from 'Layer/GeometryLayer';
import FeatureProcessing from 'Process/FeatureProcessing';
import Feature2Mesh from 'Converter/Feature2Mesh';

/**
* `FeatureGeometryLayer` displays geographic vector data (geojson, kml...) in object 3D.
* `FeatureGeometryLayer` is a pre-configured `GeometryLayer` to load and convert vector data.
* In deed, `GeometryLayer` allows customizing data loading (`update` method)
* and their conversion (`convert` method),
*
* @property {boolean} isFeatureGeometryLayer - Used to checkout whether this layer is
* a FeatureGeometryLayer. Default is true. You should not change this, as it is used
* internally for optimisation.
*/
class FeatureGeometryLayer extends GeometryLayer {
/**
* @constructor
* @extends GeometryLayer
*
* @param {string} id - The id of the layer, that should be unique. It is
* not mandatory, but an error will be emitted if this layer is added a
* {@link View} that already has a layer going by that id.
* @param {Object} [config] - Optional configuration, all elements in it
* will be merged as is in the layer.
* @param {function} [options.batchId] - optional function to create batchId attribute.
* It is passed the feature property and the feature index.
* As the batchId is using an unsigned int structure on 32 bits, the batchId could be between 0 and 4,294,967,295.
* @param {THREE.Object3D} [config.object3d=new THREE.Group()] root object3d layer.
*
*/
constructor(id, config = {}) {
config.update = FeatureProcessing.update;
config.convert = Feature2Mesh.convert({
batchId: config.batchId,
},
);
super(id, config.object3d || new Group(), config);
this.isFeatureGeometryLayer = true;
}
}

export default FeatureGeometryLayer;
1 change: 1 addition & 0 deletions src/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export { default as Layer, ImageryLayers } from 'Layer/Layer';
export { default as ColorLayer } from 'Layer/ColorLayer';
export { default as ElevationLayer } from 'Layer/ElevationLayer';
export { default as GeometryLayer } from 'Layer/GeometryLayer';
export { default as FeatureGeometryLayer } from 'Layer/FeatureGeometryLayer';
export { default as PointCloudLayer } from 'Layer/PointCloudLayer';
export { default as PotreeLayer } from 'Layer/PotreeLayer';
export { default as C3DTilesLayer } from 'Layer/C3DTilesLayer';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import * as THREE from 'three';
import assert from 'assert';
import GlobeView from 'Core/Prefab/GlobeView';
import FeatureProcessing from 'Process/FeatureProcessing';
import Feature2Mesh from 'Converter/Feature2Mesh';
import GeometryLayer from 'Layer/GeometryLayer';
import FeatureGeometryLayer from 'Layer/FeatureGeometryLayer';
import FileSource from 'Source/FileSource';
import HttpsProxyAgent from 'https-proxy-agent';
import Extent from 'Core/Geographic/Extent';
Expand All @@ -26,7 +24,7 @@ describe('Layer with Feature process', function () {
networkOptions: process.env.HTTPS_PROXY ? { agent: new HttpsProxyAgent(process.env.HTTPS_PROXY) } : {},
});

const ariege = new GeometryLayer('ariege', new THREE.Group(), {
const ariege = new FeatureGeometryLayer('ariege', {
source,
style: new Style({
fill: {
Expand All @@ -35,8 +33,6 @@ describe('Layer with Feature process', function () {
},
}),
zoom: { min: 7 },
update: FeatureProcessing.update,
convert: Feature2Mesh.convert(),
});

const context = {
Expand Down

0 comments on commit 0961787

Please sign in to comment.