• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geosolutions-it / MapStore2 / 12831531306

17 Jan 2025 03:01PM UTC coverage: 77.182% (+0.07%) from 77.115%
12831531306

Pull #10746

github

web-flow
Merge 501dbaeea into 4e4dabc03
Pull Request #10746: Fix #10739 Changing correctly resolutions limits when switching map CRS

30373 of 47156 branches covered (64.41%)

34 of 43 new or added lines in 2 files covered. (79.07%)

126 existing lines in 15 files now uncovered.

37769 of 48935 relevant lines covered (77.18%)

35.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

29.82
/web/client/components/map/cesium/plugins/ModelLayer.js
1
/*
2
 * Copyright 2024, GeoSolutions Sas.
3
 * All rights reserved.
4
 *
5
 * This source code is licensed under the BSD-style license found in the
6
 * LICENSE file in the root directory of this source tree.
7
 */
8

9
import * as Cesium from 'cesium';
10
import isEqual from 'lodash/isEqual';
11
import Layers from '../../../../utils/cesium/Layers';
12
import { ifcDataToJSON, getIFCModel } from '../../../../api/Model';
13

14
const updatePrimitivesMatrix = (primitives, feature) => {
1✔
15
    const { properties, geometry } = feature;
×
16
    const {
17
        heading,
18
        pitch,
19
        roll,
20
        scale
21
    } = properties || {};
×
22
    const [
23
        longitude,
24
        latitude,
25
        height
26
    ] = geometry?.coordinates || [];
×
27
    for (let i = 0; i < primitives.length; i++) {
×
28
        const primitive = primitives.get(i);
×
29
        const rotationMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
×
30
            new Cesium.Cartesian3(0.0, 0.0, 0.0),
31
            Cesium.Quaternion.fromHeadingPitchRoll(
32
                new Cesium.HeadingPitchRoll(
33
                    Cesium.Math.toRadians(heading || 0),
×
34
                    Cesium.Math.toRadians(pitch || 0),
×
35
                    Cesium.Math.toRadians(roll || 0)
×
36
                )
37
            ),
38
            new Cesium.Cartesian3(scale || 1.0, scale || 1.0, scale || 1.0),
×
39
            new Cesium.Matrix4()
40
        );
41
        // Apply IFC transformation to model matrix
42
        const translationMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
×
43
            Cesium.Cartesian3.fromDegrees(longitude || 0, latitude || 0, height || 0)
×
44
        );
45
        const scaleMatrix = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(scale || 1, scale || 1, scale || 1));
×
46
        primitive.modelMatrix = Cesium.Matrix4.multiply(
×
47
            translationMatrix,
48
            Cesium.Matrix4.multiply(rotationMatrix, scaleMatrix, new Cesium.Matrix4()),     // todo: try to remove this and put just the rotationMatrix
49
            new Cesium.Matrix4()
50
        );
51
    }
52
};
53
const updatePrimitivesVisibility = (primitives, visibilityOption) => {
1✔
54
    for (let i = 0; i < primitives.length; i++) {
×
55
        const primitive = primitives.get(i);
×
56
        primitive.show = visibilityOption;
×
57
    }
58
};
59
const getGeometryInstances = ({
1✔
60
    meshes
61
}) => {
62
    return meshes
×
63
        .map((mesh) => mesh.geometry.map(({
×
64
            color,
65
            positions,
66
            normals,
67
            indices,
68
            flatTransformation
69
        }) => {
70
            const rotationMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
×
71
                new Cesium.Cartesian3(0.0, 0.0, 0.0),
72
                Cesium.Quaternion.fromAxisAngle(
73
                    new Cesium.Cartesian3(1.0, 0.0, 0.0),
74
                    Math.PI / 2
75
                ),
76
                new Cesium.Cartesian3(1.0, 1.0, 1.0),
77
                new Cesium.Matrix4()
78
            );
79
            const transformedPositions = positions;
×
80
            const transformedNormals = normals;
×
81
            let geometryInstance =  new Cesium.GeometryInstance({
×
82
                id: mesh.id,
83
                modelMatrix: Cesium.Matrix4.multiply(
84
                    rotationMatrix,
85
                    flatTransformation,
86
                    new Cesium.Matrix4()
87
                ),
88
                geometry: new Cesium.Geometry({
89
                    attributes: {
90
                        position: new Cesium.GeometryAttribute({
91
                            componentDatatype: Cesium.ComponentDatatype.DOUBLE,
92
                            componentsPerAttribute: 3,
93
                            values: new Float64Array(transformedPositions)
94
                        }),
95
                        normal: new Cesium.GeometryAttribute({
96
                            componentDatatype: Cesium.ComponentDatatype.FLOAT,
97
                            componentsPerAttribute: 3,
98
                            values: transformedNormals,
99
                            normalize: true
100
                        })
101
                    },
102
                    indices,
103
                    primitiveType: Cesium.PrimitiveType.TRIANGLES,
104
                    boundingSphere: Cesium.BoundingSphere.fromVertices(transformedPositions)
105
                }),
106
                attributes: {
107
                    color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(
108
                        color.x,
109
                        color.y,
110
                        color.z,
111
                        color.w
112
                    ))
113
                }
114
            });
115
            geometryInstance.originalOpacity = color.w;
×
116
            return geometryInstance;
×
117
        })).flat();
118
};
119

120
const createPrimitiveFromMeshes = (meshes, options, primitiveName) => {
1✔
121
    const primitive = new Cesium.Primitive({
×
122
        geometryInstances: getGeometryInstances({
123
            meshes: meshes.filter(mesh => primitiveName === 'translucentPrimitive' ? !mesh.geometry.every(({ color }) => color.w === 1) : !!mesh.geometry.every(({ color }) => color.w === 1))
×
124
        }),
125
        releaseGeometryInstances: false,
126
        appearance: new Cesium.PerInstanceColorAppearance({
127
            translucent: primitiveName === 'translucentPrimitive' ? true : false
×
128
        }),
129
        asynchronous: false,
130
        allowPicking: true
131
    });
132
    // see https://github.com/geosolutions-it/MapStore2/blob/9f6f9d498796180ff59679887d300ce51e72a289/web/client/components/map/cesium/Map.jsx#L354-L393
133
    primitive._msGetFeatureById = (id) => {
×
134
        return {
×
135
            msId: options.id,
136
            feature: {
137
                properties: meshes.find((_mesh) => _mesh.id === id)?.properties || {},
×
138
                type: 'Feature',
139
                geometry: null
140
            }
141
        };
142
    };
143
    primitive.msId = options.id;
×
144
    primitive.id = primitiveName;
×
145
    return primitive;
×
146
};
147

148
const createLayer = (options, map) => {
1✔
149
    if (!options.visibility) {
2!
150
        return {
×
151
            detached: true,
152
            primitives: () => undefined,
×
153
            remove: () => {},
154
            add: () => {}
155
        };
156
    }
157
    let primitives;
158
    return {
2✔
159
        detached: true,
160
        primitives,
161
        add: () => {
162
            primitives = new Cesium.PrimitiveCollection({ destroyPrimitives: true });
1✔
163
            getIFCModel(options.url)
1✔
164
                .then(({ifcModule, data}) => {
165
                    const { meshes } = ifcDataToJSON({ ifcModule, data });
×
166
                    const translucentPrimitive = createPrimitiveFromMeshes(meshes, options, 'translucentPrimitive');
×
167
                    const opaquePrimitive = createPrimitiveFromMeshes(meshes, options, 'opaquePrimitive');
×
168
                    primitives.add(translucentPrimitive);
×
169
                    primitives.add(opaquePrimitive);
×
170
                    updatePrimitivesMatrix(primitives, options?.features?.[0]);
×
171
                });
172
            map.scene.primitives.add(primitives);
1✔
173
        },
174
        remove: () => {
175
            if (primitives && map) {
2✔
176
                map.scene.primitives.remove(primitives);
1✔
177
                primitives = undefined;
1✔
178
            }
179
        },
180
        setVisible: (
181
            newVisibility
182
        ) => {
183
            if (primitives && map) {
×
184
                updatePrimitivesVisibility(primitives, newVisibility);
×
185
            }
186
        }
187
    };
188
};
189

190
Layers.registerType('model', {
1✔
191
    create: createLayer,
192
    update: (layer, newOptions, oldOptions, map) => {
193
        if (layer?.primitives && !isEqual(newOptions?.features?.[0], oldOptions?.features?.[0])) {
1!
194
            updatePrimitivesMatrix(layer?.primitives, newOptions?.features?.[0]);
×
195
        }
196
        if (newOptions?.forceProxy !== oldOptions?.forceProxy) {
1!
197
            return createLayer(newOptions, map);
1✔
198
        }
UNCOV
199
        return null;
×
200
    }
201
});
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc