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

Fix #9775 Visibility limits not working in 3D for detached layers #9777

Merged
merged 3 commits into from
Dec 6, 2023
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,6 @@ function VisibilityLimitsForm({
clearMessages();
}, [ dpu, resolutionString ]);

useEffect(() => {
if (isMounted.current && (!isNil(maxResolution) || !isNil(minResolution))) {
setCapabilitiesMessage(maxResolution, minResolution);
setRangeError(maxResolution, minResolution);
}
}, [isMounted]);

return (
<div className="ms-visibility-limits-form">
<div className="ms-visibility-limits-form-title" style={{ display: 'flex', alignItems: 'center' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ describe('VisibilityLimitsForm', () => {
'1 : 37795',
'layerProperties.visibilityLimits.scale'
]);
const message = document.querySelector('.alert-success');
expect(message.textContent).toBe('layerProperties.visibilityLimits.serverValuesUpdate');
});
it('should render maxResolution and minResolution labels as resolution', () => {
const layer = {
Expand Down
52 changes: 41 additions & 11 deletions web/client/components/map/cesium/Layer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ class CesiumLayer extends React.Component {
};

componentDidMount() {
this.createLayer(this.props.type, this.props.options, this.props.position, this.props.map, this.props.securityToken);
if (this.props.options && this.layer && this.getVisibilityOption(this.props)) {
// initial visibility should also take into account the visibility limits
// in particular for detached layers (eg. Vector, WFS, 3D Tiles, ...)
const visibility = this.getVisibilityOption(this.props);
this.createLayer(this.props.type, { ...this.props.options, visibility }, this.props.position, this.props.map, this.props.securityToken);
if (this.props.options && this.layer && visibility) {
this.addLayer(this.props);
this.updateZIndex();
}
Expand Down Expand Up @@ -129,19 +132,46 @@ class CesiumLayer extends React.Component {
}
};

setDetachedLayerVisibility = (visibility, props) => {
// use internal setVisible
// if a detached layers implements setVisible
if (this.layer?.setVisible) {
this.layer.setVisible(visibility);
return;
}
// if visible we will remove the layer and create a new one
if (visibility) {
this.removeLayer();
this.createLayer(props.type, {
...props.options,
visibility
}, props.position, props.map, props.securityToken);
return;
}
// while hidden layers will be completely removed
this.removeLayer();
return;
};

setImageryLayerVisibility = (visibility, props) => {
// this type of layer will be added and removed from the imageryLayers array of Cesium
if (visibility) {
this.addLayer(props);
this.updateZIndex();
return;
}
this.removeLayer();
return;
}

setLayerVisibility = (newProps) => {
const oldVisibility = this.getVisibilityOption(this.props);
const newVisibility = this.getVisibilityOption(newProps);
if (newVisibility !== oldVisibility) {
if (this.layer?.detached && this.layer?.setVisible) {
this.layer.setVisible(newVisibility);
if (!!this.layer?.detached) {
this.setDetachedLayerVisibility(newVisibility, newProps);
} else {
if (newVisibility) {
this.addLayer(newProps);
this.updateZIndex();
} else {
this.removeLayer();
}
this.setImageryLayerVisibility(newVisibility, newProps);
}
newProps.map.scene.requestRender();
}
Expand All @@ -167,7 +197,7 @@ class CesiumLayer extends React.Component {
return false;
}
}
return visibility;
return !!visibility;
};

setLayerOpacity = (opacity) => {
Expand Down
10 changes: 9 additions & 1 deletion web/client/components/map/cesium/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,15 @@ class CesiumMap extends React.Component {
};

getZoomFromHeight = (height) => {
return Math.log2(this.props.zoomToHeight / height) + 1;
let distance = height;
// when camera is tilted we could compute the height as the distance between the camera point of view and the viewed point on the map
allyoucanmap marked this conversation as resolved.
Show resolved Hide resolved
// the viewed point or target is computed as the intersection of an imaginary vector based on the camera direction (ray) and the globe surface
// if the camera is orthogonal to the globe distance should match the height so this computation is still valid
const target = this.map.scene.globe.pick(new Cesium.Ray(this.map.camera.position, this.map.camera.direction), this.map.scene);
if (target) {
distance = Cesium.Cartesian3.distance(target, this.map.camera.position);
}
return Math.log2(this.props.zoomToHeight / distance) + 1;
};

getHeightFromZoom = (zoom) => {
Expand Down
12 changes: 8 additions & 4 deletions web/client/components/map/cesium/__tests__/Layer-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,8 @@ describe('Cesium layer', () => {

let options = {
id: 'overlay-1',
position: { x: 13, y: 43 }
position: { x: 13, y: 43 },
visibility: true
};
// create layers
let layer = ReactDOM.render(
Expand Down Expand Up @@ -616,7 +617,8 @@ describe('Cesium layer', () => {
position: { x: 13, y: 43 },
onClose: () => {
closed = true;
}
},
visibility: true
};
// create layers
let layer = ReactDOM.render(
Expand All @@ -643,7 +645,8 @@ describe('Cesium layer', () => {
document.body.appendChild(element);
let options = {
id: 'overlay-1',
position: { x: 13, y: 43 }
position: { x: 13, y: 43 },
visibility: true
};
// create layers
let layer = ReactDOM.render(
Expand All @@ -659,7 +662,8 @@ describe('Cesium layer', () => {

it('creates a marker layer for cesium map', () => {
let options = {
point: { lng: 13, lat: 43 }
point: { lng: 13, lat: 43 },
visibility: true
};
// create layers
let layer = ReactDOM.render(
Expand Down
2 changes: 1 addition & 1 deletion web/client/components/map/cesium/__tests__/Map-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ describe('CesiumMap', () => {
try {
expect(Math.round(Math.round(center.y * precision) / precision)).toBe(30);
expect(Math.round(Math.round(center.x * precision) / precision)).toBe(20);
expect(zoom).toBe(5);
expect(Math.round(zoom)).toBe(5);
expect(bbox.bounds).toBeTruthy();
expect(bbox.crs).toBeTruthy();
expect(size.height).toBeTruthy();
Expand Down
17 changes: 10 additions & 7 deletions web/client/components/map/cesium/plugins/MarkerLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ import { isEqual } from 'lodash';
*/
Layers.registerType('marker', {
create: (options, map) => {
if (!options.visibility) {
return {
detached: true,
point: undefined,
remove: () => {}
};
}
const style = {
point: {
pixelSize: 5,
Expand All @@ -26,7 +33,7 @@ Layers.registerType('marker', {
...options.style
};
const point = map.entities.add({
position: Cesium.Cartesian3.fromDegrees(options.point.lng, options.point.lat),
position: Cesium.Cartesian3.fromDegrees(options?.point?.lng || 0, options?.point?.lat || 0),
...style
});
return {
Expand All @@ -38,12 +45,8 @@ Layers.registerType('marker', {
};
},
update: function(layer, newOptions, oldOptions, map) {
if (!isEqual(newOptions.point, oldOptions.point)
|| newOptions.visibility !== oldOptions.visibility) {
layer.remove();
return newOptions.visibility
? this.create(newOptions, map)
: null;
if (!isEqual(newOptions.point, oldOptions.point)) {
return this.create(newOptions, map);
}
return null;
}
Expand Down
20 changes: 12 additions & 8 deletions web/client/components/map/cesium/plugins/OverlayLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,19 @@ const cloneOriginalOverlay = (original, options) => {
Layers.registerType('overlay', {
create: (options, map) => {

if (!options.visibility) {
return {
detached: true,
info: undefined,
remove: () => {}
};
}
const original = document.getElementById(options.id);
const cloned = cloneOriginalOverlay(original, options);
// use a div fallback to avoid error if the original element does not exist
const cloned = original ? cloneOriginalOverlay(original, options) : document.createElement('div');

let infoWindow = new InfoWindow(map);
infoWindow.showAt(options.position.y, options.position.x, cloned);
infoWindow.showAt(options?.position?.y || 0, options?.position?.x || 0, cloned);
infoWindow.setVisible(true);
let info = map.scene.primitives.add(infoWindow);

Expand All @@ -183,12 +191,8 @@ Layers.registerType('overlay', {
};
},
update: function(layer, newOptions, oldOptions, map) {
if (!isEqual(newOptions.position, oldOptions.position)
|| newOptions.visibility !== oldOptions.visibility) {
layer.remove();
return newOptions.visibility
? this.create(newOptions, map)
: null;
if (!isEqual(newOptions.position, oldOptions.position)) {
return this.create(newOptions, map);
}
return null;
}
Expand Down
3 changes: 1 addition & 2 deletions web/client/components/map/cesium/plugins/TerrainLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ const createLayer = (config, map) => {
terrainProvider,
remove: () => {
map.terrainProvider = new Cesium.EllipsoidTerrainProvider();
},
setVisible: () => {}
}
};
};

Expand Down
110 changes: 52 additions & 58 deletions web/client/components/map/cesium/plugins/ThreeDTilesLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,73 +129,67 @@ function updateShading(tileSet, options, map) {

Layers.registerType('3dtiles', {
create: (options, map) => {
if (options.visibility && options.url) {

let tileSet;
const resource = new Cesium.Resource({
url: options.url,
proxy: needProxy(options.url) ? new Cesium.DefaultProxy(getProxyUrl()) : undefined
// TODO: axios supports also adding access tokens or credentials (e.g. authkey, Authentication header ...).
// if we want to use internal cesium functionality to retrieve data
// we need to create a utility to set a CesiumResource that applies also this part.
// in addition to this proxy.
});
Cesium.Cesium3DTileset.fromUrl(resource,
{
showCreditsOnScreen: true
}
).then((_tileSet) => {
tileSet = _tileSet;
updateGooglePhotorealistic3DTilesBrandLogo(map, options, tileSet);
map.scene.primitives.add(tileSet);
// assign the original mapstore id of the layer
tileSet.msId = options.id;

ensureReady(tileSet, () => {
updateModelMatrix(tileSet, options);
clip3DTiles(tileSet, options, map);
updateShading(tileSet, options, map);
getStyle(options)
.then((style) => {
if (style) {
tileSet.style = new Cesium.Cesium3DTileStyle(style);
}
});
});
});

if (!options.visibility) {
return {
detached: true,
getTileSet: () => tileSet,
resource,
remove: () => {
if (tileSet) {
updateGooglePhotorealistic3DTilesBrandLogo(map, options, tileSet);
map.scene.primitives.remove(tileSet);
}
},
setVisible: (visible) => {
if (tileSet) {
tileSet.show = !!visible;
}
}
getTileSet: () => undefined,
remove: () => {}
};
}
let tileSet;
const resource = new Cesium.Resource({
url: options.url,
proxy: needProxy(options.url) ? new Cesium.DefaultProxy(getProxyUrl()) : undefined
// TODO: axios supports also adding access tokens or credentials (e.g. authkey, Authentication header ...).
// if we want to use internal cesium functionality to retrieve data
// we need to create a utility to set a CesiumResource that applies also this part.
// in addition to this proxy.
});
let promise = Cesium.Cesium3DTileset.fromUrl(resource,
{
showCreditsOnScreen: true
}
).then((_tileSet) => {
tileSet = _tileSet;
updateGooglePhotorealistic3DTilesBrandLogo(map, options, tileSet);
map.scene.primitives.add(tileSet);
// assign the original mapstore id of the layer
tileSet.msId = options.id;

ensureReady(tileSet, () => {
updateModelMatrix(tileSet, options);
clip3DTiles(tileSet, options, map);
updateShading(tileSet, options, map);
getStyle(options)
.then((style) => {
if (style) {
tileSet.style = new Cesium.Cesium3DTileStyle(style);
}
});
});
});
const removeTileset = () => {
updateGooglePhotorealistic3DTilesBrandLogo(map, options, tileSet);
map.scene.primitives.remove(tileSet);
tileSet = undefined;
};
return {
detached: true,
getTileSet: () => undefined,
remove: () => {},
setVisible: () => {}
getTileSet: () => tileSet,
resource,
remove: () => {
if (tileSet) {
removeTileset();
return;
}
promise.then(() => {
removeTileset();
});
return;
}
};
},
update: function(layer, newOptions, oldOptions, map) {
if (newOptions.visibility && !oldOptions.visibility) {
return this.create(newOptions, map);
}
if (!newOptions.visibility && oldOptions.visibility && layer?.remove) {
layer.remove();
return null;
}
const tileSet = layer?.getTileSet();
if (
(!isEqual(newOptions.clippingPolygon, oldOptions.clippingPolygon)
Expand Down
Loading
Loading