1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkCurveRepresentation
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   vtkCurveRepresentation
17  * @brief   vtkWidgetRepresentation
18  * base class for a widget that represents an curve that connects control
19  * points.
20  *
21  * Base class for widgets used to define curves from points, such as
22  * vtkPolyLineRepresentation and vtkSplineRepresentation.  This class
23  * uses handles, the number of which can be changed, to represent the
24  * points that define the curve. The handles can be picked can be
25  * picked on the curve itself to translate or rotate it in the scene.
26  */
27 
28 #ifndef vtkCurveRepresentation_h
29 #define vtkCurveRepresentation_h
30 
31 #include "vtkInteractionWidgetsModule.h" // For export macro
32 #include "vtkPolyDataAlgorithm.h"        // needed for vtkPolyDataAlgorithm
33 #include "vtkWidgetRepresentation.h"
34 
35 class vtkActor;
36 class vtkCellPicker;
37 class vtkDoubleArray;
38 class vtkHandleSource;
39 class vtkPlaneSource;
40 class vtkPoints;
41 class vtkPolyData;
42 class vtkProp;
43 class vtkProperty;
44 class vtkTransform;
45 
46 #define VTK_PROJECTION_YZ 0
47 #define VTK_PROJECTION_XZ 1
48 #define VTK_PROJECTION_XY 2
49 #define VTK_PROJECTION_OBLIQUE 3
50 class VTKINTERACTIONWIDGETS_EXPORT vtkCurveRepresentation : public vtkWidgetRepresentation
51 {
52 public:
53   vtkTypeMacro(vtkCurveRepresentation, vtkWidgetRepresentation);
54   void PrintSelf(ostream& os, vtkIndent indent) override;
55 
56   // Used to manage the InteractionState of the widget
57   enum _InteractionState
58   {
59     Outside = 0,
60     OnHandle,
61     OnLine,
62     Moving,
63     Scaling,
64     Spinning,
65     Inserting,
66     Erasing,
67     Pushing
68   };
69 
70   ///@{
71   /**
72    * Set the interaction state
73    */
74   vtkSetMacro(InteractionState, int);
75   ///@}
76 
77   ///@{
78   /**
79    * Force the widget to be projected onto one of the orthogonal
80    * planes.  Remember that when the InteractionState changes, a
81    * ModifiedEvent is invoked.  This can be used to snap the curve to
82    * the plane if it is originally not aligned.  The normal in
83    * SetProjectionNormal is 0,1,2 for YZ,XZ,XY planes respectively and
84    * 3 for arbitrary oblique planes when the widget is tied to a
85    * vtkPlaneSource.
86    */
87   vtkSetMacro(ProjectToPlane, vtkTypeBool);
88   vtkGetMacro(ProjectToPlane, vtkTypeBool);
89   vtkBooleanMacro(ProjectToPlane, vtkTypeBool);
90   ///@}
91 
92   /**
93    * Set up a reference to a vtkPlaneSource that could be from another widget
94    * object, e.g. a vtkPolyDataSourceWidget.
95    */
96   void SetPlaneSource(vtkPlaneSource* plane);
97 
98   vtkSetClampMacro(ProjectionNormal, int, VTK_PROJECTION_YZ, VTK_PROJECTION_OBLIQUE);
99   vtkGetMacro(ProjectionNormal, int);
SetProjectionNormalToXAxes()100   void SetProjectionNormalToXAxes() { this->SetProjectionNormal(0); }
SetProjectionNormalToYAxes()101   void SetProjectionNormalToYAxes() { this->SetProjectionNormal(1); }
SetProjectionNormalToZAxes()102   void SetProjectionNormalToZAxes() { this->SetProjectionNormal(2); }
SetProjectionNormalToOblique()103   void SetProjectionNormalToOblique() { this->SetProjectionNormal(3); }
104 
105   ///@{
106   /**
107    * Set the position of poly line handles and points in terms of a plane's
108    * position. i.e., if ProjectionNormal is 0, all of the x-coordinate
109    * values of the points are set to position. Any value can be passed (and is
110    * ignored) to update the poly line points when Projection normal is set to 3
111    * for arbitrary plane orientations.
112    */
113   void SetProjectionPosition(double position);
114   vtkGetMacro(ProjectionPosition, double);
115   ///@}
116 
117   /**
118    * Grab the polydata (including points) that defines the
119    * interpolating curve. Points are guaranteed to be up-to-date when
120    * either the InteractionEvent or EndInteraction events are
121    * invoked. The user provides the vtkPolyData and the points and
122    * polyline are added to it.
123    */
124   virtual void GetPolyData(vtkPolyData* pd) = 0;
125 
126   ///@{
127   /**
128    * Set/Get the handle properties (the spheres are the handles). The
129    * properties of the handles when selected and unselected can be manipulated.
130    */
131   vtkGetObjectMacro(HandleProperty, vtkProperty);
132   vtkGetObjectMacro(SelectedHandleProperty, vtkProperty);
133   ///@}
134 
135   ///@{
136   /**
137    * Set/Get the line properties. The properties of the line when selected
138    * and unselected can be manipulated.
139    */
140   vtkGetObjectMacro(LineProperty, vtkProperty);
141   vtkGetObjectMacro(SelectedLineProperty, vtkProperty);
142   ///@}
143 
144   ///@{
145   /**
146    * Set/Get the number of handles for this widget.
147    */
148   virtual void SetNumberOfHandles(int npts) = 0;
149   vtkGetMacro(NumberOfHandles, int);
150   ///@}
151 
152   ///@{
153   /**
154    * @deprecated VTK 9.1. Use `GetDirectional`  and `SetDirectional` instead.
155    */
156   VTK_DEPRECATED_IN_9_1_0("renamed to SetDirectional")
157   virtual void SetDirectionalLine(bool val);
158   VTK_DEPRECATED_IN_9_1_0("renamed to GetDirectional")
159   virtual bool GetDirectionalLine();
160   VTK_DEPRECATED_IN_9_1_0("renamed to DirectionalOn")
161   virtual void DirectionalLineOn();
162   VTK_DEPRECATED_IN_9_1_0("renamed to DirectionalOff")
163   virtual void DirectionalLineOff();
164   ///@}
165 
166   ///@{
167   /**
168    * Set the representation to be directional or not.
169    * The meaning of being directional depends on the representation and
170    * its handles implementations in the subclasses.
171    */
172   virtual void SetDirectional(bool val);
173   vtkGetMacro(Directional, bool);
174   vtkBooleanMacro(Directional, bool);
175   ///@}
176 
177   ///@{
178   /**
179    * Set/Get the position of the handles. Call GetNumberOfHandles
180    * to determine the valid range of handle indices.
181    */
182   virtual void SetHandlePosition(int handle, double x, double y, double z);
183   virtual void SetHandlePosition(int handle, double xyz[3]);
184   virtual void GetHandlePosition(int handle, double xyz[3]);
185   virtual double* GetHandlePosition(int handle);
186   virtual vtkDoubleArray* GetHandlePositions() = 0;
187   ///@}
188 
189   ///@{
190   /**
191    * Control whether the curve is open or closed. A closed forms a
192    * continuous loop: the first and last points are the same.  A
193    * minimum of 3 handles are required to form a closed loop.
194    */
195   void SetClosed(vtkTypeBool closed);
196   vtkGetMacro(Closed, vtkTypeBool);
197   vtkBooleanMacro(Closed, vtkTypeBool);
198   ///@}
199 
200   /**
201    * Convenience method to determine whether the curve is
202    * closed in a geometric sense.  The widget may be set "closed" but still
203    * be geometrically open (e.g., a straight line).
204    */
205   vtkTypeBool IsClosed();
206 
207   /**
208    * Get the approximate vs. the true arc length of the curve. Calculated as
209    * the summed lengths of the individual straight line segments. Use
210    * SetResolution to control the accuracy.
211    */
212   virtual double GetSummedLength() = 0;
213 
214   /**
215    * Convenience method to allocate and set the handles from a
216    * vtkPoints instance.  If the first and last points are the same,
217    * the curve sets Closed to the on InteractionState and disregards
218    * the last point, otherwise Closed remains unchanged.
219    */
220   virtual void InitializeHandles(vtkPoints* points) = 0;
221 
222   ///@{
223   /**
224    * These are methods that satisfy vtkWidgetRepresentation
225    * API. Note that a version of place widget is available where the
226    * center and handle position are specified.
227    */
228   void BuildRepresentation() override = 0;
229   int ComputeInteractionState(int X, int Y, int modify = 0) override;
230   void StartWidgetInteraction(double e[2]) override;
231   void WidgetInteraction(double e[2]) override;
232   void EndWidgetInteraction(double e[2]) override;
233   double* GetBounds() override;
234   ///@}
235 
236   ///@{
237   /**
238    * Methods supporting, and required by, the rendering process.
239    */
240   void ReleaseGraphicsResources(vtkWindow*) override;
241   int RenderOpaqueGeometry(vtkViewport*) override;
242   int RenderTranslucentPolygonalGeometry(vtkViewport*) override;
243   int RenderOverlay(vtkViewport*) override;
244   vtkTypeBool HasTranslucentPolygonalGeometry() override;
245   ///@}
246 
247   /**
248    * Convenience method to set the line color.
249    * Ideally one should use GetLineProperty()->SetColor().
250    */
251   void SetLineColor(double r, double g, double b);
252 
253   /*
254    * Register internal Pickers within PickingManager
255    */
256   void RegisterPickers() override;
257 
258   ///@{
259   /**
260    * Get/Set the current handle index. Setting the current handle index will
261    * also result in the handle being highlighted. Set to `-1` to remove the
262    * highlight.
263    */
264   void SetCurrentHandleIndex(int index);
265   vtkGetMacro(CurrentHandleIndex, int);
266   ///@}
267 
268   ///@{
269   /**
270    * Gets/Sets the constraint axis for translations. Returns Axis::NONE
271    * if none.
272    **/
273   vtkGetMacro(TranslationAxis, int);
274   vtkSetClampMacro(TranslationAxis, int, -1, 2);
275   ///@}
276 
277   ///@{
278   /**
279    * Toggles constraint translation axis on/off.
280    */
SetXTranslationAxisOn()281   void SetXTranslationAxisOn() { this->TranslationAxis = Axis::XAxis; }
SetYTranslationAxisOn()282   void SetYTranslationAxisOn() { this->TranslationAxis = Axis::YAxis; }
SetZTranslationAxisOn()283   void SetZTranslationAxisOn() { this->TranslationAxis = Axis::ZAxis; }
SetTranslationAxisOff()284   void SetTranslationAxisOff() { this->TranslationAxis = Axis::NONE; }
285   ///@}
286 
287   ///@{
288   /**
289    * Returns true if ContrainedAxis
290    **/
IsTranslationConstrained()291   bool IsTranslationConstrained() { return this->TranslationAxis != Axis::NONE; }
292   ///@}
293 
294 protected:
295   vtkCurveRepresentation();
296   ~vtkCurveRepresentation() override;
297 
298   double LastEventPosition[3];
299   double Bounds[6];
300 
301   // Controlling vars
302   int ProjectionNormal;
303   double ProjectionPosition;
304   vtkTypeBool ProjectToPlane;
305   vtkPlaneSource* PlaneSource;
306 
307   // Projection capabilities
308   void ProjectPointsToPlane();
309   void ProjectPointsToOrthoPlane();
310   void ProjectPointsToObliquePlane();
311 
312   int NumberOfHandles = 0;
313   vtkTypeBool Closed;
314 
315   // The line segments
316   vtkActor* LineActor;
317   void HighlightLine(int highlight);
318   int HighlightHandle(vtkProp* prop); // returns handle index or -1 on fail
319 
320   // accessors to glyphs representing hot spots (e.g., handles)
321   virtual vtkActor* GetHandleActor(int index) = 0;
322   virtual vtkHandleSource* GetHandleSource(int index) = 0;
323 
324   /**
325    * returns handle index or -1 on fail
326    */
327   virtual int GetHandleIndex(vtkProp* prop) = 0;
328   virtual void SizeHandles();
329 
330   /**
331    * Returns the position of insertion or -1 on fail.
332    */
333   virtual int InsertHandleOnLine(double* pos) = 0;
334 
335   virtual void PushHandle(double* pos);
336   virtual void EraseHandle(const int&);
337 
338   // Do the picking
339   vtkCellPicker* HandlePicker;
340   vtkCellPicker* LinePicker;
341   double LastPickPosition[3];
342   vtkActor* CurrentHandle;
343   int CurrentHandleIndex;
344   bool FirstSelected;
345 
346   // Methods to manipulate the curve.
347   void MovePoint(double* p1, double* p2);
348   void Scale(double* p1, double* p2, int X, int Y);
349   void Translate(double* p1, double* p2);
350   void Spin(double* p1, double* p2, double* vpn);
351 
352   // Transform the control points (used for spinning)
353   vtkTransform* Transform;
354 
355   // Manage how the representation appears
356   bool Directional = false;
357 
358   // Properties used to control the appearance of selected objects and
359   // the manipulator in general.
360   vtkProperty* HandleProperty;
361   vtkProperty* SelectedHandleProperty;
362   vtkProperty* LineProperty;
363   vtkProperty* SelectedLineProperty;
364   void CreateDefaultProperties();
365 
366   // For efficient spinning
367   double Centroid[3];
368   void CalculateCentroid();
369 
370   int TranslationAxis;
371 
372 private:
373   vtkCurveRepresentation(const vtkCurveRepresentation&) = delete;
374   void operator=(const vtkCurveRepresentation&) = delete;
375 };
376 #endif
377