@abi-software/scaffoldvuer 0.2.3-alpha-2 → 0.3.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.
Files changed (48) hide show
  1. package/.eslintrc.js +12 -12
  2. package/CHANGELOG.md +332 -316
  3. package/LICENSE +201 -201
  4. package/README.md +164 -164
  5. package/babel.config.js +14 -14
  6. package/dist/scaffoldvuer-wc.common.js +34 -34
  7. package/dist/scaffoldvuer-wc.umd.js +34 -34
  8. package/dist/scaffoldvuer-wc.umd.min.js +34 -34
  9. package/dist/scaffoldvuer.common.js +374 -375
  10. package/dist/scaffoldvuer.common.js.map +1 -1
  11. package/dist/scaffoldvuer.css +1 -1
  12. package/dist/scaffoldvuer.umd.js +374 -375
  13. package/dist/scaffoldvuer.umd.js.map +1 -1
  14. package/dist/scaffoldvuer.umd.min.js +1 -1
  15. package/dist/scaffoldvuer.umd.min.js.map +1 -1
  16. package/package-lock.json +18121 -18119
  17. package/package.json +89 -89
  18. package/public/index.html +17 -17
  19. package/src/App.vue +669 -669
  20. package/src/ScaffoldVuer-wc.js +13 -13
  21. package/src/app/DropZone.vue +114 -114
  22. package/src/app/ModelsInformation.js +35 -35
  23. package/src/app/ModelsTable.vue +113 -113
  24. package/src/app/TextureDemos.js +114 -114
  25. package/src/assets/_variables.scss +43 -43
  26. package/src/assets/styles.scss +7 -7
  27. package/src/components/OpacityControls.vue +222 -222
  28. package/src/components/PrimitiveControls.vue +158 -0
  29. package/src/components/ScaffoldTooltip.vue +142 -142
  30. package/src/components/ScaffoldVuer.md +44 -44
  31. package/src/components/ScaffoldVuer.vue +2006 -2007
  32. package/src/components/TreeControls.vue +699 -699
  33. package/src/components/index.js +7 -7
  34. package/src/credential.json +12 -0
  35. package/src/main.js +14 -14
  36. package/src/scripts/BaseModule.js +80 -80
  37. package/src/scripts/RendererModule.js +289 -289
  38. package/src/scripts/WebGL.js +94 -94
  39. package/src/scripts/annotation.js +5 -5
  40. package/src/scripts/eventNotifier.js +66 -66
  41. package/src/scripts/graphicsHighlight.js +134 -134
  42. package/src/scripts/organsRenderer.js +587 -587
  43. package/src/scripts/search.js +182 -182
  44. package/src/scripts/utilities.js +146 -146
  45. package/styleguide.config.js +22 -22
  46. package/vue.config.js +41 -41
  47. package/src/components/test.pdf +0 -0
  48. package/src/searchControls.vue +0 -122
@@ -1,587 +1,587 @@
1
- const THREE = require('zincjs').THREE;
2
- // Current model's associate data, data fields, external link, nerve map
3
- // informations,
4
- // these are proived in the organsFileMap array.
5
- const OrgansSceneData = function() {
6
- this.currentName = "";
7
- this.currentSystem = "";
8
- this.currentPart = "";
9
- this.currentSpecies = "";
10
- this.metaURL = "";
11
- this.viewURL = "";
12
- this.currentTime = 0.0;
13
- this.timeVarying = false;
14
- }
15
-
16
- /**
17
- * Viewer of 3D-organs models. Users can toggle on/off different views. Data is
18
- * displayed instead if models are not available.
19
- *
20
- * @class
21
- * @param {PJP.ModelsLoader}
22
- * ModelsLoaderIn - defined in modelsLoade.js, providing locations of
23
- * files.
24
- * @param {String}
25
- * PanelName - Id of the target element to create the
26
- * {@link PJP.OrgansViewer} on.
27
- * @author Alan Wu
28
- * @returns {PJP.OrgansViewer}
29
- */
30
- const OrgansViewer = function(ModelsLoaderIn) {
31
- (require('./RendererModule').RendererModule).call(this);
32
- const _this = this;
33
- let pickerScene = undefined;
34
- this.sceneData = new OrgansSceneData();
35
- const timeChangedCallbacks = new Array();
36
- const sceneChangedCallbacks = new Array();
37
- const organPartAddedCallbacks = new Array();
38
- let finishDownloadCallback = undefined;
39
- const modelsLoader = ModelsLoaderIn;
40
- this.NDCCameraControl = undefined;
41
- _this.typeName = "Organ Viewer";
42
-
43
- this.getSceneData = function() {
44
- return _this.sceneData;
45
- }
46
-
47
- /**
48
- * Used to update internal timer in scene when time slider has changed.
49
- */
50
- this.updateTime = function(value) {
51
- let duration = 6000;
52
- if (_this.scene)
53
- duration = _this.scene.getDuration();
54
- const actualTime = value / 100.0 * duration;
55
- if (!_this.sceneData.nerveMapIsActive) {
56
- if (pickerScene)
57
- pickerScene.setMorphsTime(actualTime);
58
- if (_this.scene)
59
- _this.scene.setMorphsTime(actualTime);
60
- }
61
- _this.sceneData.currentTime = value;
62
- }
63
-
64
- /**
65
- * Update the time slider and other renderers/scenes when time has changed.
66
- */
67
- const preRenderTimeUpdate = function() {
68
- let duration = 3000;
69
- if (_this.scene)
70
- duration = _this.scene.getDuration();
71
- const currentTime = _this.zincRenderer.getCurrentTime();
72
- for (let i = 0; i < timeChangedCallbacks.length;i++) {
73
- timeChangedCallbacks[i](currentTime);
74
- }
75
- if (!_this.sceneData.nerveMapIsActive && pickerScene)
76
- pickerScene.setMorphsTime(currentTime);
77
- if (_this.sceneData.nerveMap && _this.sceneData.nerveMap.additionalReader)
78
- _this.sceneData.nerveMap.additionalReader.setTime(currentTime /
79
- duration);
80
- _this.sceneData.currentTime = currentTime / duration * 100.0;
81
- }
82
-
83
- this.toggleSyncControl = (flag, rotateMode) => {
84
- let cameraControl = this.scene.getZincCameraControls();
85
- if (flag) {
86
- cameraControl.resetView();
87
- this.NDCCameraControl = cameraControl.enableSyncControl();
88
- cameraControl.setRotationMode(rotateMode);
89
- } else {
90
- cameraControl.disableSyncControl();
91
- this.NDCCameraControl = undefined;
92
- cameraControl.setRotationMode("free");
93
- }
94
- }
95
-
96
- this.isSyncControl = () => {
97
- return this.NDCCameraControl !== undefined;
98
- }
99
-
100
- this.setSyncControlZoomToBox = (box) => {
101
- if (this.NDCCameraControl) {
102
- this.NDCCameraControl.zoomToBox(box, 2);
103
- }
104
- }
105
-
106
- this.setSyncControlCallback = (callback) => {
107
- if (this.NDCCameraControl) {
108
- this.NDCCameraControl.setEventCallback(callback);
109
- }
110
- }
111
-
112
- this.setSyncControlCenterZoom = (center, zoom) => {
113
- if (this.NDCCameraControl) {
114
- this.NDCCameraControl.setCenterZoom(center, zoom);
115
- }
116
- }
117
-
118
- const postRenderSelectedCoordinatesUpdate = function() {
119
- //It is animating, the coordinates may have been updated
120
- if (_this.zincRenderer.playAnimation && _this.liveUpdatesObjects) {
121
- _this.setupLiveCoordinates(_this.liveUpdatesObjects);
122
- }
123
- if (_this.selectedCenter) {
124
- const vector = new THREE.Vector3();
125
- vector.copy(_this.selectedCenter);
126
- const coord = _this.scene.vectorToScreenXY(vector);
127
- _this.selectedScreenCoordinates.x = coord.x;
128
- _this.selectedScreenCoordinates.y = coord.y;
129
- }
130
- }
131
-
132
- const preRenderUpdateCallback = function() {
133
- return function() {
134
- preRenderTimeUpdate();
135
- }
136
- }
137
-
138
- const postRenderUpdateCallback = function() {
139
- return function() {
140
- postRenderSelectedCoordinatesUpdate();
141
- }
142
- }
143
-
144
- /**
145
- * Add a callback which will be called when time has changed
146
- */
147
- this.addTimeChangedCallback = function(callback) {
148
- if (typeof(callback === "function"))
149
- timeChangedCallbacks.push(callback);
150
- }
151
-
152
- this.setTexturePos = function(value) {
153
- if (_this.sceneData.nerveMap && _this.sceneData.nerveMap.additionalReader)
154
- _this.sceneData.nerveMap.additionalReader.setSliderPos(value);
155
- }
156
-
157
- this.addSceneChangedCallback = function(callback) {
158
- if (typeof(callback === "function")) {
159
- sceneChangedCallbacks.push(callback);
160
- }
161
- }
162
-
163
- this.addOrganPartAddedCallback = function(callback) {
164
- if (typeof(callback === "function"))
165
- organPartAddedCallbacks.push(callback);
166
- }
167
-
168
- this.setFinishDownloadCallback = function(callback) {
169
- if (typeof(callback === "function"))
170
- finishDownloadCallback = callback;
171
- }
172
-
173
- this.unsetFinishDownloadCallback = function() {
174
- finishDownloadCallback = undefined;
175
- }
176
-
177
- this.getNamedObjectsToScreenCoordinates = function(name, camera) {
178
- const vector = new THREE.Vector3();
179
- vector.setFromMatrixPosition( obj.matrixWorld );
180
- const widthHalf = (width/2);
181
- const heightHalf = (height/2);
182
- vector.project(camera);
183
- vector.x = ( vector.x * widthHalf ) + widthHalf;
184
- vector.y = - ( vector.y * heightHalf ) + heightHalf;
185
- return vector;
186
- }
187
-
188
- const getIdObjectFromIntersect = function(intersected) {
189
- let id = undefined;
190
- let intersectedObject = undefined;
191
- if (intersected !== undefined) {
192
- let marker = false;
193
- if (intersected.object.userData &&
194
- intersected.object.userData.isMarker) {
195
- marker = true;
196
- intersectedObject = intersected.object.userData.parent.morph;
197
- } else {
198
- intersectedObject = intersected.object;
199
- }
200
- try {
201
- intersectedObject.userData.userData.annotation.data.lastActionOnMarker = marker;
202
- } finally { }
203
- if (intersectedObject) {
204
- if (intersectedObject.name) {
205
- id = intersectedObject.name;
206
- } else {
207
- const annotations = _this.getAnnotationsFromObjects(
208
- [intersectedObject]);
209
- if (annotations && annotations[0]) {
210
- id = annotations[0].data.group;
211
- }
212
- }
213
- }
214
- }
215
- return {"id":id, "object":intersectedObject};
216
- }
217
-
218
- /**
219
- * Callback function when a pickable object has been picked. It will then
220
- * call functions in tissueViewer and cellPanel to show corresponding
221
- * informations.
222
- *
223
- * @callback
224
- */
225
- const _pickingCallback = function() {
226
- return function(intersects, window_x, window_y) {
227
- const intersected = _this.getIntersectedObject(intersects);
228
- const idObject = getIdObjectFromIntersect(intersected);
229
- const coords = { x: window_x, y: window_y };
230
- if (idObject.id) {
231
- if (idObject.object.userData.isGlyph) {
232
- if (idObject.object.name)
233
- _this.setSelectedByObjects([idObject.object], coords, true);
234
- else
235
- _this.setSelectedByZincObjects(idObject.object.userData.getGlyphset(),
236
- coords, true);
237
- } else {
238
- _this.setSelectedByObjects([idObject.object], coords, true);
239
- }
240
- return;
241
- } else {
242
- _this.setSelectedByObjects([], coords, true);
243
- }
244
- }
245
- };
246
-
247
- /**
248
- * Callback function when a pickable object has been hovered over.
249
- *
250
- * @callback
251
- */
252
- const _hoverCallback = function() {
253
- return function(intersects, window_x, window_y) {
254
- const intersected = _this.getIntersectedObject(intersects);
255
- const idObject = getIdObjectFromIntersect(intersected);
256
- const coords = { x: window_x, y: window_y };
257
- if (idObject.id) {
258
- _this.displayArea.style.cursor = "pointer";
259
- _this.setHighlightedByObjects([idObject.object], coords, true);
260
- return;
261
- }
262
- else {
263
- _this.displayArea.style.cursor = "auto";
264
- _this.setHighlightedByObjects([], coords, true);
265
- }
266
- }
267
- };
268
-
269
- const changeOrganPartsVisibilityForScene = function(scene, name, value, type) {
270
- if (type == "all" || type == "geometries") {
271
- const geometries = scene.findGeometriesWithGroupName(name);
272
- for (let i = 0; i < geometries.length; i ++ ) {
273
- geometries[i].setVisibility(value);
274
- }
275
- }
276
- if (type == "all" || type == "glyphsets") {
277
- const glyphsets = scene.findGlyphsetsWithGroupName(name);
278
- for (let i = 0; i < glyphsets.length; i ++ ) {
279
- glyphsets[i].setVisibility(value);
280
- }
281
- }
282
- if (type == "all" || type == "pointsets") {
283
- const pointsets = scene.findPointsetsWithGroupName(name);
284
- for (let i = 0; i < pointsets.length; i ++ ) {
285
- pointsets[i].setVisibility(value);
286
- }
287
- }
288
- if (type == "all" || type == "lines") {
289
- const lines = scene.findLinesWithGroupName(name);
290
- for (let i = 0; i < lines.length; i ++ ) {
291
- lines[i].setVisibility(value);
292
- }
293
- }
294
- }
295
-
296
- /**
297
- * Change visibility for parts of the current scene.
298
- */
299
- this.changeGeometriesVisibility = function(name, value) {
300
- changeOrganPartsVisibilityForScene(_this.scene, name, value, 'geometries');
301
- if (pickerScene)
302
- changeOrganPartsVisibilityForScene(pickerScene, name, value, 'geometries');
303
- }
304
-
305
- /**
306
- * Change visibility for parts of the current scene.
307
- */
308
- this.changeGlyphsetsVisibility = function(name, value) {
309
- changeOrganPartsVisibilityForScene(_this.scene, name, value, 'glyphsets');
310
- if (pickerScene)
311
- changeOrganPartsVisibilityForScene(pickerScene, name, value, 'glyphsets');
312
- }
313
-
314
- /**
315
- * Change visibility for parts of the current scene.
316
- */
317
- this.changeLinesVisibility = function(name, value) {
318
- changeOrganPartsVisibilityForScene(_this.scene, name, value, 'lines');
319
- if (pickerScene)
320
- changeOrganPartsVisibilityForScene(pickerScene, name, value, 'lines');
321
- }
322
-
323
- /**
324
- * Change visibility for parts of the current scene.
325
- */
326
- this.changePointsetsVisibility = function(name, value) {
327
- changeOrganPartsVisibilityForScene(_this.scene, name, value, 'pointsets');
328
- if (pickerScene)
329
- changeOrganPartsVisibilityForScene(pickerScene, name, value, 'pointsets');
330
- }
331
-
332
- /**
333
- * Change visibility for parts of the current scene.
334
- */
335
- this.changeOrganPartsVisibility = function(name, value, typeIn) {
336
- let type = "all";
337
- if (typeIn !== undefined)
338
- type = typeIn;
339
- changeOrganPartsVisibilityForScene(_this.scene, name, value, type);
340
- if (pickerScene)
341
- changeOrganPartsVisibilityForScene(pickerScene, name, value, type);
342
- }
343
-
344
- this.changeOrganPartsVisibilityCallback = function(name) {
345
- return function(value) {
346
- _this.changeOrganPartsVisibility(name, value);
347
- }
348
- }
349
-
350
- this.changeBackgroundColour = function(backgroundColourString) {
351
- const colour = new THREE.Color(backgroundColourString);
352
- if (_this.zincRenderer) {
353
- const internalRenderer = _this.zincRenderer.getThreeJSRenderer();
354
- internalRenderer.setClearColor( colour, 1 );
355
- }
356
- }
357
-
358
- const addOrganPart = function(systemName, partName, useDefautColour, zincObject) {
359
- for (let i = 0; i < organPartAddedCallbacks.length;i++) {
360
- organPartAddedCallbacks[i](zincObject, _this.scene.isTimeVarying());
361
- }
362
- if (useDefautColour)
363
- modelsLoader.setGeometryColour(zincObject, systemName, partName);
364
- const annotation = new (require('./annotation').annotation)();
365
- const region = zincObject.region.getFullPath();
366
- annotation.data = {species:_this.sceneData.currentSpecies, system:systemName,
367
- part:partName, group:zincObject.groupName, region: region, uuid:zincObject.uuid,
368
- lastActionOnMarker: false};
369
- zincObject.userData["annotation"] = annotation;
370
- }
371
-
372
- /**
373
- * New organs geometry has been added to the scene, add UIs and make
374
- * sure the viewport is correct.
375
- */
376
- const _addOrganPartCallback = function(systemName, partName, useDefautColour) {
377
- return function(zincObject) {
378
- addOrganPart(systemName, partName, useDefautColour, zincObject);
379
- }
380
- }
381
-
382
- const downloadCompletedCallback = function() {
383
- return function() {
384
- _this.settingsChanged();
385
- _this.sceneData.timeVarying = _this.scene.isTimeVarying();
386
- if (finishDownloadCallback)
387
- finishDownloadCallback();
388
- }
389
- }
390
-
391
- const singleItemDownloadCompletedCallback = function(systemName, partName, useDefautColour) {
392
- return function(geometry) {
393
- addOrganPart(systemName, partName, useDefautColour, geometry);
394
- _this.settingsChanged();
395
- }
396
- }
397
-
398
- /**
399
- * Toggle data field displays. Data fields displays flow/pressure and <button @click="play">Play</button>
400
- * other activities of the organs.
401
- */
402
- this.updateFieldvisibility = function(dataFields, value) {
403
- for ( let i = 0; i < dataFields.length; i ++ ) {
404
- if (value != i) {
405
- const geometryName = dataFields[i].PartName;
406
- _this.changeOrganPartsVisibility(geometryName, false);
407
- }
408
- }
409
- if (value > -1) {
410
- const partName = dataFields[value].PartName;
411
- if ((_this.scene.findGeometriesWithGroupName(partName).length > 0) ||
412
- (_this.scene.findGlyphsetsWithGroupName(partName).length > 0)) {
413
- _this.changeOrganPartsVisibility(partName, true);
414
- } else {
415
- const partDetails = getOrganDetails(dataFields[value].SystemName, partName);
416
- if (partDetails != undefined) {
417
- _this.scene.loadMetadataURL(modelsLoader.getOrgansDirectoryPrefix() + "/" + partDetails.meta);
418
- }
419
- }
420
- }
421
- }
422
-
423
- /**
424
- * Return an array containing name(s) of species that also contains the
425
- * currently displayed organs.
426
- *
427
- * @returns {Array} containing species name
428
- */
429
- this.getAvailableSpecies = function(currentSpecies, currentSystem, currentPart) {
430
- const availableSpecies = new Array();
431
- availableSpecies.push("none");
432
- const keysArray = Object.keys(organsFileMap);
433
- for (index in keysArray) {
434
- const species = keysArray[index];
435
- if (species != currentSpecies) {
436
- if (organsFileMap[species].hasOwnProperty(currentSystem) &&
437
- organsFileMap[species][currentSystem].hasOwnProperty(currentPart)) {
438
- availableSpecies.push(species);
439
- }
440
- }
441
- }
442
- return availableSpecies;
443
- }
444
-
445
- const setSceneData = function(speciesName, systemName, partName, organsDetails) {
446
- _this.sceneData.nerveMapIsActive = false;
447
- _this.sceneData.nerveMap = undefined;
448
- _this.sceneData.metaURL = "";
449
- _this.sceneData.viewURL = "";
450
- _this.sceneData.currentSpecies = speciesName;
451
- _this.sceneData.currentSystem = systemName;
452
- _this.sceneData.currentPart = partName;
453
- _this.sceneData.currentTime = 0.0;
454
- _this.sceneData.timeVarying = false;
455
- // This is used as title
456
- let name = "";
457
- if (speciesName)
458
- name = speciesName + "/";
459
- if (systemName)
460
- name = systemName + "/";
461
- if (partName)
462
- name = partName;
463
- _this.sceneData.currentName = name;
464
- }
465
-
466
- this.loadOrgansFromURL = function(url, speciesName, systemName, partName, viewURL, clearFirst) {
467
- if (_this.zincRenderer) {
468
- if (partName && (_this.sceneData.metaURL !== url)) {
469
- setSceneData(speciesName, systemName, partName, undefined);
470
- const name = _this.sceneData.currentName;
471
- let organScene = _this.zincRenderer.getSceneByName(name);
472
- if (organScene) {
473
- if (clearFirst)
474
- organScene.clearAll();
475
- } else {
476
- organScene = _this.zincRenderer.createScene(name);
477
- }
478
- for (let i = 0; i < sceneChangedCallbacks.length;i++) {
479
- sceneChangedCallbacks[i](_this.sceneData);
480
- }
481
- if (viewURL && viewURL != "") {
482
- _this.sceneData.viewURL = viewURL;
483
- organScene.loadViewURL(_this.sceneData.viewURL);
484
- } else {
485
- _this.sceneData.viewURL = undefined;
486
- }
487
- _this.sceneData.metaURL = url;
488
- organScene.loadMetadataURL(url, _addOrganPartCallback(systemName, partName, false),
489
- downloadCompletedCallback());
490
- _this.scene = organScene;
491
- _this.zincRenderer.setCurrentScene(organScene);
492
- _this.graphicsHighlight.reset();
493
- const zincCameraControl = organScene.getZincCameraControls();
494
- zincCameraControl.enableRaycaster(organScene, _pickingCallback(), _hoverCallback());
495
- zincCameraControl.setMouseButtonAction("AUXILIARY", "ZOOM");
496
- zincCameraControl.setMouseButtonAction("SECONDARY", "PAN");
497
- }
498
- }
499
- }
500
-
501
- this.loadGLTFFromURL = function(url, partName, clearFirst) {
502
- if (_this.zincRenderer) {
503
- if (partName && (_this.sceneData.metaURL !== url)) {
504
- setSceneData(undefined, undefined, partName, undefined);
505
- const name = _this.sceneData.currentName;
506
- let organScene = _this.zincRenderer.getSceneByName(name);
507
- if (organScene) {
508
- if (clearFirst)
509
- organScene.clearAll();
510
- } else {
511
- organScene = _this.zincRenderer.createScene(name);
512
- }
513
- for (let i = 0; i < sceneChangedCallbacks.length;i++) {
514
- sceneChangedCallbacks[i](_this.sceneData);
515
- }
516
- _this.sceneData.viewURL = undefined;
517
- _this.sceneData.metaURL = url;
518
- organScene.loadGLTF(url, _addOrganPartCallback(undefined, partName, false),
519
- downloadCompletedCallback());
520
- _this.scene = organScene;
521
- _this.zincRenderer.setCurrentScene(organScene);
522
- _this.graphicsHighlight.reset();
523
- const zincCameraControl = organScene.getZincCameraControls();
524
- zincCameraControl.enableRaycaster(organScene, _pickingCallback(), _hoverCallback());
525
- zincCameraControl.setMouseButtonAction("AUXILIARY", "ZOOM");
526
- zincCameraControl.setMouseButtonAction("SECONDARY", "PAN");
527
- }
528
- }
529
- }
530
-
531
- this.alignCameraWithSelectedObject = function(transitionTime) {
532
- const objects = _this.graphicsHighlight.getSelected();
533
- if (objects && objects[0] && objects[0].userData) {
534
- _this.scene.alignObjectToCameraView(objects[0].userData, transitionTime);
535
- }
536
- }
537
-
538
- this.exportSettings = function() {
539
- const settings = {};
540
- settings.name = _this.instanceName;
541
- if (_this.sceneData.currentSystem)
542
- settings.system = _this.sceneData.currentSystem;
543
- if (_this.sceneData.currentSpecies)
544
- settings.species = _this.sceneData.currentSpecies;
545
- if (_this.sceneData.currentPart)
546
- settings.part = _this.sceneData.currentPart;
547
- settings.metaURL = _this.sceneData.metaURL;
548
- if (_this.sceneData.viewURL)
549
- settings.viewURL = _this.sceneData.viewURL;
550
- settings.dialog = "Organ Viewer";
551
- return settings;
552
- }
553
-
554
- this.importSettings = function(settings) {
555
- if (settings && (settings.dialog == this.typeName)) {
556
- _this.setName(settings.name);
557
- if (settings.metaURL !== undefined && settings.metaURL != "") {
558
- _this.loadOrgansFromURL(settings.metaURL, settings.species,
559
- settings.system, settings.part, settings.viewURL, true);
560
- } else {
561
- _this.loadOrgans(settings.species, settings.system, settings.part);
562
- }
563
- return true;
564
- }
565
- return false;
566
- }
567
-
568
- /**
569
- * initialise loading of the html layout for the organs panel, this is
570
- * called when the {@link PJP.OrgansViewer} is created.
571
- *
572
- * @async
573
- */
574
- const initialise = function() {
575
- _this.initialiseRenderer(undefined);
576
- if (_this.zincRenderer) {
577
- _this.zincRenderer.addPreRenderCallbackFunction(preRenderUpdateCallback());
578
- _this.zincRenderer.addPostRenderCallbackFunction(postRenderUpdateCallback());
579
- }
580
- }
581
-
582
- initialise();
583
-
584
- }
585
-
586
- OrgansViewer.prototype = Object.create((require('./RendererModule').RendererModule).prototype);
587
- exports.OrgansViewer = OrgansViewer;
1
+ const THREE = require('zincjs').THREE;
2
+ // Current model's associate data, data fields, external link, nerve map
3
+ // informations,
4
+ // these are proived in the organsFileMap array.
5
+ const OrgansSceneData = function() {
6
+ this.currentName = "";
7
+ this.currentSystem = "";
8
+ this.currentPart = "";
9
+ this.currentSpecies = "";
10
+ this.metaURL = "";
11
+ this.viewURL = "";
12
+ this.currentTime = 0.0;
13
+ this.timeVarying = false;
14
+ }
15
+
16
+ /**
17
+ * Viewer of 3D-organs models. Users can toggle on/off different views. Data is
18
+ * displayed instead if models are not available.
19
+ *
20
+ * @class
21
+ * @param {PJP.ModelsLoader}
22
+ * ModelsLoaderIn - defined in modelsLoade.js, providing locations of
23
+ * files.
24
+ * @param {String}
25
+ * PanelName - Id of the target element to create the
26
+ * {@link PJP.OrgansViewer} on.
27
+ * @author Alan Wu
28
+ * @returns {PJP.OrgansViewer}
29
+ */
30
+ const OrgansViewer = function(ModelsLoaderIn) {
31
+ (require('./RendererModule').RendererModule).call(this);
32
+ const _this = this;
33
+ let pickerScene = undefined;
34
+ this.sceneData = new OrgansSceneData();
35
+ const timeChangedCallbacks = new Array();
36
+ const sceneChangedCallbacks = new Array();
37
+ const organPartAddedCallbacks = new Array();
38
+ let finishDownloadCallback = undefined;
39
+ const modelsLoader = ModelsLoaderIn;
40
+ this.NDCCameraControl = undefined;
41
+ _this.typeName = "Organ Viewer";
42
+
43
+ this.getSceneData = function() {
44
+ return _this.sceneData;
45
+ }
46
+
47
+ /**
48
+ * Used to update internal timer in scene when time slider has changed.
49
+ */
50
+ this.updateTime = function(value) {
51
+ let duration = 6000;
52
+ if (_this.scene)
53
+ duration = _this.scene.getDuration();
54
+ const actualTime = value / 100.0 * duration;
55
+ if (!_this.sceneData.nerveMapIsActive) {
56
+ if (pickerScene)
57
+ pickerScene.setMorphsTime(actualTime);
58
+ if (_this.scene)
59
+ _this.scene.setMorphsTime(actualTime);
60
+ }
61
+ _this.sceneData.currentTime = value;
62
+ }
63
+
64
+ /**
65
+ * Update the time slider and other renderers/scenes when time has changed.
66
+ */
67
+ const preRenderTimeUpdate = function() {
68
+ let duration = 3000;
69
+ if (_this.scene)
70
+ duration = _this.scene.getDuration();
71
+ const currentTime = _this.zincRenderer.getCurrentTime();
72
+ for (let i = 0; i < timeChangedCallbacks.length;i++) {
73
+ timeChangedCallbacks[i](currentTime);
74
+ }
75
+ if (!_this.sceneData.nerveMapIsActive && pickerScene)
76
+ pickerScene.setMorphsTime(currentTime);
77
+ if (_this.sceneData.nerveMap && _this.sceneData.nerveMap.additionalReader)
78
+ _this.sceneData.nerveMap.additionalReader.setTime(currentTime /
79
+ duration);
80
+ _this.sceneData.currentTime = currentTime / duration * 100.0;
81
+ }
82
+
83
+ this.toggleSyncControl = (flag, rotateMode) => {
84
+ let cameraControl = this.scene.getZincCameraControls();
85
+ if (flag) {
86
+ cameraControl.resetView();
87
+ this.NDCCameraControl = cameraControl.enableSyncControl();
88
+ cameraControl.setRotationMode(rotateMode);
89
+ } else {
90
+ cameraControl.disableSyncControl();
91
+ this.NDCCameraControl = undefined;
92
+ cameraControl.setRotationMode("free");
93
+ }
94
+ }
95
+
96
+ this.isSyncControl = () => {
97
+ return this.NDCCameraControl !== undefined;
98
+ }
99
+
100
+ this.setSyncControlZoomToBox = (box) => {
101
+ if (this.NDCCameraControl) {
102
+ this.NDCCameraControl.zoomToBox(box, 2);
103
+ }
104
+ }
105
+
106
+ this.setSyncControlCallback = (callback) => {
107
+ if (this.NDCCameraControl) {
108
+ this.NDCCameraControl.setEventCallback(callback);
109
+ }
110
+ }
111
+
112
+ this.setSyncControlCenterZoom = (center, zoom) => {
113
+ if (this.NDCCameraControl) {
114
+ this.NDCCameraControl.setCenterZoom(center, zoom);
115
+ }
116
+ }
117
+
118
+ const postRenderSelectedCoordinatesUpdate = function() {
119
+ //It is animating, the coordinates may have been updated
120
+ if (_this.zincRenderer.playAnimation && _this.liveUpdatesObjects) {
121
+ _this.setupLiveCoordinates(_this.liveUpdatesObjects);
122
+ }
123
+ if (_this.selectedCenter) {
124
+ const vector = new THREE.Vector3();
125
+ vector.copy(_this.selectedCenter);
126
+ const coord = _this.scene.vectorToScreenXY(vector);
127
+ _this.selectedScreenCoordinates.x = coord.x;
128
+ _this.selectedScreenCoordinates.y = coord.y;
129
+ }
130
+ }
131
+
132
+ const preRenderUpdateCallback = function() {
133
+ return function() {
134
+ preRenderTimeUpdate();
135
+ }
136
+ }
137
+
138
+ const postRenderUpdateCallback = function() {
139
+ return function() {
140
+ postRenderSelectedCoordinatesUpdate();
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Add a callback which will be called when time has changed
146
+ */
147
+ this.addTimeChangedCallback = function(callback) {
148
+ if (typeof(callback === "function"))
149
+ timeChangedCallbacks.push(callback);
150
+ }
151
+
152
+ this.setTexturePos = function(value) {
153
+ if (_this.sceneData.nerveMap && _this.sceneData.nerveMap.additionalReader)
154
+ _this.sceneData.nerveMap.additionalReader.setSliderPos(value);
155
+ }
156
+
157
+ this.addSceneChangedCallback = function(callback) {
158
+ if (typeof(callback === "function")) {
159
+ sceneChangedCallbacks.push(callback);
160
+ }
161
+ }
162
+
163
+ this.addOrganPartAddedCallback = function(callback) {
164
+ if (typeof(callback === "function"))
165
+ organPartAddedCallbacks.push(callback);
166
+ }
167
+
168
+ this.setFinishDownloadCallback = function(callback) {
169
+ if (typeof(callback === "function"))
170
+ finishDownloadCallback = callback;
171
+ }
172
+
173
+ this.unsetFinishDownloadCallback = function() {
174
+ finishDownloadCallback = undefined;
175
+ }
176
+
177
+ this.getNamedObjectsToScreenCoordinates = function(name, camera) {
178
+ const vector = new THREE.Vector3();
179
+ vector.setFromMatrixPosition( obj.matrixWorld );
180
+ const widthHalf = (width/2);
181
+ const heightHalf = (height/2);
182
+ vector.project(camera);
183
+ vector.x = ( vector.x * widthHalf ) + widthHalf;
184
+ vector.y = - ( vector.y * heightHalf ) + heightHalf;
185
+ return vector;
186
+ }
187
+
188
+ const getIdObjectFromIntersect = function(intersected) {
189
+ let id = undefined;
190
+ let intersectedObject = undefined;
191
+ if (intersected !== undefined) {
192
+ let marker = false;
193
+ if (intersected.object.userData &&
194
+ intersected.object.userData.isMarker) {
195
+ marker = true;
196
+ intersectedObject = intersected.object.userData.parent.morph;
197
+ } else {
198
+ intersectedObject = intersected.object;
199
+ }
200
+ try {
201
+ intersectedObject.userData.userData.annotation.data.lastActionOnMarker = marker;
202
+ } finally { }
203
+ if (intersectedObject) {
204
+ if (intersectedObject.name) {
205
+ id = intersectedObject.name;
206
+ } else {
207
+ const annotations = _this.getAnnotationsFromObjects(
208
+ [intersectedObject]);
209
+ if (annotations && annotations[0]) {
210
+ id = annotations[0].data.group;
211
+ }
212
+ }
213
+ }
214
+ }
215
+ return {"id":id, "object":intersectedObject};
216
+ }
217
+
218
+ /**
219
+ * Callback function when a pickable object has been picked. It will then
220
+ * call functions in tissueViewer and cellPanel to show corresponding
221
+ * informations.
222
+ *
223
+ * @callback
224
+ */
225
+ const _pickingCallback = function() {
226
+ return function(intersects, window_x, window_y) {
227
+ const intersected = _this.getIntersectedObject(intersects);
228
+ const idObject = getIdObjectFromIntersect(intersected);
229
+ const coords = { x: window_x, y: window_y };
230
+ if (idObject.id) {
231
+ if (idObject.object.userData.isGlyph) {
232
+ if (idObject.object.name)
233
+ _this.setSelectedByObjects([idObject.object], coords, true);
234
+ else
235
+ _this.setSelectedByZincObjects(idObject.object.userData.getGlyphset(),
236
+ coords, true);
237
+ } else {
238
+ _this.setSelectedByObjects([idObject.object], coords, true);
239
+ }
240
+ return;
241
+ } else {
242
+ _this.setSelectedByObjects([], coords, true);
243
+ }
244
+ }
245
+ };
246
+
247
+ /**
248
+ * Callback function when a pickable object has been hovered over.
249
+ *
250
+ * @callback
251
+ */
252
+ const _hoverCallback = function() {
253
+ return function(intersects, window_x, window_y) {
254
+ const intersected = _this.getIntersectedObject(intersects);
255
+ const idObject = getIdObjectFromIntersect(intersected);
256
+ const coords = { x: window_x, y: window_y };
257
+ if (idObject.id) {
258
+ _this.displayArea.style.cursor = "pointer";
259
+ _this.setHighlightedByObjects([idObject.object], coords, true);
260
+ return;
261
+ }
262
+ else {
263
+ _this.displayArea.style.cursor = "auto";
264
+ _this.setHighlightedByObjects([], coords, true);
265
+ }
266
+ }
267
+ };
268
+
269
+ const changeOrganPartsVisibilityForScene = function(scene, name, value, type) {
270
+ if (type == "all" || type == "geometries") {
271
+ const geometries = scene.findGeometriesWithGroupName(name);
272
+ for (let i = 0; i < geometries.length; i ++ ) {
273
+ geometries[i].setVisibility(value);
274
+ }
275
+ }
276
+ if (type == "all" || type == "glyphsets") {
277
+ const glyphsets = scene.findGlyphsetsWithGroupName(name);
278
+ for (let i = 0; i < glyphsets.length; i ++ ) {
279
+ glyphsets[i].setVisibility(value);
280
+ }
281
+ }
282
+ if (type == "all" || type == "pointsets") {
283
+ const pointsets = scene.findPointsetsWithGroupName(name);
284
+ for (let i = 0; i < pointsets.length; i ++ ) {
285
+ pointsets[i].setVisibility(value);
286
+ }
287
+ }
288
+ if (type == "all" || type == "lines") {
289
+ const lines = scene.findLinesWithGroupName(name);
290
+ for (let i = 0; i < lines.length; i ++ ) {
291
+ lines[i].setVisibility(value);
292
+ }
293
+ }
294
+ }
295
+
296
+ /**
297
+ * Change visibility for parts of the current scene.
298
+ */
299
+ this.changeGeometriesVisibility = function(name, value) {
300
+ changeOrganPartsVisibilityForScene(_this.scene, name, value, 'geometries');
301
+ if (pickerScene)
302
+ changeOrganPartsVisibilityForScene(pickerScene, name, value, 'geometries');
303
+ }
304
+
305
+ /**
306
+ * Change visibility for parts of the current scene.
307
+ */
308
+ this.changeGlyphsetsVisibility = function(name, value) {
309
+ changeOrganPartsVisibilityForScene(_this.scene, name, value, 'glyphsets');
310
+ if (pickerScene)
311
+ changeOrganPartsVisibilityForScene(pickerScene, name, value, 'glyphsets');
312
+ }
313
+
314
+ /**
315
+ * Change visibility for parts of the current scene.
316
+ */
317
+ this.changeLinesVisibility = function(name, value) {
318
+ changeOrganPartsVisibilityForScene(_this.scene, name, value, 'lines');
319
+ if (pickerScene)
320
+ changeOrganPartsVisibilityForScene(pickerScene, name, value, 'lines');
321
+ }
322
+
323
+ /**
324
+ * Change visibility for parts of the current scene.
325
+ */
326
+ this.changePointsetsVisibility = function(name, value) {
327
+ changeOrganPartsVisibilityForScene(_this.scene, name, value, 'pointsets');
328
+ if (pickerScene)
329
+ changeOrganPartsVisibilityForScene(pickerScene, name, value, 'pointsets');
330
+ }
331
+
332
+ /**
333
+ * Change visibility for parts of the current scene.
334
+ */
335
+ this.changeOrganPartsVisibility = function(name, value, typeIn) {
336
+ let type = "all";
337
+ if (typeIn !== undefined)
338
+ type = typeIn;
339
+ changeOrganPartsVisibilityForScene(_this.scene, name, value, type);
340
+ if (pickerScene)
341
+ changeOrganPartsVisibilityForScene(pickerScene, name, value, type);
342
+ }
343
+
344
+ this.changeOrganPartsVisibilityCallback = function(name) {
345
+ return function(value) {
346
+ _this.changeOrganPartsVisibility(name, value);
347
+ }
348
+ }
349
+
350
+ this.changeBackgroundColour = function(backgroundColourString) {
351
+ const colour = new THREE.Color(backgroundColourString);
352
+ if (_this.zincRenderer) {
353
+ const internalRenderer = _this.zincRenderer.getThreeJSRenderer();
354
+ internalRenderer.setClearColor( colour, 1 );
355
+ }
356
+ }
357
+
358
+ const addOrganPart = function(systemName, partName, useDefautColour, zincObject) {
359
+ for (let i = 0; i < organPartAddedCallbacks.length;i++) {
360
+ organPartAddedCallbacks[i](zincObject, _this.scene.isTimeVarying());
361
+ }
362
+ if (useDefautColour)
363
+ modelsLoader.setGeometryColour(zincObject, systemName, partName);
364
+ const annotation = new (require('./annotation').annotation)();
365
+ const region = zincObject.region.getFullPath();
366
+ annotation.data = {species:_this.sceneData.currentSpecies, system:systemName,
367
+ part:partName, group:zincObject.groupName, region: region, uuid:zincObject.uuid,
368
+ lastActionOnMarker: false};
369
+ zincObject.userData["annotation"] = annotation;
370
+ }
371
+
372
+ /**
373
+ * New organs geometry has been added to the scene, add UIs and make
374
+ * sure the viewport is correct.
375
+ */
376
+ const _addOrganPartCallback = function(systemName, partName, useDefautColour) {
377
+ return function(zincObject) {
378
+ addOrganPart(systemName, partName, useDefautColour, zincObject);
379
+ }
380
+ }
381
+
382
+ const downloadCompletedCallback = function() {
383
+ return function() {
384
+ _this.settingsChanged();
385
+ _this.sceneData.timeVarying = _this.scene.isTimeVarying();
386
+ if (finishDownloadCallback)
387
+ finishDownloadCallback();
388
+ }
389
+ }
390
+
391
+ const singleItemDownloadCompletedCallback = function(systemName, partName, useDefautColour) {
392
+ return function(geometry) {
393
+ addOrganPart(systemName, partName, useDefautColour, geometry);
394
+ _this.settingsChanged();
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Toggle data field displays. Data fields displays flow/pressure and <button @click="play">Play</button>
400
+ * other activities of the organs.
401
+ */
402
+ this.updateFieldvisibility = function(dataFields, value) {
403
+ for ( let i = 0; i < dataFields.length; i ++ ) {
404
+ if (value != i) {
405
+ const geometryName = dataFields[i].PartName;
406
+ _this.changeOrganPartsVisibility(geometryName, false);
407
+ }
408
+ }
409
+ if (value > -1) {
410
+ const partName = dataFields[value].PartName;
411
+ if ((_this.scene.findGeometriesWithGroupName(partName).length > 0) ||
412
+ (_this.scene.findGlyphsetsWithGroupName(partName).length > 0)) {
413
+ _this.changeOrganPartsVisibility(partName, true);
414
+ } else {
415
+ const partDetails = getOrganDetails(dataFields[value].SystemName, partName);
416
+ if (partDetails != undefined) {
417
+ _this.scene.loadMetadataURL(modelsLoader.getOrgansDirectoryPrefix() + "/" + partDetails.meta);
418
+ }
419
+ }
420
+ }
421
+ }
422
+
423
+ /**
424
+ * Return an array containing name(s) of species that also contains the
425
+ * currently displayed organs.
426
+ *
427
+ * @returns {Array} containing species name
428
+ */
429
+ this.getAvailableSpecies = function(currentSpecies, currentSystem, currentPart) {
430
+ const availableSpecies = new Array();
431
+ availableSpecies.push("none");
432
+ const keysArray = Object.keys(organsFileMap);
433
+ for (index in keysArray) {
434
+ const species = keysArray[index];
435
+ if (species != currentSpecies) {
436
+ if (organsFileMap[species].hasOwnProperty(currentSystem) &&
437
+ organsFileMap[species][currentSystem].hasOwnProperty(currentPart)) {
438
+ availableSpecies.push(species);
439
+ }
440
+ }
441
+ }
442
+ return availableSpecies;
443
+ }
444
+
445
+ const setSceneData = function(speciesName, systemName, partName, organsDetails) {
446
+ _this.sceneData.nerveMapIsActive = false;
447
+ _this.sceneData.nerveMap = undefined;
448
+ _this.sceneData.metaURL = "";
449
+ _this.sceneData.viewURL = "";
450
+ _this.sceneData.currentSpecies = speciesName;
451
+ _this.sceneData.currentSystem = systemName;
452
+ _this.sceneData.currentPart = partName;
453
+ _this.sceneData.currentTime = 0.0;
454
+ _this.sceneData.timeVarying = false;
455
+ // This is used as title
456
+ let name = "";
457
+ if (speciesName)
458
+ name = speciesName + "/";
459
+ if (systemName)
460
+ name = systemName + "/";
461
+ if (partName)
462
+ name = partName;
463
+ _this.sceneData.currentName = name;
464
+ }
465
+
466
+ this.loadOrgansFromURL = function(url, speciesName, systemName, partName, viewURL, clearFirst) {
467
+ if (_this.zincRenderer) {
468
+ if (partName && (_this.sceneData.metaURL !== url)) {
469
+ setSceneData(speciesName, systemName, partName, undefined);
470
+ const name = _this.sceneData.currentName;
471
+ let organScene = _this.zincRenderer.getSceneByName(name);
472
+ if (organScene) {
473
+ if (clearFirst)
474
+ organScene.clearAll();
475
+ } else {
476
+ organScene = _this.zincRenderer.createScene(name);
477
+ }
478
+ for (let i = 0; i < sceneChangedCallbacks.length;i++) {
479
+ sceneChangedCallbacks[i](_this.sceneData);
480
+ }
481
+ if (viewURL && viewURL != "") {
482
+ _this.sceneData.viewURL = viewURL;
483
+ organScene.loadViewURL(_this.sceneData.viewURL);
484
+ } else {
485
+ _this.sceneData.viewURL = undefined;
486
+ }
487
+ _this.sceneData.metaURL = url;
488
+ organScene.loadMetadataURL(url, _addOrganPartCallback(systemName, partName, false),
489
+ downloadCompletedCallback());
490
+ _this.scene = organScene;
491
+ _this.zincRenderer.setCurrentScene(organScene);
492
+ _this.graphicsHighlight.reset();
493
+ const zincCameraControl = organScene.getZincCameraControls();
494
+ zincCameraControl.enableRaycaster(organScene, _pickingCallback(), _hoverCallback());
495
+ zincCameraControl.setMouseButtonAction("AUXILIARY", "ZOOM");
496
+ zincCameraControl.setMouseButtonAction("SECONDARY", "PAN");
497
+ }
498
+ }
499
+ }
500
+
501
+ this.loadGLTFFromURL = function(url, partName, clearFirst) {
502
+ if (_this.zincRenderer) {
503
+ if (partName && (_this.sceneData.metaURL !== url)) {
504
+ setSceneData(undefined, undefined, partName, undefined);
505
+ const name = _this.sceneData.currentName;
506
+ let organScene = _this.zincRenderer.getSceneByName(name);
507
+ if (organScene) {
508
+ if (clearFirst)
509
+ organScene.clearAll();
510
+ } else {
511
+ organScene = _this.zincRenderer.createScene(name);
512
+ }
513
+ for (let i = 0; i < sceneChangedCallbacks.length;i++) {
514
+ sceneChangedCallbacks[i](_this.sceneData);
515
+ }
516
+ _this.sceneData.viewURL = undefined;
517
+ _this.sceneData.metaURL = url;
518
+ organScene.loadGLTF(url, _addOrganPartCallback(undefined, partName, false),
519
+ downloadCompletedCallback());
520
+ _this.scene = organScene;
521
+ _this.zincRenderer.setCurrentScene(organScene);
522
+ _this.graphicsHighlight.reset();
523
+ const zincCameraControl = organScene.getZincCameraControls();
524
+ zincCameraControl.enableRaycaster(organScene, _pickingCallback(), _hoverCallback());
525
+ zincCameraControl.setMouseButtonAction("AUXILIARY", "ZOOM");
526
+ zincCameraControl.setMouseButtonAction("SECONDARY", "PAN");
527
+ }
528
+ }
529
+ }
530
+
531
+ this.alignCameraWithSelectedObject = function(transitionTime) {
532
+ const objects = _this.graphicsHighlight.getSelected();
533
+ if (objects && objects[0] && objects[0].userData) {
534
+ _this.scene.alignObjectToCameraView(objects[0].userData, transitionTime);
535
+ }
536
+ }
537
+
538
+ this.exportSettings = function() {
539
+ const settings = {};
540
+ settings.name = _this.instanceName;
541
+ if (_this.sceneData.currentSystem)
542
+ settings.system = _this.sceneData.currentSystem;
543
+ if (_this.sceneData.currentSpecies)
544
+ settings.species = _this.sceneData.currentSpecies;
545
+ if (_this.sceneData.currentPart)
546
+ settings.part = _this.sceneData.currentPart;
547
+ settings.metaURL = _this.sceneData.metaURL;
548
+ if (_this.sceneData.viewURL)
549
+ settings.viewURL = _this.sceneData.viewURL;
550
+ settings.dialog = "Organ Viewer";
551
+ return settings;
552
+ }
553
+
554
+ this.importSettings = function(settings) {
555
+ if (settings && (settings.dialog == this.typeName)) {
556
+ _this.setName(settings.name);
557
+ if (settings.metaURL !== undefined && settings.metaURL != "") {
558
+ _this.loadOrgansFromURL(settings.metaURL, settings.species,
559
+ settings.system, settings.part, settings.viewURL, true);
560
+ } else {
561
+ _this.loadOrgans(settings.species, settings.system, settings.part);
562
+ }
563
+ return true;
564
+ }
565
+ return false;
566
+ }
567
+
568
+ /**
569
+ * initialise loading of the html layout for the organs panel, this is
570
+ * called when the {@link PJP.OrgansViewer} is created.
571
+ *
572
+ * @async
573
+ */
574
+ const initialise = function() {
575
+ _this.initialiseRenderer(undefined);
576
+ if (_this.zincRenderer) {
577
+ _this.zincRenderer.addPreRenderCallbackFunction(preRenderUpdateCallback());
578
+ _this.zincRenderer.addPostRenderCallbackFunction(postRenderUpdateCallback());
579
+ }
580
+ }
581
+
582
+ initialise();
583
+
584
+ }
585
+
586
+ OrgansViewer.prototype = Object.create((require('./RendererModule').RendererModule).prototype);
587
+ exports.OrgansViewer = OrgansViewer;