1
1
import macro from 'vtk.js/Sources/macros' ;
2
- import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor' ;
3
- import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper' ;
4
2
import * as vtkMath from 'vtk.js/Sources/Common/Core/Math' ;
5
3
import vtkBoundingBox from 'vtk.js/Sources/Common/DataModel/BoundingBox' ;
6
- import vtkTubeFilter from 'vtk.js/Sources/Filters/General/TubeFilter' ;
7
4
import { getPixelWorldHeightAtCoord } from 'vtk.js/Sources/Widgets/Core/WidgetManager' ;
8
5
import vtkWidgetRepresentation , {
9
6
allocateArray ,
10
7
} from 'vtk.js/Sources/Widgets/Representations/WidgetRepresentation' ;
11
8
import { RenderingTypes } from 'vtk.js/Sources/Widgets/Core/WidgetManager/Constants' ;
12
9
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData' ;
10
+ import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor' ;
11
+ import vtkGlyph3DMapper from 'vtk.js/Sources/Rendering/Core/Glyph3DMapper' ;
12
+ import { OrientationModes } from 'vtk.js/Sources/Rendering/Core/Glyph3DMapper/Constants' ;
13
+ import vtkCylinderSource from 'vtk.js/Sources/Filters/Sources/CylinderSource' ;
13
14
14
15
// ----------------------------------------------------------------------------
15
16
// vtkPolyLineRepresentation methods
16
17
// ----------------------------------------------------------------------------
17
18
18
19
function vtkPolyLineRepresentation ( publicAPI , model ) {
19
- // Set our className
20
20
model . classHierarchy . push ( 'vtkPolyLineRepresentation' ) ;
21
21
const superClass = { ...publicAPI } ;
22
22
23
- // --------------------------------------------------------------------------
24
- // Internal polydata dataset
25
- // --------------------------------------------------------------------------
26
23
const internalPolyData = vtkPolyData . newInstance ( { mtime : 0 } ) ;
27
24
28
25
function allocateSize ( polyData , size , closePolyLine = false ) {
29
- let points = null ;
30
- if ( size < 2 ) {
31
- // FIXME: Why 1 point and not 0 ?
32
- points = allocateArray ( polyData , 'points' , 1 ) . getData ( ) ;
33
- points . set ( [ 0 , 0 , 0 ] ) ;
34
- allocateArray ( polyData , 'lines' , 0 ) . getData ( ) ;
35
- } else if (
36
- ! polyData . getPoints ( ) ||
37
- polyData . getPoints ( ) . length !== size * 3
26
+ if ( ! polyData . getPoints ( ) || polyData . getPoints ( ) . length !== size * 3 ) {
27
+ allocateArray ( polyData , 'points' , size ) . getData ( ) ;
28
+ }
29
+
30
+ const cellSize = size + ( closePolyLine ? 1 : 0 ) ;
31
+ if (
32
+ polyData . getLines ( ) . getNumberOfCells ( ) !== 1 ||
33
+ polyData . getLines ( ) . getCellSizes ( ) [ 0 ] !== cellSize
38
34
) {
39
- points = allocateArray ( polyData , 'points' , size ) . getData ( ) ;
40
- const cellSize = size + ( closePolyLine ? 1 : 0 ) ;
41
- if (
42
- polyData . getLines ( ) . getNumberOfCells ( ) !== 1 ||
43
- polyData . getLines ( ) . getCellSizes ( ) [ 0 ] !== cellSize
44
- ) {
45
- const lines = allocateArray ( polyData , 'lines' , cellSize + 1 ) ; // +1 for the number of points
46
- const cellData = lines . getData ( ) ;
47
- cellData [ 0 ] = cellSize ;
48
- for ( let i = 1 ; i <= cellSize ; i ++ ) {
49
- cellData [ i ] = i - 1 ;
50
- }
51
- if ( closePolyLine ) {
52
- cellData [ cellSize ] = 0 ;
53
- }
54
- lines . setData ( cellData ) ;
35
+ const lines = allocateArray ( polyData , 'lines' , cellSize + 1 ) . getData ( ) ; // +1 for the number of points
36
+ lines [ 0 ] = cellSize ;
37
+ for ( let i = 1 ; i <= cellSize ; i ++ ) {
38
+ lines [ i ] = i - 1 ;
39
+ }
40
+ if ( closePolyLine ) {
41
+ lines [ cellSize ] = 0 ;
55
42
}
56
43
}
57
- return points ;
58
44
}
59
45
60
46
/**
61
- * Change the line/tube thickness.
47
+ * Change the segments thickness.
62
48
* @param {number } lineThickness
63
49
*/
64
50
function applyLineThickness ( lineThickness ) {
@@ -70,35 +56,30 @@ function vtkPolyLineRepresentation(publicAPI, model) {
70
56
model . displayScaleParams
71
57
) ;
72
58
}
73
- model . _pipelines . tubes . filter . setRadius ( scaledLineThickness ) ;
59
+ model . _pipeline . glyph . setRadius ( scaledLineThickness ) ;
74
60
}
75
61
76
- // --------------------------------------------------------------------------
77
- // Generic rendering pipeline
78
- // --------------------------------------------------------------------------
79
-
80
- model . _pipelines = {
81
- tubes : {
82
- source : publicAPI ,
83
- filter : vtkTubeFilter . newInstance ( {
84
- radius : model . lineThickness ,
85
- numberOfSides : 12 ,
86
- capping : false ,
87
- } ) ,
88
- mapper : vtkMapper . newInstance ( ) ,
89
- actor : vtkActor . newInstance ( { parentProp : publicAPI } ) ,
90
- } ,
62
+ model . _pipeline = {
63
+ source : publicAPI ,
64
+ glyph : vtkCylinderSource . newInstance ( {
65
+ direction : [ 1 , 0 , 0 ] ,
66
+ } ) ,
67
+ mapper : vtkGlyph3DMapper . newInstance ( {
68
+ orientationArray : 'directions' ,
69
+ orientationMode : OrientationModes . DIRECTION ,
70
+ } ) ,
71
+ actor : vtkActor . newInstance ( { parentProp : publicAPI } ) ,
91
72
} ;
92
73
93
- vtkWidgetRepresentation . connectPipeline ( model . _pipelines . tubes ) ;
94
- publicAPI . addActor ( model . _pipelines . tubes . actor ) ;
74
+ vtkWidgetRepresentation . connectPipeline ( model . _pipeline ) ;
75
+ publicAPI . addActor ( model . _pipeline . actor ) ;
95
76
96
77
// --------------------------------------------------------------------------
97
78
publicAPI . requestData = ( inData , outData ) => {
98
79
const state = inData [ 0 ] ;
99
80
outData [ 0 ] = internalPolyData ;
100
81
101
- // Remove invalid and coincident points for tube filter .
82
+ // Remove invalid and coincident points.
102
83
const list = publicAPI
103
84
. getRepresentationStates ( state )
104
85
. reduce ( ( subStates , subState ) => {
@@ -120,23 +101,44 @@ function vtkPolyLineRepresentation(publicAPI, model) {
120
101
} , [ ] ) ;
121
102
const size = list . length ;
122
103
123
- const points = allocateSize (
124
- outData [ 0 ] ,
125
- size ,
126
- model . closePolyLine && size > 2
127
- ) ;
104
+ allocateSize ( internalPolyData , size , model . closePolyLine && size > 2 ) ;
128
105
129
- if ( points ) {
130
- for ( let i = 0 ; i < size ; i ++ ) {
131
- const coords = list [ i ] . getOrigin ( ) ;
132
- points [ i * 3 ] = coords [ 0 ] ;
133
- points [ i * 3 + 1 ] = coords [ 1 ] ;
134
- points [ i * 3 + 2 ] = coords [ 2 ] ;
135
- }
106
+ const points = internalPolyData . getPoints ( ) . getData ( ) ;
107
+ const lines = internalPolyData . getLines ( ) . getData ( ) ;
108
+
109
+ for ( let i = 0 ; i < size ; i ++ ) {
110
+ const coords = list [ i ] . getOrigin ( ) ;
111
+ points [ i * 3 ] = coords [ 0 ] ;
112
+ points [ i * 3 + 1 ] = coords [ 1 ] ;
113
+ points [ i * 3 + 2 ] = coords [ 2 ] ;
114
+ }
115
+
116
+ // Orient glyphs to next point.
117
+ const directions = allocateArray (
118
+ internalPolyData ,
119
+ 'directions' ,
120
+ lines . length - 1 ,
121
+ undefined ,
122
+ 3
123
+ ) . getData ( ) ;
124
+ for ( let point = 1 ; point < lines . length - 1 ; point ++ ) {
125
+ const eye = lines [ point ] * 3 ;
126
+ const eyePoint = [ points [ eye ] , points [ eye + 1 ] , points [ eye + 2 ] ] ;
127
+ const target = lines [ point + 1 ] * 3 ;
128
+ const targetPoint = [
129
+ points [ target ] ,
130
+ points [ target + 1 ] ,
131
+ points [ target + 2 ] ,
132
+ ] ;
133
+ const direction = vtkMath . subtract ( targetPoint , eyePoint , [ ] ) ;
134
+ const glyph = ( point - 1 ) * 3 ;
135
+ directions [ glyph ] = direction [ 0 ] ;
136
+ directions [ glyph + 1 ] = direction [ 1 ] ;
137
+ directions [ glyph + 2 ] = direction [ 2 ] ;
136
138
}
137
139
138
- outData [ 0 ] . getPoints ( ) . modified ( ) ;
139
- outData [ 0 ] . modified ( ) ;
140
+ internalPolyData . getPoints ( ) . modified ( ) ;
141
+ internalPolyData . modified ( ) ;
140
142
141
143
const lineThickness = state . getLineThickness ?. ( ) ?? model . lineThickness ;
142
144
applyLineThickness ( lineThickness ) ;
0 commit comments