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.

@@ -55,6 +55,9 @@ class SensorAssignment(models.Model):
55
55
  ]
56
56
  )
57
57
 
58
+ def __str__(self):
59
+ return f"{self.predictor.name} - {self.sensor.name} ({self.role})"
60
+
58
61
  # orient_z = models.FloatField()
59
62
  # orient_x = models.FloatField()
60
63
  # orient_y = models.FloatField()
@@ -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, create_model, collect_outlines
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):
@@ -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/$", 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")
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
  ]
@@ -16,32 +16,39 @@ import uuid
16
16
  import base64
17
17
  import hashlib
18
18
 
19
- from django.shortcuts import HttpResponse
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
- def _string_to_id(s: str) -> str:
34
- # 1. SHA-256 → bytes 2. URL-safe Base64 (no + / =) 3. strip padding
35
- b64 = base64.urlsafe_b64encode(
36
- hashlib.sha256(s.encode()).digest()
37
- ).rstrip(b'=').decode('ascii')
38
- return f"id_{b64}"
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 = {"segment": "assets"}
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
- try:
72
- predictor = PredictorModel.objects.get(pk=int(preid))
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
- context = {}
125
- context["segment"] = "assets"
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
- try:
133
- predictor = PredictorModel.objects.get(pk=int(preid))
134
- except ObjectDoesNotExist:
135
- return raise404(request, context)
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": "babylon",
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
- "imports": {
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
- function createAssetLayerThreeJS(options) {
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: '&copy; 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>