@abi-software/scaffoldvuer 1.21.1-beta.2 → 2.0.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.
- package/README.md +31 -12
- package/dist/index.html +9 -6
- package/dist/scaffoldvuer.js +14095 -13154
- package/dist/scaffoldvuer.umd.cjs +48 -48
- package/dist/style.css +1 -1
- package/eslint.config.js +37 -9
- package/package.json +10 -3
- package/public/index.html +9 -6
- package/src/App.vue +312 -279
- package/src/ScaffoldVuer-wc.js +4 -4
- package/src/app/DropZone.vue +11 -27
- package/src/app/ModelsInformation.js +22 -19
- package/src/app/ModelsTable.vue +42 -65
- package/src/app/TextureDemos.js +38 -64
- package/src/assets/_variables.scss +12 -10
- package/src/components/GlyphsControls.vue +3 -23
- package/src/components/LinesControls.vue +27 -66
- package/src/components/OpacityControls.vue +22 -26
- package/src/components/PointsControls.vue +20 -71
- package/src/components/PrimitiveControls.vue +35 -49
- package/src/components/ScaffoldOverlay.vue +63 -63
- package/src/components/ScaffoldTooltip.vue +36 -49
- package/src/components/ScaffoldTreeControls.vue +81 -129
- package/src/components/ScaffoldVuer.vue +509 -498
- package/src/components/TextureSlidesControls.vue +22 -64
- package/src/components/TransformationControls.vue +15 -42
- package/src/components/index.js +2 -2
- package/src/main.js +16 -18
- package/src/scripts/Annotation.js +3 -3
- package/src/scripts/BaseModule.js +26 -30
- package/src/scripts/EventNotifier.js +30 -36
- package/src/scripts/GraphicsHighlight.js +43 -50
- package/src/scripts/LocalFilesHelper.js +27 -26
- package/src/scripts/MappedNerves.js +2139 -697
- package/src/scripts/MappedOrgans.js +24 -25
- package/src/scripts/OrgansRenderer.js +445 -425
- package/src/scripts/RendererModule.js +133 -122
- package/src/scripts/Search.js +135 -151
- package/src/scripts/Utilities.js +129 -127
- package/src/scripts/WebGL.js +57 -91
- package/src/scripts/niftiHelper.js +3 -3
- package/src/store/index.js +7 -7
- package/vite.config.js +51 -50
- package/vite.static-build.js +7 -7
- package/vuese-generator.js +48 -56
package/src/scripts/Utilities.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { THREE } from 'zincjs';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
// This will be the config for nerves selection and highlight
|
|
4
|
+
export const NERVE_CONFIG = {
|
|
5
|
+
SELECTED_COLOUR: '#00ff00',
|
|
6
|
+
HIGHLIGHTED_COLOUR: '#ff0000',
|
|
7
|
+
DEFAULT_RADIUS: 1,
|
|
8
|
+
DEFAULT_RADIAL_SEGMENTS: 8,
|
|
9
|
+
ZOOM_RADIUS: 5,
|
|
10
|
+
ZOOM_RADIAL_SEGMENTS: 12,
|
|
11
|
+
};
|
|
12
12
|
|
|
13
13
|
export const createListFromPrimitives = (primitives, list) => {
|
|
14
14
|
if (primitives) {
|
|
15
|
-
let id =
|
|
16
|
-
primitives.forEach(primitive => {
|
|
15
|
+
let id = '';
|
|
16
|
+
primitives.forEach((primitive) => {
|
|
17
17
|
id = primitive.uuid;
|
|
18
18
|
if (primitive.region) {
|
|
19
|
-
id = primitive.region.uuid +
|
|
19
|
+
id = primitive.region.uuid + '/' + id;
|
|
20
20
|
}
|
|
21
21
|
if (primitive && primitive.getVisibility()) {
|
|
22
22
|
list.push(id);
|
|
@@ -24,14 +24,14 @@ export const createListFromPrimitives = (primitives, list) => {
|
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
return list;
|
|
27
|
-
}
|
|
27
|
+
};
|
|
28
28
|
|
|
29
29
|
const getDistance = (point1, point2) => {
|
|
30
30
|
const dist0 = point1[0] - point2[0];
|
|
31
31
|
const dist1 = point1[1] - point2[1];
|
|
32
32
|
const dist2 = point1[2] - point2[2];
|
|
33
33
|
return Math.sqrt(dist0 * dist0 + dist1 * dist1 + dist2 * dist2);
|
|
34
|
-
}
|
|
34
|
+
};
|
|
35
35
|
|
|
36
36
|
export const getEditablePoint = (eventIdentifiers) => {
|
|
37
37
|
//const zincObjects = event.zincObjects;
|
|
@@ -42,13 +42,13 @@ export const getEditablePoint = (eventIdentifiers) => {
|
|
|
42
42
|
if (info && info.index > -1) {
|
|
43
43
|
const v = zincObject.getVerticesByIndex(info.index);
|
|
44
44
|
if (v) {
|
|
45
|
-
return { zincObject, index: info.index, point: v};
|
|
45
|
+
return { zincObject, index: info.index, point: v };
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
return undefined;
|
|
51
|
-
}
|
|
51
|
+
};
|
|
52
52
|
|
|
53
53
|
export const getDeletableObjects = (eventIdentifiers) => {
|
|
54
54
|
const zincObject = eventIdentifiers[0].data?.zincObject;
|
|
@@ -58,7 +58,7 @@ export const getDeletableObjects = (eventIdentifiers) => {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
return undefined;
|
|
61
|
-
}
|
|
61
|
+
};
|
|
62
62
|
|
|
63
63
|
export const getEditableLines = (eventIdentifiers) => {
|
|
64
64
|
const zincObject = eventIdentifiers[0].data?.zincObject;
|
|
@@ -72,16 +72,26 @@ export const getEditableLines = (eventIdentifiers) => {
|
|
|
72
72
|
const dist0 = getDistance(v[0], [p.x, p.y, p.z]);
|
|
73
73
|
const dist1 = getDistance(v[1], [p.x, p.y, p.z]);
|
|
74
74
|
if (dist0 > dist1) {
|
|
75
|
-
return {
|
|
75
|
+
return {
|
|
76
|
+
zincObject,
|
|
77
|
+
faceIndex: info.faceIndex,
|
|
78
|
+
vertexIndex: info.faceIndex * 2 + 1,
|
|
79
|
+
point: v[0],
|
|
80
|
+
};
|
|
76
81
|
} else {
|
|
77
|
-
return {
|
|
82
|
+
return {
|
|
83
|
+
zincObject,
|
|
84
|
+
faceIndex: info.faceIndex,
|
|
85
|
+
vertexIndex: info.faceIndex * 2,
|
|
86
|
+
point: v[1],
|
|
87
|
+
};
|
|
78
88
|
}
|
|
79
89
|
}
|
|
80
90
|
}
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
93
|
return undefined;
|
|
84
|
-
}
|
|
94
|
+
};
|
|
85
95
|
|
|
86
96
|
export const getClickedObjects = (event) => {
|
|
87
97
|
const zincObjects = event.zincObjects;
|
|
@@ -90,7 +100,7 @@ export const getClickedObjects = (event) => {
|
|
|
90
100
|
return zincObject;
|
|
91
101
|
}
|
|
92
102
|
return undefined;
|
|
93
|
-
}
|
|
103
|
+
};
|
|
94
104
|
|
|
95
105
|
export const movePoint = (zincObject, index, diff) => {
|
|
96
106
|
if (zincObject?.isEditable && zincObject?.isPointset) {
|
|
@@ -113,7 +123,7 @@ export const movePoint = (zincObject, index, diff) => {
|
|
|
113
123
|
}
|
|
114
124
|
}
|
|
115
125
|
return false;
|
|
116
|
-
}
|
|
126
|
+
};
|
|
117
127
|
|
|
118
128
|
export const getLineDistance = (zincObject, faceIndex) => {
|
|
119
129
|
if (zincObject?.isEditable && zincObject?.isLines2) {
|
|
@@ -125,7 +135,7 @@ export const getLineDistance = (zincObject, faceIndex) => {
|
|
|
125
135
|
}
|
|
126
136
|
}
|
|
127
137
|
return 0;
|
|
128
|
-
}
|
|
138
|
+
};
|
|
129
139
|
|
|
130
140
|
//Move or extend a line
|
|
131
141
|
export const moveAndExtendLine = (zincObject, faceIndex, unit, extendOnly) => {
|
|
@@ -136,7 +146,7 @@ export const moveAndExtendLine = (zincObject, faceIndex, unit, extendOnly) => {
|
|
|
136
146
|
let d = [v[1][0] - v[0][0], v[1][1] - v[0][1], v[1][2] - v[0][2]];
|
|
137
147
|
const mag = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
|
|
138
148
|
for (let i = 0; i < 3; i++) {
|
|
139
|
-
d[i] = d[i] / mag * unit;
|
|
149
|
+
d[i] = (d[i] / mag) * unit;
|
|
140
150
|
if (!extendOnly) {
|
|
141
151
|
v[0][i] = v[0][i] + d[i];
|
|
142
152
|
v[1][i] = v[1][i] + d[i];
|
|
@@ -151,30 +161,26 @@ export const moveAndExtendLine = (zincObject, faceIndex, unit, extendOnly) => {
|
|
|
151
161
|
}
|
|
152
162
|
}
|
|
153
163
|
return false;
|
|
154
|
-
}
|
|
164
|
+
};
|
|
155
165
|
|
|
156
166
|
export const updateBoundingBox = (geometry, scene) => {
|
|
157
167
|
const box = scene.getBoundingBox();
|
|
158
168
|
const dim = new THREE.Vector3().subVectors(box.max, box.min);
|
|
159
169
|
const boxGeo = new THREE.BoxGeometry(dim.x, dim.y, dim.z);
|
|
160
|
-
dim.addVectors(box.min, box.max).multiplyScalar(
|
|
161
|
-
const positions = boxGeo.getAttribute(
|
|
170
|
+
dim.addVectors(box.min, box.max).multiplyScalar(0.5);
|
|
171
|
+
const positions = boxGeo.getAttribute('position');
|
|
162
172
|
const count = positions.count;
|
|
163
173
|
const vertices = [];
|
|
164
174
|
for (let i = 0; i < count; i++) {
|
|
165
|
-
vertices[i] = [
|
|
166
|
-
positions.array[i * 3],
|
|
167
|
-
positions.array[i * 3 + 1],
|
|
168
|
-
positions.array[i * 3 + 2]
|
|
169
|
-
];
|
|
175
|
+
vertices[i] = [positions.array[i * 3], positions.array[i * 3 + 1], positions.array[i * 3 + 2]];
|
|
170
176
|
}
|
|
171
|
-
geometry.editVertices(vertices
|
|
177
|
+
geometry.editVertices(vertices, 0);
|
|
172
178
|
geometry.setPosition(dim.x, dim.y, dim.z);
|
|
173
179
|
boxGeo.dispose();
|
|
174
|
-
}
|
|
180
|
+
};
|
|
175
181
|
|
|
176
182
|
export const extractAllFullPaths = (item, list) => {
|
|
177
|
-
let nodeName =
|
|
183
|
+
let nodeName = '';
|
|
178
184
|
if (item.isRegion) {
|
|
179
185
|
nodeName = `__r${item.regionPath}`;
|
|
180
186
|
}
|
|
@@ -182,37 +188,35 @@ export const extractAllFullPaths = (item, list) => {
|
|
|
182
188
|
nodeName = `${item.regionPath}/${item.label}`;
|
|
183
189
|
}
|
|
184
190
|
list.push(nodeName);
|
|
185
|
-
if (item.children)
|
|
186
|
-
|
|
187
|
-
}
|
|
191
|
+
if (item.children) item.children.forEach((child) => extractAllFullPaths(child, list));
|
|
192
|
+
};
|
|
188
193
|
|
|
189
194
|
export const findObjectsWithNames = (rootRegion, names, regionPath, transverse) => {
|
|
190
195
|
let targetRegion = rootRegion;
|
|
191
196
|
const targetObjects = [];
|
|
192
|
-
if (regionPath)
|
|
193
|
-
targetRegion = rootRegion.findChildFromPath(regionPath);
|
|
197
|
+
if (regionPath) targetRegion = rootRegion.findChildFromPath(regionPath);
|
|
194
198
|
if (targetRegion) {
|
|
195
199
|
const isArray = Array.isArray(names);
|
|
196
200
|
let array = names;
|
|
197
201
|
if (!isArray) {
|
|
198
202
|
array = [array];
|
|
199
203
|
}
|
|
200
|
-
array.forEach(name => {
|
|
204
|
+
array.forEach((name) => {
|
|
201
205
|
const temp = targetRegion.findObjectsWithGroupName(name, transverse);
|
|
202
206
|
targetObjects.push(...temp);
|
|
203
207
|
});
|
|
204
208
|
}
|
|
205
209
|
return targetObjects;
|
|
206
|
-
}
|
|
210
|
+
};
|
|
207
211
|
|
|
208
212
|
export const getAllObjects = (scene) => {
|
|
209
213
|
let objects = scene.getRootRegion().getAllObjects(true);
|
|
210
214
|
let id = 1;
|
|
211
|
-
return objects.map(object => Object.assign(object, { id: id++ })); // Add id to each object
|
|
212
|
-
}
|
|
215
|
+
return objects.map((object) => Object.assign(object, { id: id++ })); // Add id to each object
|
|
216
|
+
};
|
|
213
217
|
|
|
214
218
|
const findObjectWithUUID = (objects, uuid, remove) => {
|
|
215
|
-
const index = objects.findIndex(obj => obj.uuid === uuid);
|
|
219
|
+
const index = objects.findIndex((obj) => obj.uuid === uuid);
|
|
216
220
|
let object = undefined;
|
|
217
221
|
if (index > -1) {
|
|
218
222
|
object = objects[index];
|
|
@@ -221,7 +225,7 @@ const findObjectWithUUID = (objects, uuid, remove) => {
|
|
|
221
225
|
}
|
|
222
226
|
}
|
|
223
227
|
return object;
|
|
224
|
-
}
|
|
228
|
+
};
|
|
225
229
|
|
|
226
230
|
export const convertUUIDsToFullPaths = (rootRegion, IDs) => {
|
|
227
231
|
const results = [];
|
|
@@ -234,8 +238,8 @@ export const convertUUIDsToFullPaths = (rootRegion, IDs) => {
|
|
|
234
238
|
let primitive = undefined;
|
|
235
239
|
let regionID = undefined;
|
|
236
240
|
|
|
237
|
-
IDs.forEach(id => {
|
|
238
|
-
const uuids = id.split(
|
|
241
|
+
IDs.forEach((id) => {
|
|
242
|
+
const uuids = id.split('/');
|
|
239
243
|
regionID = uuids[0];
|
|
240
244
|
region = findObjectWithUUID(allRegions, regionID, false);
|
|
241
245
|
if (region) {
|
|
@@ -257,28 +261,26 @@ export const convertUUIDsToFullPaths = (rootRegion, IDs) => {
|
|
|
257
261
|
});
|
|
258
262
|
}
|
|
259
263
|
return results;
|
|
260
|
-
}
|
|
264
|
+
};
|
|
261
265
|
|
|
262
266
|
export const createUnqiuesFromObjects = (zincObjects) => {
|
|
263
267
|
if (zincObjects) {
|
|
264
268
|
const expanded = [];
|
|
265
|
-
zincObjects.forEach(obj => {
|
|
269
|
+
zincObjects.forEach((obj) => {
|
|
266
270
|
if (obj.isZincObject) {
|
|
267
271
|
expanded.push(obj);
|
|
268
272
|
} else if (obj.isRegion) {
|
|
269
273
|
expanded.push(...obj.getAllObjects(true));
|
|
270
274
|
}
|
|
271
275
|
});
|
|
272
|
-
const uniq = Object.values(
|
|
273
|
-
expanded.reduce((acc, obj) => ({ ...acc, [obj.uuid]: obj }), {})
|
|
274
|
-
);
|
|
276
|
+
const uniq = Object.values(expanded.reduce((acc, obj) => ({ ...acc, [obj.uuid]: obj }), {}));
|
|
275
277
|
return uniq;
|
|
276
278
|
}
|
|
277
279
|
return [];
|
|
278
|
-
}
|
|
280
|
+
};
|
|
279
281
|
|
|
280
282
|
export const getObjectsFromAnnotations = (scene, annotations) => {
|
|
281
|
-
const returned = {label:
|
|
283
|
+
const returned = { label: 'Multiple selections', regionPath: '', objects: [] };
|
|
282
284
|
if (annotations && scene) {
|
|
283
285
|
const rpList = {};
|
|
284
286
|
const rootRegion = scene.getRootRegion();
|
|
@@ -286,12 +288,12 @@ export const getObjectsFromAnnotations = (scene, annotations) => {
|
|
|
286
288
|
returned.regionPath = annotations[0].data.region;
|
|
287
289
|
returned.label = annotations[0].data.group;
|
|
288
290
|
}
|
|
289
|
-
annotations.forEach(annotation => {
|
|
291
|
+
annotations.forEach((annotation) => {
|
|
290
292
|
if (!annotation.data.region.includes(returned.regionPath)) {
|
|
291
|
-
returned.regionPath =
|
|
293
|
+
returned.regionPath = '';
|
|
292
294
|
}
|
|
293
295
|
if (returned.label !== annotation.data.group) {
|
|
294
|
-
returned.label =
|
|
296
|
+
returned.label = 'Multiple selections';
|
|
295
297
|
}
|
|
296
298
|
const region = rootRegion.findChildFromPath(annotation.data.region);
|
|
297
299
|
if (!rpList[region.uuid]) {
|
|
@@ -302,7 +304,7 @@ export const getObjectsFromAnnotations = (scene, annotations) => {
|
|
|
302
304
|
});
|
|
303
305
|
}
|
|
304
306
|
return returned;
|
|
305
|
-
}
|
|
307
|
+
};
|
|
306
308
|
|
|
307
309
|
const getCoordinatesForAnnotationFeature = (zincObject) => {
|
|
308
310
|
const mesh = zincObject.getMorph();
|
|
@@ -311,11 +313,7 @@ const getCoordinatesForAnnotationFeature = (zincObject) => {
|
|
|
311
313
|
if (zincObject.isPointset) {
|
|
312
314
|
const positionArray = mesh.pointPositions;
|
|
313
315
|
for (let i = 0; i < zincObject.drawRange; i++) {
|
|
314
|
-
coords.push([
|
|
315
|
-
positionArray[vIndex++],
|
|
316
|
-
positionArray[vIndex++],
|
|
317
|
-
positionArray[vIndex++],
|
|
318
|
-
]);
|
|
316
|
+
coords.push([positionArray[vIndex++], positionArray[vIndex++], positionArray[vIndex++]]);
|
|
319
317
|
}
|
|
320
318
|
return coords;
|
|
321
319
|
}
|
|
@@ -323,86 +321,102 @@ const getCoordinatesForAnnotationFeature = (zincObject) => {
|
|
|
323
321
|
if (zincObject.isLines2) {
|
|
324
322
|
attr = 'instanceStart';
|
|
325
323
|
}
|
|
326
|
-
const position = mesh.geometry.getAttribute(
|
|
324
|
+
const position = mesh.geometry.getAttribute(attr);
|
|
327
325
|
for (let i = 0; i < zincObject.drawRange; i++) {
|
|
328
|
-
coords.push([
|
|
329
|
-
position.array[vIndex++],
|
|
330
|
-
position.array[vIndex++],
|
|
331
|
-
position.array[vIndex++],
|
|
332
|
-
]);
|
|
326
|
+
coords.push([position.array[vIndex++], position.array[vIndex++], position.array[vIndex++]]);
|
|
333
327
|
}
|
|
334
328
|
return coords;
|
|
335
|
-
}
|
|
329
|
+
};
|
|
336
330
|
|
|
337
|
-
export const createNewAnnotationsWithFeatures = (
|
|
338
|
-
|
|
331
|
+
export const createNewAnnotationsWithFeatures = (
|
|
332
|
+
zincObject,
|
|
333
|
+
region,
|
|
334
|
+
group,
|
|
335
|
+
scaffoldUrl,
|
|
336
|
+
comment,
|
|
337
|
+
) => {
|
|
338
|
+
let type;
|
|
339
339
|
if (zincObject.isPointset) {
|
|
340
|
-
type =
|
|
340
|
+
type = 'MultiPoint';
|
|
341
341
|
} else if (zincObject.isLines2) {
|
|
342
|
-
type =
|
|
342
|
+
type = 'MultiLineString';
|
|
343
343
|
} else {
|
|
344
|
-
type =
|
|
344
|
+
type = 'Feature';
|
|
345
345
|
}
|
|
346
|
-
const drawn = type ===
|
|
347
|
-
const label = type ===
|
|
346
|
+
const drawn = type === 'Feature' ? false : true;
|
|
347
|
+
const label = type === 'Feature' ? 'Feature annotation' : 'Drawn annotation';
|
|
348
348
|
if (type) {
|
|
349
349
|
const coords = getCoordinatesForAnnotationFeature(zincObject);
|
|
350
350
|
//Check if region ends with a slash
|
|
351
|
-
let fullName = region.slice(-1) ===
|
|
351
|
+
let fullName = region.slice(-1) === '/' ? region : region + '/';
|
|
352
352
|
fullName = fullName + group;
|
|
353
353
|
const featureID = fullName;
|
|
354
354
|
const userAnnotation = {
|
|
355
355
|
resource: scaffoldUrl,
|
|
356
356
|
item: {
|
|
357
|
-
|
|
357
|
+
id: featureID,
|
|
358
358
|
},
|
|
359
359
|
body: {
|
|
360
360
|
evidence: [],
|
|
361
361
|
comment: comment,
|
|
362
362
|
},
|
|
363
363
|
feature: {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
364
|
+
id: featureID,
|
|
365
|
+
properties: {
|
|
366
|
+
drawn: drawn,
|
|
367
|
+
label: label,
|
|
368
|
+
},
|
|
369
|
+
geometry: {
|
|
370
|
+
coordinates: coords,
|
|
371
|
+
type: type,
|
|
368
372
|
},
|
|
369
|
-
"geometry": {
|
|
370
|
-
"coordinates": coords,
|
|
371
|
-
"type": type
|
|
372
|
-
}
|
|
373
373
|
},
|
|
374
|
-
}
|
|
375
|
-
if (comment ===
|
|
374
|
+
};
|
|
375
|
+
if (comment === 'Deleted') {
|
|
376
376
|
userAnnotation.feature = undefined;
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
return userAnnotation;
|
|
380
380
|
}
|
|
381
|
-
}
|
|
381
|
+
};
|
|
382
382
|
|
|
383
383
|
/*
|
|
384
384
|
* Add/Update drawn annotations to the server.
|
|
385
385
|
*/
|
|
386
|
-
export const addUserAnnotationWithFeature = (
|
|
387
|
-
|
|
388
|
-
|
|
386
|
+
export const addUserAnnotationWithFeature = (
|
|
387
|
+
service,
|
|
388
|
+
userToken,
|
|
389
|
+
zincObject,
|
|
390
|
+
region,
|
|
391
|
+
group,
|
|
392
|
+
scaffoldUrl,
|
|
393
|
+
action,
|
|
394
|
+
) => {
|
|
395
|
+
const annotation = createNewAnnotationsWithFeatures(
|
|
396
|
+
zincObject,
|
|
397
|
+
region,
|
|
398
|
+
group,
|
|
399
|
+
scaffoldUrl,
|
|
400
|
+
action,
|
|
401
|
+
);
|
|
389
402
|
if (annotation) {
|
|
390
403
|
if (service && service.currentUser) {
|
|
391
|
-
annotation.creator = {...service.currentUser};
|
|
404
|
+
annotation.creator = { ...service.currentUser };
|
|
392
405
|
if (!annotation.creator.orcid) annotation.creator.orcid = '0000-0000-0000-0000';
|
|
393
|
-
service
|
|
394
|
-
|
|
395
|
-
|
|
406
|
+
service
|
|
407
|
+
.addAnnotation(userToken, annotation)
|
|
408
|
+
.then((response) => {
|
|
409
|
+
if (!response.annotationId) {
|
|
410
|
+
console.log('There is a problem with the submission, please try again later');
|
|
411
|
+
}
|
|
412
|
+
})
|
|
413
|
+
.catch(() => {
|
|
396
414
|
console.log('There is a problem with the submission, please try again later');
|
|
397
|
-
}
|
|
398
|
-
})
|
|
399
|
-
.catch(() => {
|
|
400
|
-
console.log('There is a problem with the submission, please try again later');
|
|
401
|
-
})
|
|
415
|
+
});
|
|
402
416
|
}
|
|
403
417
|
return annotation;
|
|
404
418
|
}
|
|
405
|
-
}
|
|
419
|
+
};
|
|
406
420
|
|
|
407
421
|
/*
|
|
408
422
|
* Get the drawn annotation stored on the annotation server
|
|
@@ -410,12 +424,12 @@ export const addUserAnnotationWithFeature = (service, userToken, zincObject,
|
|
|
410
424
|
export const getDrawnAnnotations = async (service, userToken, scaffoldUrl) => {
|
|
411
425
|
const resource = scaffoldUrl;
|
|
412
426
|
return await service.drawnFeatures(userToken, resource);
|
|
413
|
-
}
|
|
427
|
+
};
|
|
414
428
|
|
|
415
429
|
/*
|
|
416
430
|
* Convert features store in annotation server into primitives
|
|
417
431
|
*/
|
|
418
|
-
export const annotationFeaturesToPrimitives = (scene, features)
|
|
432
|
+
export const annotationFeaturesToPrimitives = (scene, features) => {
|
|
419
433
|
if (scene) {
|
|
420
434
|
features.forEach((feature) => {
|
|
421
435
|
const geometry = feature.geometry;
|
|
@@ -424,36 +438,24 @@ export const annotationFeaturesToPrimitives = (scene, features) => {
|
|
|
424
438
|
const region = regionGroup.substring(0, last);
|
|
425
439
|
const group = regionGroup.substring(last + 1);
|
|
426
440
|
let object = undefined;
|
|
427
|
-
if (geometry.type ===
|
|
428
|
-
object = scene.createPoints(
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
geometry.coordinates,
|
|
432
|
-
group,
|
|
433
|
-
0x0022ee,
|
|
434
|
-
);
|
|
435
|
-
} else if (geometry.type === "MultiLineString") {
|
|
436
|
-
object = scene.createLines(
|
|
437
|
-
region,
|
|
438
|
-
group,
|
|
439
|
-
geometry.coordinates,
|
|
440
|
-
0x00ee22,
|
|
441
|
-
);
|
|
441
|
+
if (geometry.type === 'MultiPoint') {
|
|
442
|
+
object = scene.createPoints(region, group, geometry.coordinates, group, 0x0022ee);
|
|
443
|
+
} else if (geometry.type === 'MultiLineString') {
|
|
444
|
+
object = scene.createLines(region, group, geometry.coordinates, 0x00ee22);
|
|
442
445
|
}
|
|
443
446
|
if (object) object.zincObject.isEditable = true;
|
|
444
447
|
});
|
|
445
448
|
}
|
|
446
|
-
}
|
|
449
|
+
};
|
|
447
450
|
|
|
448
|
-
export const objectsToZincObjects = function(objects) {
|
|
451
|
+
export const objectsToZincObjects = function (objects) {
|
|
449
452
|
const zincObjects = [];
|
|
450
453
|
for (let i = 0; i < objects.length; i++) {
|
|
451
454
|
let zincObject = objects[i].userData;
|
|
452
455
|
if (zincObject) {
|
|
453
456
|
if (zincObject.isGlyph || zincObject.isGlyphset) {
|
|
454
457
|
let glyphset = zincObject;
|
|
455
|
-
if (zincObject.isGlyph)
|
|
456
|
-
glyphset = zincObject.getGlyphset();
|
|
458
|
+
if (zincObject.isGlyph) glyphset = zincObject.getGlyphset();
|
|
457
459
|
zincObjects.push(glyphset);
|
|
458
460
|
} else {
|
|
459
461
|
zincObjects.push(zincObject);
|
|
@@ -461,4 +463,4 @@ export const objectsToZincObjects = function(objects) {
|
|
|
461
463
|
}
|
|
462
464
|
}
|
|
463
465
|
return zincObjects;
|
|
464
|
-
}
|
|
466
|
+
};
|
package/src/scripts/WebGL.js
CHANGED
|
@@ -1,96 +1,62 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Checks whether the browser can run the ZincJS renderer. ZincJS uses
|
|
3
|
+
* THREE.WebGPURenderer, which renders with WebGPU when it is available and
|
|
4
|
+
* falls back to WebGL 2 otherwise. WebGL 1 is not supported.
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
2: window.WebGL2RenderingContext
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
var message = 'This module requires <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#008">$1</a> support but your $0 does not seem to support it.';
|
|
63
|
-
|
|
64
|
-
var element = document.createElement( 'div' );
|
|
65
|
-
element.id = 'webglmessage';
|
|
66
|
-
element.style.fontFamily = 'monospace';
|
|
67
|
-
element.style.fontSize = '20px';
|
|
68
|
-
element.style.fontWeight = 'normal';
|
|
69
|
-
element.style.textAlign = 'center';
|
|
70
|
-
element.style.background = '#fff';
|
|
71
|
-
element.style.color = '#000';
|
|
72
|
-
element.style.padding = '1.5em';
|
|
73
|
-
element.style.width = '400px';
|
|
74
|
-
element.style.margin = '5em auto 0';
|
|
75
|
-
|
|
76
|
-
if ( contexts[ version ] ) {
|
|
77
|
-
|
|
78
|
-
message = message.replace( '$0', 'graphics card' );
|
|
79
|
-
|
|
80
|
-
} else {
|
|
81
|
-
|
|
82
|
-
message = message.replace( '$0', 'browser' );
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
message = message.replace( '$1', names[ version ] );
|
|
87
|
-
|
|
88
|
-
element.innerHTML = message;
|
|
89
|
-
|
|
90
|
-
return element;
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
7
|
+
const GPU_SUPPORT = {
|
|
8
|
+
isWebGPUAvailable: async function () {
|
|
9
|
+
try {
|
|
10
|
+
if (typeof navigator === 'undefined' || !navigator.gpu) return false;
|
|
11
|
+
//navigator.gpu can exist without a usable adapter, e.g. on a blocklisted GPU.
|
|
12
|
+
const adapter = await navigator.gpu.requestAdapter();
|
|
13
|
+
return !!adapter;
|
|
14
|
+
} catch (_e) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
isWebGL2Available: function () {
|
|
20
|
+
try {
|
|
21
|
+
const canvas = document.createElement('canvas');
|
|
22
|
+
return !!(window.WebGL2RenderingContext && canvas.getContext('webgl2'));
|
|
23
|
+
} catch (_e) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
isRendererSupported: async function () {
|
|
29
|
+
return (await this.isWebGPUAvailable()) || this.isWebGL2Available();
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
getErrorMessage: function () {
|
|
33
|
+
let message =
|
|
34
|
+
'This module requires <a href="https://caniuse.com/webgpu" style="color:#008">WebGPU</a> or ' +
|
|
35
|
+
'<a href="https://caniuse.com/webgl2" style="color:#008">WebGL 2</a> support but your $0 does not seem to support either.';
|
|
36
|
+
|
|
37
|
+
const element = document.createElement('div');
|
|
38
|
+
element.id = 'webglmessage';
|
|
39
|
+
element.style.fontFamily = 'monospace';
|
|
40
|
+
element.style.fontSize = '20px';
|
|
41
|
+
element.style.fontWeight = 'normal';
|
|
42
|
+
element.style.textAlign = 'center';
|
|
43
|
+
element.style.background = '#fff';
|
|
44
|
+
element.style.color = '#000';
|
|
45
|
+
element.style.padding = '1.5em';
|
|
46
|
+
element.style.width = '400px';
|
|
47
|
+
element.style.margin = '5em auto 0';
|
|
48
|
+
|
|
49
|
+
//The browser knows the APIs but could not create a context: blame the graphics card.
|
|
50
|
+
if ((typeof navigator !== 'undefined' && navigator.gpu) || window.WebGL2RenderingContext) {
|
|
51
|
+
message = message.replace('$0', 'graphics card');
|
|
52
|
+
} else {
|
|
53
|
+
message = message.replace('$0', 'browser');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
element.innerHTML = message;
|
|
57
|
+
|
|
58
|
+
return element;
|
|
59
|
+
},
|
|
94
60
|
};
|
|
95
61
|
|
|
96
|
-
export {
|
|
62
|
+
export { GPU_SUPPORT as default };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
//import * as nifti from 'nifti-reader-js';
|
|
2
|
-
import { createPrimitivesFromNIFTI } from
|
|
2
|
+
import { createPrimitivesFromNIFTI } from 'zincjs';
|
|
3
3
|
|
|
4
4
|
const readNIFTIFromSource = async (url, useHeaderInfo, maskURL, settings, options) => {
|
|
5
5
|
const images = await createPrimitivesFromNIFTI(url, useHeaderInfo, maskURL, settings, options);
|
|
6
6
|
return images;
|
|
7
|
-
}
|
|
7
|
+
};
|
|
8
8
|
|
|
9
|
-
export { readNIFTIFromSource }
|
|
9
|
+
export { readNIFTIFromSource };
|