1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkStreamer.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 // .NAME vtkStreamer - abstract object implements integration of massless particle through vector field
16 // .SECTION Description
17 // vtkStreamer is a filter that integrates a massless particle through a vector
18 // field. The integration is performed using second order Runge-Kutta method.
19 // vtkStreamer often serves as a base class for other classes that perform
20 // numerical integration through a vector field (e.g., vtkStreamLine).
21 //
22 // Note that vtkStreamer can integrate both forward and backward in time,
23 // or in both directions. The length of the streamer is controlled by
24 // specifying an elapsed time. (The elapsed time is the time each particle
25 // travels.) Otherwise, the integration terminates after exiting the dataset or
26 // if the particle speed is reduced to a value less than the terminal speed.
27 //
28 // vtkStreamer integrates through any type of dataset. As a result, if the
29 // dataset contains 2D cells such as polygons or triangles, the integration is
30 // constrained to lie on the surface defined by the 2D cells.
31 //
32 // The starting point of streamers may be defined in three different ways.
33 // Starting from global x-y-z "position" allows you to start a single streamer
34 // at a specified x-y-z coordinate. Starting from "location" allows you to
35 // start at a specified cell, subId, and parametric coordinate. Finally, you
36 // may specify a source object to start multiple streamers. If you start
37 // streamers using a source object, for each point in the source that is
38 // inside the dataset a streamer is created.
39 //
40 // vtkStreamer implements the integration process in the Integrate() method.
41 // Because vtkStreamer does not implement the Execute() method that its
42 // superclass (i.e., Filter) requires, it is an abstract class. Its subclasses
43 // implement the execute method and use the Integrate() method, and then build
44 // their own representation of the integration path (i.e., lines, dashed
45 // lines, points, etc.).
46 
47 // .SECTION See Also
48 // vtkStreamLine vtkDashedStreamLine vtkStreamPoints
49 
50 #ifndef vtkStreamer_h
51 #define vtkStreamer_h
52 
53 #include "vtkFiltersFlowPathsModule.h" // For export macro
54 #include "vtkPolyDataAlgorithm.h"
55 
56 class vtkInitialValueProblemSolver;
57 class vtkMultiThreader;
58 
59 #define VTK_INTEGRATE_FORWARD 0
60 #define VTK_INTEGRATE_BACKWARD 1
61 #define VTK_INTEGRATE_BOTH_DIRECTIONS 2
62 
63 class VTKFILTERSFLOWPATHS_EXPORT vtkStreamer : public vtkPolyDataAlgorithm
64 {
65 public:
66   vtkTypeMacro(vtkStreamer,vtkPolyDataAlgorithm);
67   void PrintSelf(ostream& os, vtkIndent indent);
68 
69   // Description:
70   // Specify the start of the streamline in the cell coordinate system. That
71   // is, cellId and subId (if composite cell), and parametric coordinates.
72   void SetStartLocation(vtkIdType cellId, int subId, double pcoords[3]);
73 
74   // Description:
75   // Specify the start of the streamline in the cell coordinate system. That
76   // is, cellId and subId (if composite cell), and parametric coordinates.
77   void SetStartLocation(vtkIdType cellId, int subId, double r, double s,
78                         double t);
79 
80   // Description:
81   // Get the starting location of the streamline in the cell coordinate system.
82   vtkIdType GetStartLocation(int& subId, double pcoords[3]);
83 
84   // Description:
85   // Specify the start of the streamline in the global coordinate
86   // system. Search must be performed to find initial cell to start
87   // integration from.
88   void SetStartPosition(double x[3]);
89 
90   // Description:
91   // Specify the start of the streamline in the global coordinate
92   // system. Search must be performed to find initial cell to start
93   // integration from.
94   void SetStartPosition(double x, double y, double z);
95 
96   // Description:
97   // Get the start position in global x-y-z coordinates.
98   double *GetStartPosition();
99 
100   // Description:
101   // Specify the source object used to generate starting points.
102   void SetSourceData(vtkDataSet *source);
103   vtkDataSet *GetSource();
104 
105   //Description:
106   // Specify the source object used to generate starting points
107   // by making a pipeline connection
108   void SetSourceConnection(vtkAlgorithmOutput* algOutput);
109 
110   // Description:
111   // Specify the maximum length of the Streamer expressed in elapsed time.
112   vtkSetClampMacro(MaximumPropagationTime,double,0.0,VTK_DOUBLE_MAX);
113   vtkGetMacro(MaximumPropagationTime,double);
114 
115   // Description:
116   // Specify the direction in which to integrate the Streamer.
117   vtkSetClampMacro(IntegrationDirection,int,
118                    VTK_INTEGRATE_FORWARD,VTK_INTEGRATE_BOTH_DIRECTIONS);
119   vtkGetMacro(IntegrationDirection,int);
SetIntegrationDirectionToForward()120   void SetIntegrationDirectionToForward()
121     {this->SetIntegrationDirection(VTK_INTEGRATE_FORWARD);};
SetIntegrationDirectionToBackward()122   void SetIntegrationDirectionToBackward()
123     {this->SetIntegrationDirection(VTK_INTEGRATE_BACKWARD);};
SetIntegrationDirectionToIntegrateBothDirections()124   void SetIntegrationDirectionToIntegrateBothDirections()
125     {this->SetIntegrationDirection(VTK_INTEGRATE_BOTH_DIRECTIONS);};
126   const char *GetIntegrationDirectionAsString();
127 
128   // Description:
129   // Specify a nominal integration step size (expressed as a fraction of
130   // the size of each cell). This value can be larger than 1.
131   vtkSetClampMacro(IntegrationStepLength,double,0.0000001,VTK_DOUBLE_MAX);
132   vtkGetMacro(IntegrationStepLength,double);
133 
134   // Description:
135   // Turn on/off the creation of scalar data from velocity magnitude. If off,
136   // and input dataset has scalars, input dataset scalars are used.
137   vtkSetMacro(SpeedScalars,int);
138   vtkGetMacro(SpeedScalars,int);
139   vtkBooleanMacro(SpeedScalars,int);
140 
141   // Description:
142   // Turn on/off the creation of scalar data from vorticity information.
143   // The scalar information is currently the orientation value "theta"
144   // used in rotating stream tubes. If off, and input dataset has scalars,
145   // then input dataset scalars are used, unless SpeedScalars is also on.
146   // SpeedScalars takes precedence over OrientationScalars.
147   vtkSetMacro(OrientationScalars, int);
148   vtkGetMacro(OrientationScalars, int);
149   vtkBooleanMacro(OrientationScalars, int);
150 
151   // Description:
152   // Set/get terminal speed (i.e., speed is velocity magnitude).  Terminal
153   // speed is speed at which streamer will terminate propagation.
154   vtkSetClampMacro(TerminalSpeed,double,0.0,VTK_DOUBLE_MAX);
155   vtkGetMacro(TerminalSpeed,double);
156 
157   // Description:
158   // Turn on/off the computation of vorticity. Vorticity is an indication of
159   // the rotation of the flow. In combination with vtkStreamLine and
160   // vtkTubeFilter can be used to create rotated tubes.
161   // If vorticity is turned on, in the output, the velocity vectors
162   // are replaced by vorticity vectors.
163   vtkSetMacro(Vorticity,int);
164   vtkGetMacro(Vorticity,int);
165   vtkBooleanMacro(Vorticity,int);
166 
167   vtkSetMacro( NumberOfThreads, int );
168   vtkGetMacro( NumberOfThreads, int );
169 
170   vtkSetMacro( SavePointInterval, double );
171   vtkGetMacro( SavePointInterval, double );
172 
173   // Description:
174   // Set/get the integrator type to be used in the stream line
175   // calculation. The object passed is not actually used but
176   // is cloned with NewInstance by each thread/process in the
177   // process of integration (prototype pattern). The default is
178   // 2nd order Runge Kutta.
179   void SetIntegrator(vtkInitialValueProblemSolver *);
180   vtkGetObjectMacro ( Integrator, vtkInitialValueProblemSolver );
181 
182   // Description:
183   // A positive value, as small as possible for numerical comparison.
184   // The initial value is 1E-12.
185   vtkSetMacro(Epsilon,double);
186   vtkGetMacro(Epsilon,double);
187 
188 protected:
189   // Description:
190   // Construct object to start from position (0,0,0); integrate forward;
191   // terminal speed 0.0; vorticity computation off; integrations step length
192   // 0.2; and maximum propagation time 100.0.
193   vtkStreamer();
194   ~vtkStreamer();
195 
196   // Integrate data
197   void Integrate(vtkDataSet *input, vtkDataSet *source);
198 
199   // Controls where streamlines start from (either position or location).
200   int StartFrom;
201 
202   // Starting from cell location
203   vtkIdType StartCell;
204   int StartSubId;
205   double StartPCoords[3];
206 
207   // starting from global x-y-z position
208   double StartPosition[3];
209 
210   //
211   // Special classes for manipulating data
212   //
213   //BTX - begin tcl exclude
214   //
215   class StreamPoint {
216   public:
217     double    x[3];    // position
218     vtkIdType cellId;  // cell
219     int       subId;   // cell sub id
220     double    p[3];    // parametric coords in cell
221     double    v[3];    // velocity
222     double    speed;   // velocity norm
223     double    s;       // scalar value
224     double    t;       // time travelled so far
225     double    d;       // distance travelled so far
226     double    omega;   // stream vorticity, if computed
227     double    theta;   // rotation angle, if vorticity is computed
228   };
229 
230   class StreamArray;
231   friend class StreamArray;
232   class StreamArray { //;prevent man page generation
233   public:
234     StreamArray();
~StreamArray()235     ~StreamArray()
236       {
237         delete [] this->Array;
238       };
GetNumberOfPoints()239     vtkIdType GetNumberOfPoints() {return this->MaxId + 1;};
GetStreamPoint(vtkIdType i)240     StreamPoint *GetStreamPoint(vtkIdType i) {return this->Array + i;};
InsertNextStreamPoint()241     vtkIdType InsertNextStreamPoint()
242       {
243         if ( ++this->MaxId >= this->Size )
244           {
245           this->Resize(this->MaxId);
246           }
247         return this->MaxId; //return offset from array
248       }
249     StreamPoint *Resize(vtkIdType sz); //reallocates data
Reset()250     void Reset() {this->MaxId = -1;};
251 
252     StreamPoint *Array;     // pointer to data
253     vtkIdType MaxId;        // maximum index inserted thus far
254     vtkIdType Size;         // allocated size of data
255     vtkIdType Extend;       // grow array by this amount
256     double Direction;       // integration direction
257   };
258   //ETX
259   //
260 
261   //array of streamers
262   StreamArray *Streamers;
263   vtkIdType NumberOfStreamers;
264 
265   // length of Streamer is generated by time, or by MaximumSteps
266   double MaximumPropagationTime;
267 
268   // integration direction
269   int IntegrationDirection;
270 
271   // the length (fraction of cell size) of integration steps
272   double IntegrationStepLength;
273 
274   // boolean controls whether vorticity is computed
275   int Vorticity;
276 
277   // terminal propagation speed
278   double TerminalSpeed;
279 
280   // boolean controls whether data scalars or velocity magnitude are used
281   int SpeedScalars;
282 
283   // boolean controls whether data scalars or vorticity orientation are used
284   int OrientationScalars;
285 
286   // Prototype showing the integrator type to be set by the user.
287   vtkInitialValueProblemSolver* Integrator;
288 
289   // A positive value, as small as possible for numerical comparison.
290   // The initial value is 1E-12.
291   double Epsilon;
292 
293   // Interval with which the stream points will be stored.
294   // Useful in reducing the memory footprint. Since the initial
295   // value is small, by default, it will store all/most points.
296   double SavePointInterval;
297 
298   static VTK_THREAD_RETURN_TYPE ThreadedIntegrate( void *arg );
299 
300   // Description:
301   // These methods were added to allow access to these variables from the
302   // threads.
303   vtkGetMacro( NumberOfStreamers, vtkIdType );
GetStreamers()304   StreamArray *GetStreamers() { return this->Streamers; };
305 
306   void InitializeThreadedIntegrate();
307   vtkMultiThreader           *Threader;
308   int                        NumberOfThreads;
309 
310   virtual int FillInputPortInformation(int port, vtkInformation *info);
311 
312 private:
313   vtkStreamer(const vtkStreamer&);  // Not implemented.
314   void operator=(const vtkStreamer&);  // Not implemented.
315 };
316 
317 // Description:
318 // Return the integration direction as a character string.
GetIntegrationDirectionAsString()319 inline const char *vtkStreamer::GetIntegrationDirectionAsString()
320 {
321   if ( this->IntegrationDirection == VTK_INTEGRATE_FORWARD )
322     {
323     return "IntegrateForward";
324     }
325   else if ( this->IntegrationDirection == VTK_INTEGRATE_BACKWARD )
326     {
327     return "IntegrateBackward";
328     }
329   else
330     {
331     return "IntegrateBothDirections";
332     }
333 }
334 
335 #endif
336