1
1
import { vec4 , mat4 } from 'gl-matrix' ;
2
2
3
- import macro from 'vtk.js/Sources/macros' ;
3
+ import macro , { vtkWarningMacro } from 'vtk.js/Sources/macros' ;
4
4
import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray' ;
5
+ import vtkMath from 'vtk.js/Sources/Common/Core/Math' ;
6
+ import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder' ;
5
7
import { VtkDataTypes } from 'vtk.js/Sources/Common/Core/DataArray/Constants' ;
6
8
import vtkBoundingBox from 'vtk.js/Sources/Common/DataModel/BoundingBox' ;
7
9
import vtkImageData from 'vtk.js/Sources/Common/DataModel/ImageData' ;
@@ -20,7 +22,7 @@ import Constants from 'vtk.js/Sources/Imaging/Core/ImageReslice/Constants';
20
22
21
23
const { SlabMode } = Constants ;
22
24
23
- const { capitalize , vtkErrorMacro } = macro ;
25
+ const { vtkErrorMacro } = macro ;
24
26
25
27
// ----------------------------------------------------------------------------
26
28
// vtkImageReslice methods
@@ -29,6 +31,7 @@ const { capitalize, vtkErrorMacro } = macro;
29
31
function vtkImageReslice ( publicAPI , model ) {
30
32
// Set our className
31
33
model . classHierarchy . push ( 'vtkImageReslice' ) ;
34
+ const superClass = { ...publicAPI } ;
32
35
33
36
let indexMatrix = null ;
34
37
let optimizedTransform = null ;
@@ -99,6 +102,14 @@ function vtkImageReslice(publicAPI, model) {
99
102
getImageResliceSlabTrap ( tmpPtr , inComponents , sampleCount , f ) ;
100
103
}
101
104
105
+ publicAPI . getMTime = ( ) => {
106
+ let mTime = superClass . getMTime ( ) ;
107
+ if ( model . resliceTransform ) {
108
+ mTime = Math . max ( mTime , model . resliceTransform . getMTime ( ) ) ;
109
+ }
110
+ return mTime ;
111
+ } ;
112
+
102
113
publicAPI . setResliceAxes = ( resliceAxes ) => {
103
114
if ( ! model . resliceAxes ) {
104
115
model . resliceAxes = mat4 . identity ( new Float64Array ( 16 ) ) ;
@@ -136,11 +147,9 @@ function vtkImageReslice(publicAPI, model) {
136
147
const outWholeExt = [ 0 , 0 , 0 , 0 , 0 , 0 ] ;
137
148
const outDims = [ 0 , 0 , 0 ] ;
138
149
139
- let matrix = null ;
150
+ const matrix = mat4 . identity ( new Float64Array ( 16 ) ) ;
140
151
if ( model . resliceAxes ) {
141
- matrix = model . resliceAxes ;
142
- } else {
143
- matrix = mat4 . identity ( new Float64Array ( 16 ) ) ;
152
+ mat4 . multiply ( matrix , matrix , model . resliceAxes ) ;
144
153
}
145
154
const imatrix = new Float64Array ( 16 ) ;
146
155
mat4 . invert ( imatrix , matrix ) ;
@@ -250,6 +259,9 @@ function vtkImageReslice(publicAPI, model) {
250
259
output . setDimensions ( outDims ) ;
251
260
output . setOrigin ( outOrigin ) ;
252
261
output . setSpacing ( outSpacing ) ;
262
+ if ( model . outputDirection ) {
263
+ output . setDirection ( model . outputDirection ) ;
264
+ }
253
265
output . getPointData ( ) . setScalars ( outScalars ) ;
254
266
255
267
publicAPI . getIndexMatrix ( input , output ) ;
@@ -385,7 +397,9 @@ function vtkImageReslice(publicAPI, model) {
385
397
// allocate an output row of type double
386
398
let floatPtr = null ;
387
399
if ( ! optimizeNearest ) {
388
- floatPtr = new Float64Array ( inComponents * ( outExt [ 1 ] - outExt [ 0 ] ) ) ;
400
+ floatPtr = new Float64Array (
401
+ inComponents * ( outExt [ 1 ] - outExt [ 0 ] + nsamples )
402
+ ) ;
389
403
}
390
404
391
405
const background = macro . newTypedArray (
@@ -711,7 +725,19 @@ function vtkImageReslice(publicAPI, model) {
711
725
}
712
726
}
713
727
} ;
714
-
728
+ /**
729
+ * The transform matrix supplied by the user converts output coordinates
730
+ * to input coordinates.
731
+ * To speed up the pixel lookup, the following function provides a
732
+ * matrix which converts output pixel indices to input pixel indices.
733
+ * This will also concatenate the ResliceAxes and the ResliceTransform
734
+ * if possible (if the ResliceTransform is a 4x4 matrix transform).
735
+ * If it does, this->OptimizedTransform will be set to nullptr, otherwise
736
+ * this->OptimizedTransform will be equal to this->ResliceTransform.
737
+ * @param {vtkPolyData } input
738
+ * @param {vtkPolyData } output
739
+ * @returns
740
+ */
715
741
publicAPI . getIndexMatrix = ( input , output ) => {
716
742
// first verify that we have to update the matrix
717
743
if ( indexMatrix === null ) {
@@ -720,6 +746,7 @@ function vtkImageReslice(publicAPI, model) {
720
746
721
747
const inOrigin = input . getOrigin ( ) ;
722
748
const inSpacing = input . getSpacing ( ) ;
749
+ const inDirection = input . getDirection ( ) ;
723
750
const outOrigin = output . getOrigin ( ) ;
724
751
const outSpacing = output . getSpacing ( ) ;
725
752
@@ -735,19 +762,36 @@ function vtkImageReslice(publicAPI, model) {
735
762
mat4 . copy ( transform , model . resliceAxes ) ;
736
763
}
737
764
if ( model . resliceTransform ) {
738
- // TODO
765
+ if ( model . resliceTransform . isA ( 'vtkHomogeneousTransform' ) ) {
766
+ // transform->PostMultiply();
767
+ // transform->Concatenate(
768
+ // mat4.multiply(transform, transform, model.resliceTransform.getMatrix());
769
+ mat4 . multiply ( transform , model . resliceTransform . getMatrix ( ) , transform ) ;
770
+ } else {
771
+ // TODO
772
+ vtkWarningMacro ( 'Non homogeneous transform have not yet been ported' ) ;
773
+ }
774
+ }
775
+
776
+ if ( ! vtkMath . isIdentity3x3 ( inDirection ) ) {
777
+ const imageTransform = vtkMatrixBuilder
778
+ . buildFromRadian ( )
779
+ . translate ( inOrigin [ 0 ] , inOrigin [ 1 ] , inOrigin [ 2 ] )
780
+ . multiply3x3 ( inDirection )
781
+ . translate ( - inOrigin [ 0 ] , - inOrigin [ 1 ] , - inOrigin [ 2 ] ) ;
782
+ mat4 . multiply ( transform , imageTransform . getMatrix ( ) , transform ) ;
739
783
}
740
784
741
785
// check to see if we have an identity matrix
742
- let isIdentity = publicAPI . isIdentityMatrix ( transform ) ;
786
+ let isIdentity = vtkMath . isIdentity ( transform ) ;
743
787
744
788
// the outMatrix takes OutputData indices to OutputData coordinates,
745
789
// the inMatrix takes InputData coordinates to InputData indices
746
790
for ( let i = 0 ; i < 3 ; i ++ ) {
747
791
if (
748
- ( optimizedTransform === null &&
792
+ ( optimizedTransform == null &&
749
793
( inSpacing [ i ] !== outSpacing [ i ] || inOrigin [ i ] !== outOrigin [ i ] ) ) ||
750
- ( optimizedTransform !== null &&
794
+ ( optimizedTransform != null &&
751
795
( outSpacing [ i ] !== 1.0 || outOrigin [ i ] !== 0.0 ) )
752
796
) {
753
797
isIdentity = false ;
@@ -780,6 +824,7 @@ function vtkImageReslice(publicAPI, model) {
780
824
publicAPI . getAutoCroppedOutputBounds = ( input ) => {
781
825
const inOrigin = input . getOrigin ( ) ;
782
826
const inSpacing = input . getSpacing ( ) ;
827
+ const inDirection = input . getDirection ( ) ;
783
828
const dims = input . getDimensions ( ) ;
784
829
const inWholeExt = [ 0 , dims [ 0 ] - 1 , 0 , dims [ 1 ] - 1 , 0 , dims [ 2 ] - 1 ] ;
785
830
@@ -789,6 +834,20 @@ function vtkImageReslice(publicAPI, model) {
789
834
} else {
790
835
mat4 . identity ( matrix ) ;
791
836
}
837
+ let transform = null ;
838
+ if ( model . resliceTransform ) {
839
+ transform = model . resliceTransform . getInverse ( ) ;
840
+ }
841
+ let imageTransform = null ;
842
+ if ( ! vtkMath . isIdentity3x3 ( inDirection ) ) {
843
+ imageTransform = vtkMatrixBuilder
844
+ . buildFromRadian ( )
845
+ . translate ( inOrigin [ 0 ] , inOrigin [ 1 ] , inOrigin [ 2 ] )
846
+ . multiply3x3 ( inDirection )
847
+ . translate ( - inOrigin [ 0 ] , - inOrigin [ 1 ] , - inOrigin [ 2 ] )
848
+ . invert ( )
849
+ . getMatrix ( ) ;
850
+ }
792
851
793
852
const bounds = [
794
853
Number . MAX_VALUE ,
@@ -808,8 +867,12 @@ function vtkImageReslice(publicAPI, model) {
808
867
inOrigin [ 2 ] + inWholeExt [ 4 + ( Math . floor ( i / 4 ) % 2 ) ] * inSpacing [ 2 ] ;
809
868
point [ 3 ] = 1.0 ;
810
869
870
+ if ( imageTransform ) {
871
+ vec4 . transformMat4 ( point , point , imageTransform ) ;
872
+ }
873
+
811
874
if ( model . resliceTransform ) {
812
- // TODO
875
+ transform . transformPoint ( point , point ) ;
813
876
}
814
877
815
878
vec4 . transformMat4 ( point , point , matrix ) ;
@@ -1048,24 +1111,6 @@ function vtkImageReslice(publicAPI, model) {
1048
1111
} ;
1049
1112
}
1050
1113
1051
- function setNullArray ( publicAPI , model , fieldNames ) {
1052
- fieldNames . forEach ( ( field ) => {
1053
- const setterName = `set${ capitalize ( field ) } ` ;
1054
- const superSet = publicAPI [ setterName ] ;
1055
- publicAPI [ setterName ] = ( ...args ) => {
1056
- if ( ( args . length === 1 && args [ 0 ] == null ) || model [ field ] == null ) {
1057
- if ( args [ 0 ] !== model [ field ] ) {
1058
- model [ field ] = args [ 0 ] ;
1059
- publicAPI . modified ( ) ;
1060
- return true ;
1061
- }
1062
- return null ;
1063
- }
1064
- return superSet ( ...args ) ;
1065
- } ;
1066
- } ) ;
1067
- }
1068
-
1069
1114
// ----------------------------------------------------------------------------
1070
1115
// Object factory
1071
1116
// ----------------------------------------------------------------------------
@@ -1076,6 +1121,7 @@ const DEFAULT_VALUES = {
1076
1121
outputDimensionality : 3 ,
1077
1122
outputSpacing : null , // automatically computed if null
1078
1123
outputOrigin : null , // automatically computed if null
1124
+ outputDirection : null , // identity if null
1079
1125
outputExtent : null , // automatically computed if null
1080
1126
outputScalarType : null ,
1081
1127
wrap : false , // don't wrap
@@ -1091,7 +1137,7 @@ const DEFAULT_VALUES = {
1091
1137
scalarScale : 1 ,
1092
1138
backgroundColor : [ 0 , 0 , 0 , 0 ] ,
1093
1139
resliceAxes : null ,
1094
- resliceTransform : null ,
1140
+ // resliceTransform: null,
1095
1141
interpolator : vtkImageInterpolator . newInstance ( ) ,
1096
1142
usePermuteExecute : false , // no supported yet
1097
1143
} ;
@@ -1117,8 +1163,8 @@ export function extend(publicAPI, model, initialValues = {}) {
1117
1163
'wrap' ,
1118
1164
'mirror' ,
1119
1165
'border' ,
1120
- 'backgroundColor' ,
1121
1166
'interpolationMode' ,
1167
+ 'resliceTransform' ,
1122
1168
'slabMode' ,
1123
1169
'slabTrapezoidIntegration' ,
1124
1170
'slabNumberOfSlices' ,
@@ -1127,12 +1173,8 @@ export function extend(publicAPI, model, initialValues = {}) {
1127
1173
1128
1174
macro . setGetArray ( publicAPI , model , [ 'outputOrigin' , 'outputSpacing' ] , 3 ) ;
1129
1175
macro . setGetArray ( publicAPI , model , [ 'outputExtent' ] , 6 ) ;
1130
-
1131
- setNullArray ( publicAPI , model , [
1132
- 'outputOrigin' ,
1133
- 'outputSpacing' ,
1134
- 'outputExtent' ,
1135
- ] ) ;
1176
+ macro . setGetArray ( publicAPI , model , [ 'outputDirection' ] , 9 ) ;
1177
+ macro . setGetArray ( publicAPI , model , [ 'backgroundColor' ] , 4 ) ;
1136
1178
1137
1179
macro . get ( publicAPI , model , [ 'resliceAxes' ] ) ;
1138
1180
0 commit comments