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