@team-geospan/struct3d 1.0.4 → 1.0.6

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.
@@ -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 = "sq. m.";
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
- // assume a surface
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
@@ -20,3 +20,8 @@ export const DEFAULT_EDGE_COLORS = {
20
20
  fance: "#a97bc2",
21
21
  chimney: "#5b517d",
22
22
  };
23
+
24
+ export const DEFAULT_SCENE_THEME = {
25
+ sky: "#CDEBF7",
26
+ ground: 0x315d0a,
27
+ };
package/lib/draw.js CHANGED
@@ -195,10 +195,10 @@ export function createFacets(structureCollection, baseElevation, facetColors) {
195
195
  return meshes;
196
196
  }
197
197
 
198
- export function createReferences(scene) {
198
+ export function createReferences(scene, groundColor = 0x315d0a) {
199
199
  const floorGeom = new THREE.PlaneGeometry(1000, 1000);
200
200
  const floorMaterial = new THREE.MeshPhongMaterial({
201
- color: 0x315d0a,
201
+ color: groundColor,
202
202
  side: THREE.DoubleSide,
203
203
  });
204
204
  const floorMesh = new THREE.Mesh(floorGeom, floorMaterial);
@@ -214,6 +214,42 @@ export function createReferences(scene) {
214
214
  scene.add(gridHelper);
215
215
  }
216
216
 
217
+ export function createAccessories(structureCollection, baseElevation) {
218
+ const [x0, y0, minz] = getAnchor(structureCollection);
219
+ const points = structureCollection.structures[0].points;
220
+ const pois = structureCollection.structures.flatMap((structure, stIdx) => {
221
+ return Object.keys(structure.surfaces).flatMap((surfaceId) => {
222
+ const surface = structure.surfaces[surfaceId];
223
+ const poiIDs = surface.properties?.accessories || [];
224
+
225
+ return poiIDs.map((poiID) => {
226
+ const pinGeom = new THREE.SphereGeometry(0.3, 32, 32);
227
+ const poiColor = points[poiID].color;
228
+ const poiLabel = points[poiID].label;
229
+ const material = new THREE.MeshBasicMaterial({
230
+ color: poiColor,
231
+ });
232
+ const pin = new THREE.Mesh(pinGeom, material);
233
+ const point = points[poiID].coordinates;
234
+ const coords = [
235
+ point[0] - x0,
236
+ point[2] - minz + baseElevation,
237
+ y0 - point[1],
238
+ ];
239
+ pin.position.fromArray(coords);
240
+ pin.userData = {
241
+ id: `${stIdx}-${poiID}`,
242
+ layer: "accessories",
243
+ label: poiLabel,
244
+ color: poiColor,
245
+ };
246
+ return pin;
247
+ });
248
+ });
249
+ });
250
+ return pois;
251
+ }
252
+
217
253
  export function addLights(scene, center, bounds) {
218
254
  const intensity = 5000;
219
255
  const ambient = new THREE.AmbientLight(0xffffff);
package/lib/index.js CHANGED
@@ -21,12 +21,14 @@ import { toMercator } from "@turf/projection";
21
21
  import PropTypes from "prop-types";
22
22
  import * as THREE from "three";
23
23
  import { OrbitControls } from "three/addons/controls/OrbitControls";
24
+ import { DEFAULT_SCENE_THEME } from "./defaults";
24
25
 
25
26
  import {
26
27
  addLights,
27
28
  clearScene,
28
29
  createFacets,
29
30
  createLines,
31
+ createAccessories,
30
32
  createReferences,
31
33
  } from "./draw";
32
34
 
@@ -39,6 +41,7 @@ const setupScene = (
39
41
  rendererRef,
40
42
  orbitRef,
41
43
  fieldOfView,
44
+ skyColor = THREED_SKY_COLOR,
42
45
  ) => {
43
46
  const [width, height] = [
44
47
  divRef.current.offsetWidth,
@@ -49,7 +52,7 @@ const setupScene = (
49
52
  const scene = new THREE.Scene();
50
53
  sceneRef.current = scene;
51
54
 
52
- scene.background = new THREE.Color(THREED_SKY_COLOR);
55
+ scene.background = new THREE.Color(skyColor);
53
56
  scene.fog = new THREE.Fog(scene.background, 1, 5000);
54
57
 
55
58
  const camera = new THREE.PerspectiveCamera(
@@ -89,6 +92,7 @@ const renderModel = (
89
92
  cameraRef,
90
93
  orbitRef,
91
94
  fieldOfView,
95
+ groundColor = 0x315d0a,
92
96
  ) => {
93
97
  // calculate the spatial extents of the meshes
94
98
  const boundingBox = new THREE.Box3();
@@ -121,13 +125,18 @@ const renderModel = (
121
125
  scene.add(line);
122
126
  });
123
127
 
128
+ const pois = createAccessories(collection, baseElevation);
129
+ pois.forEach((poi) => {
130
+ scene.add(poi);
131
+ });
132
+
124
133
  const center = new THREE.Vector3();
125
134
  boundingBox.getCenter(center);
126
135
 
127
136
  const bounds = new THREE.Vector3();
128
137
  boundingBox.getSize(bounds);
129
138
 
130
- createReferences(scene, center, bounds);
139
+ createReferences(scene, groundColor);
131
140
 
132
141
  addLights(scene, center, bounds);
133
142
 
@@ -150,6 +159,7 @@ export default function StructureThreeD({
150
159
  selectionColor = "#d4af38",
151
160
  facetColors = DEFAULT_FACET_COLORS,
152
161
  edgeColors = DEFAULT_EDGE_COLORS,
162
+ sceneTheme = DEFAULT_SCENE_THEME,
153
163
  }) {
154
164
  const baseElevation = 10;
155
165
  const fieldOfView = 70;
@@ -158,6 +168,8 @@ export default function StructureThreeD({
158
168
  const cameraRef = useRef(null);
159
169
  const orbitRef = useRef(null);
160
170
  const rendererRef = useRef(null);
171
+ const skyColor = sceneTheme.sky;
172
+ const groundColor = sceneTheme.ground;
161
173
 
162
174
  const collection = useMemo(() => {
163
175
  // check the projection of the structures and put them into webmerc
@@ -205,7 +217,12 @@ export default function StructureThreeD({
205
217
  rendererRef,
206
218
  orbitRef,
207
219
  fieldOfView,
220
+ skyColor,
208
221
  );
222
+ } else {
223
+ // update colors
224
+ sceneRef.current.background = new THREE.Color(skyColor);
225
+ sceneRef.current.fog = new THREE.Fog(skyColor, 1, 5000);
209
226
  }
210
227
 
211
228
  clearScene(sceneRef.current);
@@ -219,9 +236,10 @@ export default function StructureThreeD({
219
236
  cameraRef,
220
237
  orbitRef,
221
238
  fieldOfView,
239
+ groundColor,
222
240
  );
223
241
  }
224
- }, [collection, selectionColor]);
242
+ }, [collection, selectionColor, skyColor, groundColor, sceneTheme]);
225
243
 
226
244
  const handleClick = useCallback(
227
245
  (evt) => {
@@ -239,12 +257,12 @@ export default function StructureThreeD({
239
257
  true,
240
258
  );
241
259
  const ids = intersects
242
- .map((f) => f.object.userData)
243
- .map((f) => f.id)
260
+ .map((f) => f.object.userData.id)
244
261
  // ensure the object has an ID
245
262
  .filter((id) => !!id);
246
263
  if (onClick) {
247
- onClick(ids);
264
+ // only return the closest intersected object
265
+ onClick(ids.slice(0, 1));
248
266
  }
249
267
  },
250
268
  [onClick],
@@ -255,10 +273,18 @@ export default function StructureThreeD({
255
273
  sceneRef.current.traverse((object) => {
256
274
  // ensure the object has a material set and the userData has our layer specified
257
275
  if (object.material && Boolean(object.userData?.layer)) {
258
- let color =
259
- object.userData.layer === "facets"
260
- ? facetColors[object.userData?.material || "asphalt"]
261
- : edgeColors[object.userData.kind] || "#00000000";
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
+ }
262
288
  if (selectedIds.includes(object.userData?.id)) {
263
289
  color = selectionColor;
264
290
  }
@@ -311,4 +337,5 @@ StructureThreeD.propTypes = {
311
337
  selectionColor: PropTypes.string,
312
338
  facetColors: PropTypes.object,
313
339
  edgeColors: PropTypes.object,
340
+ sceneTheme: PropTypes.object,
314
341
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-geospan/struct3d",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
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",
@@ -1,465 +0,0 @@
1
- {
2
- "kind": "structurecollection",
3
- "structures": [
4
- {
5
- "kind": "structure",
6
- "projection": "planar",
7
- "points": {
8
- "c101": {
9
- "kind": "corner",
10
- "coordinates": [
11
- -0.0,
12
- 0.101,
13
- 3.370403808593778
14
- ]
15
- },
16
- "c102": {
17
- "kind": "corner",
18
- "coordinates": [
19
- 0.129,
20
- 11.677,
21
- 3.370403808593778
22
- ]
23
- },
24
- "c103": {
25
- "kind": "corner",
26
- "coordinates": [
27
- 4.579,
28
- 7.122,
29
- 5.351403808593773
30
- ]
31
- },
32
- "c104": {
33
- "kind": "corner",
34
- "coordinates": [
35
- 4.55,
36
- 4.546,
37
- 5.351403808593773
38
- ]
39
- },
40
- "c105": {
41
- "kind": "corner",
42
- "coordinates": [
43
- 9.129,
44
- 11.576,
45
- 3.370403808593778
46
- ]
47
- },
48
- "c106": {
49
- "kind": "corner",
50
- "coordinates": [
51
- 9.0,
52
- 0.0,
53
- 3.370403808593778
54
- ]
55
- },
56
- "ground": {
57
- "kind": "ground",
58
- "coordinates": [
59
- -0.0,
60
- 0.0,
61
- 0.00040380859377364686
62
- ]
63
- }
64
- },
65
- "edges": {
66
- "e101": {
67
- "kind": "eave",
68
- "points": [
69
- "c101",
70
- "c102"
71
- ],
72
- "properties": {
73
- "attachments": [
74
- "gutter"
75
- ],
76
- "length": 11.577
77
- }
78
- },
79
- "e102": {
80
- "kind": "hip",
81
- "points": [
82
- "c102",
83
- "c103"
84
- ],
85
- "properties": {
86
- "length": 6.669
87
- }
88
- },
89
- "e108": {
90
- "kind": "eave",
91
- "points": [
92
- "c102",
93
- "c105"
94
- ],
95
- "properties": {
96
- "attachments": [
97
- "gutter"
98
- ],
99
- "length": 9.001
100
- }
101
- },
102
- "e103": {
103
- "kind": "hip",
104
- "points": [
105
- "c104",
106
- "c101"
107
- ],
108
- "properties": {
109
- "length": 6.663
110
- }
111
- },
112
- "e107": {
113
- "kind": "hip",
114
- "points": [
115
- "c104",
116
- "c106"
117
- ],
118
- "properties": {
119
- "length": 6.663
120
- }
121
- },
122
- "e104": {
123
- "kind": "ridge",
124
- "points": [
125
- "c103",
126
- "c104"
127
- ],
128
- "properties": {
129
- "length": 2.576
130
- }
131
- },
132
- "e105": {
133
- "kind": "eave",
134
- "points": [
135
- "c105",
136
- "c106"
137
- ],
138
- "properties": {
139
- "attachments": [
140
- "gutter"
141
- ],
142
- "length": 11.577
143
- }
144
- },
145
- "e106": {
146
- "kind": "hip",
147
- "points": [
148
- "c105",
149
- "c103"
150
- ],
151
- "properties": {
152
- "length": 6.669
153
- }
154
- },
155
- "e109": {
156
- "kind": "eave",
157
- "points": [
158
- "c106",
159
- "c101"
160
- ],
161
- "properties": {
162
- "attachments": [
163
- "gutter"
164
- ],
165
- "length": 9.001
166
- }
167
- }
168
- },
169
- "surfaces": {
170
- "surface1": {
171
- "kind": "roof",
172
- "edges": [
173
- [
174
- "e101",
175
- "e102",
176
- "e103",
177
- "e104"
178
- ]
179
- ],
180
- "properties": {
181
- "material": "asphalt",
182
- "pitch": 5,
183
- "area": 34.799
184
- }
185
- },
186
- "surface2": {
187
- "kind": "roof",
188
- "edges": [
189
- [
190
- "e105",
191
- "e106",
192
- "e107",
193
- "e104"
194
- ]
195
- ],
196
- "properties": {
197
- "material": "asphalt",
198
- "pitch": 5,
199
- "area": 34.799
200
- }
201
- },
202
- "surface3": {
203
- "kind": "roof",
204
- "edges": [
205
- [
206
- "e108",
207
- "e106",
208
- "e102"
209
- ]
210
- ],
211
- "properties": {
212
- "material": "asphalt",
213
- "pitch": 5,
214
- "area": 22.149
215
- }
216
- },
217
- "surface4": {
218
- "kind": "roof",
219
- "edges": [
220
- [
221
- "e109",
222
- "e107",
223
- "e103"
224
- ]
225
- ],
226
- "properties": {
227
- "material": "asphalt",
228
- "pitch": 5,
229
- "area": 22.112
230
- }
231
- }
232
- },
233
- "components": {
234
- "roof": {
235
- "surfaces": [
236
- "surface1",
237
- "surface2",
238
- "surface3",
239
- "surface4"
240
- ]
241
- }
242
- }
243
- },
244
- {
245
- "kind": "structure",
246
- "projection": "planar",
247
- "points": {
248
- "c107": {
249
- "kind": "corner",
250
- "coordinates": [
251
- 15.606,
252
- 4.39,
253
- 4.419403808593756
254
- ]
255
- },
256
- "c108": {
257
- "kind": "corner",
258
- "coordinates": [
259
- 19.581,
260
- 0.44,
261
- 2.5904038085937486
262
- ]
263
- },
264
- "c109": {
265
- "kind": "corner",
266
- "coordinates": [
267
- 11.656,
268
- 0.415,
269
- 2.5904038085937486
270
- ]
271
- },
272
- "c110": {
273
- "kind": "corner",
274
- "coordinates": [
275
- 19.556,
276
- 8.365,
277
- 2.5904038085937486
278
- ]
279
- },
280
- "c111": {
281
- "kind": "corner",
282
- "coordinates": [
283
- 11.631,
284
- 8.34,
285
- 2.5904038085937486
286
- ]
287
- },
288
- "ground": {
289
- "kind": "ground",
290
- "coordinates": [
291
- 11.631,
292
- 0.415,
293
- 0.00040380859377364686
294
- ]
295
- }
296
- },
297
- "edges": {
298
- "e110": {
299
- "kind": "eave",
300
- "points": [
301
- "c108",
302
- "c109"
303
- ],
304
- "properties": {
305
- "attachments": [
306
- "gutter"
307
- ],
308
- "length": 7.926
309
- }
310
- },
311
- "e112": {
312
- "kind": "hip",
313
- "points": [
314
- "c108",
315
- "c107"
316
- ],
317
- "properties": {
318
- "length": 5.895
319
- }
320
- },
321
- "e111": {
322
- "kind": "hip",
323
- "points": [
324
- "c107",
325
- "c109"
326
- ],
327
- "properties": {
328
- "length": 5.895
329
- }
330
- },
331
- "e113": {
332
- "kind": "eave",
333
- "points": [
334
- "c110",
335
- "c108"
336
- ],
337
- "properties": {
338
- "attachments": [
339
- "gutter"
340
- ],
341
- "length": 7.926
342
- }
343
- },
344
- "e114": {
345
- "kind": "hip",
346
- "points": [
347
- "c110",
348
- "c107"
349
- ],
350
- "properties": {
351
- "length": 5.895
352
- }
353
- },
354
- "e115": {
355
- "kind": "eave",
356
- "points": [
357
- "c110",
358
- "c111"
359
- ],
360
- "properties": {
361
- "attachments": [
362
- "gutter"
363
- ],
364
- "length": 7.926
365
- }
366
- },
367
- "e116": {
368
- "kind": "hip",
369
- "points": [
370
- "c111",
371
- "c107"
372
- ],
373
- "properties": {
374
- "length": 5.895
375
- }
376
- },
377
- "e117": {
378
- "kind": "eave",
379
- "points": [
380
- "c111",
381
- "c109"
382
- ],
383
- "properties": {
384
- "attachments": [
385
- "gutter"
386
- ],
387
- "length": 7.926
388
- }
389
- }
390
- },
391
- "surfaces": {
392
- "surface5": {
393
- "kind": "roof",
394
- "edges": [
395
- [
396
- "e110",
397
- "e111",
398
- "e112"
399
- ]
400
- ],
401
- "properties": {
402
- "material": "asphalt",
403
- "pitch": 6,
404
- "area": 17.296
405
- }
406
- },
407
- "surface6": {
408
- "kind": "roof",
409
- "edges": [
410
- [
411
- "e113",
412
- "e112",
413
- "e114"
414
- ]
415
- ],
416
- "properties": {
417
- "material": "asphalt",
418
- "pitch": 6,
419
- "area": 17.296
420
- }
421
- },
422
- "surface7": {
423
- "kind": "roof",
424
- "edges": [
425
- [
426
- "e115",
427
- "e116",
428
- "e114"
429
- ]
430
- ],
431
- "properties": {
432
- "material": "asphalt",
433
- "pitch": 6,
434
- "area": 17.295
435
- }
436
- },
437
- "surface8": {
438
- "kind": "roof",
439
- "edges": [
440
- [
441
- "e117",
442
- "e111",
443
- "e116"
444
- ]
445
- ],
446
- "properties": {
447
- "material": "asphalt",
448
- "pitch": 6,
449
- "area": 17.295
450
- }
451
- }
452
- },
453
- "components": {
454
- "roof": {
455
- "surfaces": [
456
- "surface5",
457
- "surface6",
458
- "surface7",
459
- "surface8"
460
- ]
461
- }
462
- }
463
- }
464
- ]
465
- }
Binary file
Binary file