@abi-software/scaffoldvuer 1.10.0 → 1.11.0-beta.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/scaffoldvuer",
3
- "version": "1.10.0",
3
+ "version": "1.11.0-beta.1",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -54,7 +54,7 @@
54
54
  "vue": "^3.4.21",
55
55
  "vue-router": "^4.2.5",
56
56
  "vue3-component-svg-sprite": "^0.0.1",
57
- "zincjs": "^1.14.0"
57
+ "zincjs": "^1.14.3"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@vitejs/plugin-vue": "^4.6.2",
@@ -218,7 +218,7 @@ export default {
218
218
  border-radius: 4px;
219
219
  white-space: nowrap;
220
220
  min-width: unset!important;
221
- max-width:330px;
221
+ max-width:fit-content;
222
222
  width:unset!important;
223
223
  pointer-events: none;
224
224
  top: -15px !important;
@@ -77,6 +77,7 @@ export default {
77
77
  drawerOpen: true,
78
78
  nodeNumbers: 0,
79
79
  module: undefined,
80
+ //checkedRegions: [],
80
81
  };
81
82
  },
82
83
  computed: {
@@ -91,9 +92,21 @@ export default {
91
92
  if (this.isReady) {
92
93
  // Updated colour when scaffold is ready
93
94
  this.setColourField(data);
95
+ // _helper is unchecked by default
96
+ //this.checkedRegions = data.filter(region => region.label !== '_helper');
94
97
  }
95
98
  },
96
99
  },
100
+ /*
101
+ checkedRegions: {
102
+ deep: true,
103
+ handler: function (data) {
104
+ if (this.isReady) {
105
+ this.$emit('checked-regions', data);
106
+ }
107
+ },
108
+ },
109
+ */
97
110
  },
98
111
  methods: {
99
112
  addTreeItem: function (parentContainer, item, object) {
@@ -221,7 +234,13 @@ export default {
221
234
  .getRootRegion()
222
235
  .findChildFromPath(node.regionPath);
223
236
  if (isRegion) {
224
- isChecked ? region.showAllPrimitives() : region.hideAllPrimitives();
237
+ if (isChecked) {
238
+ region.showAllPrimitives();
239
+ //this.checkedRegions.push(node);
240
+ } else {
241
+ region.hideAllPrimitives();
242
+ //this.checkedRegions = this.checkedRegions.filter(region => region.label !== node.label);
243
+ }
225
244
  }
226
245
  if (isPrimitives) {
227
246
  const primitives = region.findObjectsWithGroupName(node.label);
@@ -514,13 +533,28 @@ export default {
514
533
  });
515
534
  }
516
535
  },
517
- checkAllKeys: function () {
536
+ setCheckedKeys: function (ids, clear) {
537
+ this.$nextTick(() => {
538
+ if (clear) {
539
+ this.$refs.treeControls.$refs.regionTree.setCheckedKeys([]); // Clear previous checked keys
540
+ }
541
+ // this will be faster as it only requires region node ids only
542
+ // the number will be much less than all node ids
543
+ ids.forEach((id) => {
544
+ this.$refs.treeControls.$refs.regionTree.setChecked(id, true, true); // Set new checked keys
545
+ })
546
+ });
547
+ },
548
+ checkAllKeys: function (ignore = []) {
518
549
  const keysList = [];
519
550
  const ids = [];
520
551
  extractAllFullPaths(this.treeData[0], keysList);
552
+ const modifiedKeysList = keysList.filter((key) => {
553
+ return !ignore.some(item => key.includes(item));
554
+ });
521
555
  this.setTreeVisibilityWithFullPaths(
522
556
  this.treeData[0],
523
- keysList,
557
+ modifiedKeysList,
524
558
  ids,
525
559
  true
526
560
  );
@@ -109,6 +109,7 @@
109
109
  </el-popover>
110
110
  <div class="primitive-controls-box">
111
111
  <primitive-controls
112
+ v-show="viewingMode === 'Exploration' || viewingMode === 'Annotation'"
112
113
  ref="primitiveControls"
113
114
  :createData="createData"
114
115
  @primitivesUpdated="primitivesUpdated"
@@ -288,7 +289,7 @@
288
289
  ref="backgroundPopover"
289
290
  :virtual-ref="backgroundIconRef"
290
291
  placement="top-start"
291
- width="128"
292
+ width="320"
292
293
  :teleported="false"
293
294
  trigger="click"
294
295
  popper-class="background-popper non-selectable h-auto"
@@ -323,7 +324,7 @@
323
324
  <el-radio-group
324
325
  v-model="colourRadio"
325
326
  class="scaffold-radio"
326
- @change="setColour"
327
+ @change="setColour(colourRadio, true)"
327
328
  >
328
329
  <el-radio :value="true">Colour</el-radio>
329
330
  <el-radio :value="false">Greyscale</el-radio>
@@ -335,7 +336,7 @@
335
336
  <el-radio-group
336
337
  v-model="outlinesRadio"
337
338
  class="scaffold-radio"
338
- @change="setOutlines"
339
+ @change="setOutlines(outlinesRadio, true)"
339
340
  >
340
341
  <el-radio :value="true">Show</el-radio>
341
342
  <el-radio :value="false">Hide</el-radio>
@@ -437,7 +438,6 @@ import {
437
438
  findObjectsWithNames,
438
439
  updateBoundingBox,
439
440
  } from "../scripts/Utilities.js";
440
-
441
441
  import {
442
442
  ElButton as Button,
443
443
  ElCol as Col,
@@ -458,6 +458,9 @@ import { OrgansViewer } from "../scripts/OrgansRenderer.js";
458
458
  import { SearchIndex } from "../scripts/Search.js";
459
459
  import { mapState } from 'pinia';
460
460
  import { useMainStore } from "@/store/index";
461
+ import { getNerveMaps } from "../scripts/MappedNerves.js";
462
+ const nervesMap = getNerveMaps();
463
+ let totalNerves = 0, foundNerves = 0;
461
464
 
462
465
  /**
463
466
  * A vue component of the scaffold viewer.
@@ -860,6 +863,7 @@ export default {
860
863
  viewingMode: "Exploration",
861
864
  viewingModes: {
862
865
  "Exploration": "View and explore detailed visualization of 3D scaffolds",
866
+ "Neuron Connection": "Discover nerve connections by selecting a nerve and viewing its associated connections",
863
867
  "Annotation": ['View feature annotations', 'Add, comment on and view feature annotations'],
864
868
  },
865
869
  openMapRef: undefined,
@@ -885,7 +889,8 @@ export default {
885
889
  region: "",
886
890
  group: "",
887
891
  isSearch: false,
888
- })
892
+ }),
893
+ //checkedRegions: []
889
894
  };
890
895
  },
891
896
  watch: {
@@ -1033,6 +1038,91 @@ export default {
1033
1038
  },
1034
1039
  },
1035
1040
  methods: {
1041
+ /*
1042
+ setCheckedRegions: function (data) {
1043
+ this.checkedRegions = data;
1044
+ },
1045
+ */
1046
+ /**
1047
+ *
1048
+ * @param nerves array of nerve names, show all nerves if empty
1049
+ * @param processed boolean, whether unselect all checkboxes
1050
+ */
1051
+ zoomToNerves: function (nerves, processed = false) {
1052
+ if (this.$module.scene) {
1053
+ const nervesList = [];
1054
+ let nervesUUID = undefined;
1055
+ const regions = this.$module.scene.getRootRegion().getChildRegions();
1056
+ regions.forEach((region) => {
1057
+ const regionName = region.getName();
1058
+ if (processed) {
1059
+ if (regionName === 'Nerves') {
1060
+ if (nerves.length) {
1061
+ const ids = nerves.forEach((nerve) => {
1062
+ const primitives = this.findObjectsWithGroupName(nerve)
1063
+ nervesList.push(...primitives);
1064
+ primitives.forEach((primitive) => {
1065
+ primitive.setVisibility(true);
1066
+ nervesList.push(primitive);
1067
+ if (!nervesUUID) nervesUUID = primitive.region.uuid;
1068
+ });
1069
+ });
1070
+ }
1071
+ }
1072
+ }
1073
+ });
1074
+ if (nervesList.length) {
1075
+ let box = this.$module.scene.getBoundingBoxOfZincObjects(nervesList);
1076
+ if (box) this.$module.scene.viewAllWithBoundingBox(box);
1077
+ }
1078
+ if (nervesUUID) {
1079
+ this.$refs.scaffoldTreeControls.setCheckedKeys([nervesUUID], false);
1080
+ }
1081
+ }
1082
+
1083
+ //The following hide all the other primitives
1084
+ /*
1085
+ if (this.$module.scene) {
1086
+ const idsList = [];
1087
+ const regions = this.$module.scene.getRootRegion().getChildRegions();
1088
+ regions.forEach((region) => {
1089
+ const regionName = region.getName();
1090
+ if (processed) {
1091
+ region.hideAllPrimitives();
1092
+ if (regionName === 'Nerves') {
1093
+ if (nerves.length) {
1094
+ const ids = nerves.reduce((acc, nerve) => {
1095
+ const primitives = this.findObjectsWithGroupName(nerve)
1096
+ const ids = primitives.map((object) => {
1097
+ object.setVisibility(true);
1098
+ return `${object.region.uuid}/${object.uuid}`;
1099
+ });
1100
+ acc.push(...ids);
1101
+ return acc;
1102
+ }, []);
1103
+ idsList.push(...ids)
1104
+ } else {
1105
+ region.showAllPrimitives();
1106
+ idsList.push(region.uuid)
1107
+ }
1108
+ }
1109
+ } else {
1110
+ // if the checkboxes are checked previously, restore them
1111
+ const isChecked = this.checkedRegions.find(item => item.label === regionName);
1112
+ if (isChecked) {
1113
+ region.showAllPrimitives();
1114
+ idsList.push(region.uuid);
1115
+ }
1116
+ }
1117
+
1118
+ });
1119
+ if (nerves.length) {
1120
+ this.fitWindow();
1121
+ }
1122
+ this.$refs.scaffoldTreeControls.setCheckedKeys(idsList, processed);
1123
+ }
1124
+ */
1125
+ },
1036
1126
  enableAxisDisplay: function (enable, miniaxes) {
1037
1127
  if (this.$module.scene) {
1038
1128
  this.$module.scene.enableAxisDisplay(enable, miniaxes);
@@ -1072,10 +1162,17 @@ export default {
1072
1162
  for (let i = 0; i < regions.length; i++) {
1073
1163
  if (regionPath.includes(regions[i].toLowerCase())) {
1074
1164
  zincObject.userData.isNerves = true;
1165
+ const groupName = zincObject.groupName.toLowerCase();
1166
+ if (groupName in nervesMap) {
1167
+ foundNerves++;
1168
+ zincObject.setAnatomicalId(nervesMap[groupName]);
1169
+ //console.log(groupName, zincObject.anatomicalId, zincObject.uuid)
1170
+ }
1075
1171
  } else {
1076
1172
  zincObject.userData.isNerves = false;
1077
1173
  }
1078
1174
  }
1175
+
1079
1176
  }
1080
1177
  /**
1081
1178
  * Emit when a new object is added to the scene
@@ -1779,11 +1876,13 @@ export default {
1779
1876
  * @arg objects objects to be set for the selected
1780
1877
  */
1781
1878
  updatePrimitiveControls: function (objects) {
1782
- this.selectedObjects = objects;
1783
- if (this.selectedObjects && this.selectedObjects.length > 0) {
1784
- this.$refs.primitiveControls.setObject(this.selectedObjects[0]);
1785
- } else {
1786
- this.$refs.primitiveControls.setObject(undefined);
1879
+ if (this.viewingMode === 'Exploration' || this.viewingMode === 'Annotation') {
1880
+ this.selectedObjects = objects;
1881
+ if (this.selectedObjects && this.selectedObjects.length > 0) {
1882
+ this.$refs.primitiveControls.setObject(this.selectedObjects[0]);
1883
+ } else {
1884
+ this.$refs.primitiveControls.setObject(undefined);
1885
+ }
1787
1886
  }
1788
1887
  },
1789
1888
  /**
@@ -2125,6 +2224,7 @@ export default {
2125
2224
  * Optional, can be used to update the view mode.
2126
2225
  */
2127
2226
  changeViewingMode: function (modeName) {
2227
+ let nonNervesIsPickable = true;
2128
2228
  if (this.$module) {
2129
2229
  if (modeName) {
2130
2230
  this.viewingMode = modeName;
@@ -2144,12 +2244,12 @@ export default {
2144
2244
  this.addAnnotationFeature();
2145
2245
  this.loading = false;
2146
2246
  });
2147
- } else {
2148
- if (this.viewingMode === "Exploration") {
2149
- this.activeDrawTool = undefined;
2150
- this.activeDrawMode = undefined;
2151
- this.createData.shape = "";
2152
- }
2247
+ } else if (this.viewingMode === "Exploration") {
2248
+ this.activeDrawTool = undefined;
2249
+ this.activeDrawMode = undefined;
2250
+ this.createData.shape = "";
2251
+ } else if (this.viewingMode === "Neuron Connection") {
2252
+ nonNervesIsPickable = false;
2153
2253
  }
2154
2254
  if ((this.viewingMode === "Exploration") ||
2155
2255
  (this.viewingMode === "Annotation") &&
@@ -2159,6 +2259,9 @@ export default {
2159
2259
  this.$module.selectObjectOnPick = false;
2160
2260
  }
2161
2261
  this.cancelCreate();
2262
+ if (modeName) {
2263
+ this.setNonNervesIsPickable(nonNervesIsPickable);
2264
+ }
2162
2265
  }
2163
2266
  },
2164
2267
  /**
@@ -2183,24 +2286,50 @@ export default {
2183
2286
  this.tData.visible = false;
2184
2287
  this.tData.region = undefined;
2185
2288
  },
2289
+ /**
2290
+ * Currently will only apply to non-nerve object
2291
+ * @param flag boolean to control whether objects pickable
2292
+ */
2293
+ setNonNervesIsPickable: function (flag) {
2294
+ const objects = this.$module.scene.getRootRegion().getAllObjects(true);
2295
+ objects.forEach((zincObject) => {
2296
+ if (!zincObject.userData.isNerves) zincObject.setIsPickable(flag);
2297
+ });
2298
+ },
2299
+ /**
2300
+ *
2301
+ * @param flag boolean
2302
+ * @param nerves array of nerve names
2303
+ */
2304
+ setGreyScale: function (flag, nerves = []) {
2305
+ const objects = this.$module.scene.getRootRegion().getAllObjects(true);
2306
+ objects.forEach((zincObject) => {
2307
+ if (nerves.length) {
2308
+ const groupName = zincObject.groupName.toLowerCase();
2309
+ if (zincObject.userData.isNerves) {
2310
+ if (!nerves.includes(groupName)) zincObject.setGreyScale(flag);
2311
+ }
2312
+ } else {
2313
+ if (!zincObject.userData.isNerves) zincObject.setGreyScale(flag);
2314
+ }
2315
+ });
2316
+ this.$refs.scaffoldTreeControls.updateAllNodeColours();
2317
+ },
2186
2318
  /**
2187
2319
  * @public
2188
2320
  * Function to toggle colour/greyscale of primitives.
2189
2321
  * The parameter ``flag`` is a boolean, ``true`` (colour) and ``false`` (greyscale).
2190
2322
  * @arg {Boolean} `flag`
2191
2323
  */
2192
- setColour: function (flag) {
2324
+ setColour: function (flag, forced = false) {
2193
2325
  if (this.isReady && this.$module.scene &&
2194
- typeof flag === "boolean" && flag !== this.colourRadio) {
2326
+ typeof flag === "boolean" &&
2327
+ (forced || flag !== this.colourRadio)) {
2195
2328
  this.loading = true;
2196
2329
  //This can take sometime to finish , nextTick does not bring out
2197
2330
  //the loading screen so I opt for timeout loop here.
2198
2331
  setTimeout(() => {
2199
- const objects = this.$module.scene.getRootRegion().getAllObjects(true);
2200
- objects.forEach((zincObject) => {
2201
- if (!zincObject.userData.isNerves) zincObject.setGreyScale(!flag);
2202
- });
2203
- this.$refs.scaffoldTreeControls.updateAllNodeColours();
2332
+ this.setGreyScale(!flag)
2204
2333
  this.loading = false;
2205
2334
  this.colourRadio = flag;
2206
2335
  }, 100);
@@ -2212,9 +2341,10 @@ export default {
2212
2341
  * The parameter ``flag`` is a boolean, ``true`` to show lines, ``false`` to hide them.
2213
2342
  * @arg {Boolean} `flag`
2214
2343
  */
2215
- setOutlines: function (flag) {
2344
+ setOutlines: function (flag, forced = false) {
2216
2345
  if (this.isReady && this.$module.scene &&
2217
- typeof flag === "boolean" && flag !== this.outlinesRadio) {
2346
+ typeof flag === "boolean" &&
2347
+ (forced || flag !== this.outlinesRadio)) {
2218
2348
  this.outlinesRadio = flag;
2219
2349
  this.$nextTick(() => this.$refs.scaffoldTreeControls.setOutlines(flag));
2220
2350
  }
@@ -2431,6 +2561,7 @@ export default {
2431
2561
  //this.$module.scene.createAxisDisplay(false);
2432
2562
  //this.$module.scene.enableAxisDisplay(true, true);
2433
2563
  this.isReady = true;
2564
+ //console.log(`Total ${totalNerves}, found ${foundNerves}`);
2434
2565
  this.$nextTick(() => {
2435
2566
  this.restoreSettings(options);
2436
2567
  this.$emit("on-ready");