@@ -9,42 +9,46 @@ import { RenderingTypes } from 'vtk.js/Sources/Widgets/Core/WidgetManager/Consta
9
9
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData' ;
10
10
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor' ;
11
11
import vtkGlyph3DMapper from 'vtk.js/Sources/Rendering/Core/Glyph3DMapper' ;
12
- import { OrientationModes } from 'vtk.js/Sources/Rendering/Core/Glyph3DMapper/Constants' ;
12
+ import {
13
+ OrientationModes ,
14
+ ScaleModes ,
15
+ } from 'vtk.js/Sources/Rendering/Core/Glyph3DMapper/Constants' ;
13
16
import vtkCylinderSource from 'vtk.js/Sources/Filters/Sources/CylinderSource' ;
17
+ import { vec3 } from 'gl-matrix' ;
14
18
15
- // ----------------------------------------------------------------------------
16
- // vtkPolyLineRepresentation methods
17
- // ----------------------------------------------------------------------------
18
-
19
- function vtkPolyLineRepresentation ( publicAPI , model ) {
20
- model . classHierarchy . push ( 'vtkPolyLineRepresentation' ) ;
19
+ function vtkSegmentedLineRepresentation ( publicAPI , model ) {
20
+ model . classHierarchy . push ( 'vtkSegmentedLineRepresentation' ) ;
21
21
const superClass = { ...publicAPI } ;
22
22
23
23
const internalPolyData = vtkPolyData . newInstance ( { mtime : 0 } ) ;
24
24
25
- function allocateSize ( polyData , size , closePolyLine = false ) {
26
- if ( ! polyData . getPoints ( ) || polyData . getPoints ( ) . length !== size * 3 ) {
27
- allocateArray ( polyData , 'points' , size ) . getData ( ) ;
28
- }
29
-
30
- const cellSize = size + ( closePolyLine ? 1 : 0 ) ;
25
+ function allocateSize ( polyData , pointCount , close = false ) {
26
+ const glyphCount = pointCount + ( close ? 0 : - 1 ) ;
31
27
if (
32
- polyData . getLines ( ) . getNumberOfCells ( ) !== 1 ||
33
- polyData . getLines ( ) . getCellSizes ( ) [ 0 ] !== cellSize
28
+ ! polyData . getPoints ( ) ||
29
+ polyData . getPoints ( ) . length !== glyphCount * 3
34
30
) {
35
- const lines = allocateArray ( polyData , 'lines' , cellSize + 1 ) . getData ( ) ; // +1 for the number of points
36
- lines [ 0 ] = cellSize ;
31
+ allocateArray ( polyData , 'points' , glyphCount ) . getData ( ) ;
32
+ }
33
+
34
+ const cellSize = glyphCount + 1 ;
35
+ const oldSize = Array . from ( polyData . getLines ( ) . getCellSizes ( ) ) [ 0 ] ;
36
+ if ( oldSize !== cellSize ) {
37
+ const lines = allocateArray ( polyData , 'lines' , cellSize + 1 ) ; // +1 for to hold number of elements per cell
38
+ const cellArray = lines . getData ( ) ;
39
+ cellArray [ 0 ] = cellSize ;
37
40
for ( let i = 1 ; i <= cellSize ; i ++ ) {
38
- lines [ i ] = i - 1 ;
41
+ cellArray [ i ] = i - 1 ;
39
42
}
40
- if ( closePolyLine ) {
41
- lines [ cellSize ] = 0 ;
43
+ if ( close ) {
44
+ cellArray [ cellSize ] = 0 ;
42
45
}
46
+ lines . setData ( cellArray ) ;
43
47
}
44
48
}
45
49
46
50
/**
47
- * Change the segments thickness.
51
+ * Change the segments' thickness.
48
52
* @param {number } lineThickness
49
53
*/
50
54
function applyLineThickness ( lineThickness ) {
@@ -67,6 +71,8 @@ function vtkPolyLineRepresentation(publicAPI, model) {
67
71
mapper : vtkGlyph3DMapper . newInstance ( {
68
72
orientationArray : 'directions' ,
69
73
orientationMode : OrientationModes . DIRECTION ,
74
+ scaleArray : 'lengths' ,
75
+ scaleMode : ScaleModes . SCALE_BY_COMPONENTS ,
70
76
} ) ,
71
77
actor : vtkActor . newInstance ( { parentProp : publicAPI } ) ,
72
78
} ;
@@ -79,62 +85,57 @@ function vtkPolyLineRepresentation(publicAPI, model) {
79
85
const state = inData [ 0 ] ;
80
86
outData [ 0 ] = internalPolyData ;
81
87
82
- // Remove invalid and coincident points.
83
- const list = publicAPI
84
- . getRepresentationStates ( state )
85
- . reduce ( ( subStates , subState ) => {
86
- const subStateOrigin =
87
- subState . getOrigin && subState . getOrigin ( )
88
- ? subState . getOrigin ( )
89
- : null ;
90
- const previousSubStateOrigin =
91
- subStates . length && subStates [ subStates . length - 1 ] . getOrigin ( ) ;
92
- if (
93
- ! subStateOrigin ||
94
- ( previousSubStateOrigin &&
95
- vtkMath . areEquals ( subStateOrigin , previousSubStateOrigin ) )
96
- ) {
97
- return subStates ;
98
- }
99
- subStates . push ( subState ) ;
100
- return subStates ;
101
- } , [ ] ) ;
102
- const size = list . length ;
103
-
104
- allocateSize ( internalPolyData , size , model . closePolyLine && size > 2 ) ;
105
-
106
- const points = internalPolyData . getPoints ( ) . getData ( ) ;
107
- const lines = internalPolyData . getLines ( ) . getData ( ) ;
88
+ const originStates = publicAPI . getRepresentationStates ( state ) ;
89
+ const points = originStates
90
+ . map ( ( subState ) => subState . getOrigin ( ) )
91
+ . filter ( Boolean ) ; // filter out states that return invalid origins
92
+ const pointCount = points . length ;
108
93
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
- }
94
+ allocateSize ( internalPolyData , pointCount , model . close && pointCount > 2 ) ;
95
+
96
+ const glyphPositions = internalPolyData . getPoints ( ) . getData ( ) ;
97
+ const lines = internalPolyData . getLines ( ) . getData ( ) ;
115
98
116
- // Orient glyphs to next point.
117
99
const directions = allocateArray (
118
100
internalPolyData ,
119
101
'directions' ,
120
102
lines . length - 1 ,
121
103
undefined ,
122
104
3
123
105
) . getData ( ) ;
106
+ const lengths = allocateArray (
107
+ internalPolyData ,
108
+ 'lengths' ,
109
+ lines . length - 1 ,
110
+ undefined ,
111
+ 3
112
+ ) . getData ( ) ;
113
+
114
+ const pos = [ ] ; // scratch
124
115
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 , [ ] ) ;
116
+ // Orient glyphs to next point.
117
+ const eye = points [ lines [ point ] ] ;
118
+ const target = points [ lines [ point + 1 ] ] ;
119
+ const direction = vtkMath . subtract ( target , eye , pos ) ;
134
120
const glyph = ( point - 1 ) * 3 ;
135
- directions [ glyph ] = direction [ 0 ] ;
136
- directions [ glyph + 1 ] = direction [ 1 ] ;
137
- directions [ glyph + 2 ] = direction [ 2 ] ;
121
+ [ directions [ glyph ] , directions [ glyph + 1 ] , directions [ glyph + 2 ] ] =
122
+ direction ;
123
+
124
+ // scale to span between points
125
+ const distance = vec3 . length ( direction ) ;
126
+ lengths [ glyph ] = distance ;
127
+ lengths [ glyph + 1 ] = 1 ;
128
+ lengths [ glyph + 2 ] = 1 ;
129
+
130
+ // Position glyph at center of line segment.
131
+ vec3 . normalize ( pos , direction ) ;
132
+ vec3 . scale ( pos , pos , distance / 2 ) ;
133
+ vec3 . add ( pos , eye , direction ) ;
134
+ [
135
+ glyphPositions [ glyph ] ,
136
+ glyphPositions [ glyph + 1 ] ,
137
+ glyphPositions [ glyph + 2 ] ,
138
+ ] = pos ;
138
139
}
139
140
140
141
internalPolyData . getPoints ( ) . modified ( ) ;
@@ -144,14 +145,8 @@ function vtkPolyLineRepresentation(publicAPI, model) {
144
145
applyLineThickness ( lineThickness ) ;
145
146
} ;
146
147
147
- /**
148
- * When mousing over the line, if behavior != CONTEXT,
149
- * returns the parent state.
150
- * @param {object } prop
151
- * @param {number } compositeID
152
- * @returns {object }
153
- */
154
- publicAPI . getSelectedState = ( prop , compositeID ) => model . inputData [ 0 ] ;
148
+ // return array of all states
149
+ publicAPI . getSelectedState = ( ) => model . inputData [ 0 ] ;
155
150
156
151
publicAPI . updateActorVisibility = ( renderingType , ctxVisible , hVisible ) => {
157
152
const state = model . inputData [ 0 ] ;
@@ -176,9 +171,8 @@ function vtkPolyLineRepresentation(publicAPI, model) {
176
171
// ----------------------------------------------------------------------------
177
172
178
173
const DEFAULT_VALUES = {
179
- threshold : Number . EPSILON ,
180
- closePolyLine : false ,
181
- lineThickness : 2 ,
174
+ close : false ,
175
+ lineThickness : 1 ,
182
176
scaleInPixels : true ,
183
177
} ;
184
178
@@ -187,20 +181,16 @@ const DEFAULT_VALUES = {
187
181
export function extend ( publicAPI , model , initialValues = { } ) {
188
182
const newDefault = { ...DEFAULT_VALUES , ...initialValues } ;
189
183
vtkWidgetRepresentation . extend ( publicAPI , model , newDefault ) ;
190
- macro . setGet ( publicAPI , model , [
191
- 'threshold' ,
192
- 'closePolyLine' ,
193
- 'lineThickness' ,
194
- ] ) ;
184
+ macro . setGet ( publicAPI , model , [ 'close' , 'lineThickness' ] ) ;
195
185
196
- vtkPolyLineRepresentation ( publicAPI , model ) ;
186
+ vtkSegmentedLineRepresentation ( publicAPI , model ) ;
197
187
}
198
188
199
189
// ----------------------------------------------------------------------------
200
190
201
191
export const newInstance = macro . newInstance (
202
192
extend ,
203
- 'vtkPolyLineRepresentation '
193
+ 'vtkSegmentedLineRepresentation '
204
194
) ;
205
195
206
196
// ----------------------------------------------------------------------------
0 commit comments