@eturnity/eturnity_3d 7.24.0-EPDM-10926.0 → 7.24.1

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_3d",
3
3
  "private": false,
4
- "version": "7.24.0-EPDM-10926.0",
4
+ "version": "7.24.1",
5
5
  "files": [
6
6
  "dist",
7
7
  "src"
@@ -15,7 +15,7 @@
15
15
  "prettier": "prettier --write \"**/*.{js,vue}\""
16
16
  },
17
17
  "dependencies": {
18
- "@eturnity/eturnity_maths": "7.24.0",
18
+ "@eturnity/eturnity_maths": "7.24.1",
19
19
  "@originjs/vite-plugin-commonjs": "1.0.3",
20
20
  "core-js": "2.6.12",
21
21
  "cors": "2.8.5",
@@ -17,14 +17,14 @@ import {
17
17
  rotateTransformation
18
18
  } from '@eturnity/eturnity_maths'
19
19
  let Paper
20
- export default class ThreeDModelOverlay extends Overlay {
21
- constructor(overlay, emit, origin, loader) {
20
+ export default class AirTeamOverlay extends Overlay {
21
+ constructor(overlay, emit, origin) {
22
22
  super(overlay, emit)
23
+ //this.updateVerticalProjectionIfNeeded()
23
24
  this.canvasWidth = 400
24
25
  this.canvasHeight = 400
25
26
  this.origin = origin
26
27
  this.imageUrl = null
27
- this.loader = loader
28
28
  this.initialiseModel().then((isReady) => {
29
29
  this.isReady = isReady
30
30
  this.version++
@@ -42,7 +42,6 @@ export default class ThreeDModelOverlay extends Overlay {
42
42
  this.extracted = false
43
43
  this.geoLocalisation = this.settings.geoLocalisation
44
44
  }
45
- loadFile() {}
46
45
  onLoad() {
47
46
  return new Promise((resolve) => {
48
47
  if (this.isReady) {
@@ -52,17 +51,65 @@ export default class ThreeDModelOverlay extends Overlay {
52
51
  }
53
52
  })
54
53
  }
54
+ setOpacity(opacity) {
55
+ this.opacity = opacity
56
+ this.emit('item-updated', this)
57
+ this.emit('overlay-three-loaded', this)
58
+ }
59
+ hasVerticalProjection() {
60
+ return this.resources.some((resource) => resource.file_type == 'image')
61
+ }
62
+ loadGLBFile() {
63
+ this.isReady = false
64
+ return new Promise((resolve) => {
65
+ if (this.overlayMesh) {
66
+ resolve(this.overlayMesh)
67
+ }
68
+ let resource = this.resources[0]
69
+ let overlayMesh = new THREE.Group()
70
+ const glbLoader = new GLTFLoader()
71
+ glbLoader.load(resource.file_url, (gltf) => {
72
+ const model = gltf.scene
73
+ overlayMesh.attach(model)
74
+ overlayMesh.userData.meshId = this.id
75
+ model.rotateX(Math.PI / 2)
76
+ model.children = model.children.filter((child) =>
77
+ [
78
+ 'textured_facade',
79
+ 'textured_environment',
80
+ 'textured_roof',
81
+ 'plain_roof_simplified'
82
+ ].includes(child.name)
83
+ )
84
+ model.children.forEach((child) => {
85
+ if (['plain_roof_simplified'].includes(child.name)) {
86
+ child.visible = false
87
+ }
88
+ })
89
+
90
+ overlayMesh.userData.type = 'overlayMeshes'
91
+ overlayMesh.userData.meshId = this.id
92
+ overlayMesh.userData.version = this.version
93
+ overlayMesh.position.set(0, 0, 0)
94
+ const box = new THREE.Box3().setFromObject(overlayMesh)
95
+ overlayMesh.position.set(0, 0, -box.min.z)
96
+ resolve(overlayMesh)
97
+ })
98
+ })
99
+ }
55
100
  set3DObjectMaterialOpacity(obj) {
56
101
  obj.children.forEach((child) => {
57
102
  this.set3DObjectMaterialOpacity(child, this.opacity)
58
103
  })
59
- obj.visible = this.opacity > 0
60
- obj.material.opacity = this.opacity
61
- obj.material.transparent = this.opacity < 1
104
+ if (obj.material && obj.name!='plain_roof_simplified') {
105
+ obj.visible = this.opacity > 0
106
+ obj.material.opacity = this.opacity
107
+ obj.material.transparent = this.opacity < 1
108
+ }
62
109
  }
63
110
  async renderOnThreeJS(threeJSComponent) {
64
111
  if (this.overlayMesh && this.overlayMesh.children.length == 0) {
65
- this.overlayMesh = await this.loadFile()
112
+ this.overlayMesh = await this.loadGLBFile()
66
113
  }
67
114
 
68
115
  if (!this.isReady) {
@@ -103,7 +150,7 @@ export default class ThreeDModelOverlay extends Overlay {
103
150
  threeJSComponent.scene.add(overlayMesh)
104
151
  }
105
152
  if (!overlayMesh) {
106
- overlayMesh = await this.loadFile()
153
+ overlayMesh = await this.loadGLBFile()
107
154
  threeJSComponent.meshes.overlayMeshes[meshId] = overlayMesh
108
155
  }
109
156
  const positionOffset = multiplyVector(1 / 1000, this.positionOffset)
@@ -192,6 +239,11 @@ export default class ThreeDModelOverlay extends Overlay {
192
239
  handles = this.renderImageOverlayHandles(corners, isRotationHandleVisible)
193
240
  group.addChild(imageOverlayPath)
194
241
  group.addChild(handles)
242
+ // let circle=new Paper.Path.Circle(new Paper.Point(paperJSComponent.toCanvasRef(multiplyVector(1000,this.geoLocalisation))),10)
243
+ // circle.strokeWidth=2
244
+ // circle.strokeColor = 'lime'
245
+ // group.addChild(circle)
246
+
195
247
  group.itemType = 'imageOverlays'
196
248
  group.data.url = this.url
197
249
  group.type = 'imageOverlays'
@@ -322,10 +374,49 @@ export default class ThreeDModelOverlay extends Overlay {
322
374
  circleHandle.visible = rotateHandleVisible
323
375
  return handles
324
376
  }
325
- initialiseCornersAndProjectionCamera(){
377
+ async initialiseModel() {
378
+ this.overlayMesh = await this.loadGLBFile()
379
+ if (!this.geoLocalisation) {
380
+ this.checkGeoLocDataAndOffset()
381
+ }
382
+ this.imageUrl = await this.initialiseVerticalProjectionImg()
383
+ this.overlayMesh.position.set(
384
+ this.positionOffset.x / 1000,
385
+ this.positionOffset.y / 1000,
386
+ 0
387
+ )
388
+ this.overlayMesh.rotateZ(-this.angleOffset)
389
+ return true
390
+ }
391
+ checkGeoLocDataAndOffset() {
392
+ const lat0 = this.overlayMesh.children[0].userData.latitude_origin
393
+ const lng0 = this.overlayMesh.children[0].userData.longitude_origin
394
+ if (lat0 && lng0 && this.origin) {
395
+ let { x, y } = deltaLatLngToDistance(
396
+ lat0 - this.origin.lat,
397
+ lng0 - this.origin.lng,
398
+ lat0
399
+ )
400
+ if (Math.hypot(x, y) < 100000) {
401
+ this.positionOffset.x = x
402
+ this.positionOffset.y = y
403
+ this.positionOffset.z = 0
404
+ } else {
405
+ this.positionOffset.x = 0
406
+ this.positionOffset.y = 0
407
+ this.positionOffset.z = 0
408
+ this.emit('overlay-offset-position-error', { id: this.id })
409
+ }
410
+ this.geoLocalisation={x,y}
411
+ }
412
+ }
413
+ initialiseVerticalProjectionImg() {
414
+ return new Promise((resolve, reject) => {
326
415
  const box = new THREE.Box3().setFromObject(this.overlayMesh)
327
416
  const boxSize = box.getSize(new THREE.Vector3())
328
417
  this.boxSize = boxSize
418
+ this.canvasWidth = boxSize.x * 100
419
+ this.canvasHeight = boxSize.y * 100
329
420
  const boxCenter = box.getCenter(new THREE.Vector3())
330
421
  const left = -boxSize.x / 2
331
422
  const right = +boxSize.x / 2
@@ -364,6 +455,11 @@ export default class ThreeDModelOverlay extends Overlay {
364
455
  corner = addVector(corner, this.positionOffset)
365
456
  this.corners[index] = corner
366
457
  })
458
+ // Create a canvas element
459
+ const canvas = this.createCanvas()
460
+
461
+ // Initialize Three.js
462
+ const scene = new THREE.Scene()
367
463
  this.overlayProjectionCamera = new THREE.OrthographicCamera(
368
464
  left,
369
465
  right,
@@ -372,37 +468,6 @@ export default class ThreeDModelOverlay extends Overlay {
372
468
  0.1, // near
373
469
  1000 // far
374
470
  )
375
- }
376
- checkGeoLocDataAndOffset(){
377
- return
378
- }
379
- async initialiseModel() {
380
- this.overlayMesh = await this.loadFile()
381
- if (!this.geoLocalisation) {
382
- this.checkGeoLocDataAndOffset()
383
- }
384
- this.initialiseCornersAndProjectionCamera()
385
- this.imageUrl = await this.initialiseVerticalProjectionImg()
386
- this.overlayMesh.position.set(
387
- this.positionOffset.x / 1000,
388
- this.positionOffset.y / 1000,
389
- 0
390
- )
391
- this.overlayMesh.rotateZ(-this.angleOffset)
392
- return true
393
- }
394
- setOverlayVisibilityFor2D(){
395
- return this.overlayMesh
396
- }
397
- initialiseVerticalProjectionImg() {
398
- return new Promise((resolve, reject) => {
399
- // Create a canvas element
400
- this.canvasWidth = this.boxSize.x * 100
401
- this.canvasHeight = this.boxSize.y * 100
402
- const canvas = this.createCanvas()
403
-
404
- // Initialize Three.js
405
- const scene = new THREE.Scene()
406
471
 
407
472
  const renderer = new THREE.WebGLRenderer({
408
473
  canvas: canvas,
@@ -410,17 +475,23 @@ export default class ThreeDModelOverlay extends Overlay {
410
475
  })
411
476
  renderer.setSize(this.canvasWidth, this.canvasHeight)
412
477
  renderer.setClearColor(0x000000, 0) // Make background transparent
413
- this.setOverlayVisibilityFor2D()
478
+
414
479
  scene.add(this.overlayMesh)
415
480
 
416
481
  // Set camera position and look at the center of the model
417
482
  this.overlayProjectionCamera.position.set(
418
- this.boxCenter.x,
419
- this.boxCenter.y,
420
- this.boxCenter.z + 100
483
+ boxCenter.x,
484
+ boxCenter.y,
485
+ boxCenter.z + 100
421
486
  )
422
- this.overlayProjectionCamera.lookAt(this.boxCenter.x, this.boxCenter.y, 0)
487
+ this.overlayProjectionCamera.lookAt(boxCenter.x, boxCenter.y, 0)
423
488
  this.overlayProjectionCamera.updateProjectionMatrix()
489
+ const childrenVisibility = this.overlayMesh.children[0].children.map(
490
+ (child) => child.visible
491
+ )
492
+ this.overlayMesh.children[0].children.forEach(
493
+ (child) => (child.visible = child.name == 'textured_roof')
494
+ )
424
495
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
425
496
  this.overlayMesh.children[0].add(ambientLight)
426
497
  const light = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.8)
@@ -432,12 +503,25 @@ export default class ThreeDModelOverlay extends Overlay {
432
503
  const imageUrl = canvas.toDataURL()
433
504
  this.overlayMesh.children[0].remove(light)
434
505
  this.overlayMesh.children[0].remove(ambientLight)
506
+ this.overlayMesh.children[0].children.forEach((child, index) => {
507
+ child.visible = childrenVisibility[index]
508
+ })
435
509
  canvas.parentNode.removeChild(canvas)
436
510
  resolve(imageUrl)
437
511
  })
438
512
  }
439
513
  getProjectedPlanesOnOverlay(outlines) {
514
+ // const scene = new THREE.Scene()
440
515
  const RayCaster = new THREE.Raycaster()
516
+ // let overlaySimplifiedRoof = this.overlayMesh.getObjectByName(
517
+ // 'plain_roof_simplified'
518
+ // )
519
+ // overlaySimplifiedRoof.visible = true
520
+ // if(overlaySimplifiedRoof){
521
+ // }else{
522
+ let overlaySimplifiedRoof = this.overlayMesh.clone()
523
+ //}
524
+ //scene.add(overlayMesh)
441
525
  const cloudsPoints = outlines.map((outline) => {
442
526
  let outlineBounds = outline.reduce(
443
527
  (acc, cur) => {
@@ -460,13 +544,15 @@ export default class ThreeDModelOverlay extends Overlay {
460
544
  }
461
545
  if (isInsidePolygon(testPoint, outline)) {
462
546
  RayCaster.set(
463
- new THREE.Vector3(testPoint.x / 1000, testPoint.y / 1000, 100),
464
- new THREE.Vector3(0, 0, -1)
547
+ new THREE.Vector3(testPoint.x / 1000, testPoint.y / 1000, 0),
548
+ new THREE.Vector3(0, 0, 1)
465
549
  )
466
- let intersects = RayCaster.intersectObject(this.overlayMesh)
467
- if(intersects.length>0){
468
- cloudPoints.push(intersects[0].point)
469
- }
550
+ let intersects = RayCaster.intersectObject(overlaySimplifiedRoof)
551
+ intersects.forEach((intersection) => {
552
+ if (intersection.object.name == 'textured_roof') {
553
+ cloudPoints.push(intersection.point)
554
+ }
555
+ })
470
556
  }
471
557
  }
472
558
  }
@@ -512,7 +598,8 @@ export default class ThreeDModelOverlay extends Overlay {
512
598
  serializeSettings() {
513
599
  return {
514
600
  version: this.version,
515
- corners: this.corners
601
+ corners: this.corners,
602
+ geoLocalisation: this.geoLocalisation
516
603
  }
517
604
  }
518
605
  }
@@ -1,12 +1,12 @@
1
1
  import Overlay from './Overlay'
2
- import GLBOverlay from './GLBOverlay'
2
+ import AirTeamOverlay from './AirTeamOverlay'
3
3
  import ImageOverlay from './ImageOverlay'
4
4
 
5
5
  const OverlayFactory = {
6
6
  createOverlay(serializedOverlay, emit, origin = { lat: null, lng: null }) {
7
7
  let overlayInstance
8
8
  if (serializedOverlay.type == 'airteam') {
9
- overlayInstance = new GLBOverlay(serializedOverlay, emit, origin)
9
+ overlayInstance = new AirTeamOverlay(serializedOverlay, emit, origin)
10
10
  } else if (serializedOverlay.type == 'image_overlay') {
11
11
  overlayInstance = new ImageOverlay(serializedOverlay, emit)
12
12
  } else {
@@ -31,13 +31,15 @@ export function UpdateRoofObstacleRelations(state, updateVersionEnable = true) {
31
31
  obstacle.roofs = []
32
32
 
33
33
  let roofsWithObstacle = roofPolygons.filter((roof) => {
34
+ if (roof.id == obstacle.id) {
35
+ return false
36
+ }
34
37
  let intersection =
35
38
  intersectOutlines(obstacle.outline, roof.outline)[0] || []
36
39
  if (intersection.length == 0) return false
37
40
  if (obstacle.layer == 'obstacle') return true
38
-
39
41
  let deltaArea = calculateArea(roof.outline) - calculateArea(intersection)
40
- if (deltaArea < 100) return false
42
+ if (deltaArea < 100 || calculateArea(intersection) < 100) return false
41
43
  return true
42
44
  })
43
45
 
@@ -21,7 +21,7 @@ export default {
21
21
  methods: {
22
22
  renderImageOverlayOnBackground() {
23
23
  const overlayGeometries = OverlayLayer.getReadyItems()
24
- .filter((overlay) => overlay.isReady && overlay.corners && overlay.type=='image_overlay')
24
+ .filter((overlay) => overlay.isReady && overlay.corners)
25
25
  .map((overlay) => {
26
26
  return overlay.getBackgroundGeometry()
27
27
  })
@@ -40,6 +40,7 @@ export default {
40
40
  this.applyTextureOnMesh(this.overlayMaterials, this.meshes.backgroundMesh)
41
41
 
42
42
  this.meshes.backgroundMesh.visible = true
43
+
43
44
  return
44
45
  },
45
46
  async getOverlaysMaterials() {
@@ -48,8 +49,7 @@ export default {
48
49
  overlayMaterialsPromises.push(overlay.getProjectionMaterial())
49
50
  })
50
51
  overlayMaterialsPromises = overlayMaterialsPromises.filter((p) => !!p)
51
- const imageOverlayMaterial = await Promise.all(overlayMaterialsPromises)
52
- this.imageOverlayMaterial=imageOverlayMaterial.filter(m=>!!m)
52
+ this.imageOverlayMaterial = await Promise.all(overlayMaterialsPromises)
53
53
  return this.imageOverlayMaterial
54
54
  }
55
55
  }
@@ -1,3 +1,5 @@
1
+ import * as THREE from 'three'
2
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
1
3
  import { mapState } from 'vuex'
2
4
  import OverlayLayer from '../../Overlay/OverlayLayer.js'
3
5
 
@@ -6,6 +8,7 @@ export default {
6
8
  return {}
7
9
  },
8
10
  created() {
11
+ this.glbLoader = new GLTFLoader()
9
12
  },
10
13
  computed: {
11
14
  ...mapState({})
@@ -1,91 +0,0 @@
1
- import ThreeDModelOverlay from './ThreeDModelOverlay'
2
- import * as THREE from 'three'
3
- import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
4
- import { deltaLatLngToDistance } from '@eturnity/eturnity_maths'
5
- export default class GLBOverlay extends ThreeDModelOverlay {
6
- constructor(overlay, emit, origin) {
7
- super(overlay, emit, origin, new GLTFLoader())
8
- this.extracted = false
9
- this.geoLocalisation = this.settings.geoLocalisation
10
- this.has_plain_roof_simplified = false
11
- }
12
- loadFile() {
13
- this.isReady = false
14
- return new Promise((resolve) => {
15
- if (this.overlayMesh) {
16
- resolve(this.overlayMesh)
17
- }
18
- let resource = this.resources[0]
19
- let overlayMesh = new THREE.Group()
20
- this.loader.load(resource.file_url, (gltf) => {
21
- const model = gltf.scene
22
- model.rotateX(Math.PI / 2)
23
- overlayMesh.userData.meshId = this.id
24
- overlayMesh.userData.type = 'overlayMeshes'
25
- overlayMesh.userData.version = this.version
26
- overlayMesh.attach(model)
27
- overlayMesh.position.set(0, 0, 0)
28
- const box = new THREE.Box3().setFromObject(overlayMesh)
29
- overlayMesh.position.set(0, 0, -box.min.z)
30
- if (overlayMesh.getObjectByName('plain_roof_simplified')) {
31
- this.has_plain_roof_simplified = true
32
- this.type = 'airteam'
33
- } else {
34
- this.type = 'custom_3d_model'
35
- }
36
- resolve(overlayMesh)
37
- })
38
- })
39
- }
40
- checkGeoLocDataAndOffset() {
41
- const lat0 = this.overlayMesh.children[0].userData.latitude_origin
42
- const lng0 = this.overlayMesh.children[0].userData.longitude_origin
43
- if (lat0 && lng0 && this.origin) {
44
- let { x, y } = deltaLatLngToDistance(
45
- lat0 - this.origin.lat,
46
- lng0 - this.origin.lng,
47
- lat0
48
- )
49
- if (Math.hypot(x, y) < 100000) {
50
- this.positionOffset.x = x
51
- this.positionOffset.y = y
52
- this.positionOffset.z = 0
53
- } else {
54
- this.positionOffset.x = 0
55
- this.positionOffset.y = 0
56
- this.positionOffset.z = 0
57
- this.emit('overlay-offset-position-error', { id: this.id })
58
- }
59
- this.geoLocalisation = { x, y }
60
- }
61
- }
62
- setOverlayVisibilityFor2D() {
63
- if (
64
- this.overlayMesh.children[0].children.some(
65
- (child) => child.name == 'textured_roof'
66
- )
67
- ) {
68
- this.overlayMesh.children[0].children.forEach(
69
- (child) => (child.visible = child.name == 'textured_roof')
70
- )
71
- }
72
- return this.overlayMesh
73
- }
74
- set3DObjectMaterialOpacity(obj) {
75
- obj.children.forEach((child) => {
76
- this.set3DObjectMaterialOpacity(child, this.opacity)
77
- })
78
- if (obj.material && obj.name != 'plain_roof_simplified') {
79
- obj.visible = this.opacity > 0
80
- obj.material.opacity = this.opacity
81
- obj.material.transparent = this.opacity < 1
82
- }
83
- }
84
- serializeSettings() {
85
- return {
86
- version: this.version,
87
- corners: this.corners,
88
- geoLocalisation: this.geoLocalisation
89
- }
90
- }
91
- }