1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkContourRepresentation.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 /**
16  * @class   vtkContourRepresentation
17  * @brief   represent the vtkContourWidget
18  *
19  * The vtkContourRepresentation is a superclass for various types of
20  * representations for vtkContourWidget.
21  *
22  * @par Managing contour points:
23  * The classes vtkContourRepresentationNode, vtkContourRepresentationInternals,
24  * and vtkContourRepresentationPoint manage the data structure used to represent
25  * nodes and points on a contour. A contour may contain several nodes and
26  * several additional points. Nodes are usually the result of user-clicked points
27  * on the contour. Additional points are created between nodes to generate a
28  * smooth curve using some Interpolator -- see the method \c SetLineInterpolator.
29  *
30  * @par Managing contour points:
31  * \par
32  * The data structure stores both the world and display positions for every
33  * point. (This may seem like a duplication.) The default behaviour of this
34  * class is to use the WorldPosition to do all the math. Typically a point is
35  * added at a given display position. Its corresponding world position is
36  * computed using the point placer, and stored. Any query of the display
37  * position of a stored point is done via the Renderer, which computes the
38  * display position given a world position.
39  *
40  * @par Managing contour points:
41  * \par
42  * So why maintain the display position? Consider drawing a contour on a
43  * volume widget. You might want the contour to be located at a certain world
44  * position in the volume or you might want to be overlaid over the window
45  * like an Actor2D. The default behaviour of this class is to provide the
46  * former behaviour.
47  *
48  * @par Managing contour points:
49  * \par
50  * To achieve the latter behaviour, override the methods that return the display
51  * position (to return the set display position instead of computing it from
52  * the world positions) and the method \c BuildLines() to interpolate lines
53  * using their display positions instead of world positions.
54  *
55  * @sa
56  * vtkContourWidget
57 */
58 
59 #ifndef vtkContourRepresentation_h
60 #define vtkContourRepresentation_h
61 
62 #include "vtkInteractionWidgetsModule.h" // For export macro
63 #include "vtkWidgetRepresentation.h"
64 #include <vector> // STL Header; Required for vector
65 
66 class vtkContourLineInterpolator;
67 class vtkIncrementalOctreePointLocator;
68 class vtkPointPlacer;
69 class vtkPolyData;
70 class vtkIdList;
71 
72 //----------------------------------------------------------------------
73 class vtkContourRepresentationPoint
74 {
75 public:
76   double        WorldPosition[3];
77   double        NormalizedDisplayPosition[2];
78 
79   // The point id. This is blank except in the case of
80   // vtkPolygonalSurfaceContourLineInterpolator
81   vtkIdType     PointId;
82 };
83 
84 class vtkContourRepresentationNode
85 {
86 public:
87   double        WorldPosition[3];
88   double        WorldOrientation[9];
89   double        NormalizedDisplayPosition[2];
90   int           Selected;
91   std::vector<vtkContourRepresentationPoint*> Points;
92 
93   // The point id. This is blank except in the case of
94   // vtkPolygonalSurfaceContourLineInterpolator
95   vtkIdType     PointId;
96 };
97 
98 class vtkContourRepresentationInternals
99 {
100 public:
101   std::vector<vtkContourRepresentationNode*> Nodes;
ClearNodes()102   void ClearNodes()
103   {
104     for(unsigned int i=0;i<this->Nodes.size();i++)
105     {
106       for (unsigned int j=0;j<this->Nodes[i]->Points.size();j++)
107       {
108         delete this->Nodes[i]->Points[j];
109       }
110       this->Nodes[i]->Points.clear();
111       delete this->Nodes[i];
112     }
113     this->Nodes.clear();
114   }
115 };
116 
117 class VTKINTERACTIONWIDGETS_EXPORT vtkContourRepresentation : public vtkWidgetRepresentation
118 {
119   friend class vtkContourWidget;
120 public:
121   //@{
122   /**
123    * Standard VTK methods.
124    */
125   vtkTypeMacro(vtkContourRepresentation,vtkWidgetRepresentation);
126   void PrintSelf(ostream& os, vtkIndent indent) override;
127   //@}
128 
129   //@{
130   /**
131    * Add a node at a specific world position. Returns 0 if the
132    * node could not be added, 1 otherwise.
133    */
134   virtual int AddNodeAtWorldPosition( double x, double y, double z);
135   virtual int AddNodeAtWorldPosition( double worldPos[3] );
136   virtual int AddNodeAtWorldPosition( double worldPos[3],
137                                       double worldOrient[9] );
138   //@}
139 
140   //@{
141   /**
142    * Add a node at a specific display position. This will be
143    * converted into a world position according to the current
144    * constraints of the point placer. Return 0 if a point could
145    * not be added, 1 otherwise.
146    */
147   virtual int AddNodeAtDisplayPosition( double displayPos[2] );
148   virtual int AddNodeAtDisplayPosition( int displayPos[2] );
149   virtual int AddNodeAtDisplayPosition( int X, int Y );
150   //@}
151 
152   //@{
153   /**
154    * Given a display position, activate a node. The closest
155    * node within tolerance will be activated. If a node is
156    * activated, 1 will be returned, otherwise 0 will be
157    * returned.
158    */
159   virtual int ActivateNode( double displayPos[2] );
160   virtual int ActivateNode( int displayPos[2] );
161   virtual int ActivateNode( int X, int Y );
162   //@}
163 
164   // Description:
165   // Move the active node to a specified world position.
166   // Will return 0 if there is no active node or the node
167   // could not be moved to that position. 1 will be returned
168   // on success.
169   virtual int SetActiveNodeToWorldPosition( double pos[3] );
170   virtual int SetActiveNodeToWorldPosition( double pos[3],
171                                             double orient[9] );
172 
173   //@{
174   /**
175    * Move the active node based on a specified display position.
176    * The display position will be converted into a world
177    * position. If the new position is not valid or there is
178    * no active node, a 0 will be returned. Otherwise, on
179    * success a 1 will be returned.
180    */
181   virtual int SetActiveNodeToDisplayPosition( double pos[2] );
182   virtual int SetActiveNodeToDisplayPosition( int pos[2] );
183   virtual int SetActiveNodeToDisplayPosition( int X, int Y );
184   //@}
185 
186   //@{
187   /**
188    * Set/Get whether the active or nth node is selected.
189    */
190   virtual int ToggleActiveNodeSelected();
191   virtual int GetActiveNodeSelected();
192   virtual int GetNthNodeSelected(int);
193   virtual int SetNthNodeSelected(int);
194   //@}
195 
196   /**
197    * Get the world position of the active node. Will return
198    * 0 if there is no active node, or 1 otherwise.
199    */
200   virtual int GetActiveNodeWorldPosition( double pos[3] );
201 
202   /**
203    * Get the world orientation of the active node. Will return
204    * 0 if there is no active node, or 1 otherwise.
205    */
206   virtual int GetActiveNodeWorldOrientation( double orient[9] );
207 
208   /**
209    * Get the display position of the active node. Will return
210    * 0 if there is no active node, or 1 otherwise.
211    */
212   virtual int GetActiveNodeDisplayPosition( double pos[2] );
213 
214   /**
215    * Get the number of nodes.
216    */
217   virtual int GetNumberOfNodes();
218 
219   /**
220    * Get the nth node's display position. Will return
221    * 1 on success, or 0 if there are not at least
222    * (n+1) nodes (0 based counting).
223    */
224   virtual int GetNthNodeDisplayPosition( int n, double pos[2] );
225 
226   /**
227    * Get the nth node's world position. Will return
228    * 1 on success, or 0 if there are not at least
229    * (n+1) nodes (0 based counting).
230    */
231   virtual int GetNthNodeWorldPosition( int n, double pos[3] );
232 
233   /**
234    * Get the nth node.
235    */
236   virtual vtkContourRepresentationNode *GetNthNode(int n);
237 
238   /**
239    * Get the nth node's world orientation. Will return
240    * 1 on success, or 0 if there are not at least
241    * (n+1) nodes (0 based counting).
242    */
243   virtual int GetNthNodeWorldOrientation( int n, double orient[9] );
244 
245   //@{
246   /**
247    * Set the nth node's display position. Display position
248    * will be converted into world position according to the
249    * constraints of the point placer. Will return
250    * 1 on success, or 0 if there are not at least
251    * (n+1) nodes (0 based counting) or the world position
252    * is not valid.
253    */
254   virtual int SetNthNodeDisplayPosition( int n, int X, int Y );
255   virtual int SetNthNodeDisplayPosition( int n, int pos[2] );
256   virtual int SetNthNodeDisplayPosition( int n, double pos[2] );
257   //@}
258 
259   //@{
260   /**
261    * Set the nth node's world position. Will return
262    * 1 on success, or 0 if there are not at least
263    * (n+1) nodes (0 based counting) or the world
264    * position is not valid according to the point
265    * placer.
266    */
267   virtual int SetNthNodeWorldPosition( int n, double pos[3] );
268   virtual int SetNthNodeWorldPosition( int n, double pos[3],
269                                        double orient[9] );
270   //@}
271 
272   /**
273    * Get the nth node's slope. Will return
274    * 1 on success, or 0 if there are not at least
275    * (n+1) nodes (0 based counting).
276    */
277   virtual int  GetNthNodeSlope( int idx, double slope[3] );
278 
279   // Description:
280   // For a given node n, get the number of intermediate
281   // points between this node and the node at
282   // (n+1). If n is the last node and the loop is
283   // closed, this is the number of intermediate points
284   // between node n and node 0. 0 is returned if n is
285   // out of range.
286   virtual int GetNumberOfIntermediatePoints( int n );
287 
288   /**
289    * Get the world position of the intermediate point at
290    * index idx between nodes n and (n+1) (or n and 0 if
291    * n is the last node and the loop is closed). Returns
292    * 1 on success or 0 if n or idx are out of range.
293    */
294   virtual int GetIntermediatePointWorldPosition( int n,
295                                                  int idx, double point[3] );
296 
297   /**
298    * Add an intermediate point between node n and n+1
299    * (or n and 0 if n is the last node and the loop is closed).
300    * Returns 1 on success or 0 if n is out of range.
301    */
302   virtual int AddIntermediatePointWorldPosition( int n,
303                                                  double point[3] );
304 
305   /**
306    * Add an intermediate point between node n and n+1
307    * (or n and 0 if n is the last node and the loop is closed).
308    * Returns 1 on success or 0 if n is out of range. The added point is
309    * assigned a ptId as supplied.
310    */
311   virtual int AddIntermediatePointWorldPosition( int n,
312                                double point[3], vtkIdType ptId );
313 
314   /**
315    * Delete the last node. Returns 1 on success or 0 if
316    * there were not any nodes.
317    */
318   virtual int DeleteLastNode();
319 
320   /**
321    * Delete the active node. Returns 1 on success or 0 if
322    * the active node did not indicate a valid node.
323    */
324   virtual int DeleteActiveNode();
325 
326   /**
327    * Delete the nth node. Return 1 on success or 0 if n
328    * is out of range.
329    */
330   virtual int DeleteNthNode( int n );
331 
332   /**
333    * Delete all nodes.
334    */
335   virtual void ClearAllNodes();
336 
337   /**
338    * Given a specific X, Y pixel location, add a new node
339    * on the contour at this location.
340    */
341   virtual int AddNodeOnContour( int X, int Y );
342 
343   //@{
344   /**
345    * The tolerance to use when calculations are performed in
346    * display coordinates
347    */
348   vtkSetClampMacro(PixelTolerance,int,1,100);
349   vtkGetMacro(PixelTolerance,int);
350   //@}
351 
352   //@{
353   /**
354    * The tolerance to use when calculations are performed in
355    * world coordinates
356    */
357   vtkSetClampMacro(WorldTolerance, double, 0.0, VTK_DOUBLE_MAX);
358   vtkGetMacro(WorldTolerance, double);
359   //@}
360 
361   // Used to communicate about the state of the representation
362   enum {
363     Outside=0,
364     Nearby
365   };
366 
367   enum {
368     Inactive = 0,
369     Translate,
370     Shift,
371     Scale
372   };
373 
374   //@{
375   /**
376    * Set / get the current operation. The widget is either
377    * inactive, or it is being translated.
378    */
379   vtkGetMacro( CurrentOperation, int );
380   vtkSetClampMacro( CurrentOperation, int,
381                     vtkContourRepresentation::Inactive,
382                     vtkContourRepresentation::Scale );
SetCurrentOperationToInactive()383   void SetCurrentOperationToInactive()
384     { this->SetCurrentOperation( vtkContourRepresentation::Inactive ); }
SetCurrentOperationToTranslate()385   void SetCurrentOperationToTranslate()
386     { this->SetCurrentOperation( vtkContourRepresentation::Translate ); }
SetCurrentOperationToShift()387   void SetCurrentOperationToShift()
388     {this->SetCurrentOperation( vtkContourRepresentation::Shift ); }
SetCurrentOperationToScale()389   void SetCurrentOperationToScale()
390     {this->SetCurrentOperation( vtkContourRepresentation::Scale ); }
391   //@}
392 
393   // Description:
394   // Set / get the Point Placer. The point placer is
395   // responsible for converting display coordinates into
396   // world coordinates according to some constraints, and
397   // for validating world positions.
398   void SetPointPlacer( vtkPointPlacer * );
399   vtkGetObjectMacro( PointPlacer, vtkPointPlacer );
400 
401   //@{
402   /**
403    * Set / Get the Line Interpolator. The line interpolator
404    * is responsible for generating the line segments connecting
405    * nodes.
406    */
407   void SetLineInterpolator( vtkContourLineInterpolator *);
408   vtkGetObjectMacro( LineInterpolator, vtkContourLineInterpolator );
409   //@}
410 
411   //@{
412   /**
413    * These are methods that satisfy vtkWidgetRepresentation's API.
414    */
415   void BuildRepresentation() override =0;
416   int ComputeInteractionState(int X, int Y, int modified=0) override =0;
417   void StartWidgetInteraction(double e[2]) override =0;
418   void WidgetInteraction(double e[2]) override =0;
419   //@}
420 
421   //@{
422   /**
423    * Methods required by vtkProp superclass.
424    */
425   void ReleaseGraphicsResources(vtkWindow *w) override =0;
426   int RenderOverlay(vtkViewport *viewport) override =0;
427   int RenderOpaqueGeometry(vtkViewport *viewport) override =0;
428   int RenderTranslucentPolygonalGeometry(vtkViewport *viewport) override =0;
429   vtkTypeBool HasTranslucentPolygonalGeometry() override =0;
430   //@}
431 
432   //@{
433   /**
434    * Set / Get the ClosedLoop value. This ivar indicates whether the contour
435    * forms a closed loop.
436    */
437   void SetClosedLoop( vtkTypeBool val );
438   vtkGetMacro( ClosedLoop, vtkTypeBool );
439   vtkBooleanMacro( ClosedLoop, vtkTypeBool );
440   //@}
441 
442   //@{
443   /**
444    * A flag to indicate whether to show the Selected nodes
445    * Default is to set it to false.
446    */
447   virtual void SetShowSelectedNodes(vtkTypeBool);
448   vtkGetMacro( ShowSelectedNodes, vtkTypeBool );
449   vtkBooleanMacro( ShowSelectedNodes, vtkTypeBool );
450   //@}
451 
452   /**
453    * Get the points in this contour as a vtkPolyData.
454    */
455   virtual vtkPolyData* GetContourRepresentationAsPolyData() = 0;
456 
457   /**
458    * Get the nodes and not the intermediate points in this
459    * contour as a vtkPolyData.
460    */
461   void GetNodePolyData( vtkPolyData* poly );
462 
463   vtkSetMacro(RebuildLocator,bool);
464 
465 protected:
466   vtkContourRepresentation();
467   ~vtkContourRepresentation() override;
468 
469   // Selection tolerance for the handles
470   int    PixelTolerance;
471   double WorldTolerance;
472 
473   vtkPointPlacer             *PointPlacer;
474   vtkContourLineInterpolator *LineInterpolator;
475 
476   int ActiveNode;
477 
478   int CurrentOperation;
479   vtkTypeBool ClosedLoop;
480 
481   // A flag to indicate whether to show the Selected nodes
482   vtkTypeBool                   ShowSelectedNodes;
483 
484   vtkContourRepresentationInternals *Internal;
485 
486   void AddNodeAtPositionInternal( double worldPos[3],
487                                   double worldOrient[9], int displayPos[2] );
488   void AddNodeAtPositionInternal( double worldPos[3],
489                                   double worldOrient[9], double displayPos[2] );
490   void SetNthNodeWorldPositionInternal( int n, double worldPos[3],
491                                         double worldOrient[9] );
492 
493   //@{
494   /**
495    * Given a world position and orientation, this computes the display position
496    * using the renderer of this class.
497    */
498   void GetRendererComputedDisplayPositionFromWorldPosition( double worldPos[3],
499                                     double worldOrient[9], int displayPos[2] );
500   void GetRendererComputedDisplayPositionFromWorldPosition( double worldPos[3],
501                                     double worldOrient[9], double displayPos[2] );
502   //@}
503 
504   virtual void UpdateLines( int index );
505   void UpdateLine( int idx1, int idx2 );
506 
507   virtual int FindClosestPointOnContour( int X, int Y,
508                                  double worldPos[3],
509                                  int *idx );
510 
511   virtual void BuildLines()=0;
512 
513   // This method is called when something changes in the point placer.
514   // It will cause all points to be updated, and all lines to be regenerated.
515   // It should be extended to detect changes in the line interpolator too.
516   virtual int  UpdateContour();
517   vtkTimeStamp ContourBuildTime;
518 
ComputeMidpoint(double p1[3],double p2[3],double mid[3])519   void ComputeMidpoint( double p1[3], double p2[3], double mid[3] )
520   {
521       mid[0] = (p1[0] + p2[0])/2;
522       mid[1] = (p1[1] + p2[1])/2;
523       mid[2] = (p1[2] + p2[2])/2;
524   }
525 
526   /**
527    * Build a contour representation from externally supplied PolyData. This
528    * is very useful when you use an external program to compute a set of
529    * contour nodes (let's say based on image features) and subsequently want
530    * to build and display a contour that runs through those points.
531    * This method is protected and accessible only from
532    * vtkContourWidget::Initialize. The idlist here may be used to initialize
533    * a contour widget that uses a vtkPolygonalSurfacePointPlacer. This stores
534    * the point id's of the nodes, since the contour is drawn on the vertices
535    * of a surface mesh.
536    */
537   virtual void Initialize( vtkPolyData *, vtkIdList *);
538 
539   /**
540    * Overloaded initialize method, that is called when the vtkIdList is nullptr
541    * to maintain backwards compatibility.
542    */
543   virtual void Initialize( vtkPolyData *);
544 
545   /**
546    * Internal implementation, delegated to another method, so that users who
547    * override the method Initialize that takes in one argument are supported.
548    */
549   virtual void InitializeContour( vtkPolyData *, vtkIdList * );
550 
551   /**
552    * Adding a point locator to the representation to speed
553    * up lookup of the active node when dealing with large datasets (100k+)
554    */
555   vtkIncrementalOctreePointLocator *Locator;
556 
557   /**
558    * Deletes the previous locator if it exists and creates
559    * a new locator. Also deletes / recreates the attached data set.
560    */
561   void ResetLocator();
562 
563   void BuildLocator();
564 
565   bool RebuildLocator;
566 
567 
568 private:
569   vtkContourRepresentation(const vtkContourRepresentation&) = delete;
570   void operator=(const vtkContourRepresentation&) = delete;
571 };
572 
573 #endif
574 
575