irie 0.0.57__py3-none-any.whl → 0.0.58__py3-none-any.whl
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.
Potentially problematic release.
This version of irie might be problematic. Click here for more details.
- irie/apps/evaluation/identification.py +1 -6
- irie/apps/inventory/models.py +46 -1
- irie/apps/inventory/services/maps/__init__.py +0 -0
- irie/apps/inventory/views.py +213 -302
- irie/apps/prediction/models.py +3 -0
- irie/apps/prediction/runners/opensees/__init__.py +2 -2
- irie/apps/prediction/urls.py +4 -4
- irie/apps/prediction/views.py +37 -46
- irie/apps/site/views.py +1 -0
- irie/apps/templates/inventory/asset-on-map.html +3 -410
- irie/apps/templates/inventory/asset-on-map.js +388 -0
- irie/apps/templates/inventory/sensor-upload.html +1 -0
- irie/apps/templates/layouts/base.html +10 -6
- irie/apps/templates/prediction/create-model.html +11 -1
- irie/maps.py +101 -0
- {irie-0.0.57.dist-info → irie-0.0.58.dist-info}/METADATA +1 -1
- {irie-0.0.57.dist-info → irie-0.0.58.dist-info}/RECORD +20 -17
- {irie-0.0.57.dist-info → irie-0.0.58.dist-info}/WHEEL +0 -0
- {irie-0.0.57.dist-info → irie-0.0.58.dist-info}/entry_points.txt +0 -0
- {irie-0.0.57.dist-info → irie-0.0.58.dist-info}/top_level.txt +0 -0
irie/apps/prediction/models.py
CHANGED
|
@@ -16,7 +16,7 @@ try:
|
|
|
16
16
|
from xcsi.job import Job
|
|
17
17
|
from xcsi.metrics import PeakDrift
|
|
18
18
|
except:
|
|
19
|
-
from openbim.csi import load as load_csi,
|
|
19
|
+
from openbim.csi import load as load_csi, collect_outlines
|
|
20
20
|
from openbim.csi._frame.section import create_section, iter_sections
|
|
21
21
|
|
|
22
22
|
|
|
@@ -64,7 +64,7 @@ def _analyze_and_render(model, artist, nt, dt):
|
|
|
64
64
|
motion.add_to(artist.canvas)
|
|
65
65
|
return 0
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
|
|
69
69
|
@contextlib.contextmanager
|
|
70
70
|
def new_cd(x):
|
irie/apps/prediction/urls.py
CHANGED
|
@@ -18,8 +18,8 @@ _ROOT = "^inventory/(?P<calid>[0-9 A-Z-]*)/predictors"
|
|
|
18
18
|
urlpatterns = [
|
|
19
19
|
re_path(f"{_ROOT}/(?P<preid>[0-9]{{1,}})/$", predictor_profile),
|
|
20
20
|
re_path(f"{_ROOT}/(?P<preid>[0-9]{{1,}})/render/", predictor_render),
|
|
21
|
-
re_path(f"{_ROOT}/create/map/$",
|
|
22
|
-
re_path(f"{_ROOT}/create/model/$",
|
|
23
|
-
re_path(f"{_ROOT}/create/v1/$",
|
|
24
|
-
re_path(f"{_ROOT}/$",
|
|
21
|
+
re_path(f"{_ROOT}/create/map/$", asset_map),
|
|
22
|
+
re_path(f"{_ROOT}/create/model/$", create_model),
|
|
23
|
+
re_path(f"{_ROOT}/create/v1/$", create_mdof),
|
|
24
|
+
re_path(f"{_ROOT}/$", asset_predictors, name="asset_predictors")
|
|
25
25
|
]
|
irie/apps/prediction/views.py
CHANGED
|
@@ -16,32 +16,39 @@ import uuid
|
|
|
16
16
|
import base64
|
|
17
17
|
import hashlib
|
|
18
18
|
|
|
19
|
-
from django.
|
|
20
|
-
from django.template import loader, TemplateDoesNotExist
|
|
19
|
+
from django.template import loader
|
|
21
20
|
from django.contrib.auth.decorators import login_required
|
|
22
21
|
from django.core.exceptions import ObjectDoesNotExist
|
|
23
22
|
from django.core.files.base import ContentFile
|
|
23
|
+
from django.shortcuts import HttpResponse, get_object_or_404
|
|
24
24
|
|
|
25
|
-
from irie.apps.site.view_utils import raise404
|
|
26
25
|
from irie.apps.inventory.models import Asset
|
|
27
26
|
from irie.apps.prediction.predictor import PREDICTOR_TYPES
|
|
28
27
|
from irie.apps.prediction.models import PredictorModel
|
|
29
28
|
from .forms import PredictorForm
|
|
30
29
|
|
|
31
30
|
|
|
31
|
+
def _get_asset(calid, request):
|
|
32
|
+
# TODO: Implement this like get_object_or_404 and move under apps.inventory
|
|
33
|
+
try:
|
|
34
|
+
return Asset.objects.get(calid=calid)
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
except Asset.DoesNotExist:
|
|
37
|
+
context = {
|
|
38
|
+
"segment": "assets"
|
|
39
|
+
}
|
|
40
|
+
return HttpResponse(
|
|
41
|
+
loader.get_template("site/page-404-sidebar.html").render(context, request)
|
|
42
|
+
)
|
|
39
43
|
|
|
40
44
|
|
|
41
45
|
@login_required(login_url="/login/")
|
|
42
46
|
def asset_predictors(request, calid):
|
|
47
|
+
html_template = loader.get_template("prediction/asset-predictors.html")
|
|
43
48
|
|
|
44
|
-
context = {
|
|
49
|
+
context = {
|
|
50
|
+
"segment": "assets"
|
|
51
|
+
}
|
|
45
52
|
|
|
46
53
|
context["runners"] = list(reversed([
|
|
47
54
|
{
|
|
@@ -62,16 +69,13 @@ def asset_predictors(request, calid):
|
|
|
62
69
|
loader.get_template("site/page-404-sidebar.html").render(context, request)
|
|
63
70
|
)
|
|
64
71
|
|
|
65
|
-
html_template = loader.get_template("prediction/asset-predictors.html")
|
|
66
72
|
return HttpResponse(html_template.render(context, request))
|
|
67
73
|
|
|
68
74
|
|
|
69
75
|
@login_required(login_url="/login/")
|
|
70
76
|
def predictor_render(request, calid, preid):
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
except ObjectDoesNotExist:
|
|
74
|
-
return raise404(request, {})
|
|
77
|
+
|
|
78
|
+
predictor = get_object_or_404(PredictorModel, pk=int(preid))
|
|
75
79
|
|
|
76
80
|
sname = request.GET.get("section", None)
|
|
77
81
|
|
|
@@ -91,48 +95,34 @@ def predictor_render(request, calid, preid):
|
|
|
91
95
|
return HttpResponse(glb, content_type="application/binary")
|
|
92
96
|
|
|
93
97
|
except Exception as e:
|
|
94
|
-
raise e
|
|
95
98
|
return HttpResponse(
|
|
96
99
|
json.dumps({"error": "Section not found"}),
|
|
97
100
|
content_type="application/json",
|
|
98
101
|
status=404
|
|
99
102
|
)
|
|
100
103
|
|
|
101
|
-
from veux.plane import PlaneModel
|
|
102
|
-
art = veux.create_artist(mesh, ndf=1, canvas="gltf")
|
|
103
|
-
art.draw_surfaces()
|
|
104
|
-
art.draw_outlines()
|
|
105
|
-
|
|
106
|
-
glb = art.canvas.to_glb()
|
|
107
|
-
return HttpResponse(glb, content_type="application/binary")
|
|
108
|
-
|
|
109
|
-
# rendering = f"data:application/octet-stream;base64,{glb64}"
|
|
110
|
-
# rendering = art._repr_html_()
|
|
111
|
-
r = dict(
|
|
112
|
-
properties = {
|
|
113
|
-
"Area": 1.0,
|
|
114
|
-
"Inertia": 2.0
|
|
115
|
-
},
|
|
116
|
-
rendering = glb64 #rendering
|
|
117
|
-
)
|
|
118
|
-
return HttpResponse(json.dumps(r), content_type="application/json")
|
|
119
|
-
|
|
120
104
|
|
|
121
105
|
@login_required(login_url="/login/")
|
|
122
106
|
def predictor_profile(request, calid, preid):
|
|
123
107
|
|
|
124
|
-
|
|
125
|
-
|
|
108
|
+
def _string_to_id(s: str) -> str:
|
|
109
|
+
"""Convert a string to a URL-safe identifier."""
|
|
110
|
+
# 1. SHA-256 into bytes
|
|
111
|
+
# 2. URL-safe Base64 (no + / =)
|
|
112
|
+
# 3. strip padding
|
|
113
|
+
b64 = base64.urlsafe_b64encode(
|
|
114
|
+
hashlib.sha256(s.encode()).digest()
|
|
115
|
+
).rstrip(b'=').decode('ascii')
|
|
116
|
+
return f"id_{b64}"
|
|
126
117
|
|
|
127
|
-
try:
|
|
128
|
-
asset = Asset.objects.get(calid=calid)
|
|
129
|
-
except Asset.DoesNotExist:
|
|
130
|
-
return raise404(request, context)
|
|
131
118
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
119
|
+
context = {
|
|
120
|
+
"segment": "assets",
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
asset = get_object_or_404(Asset, calid=calid)
|
|
124
|
+
|
|
125
|
+
predictor = get_object_or_404(PredictorModel, pk=int(preid))
|
|
136
126
|
|
|
137
127
|
context["asset"] = asset
|
|
138
128
|
context["runner"] = PREDICTOR_TYPES[predictor.protocol](predictor)
|
|
@@ -214,6 +204,7 @@ def asset_map(request, calid):
|
|
|
214
204
|
return HttpResponse(r200.render(context, request))
|
|
215
205
|
|
|
216
206
|
except Exception as e:
|
|
207
|
+
raise e
|
|
217
208
|
r500 = loader.get_template("site/page-500.html")
|
|
218
209
|
return HttpResponse(r500.render({"message": str(e)}, request), status=500)
|
|
219
210
|
|
|
@@ -239,7 +230,7 @@ def create_model(request, calid):
|
|
|
239
230
|
context = {
|
|
240
231
|
"asset": asset,
|
|
241
232
|
"segment": "assets",
|
|
242
|
-
"viewer": "
|
|
233
|
+
"viewer": "three",
|
|
243
234
|
"offset": json.dumps(list(reversed(list(asset.coordinates)))),
|
|
244
235
|
}
|
|
245
236
|
|
irie/apps/site/views.py
CHANGED
|
@@ -35,6 +35,7 @@ from django.contrib.auth.decorators import login_required
|
|
|
35
35
|
from django.http import HttpResponse, HttpResponseRedirect
|
|
36
36
|
from django.template import loader
|
|
37
37
|
from django.urls import reverse
|
|
38
|
+
from irie.apps.site.view_utils import raise404
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
def index(request):
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
{% if viewer == "three" %}
|
|
15
15
|
<script type="importmap">
|
|
16
16
|
{
|
|
17
|
-
|
|
17
|
+
"imports": {
|
|
18
18
|
"three": "https://cdn.jsdelivr.net/npm/three@0.169.0/build/three.module.js",
|
|
19
19
|
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.169.0/examples/jsm/"
|
|
20
|
-
|
|
20
|
+
}
|
|
21
21
|
}
|
|
22
22
|
</script>
|
|
23
23
|
{% else %}
|
|
@@ -43,414 +43,7 @@
|
|
|
43
43
|
{% else %}
|
|
44
44
|
<script>
|
|
45
45
|
{% endif %}
|
|
46
|
-
|
|
47
|
-
const {map, modelSource, modelOrigin, modelRotate, unitToMeter} = options;
|
|
48
|
-
const modelAltitude = 0;
|
|
49
|
-
const modelCoord = maplibregl.MercatorCoordinate.fromLngLat(
|
|
50
|
-
modelOrigin,
|
|
51
|
-
modelAltitude
|
|
52
|
-
);
|
|
53
|
-
const modelScale = modelCoord.meterInMercatorCoordinateUnits()*unitToMeter;
|
|
54
|
-
const modelTransform = {
|
|
55
|
-
translateX: modelCoord.x,
|
|
56
|
-
translateY: modelCoord.y, //-25*modelScale,
|
|
57
|
-
translateZ: modelCoord.z+100*modelScale, // 35
|
|
58
|
-
rotateX: modelRotate[0],
|
|
59
|
-
rotateY: modelRotate[1],
|
|
60
|
-
rotateZ: modelRotate[2],
|
|
61
|
-
scale: modelScale
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
id: '3d-model',
|
|
66
|
-
type: 'custom',
|
|
67
|
-
renderingMode: '3d',
|
|
68
|
-
onAdd(map, gl) {
|
|
69
|
-
this.camera = new THREE.Camera();
|
|
70
|
-
this.scene = new THREE.Scene();
|
|
71
|
-
|
|
72
|
-
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
|
|
73
|
-
directionalLight.position.set(100, 100, 100);
|
|
74
|
-
directionalLight.castShadow = true;
|
|
75
|
-
this.scene.add(directionalLight);
|
|
76
|
-
|
|
77
|
-
directionalLight.shadow.camera.near = 0.1;
|
|
78
|
-
directionalLight.shadow.camera.far = 2000;
|
|
79
|
-
directionalLight.shadow.camera.left = -50000; // was 500
|
|
80
|
-
directionalLight.shadow.camera.right = 50000; // was 500
|
|
81
|
-
directionalLight.shadow.camera.top = 50000; // was 500
|
|
82
|
-
directionalLight.shadow.camera.bottom = -50000; // was 500
|
|
83
|
-
|
|
84
|
-
directionalLight.shadow.mapSize.width = 4096;
|
|
85
|
-
directionalLight.shadow.mapSize.height = 4096;
|
|
86
|
-
|
|
87
|
-
const groundGeometry = new THREE.PlaneGeometry(5000, 5000);
|
|
88
|
-
const groundMaterial = new THREE.ShadowMaterial({ opacity: 0.3 });
|
|
89
|
-
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
|
|
90
|
-
ground.rotation.x = -Math.PI / 2;
|
|
91
|
-
ground.position.y = - 100; // 35;
|
|
92
|
-
ground.receiveShadow = true;
|
|
93
|
-
this.scene.add(ground);
|
|
94
|
-
|
|
95
|
-
const loader = new GLTFLoader();
|
|
96
|
-
loader.load(
|
|
97
|
-
modelSource,
|
|
98
|
-
(gltf) => {
|
|
99
|
-
gltf.scene.traverse(function (node) {
|
|
100
|
-
if (node.isMesh || node.isLight) {
|
|
101
|
-
node.castShadow = true;
|
|
102
|
-
node.receiveShadow = true;
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
this.scene.add(gltf.scene);
|
|
106
|
-
}
|
|
107
|
-
);
|
|
108
|
-
this.map = map;
|
|
109
|
-
|
|
110
|
-
this.renderer = new THREE.WebGLRenderer({
|
|
111
|
-
canvas: map.getCanvas(),
|
|
112
|
-
context: gl,
|
|
113
|
-
antialias: true
|
|
114
|
-
});
|
|
115
|
-
this.renderer.shadowMap.enabled = true;
|
|
116
|
-
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
|
117
|
-
|
|
118
|
-
this.renderer.autoClear = false;
|
|
119
|
-
},
|
|
120
|
-
render(gl, args) {
|
|
121
|
-
const rotationX = new THREE.Matrix4().makeRotationAxis(
|
|
122
|
-
new THREE.Vector3(1, 0, 0),
|
|
123
|
-
modelTransform.rotateX
|
|
124
|
-
);
|
|
125
|
-
const rotationY = new THREE.Matrix4().makeRotationAxis(
|
|
126
|
-
new THREE.Vector3(0, 1, 0),
|
|
127
|
-
modelTransform.rotateY
|
|
128
|
-
);
|
|
129
|
-
const rotationZ = new THREE.Matrix4().makeRotationAxis(
|
|
130
|
-
new THREE.Vector3(0, 0, 1),
|
|
131
|
-
modelTransform.rotateZ
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
const m = new THREE.Matrix4().fromArray(args.defaultProjectionData.mainMatrix);
|
|
135
|
-
const l = new THREE.Matrix4()
|
|
136
|
-
.makeTranslation(
|
|
137
|
-
modelTransform.translateX,
|
|
138
|
-
modelTransform.translateY,
|
|
139
|
-
modelTransform.translateZ
|
|
140
|
-
)
|
|
141
|
-
.scale(
|
|
142
|
-
new THREE.Vector3(
|
|
143
|
-
modelTransform.scale,
|
|
144
|
-
-modelTransform.scale,
|
|
145
|
-
modelTransform.scale
|
|
146
|
-
)
|
|
147
|
-
)
|
|
148
|
-
.multiply(rotationX)
|
|
149
|
-
.multiply(rotationY)
|
|
150
|
-
.multiply(rotationZ);
|
|
151
|
-
|
|
152
|
-
this.camera.projectionMatrix = m.multiply(l);
|
|
153
|
-
this.renderer.resetState();
|
|
154
|
-
this.renderer.render(this.scene, this.camera);
|
|
155
|
-
this.map.triggerRepaint();
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function createAssetLayerBabylon(options) {
|
|
161
|
-
const {map, modelSource, modelOrigin, modelRotate, unitToMeter} = options;
|
|
162
|
-
const worldAltitude = 0;
|
|
163
|
-
|
|
164
|
-
const BABYLON = window.BABYLON;
|
|
165
|
-
// +x east, +y up, +z north
|
|
166
|
-
// const modelRotate = [Math.PI / 2, 0, 0];
|
|
167
|
-
// Maplibre.js default coordinate system (no rotations)
|
|
168
|
-
// +x east, -y north, +z up
|
|
169
|
-
//var worldRotate = [0, 0, 0];
|
|
170
|
-
|
|
171
|
-
const worldOriginMercator = maplibregl.MercatorCoordinate.fromLngLat(
|
|
172
|
-
modelOrigin,
|
|
173
|
-
worldAltitude
|
|
174
|
-
);
|
|
175
|
-
const modelScale = worldOriginMercator.meterInMercatorCoordinateUnits()*unitToMeter;
|
|
176
|
-
const modelTransform = {
|
|
177
|
-
translateX: worldOriginMercator.x,
|
|
178
|
-
translateY: worldOriginMercator.y-25*modelScale,
|
|
179
|
-
translateZ: worldOriginMercator.z+35*modelScale,
|
|
180
|
-
rotateX: modelRotate[0],
|
|
181
|
-
rotateY: modelRotate[1],
|
|
182
|
-
rotateZ: modelRotate[2],
|
|
183
|
-
scale: modelScale
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
// Calculate world matrix
|
|
187
|
-
const worldMatrix = BABYLON.Matrix.Compose(
|
|
188
|
-
new BABYLON.Vector3(modelScale, modelScale, modelScale),
|
|
189
|
-
BABYLON.Quaternion.FromEulerAngles(
|
|
190
|
-
modelRotate[0],
|
|
191
|
-
modelRotate[1],
|
|
192
|
-
modelRotate[2]
|
|
193
|
-
),
|
|
194
|
-
new BABYLON.Vector3(
|
|
195
|
-
worldOriginMercator.x,
|
|
196
|
-
worldOriginMercator.y,
|
|
197
|
-
worldOriginMercator.z
|
|
198
|
-
)
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
return {
|
|
202
|
-
id: '3d-model',
|
|
203
|
-
type: 'custom',
|
|
204
|
-
renderingMode: '3d',
|
|
205
|
-
onAdd (map, gl) {
|
|
206
|
-
this.engine = new BABYLON.Engine(
|
|
207
|
-
gl,
|
|
208
|
-
true,
|
|
209
|
-
{
|
|
210
|
-
useHighPrecisionMatrix: true // Important to prevent jitter at mercator scale
|
|
211
|
-
},
|
|
212
|
-
true
|
|
213
|
-
);
|
|
214
|
-
this.scene = new BABYLON.Scene(this.engine);
|
|
215
|
-
/**
|
|
216
|
-
* optionally add
|
|
217
|
-
* this.scene.autoClearDepthAndStencil = false
|
|
218
|
-
* and for renderingGroupIds set this individually via
|
|
219
|
-
* this.scene.setRenderingAutoClearDepthStencil(1,false)
|
|
220
|
-
* to allow blending with maplibre scene
|
|
221
|
-
* as documented in https://doc.babylonjs.com/features/featuresDeepDive/scene/optimize_your_scene#reducing-calls-to-glclear
|
|
222
|
-
*/
|
|
223
|
-
this.scene.autoClear = false;
|
|
224
|
-
/**
|
|
225
|
-
* use detachControl if you only want to interact with maplibre-gl and do not need pointer events of babylonjs.
|
|
226
|
-
* alternatively exchange this.scene.detachControl() with the following two lines, they will allow bubbling up events to maplibre-gl.
|
|
227
|
-
* this.scene.preventDefaultOnPointerDown = false
|
|
228
|
-
* this.scene.preventDefaultOnPointerUp = false
|
|
229
|
-
* https://doc.babylonjs.com/typedoc/classes/BABYLON.Scene#preventDefaultOnPointerDown
|
|
230
|
-
*/
|
|
231
|
-
this.scene.detachControl();
|
|
232
|
-
|
|
233
|
-
this.scene.beforeRender = () => {
|
|
234
|
-
this.engine.wipeCaches(true);
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
// create simple camera (will have its project matrix manually calculated)
|
|
238
|
-
this.camera = new BABYLON.Camera(
|
|
239
|
-
'Camera',
|
|
240
|
-
new BABYLON.Vector3(0, 0, 0),
|
|
241
|
-
this.scene
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
// create simple light
|
|
245
|
-
const light = new BABYLON.HemisphericLight(
|
|
246
|
-
'light1',
|
|
247
|
-
new BABYLON.Vector3(0, 0, 100),
|
|
248
|
-
this.scene
|
|
249
|
-
);
|
|
250
|
-
light.intensity = 0.7;
|
|
251
|
-
|
|
252
|
-
// Add debug axes viewer, positioned at origin, 10 meter axis lengths
|
|
253
|
-
new BABYLON.AxesViewer(this.scene, 10);
|
|
254
|
-
|
|
255
|
-
// load GLTF model in to the scene
|
|
256
|
-
BABYLON.SceneLoader.LoadAssetContainerAsync(
|
|
257
|
-
modelSource, '', this.scene
|
|
258
|
-
).then((modelContainer) => {
|
|
259
|
-
modelContainer.addAllToScene();
|
|
260
|
-
|
|
261
|
-
const rootMesh = modelContainer.createRootMesh();
|
|
262
|
-
|
|
263
|
-
// If using maplibre.js coordinate system (+z up)
|
|
264
|
-
// rootMesh.rotation.x = Math.PI/2
|
|
265
|
-
|
|
266
|
-
// // Create a second mesh
|
|
267
|
-
// const rootMesh2 = rootMesh.clone();
|
|
268
|
-
|
|
269
|
-
// // Position in babylon.js coordinate system
|
|
270
|
-
// rootMesh2.position.x = 25; // +east, meters
|
|
271
|
-
// rootMesh2.position.z = 25; // +north, meters
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
this.map = map;
|
|
275
|
-
},
|
|
276
|
-
render (gl, args) {
|
|
277
|
-
const cameraMatrix = BABYLON.Matrix.FromArray(args.defaultProjectionData.mainMatrix);
|
|
278
|
-
|
|
279
|
-
// world-view-projection matrix
|
|
280
|
-
const wvpMatrix = worldMatrix.multiply(cameraMatrix);
|
|
281
|
-
|
|
282
|
-
this.camera.freezeProjectionMatrix(wvpMatrix);
|
|
283
|
-
|
|
284
|
-
this.scene.render(false);
|
|
285
|
-
this.map.triggerRepaint();
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/*
|
|
292
|
-
* Helper function used to get threejs-scene-coordinates from mercator coordinates.
|
|
293
|
-
* This is just a quick and dirty solution - it won't work if points are far away from each other
|
|
294
|
-
* because a meter near the north-pole covers more mercator-units
|
|
295
|
-
* than a meter near the equator.
|
|
296
|
-
*/
|
|
297
|
-
function calculateDistanceMercatorToMeters(from, to) {
|
|
298
|
-
const mercatorPerMeter = from.meterInMercatorCoordinateUnits();
|
|
299
|
-
// mercator x: 0=west, 1=east
|
|
300
|
-
const dEast = to.x - from.x;
|
|
301
|
-
const dEastMeter = dEast / mercatorPerMeter;
|
|
302
|
-
// mercator y: 0=north, 1=south
|
|
303
|
-
const dNorth = from.y - to.y;
|
|
304
|
-
const dNorthMeter = dNorth / mercatorPerMeter;
|
|
305
|
-
return {dEastMeter, dNorthMeter};
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const div = document.querySelector('#map');
|
|
309
|
-
const modelOrigin = JSON.parse(div.dataset.location); // [-124.1014, 40.50303];
|
|
310
|
-
var modelSource = undefined;
|
|
311
|
-
if (div.dataset.renderSource)
|
|
312
|
-
modelSource = div.dataset.renderSource;
|
|
313
|
-
else
|
|
314
|
-
modelSource = div.dataset.renderInline;
|
|
315
|
-
|
|
316
|
-
const unitToMeter = 1/3.2808;
|
|
317
|
-
|
|
318
|
-
const MAPTILER_KEY = 'get_your_own_OpIi9ZULNHzrESv6T2vL';
|
|
319
|
-
const mapid = 'winter'; // 'dataviz'; // 'basic-v2'; // 'aquarelle';
|
|
320
|
-
const map = (window.map = new maplibregl.Map({
|
|
321
|
-
container: 'map',
|
|
322
|
-
style: `https://api.maptiler.com/maps/${mapid}/style.json?key=${MAPTILER_KEY}`,
|
|
323
|
-
// style: {
|
|
324
|
-
// version: 8,
|
|
325
|
-
// sources: {
|
|
326
|
-
// osm: {
|
|
327
|
-
// type: 'raster',
|
|
328
|
-
// tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'],
|
|
329
|
-
// tileSize: 256,
|
|
330
|
-
// attribution: '© OpenStreetMap Contributors',
|
|
331
|
-
// maxzoom: 19
|
|
332
|
-
// },
|
|
333
|
-
// // Use a different source for terrain and hillshade layers, to improve render quality
|
|
334
|
-
// terrainSource: {
|
|
335
|
-
// type: 'raster-dem',
|
|
336
|
-
// url: 'https://demotiles.maplibre.org/terrain-tiles/tiles.json',
|
|
337
|
-
// tileSize: 256
|
|
338
|
-
// },
|
|
339
|
-
// hillshadeSource: {
|
|
340
|
-
// type: 'raster-dem',
|
|
341
|
-
// url: 'https://demotiles.maplibre.org/terrain-tiles/tiles.json',
|
|
342
|
-
// tileSize: 256
|
|
343
|
-
// }
|
|
344
|
-
// },
|
|
345
|
-
// layers: [
|
|
346
|
-
// {
|
|
347
|
-
// id: 'osm',
|
|
348
|
-
// type: 'raster',
|
|
349
|
-
// source: 'osm'
|
|
350
|
-
// },
|
|
351
|
-
// {
|
|
352
|
-
// id: 'hills',
|
|
353
|
-
// type: 'hillshade',
|
|
354
|
-
// source: 'hillshadeSource',
|
|
355
|
-
// layout: {visibility: 'visible'},
|
|
356
|
-
// paint: {'hillshade-shadow-color': '#473B24'}
|
|
357
|
-
// }
|
|
358
|
-
// ],
|
|
359
|
-
// terrain: {
|
|
360
|
-
// source: 'terrainSource',
|
|
361
|
-
// exaggeration: 1
|
|
362
|
-
// }
|
|
363
|
-
// },
|
|
364
|
-
zoom: 18,
|
|
365
|
-
center: modelOrigin,
|
|
366
|
-
zoom: 18,
|
|
367
|
-
maxZoom: 30,
|
|
368
|
-
maxPitch: 85,
|
|
369
|
-
pitch: 77,
|
|
370
|
-
canvasContextAttributes: {antialias: true} // create the gl context with MSAA antialiasing, so custom layers are antialiased
|
|
371
|
-
}));
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
//
|
|
375
|
-
// Add Buildings
|
|
376
|
-
//
|
|
377
|
-
|
|
378
|
-
// The 'building' layer in the streets vector source contains building-height
|
|
379
|
-
// data from OpenStreetMap.
|
|
380
|
-
map.on('load', () => {
|
|
381
|
-
// Insert the layer beneath any symbol layer.
|
|
382
|
-
const layers = map.getStyle().layers;
|
|
383
|
-
|
|
384
|
-
let labelLayerId;
|
|
385
|
-
for (let i = 0; i < layers.length; i++) {
|
|
386
|
-
if (layers[i].type === 'symbol' && layers[i].layout['text-field']) {
|
|
387
|
-
labelLayerId = layers[i].id;
|
|
388
|
-
break;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
map.addSource('openmaptiles', {
|
|
393
|
-
url: `https://api.maptiler.com/tiles/v3/tiles.json?key=${MAPTILER_KEY}`,
|
|
394
|
-
type: 'vector',
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
map.addLayer(
|
|
398
|
-
{
|
|
399
|
-
'id': '3d-buildings',
|
|
400
|
-
'source': 'openmaptiles',
|
|
401
|
-
'source-layer': 'building',
|
|
402
|
-
'type': 'fill-extrusion',
|
|
403
|
-
'minzoom': 15,
|
|
404
|
-
'filter': ['!=', ['get', 'hide_3d'], true],
|
|
405
|
-
'paint': {
|
|
406
|
-
'fill-extrusion-color': [
|
|
407
|
-
'interpolate',
|
|
408
|
-
['linear'],
|
|
409
|
-
['get', 'render_height'], 0, 'lightgray', 200, 'royalblue', 400, 'lightblue'
|
|
410
|
-
],
|
|
411
|
-
'fill-extrusion-height': [
|
|
412
|
-
'interpolate',
|
|
413
|
-
['linear'],
|
|
414
|
-
['zoom'],
|
|
415
|
-
15,
|
|
416
|
-
0,
|
|
417
|
-
16,
|
|
418
|
-
['get', 'render_height']
|
|
419
|
-
],
|
|
420
|
-
'fill-extrusion-base': ['case',
|
|
421
|
-
['>=', ['get', 'zoom'], 16],
|
|
422
|
-
['get', 'render_min_height'], 0
|
|
423
|
-
]
|
|
424
|
-
}
|
|
425
|
-
},
|
|
426
|
-
labelLayerId
|
|
427
|
-
);
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
//
|
|
432
|
-
// Add Asset
|
|
433
|
-
//
|
|
434
|
-
const worldAltitude = 0;
|
|
435
|
-
// +x east, +y up, +z north
|
|
436
|
-
const modelRotate = [Math.PI / 2, 0, 0];
|
|
437
|
-
// Maplibre.js default coordinate system (no rotations)
|
|
438
|
-
// +x east, -y north, +z up
|
|
439
|
-
// const modelRotate = [0, 0, 0];
|
|
440
|
-
|
|
441
|
-
map.on('style.load', () => {
|
|
442
|
-
{% if viewer == "three" %}
|
|
443
|
-
map.addLayer(createAssetLayerThreeJS({
|
|
444
|
-
{% else %}
|
|
445
|
-
map.addLayer(createAssetLayerBabylon({
|
|
446
|
-
{% endif %}
|
|
447
|
-
map,
|
|
448
|
-
modelSource,
|
|
449
|
-
modelOrigin,
|
|
450
|
-
modelRotate,
|
|
451
|
-
unitToMeter
|
|
452
|
-
}));
|
|
453
|
-
});
|
|
46
|
+
{% include "inventory/asset-on-map.js" with viewer=viewer %}
|
|
454
47
|
</script>
|
|
455
48
|
|
|
456
49
|
</body>
|