@eturnity/eturnity_3d 0.0.4
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/.babelrc +3 -0
- package/.env +0 -0
- package/.eslintrc +18 -0
- package/.eslintrc.json +18 -0
- package/.prettierrc +7 -0
- package/Dockerfile +17 -0
- package/README.md +18 -0
- package/bitbucket-pipelines.yml +681 -0
- package/dist/assets/images/panels/longiSolarLR4_60HPH_350M.png +0 -0
- package/dist/assets/images/panels/longiSolarLR4_60HPH_370M.png +0 -0
- package/dist/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw copy.png +0 -0
- package/dist/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
- package/dist/assets/images/panels/uv.png +0 -0
- package/dist/assets/panels/longiSolarLR4_60HPH_350M.png +0 -0
- package/dist/assets/panels/longiSolarLR4_60HPH_370M.png +0 -0
- package/dist/assets/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
- package/dist/assets/panels/uv.png +0 -0
- package/dist/assets/theme.js +43 -0
- package/dist/assets/vue.svg +1 -0
- package/dist/css/main.1f8fe45d.css +1 -0
- package/dist/img/longiSolarLR4_60HPH_350M.85a84b2e.png +0 -0
- package/dist/img/longiSolarLR4_60HPH_370M.bf6b1f4e.png +0 -0
- package/dist/img/reneSola_Virtus_2_JC320S_24_Bbw.8b1892e0.png +0 -0
- package/dist/index.html +26 -0
- package/dist/main.js +60230 -0
- package/dist/main.js.map +1 -0
- package/dist/vite.svg +1 -0
- package/docker_conf/nginx/nginx.conf +16 -0
- package/index.html +26 -0
- package/package.json +71 -0
- package/postcss.config.js +1 -0
- package/preview.html +55 -0
- package/public/assets/images/panels/longiSolarLR4_60HPH_350M.png +0 -0
- package/public/assets/images/panels/longiSolarLR4_60HPH_370M.png +0 -0
- package/public/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw copy.png +0 -0
- package/public/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
- package/public/assets/images/panels/uv.png +0 -0
- package/public/assets/panels/longiSolarLR4_60HPH_350M.png +0 -0
- package/public/assets/panels/longiSolarLR4_60HPH_370M.png +0 -0
- package/public/assets/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
- package/public/assets/panels/uv.png +0 -0
- package/public/assets/theme.js +43 -0
- package/public/assets/vue.svg +1 -0
- package/public/vite.svg +1 -0
- package/server.js +17 -0
- package/src/App.vue +28 -0
- package/src/assets/images/panels/longiSolarLR4_60HPH_350M.png +0 -0
- package/src/assets/images/panels/longiSolarLR4_60HPH_370M.png +0 -0
- package/src/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw copy.png +0 -0
- package/src/assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw.png +0 -0
- package/src/assets/images/panels/uv.png +0 -0
- package/src/assets/images/white_tile.png +0 -0
- package/src/assets/theme.js +43 -0
- package/src/components/ThreeCanvasViewer.vue +247 -0
- package/src/config.js +104 -0
- package/src/functions.js +2 -0
- package/src/helper/DFS.js +80 -0
- package/src/helper/MapView.js +253 -0
- package/src/helper/UpdateRoofModuleFieldRelations.js +119 -0
- package/src/helper/UpdateRoofObstacleRelations.js +86 -0
- package/src/helper/clearThreeObjects.js +21 -0
- package/src/helper/customProvider.js +57 -0
- package/src/helper/geometryHandler.js +606 -0
- package/src/helper/graphCreation.js +43 -0
- package/src/helper/materials.js +55 -0
- package/src/helper/projectedMaterial.js +502 -0
- package/src/helper/renderMixin.js +1132 -0
- package/src/helper/threeMixin.js +171 -0
- package/src/main.js +28 -0
- package/src/store/AddMargin.js +107 -0
- package/src/store/hydrateData.js +209 -0
- package/src/store/nodesEdgesCreation.js +216 -0
- package/src/store/store.js +10 -0
- package/src/store/three-d-module.js +142 -0
- package/src/style.css +96 -0
- package/src/utils/layers.js +265 -0
- package/src/utils/leaflet-config.service.js +67 -0
- package/vue.config.js +46 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
import * as THREE from 'three'
|
|
2
|
+
import { defaultBaseHeight } from '../config'
|
|
3
|
+
import earcut from 'earcut'
|
|
4
|
+
import {
|
|
5
|
+
verticalProjectionOnPlane,
|
|
6
|
+
addVector,
|
|
7
|
+
multiplyVector,
|
|
8
|
+
getNormalVectorFrom3Points,
|
|
9
|
+
hasNaN,
|
|
10
|
+
getDistanceBetweenPoints,
|
|
11
|
+
intersectOutlines
|
|
12
|
+
} from '@eturnity/eturnity_maths'
|
|
13
|
+
|
|
14
|
+
export function getTriangleVerticesFromOutline(
|
|
15
|
+
polygonOutline,
|
|
16
|
+
holesOutlines = []
|
|
17
|
+
) {
|
|
18
|
+
if(polygonOutline.length==0){
|
|
19
|
+
return new Float32Array([])
|
|
20
|
+
}
|
|
21
|
+
var dataVertices = polygonOutline
|
|
22
|
+
.map((p) => {
|
|
23
|
+
return [p.x / 1000, p.y / 1000, p.z / 1000]
|
|
24
|
+
})
|
|
25
|
+
.flat()
|
|
26
|
+
let holesStartingIndexes = []
|
|
27
|
+
let holesVertices=[]
|
|
28
|
+
//we group building and wall vertices and give the starting index of each obstacles.
|
|
29
|
+
if (holesOutlines.length > 0) {
|
|
30
|
+
const HoleIndexOffset = (dataVertices.length / 3)+1
|
|
31
|
+
holesStartingIndexes.push(HoleIndexOffset)
|
|
32
|
+
let lastIndex=HoleIndexOffset
|
|
33
|
+
for(let k=0;k<holesOutlines.length-1;k++){
|
|
34
|
+
let newIndex=lastIndex+(holesOutlines[k].length)
|
|
35
|
+
holesStartingIndexes.push(newIndex)
|
|
36
|
+
lastIndex=newIndex
|
|
37
|
+
}
|
|
38
|
+
holesStartingIndexes=[...new Set(holesStartingIndexes)]
|
|
39
|
+
holesVertices = holesOutlines
|
|
40
|
+
.map((holeOutline) => {
|
|
41
|
+
return holeOutline.map((p) => {
|
|
42
|
+
return [p.x / 1000, p.y / 1000, p.z / 1000]
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
.flat().flat()
|
|
46
|
+
}
|
|
47
|
+
let lastPoint = polygonOutline[polygonOutline.length - 1]
|
|
48
|
+
let lastVertex = [lastPoint.x / 1000, lastPoint.y / 1000, lastPoint.z / 1000]
|
|
49
|
+
dataVertices.push(...lastVertex)
|
|
50
|
+
dataVertices.push(...holesVertices)
|
|
51
|
+
|
|
52
|
+
var triangles = []
|
|
53
|
+
try{
|
|
54
|
+
triangles=earcut(dataVertices, holesStartingIndexes, 3)
|
|
55
|
+
}catch(err){
|
|
56
|
+
console.error(err)
|
|
57
|
+
}
|
|
58
|
+
const triangleVertices = []
|
|
59
|
+
triangles.forEach((index) => {
|
|
60
|
+
triangleVertices.push(
|
|
61
|
+
dataVertices[3 * index],
|
|
62
|
+
dataVertices[3 * index + 1],
|
|
63
|
+
dataVertices[3 * index + 2]
|
|
64
|
+
)
|
|
65
|
+
})
|
|
66
|
+
return triangleVertices
|
|
67
|
+
}
|
|
68
|
+
export function updateBufferRoofGeometry(polygonOutline,holesOutline=[],geometry) {
|
|
69
|
+
//Calcul of triangles using cutear algo
|
|
70
|
+
const triangleVertices = getTriangleVerticesFromOutline(polygonOutline,holesOutline)
|
|
71
|
+
if(hasNaN(triangleVertices)){return null}
|
|
72
|
+
const vertices = new Float32Array(triangleVertices)
|
|
73
|
+
// itemSize = 3 because there are 3 values (components) per vertex
|
|
74
|
+
if(geometry.attributes.position && geometry.attributes.position.array.length>=vertices.length){
|
|
75
|
+
let positions=geometry.attributes.position.array
|
|
76
|
+
for(let k in vertices){
|
|
77
|
+
positions[k]=vertices[k]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
}else{
|
|
81
|
+
geometry.dispose()
|
|
82
|
+
geometry=null
|
|
83
|
+
geometry = new THREE.BufferGeometry()
|
|
84
|
+
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
|
|
85
|
+
}
|
|
86
|
+
geometry.setDrawRange( 0, vertices.length/3 );
|
|
87
|
+
geometry.computeVertexNormals()
|
|
88
|
+
geometry.attributes.position.needsUpdate = true;
|
|
89
|
+
return geometry
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function getBufferRoofGeometry(polygonOutline,holesOutline=[]) {
|
|
93
|
+
const geometry = new THREE.BufferGeometry()
|
|
94
|
+
//Calcul of triangles using cutear algo
|
|
95
|
+
const triangleVertices = getTriangleVerticesFromOutline(polygonOutline,holesOutline)
|
|
96
|
+
if(hasNaN(triangleVertices)){return null}
|
|
97
|
+
const vertices = new Float32Array(triangleVertices)
|
|
98
|
+
// itemSize = 3 because there are 3 values (components) per vertex
|
|
99
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
|
|
100
|
+
geometry.computeVertexNormals()
|
|
101
|
+
return geometry
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
export function getWallVertices(polygon){
|
|
107
|
+
const length = polygon.outline.length
|
|
108
|
+
const trianglesVertices = []
|
|
109
|
+
polygon.outline.forEach((p_up_0, index) => {
|
|
110
|
+
const p_up_1 = polygon.outline[(index + 1) % length]
|
|
111
|
+
const p_bottom_0 = { ...p_up_0, z: 0 }
|
|
112
|
+
const p_bottom_1 = { ...p_up_1, z: 0 }
|
|
113
|
+
|
|
114
|
+
trianglesVertices.push(
|
|
115
|
+
...[
|
|
116
|
+
p_up_0.x / 1000,
|
|
117
|
+
p_up_0.y / 1000,
|
|
118
|
+
p_up_0.z / 1000,
|
|
119
|
+
p_up_1.x / 1000,
|
|
120
|
+
p_up_1.y / 1000,
|
|
121
|
+
p_up_1.z / 1000,
|
|
122
|
+
p_bottom_0.x / 1000,
|
|
123
|
+
p_bottom_0.y / 1000,
|
|
124
|
+
p_bottom_0.z / 1000,
|
|
125
|
+
p_up_1.x / 1000,
|
|
126
|
+
p_up_1.y / 1000,
|
|
127
|
+
p_up_1.z / 1000,
|
|
128
|
+
p_bottom_0.x / 1000,
|
|
129
|
+
p_bottom_0.y / 1000,
|
|
130
|
+
p_bottom_0.z / 1000,
|
|
131
|
+
p_bottom_1.x / 1000,
|
|
132
|
+
p_bottom_1.y / 1000,
|
|
133
|
+
p_bottom_1.z / 1000
|
|
134
|
+
]
|
|
135
|
+
)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
polygon.holes.forEach((hole)=>{
|
|
139
|
+
let obstacleWallOutline=intersectOutlines(hole.outline, polygon.outline)[0]||[]
|
|
140
|
+
obstacleWallOutline=obstacleWallOutline.map(p=>{
|
|
141
|
+
return {
|
|
142
|
+
...p,
|
|
143
|
+
z:verticalProjectionOnPlane(p,polygon.normalVector,polygon.flatOutline[0]).z
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
const lengthHole = obstacleWallOutline.length
|
|
147
|
+
obstacleWallOutline.forEach((p_up_0, index) => {
|
|
148
|
+
const p_up_1 = obstacleWallOutline[(index + 1) % lengthHole]
|
|
149
|
+
const p_bottom_0 = { ...p_up_0, z: 0 }
|
|
150
|
+
const p_bottom_1 = { ...p_up_1, z: 0 }
|
|
151
|
+
|
|
152
|
+
trianglesVertices.push(
|
|
153
|
+
...[
|
|
154
|
+
p_up_0.x / 1000,
|
|
155
|
+
p_up_0.y / 1000,
|
|
156
|
+
p_up_0.z / 1000,
|
|
157
|
+
p_up_1.x / 1000,
|
|
158
|
+
p_up_1.y / 1000,
|
|
159
|
+
p_up_1.z / 1000,
|
|
160
|
+
p_bottom_0.x / 1000,
|
|
161
|
+
p_bottom_0.y / 1000,
|
|
162
|
+
p_bottom_0.z / 1000,
|
|
163
|
+
p_up_1.x / 1000,
|
|
164
|
+
p_up_1.y / 1000,
|
|
165
|
+
p_up_1.z / 1000,
|
|
166
|
+
p_bottom_0.x / 1000,
|
|
167
|
+
p_bottom_0.y / 1000,
|
|
168
|
+
p_bottom_0.z / 1000,
|
|
169
|
+
p_bottom_1.x / 1000,
|
|
170
|
+
p_bottom_1.y / 1000,
|
|
171
|
+
p_bottom_1.z / 1000
|
|
172
|
+
]
|
|
173
|
+
)
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
if(hasNaN(trianglesVertices)){return null}
|
|
177
|
+
const vertices = new Float32Array(trianglesVertices)
|
|
178
|
+
return vertices
|
|
179
|
+
}
|
|
180
|
+
export function updateBufferWallGeometry(polygon,geometry) {
|
|
181
|
+
//geometry = new THREE.BufferGeometry()
|
|
182
|
+
//Calcul of triangles using cutear algo
|
|
183
|
+
const vertices=getWallVertices(polygon)
|
|
184
|
+
// itemSize = 3 because there are 3 values (components) per vertex
|
|
185
|
+
|
|
186
|
+
if(geometry.attributes.position && geometry.attributes.position.array.length>=vertices.length){
|
|
187
|
+
let positions=geometry.attributes.position.array
|
|
188
|
+
for(let k in vertices){
|
|
189
|
+
positions[k]=vertices[k]
|
|
190
|
+
}
|
|
191
|
+
geometry.setDrawRange( 0, vertices.length/3 );
|
|
192
|
+
}else{
|
|
193
|
+
geometry.dispose()
|
|
194
|
+
geometry=null
|
|
195
|
+
geometry = new THREE.BufferGeometry()
|
|
196
|
+
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
|
|
197
|
+
}
|
|
198
|
+
geometry.computeVertexNormals()
|
|
199
|
+
geometry.attributes.position.needsUpdate = true;
|
|
200
|
+
return geometry
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function getBufferWallGeometry(polygon) {
|
|
204
|
+
const geometry = new THREE.BufferGeometry()
|
|
205
|
+
//Calcul of triangles using cutear algo
|
|
206
|
+
const vertices=getWallVertices(polygon)
|
|
207
|
+
// itemSize = 3 because there are 3 values (components) per vertex
|
|
208
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
|
|
209
|
+
geometry.computeVertexNormals()
|
|
210
|
+
|
|
211
|
+
return geometry
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function getBufferObstacleGeometry(obstaclePolygon, roofPolygon) {
|
|
215
|
+
let obstacleHeight
|
|
216
|
+
if(obstaclePolygon.isParallel){
|
|
217
|
+
obstacleHeight = parseInt(obstaclePolygon.height || 0)
|
|
218
|
+
}else{
|
|
219
|
+
obstacleHeight = parseInt(obstaclePolygon.heightReference + obstaclePolygon.height || 0)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
//get lowest verticalProjection
|
|
223
|
+
const normalVector = roofPolygon.normalVector
|
|
224
|
+
const passByPoint = roofPolygon.flatOutline[0]
|
|
225
|
+
|
|
226
|
+
// const minHeight = Math.min(
|
|
227
|
+
// ...obstaclePolygon.outline.map(
|
|
228
|
+
// (p) => verticalProjectionOnPlane(p, normalVector, passByPoint).z
|
|
229
|
+
// )
|
|
230
|
+
// )
|
|
231
|
+
// const topHeight = minHeight + obstacleHeight
|
|
232
|
+
const topHeight = obstacleHeight
|
|
233
|
+
|
|
234
|
+
const geometry = new THREE.BufferGeometry()
|
|
235
|
+
const cropedHoleOutline=intersectOutlines(obstaclePolygon.outline, roofPolygon.outline)[0] || []
|
|
236
|
+
|
|
237
|
+
//Calcul of triangles using cutear algo
|
|
238
|
+
const trianglesVertices = []
|
|
239
|
+
const obstacleOutlineTop = []
|
|
240
|
+
cropedHoleOutline.forEach((p) => {
|
|
241
|
+
const p_bottom_0 = verticalProjectionOnPlane(p, normalVector, passByPoint)
|
|
242
|
+
|
|
243
|
+
let p_up_0
|
|
244
|
+
if (!obstaclePolygon.isParallel) {
|
|
245
|
+
p_up_0 = { ...p_bottom_0, z: topHeight }
|
|
246
|
+
} else {
|
|
247
|
+
const vectorFromBottomToTop = multiplyVector(obstacleHeight, {
|
|
248
|
+
x: 0,
|
|
249
|
+
y: 0,
|
|
250
|
+
z: 1
|
|
251
|
+
})
|
|
252
|
+
p_up_0 = addVector(p_bottom_0, vectorFromBottomToTop)
|
|
253
|
+
}
|
|
254
|
+
obstacleOutlineTop.push(p_up_0)
|
|
255
|
+
})
|
|
256
|
+
trianglesVertices.push(...getTriangleVerticesFromOutline(obstacleOutlineTop))
|
|
257
|
+
|
|
258
|
+
if(hasNaN(trianglesVertices)){return null}
|
|
259
|
+
const vertices = new Float32Array(trianglesVertices)
|
|
260
|
+
// itemSize = 3 because there are 3 values (components) per vertex
|
|
261
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
|
|
262
|
+
geometry.computeVertexNormals()
|
|
263
|
+
return geometry
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function getBufferObstacleSideGeometry(obstaclePolygon, roofPolygon) {
|
|
267
|
+
let obstacleHeight
|
|
268
|
+
if(obstaclePolygon.isParallel){
|
|
269
|
+
obstacleHeight = parseInt(obstaclePolygon.height || 0)
|
|
270
|
+
}else{
|
|
271
|
+
obstacleHeight = parseInt(obstaclePolygon.heightReference + obstaclePolygon.height || 0)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const normalVector = roofPolygon.normalVector
|
|
275
|
+
const passByPoint = roofPolygon.flatOutline[0]
|
|
276
|
+
|
|
277
|
+
// const minHeight = Math.min(
|
|
278
|
+
// ...obstaclePolygon.outline.map(
|
|
279
|
+
// (p) => verticalProjectionOnPlane(p, normalVector, passByPoint).z
|
|
280
|
+
// )
|
|
281
|
+
// )
|
|
282
|
+
// const topHeight = minHeight + obstacleHeight
|
|
283
|
+
const topHeight = obstacleHeight
|
|
284
|
+
|
|
285
|
+
const geometry = new THREE.BufferGeometry()
|
|
286
|
+
const cropedHoleOutline=intersectOutlines(obstaclePolygon.outline, roofPolygon.outline)[0] || []
|
|
287
|
+
//Calcul of triangles using cutear algo
|
|
288
|
+
const obstacleLength = cropedHoleOutline.length
|
|
289
|
+
const trianglesVertices = []
|
|
290
|
+
const obstacleOutlineTop = []
|
|
291
|
+
cropedHoleOutline.forEach((p, index) => {
|
|
292
|
+
const p_bottom_0 = verticalProjectionOnPlane(p, normalVector, passByPoint)
|
|
293
|
+
const p_bottom_1 = verticalProjectionOnPlane(
|
|
294
|
+
cropedHoleOutline[(index + 1) % obstacleLength],
|
|
295
|
+
normalVector,
|
|
296
|
+
passByPoint
|
|
297
|
+
)
|
|
298
|
+
let p_up_0
|
|
299
|
+
let p_up_1
|
|
300
|
+
if (!obstaclePolygon.isParallel) {
|
|
301
|
+
p_up_0 = { ...p_bottom_0, z: topHeight }
|
|
302
|
+
p_up_1 = { ...p_bottom_1, z: topHeight }
|
|
303
|
+
} else {
|
|
304
|
+
//const vectorFromBottomToTop=multiplyVector(obstacleHeight,{normalVector})
|
|
305
|
+
const vectorFromBottomToTop = multiplyVector(obstacleHeight, {
|
|
306
|
+
x: 0,
|
|
307
|
+
y: 0,
|
|
308
|
+
z: 1
|
|
309
|
+
})
|
|
310
|
+
p_up_0 = addVector(p_bottom_0, vectorFromBottomToTop)
|
|
311
|
+
p_up_1 = addVector(p_bottom_1, vectorFromBottomToTop)
|
|
312
|
+
}
|
|
313
|
+
trianglesVertices.push(
|
|
314
|
+
...[
|
|
315
|
+
p_up_0.x / 1000,
|
|
316
|
+
p_up_0.y / 1000,
|
|
317
|
+
p_up_0.z / 1000,
|
|
318
|
+
p_up_1.x / 1000,
|
|
319
|
+
p_up_1.y / 1000,
|
|
320
|
+
p_up_1.z / 1000,
|
|
321
|
+
p_bottom_0.x / 1000,
|
|
322
|
+
p_bottom_0.y / 1000,
|
|
323
|
+
p_bottom_0.z / 1000,
|
|
324
|
+
p_up_1.x / 1000,
|
|
325
|
+
p_up_1.y / 1000,
|
|
326
|
+
p_up_1.z / 1000,
|
|
327
|
+
p_bottom_0.x / 1000,
|
|
328
|
+
p_bottom_0.y / 1000,
|
|
329
|
+
p_bottom_0.z / 1000,
|
|
330
|
+
p_bottom_1.x / 1000,
|
|
331
|
+
p_bottom_1.y / 1000,
|
|
332
|
+
p_bottom_1.z / 1000
|
|
333
|
+
]
|
|
334
|
+
)
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
if(hasNaN(trianglesVertices)){return null}
|
|
338
|
+
const vertices = new Float32Array(trianglesVertices)
|
|
339
|
+
// itemSize = 3 because there are 3 values (components) per vertex
|
|
340
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
|
|
341
|
+
geometry.computeVertexNormals()
|
|
342
|
+
return geometry
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export function getBufferModuleFieldGeometry(moduleFieldPolygon) {
|
|
346
|
+
const roofPolygon = moduleFieldPolygon.roof
|
|
347
|
+
const moduleHeight = 10
|
|
348
|
+
//get lowest verticalProjection
|
|
349
|
+
const normalVector = roofPolygon.normalVector
|
|
350
|
+
|
|
351
|
+
const moduleFieldOutlineTop = []
|
|
352
|
+
const geometry = new THREE.BufferGeometry()
|
|
353
|
+
//Calcul of triangles using cutear algo
|
|
354
|
+
const trianglesVertices = []
|
|
355
|
+
moduleFieldPolygon.outline.forEach((p) => {
|
|
356
|
+
const vectorFromBottomToTop = multiplyVector(moduleHeight, normalVector)
|
|
357
|
+
let p_up_0 = addVector(p, vectorFromBottomToTop)
|
|
358
|
+
moduleFieldOutlineTop.push(p_up_0)
|
|
359
|
+
})
|
|
360
|
+
trianglesVertices.push(
|
|
361
|
+
...getTriangleVerticesFromOutline(moduleFieldOutlineTop)
|
|
362
|
+
)
|
|
363
|
+
if(hasNaN(trianglesVertices)){return null}
|
|
364
|
+
const vertices = new Float32Array(trianglesVertices)
|
|
365
|
+
var uvs = new Float32Array([
|
|
366
|
+
1, 1, 0, 1, 0, 0,
|
|
367
|
+
|
|
368
|
+
1, 1, 0, 0, 1, 0
|
|
369
|
+
])
|
|
370
|
+
|
|
371
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
|
|
372
|
+
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
|
|
373
|
+
|
|
374
|
+
geometry.computeVertexNormals()
|
|
375
|
+
return geometry
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export function getBufferPanelGeometry(panelPolygon) {
|
|
379
|
+
let panelNormalVector = getNormalVectorFrom3Points(
|
|
380
|
+
panelPolygon.outline[0],
|
|
381
|
+
panelPolygon.outline[1],
|
|
382
|
+
panelPolygon.outline[2]
|
|
383
|
+
)
|
|
384
|
+
if (panelNormalVector.z < 0) {
|
|
385
|
+
panelNormalVector = multiplyVector(-1, panelNormalVector)
|
|
386
|
+
}
|
|
387
|
+
const roofPolygon = panelPolygon.roof
|
|
388
|
+
const panelHeight = parseInt(panelPolygon.height || 50)
|
|
389
|
+
//get lowest verticalProjection
|
|
390
|
+
|
|
391
|
+
const panelOutlineTop = []
|
|
392
|
+
const geometry = new THREE.BufferGeometry()
|
|
393
|
+
//Calcul of triangles using cutear algo
|
|
394
|
+
const trianglesVertices = []
|
|
395
|
+
panelPolygon.outline.forEach((p) => {
|
|
396
|
+
const vectorFromBottomToTop = multiplyVector(panelHeight, panelNormalVector)
|
|
397
|
+
let p_up_0 = addVector(p, vectorFromBottomToTop)
|
|
398
|
+
|
|
399
|
+
panelOutlineTop.push(p_up_0)
|
|
400
|
+
})
|
|
401
|
+
trianglesVertices.push(...getTriangleVerticesFromOutline(panelOutlineTop))
|
|
402
|
+
|
|
403
|
+
if(hasNaN(trianglesVertices)){return null}
|
|
404
|
+
const vertices = new Float32Array(trianglesVertices)
|
|
405
|
+
var A = panelPolygon.outline[2]
|
|
406
|
+
var B = panelPolygon.outline[3]
|
|
407
|
+
var C = panelPolygon.outline[1]
|
|
408
|
+
var D = panelPolygon.outline[0]
|
|
409
|
+
const AB = getDistanceBetweenPoints(A, B)
|
|
410
|
+
const AC = getDistanceBetweenPoints(A, C)
|
|
411
|
+
let uvs
|
|
412
|
+
if (AB < AC) {
|
|
413
|
+
uvs = new Float32Array([
|
|
414
|
+
0, 1,
|
|
415
|
+
0, 0,
|
|
416
|
+
1, 0,
|
|
417
|
+
|
|
418
|
+
0, 1,
|
|
419
|
+
1, 0,
|
|
420
|
+
1, 1
|
|
421
|
+
])
|
|
422
|
+
}else{
|
|
423
|
+
uvs = new Float32Array([
|
|
424
|
+
0, 0,
|
|
425
|
+
1, 0,
|
|
426
|
+
1, 1,
|
|
427
|
+
|
|
428
|
+
1, 0,
|
|
429
|
+
0, 1,
|
|
430
|
+
1, 1
|
|
431
|
+
])
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
|
|
435
|
+
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
|
|
436
|
+
|
|
437
|
+
geometry.computeVertexNormals()
|
|
438
|
+
return geometry
|
|
439
|
+
}
|
|
440
|
+
export function updateBufferPanelGeometry(panelPolygon,geometry){
|
|
441
|
+
geometry=updateBufferRoofGeometry(panelPolygon.outline,[],geometry)
|
|
442
|
+
return geometry
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export function updateBufferPanelSideGeometry(panelPolygon,geometry){
|
|
446
|
+
geometry=updateBufferRoofGeometry(panelPolygon.outline,[],geometry)
|
|
447
|
+
return geometry
|
|
448
|
+
}
|
|
449
|
+
export function getBufferPanelSideGeometry(panelPolygon) {
|
|
450
|
+
let panelNormalVector = getNormalVectorFrom3Points(
|
|
451
|
+
panelPolygon.outline[0],
|
|
452
|
+
panelPolygon.outline[1],
|
|
453
|
+
panelPolygon.outline[2]
|
|
454
|
+
)
|
|
455
|
+
if (panelNormalVector.z < 0) {
|
|
456
|
+
panelNormalVector = multiplyVector(-1, panelNormalVector)
|
|
457
|
+
}
|
|
458
|
+
const roofPolygon = panelPolygon.roof
|
|
459
|
+
const panelHeight = parseInt(panelPolygon.height || 50)
|
|
460
|
+
// const normalVector = roofPolygon.normalVector
|
|
461
|
+
// const passByPoint = roofPolygon.flatOutline[0]
|
|
462
|
+
|
|
463
|
+
const geometry = new THREE.BufferGeometry()
|
|
464
|
+
//Calcul of triangles using cutear algo
|
|
465
|
+
const panelLength = panelPolygon.outline.length
|
|
466
|
+
const trianglesVertices = []
|
|
467
|
+
const panelOutlineTop = []
|
|
468
|
+
panelPolygon.outline.forEach((p, index) => {
|
|
469
|
+
//const vectorFromBottomToTop=multiplyVector(obstacleHeight,{normalVector})
|
|
470
|
+
const p_bottom_0 = p
|
|
471
|
+
const p_bottom_1 = panelPolygon.outline[(index + 1) % panelLength]
|
|
472
|
+
const vectorFromBottomToTop = multiplyVector(panelHeight, panelNormalVector)
|
|
473
|
+
let p_up_0 = addVector(p_bottom_0, vectorFromBottomToTop)
|
|
474
|
+
let p_up_1 = addVector(p_bottom_1, vectorFromBottomToTop)
|
|
475
|
+
trianglesVertices.push(
|
|
476
|
+
...[
|
|
477
|
+
p_up_0.x / 1000,
|
|
478
|
+
p_up_0.y / 1000,
|
|
479
|
+
p_up_0.z / 1000,
|
|
480
|
+
p_up_1.x / 1000,
|
|
481
|
+
p_up_1.y / 1000,
|
|
482
|
+
p_up_1.z / 1000,
|
|
483
|
+
p_bottom_0.x / 1000,
|
|
484
|
+
p_bottom_0.y / 1000,
|
|
485
|
+
p_bottom_0.z / 1000,
|
|
486
|
+
p_bottom_0.x / 1000,
|
|
487
|
+
p_bottom_0.y / 1000,
|
|
488
|
+
p_bottom_0.z / 1000,
|
|
489
|
+
p_up_1.x / 1000,
|
|
490
|
+
p_up_1.y / 1000,
|
|
491
|
+
p_up_1.z / 1000,
|
|
492
|
+
p_bottom_1.x / 1000,
|
|
493
|
+
p_bottom_1.y / 1000,
|
|
494
|
+
p_bottom_1.z / 1000
|
|
495
|
+
]
|
|
496
|
+
)
|
|
497
|
+
})
|
|
498
|
+
if(hasNaN(trianglesVertices)){return null}
|
|
499
|
+
|
|
500
|
+
const vertices = new Float32Array(trianglesVertices)
|
|
501
|
+
|
|
502
|
+
// itemSize = 3 because there are 3 values (components) per vertex
|
|
503
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
|
|
504
|
+
geometry.computeVertexNormals()
|
|
505
|
+
return geometry
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
export function getBufferRoofMarginGeometry(polygon,roofPolygon=null) {
|
|
509
|
+
const geometries = []
|
|
510
|
+
const length = polygon.margins.innerOutline.length
|
|
511
|
+
|
|
512
|
+
polygon.margins.innerOutline.forEach((K, index) => {
|
|
513
|
+
//check if distance ==0 then margin not displayed
|
|
514
|
+
let geometry
|
|
515
|
+
const distance=polygon.margins.isSameMargin?polygon.margins.sameMargin:polygon.margins.distances[index]
|
|
516
|
+
if(distance<=0){
|
|
517
|
+
geometry=null
|
|
518
|
+
}else{
|
|
519
|
+
const A = polygon.margins.outterOutline[index]
|
|
520
|
+
const B = polygon.margins.outterOutline[(index + 1) % length]
|
|
521
|
+
const J = polygon.margins.innerOutline[(index + 1) % length]
|
|
522
|
+
|
|
523
|
+
let marginOutline=[A,B,J,K]
|
|
524
|
+
if(roofPolygon){
|
|
525
|
+
marginOutline=intersectOutlines(marginOutline, roofPolygon.flatOutline)[0] || []
|
|
526
|
+
marginOutline=marginOutline.map(p=>{
|
|
527
|
+
return {
|
|
528
|
+
x:p.x,
|
|
529
|
+
y:p.y,
|
|
530
|
+
z:verticalProjectionOnPlane(p,roofPolygon.normalVector,roofPolygon.flatOutline[0]).z
|
|
531
|
+
}
|
|
532
|
+
})
|
|
533
|
+
}
|
|
534
|
+
marginOutline=marginOutline.map(p=>{return {x:p.x,y:p.y,z:p.z+10}})
|
|
535
|
+
geometry = new THREE.BufferGeometry()
|
|
536
|
+
|
|
537
|
+
const trianglesVertices = []
|
|
538
|
+
|
|
539
|
+
trianglesVertices.push(
|
|
540
|
+
...getTriangleVerticesFromOutline(marginOutline)
|
|
541
|
+
)
|
|
542
|
+
if(hasNaN(trianglesVertices)){return null}
|
|
543
|
+
const vertices = new Float32Array(trianglesVertices)
|
|
544
|
+
|
|
545
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
|
|
546
|
+
geometry.computeVertexNormals()
|
|
547
|
+
}
|
|
548
|
+
geometries.push(geometry)
|
|
549
|
+
})
|
|
550
|
+
return geometries
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
export function getExtrusionGeometry(
|
|
554
|
+
solidsHolesMapData,
|
|
555
|
+
height = (defaultBaseHeight - 100) / 1000
|
|
556
|
+
) {
|
|
557
|
+
const shapes = []
|
|
558
|
+
const getBezierPath = (segments) => {
|
|
559
|
+
const bezierPath = new THREE.Shape()
|
|
560
|
+
for (let i = 0; i < segments.length; i += 1) {
|
|
561
|
+
const curr = segments[i]
|
|
562
|
+
const next = segments[(i + 1) % segments.length]
|
|
563
|
+
const p = []
|
|
564
|
+
p[0] = curr
|
|
565
|
+
p[1] = curr
|
|
566
|
+
p[2] = next
|
|
567
|
+
p[3] = next
|
|
568
|
+
|
|
569
|
+
if (i === 0) {
|
|
570
|
+
bezierPath.moveTo(p[0].x / 1000, p[0].y / 1000)
|
|
571
|
+
}
|
|
572
|
+
bezierPath.bezierCurveTo(
|
|
573
|
+
p[1].x / 1000,
|
|
574
|
+
p[1].y / 1000,
|
|
575
|
+
p[2].x / 1000,
|
|
576
|
+
p[2].y / 1000,
|
|
577
|
+
p[3].x / 1000,
|
|
578
|
+
p[3].y / 1000
|
|
579
|
+
)
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
bezierPath.closePath()
|
|
583
|
+
return bezierPath
|
|
584
|
+
}
|
|
585
|
+
for (const shape of solidsHolesMapData) {
|
|
586
|
+
const solidShape = getBezierPath(shape.outline)
|
|
587
|
+
const holes = shape.holes
|
|
588
|
+
const holePaths = []
|
|
589
|
+
for (let i = 0; i < holes.length; i += 1) {
|
|
590
|
+
const holePath = getBezierPath(holes[i])
|
|
591
|
+
holePaths.push(holePath)
|
|
592
|
+
}
|
|
593
|
+
solidShape.holes = holePaths
|
|
594
|
+
shapes.push(solidShape)
|
|
595
|
+
}
|
|
596
|
+
const settings = {
|
|
597
|
+
depth: height,
|
|
598
|
+
curveSegments: 10,
|
|
599
|
+
bevelEnabled: false,
|
|
600
|
+
material: 0,
|
|
601
|
+
extrudeMaterial: 1
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const geometry = new THREE.ExtrudeGeometry(shapes, settings)
|
|
605
|
+
return geometry
|
|
606
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {Graph} from './DFS'
|
|
2
|
+
import {
|
|
3
|
+
isSameSegment2D,
|
|
4
|
+
} from '@eturnity/eturnity_maths'
|
|
5
|
+
export function generateGraph(polygons){
|
|
6
|
+
const edges2D=[]
|
|
7
|
+
const g=new Graph()
|
|
8
|
+
polygons
|
|
9
|
+
.filter((poly) => poly.layer=='roof')
|
|
10
|
+
.forEach((polygon,index) => {
|
|
11
|
+
g.dict.push(polygon.id)
|
|
12
|
+
const outline = polygon.outline
|
|
13
|
+
outline.forEach((point, i) => {
|
|
14
|
+
//check if edge2D already exist
|
|
15
|
+
const nextPoint = outline[(i + 1) % outline.length]
|
|
16
|
+
let edge2D = edges2D.find((edge) => {
|
|
17
|
+
return (
|
|
18
|
+
isSameSegment2D([point, nextPoint], edge.outline)
|
|
19
|
+
)
|
|
20
|
+
})
|
|
21
|
+
if (!edge2D) {
|
|
22
|
+
//create an edge at this position
|
|
23
|
+
edge2D = {}
|
|
24
|
+
edge2D.outline=[point, nextPoint]
|
|
25
|
+
edge2D.belongsTo = []
|
|
26
|
+
edges2D.push(edge2D)
|
|
27
|
+
}
|
|
28
|
+
//add BelongToPolygon
|
|
29
|
+
edge2D.belongsTo.push({
|
|
30
|
+
polygonId: polygon.id,
|
|
31
|
+
index: i,
|
|
32
|
+
polygon
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
for(let k in edges2D){
|
|
37
|
+
let edge=edges2D[k]
|
|
38
|
+
if(edge.belongsTo.length==2){
|
|
39
|
+
g.addEdge(edge.belongsTo[0].polygonId,edge.belongsTo[1].polygonId)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return g
|
|
43
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as THREE from 'three'
|
|
2
|
+
import {beamColor,beamOpacity,node3DColor,node3dOpacity,defaultTextureUrls} from '../config'
|
|
3
|
+
const material=[]
|
|
4
|
+
|
|
5
|
+
material.wall = new THREE.MeshLambertMaterial({
|
|
6
|
+
color: 0xdddddd,
|
|
7
|
+
side:THREE.DoubleSide
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
// TODO get Canvas image from TwoD
|
|
11
|
+
material.obstacle = new THREE.MeshPhongMaterial({
|
|
12
|
+
color: 0xff0000,
|
|
13
|
+
side:THREE.DoubleSide,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
material.edge=new THREE.MeshPhongMaterial({ color: beamColor,transparent:true,opacity:beamOpacity })
|
|
17
|
+
material.node=new THREE.PointsMaterial( { size: 0.05, sizeAttenuation: true,color: node3DColor, opacity:node3dOpacity, transparent: true } );
|
|
18
|
+
const loader = new THREE.TextureLoader()
|
|
19
|
+
// texture.minFilter = THREE.LinearFilter
|
|
20
|
+
material.panel={}
|
|
21
|
+
|
|
22
|
+
for(let k=0;k<defaultTextureUrls.length;k++){
|
|
23
|
+
let texture=loader.load(defaultTextureUrls[k], function (texture) {})
|
|
24
|
+
material.panel['default_'+k] = new THREE.MeshBasicMaterial({
|
|
25
|
+
map: texture,
|
|
26
|
+
side: THREE.DoubleSide,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
material.flatRoof = new THREE.MeshPhongMaterial({
|
|
31
|
+
color: 0x00ff00,
|
|
32
|
+
specular: 0x009900,
|
|
33
|
+
shininess: 0,
|
|
34
|
+
flatShading: true,
|
|
35
|
+
side:THREE.DoubleSide,
|
|
36
|
+
transparent:true,
|
|
37
|
+
opacity:0.5
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
material.moduleField = new THREE.MeshLambertMaterial({
|
|
41
|
+
color: 0xff0000,
|
|
42
|
+
side:THREE.DoubleSide,
|
|
43
|
+
})
|
|
44
|
+
material.curvedRoof = new THREE.MeshPhongMaterial({
|
|
45
|
+
color: 0xffff00,
|
|
46
|
+
specular: 0x009900,
|
|
47
|
+
shininess: 0,
|
|
48
|
+
flatShading: true,
|
|
49
|
+
side:THREE.DoubleSide,
|
|
50
|
+
transparent:true,
|
|
51
|
+
opacity:0.5
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
export {material}
|