Skip to content

Commit

Permalink
feature(Feature2Mesh): Stylize points mesh.
Browse files Browse the repository at this point in the history
Refactoring Feature and Feature2Mesh to improve software architecture
and add styling points feature.

Software architecture
 * move Style responsibility from Feature to Feature2Mesh,
   because no stylisation must be applied when parsing.
 * add FeatureContext class to encapsulate all properties
   and methods necessary for stylization.
  • Loading branch information
gchoqueux authored and jailln committed Oct 30, 2023
1 parent ebadc9c commit b7538b0
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 284 deletions.
147 changes: 99 additions & 48 deletions examples/source_stream_wfs_25d.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@
// `viewerDiv` will contain iTowns' rendering area (`<canvas>`)
viewerDiv = document.getElementById('viewerDiv');

const centerMap = new itowns.Coordinates('EPSG:3946', 1840839, 5172718, 0);

// Instanciate PlanarView*
view = new itowns.PlanarView(viewerDiv, extent, {
placement: {
coord: new itowns.Coordinates('EPSG:3946', 1840839, 5172718, 0),
coord: centerMap,
heading: 45,
range: 1800,
tilt: 30,
Expand Down Expand Up @@ -104,13 +106,13 @@
var tile;
var linesBus = [];

function altitudeLine(properties, contour) {
function altitudeLine(properties, ctx) {
var result;
var z = 0;
if (contour) {
result = itowns.DEMUtils.getTerrainObjectAt(view.tileLayer, contour, 0, tile);
if (ctx.coordinates) {
result = itowns.DEMUtils.getTerrainObjectAt(view.tileLayer, ctx.coordinates, 0, tile);
if (!result) {
result = itowns.DEMUtils.getTerrainObjectAt(view.tileLayer, contour, 0);
result = itowns.DEMUtils.getTerrainObjectAt(view.tileLayer, ctx.coordinates, 0);
}
if (result) {
tile = [result.tile];
Expand All @@ -121,14 +123,7 @@
}

function acceptFeatureBus(properties) {
if (properties.sens == 'Aller') {
var line = properties.ligne;
if (linesBus.indexOf(line) === -1) {
linesBus.push(line);
return true;
}
}
return false;
return properties.sens === "Aller";
}

lyonTclBusSource = new itowns.WFSSource({
Expand All @@ -147,37 +142,89 @@
format: 'application/json',
});

const colorsLine = new Map();

const colorLine = (properties) => {
const line = properties.ligne;
let color = colorsLine.get(line);
if (color === undefined) {
color = new itowns.THREE.Color(0xffffff * Math.random());
colorsLine.set(line, color);
}
return colorsLine.get(line);
}

var lyonTclBusLayer = new itowns.FeatureGeometryLayer('lyon_tcl_bus', {
filter: acceptFeatureBus,
source: lyonTclBusSource,
zoom: { min: 2 },
zoom: { min: 1 },

style: {
stroke: {
base_altitude: altitudeLine,
color: colorLine,
width: 5,
}
}
});

view.addLayer(lyonTclBusLayer);
const lyonBusStopSource = new itowns.WFSSource({
url: "https://data.grandlyon.com/geoserver/sytral/ows?",
protocol: 'wfs',
version: '2.0.0',
id: 'pool',
typeName: "sytral:tcl_sytral.tclarret",
crs: 'EPSG:3946',
extent,
format: 'application/json',
});

function colorBuildings(properties) {
var lyonBusStopLayer = new itowns.FeatureGeometryLayer('lyon_tcl_bus_stop', {
source: lyonBusStopSource,
zoom: { min: 4 },
style: {
point: {
base_altitude: altitudeLine,
color: 'DarkTurquoise',
radius: 30,
}
}
});

const orange = new itowns.THREE.Color(0xffa400);
const blue = new itowns.THREE.Color(0x47edff);
const black = new itowns.THREE.Color(0x000000);
const red = new itowns.THREE.Color(0xff0000);

function colorBuildings(properties, ctx) {
const distance = ctx.coordinates.planarDistanceTo(centerMap);
if (properties.usage_1 === 'Résidentiel') {
return color.set(0xFDFDFF);
color.set(0xFDFDFF);
} else if (properties.usage_1 === 'Annexe') {
return color.set(0xC6C5B9);
color.set(0xC6C5B9);
} else if (properties.usage_1 === 'Commercial et services') {
return color.set(0x62929E);
color.set(0x62929E);
} else if (properties.usage_1 === 'Religieux') {
return color.set(0x393D3F);
color.set(0x393D3F);
} else if (properties.usage_1 === 'Sportif') {
return color.set(0x546A7B);
color.set(0x546A7B);
} else {
color.set(0x555555);
}

return color.set(0x555555);
if (distance < 300) {
return blue;
} else if (distance < 350){
return black;
} else if (distance < 1000){
return color;
} else if (distance < 1050){
return red;
}
return color.lerp(orange, Math.min(distance / 4000, 1.0));
}


function extrudeBuildings(properties) {
return properties.hauteur;
}
Expand All @@ -186,28 +233,10 @@
return properties.altitude_minimale_sol;
}

meshes = [];
function scaler(/* dt */) {
var i;
var mesh;
if (meshes.length) {
view.notifyChange();
}
for (i = 0; i < meshes.length; i++) {
mesh = meshes[i];
mesh.scale.z = Math.min(
1.0, mesh.scale.z + 0.1);
mesh.updateMatrixWorld(true);
}
meshes = meshes.filter(function filter(m) { return m.scale.z < 1; });
}

function acceptFeature(properties) {
return !!properties.hauteur;
}

view.addFrameRequester(itowns.MAIN_LOOP_EVENTS.BEFORE_RENDER, scaler);

var wfsBuildingSource = new itowns.WFSSource({
url: 'https://wxs.ign.fr/topographie/geoportail/wfs?',
version: '2.0.0',
Expand All @@ -224,12 +253,6 @@
});

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',
Expand Down Expand Up @@ -260,9 +283,29 @@
zoom: { min: 0, max: 20 },
text: {
field: '{toponyme}',
color: 'white',
color: (p) => {
switch (p.importance) {
case 'Quartier de ville':
return 'Cornsilk';
case 'Hameau':
return 'WhiteSmoke';
case 'Chef-lieu de commune':
default:
return 'white';
}
},
transform: 'uppercase',
size: 15,
size: (p) => {
switch (p.importance) {
case 'Quartier de ville':
return 11;
case 'Hameau':
return 13;
case 'Chef-lieu de commune':
default:
return 18;
}
},
haloColor: 'rgba(20,20,20, 0.8)',
haloWidth: 3,
},
Expand Down Expand Up @@ -300,6 +343,14 @@
}
}

// Wait for globe initialization since we are using the elevation
// layer to calculate the base altitude of both feature layers.
// See the function `altitudeLine` above.
view.addEventListener(itowns.GLOBE_VIEW_EVENTS.GLOBE_INITIALIZED, function m() {
view.addLayer(lyonTclBusLayer);
view.addLayer(lyonBusStopLayer);
});

window.addEventListener('mousemove', picking, false);
</script>
</body>
Expand Down
10 changes: 5 additions & 5 deletions examples/vector_tile_3d_mesh_mapbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@
});

// Get buildings ground elevation
function altitudeBuildings(properties, coord) {
if (coord) {
return itowns.DEMUtils.getElevationValueAt(view.tileLayer, coord);
function altitudeBuildings(properties, ctx) {
if (ctx.coordinates) {
return itowns.DEMUtils.getElevationValueAt(view.tileLayer, ctx.coordinates);
}
}

Expand All @@ -116,8 +116,8 @@
style: {
fill: {
// the building with type = roof doesn't have same properties as the others
base_altitude: (p, c) => {
return (altitudeBuildings(p, c) || 0) + (p.min_height || 0);
base_altitude: (p, ctx) => {
return (altitudeBuildings(p, ctx) || 0) + (p.min_height || 0);
},
extrusion_height: (p) => {
return p.height || 0;
Expand Down
Loading

0 comments on commit b7538b0

Please sign in to comment.