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 #9551 Ability to move GLTF 3D models by given x/y #9779

Merged
merged 2 commits into from
Dec 1, 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
2 changes: 2 additions & 0 deletions docs/developer-guide/vector-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ The `symbolizer` could be of following `kinds`:
| `opacity` | color opacity | | x |
| `msHeightReference` | reference to compute the distance of the point geometry, one of **none**, **ground** or **clamp** | | x |
| `msHeight` | height of the point, the original geometry is applied if undefined | | x |
| `msTranslateX` | move the model on the x axis with a value in meters (west negative value, east positive value) | | x |
| `msTranslateY` | move the model on the y axis with a value in meters (south negative value, north positive value) | | x |
| `msLeaderLineColor` | color of the leading line connecting the point to the terrain | | x |
| `msLeaderLineOpacity` | opacity of the leading line connecting the point to the terrain | | x |
| `msLeaderLineWidth` | width of the leading line connecting the point to the terrain | | x |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,8 @@ describe('VisualStyleEditor', () => {
'styleeditor.color',
'styleeditor.heightReferenceFromGround',
'styleeditor.height',
'styleeditor.msTranslateX',
'styleeditor.msTranslateY',
'styleeditor.leaderLineColor',
'styleeditor.leaderLineWidth'
]);
Expand Down
21 changes: 19 additions & 2 deletions web/client/components/styleeditor/config/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ const lineGeometryTransformation = () => ({
})
});

const heightPoint3dOptions = ({ isDisabled }) => ({
const heightPoint3dOptions = ({ isDisabled, enableTranslation }) => ({
msHeightReference: property.msHeightReference({
label: "styleeditor.heightReferenceFromGround",
isDisabled
Expand All @@ -148,6 +148,22 @@ const heightPoint3dOptions = ({ isDisabled }) => ({
placeholderId: 'styleeditor.pointHeight',
isDisabled: (value, properties) => isDisabled() || properties?.msHeightReference === 'clamp'
}),
...(enableTranslation && {
msTranslateX: property.number({
key: 'msTranslateX',
label: 'styleeditor.msTranslateX',
uom: 'm',
fallbackValue: 0,
isDisabled
}),
msTranslateY: property.number({
key: 'msTranslateY',
label: 'styleeditor.msTranslateY',
uom: 'm',
fallbackValue: 0,
isDisabled
})
}),
msLeaderLineColor: property.color({
key: 'msLeaderLineColor',
opacityKey: 'msLeaderLineOpacity',
Expand Down Expand Up @@ -556,7 +572,8 @@ const getBlocks = ({
isDisabled: () => !enable3dStyleOptions
}),
...heightPoint3dOptions({
isDisabled: () => !enable3dStyleOptions
isDisabled: () => !enable3dStyleOptions,
enableTranslation: true
}),
...(!shouldHideVectorStyleOptions && pointGeometryTransformation({}))
},
Expand Down
3 changes: 1 addition & 2 deletions web/client/components/styleeditor/config/property.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,7 @@ const property = {
},
getValue: (value) => {
return {
[key]: value,
...(value === 'clamp' && { msHeight: undefined })
[key]: value
};
},
isDisabled
Expand Down
4 changes: 3 additions & 1 deletion web/client/translations/data.de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -2630,7 +2630,9 @@
"offset": "Offset",
"propertyValue": "Eigenschaftswert",
"colorPropertyInfoMessage": "Der Farbeigenschaftswert muss eine hexadezimale Zeichenfolge sein. Beispiel: \"#ffffff\"",
"pointCloudSizeInfo": "Der Punktwolkenradius wird nur angewendet, wenn die Dämpfungsoptionen deaktiviert sind. Die Dämpfungsoption hat Vorrang vor dieser Eigenschaft."
"pointCloudSizeInfo": "Der Punktwolkenradius wird nur angewendet, wenn die Dämpfungsoptionen deaktiviert sind. Die Dämpfungsoption hat Vorrang vor dieser Eigenschaft.",
"msTranslateX": "Versatz x",
"msTranslateY": "Versatz y"
},
"playback": {
"settings": {
Expand Down
4 changes: 3 additions & 1 deletion web/client/translations/data.en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -2602,7 +2602,9 @@
"offset": "Offset",
"propertyValue": "Property value",
"colorPropertyInfoMessage": "The color property value must be an hexadecimal string. Example: \"#ffffff\"",
"pointCloudSizeInfo": "The point cloud radius is applied only when the attenuation options is disabled. The attenuation option takes precedence over this property."
"pointCloudSizeInfo": "The point cloud radius is applied only when the attenuation options is disabled. The attenuation option takes precedence over this property.",
"msTranslateX": "Translate x",
"msTranslateY": "Translate y"
},
"playback": {
"settings": {
Expand Down
4 changes: 3 additions & 1 deletion web/client/translations/data.es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -2592,7 +2592,9 @@
"offset": "Desplazamiento",
"propertyValue": "Valor de la propiedad",
"colorPropertyInfoMessage": "El valor de la propiedad de color debe ser una cadena hexadecimal. Ejemplo: \"#ffffff\"",
"pointCloudSizeInfo": "El radio de la nube de puntos se aplica sólo cuando las opciones de atenuación están deshabilitadas. La opción de atenuación tiene prioridad sobre esta propiedad."
"pointCloudSizeInfo": "El radio de la nube de puntos se aplica sólo cuando las opciones de atenuación están deshabilitadas. La opción de atenuación tiene prioridad sobre esta propiedad.",
"msTranslateX": "Desplazamiento x",
"msTranslateY": "Desplazamiento y"
},
"playback": {
"settings": {
Expand Down
4 changes: 3 additions & 1 deletion web/client/translations/data.fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -2592,7 +2592,9 @@
"offset": "Décalage",
"propertyValue": "Valeur de la propriété",
"colorPropertyInfoMessage": "La valeur de la propriété de couleur doit être une chaîne hexadécimale. Exemple : \"#ffffff\"",
"pointCloudSizeInfo": "Le rayon du nuage de points est appliqué uniquement lorsque les options d'atténuation sont désactivées. L'option d'atténuation est prioritaire sur cette propriété."
"pointCloudSizeInfo": "Le rayon du nuage de points est appliqué uniquement lorsque les options d'atténuation sont désactivées. L'option d'atténuation est prioritaire sur cette propriété.",
"msTranslateX": "Décalage x",
"msTranslateY": "Décalage y"
},
"playback": {
"settings": {
Expand Down
4 changes: 3 additions & 1 deletion web/client/translations/data.it-IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -2593,7 +2593,9 @@
"offset": "Offset",
"propertyValue": "Valore della proprietà",
"colorPropertyInfoMessage": "Il valore della proprietà colore deve essere una stringa esadecimale. Esempio: \"#ffffff\"",
"pointCloudSizeInfo": "Il raggio della nuvola di punti viene applicato solo quando le opzioni di attenuazione sono disabilitate. L'opzione di attenuazione ha la precedenza su questa proprietà."
"pointCloudSizeInfo": "Il raggio della nuvola di punti viene applicato solo quando le opzioni di attenuazione sono disabilitate. L'opzione di attenuazione ha la precedenza su questa proprietà.",
"msTranslateX": "Offset x",
"msTranslateY": "Offset y"
},
"playback": {
"settings": {
Expand Down
62 changes: 54 additions & 8 deletions web/client/utils/styleparser/CesiumStyleParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,19 @@ function createLeaderLineCanvas({
return canvas;
}

const translatePoint = (cartesian, symbolizer) => {
const { msTranslateX, msTranslateY } = symbolizer || {};
const x = getNumberAttributeValue(msTranslateX);
const y = getNumberAttributeValue(msTranslateY);
return (x || y)
? Cesium.Matrix4.multiplyByPoint(
Cesium.Transforms.eastNorthUpToFixedFrame(cartesian),
new Cesium.Cartesian3(x || 0, y || 0, 0),
new Cesium.Cartesian3()
)
: cartesian;
};

function addLeaderLineGraphic({
map,
symbolizer,
Expand All @@ -172,7 +185,9 @@ function addLeaderLineGraphic({
'msLeaderLineWidth',
'msHeight',
'msHeightReference',
'offset'
'offset',
'msTranslateX',
'msTranslateY'
];
const shouldNotUpdateLeaderLine = entity._msSymbolizer
&& !isGlobalOpacityChanged(entity, globalOpacity)
Expand All @@ -195,15 +210,39 @@ function addLeaderLineGraphic({
}

const cartographic = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now()));
const originalCartographic = Cesium.Cartographic.fromCartesian(entity._msPosition);
const heightReference = symbolizer.msHeightReference;
return (
(
symbolizer?.msHeight !== entity._msSymbolizer?.msHeight
|| symbolizer?.msHeightReference !== entity._msSymbolizer?.msHeightReference
|| symbolizer?.msTranslateX !== entity._msSymbolizer?.msTranslateX
|| symbolizer?.msTranslateY !== entity._msSymbolizer?.msTranslateY
|| !entity.polyline
)
? getLeaderLinePositions({ map, cartographic, heightReference, sampleTerrain })
.then((positions) => new Cesium.PolylineGraphics({ positions }))
? getLeaderLinePositions({
map,
// we create a cartographic that include:
// the original longitude and latitude
// and the modified height
// later we can translate the coordinate connected to the entity
cartographic: new Cesium.Cartographic(
originalCartographic.longitude,
originalCartographic.latitude,
cartographic.height),
heightReference,
sampleTerrain
})
.then((positions) => {
return new Cesium.PolylineGraphics({
positions: [
// original position
positions[0],
// apply translation to the coordinate connected to the entity
translatePoint(positions[1], symbolizer)
]
});
})
: Promise.resolve(entity.polyline)
)
.then((polyline) => {
Expand Down Expand Up @@ -244,13 +283,14 @@ function modifyPointHeight({ entity, symbolizer }) {
const height = getNumberAttributeValue(symbolizer.msHeight);

if (height === null) {
entity.position.setValue(entity._msPosition);
entity.position.setValue(translatePoint(entity._msPosition, symbolizer));
return;
}

const cartographic = Cesium.Cartographic.fromCartesian(entity._msPosition);
cartographic.height = height;
entity.position.setValue(Cesium.Cartographic.toCartesian(cartographic));
const cartesian = Cesium.Cartographic.toCartesian(cartographic);
entity.position.setValue(translatePoint(cartesian, symbolizer));
return;
}

Expand Down Expand Up @@ -742,9 +782,15 @@ function getStyleFuncFromRules({
: getGeometryFunction({ msGeometry: { name: 'centerPoint' }, ...symbolizer });
if (geometryFunction) {
const additionalEntity = entity.entityCollection.add({
position: entity.position
? entity.position.getValue(Cesium.JulianDate.now()).clone()
: new Cesium.Cartesian3(0, 0, 0)
// use the stored position when available
position: entity._msPosition
? entity._msPosition
// if a point geometry we can access de initial value
: entity.position
? entity.position.getValue(Cesium.JulianDate.now()).clone()
// for other computed point we use the geometry function
// so we can apply the origin cartesian
: new Cesium.Cartesian3(0, 0, 0)
});
additionalEntity._msStoredCoordinates = entity._msStoredCoordinates;
additionalEntity._msAdditional = true;
Expand Down
71 changes: 71 additions & 0 deletions web/client/utils/styleparser/__tests__/CesiumStyleParser-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -811,5 +811,76 @@ describe('CesiumStyleParser', () => {
});
});
});
it('should write a style function with model symbolizer with x/y translation', (done) => {

const translateDelta = 100;
const style = {
name: '',
rules: [
{
filter: undefined,
name: '',
symbolizers: [
{
kind: 'Model',
model: '/path/to/file.glb',
scale: 1,
heading: 0,
roll: 0,
pitch: 0,
color: '#ffffff',
opacity: 0.5,
msHeightReference: 'relative',
height: 10,
msTranslateX: translateDelta,
msTranslateY: translateDelta,
msLeaderLineColor: '#ff0000',
msLeaderLineOpacity: 0.5,
msLeaderLineWidth: 2
}
]
}
]
};

const lng = 7;
const lat = 41;

parser.writeStyle(style)
.then((styleFunc) => {
Cesium.GeoJsonDataSource.load({
type: 'Feature',
properties: {},
geometry: {
type: 'Point',
coordinates: [lng, lat]
}
}).then((dataSource) => {
const entities = dataSource?.entities?.values;
return styleFunc({ entities })
.then(() => {
const expectedTranslatedDistance = Math.round(Math.sqrt(2) * translateDelta);
const distancePosition = Math.round(Cesium.Cartesian3.distance(
entities[0]._msPosition,
entities[0].position.getValue(Cesium.JulianDate.now())
));
expect(distancePosition).toBe(expectedTranslatedDistance);
const leaderLinePositions = entities[0].polyline.positions.getValue();
const distanceLeaderLineA = Math.round(Cesium.Cartesian3.distance(
entities[0]._msPosition,
leaderLinePositions[0]
));
expect(distanceLeaderLineA).toBe(0);
const distanceLeaderLineB = Math.round(Cesium.Cartesian3.distance(
entities[0]._msPosition,
leaderLinePositions[1]
));
expect(distanceLeaderLineB).toBe(expectedTranslatedDistance);
done();
})
.catch(done);
});
});
});
});
});
Loading