Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update style by clearing cache #2130

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions examples/misc_redraw_layer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<html>
<head>
<title>Itowns - Globe + WFS</title>

<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css/example.css">
<link rel="stylesheet" type="text/css" href="css/LoadingScreen.css">

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
</head>
<body>
<div id="viewerDiv"></div>
<div id="description" style="border-radius: 5%;">
<select id="styleBox" onChange="selectStyle()" style="font-size: 15px; background-color: rgba(0,0,0,0.3); border-radius: 5%; width: 175px; height: 25px; color: white; text-align: center;">
<option value='Type'>Stylized by Type</option>
<option value='Surface'>Stylized by Surface</option>
</select>
</div>
<script src="js/GUI/GuiTools.js"></script>
<script src="../dist/itowns.js"></script>
<script src="js/GUI/LoadingScreen.js"></script>
<script src="../dist/debug.js"></script>
<script type="text/javascript">
// Define crs projection that we will use (taken from https://epsg.io/3946, Proj4js section)
itowns.proj4.defs('EPSG:3946', '+proj=lcc +lat_1=45.25 +lat_2=46.75 +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');

// # Simple Globe viewer

// Define initial camera position
// var positionOnGlobe = { longitude: 4.4985, latitude: 46.3417, altitude: 5000 };
var placement = {
coord: new itowns.Coordinates('EPSG:4326', 4.4985, 46.3417),
range: 5000,
}

// `viewerDiv` will contain iTowns' rendering area (`<canvas>`)
var viewerDiv = document.getElementById('viewerDiv');

// Instanciate iTowns GlobeView*
var view = new itowns.GlobeView(viewerDiv, placement);
var menuGlobe = new GuiTools('menuDiv', view);

setupLoadingScreen(viewerDiv, view);

// Add one imagery layer to the scene
// This layer is defined in a json file but it could be defined as a plain js
// object. See Layer* for more info.
itowns.Fetcher.json('./layers/JSONLayers/Ortho.json').then(function _(config) {
config.source = new itowns.WMTSSource(config.source);
var layer = new itowns.ColorLayer('Ortho', config);
view.addLayer(layer).then(function _() {
menuGlobe.addLayerGUI.bind(menuGlobe);
itowns.ColorLayersOrdering.moveLayerToIndex(view, 'Ortho', 0);
});
});

// Add two elevation layers.
// These will deform iTowns globe geometry to represent terrain elevation.
function addElevationLayerFromConfig(config) {
config.source = new itowns.WMTSSource(config.source);
var layer = new itowns.ElevationLayer(config.id, config);
view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe));
}
itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig);
itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig);

// Declare the source for the data on a rural area from the geoportail
var wfsAgriLayer = new itowns.WFSSource({
url: 'https://data.geopf.fr/wfs/ows?',
version: '2.0.0',
typeName: 'RPG.2013:rpg_2013',
crs: 'EPSG:4326',
extent: {
west: 4.3764,
east: 4.6341,
south: 46.2729,
north: 46.3855,
},
ipr: 'IGN',
format: 'application/json',
});

// Define the function that sets the color according to the properties and the choosen style.
const color = function (properties) {
const styleBox = document.getElementById('styleBox');
if (styleBox.value === 'Type') {
if (properties.code_cultu == '28') { return '#FD8A8A'; }
else if (properties.code_cultu == '01') { return '#F1F7B5'; }
else if (properties.code_cultu == '02') { return '#A8D1D1'; }
else if (properties.code_cultu == '03') { return '#9EA1D4'; }
else if (properties.code_cultu == '04') { return '#3CA59D'; }
else if (properties.code_cultu == '05') { return '#5A3D55'; }
else if (properties.code_cultu == '18') { return '#A2DE96'; }
else if (properties.code_cultu == '19') { return '#E79C2A'; }
else { return '#E0E0E0'; }
} else if (styleBox.value === 'Surface') {
let surf = parseFloat(properties.surf_cultu);
if (surf >=0 && surf < 2.84) { return '#f4cdd7'; }
else if (surf >= 2.84 && surf < 6.19) { return '#e5a4b0'; }
else if (surf >= 6.19 && surf < 10.43) { return '#d47c86'; }
else if (surf >= 10.43 && surf < 15.2) { return '#bf545b'; }
else if (surf > 15.2) { return '#a6292f'; }
else { return '#E0E0E0'; }
}
}
const style = {
fill: {
color,
opacity: 0.8
},
stroke: {
color: 'black',
width: 1.0,
},
}

// Create the layer where you specified the starting style
var wfsAgriLayer = new itowns.ColorLayer('wfsAgri', {
transparent: true,
style,
source: wfsAgriLayer,
zoom: { min: 11 },
});
view.addLayer(wfsAgriLayer);

// Function that calls the onChange event in the combobox
function selectStyle() {
view.redrawLayer('wfsAgri');
}

</script>
</body>
</html>
19 changes: 19 additions & 0 deletions src/Core/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,25 @@ class View extends THREE.EventDispatcher {
}
}

/**
* Redraws some imagery layers from the current layer list when the style has been modified.
* @example
* view.redrawLayer(layers);
* @param {string|Array<string>} layerId The identifier or an array of identifier
*/
redrawLayer(layerId) {
if (!layerId.isArray) { layerId = [layerId]; }
layerId.forEach((layerIds) => {
const layer = this.getLayerById(layerIds);
if (layer) {
layer.invalidateCache();
this.notifyChange(layer);
} else {
throw new Error(`${layerIds} doesn't exist`);
}
});
}

/**
* Notifies the scene it needs to be updated due to changes exterior to the
* scene itself (e.g. camera movement).
Expand Down
10 changes: 10 additions & 0 deletions src/Layer/ColorLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ class ColorLayer extends RasterLayer {
update(context, layer, node, parent) {
return updateLayeredMaterialNodeImagery(context, this, node, parent);
}

invalidateCache() {
this.cache.clear();
this.parent.level0Nodes.forEach((node0) => {
node0.traverse((tile) => {
tile.layerUpdateState[this.id] = undefined;
tile.redraw = true;
});
});
}
}

export default ColorLayer;
10 changes: 10 additions & 0 deletions src/Layer/FeatureGeometryLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ class FeatureGeometryLayer extends GeometryLayer {
this.object3d.clear();
}
}

invalidateCache() {
this.cache.clear();
this.parent.level0Nodes.forEach((node0) => {
node0.traverse((tile) => {
tile.layerUpdateState[this.id] = undefined;
tile.redraw = true;
});
});
}
}

export default FeatureGeometryLayer;
8 changes: 8 additions & 0 deletions src/Layer/Layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,14 @@ class Layer extends THREE.EventDispatcher {
delete(clearCache) {
console.warn('Function delete doesn\'t exist for this layer');
}

/**
* Invalidate the cache of this layer.
* Only implemented in {@link ColorLayer} and {@link FeatureGeometryLayer} for the moment.
*/
invalidateCache() {
throw new Error('invalidateCache is not supported yet in this type of layer');
}
}

export default Layer;
Expand Down
4 changes: 4 additions & 0 deletions src/Process/FeatureProcessing.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export default {
return;
}

if (node.redraw) {
node.link[this.id] = [];
}

if (node.layerUpdateState[layer.id] === undefined) {
node.layerUpdateState[layer.id] = new LayerUpdateState();
} else if (!node.layerUpdateState[layer.id].canTryUpdate()) {
Expand Down
12 changes: 8 additions & 4 deletions src/Process/LayeredMaterialNodeProcessing.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,15 @@ export function updateLayeredMaterialNodeImagery(context, layer, node, parent) {
return;
}

if (nodeLayer.level >= extentsDestination[0].zoom) {
// default decision method
node.layerUpdateState[layer.id].noMoreUpdatePossible();
return;
// During the redraw processing, skip the noMoreUpdatePossible state
if (!node.redraw) {
if (nodeLayer.level >= extentsDestination[0].zoom) {
// default decision method
node.layerUpdateState[layer.id].noMoreUpdatePossible();
return;
}
}
node.redraw = false;

// is fetching data from this layer disabled?
if (layer.frozen) {
Expand Down
37 changes: 37 additions & 0 deletions test/unit/colorlayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import assert from 'assert';
import ColorLayer from 'Layer/ColorLayer';
import GlobeView from 'Core/Prefab/GlobeView';
import FileSource from 'Source/FileSource';
import Coordinates from 'Core/Geographic/Coordinates';
import HttpsProxyAgent from 'https-proxy-agent';
import Renderer from './bootstrap';

describe('ColorLayer', function () {
const renderer = new Renderer();
const placement = { coord: new Coordinates('EPSG:4326', 1.5, 43), range: 300000 };
const viewer = new GlobeView(renderer.domElement, placement, { renderer });

const source = new FileSource({
url: 'https://raw.githubusercontent.com/gregoiredavid/france-geojson/master/departements/09-ariege/departement-09-ariege.geojson',
crs: 'EPSG:4326',
format: 'application/json',
networkOptions: process.env.HTTPS_PROXY ? { agent: new HttpsProxyAgent(process.env.HTTPS_PROXY) } : {},
});

const ariege = new ColorLayer('ariege', {
transparent: true,
style: {
fill: { color: 'blue', opacity: 0.8 },
stroke: { color: 'black', width: 1.0 },
},
source,
zoom: { min: 11 },
});
viewer.addLayer(ariege);

it('invalidate cache', function () {
ariege.invalidateCache();
assert.equal(ariege.parent.level0Nodes[0].redraw, true);
assert.equal(ariege.parent.level0Nodes[0].layerUpdateState[ariege.id], undefined);
});
});
7 changes: 6 additions & 1 deletion test/unit/featuregeometrylayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,10 @@ describe('Layer with Feature process', function () {
done();
}).catch(done);
});
});

it('invalidate cache', function () {
ariege.invalidateCache();
assert.equal(ariege.parent.level0Nodes[0].redraw, true);
assert.equal(ariege.parent.level0Nodes[0].layerUpdateState[ariege.id], undefined);
});
});
Loading