@eturnity/eturnity_3d 7.20.1 → 7.24.0
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 +2 -2
- package/src/EventManager/EventManager.js +48 -0
- package/src/Item/Item.js +12 -0
- package/src/Layer/Layer.js +119 -0
- package/src/Overlay/AirTeamOverlay.js +605 -0
- package/src/Overlay/ImageOverlay.js +309 -0
- package/src/Overlay/Overlay.js +255 -0
- package/src/Overlay/OverlayFactory.js +19 -0
- package/src/Overlay/OverlayLayer.js +36 -0
- package/src/components/ThreeCanvasViewer.vue +17 -6
- package/src/config.js +120 -17
- package/src/helper/UpdateRoofModuleFieldRelations.js +65 -25
- package/src/helper/cameraMixin.js +25 -0
- package/src/helper/materialMixin.js +14 -1
- package/src/helper/projectedMaterial.js +662 -0
- package/src/helper/render/base.js +5 -5
- package/src/helper/render/clear.js +0 -17
- package/src/helper/render/edge.js +2 -0
- package/src/helper/render/geometryHandler.js +60 -31
- package/src/helper/render/imageOverlay.js +25 -144
- package/src/helper/render/index.js +2 -0
- package/src/helper/render/mergedGeometry.js +11 -2
- package/src/helper/render/obstacle.js +2 -1
- package/src/helper/render/overlay.js +41 -0
- package/src/helper/render/projectionMaterial.js +17 -19
- package/src/helper/render/roof.js +49 -52
- package/src/helper/render/texture.js +25 -0
- package/src/helper/render/tile.js +84 -24
- package/src/helper/render/tileProjection.js +23 -14
- package/src/helper/renderMixin.js +22 -8
- package/src/helper/threeMixin.js +5 -2
- package/src/store/hydrateData.js +23 -11
- package/src/store/nodesEdgesCreation.js +78 -4
- package/src/store/three-d-module.js +1 -1
- package/dist/css/app.58568098.css +0 -1
- package/dist/img/reneSola_Virtus_2_JC320S_24_Bbw.85a0cb6d.png +0 -0
- package/dist/index.html +0 -15
- package/dist/js/app-legacy.aa792c98.js +0 -2
- package/dist/js/app-legacy.aa792c98.js.map +0 -1
- package/dist/js/chunk-vendors-legacy.9bb3863d.js +0 -41
- package/dist/js/chunk-vendors-legacy.9bb3863d.js.map +0 -1
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import Overlay from './Overlay'
|
|
2
|
+
import { layerColors } from '../config'
|
|
3
|
+
import {
|
|
4
|
+
getDistanceBetweenPoints,
|
|
5
|
+
addVector,
|
|
6
|
+
multiplyVector,
|
|
7
|
+
substractVector,
|
|
8
|
+
getAngleInDegFromCanvasVector,
|
|
9
|
+
normalize2DVector,
|
|
10
|
+
vectorLength2D
|
|
11
|
+
} from '@eturnity/eturnity_maths'
|
|
12
|
+
let Paper
|
|
13
|
+
export default class ImageOverlay extends Overlay {
|
|
14
|
+
constructor(overlay, emit) {
|
|
15
|
+
super(overlay, emit)
|
|
16
|
+
this.url = this.resources[0].file_url
|
|
17
|
+
this.opacity = 1
|
|
18
|
+
this.imageUrl = this.resources[0].file_url
|
|
19
|
+
this.corners = overlay.settings.corners
|
|
20
|
+
this.hasScale = overlay.settings.hasScale
|
|
21
|
+
this.points =
|
|
22
|
+
overlay.settings.scaleParams && overlay.settings.scaleParams.points
|
|
23
|
+
? overlay.settings.scaleParams.points
|
|
24
|
+
: []
|
|
25
|
+
this.mmPerPx =
|
|
26
|
+
overlay.settings.scaleParams && overlay.settings.scaleParams.mmPerPx
|
|
27
|
+
? overlay.settings.scaleParams.mmPerPx
|
|
28
|
+
: null
|
|
29
|
+
this.distance =
|
|
30
|
+
overlay.settings.scaleParams && overlay.settings.scaleParams.distance
|
|
31
|
+
? overlay.settings.scaleParams.distance
|
|
32
|
+
: 10000
|
|
33
|
+
this.initialiseImage(this.url).then((isReady) => {
|
|
34
|
+
this.isReady = isReady
|
|
35
|
+
this.version++
|
|
36
|
+
this.emit('overlay-is-ready', { id: this.id })
|
|
37
|
+
this.isReadyCallback.forEach((callback) => {
|
|
38
|
+
if (typeof callback === 'function') {
|
|
39
|
+
callback()
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
this.isReadyCallback = []
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
onLoad() {
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
if (this.isReady) {
|
|
48
|
+
resolve(this)
|
|
49
|
+
} else {
|
|
50
|
+
this.isReadyCallback.push(resolve)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
async initialiseImage(url) {
|
|
55
|
+
const img = new Image()
|
|
56
|
+
const _this = this
|
|
57
|
+
const promise = new Promise((resolve, reject) => {
|
|
58
|
+
img.onload = function () {
|
|
59
|
+
_this.width = this.width
|
|
60
|
+
_this.height = this.height
|
|
61
|
+
resolve(true)
|
|
62
|
+
}
|
|
63
|
+
img.onerror = reject
|
|
64
|
+
this.img = img
|
|
65
|
+
})
|
|
66
|
+
img.src = url
|
|
67
|
+
return promise
|
|
68
|
+
}
|
|
69
|
+
async getInitial2DCorners(mmPerPx) {
|
|
70
|
+
const initialWidthMm = this.width * mmPerPx
|
|
71
|
+
const ratio = this.height / this.width
|
|
72
|
+
const initialHeightMm = ratio * initialWidthMm
|
|
73
|
+
const cornersTopLeft = {
|
|
74
|
+
x: -initialWidthMm / 2,
|
|
75
|
+
y: initialHeightMm / 2
|
|
76
|
+
}
|
|
77
|
+
const cornersTopRight = {
|
|
78
|
+
x: initialWidthMm / 2,
|
|
79
|
+
y: initialHeightMm / 2
|
|
80
|
+
}
|
|
81
|
+
const cornersBottomLeft = {
|
|
82
|
+
x: -initialWidthMm / 2,
|
|
83
|
+
y: -initialHeightMm / 2
|
|
84
|
+
}
|
|
85
|
+
const cornersBottomRight = {
|
|
86
|
+
x: initialWidthMm / 2,
|
|
87
|
+
y: -initialHeightMm / 2
|
|
88
|
+
}
|
|
89
|
+
const corners = [
|
|
90
|
+
cornersTopLeft,
|
|
91
|
+
cornersTopRight,
|
|
92
|
+
cornersBottomRight,
|
|
93
|
+
cornersBottomLeft
|
|
94
|
+
]
|
|
95
|
+
return corners
|
|
96
|
+
}
|
|
97
|
+
async setScale(scaleParams) {
|
|
98
|
+
if (!scaleParams) {
|
|
99
|
+
this.hasScale = false
|
|
100
|
+
this.version++
|
|
101
|
+
this.emit('overlay-scale-updated', { id: this.id })
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
let { points, distance, mmPerPx } = scaleParams
|
|
105
|
+
|
|
106
|
+
if (points.length < 2 || !distance) {
|
|
107
|
+
this.hasScale = false
|
|
108
|
+
this.version++
|
|
109
|
+
this.emit('overlay-scale-updated', { id: this.id })
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
this.mmPerPx = mmPerPx
|
|
113
|
+
this.points = points
|
|
114
|
+
this.distance = distance
|
|
115
|
+
this.hasScale = true
|
|
116
|
+
this.points = [{ ...this.points[0] }, { ...this.points[1] }]
|
|
117
|
+
this.version++
|
|
118
|
+
this.corners = await this.getInitial2DCorners(mmPerPx)
|
|
119
|
+
this.emit('overlay-scale-updated', { id: this.id })
|
|
120
|
+
}
|
|
121
|
+
renderOnPaperJS(paperJSComponent) {
|
|
122
|
+
Paper = paperJSComponent.paperScope
|
|
123
|
+
if (!this.isReady || !this.isActive || !this.corners) {
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
let group = paperJSComponent.paths.imageOverlays[this.id]
|
|
127
|
+
paperJSComponent.paperLayer['imageOverlays'].activate()
|
|
128
|
+
|
|
129
|
+
let imageOverlayPath
|
|
130
|
+
let handles
|
|
131
|
+
let isRotationHandleVisible =
|
|
132
|
+
paperJSComponent.selectedTool == 'selectOverlay' && this.isSelected
|
|
133
|
+
let corners = this.corners.map((p) => paperJSComponent.toCanvasRef(p))
|
|
134
|
+
if (group) {
|
|
135
|
+
if (group.data.url == this.url) {
|
|
136
|
+
imageOverlayPath = group.children[0]
|
|
137
|
+
} else {
|
|
138
|
+
imageOverlayPath = this.loadImageOverlay(this.url, corners)
|
|
139
|
+
paperJSComponent.clearPath(group.children[0])
|
|
140
|
+
group.insertChild(0, imageOverlayPath)
|
|
141
|
+
}
|
|
142
|
+
handles = this.renderImageOverlayHandles(
|
|
143
|
+
corners,
|
|
144
|
+
isRotationHandleVisible,
|
|
145
|
+
group.children[1]
|
|
146
|
+
)
|
|
147
|
+
this.applyRasterToCorners(imageOverlayPath, corners)
|
|
148
|
+
group.visible = true
|
|
149
|
+
} else {
|
|
150
|
+
group = new Paper.Group()
|
|
151
|
+
imageOverlayPath = this.loadImageOverlay(this.url, corners)
|
|
152
|
+
|
|
153
|
+
handles = this.renderImageOverlayHandles(corners, isRotationHandleVisible)
|
|
154
|
+
|
|
155
|
+
group.addChild(imageOverlayPath)
|
|
156
|
+
group.addChild(handles)
|
|
157
|
+
group.itemType = 'imageOverlays'
|
|
158
|
+
group.data.url = this.url
|
|
159
|
+
group.type = 'imageOverlays'
|
|
160
|
+
group.pathId = this.id
|
|
161
|
+
group.overlayId = this.id
|
|
162
|
+
group.visible = true
|
|
163
|
+
paperJSComponent.paths.imageOverlays[this.id] = group
|
|
164
|
+
}
|
|
165
|
+
imageOverlayPath.opacity = this.opacity
|
|
166
|
+
handles.visible = isRotationHandleVisible
|
|
167
|
+
}
|
|
168
|
+
loadImageOverlay(url, corners) {
|
|
169
|
+
let rasterImageOverlay = new Paper.Raster({
|
|
170
|
+
source: url,
|
|
171
|
+
crossOrigin: 'Anonymous'
|
|
172
|
+
})
|
|
173
|
+
rasterImageOverlay.onLoad = () => {
|
|
174
|
+
this.applyRasterToCorners(rasterImageOverlay, corners)
|
|
175
|
+
}
|
|
176
|
+
rasterImageOverlay.data.angle = 0
|
|
177
|
+
rasterImageOverlay.data.type = 'imageOverlayRaster'
|
|
178
|
+
rasterImageOverlay.data.overlayId = this.id
|
|
179
|
+
rasterImageOverlay.data.url = url
|
|
180
|
+
return rasterImageOverlay
|
|
181
|
+
}
|
|
182
|
+
applyRasterToCorners(texture, corners = this.corners) {
|
|
183
|
+
//remove angle of texture
|
|
184
|
+
let textureAngle = texture.angle || 0
|
|
185
|
+
texture.rotate(-textureAngle)
|
|
186
|
+
|
|
187
|
+
//make texture the same size to fit corners
|
|
188
|
+
const textureWidth = texture.bounds.width
|
|
189
|
+
const textureHeight = texture.bounds.height
|
|
190
|
+
const frameWidth = getDistanceBetweenPoints(corners[1], corners[0])
|
|
191
|
+
const frameHeight = getDistanceBetweenPoints(corners[3], corners[0])
|
|
192
|
+
const center = multiplyVector(0.5, addVector(corners[0], corners[2]))
|
|
193
|
+
if (texture.bounds.width) {
|
|
194
|
+
var a = frameWidth / textureWidth
|
|
195
|
+
var b = 0
|
|
196
|
+
var c = 0
|
|
197
|
+
var d = frameHeight / textureHeight
|
|
198
|
+
texture.transform(new Paper.Matrix(a, b, c, d, 0, 0))
|
|
199
|
+
//translate to fit top left corner
|
|
200
|
+
var tx = center.x - texture.bounds.center.x
|
|
201
|
+
var ty = center.y - texture.bounds.center.y
|
|
202
|
+
texture.transform(new Paper.Matrix(1, 0, 0, 1, tx, ty))
|
|
203
|
+
//rotate
|
|
204
|
+
let angle = getAngleInDegFromCanvasVector(
|
|
205
|
+
substractVector(corners[0], corners[3])
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
texture.angle = angle
|
|
209
|
+
texture.rotate(angle)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
renderImageOverlayHandles(corners, rotateHandleVisible, group = null) {
|
|
213
|
+
let circleHandle
|
|
214
|
+
let hasPaths = !!group
|
|
215
|
+
let handles = group || new Paper.Group()
|
|
216
|
+
let u = normalize2DVector(substractVector(corners[1], corners[0]))
|
|
217
|
+
let v = normalize2DVector(substractVector(corners[0], corners[3]))
|
|
218
|
+
|
|
219
|
+
//rotation handle
|
|
220
|
+
let center = multiplyVector(0.5, addVector(corners[0], corners[2]))
|
|
221
|
+
|
|
222
|
+
let radius = vectorLength2D(substractVector(center, corners[0])) - 10
|
|
223
|
+
if (!hasPaths) {
|
|
224
|
+
circleHandle = new Paper.Path.Circle(center, radius)
|
|
225
|
+
circleHandle.fillColor = layerColors.imageOverlayHandle.fillColor
|
|
226
|
+
circleHandle.strokeWidth = layerColors.imageOverlayHandle.strokeWidth
|
|
227
|
+
circleHandle.strokeColor = layerColors.imageOverlayHandle.strokeColor
|
|
228
|
+
circleHandle.data.type = 'imageOverlayRotateHandle'
|
|
229
|
+
circleHandle.data.overlayId = this.id
|
|
230
|
+
circleHandle.radius = radius
|
|
231
|
+
handles.addChild(circleHandle)
|
|
232
|
+
} else {
|
|
233
|
+
circleHandle = handles.children[0]
|
|
234
|
+
let ratio = radius / circleHandle.radius
|
|
235
|
+
circleHandle.transform(new Paper.Matrix(ratio, 0, 0, ratio, 0, 0))
|
|
236
|
+
circleHandle.position = center
|
|
237
|
+
circleHandle.radius = radius
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
circleHandle.visible = rotateHandleVisible
|
|
241
|
+
|
|
242
|
+
//scale handle
|
|
243
|
+
for (let k = 0; k < 4; k++) {
|
|
244
|
+
let squareSize = 10
|
|
245
|
+
let squareHandleVertices = [
|
|
246
|
+
addVector(
|
|
247
|
+
addVector(corners[k], multiplyVector(squareSize / 2, u)),
|
|
248
|
+
multiplyVector(squareSize / 2, v)
|
|
249
|
+
),
|
|
250
|
+
addVector(
|
|
251
|
+
addVector(corners[k], multiplyVector(-squareSize / 2, u)),
|
|
252
|
+
multiplyVector(squareSize / 2, v)
|
|
253
|
+
),
|
|
254
|
+
addVector(
|
|
255
|
+
addVector(corners[k], multiplyVector(-squareSize / 2, u)),
|
|
256
|
+
multiplyVector(-squareSize / 2, v)
|
|
257
|
+
),
|
|
258
|
+
addVector(
|
|
259
|
+
addVector(corners[k], multiplyVector(squareSize / 2, u)),
|
|
260
|
+
multiplyVector(-squareSize / 2, v)
|
|
261
|
+
),
|
|
262
|
+
addVector(
|
|
263
|
+
addVector(corners[k], multiplyVector(squareSize / 2, u)),
|
|
264
|
+
multiplyVector(squareSize / 2, v)
|
|
265
|
+
)
|
|
266
|
+
]
|
|
267
|
+
let squareHandle
|
|
268
|
+
|
|
269
|
+
if (hasPaths) {
|
|
270
|
+
squareHandle = handles.children[k + 1]
|
|
271
|
+
squareHandle.position = corners[k]
|
|
272
|
+
//squareHandle.rotate()
|
|
273
|
+
for (let index in squareHandleVertices) {
|
|
274
|
+
let vertex = squareHandleVertices[index]
|
|
275
|
+
squareHandle.segments[index].point = vertex
|
|
276
|
+
}
|
|
277
|
+
} else {
|
|
278
|
+
squareHandle = new Paper.Path()
|
|
279
|
+
|
|
280
|
+
for (let vertex of squareHandleVertices) {
|
|
281
|
+
squareHandle.add(vertex)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
squareHandle.fillColor = layerColors.imageOverlayHandle.fillColor
|
|
285
|
+
squareHandle.strokeWidth = layerColors.imageOverlayHandle.strokeWidth
|
|
286
|
+
squareHandle.strokeColor = layerColors.imageOverlayHandle.strokeColor
|
|
287
|
+
squareHandle.data.type = 'handle'
|
|
288
|
+
squareHandle.data.index = k
|
|
289
|
+
|
|
290
|
+
handles.addChild(squareHandle)
|
|
291
|
+
}
|
|
292
|
+
squareHandle.visible = false
|
|
293
|
+
}
|
|
294
|
+
return handles
|
|
295
|
+
}
|
|
296
|
+
renderOnThreeJS(threeJSComponent) {}
|
|
297
|
+
serializeSettings() {
|
|
298
|
+
return {
|
|
299
|
+
hasScale: this.hasScale,
|
|
300
|
+
scaleParams: {
|
|
301
|
+
points: this.points,
|
|
302
|
+
distance: this.distance,
|
|
303
|
+
mmPerPx: this.mmPerPx
|
|
304
|
+
},
|
|
305
|
+
corners: this.corners,
|
|
306
|
+
version: this.version
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid'
|
|
2
|
+
import Item from '../Item/Item'
|
|
3
|
+
import {
|
|
4
|
+
multiplyVector,
|
|
5
|
+
addVector,
|
|
6
|
+
rotateTransformation,
|
|
7
|
+
substractVector,
|
|
8
|
+
getDistanceBetweenPoints,
|
|
9
|
+
getAngleInDegFromCanvasVector
|
|
10
|
+
} from '@eturnity/eturnity_maths'
|
|
11
|
+
import {
|
|
12
|
+
updateBufferRoofGeometry,
|
|
13
|
+
getBufferRoofGeometry
|
|
14
|
+
} from '../helper/render/geometryHandler'
|
|
15
|
+
import * as THREE from 'three'
|
|
16
|
+
import ProjectedMaterial from 'three-projected-material'
|
|
17
|
+
export default class Overlay extends Item {
|
|
18
|
+
constructor(overlay, emit) {
|
|
19
|
+
super(emit)
|
|
20
|
+
this.id = overlay.layouting_overlay_uuid
|
|
21
|
+
? overlay.layouting_overlay_uuid.toString()
|
|
22
|
+
: uuidv4()
|
|
23
|
+
this.actionsAvailable.push('setOpacity')
|
|
24
|
+
this.isActive = overlay.is_active
|
|
25
|
+
this.isReady = false
|
|
26
|
+
this.resources = overlay.resources
|
|
27
|
+
this.type = overlay.type
|
|
28
|
+
this.corners = overlay.settings.corners
|
|
29
|
+
this.placeHolderCorners = [
|
|
30
|
+
{ x: 10000, y: 7000 },
|
|
31
|
+
{ x: 10000, y: -7000 },
|
|
32
|
+
{ x: -10000, y: -7000 },
|
|
33
|
+
{ x: -10000, y: 7000 }
|
|
34
|
+
]
|
|
35
|
+
this.positionOffset = overlay.settings.positionOffset || {
|
|
36
|
+
x: 0,
|
|
37
|
+
y: 0,
|
|
38
|
+
z: 0
|
|
39
|
+
}
|
|
40
|
+
this.angleOffset = overlay.settings.angleOffset || 0
|
|
41
|
+
this.imageUrl = null
|
|
42
|
+
this.imageOverlayProjectionMaterial = null
|
|
43
|
+
this.settings = overlay.settings
|
|
44
|
+
this.version = this.settings.version || 0
|
|
45
|
+
this.overlayProjectionCamera = new THREE.OrthographicCamera(
|
|
46
|
+
-20,
|
|
47
|
+
20,
|
|
48
|
+
20,
|
|
49
|
+
-20,
|
|
50
|
+
1,
|
|
51
|
+
1000
|
|
52
|
+
)
|
|
53
|
+
this.backgroundGeometry = null
|
|
54
|
+
this.overlayProjectionCamera.up.set(0, 1, 0)
|
|
55
|
+
this.isSelected = false
|
|
56
|
+
this.isReadyCallback = []
|
|
57
|
+
}
|
|
58
|
+
getCenter() {
|
|
59
|
+
let center = multiplyVector(
|
|
60
|
+
0.5,
|
|
61
|
+
addVector(this.corners[0], this.corners[2])
|
|
62
|
+
)
|
|
63
|
+
return center
|
|
64
|
+
}
|
|
65
|
+
setOpacity(opacity) {
|
|
66
|
+
this.opacity = opacity
|
|
67
|
+
this.emit('item-updated', this)
|
|
68
|
+
}
|
|
69
|
+
translateBy(shift) {
|
|
70
|
+
this.version++
|
|
71
|
+
let newCorners = []
|
|
72
|
+
for (let cornerIndex in this.corners) {
|
|
73
|
+
let corner = this.corners[cornerIndex]
|
|
74
|
+
newCorners[cornerIndex] = {}
|
|
75
|
+
newCorners[cornerIndex].x = corner.x + shift.x
|
|
76
|
+
newCorners[cornerIndex].y = corner.y + shift.y
|
|
77
|
+
newCorners[cornerIndex].z = corner.z + shift.z
|
|
78
|
+
}
|
|
79
|
+
this.positionOffset.x += shift.x
|
|
80
|
+
this.positionOffset.y += shift.y
|
|
81
|
+
this.positionOffset.z += shift.z
|
|
82
|
+
this.corners = newCorners
|
|
83
|
+
this.emit('item-updated', this)
|
|
84
|
+
}
|
|
85
|
+
translate(newPositionOffset) {
|
|
86
|
+
this.version++
|
|
87
|
+
let newCorners = []
|
|
88
|
+
let shift = substractVector(newPositionOffset, this.positionOffset)
|
|
89
|
+
for (let cornerIndex in this.corners) {
|
|
90
|
+
let corner = this.corners[cornerIndex]
|
|
91
|
+
newCorners[cornerIndex] = {}
|
|
92
|
+
newCorners[cornerIndex].x = corner.x + shift.x
|
|
93
|
+
newCorners[cornerIndex].y = corner.y + shift.y
|
|
94
|
+
newCorners[cornerIndex].z = corner.z + shift.z
|
|
95
|
+
}
|
|
96
|
+
this.positionOffset = newPositionOffset
|
|
97
|
+
this.corners = newCorners
|
|
98
|
+
this.emit('item-updated', this)
|
|
99
|
+
}
|
|
100
|
+
rotateBy(deltaAngle) {
|
|
101
|
+
this.version++
|
|
102
|
+
const newCorners = this.corners
|
|
103
|
+
let center = multiplyVector(
|
|
104
|
+
0.5,
|
|
105
|
+
addVector(this.corners[0], this.corners[2])
|
|
106
|
+
)
|
|
107
|
+
for (let k in this.corners) {
|
|
108
|
+
let corner = this.corners[k]
|
|
109
|
+
newCorners[k] = rotateTransformation(corner, deltaAngle, center)
|
|
110
|
+
newCorners[k].z = this.corners[k].z
|
|
111
|
+
}
|
|
112
|
+
this.angleOffset += deltaAngle
|
|
113
|
+
this.corners = newCorners
|
|
114
|
+
this.emit('item-updated', this)
|
|
115
|
+
}
|
|
116
|
+
rotate(newAngle) {
|
|
117
|
+
this.version++
|
|
118
|
+
const newCorners = this.corners
|
|
119
|
+
let center = multiplyVector(
|
|
120
|
+
0.5,
|
|
121
|
+
addVector(this.corners[0], this.corners[2])
|
|
122
|
+
)
|
|
123
|
+
for (let k in this.corners) {
|
|
124
|
+
let corner = this.corners[k]
|
|
125
|
+
newCorners[k] = rotateTransformation(
|
|
126
|
+
corner,
|
|
127
|
+
newAngle - this.angleOffset,
|
|
128
|
+
center
|
|
129
|
+
)
|
|
130
|
+
newCorners[k].z = this.corners[k].z
|
|
131
|
+
}
|
|
132
|
+
this.angleOffset = newAngle
|
|
133
|
+
this.corners = newCorners
|
|
134
|
+
this.emit('item-updated', this)
|
|
135
|
+
}
|
|
136
|
+
async getProjectionMaterial() {
|
|
137
|
+
if (!this.isReady || !this.corners) {
|
|
138
|
+
return null
|
|
139
|
+
}
|
|
140
|
+
const url = this.imageUrl
|
|
141
|
+
return new Promise((resolve) => {
|
|
142
|
+
if (this.imageOverlayProjectionMaterial) {
|
|
143
|
+
const cameraChanged = this.setImageOverlayCameraPosition()
|
|
144
|
+
if (cameraChanged) {
|
|
145
|
+
this.imageOverlayProjectionMaterial.userData.version++
|
|
146
|
+
}
|
|
147
|
+
this.imageOverlayProjectionMaterial.opacity = this.opacity
|
|
148
|
+
resolve(this.imageOverlayProjectionMaterial)
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
const loader = new THREE.TextureLoader()
|
|
152
|
+
loader.load(url, (texture) => {
|
|
153
|
+
this.setImageOverlayCameraPosition()
|
|
154
|
+
let imageOverlayProjectionMaterial = new ProjectedMaterial({
|
|
155
|
+
camera: this.overlayProjectionCamera,
|
|
156
|
+
texture,
|
|
157
|
+
transparent: true,
|
|
158
|
+
side: THREE.DoubleSide
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
imageOverlayProjectionMaterial.userData = {}
|
|
162
|
+
imageOverlayProjectionMaterial.userData.type = 'overlayMaterial'
|
|
163
|
+
imageOverlayProjectionMaterial.userData.version = 0
|
|
164
|
+
imageOverlayProjectionMaterial.priority = 30
|
|
165
|
+
imageOverlayProjectionMaterial.userData.url = url
|
|
166
|
+
imageOverlayProjectionMaterial.opacity = this.opacity
|
|
167
|
+
this.imageOverlayProjectionMaterial = imageOverlayProjectionMaterial
|
|
168
|
+
resolve(imageOverlayProjectionMaterial)
|
|
169
|
+
})
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
getBackgroundGeometry() {
|
|
173
|
+
const outline = this.corners.map((p) => {
|
|
174
|
+
return { ...p, z: 100 }
|
|
175
|
+
})
|
|
176
|
+
if (this.backgroundGeometry) {
|
|
177
|
+
this.backgroundGeometry = updateBufferRoofGeometry(
|
|
178
|
+
outline,
|
|
179
|
+
[],
|
|
180
|
+
this.backgroundGeometry
|
|
181
|
+
)
|
|
182
|
+
} else {
|
|
183
|
+
this.backgroundGeometry = getBufferRoofGeometry(outline, [])
|
|
184
|
+
}
|
|
185
|
+
return this.backgroundGeometry
|
|
186
|
+
}
|
|
187
|
+
setImageOverlayCameraPosition() {
|
|
188
|
+
let cameraChanged = false
|
|
189
|
+
const boxCenter = multiplyVector(
|
|
190
|
+
0.5,
|
|
191
|
+
addVector(this.corners[0], this.corners[2])
|
|
192
|
+
)
|
|
193
|
+
boxCenter.z = 0
|
|
194
|
+
const boxSize = {
|
|
195
|
+
x: getDistanceBetweenPoints(this.corners[0], this.corners[1]) / 1000,
|
|
196
|
+
y: getDistanceBetweenPoints(this.corners[1], this.corners[2]) / 1000,
|
|
197
|
+
z: 0
|
|
198
|
+
}
|
|
199
|
+
if (
|
|
200
|
+
this.overlayProjectionCamera.left != -boxSize.x / 2 ||
|
|
201
|
+
this.overlayProjectionCamera.right != boxSize.x / 2 ||
|
|
202
|
+
this.overlayProjectionCamera.top != boxSize.y / 2 ||
|
|
203
|
+
this.overlayProjectionCamera.bottom != -boxSize.y / 2
|
|
204
|
+
) {
|
|
205
|
+
cameraChanged = true
|
|
206
|
+
}
|
|
207
|
+
this.overlayProjectionCamera.left = -boxSize.x / 2
|
|
208
|
+
this.overlayProjectionCamera.right = boxSize.x / 2
|
|
209
|
+
this.overlayProjectionCamera.top = boxSize.y / 2
|
|
210
|
+
this.overlayProjectionCamera.bottom = -boxSize.y / 2
|
|
211
|
+
|
|
212
|
+
let zAngle = getAngleInDegFromCanvasVector(
|
|
213
|
+
substractVector(this.corners[3], this.corners[0])
|
|
214
|
+
)
|
|
215
|
+
if (this.overlayProjectionCamera.rotation.z != (zAngle * Math.PI) / 180) {
|
|
216
|
+
cameraChanged = true
|
|
217
|
+
}
|
|
218
|
+
this.overlayProjectionCamera.rotation.set(0, 0, (zAngle * Math.PI) / 180)
|
|
219
|
+
if (
|
|
220
|
+
this.overlayProjectionCamera.position.x != boxCenter.x / 1000 ||
|
|
221
|
+
this.overlayProjectionCamera.position.y != boxCenter.y / 1000 ||
|
|
222
|
+
this.overlayProjectionCamera.position.z != boxCenter.z / 1000 + 50
|
|
223
|
+
) {
|
|
224
|
+
cameraChanged = true
|
|
225
|
+
}
|
|
226
|
+
this.overlayProjectionCamera.position.set(
|
|
227
|
+
boxCenter.x / 1000,
|
|
228
|
+
boxCenter.y / 1000,
|
|
229
|
+
boxCenter.z / 1000 + 50
|
|
230
|
+
)
|
|
231
|
+
this.overlayProjectionCamera.updateProjectionMatrix()
|
|
232
|
+
return cameraChanged
|
|
233
|
+
}
|
|
234
|
+
serialize() {
|
|
235
|
+
const serializedOverlay = {
|
|
236
|
+
layouting_overlay_uuid: this.id,
|
|
237
|
+
settings: {
|
|
238
|
+
...this.settings,
|
|
239
|
+
positionOffset: this.positionOffset,
|
|
240
|
+
angleOffset: this.angleOffset,
|
|
241
|
+
...this.serializeSettings()
|
|
242
|
+
},
|
|
243
|
+
type: this.type,
|
|
244
|
+
is_active: this.isActive,
|
|
245
|
+
resources: this.resources
|
|
246
|
+
}
|
|
247
|
+
return serializedOverlay
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
renderOnPaperJS(paperJSComponent) {}
|
|
251
|
+
renderOnThreeJS(threeJSComponent) {}
|
|
252
|
+
serializeSettings() {
|
|
253
|
+
return {}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Overlay from './Overlay'
|
|
2
|
+
import AirTeamOverlay from './AirTeamOverlay'
|
|
3
|
+
import ImageOverlay from './ImageOverlay'
|
|
4
|
+
|
|
5
|
+
const OverlayFactory = {
|
|
6
|
+
createOverlay(serializedOverlay, emit, origin = { lat: null, lng: null }) {
|
|
7
|
+
let overlayInstance
|
|
8
|
+
if (serializedOverlay.type == 'airteam') {
|
|
9
|
+
overlayInstance = new AirTeamOverlay(serializedOverlay, emit, origin)
|
|
10
|
+
} else if (serializedOverlay.type == 'image_overlay') {
|
|
11
|
+
overlayInstance = new ImageOverlay(serializedOverlay, emit)
|
|
12
|
+
} else {
|
|
13
|
+
overlayInstance = new Overlay(serializedOverlay, emit)
|
|
14
|
+
}
|
|
15
|
+
return overlayInstance
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default OverlayFactory
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import OverlayFactory from './OverlayFactory'
|
|
2
|
+
import LayerManager from '../Layer/Layer'
|
|
3
|
+
class OverlayLayer extends LayerManager {
|
|
4
|
+
constructor() {
|
|
5
|
+
super()
|
|
6
|
+
this.id = Math.random().toString(36) // Unique ID for instance
|
|
7
|
+
this.availableEvents.push(
|
|
8
|
+
'items-updated',
|
|
9
|
+
'overlay-scale-updated',
|
|
10
|
+
'overlay-is-ready',
|
|
11
|
+
'overlay-offset-position-error',
|
|
12
|
+
'overlay-three-loaded'
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
addOrUpdateSerializedItems(
|
|
16
|
+
serializedOverlays,
|
|
17
|
+
origin = { lat: null, lng: null }
|
|
18
|
+
) {
|
|
19
|
+
let addedOverlays = []
|
|
20
|
+
serializedOverlays.forEach((serializedOverlay) => {
|
|
21
|
+
let overlayInstance = OverlayFactory.createOverlay(
|
|
22
|
+
serializedOverlay,
|
|
23
|
+
(...arg) => {
|
|
24
|
+
return this.emit.call(this, ...arg)
|
|
25
|
+
},
|
|
26
|
+
origin
|
|
27
|
+
)
|
|
28
|
+
addedOverlays.push(overlayInstance)
|
|
29
|
+
this.addOrUpdateItem(overlayInstance)
|
|
30
|
+
})
|
|
31
|
+
return addedOverlays
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const OverlayLayerInstance = new OverlayLayer()
|
|
36
|
+
export default OverlayLayerInstance
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
updateComputedGeometryPolygon,
|
|
16
16
|
normalizeVector
|
|
17
17
|
} from '@eturnity/eturnity_maths'
|
|
18
|
-
|
|
18
|
+
import OverlayLayer from '../Overlay/OverlayLayer.js'
|
|
19
19
|
import threeMixin from '../helper/threeMixin'
|
|
20
20
|
|
|
21
21
|
export default {
|
|
@@ -34,6 +34,10 @@ export default {
|
|
|
34
34
|
beforeDestroy() {
|
|
35
35
|
clearInterval(this.intervalId)
|
|
36
36
|
cancelAnimationFrame(this.animationFrameId)
|
|
37
|
+
OverlayLayer.removeEventListener(
|
|
38
|
+
'overlay-is-ready',
|
|
39
|
+
this.updateOverlayRendering
|
|
40
|
+
)
|
|
37
41
|
},
|
|
38
42
|
mixins: [threeMixin],
|
|
39
43
|
async mounted() {
|
|
@@ -72,8 +76,12 @@ export default {
|
|
|
72
76
|
this.setCamera(polygon, this.view_mode)
|
|
73
77
|
}
|
|
74
78
|
this.isReady.geometry = true
|
|
75
|
-
this.render()
|
|
76
79
|
this.intervalId = setInterval(() => this.render(), 500)
|
|
80
|
+
OverlayLayer.addEventListener(
|
|
81
|
+
'overlay-is-ready',
|
|
82
|
+
this.updateOverlayRendering
|
|
83
|
+
)
|
|
84
|
+
this.render()
|
|
77
85
|
},
|
|
78
86
|
computed: {
|
|
79
87
|
...mapState({
|
|
@@ -190,8 +198,11 @@ export default {
|
|
|
190
198
|
distance =
|
|
191
199
|
5 + objectRadius / Math.sin(((this.camera.fov / 2) * Math.PI) / 180)
|
|
192
200
|
}
|
|
193
|
-
|
|
194
|
-
|
|
201
|
+
try {
|
|
202
|
+
polygonRef = updateComputedGeometryPolygon(polygonRef)
|
|
203
|
+
} catch (err) {
|
|
204
|
+
console.error(err)
|
|
205
|
+
}
|
|
195
206
|
const targetVector = polygonRef.meanPoint
|
|
196
207
|
//const target=[targetVector.x/1000,targetVector.y/1000,targetVector.z/1000]
|
|
197
208
|
let cameraMoveVector = { x: 0, y: 0, z: 0 }
|
|
@@ -292,11 +303,11 @@ export default {
|
|
|
292
303
|
watch: {
|
|
293
304
|
isReady: {
|
|
294
305
|
handler() {
|
|
306
|
+
const overlayReady = OverlayLayer.getItems().length == 0 || this.isReady.overlay
|
|
295
307
|
if (
|
|
296
308
|
this.isReady.texturesToLoad == this.isReady.texturesLoaded &&
|
|
297
309
|
this.isReady.geometry &&
|
|
298
|
-
|
|
299
|
-
this.isReady.camera
|
|
310
|
+
overlayReady
|
|
300
311
|
) {
|
|
301
312
|
var event = new CustomEvent('screenshotable')
|
|
302
313
|
// dispatch the custom event
|