@@ -2837,15 +2837,15 @@ var SkeletonAnnotations = {};
2837
2837
* This function expects child and parent to be real nodes and does no further
2838
2838
* checks in this regard for performance reasons.
2839
2839
*/
2840
- CATMAID . createVirtualNode = function ( graphics , child , parent , stackViewer ) {
2840
+ CATMAID . createVirtualNode = function ( graphics , child , parent , z , stackViewer ) {
2841
2841
// Make sure child and parent are at different sections
2842
2842
if ( stackViewer . primaryStack . projectToUnclampedStackZ ( child . z , child . y , child . x ) ===
2843
2843
stackViewer . primaryStack . projectToUnclampedStackZ ( parent . z , parent . y , parent . x ) ) {
2844
2844
console . log ( 'Child and parent have same Z, can\'t create virtual node.' ) ;
2845
2845
return null ;
2846
2846
}
2847
2847
2848
- return CATMAID . _createVirtualNode ( graphics , child , parent , stackViewer ) ;
2848
+ return CATMAID . _createVirtualNode ( graphics , child , parent , z , stackViewer ) ;
2849
2849
} ;
2850
2850
2851
2851
let _virtualNodeCreationTmpVector = new THREE . Vector3 ( ) ;
@@ -2855,10 +2855,12 @@ var SkeletonAnnotations = {};
2855
2855
/**
2856
2856
* The actual implementation of createVirtualNode(), without precondition
2857
2857
* checks to allow faster execution if this was tested before.
2858
+ *
2859
+ * We could use stackViewer.z instead of the explicit z parameter, but this
2860
+ * would require us to ensure the current stack viewer Z is between the passed
2861
+ * in nodes. This seems like an unnecessary constraint.
2858
2862
*/
2859
- CATMAID . _createVirtualNode = function ( graphics , child , parent , stackViewer , onlyInView ) {
2860
- var z = stackViewer . z ;
2861
-
2863
+ CATMAID . _createVirtualNode = function ( graphics , child , parent , z , stackViewer , onlyInView ) {
2862
2864
// Define X and Y so that they are on the intersection of the line between
2863
2865
// child and parent and the current section.
2864
2866
_virtualNodeCreationTmpLine . start . set ( child . x , child . y , child . z ) ;
@@ -2996,9 +2998,9 @@ var SkeletonAnnotations = {};
2996
2998
2997
2999
// Set currently allowed section distances, to correctly account for broken
2998
3000
// sections.
2999
- var sv = this . stackViewer ;
3000
- var dToSecBefore = sv . validZDistanceBefore ( sv . z ) ;
3001
- var dToSecAfter = sv . validZDistanceAfter ( sv . z ) ;
3001
+ var currentZ = this . stackViewer . z ;
3002
+ var dToSecBefore = this . stackViewer . validZDistanceBefore ( currentZ ) ;
3003
+ var dToSecAfter = this . stackViewer . validZDistanceAfter ( currentZ ) ;
3002
3004
this . graphics . init ( dToSecBefore , dToSecAfter ) ;
3003
3005
3004
3006
// Look-up some frequently used objects
@@ -3010,7 +3012,7 @@ var SkeletonAnnotations = {};
3010
3012
var n = extraNodes [ i ] ;
3011
3013
var stackZ = primaryStack . projectToUnclampedStackZ ( n . z , n . y , n . x ) ;
3012
3014
this . nodes . set ( n . id , this . graphics . newNode ( n . id , null , n . parent_id , n . radius ,
3013
- n . x , n . y , n . z , stackZ - this . stackViewer . z , n . confidence , n . skeleton_id ,
3015
+ n . x , n . y , n . z , stackZ - currentZ , n . confidence , n . skeleton_id ,
3014
3016
n . edition_time , n . user_id ) ) ;
3015
3017
}
3016
3018
}
@@ -3099,7 +3101,7 @@ var SkeletonAnnotations = {};
3099
3101
var stackZ = primaryStack . projectToUnclampedStackZ ( a [ 4 ] , a [ 3 ] , a [ 2 ] ) ;
3100
3102
let newNode = this . graphics . newNode (
3101
3103
a [ 0 ] , null , a [ 1 ] , a [ 6 ] , a [ 2 ] , a [ 3 ] , a [ 4 ] ,
3102
- stackZ - this . stackViewer . z , a [ 5 ] , a [ 7 ] , a [ 8 ] , a [ 9 ] ) ;
3104
+ stackZ - currentZ , a [ 5 ] , a [ 7 ] , a [ 8 ] , a [ 9 ] ) ;
3103
3105
this . nodes . set ( a [ 0 ] , newNode ) ;
3104
3106
addedNodes . push ( newNode ) ;
3105
3107
++ nAddedTreenodes ;
@@ -3167,7 +3169,7 @@ var SkeletonAnnotations = {};
3167
3169
// For performance reasons, the edition time is transmitted as epoch time
3168
3170
let newNode = this . graphics . newConnectorNode (
3169
3171
a [ 0 ] , a [ 1 ] , a [ 2 ] , a [ 3 ] ,
3170
- stackZ - this . stackViewer . z , a [ 4 ] , subtype , a [ 5 ] , a [ 6 ] ) ;
3172
+ stackZ - currentZ , a [ 4 ] , subtype , a [ 5 ] , a [ 6 ] ) ;
3171
3173
this . nodes . set ( a [ 0 ] , newNode ) ;
3172
3174
addedNodes . push ( newNode ) ;
3173
3175
++ nAddedConnectors ;
@@ -3194,7 +3196,8 @@ var SkeletonAnnotations = {};
3194
3196
// Virtual nodes can only exists if both parent and child are not on the
3195
3197
// current section and not both above or below.
3196
3198
if ( ( n . zdiff < 0 && pn . zdiff > 0 ) || ( n . zdiff > 0 && pn . zdiff < 0 ) ) {
3197
- var vn = CATMAID . _createVirtualNode ( this . graphics , n , pn , this . stackViewer ) ;
3199
+ const targetZ = this . stackViewer . primaryStack . projectToUnclampedStackZ ( n . z , n . y , n . x ) - n . zdiff ;
3200
+ var vn = CATMAID . _createVirtualNode ( this . graphics , n , pn , targetZ , this . stackViewer ) ;
3198
3201
if ( vn ) {
3199
3202
++ nAddedVirtualNodes ;
3200
3203
n . parent = vn ;
@@ -3373,22 +3376,31 @@ var SkeletonAnnotations = {};
3373
3376
var n = self . nodes . get ( addedNodes [ i ] . id ) ;
3374
3377
var p = n . parent_id ? self . nodes . get ( n . parent_id ) : null ;
3375
3378
3376
- if ( n && p && ( ( n . zdiff < 0 && p . zdiff > 0 ) || ( n . zdiff > 0 && p . zdiff < 0 ) ) ) {
3377
- var vn = CATMAID . createVirtualNode ( self . graphics , n , p , self . stackViewer ) ;
3378
- if ( vn ) {
3379
- n . parent = vn ;
3380
- n . parent_id = vn . id ;
3381
- p . addChildNode ( vn ) ;
3382
- vn . addChildNode ( n ) ;
3383
- self . nodes . set ( vn . id , vn ) ;
3384
- addedNodes . push ( vn ) ;
3385
- continue ;
3386
- }
3379
+ if ( n && p ) {
3380
+ // While n.zdiff has been computed above, p.zdiff might not be
3381
+ // up-to-date anymore (wrt to the passed in Z). This can be the case
3382
+ // if the user travels through Z very quickly. Therefore, we
3383
+ // recompute it on the fly:
3384
+ const zDiffP = self . stackViewer . primaryStack . projectToUnclampedStackZ ( p . z , p . y , p . x ) - self . stackViewer . z ;
3385
+
3386
+ if ( ( ( n . zdiff < 0 && zDiffP > 0 ) || ( n . zdiff > 0 && zDiffP < 0 ) ) ) {
3387
+ const targetZ = self . stackViewer . primaryStack . projectToUnclampedStackZ ( n . z , n . y , n . x ) - n . zdiff ;
3388
+ var vn = CATMAID . createVirtualNode ( self . graphics , n , p , targetZ , self . stackViewer ) ;
3389
+ if ( vn ) {
3390
+ n . parent = vn ;
3391
+ n . parent_id = vn . id ;
3392
+ p . addChildNode ( vn ) ;
3393
+ vn . addChildNode ( n ) ;
3394
+ self . nodes . set ( vn . id , vn ) ;
3395
+ addedNodes . push ( vn ) ;
3396
+ continue ;
3397
+ }
3387
3398
3388
- // If no virtual node was inserted, link parent and child normally.
3389
- n . parent = p ;
3390
- // update the parent's children
3391
- p . addChildNode ( n ) ;
3399
+ // If no virtual node was inserted, link parent and child normally.
3400
+ n . parent = p ;
3401
+ // update the parent's children
3402
+ p . addChildNode ( n ) ;
3403
+ }
3392
3404
}
3393
3405
}
3394
3406
@@ -6223,7 +6235,7 @@ var SkeletonAnnotations = {};
6223
6235
}
6224
6236
6225
6237
// Otherwise, add the new node to the local node store and display. This is
6226
- // done explicitely to avoid a full node update.
6238
+ // done explicitly to avoid a full node update.
6227
6239
6228
6240
// The parent will be null if there isn't one or if the parent Node
6229
6241
// object is not within the set of retrieved nodes, but the parentID
0 commit comments