@team-geospan/struct3d 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MR_TEMPLATE.md +81 -0
- package/docs/src/pages/demo.jsx +6 -3
- package/lib/defaults.js +1 -0
- package/lib/draw.js +43 -3
- package/lib/index.js +21 -7
- package/package.json +2 -1
- package/team-geospan-struct3d-1.0.5.tgz +0 -0
package/MR_TEMPLATE.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Merge Request: Add Color Theme Support to 3D Viewer
|
|
2
|
+
|
|
3
|
+
### Type of Change
|
|
4
|
+
|
|
5
|
+
Indicate the type of change this MR introduces:
|
|
6
|
+
|
|
7
|
+
- [x] New Feature
|
|
8
|
+
- [ ] Bug Fix
|
|
9
|
+
- [ ] Documentation Update
|
|
10
|
+
- [ ] Refactoring
|
|
11
|
+
- [ ] Hotfix
|
|
12
|
+
- [ ] Security Patch
|
|
13
|
+
- [ ] UI/UX Improvement
|
|
14
|
+
|
|
15
|
+
### Description
|
|
16
|
+
|
|
17
|
+
* **Summary**: Added color theme support to the StructureThreeD component, allowing users to toggle between different visual themes (default and gray) with dynamic sky and ground color changes.
|
|
18
|
+
|
|
19
|
+
* **JIRA Ticket**: N/A
|
|
20
|
+
|
|
21
|
+
**Details**: Explain the changes in more detail, including:
|
|
22
|
+
|
|
23
|
+
* **Why these changes were necessary**: The 3D viewer needed visual theme options to improve user experience and provide different viewing modes for various use cases.
|
|
24
|
+
|
|
25
|
+
* **The approach taken to implement them**:
|
|
26
|
+
- Added a `COLOR_THEMES` object with predefined theme configurations
|
|
27
|
+
- Extended the `StructureThreeD` component to accept a `colorTheme` prop
|
|
28
|
+
- Updated the `createReferences` function to accept a `groundColor` parameter
|
|
29
|
+
- Implemented dynamic color application based on the selected theme
|
|
30
|
+
|
|
31
|
+
* **Links to any related issues or tickets**: N/A
|
|
32
|
+
|
|
33
|
+
### Testing
|
|
34
|
+
|
|
35
|
+
* **Environment**: Local development environment with eitri 3D viewer integration
|
|
36
|
+
* **Steps**:
|
|
37
|
+
1. Load a 3D model in the StructureThreeD component
|
|
38
|
+
2. Toggle between "default" and "gray" themes using the theme selector
|
|
39
|
+
3. Verify sky color changes from blue to gray
|
|
40
|
+
4. Verify ground color changes from green to gray
|
|
41
|
+
5. Confirm no visual regressions in model rendering
|
|
42
|
+
* **Automated Tests**: No new automated tests added (existing functionality preserved)
|
|
43
|
+
|
|
44
|
+
### Impact
|
|
45
|
+
|
|
46
|
+
* **Performance**: Minimal impact - only adds theme selection logic and color calculations during render
|
|
47
|
+
* **Dependencies**: No new dependencies added
|
|
48
|
+
* **Risks**:
|
|
49
|
+
- None - this is a purely additive change with no breaking changes
|
|
50
|
+
|
|
51
|
+
### Rollback Plan
|
|
52
|
+
|
|
53
|
+
* **Steps to rollback**:
|
|
54
|
+
1. Remove `colorTheme` prop from `StructureThreeD` component
|
|
55
|
+
2. Remove `COLOR_THEMES` object and related theme logic
|
|
56
|
+
3. Revert `createReferences` function signature to original: `createReferences(scene)`
|
|
57
|
+
4. Revert ground color to hardcoded `0xf8f9fa`
|
|
58
|
+
* **Preconditions**: None - this is a safe rollback
|
|
59
|
+
* **Impacts**: Any projects using the new theme functionality will lose theme support
|
|
60
|
+
|
|
61
|
+
### Checklist
|
|
62
|
+
|
|
63
|
+
Ensure the following before requesting a review:
|
|
64
|
+
|
|
65
|
+
- [x] Code comments have been added, particularly for complex logic or significant changes.
|
|
66
|
+
- [ ] Documentation has been updated to reflect the changes.
|
|
67
|
+
- [ ] Unit and integration tests have been added or updated.
|
|
68
|
+
- [x] All tests are passing.
|
|
69
|
+
- [x] No new warnings are generated by the linter.
|
|
70
|
+
- [x] The GitLab pipeline passes without errors.
|
|
71
|
+
- [ ] A teammate has been assigned as a reviewer, and any high-priority MRs have been shared with #development for quicker review.
|
|
72
|
+
|
|
73
|
+
### CHANGELOG
|
|
74
|
+
|
|
75
|
+
If this MR contains changes that should be highlighted in the changelog or release notes, please provide a draft here.
|
|
76
|
+
|
|
77
|
+
* 1.0.5
|
|
78
|
+
* Add color theme support to 3D viewer
|
|
79
|
+
* Add `colorTheme` prop to `StructureThreeD` component
|
|
80
|
+
* Add `COLOR_THEMES` object with default and gray themes
|
|
81
|
+
* Update `createReferences` function to accept `groundColor` parameter
|
package/docs/src/pages/demo.jsx
CHANGED
|
@@ -40,15 +40,18 @@ function SelectedInfo({ structureCollection, selectedId }) {
|
|
|
40
40
|
const [structureIndex, elementId] = selectedId.split("-");
|
|
41
41
|
const structure = structureCollection.structures[parseInt(structureIndex)];
|
|
42
42
|
|
|
43
|
-
let unitLabel = "
|
|
43
|
+
let unitLabel = "";
|
|
44
44
|
let value = 0.0;
|
|
45
45
|
if (structure.edges[elementId]) {
|
|
46
46
|
// use as edge
|
|
47
47
|
unitLabel = "m.";
|
|
48
48
|
value = structure.edges[elementId].properties.length;
|
|
49
|
-
} else {
|
|
50
|
-
//
|
|
49
|
+
} else if (structure.surfaces[elementId]) {
|
|
50
|
+
// use as surface
|
|
51
|
+
unitLabel = "sq. m.";
|
|
51
52
|
value = structure.surfaces[elementId].properties.area;
|
|
53
|
+
} else if (structure.points[elementId]) {
|
|
54
|
+
value = structure.points[elementId].label;
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
return (
|
package/lib/defaults.js
CHANGED
package/lib/draw.js
CHANGED
|
@@ -77,6 +77,10 @@ export function createLines(
|
|
|
77
77
|
const { edges, points } = structure;
|
|
78
78
|
return Object.keys(edges).map((edgeId) => {
|
|
79
79
|
const edge = edges[edgeId];
|
|
80
|
+
const effectiveKind = edge.properties?.attachments?.includes("gutter")
|
|
81
|
+
? "gutter"
|
|
82
|
+
: edge.kind;
|
|
83
|
+
|
|
80
84
|
// offset and swap coordinates
|
|
81
85
|
const linePoints = edge.points.map((pointId) => {
|
|
82
86
|
const pt = points[pointId].coordinates;
|
|
@@ -87,15 +91,15 @@ export function createLines(
|
|
|
87
91
|
geometry.setPositions(linePoints.flatMap((p) => p));
|
|
88
92
|
|
|
89
93
|
const material = new LineMaterial({
|
|
90
|
-
color: edgeColors[
|
|
91
|
-
linewidth:
|
|
94
|
+
color: edgeColors[effectiveKind] || "#000000",
|
|
95
|
+
linewidth: effectiveKind ? 3 : 1,
|
|
92
96
|
});
|
|
93
97
|
material.resolution.set(width, height);
|
|
94
98
|
|
|
95
99
|
const line = new Line2(geometry, material);
|
|
96
100
|
line.userData = {
|
|
97
101
|
...edge.properties,
|
|
98
|
-
kind:
|
|
102
|
+
kind: effectiveKind,
|
|
99
103
|
id: `${stIdx}-${edgeId}`,
|
|
100
104
|
layer: "edges",
|
|
101
105
|
};
|
|
@@ -214,6 +218,42 @@ export function createReferences(scene, groundColor = 0x315d0a) {
|
|
|
214
218
|
scene.add(gridHelper);
|
|
215
219
|
}
|
|
216
220
|
|
|
221
|
+
export function createAccessories(structureCollection, baseElevation) {
|
|
222
|
+
const [x0, y0, minz] = getAnchor(structureCollection);
|
|
223
|
+
const points = structureCollection.structures[0].points;
|
|
224
|
+
const pois = structureCollection.structures.flatMap((structure, stIdx) => {
|
|
225
|
+
return Object.keys(structure.surfaces).flatMap((surfaceId) => {
|
|
226
|
+
const surface = structure.surfaces[surfaceId];
|
|
227
|
+
const poiIDs = surface.properties?.accessories || [];
|
|
228
|
+
|
|
229
|
+
return poiIDs.map((poiID) => {
|
|
230
|
+
const pinGeom = new THREE.SphereGeometry(0.3, 32, 32);
|
|
231
|
+
const poiColor = points[poiID].color;
|
|
232
|
+
const poiLabel = points[poiID].label;
|
|
233
|
+
const material = new THREE.MeshBasicMaterial({
|
|
234
|
+
color: poiColor,
|
|
235
|
+
});
|
|
236
|
+
const pin = new THREE.Mesh(pinGeom, material);
|
|
237
|
+
const point = points[poiID].coordinates;
|
|
238
|
+
const coords = [
|
|
239
|
+
point[0] - x0,
|
|
240
|
+
point[2] - minz + baseElevation,
|
|
241
|
+
y0 - point[1],
|
|
242
|
+
];
|
|
243
|
+
pin.position.fromArray(coords);
|
|
244
|
+
pin.userData = {
|
|
245
|
+
id: `${stIdx}-${poiID}`,
|
|
246
|
+
layer: "accessories",
|
|
247
|
+
label: poiLabel,
|
|
248
|
+
color: poiColor,
|
|
249
|
+
};
|
|
250
|
+
return pin;
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
return pois;
|
|
255
|
+
}
|
|
256
|
+
|
|
217
257
|
export function addLights(scene, center, bounds) {
|
|
218
258
|
const intensity = 5000;
|
|
219
259
|
const ambient = new THREE.AmbientLight(0xffffff);
|
package/lib/index.js
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
clearScene,
|
|
29
29
|
createFacets,
|
|
30
30
|
createLines,
|
|
31
|
+
createAccessories,
|
|
31
32
|
createReferences,
|
|
32
33
|
} from "./draw";
|
|
33
34
|
|
|
@@ -124,6 +125,11 @@ const renderModel = (
|
|
|
124
125
|
scene.add(line);
|
|
125
126
|
});
|
|
126
127
|
|
|
128
|
+
const pois = createAccessories(collection, baseElevation);
|
|
129
|
+
pois.forEach((poi) => {
|
|
130
|
+
scene.add(poi);
|
|
131
|
+
});
|
|
132
|
+
|
|
127
133
|
const center = new THREE.Vector3();
|
|
128
134
|
boundingBox.getCenter(center);
|
|
129
135
|
|
|
@@ -251,12 +257,12 @@ export default function StructureThreeD({
|
|
|
251
257
|
true,
|
|
252
258
|
);
|
|
253
259
|
const ids = intersects
|
|
254
|
-
.map((f) => f.object.userData)
|
|
255
|
-
.map((f) => f.id)
|
|
260
|
+
.map((f) => f.object.userData.id)
|
|
256
261
|
// ensure the object has an ID
|
|
257
262
|
.filter((id) => !!id);
|
|
258
263
|
if (onClick) {
|
|
259
|
-
|
|
264
|
+
// only return the closest intersected object
|
|
265
|
+
onClick(ids.slice(0, 1));
|
|
260
266
|
}
|
|
261
267
|
},
|
|
262
268
|
[onClick],
|
|
@@ -267,10 +273,18 @@ export default function StructureThreeD({
|
|
|
267
273
|
sceneRef.current.traverse((object) => {
|
|
268
274
|
// ensure the object has a material set and the userData has our layer specified
|
|
269
275
|
if (object.material && Boolean(object.userData?.layer)) {
|
|
270
|
-
let color =
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
276
|
+
let color = null;
|
|
277
|
+
switch (object.userData.layer) {
|
|
278
|
+
case "accessories":
|
|
279
|
+
color = object.userData?.color || "#FFF";
|
|
280
|
+
break;
|
|
281
|
+
case "facets":
|
|
282
|
+
color = facetColors[object.userData?.material || "asphalt"];
|
|
283
|
+
break;
|
|
284
|
+
case "edges":
|
|
285
|
+
color = edgeColors[object.userData.kind] || "#00000000";
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
274
288
|
if (selectedIds.includes(object.userData?.id)) {
|
|
275
289
|
color = selectionColor;
|
|
276
290
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@team-geospan/struct3d",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "The 3D Viewer component for StructuresJSON models.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "GEOSPAN Corp and Contributors",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
+
"@team-geospan/structuresio": "^0.0.7",
|
|
40
41
|
"@turf/projection": "^6.5.0",
|
|
41
42
|
"earcut": "^3.0.1",
|
|
42
43
|
"react-resize-detector": "^12.0.2",
|
|
Binary file
|