1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkBorderRepresentation.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   vtkBorderRepresentation
17  * @brief   represent a vtkBorderWidget
18  *
19  * This class is used to represent and render a vtBorderWidget. To
20  * use this class, you need to specify the two corners of a rectangular
21  * region.
22  *
23  * The class is typically subclassed so that specialized representations can
24  * be created.  The class defines an API and a default implementation that
25  * the vtkBorderRepresentation interacts with to render itself in the scene.
26  *
27  * @warning
28  * The separation of the widget event handling (e.g., vtkBorderWidget) from
29  * the representation (vtkBorderRepresentation) enables users and developers
30  * to create new appearances for the widget. It also facilitates parallel
31  * processing, where the client application handles events, and remote
32  * representations of the widget are slaves to the client (and do not handle
33  * events).
34  *
35  * @sa
36  * vtkBorderWidget vtkTextWidget
37  */
38 
39 #ifndef vtkBorderRepresentation_h
40 #define vtkBorderRepresentation_h
41 
42 #include "vtkCoordinate.h"               //Because of the viewport coordinate macro
43 #include "vtkInteractionWidgetsModule.h" // For export macro
44 #include "vtkWidgetRepresentation.h"
45 
46 #include "vtkNew.h" // for ivars
47 
48 class vtkPoints;
49 class vtkPolyData;
50 class vtkTransform;
51 class vtkTransformPolyDataFilter;
52 class vtkPolyDataMapper2D;
53 class vtkActor2D;
54 class vtkProperty2D;
55 class vtkCellArray;
56 
57 class VTKINTERACTIONWIDGETS_EXPORT vtkBorderRepresentation : public vtkWidgetRepresentation
58 {
59 public:
60   /**
61    * Instantiate this class.
62    */
63   static vtkBorderRepresentation* New();
64 
65   ///@{
66   /**
67    * Define standard methods.
68    */
69   vtkTypeMacro(vtkBorderRepresentation, vtkWidgetRepresentation);
70   void PrintSelf(ostream& os, vtkIndent indent) override;
71   ///@}
72 
73   ///@{
74   /**
75    * Specify opposite corners of the box defining the boundary of the
76    * widget. By default, these coordinates are in the normalized viewport
77    * coordinate system, with Position the lower left of the outline, and
78    * Position2 relative to Position. Note that using these methods are
79    * affected by the ProportionalResize flag. That is, if the aspect ratio of
80    * the representation is to be preserved (e.g., ProportionalResize is on),
81    * then the rectangle (Position,Position2) is a bounding rectangle.
82    */
83   vtkViewportCoordinateMacro(Position);
84   vtkViewportCoordinateMacro(Position2);
85   ///@}
86 
87   enum
88   {
89     BORDER_OFF = 0,
90     BORDER_ON,
91     BORDER_ACTIVE
92   };
93 
94   ///@{
95   /**
96    * Specify when and if the border should appear. If ShowBorder is "on",
97    * then the border will always appear. If ShowBorder is "off" then the
98    * border will never appear.  If ShowBorder is "active" then the border
99    * will appear when the mouse pointer enters the region bounded by the
100    * border widget.
101    * This method is provided as conveniency to set both horizontal and
102    * vertical borders.
103    * BORDER_ON by default.
104    * See Also: SetShowHorizontalBorder(), SetShowVerticalBorder()
105    */
106   virtual void SetShowBorder(int border);
107   virtual int GetShowBorderMinValue();
108   virtual int GetShowBorderMaxValue();
109   virtual int GetShowBorder();
SetShowBorderToOff()110   void SetShowBorderToOff() { this->SetShowBorder(BORDER_OFF); }
SetShowBorderToOn()111   void SetShowBorderToOn() { this->SetShowBorder(BORDER_ON); }
SetShowBorderToActive()112   void SetShowBorderToActive() { this->SetShowBorder(BORDER_ACTIVE); }
113   ///@}
114 
115   ///@{
116   /**
117    * Specify when and if the vertical border should appear.
118    * See Also: SetShowBorder(), SetShowHorizontalBorder()
119    */
120   vtkSetClampMacro(ShowVerticalBorder, int, BORDER_OFF, BORDER_ACTIVE);
121   vtkGetMacro(ShowVerticalBorder, int);
122   ///@}
123 
124   ///@{
125   /**
126    * Specify when and if the horizontal border should appear.
127    * See Also: SetShowBorder(), SetShowVerticalBorder()
128    */
129   vtkSetClampMacro(ShowHorizontalBorder, int, BORDER_OFF, BORDER_ACTIVE);
130   vtkGetMacro(ShowHorizontalBorder, int);
131   ///@}
132 
133   ///@{
134   /**
135    * Specify the properties of the border.
136    */
137   vtkGetObjectMacro(BorderProperty, vtkProperty2D);
138   ///@}
139 
140   ///@{
141   /**
142    * Whether to enforce the minimum normalized viewport size and limit
143    * the normalized viewport coordinates to [0.0 -> 1.0]. This keeps
144    * widgets from being moved offscreen or being scaled down past their
145    * minimum viewport size.
146    *
147    * Off by Default.
148    *
149    * Note: ProportionalResize must be off for this function to take effect.
150    */
151   vtkSetMacro(EnforceNormalizedViewportBounds, vtkTypeBool);
152   vtkGetMacro(EnforceNormalizedViewportBounds, vtkTypeBool);
153   vtkBooleanMacro(EnforceNormalizedViewportBounds, vtkTypeBool);
154   //@}
155 
156   //@{
157   /**
158    * Indicate whether resizing operations should keep the x-y directions
159    * proportional to one another. Also, if ProportionalResize is on, then
160    * the rectangle (Position,Position2) is a bounding rectangle, and the
161    * representation will be placed in the rectangle in such a way as to
162    * preserve the aspect ratio of the representation.
163    *
164    * Off by Default.
165    */
166   vtkSetMacro(ProportionalResize, vtkTypeBool);
167   vtkGetMacro(ProportionalResize, vtkTypeBool);
168   vtkBooleanMacro(ProportionalResize, vtkTypeBool);
169   ///@}
170 
171   ///@{
172   /**
173    * Specify a minimum and/or maximum size [0.0 -> 1.0] that this representation
174    * can take. These methods require two values: size values in the x and y
175    * directions, respectively.
176    *
177    * Default is { 0.0, 0.0 }.
178    */
179   vtkSetVector2Macro(MinimumNormalizedViewportSize, double);
180   vtkGetVector2Macro(MinimumNormalizedViewportSize, double);
181   //@}
182 
183   //@{
184   /**
185    * Specify a minimum and/or maximum size (in pixels) that this representation
186    * can take. These methods require two values: size values in the x and y
187    * directions, respectively.
188    *
189    * Default is { 1, 1 }.
190    */
191   vtkSetVector2Macro(MinimumSize, int);
192   vtkGetVector2Macro(MinimumSize, int);
193   vtkSetVector2Macro(MaximumSize, int);
194   vtkGetVector2Macro(MaximumSize, int);
195   ///@}
196 
197   ///@{
198   /**
199    * The tolerance representing the distance to the widget (in pixels)
200    * in which the cursor is considered to be on the widget, or on a
201    * widget feature (e.g., a corner point or edge).
202    *
203    * Default is 3.
204    */
205   vtkSetClampMacro(Tolerance, int, 1, 10);
206   vtkGetMacro(Tolerance, int);
207   ///@}
208 
209   ///@{
210   /**
211    * After a selection event within the region interior to the border; the
212    * normalized selection coordinates may be obtained.
213    */
214   vtkGetVectorMacro(SelectionPoint, double, 2);
215   ///@}
216 
217   ///@{
218   /**
219    * This is a modifier of the interaction state. When set, widget interaction
220    * allows the border (and stuff inside of it) to be translated with mouse
221    * motion.
222    */
223   vtkSetMacro(Moving, vtkTypeBool);
224   vtkGetMacro(Moving, vtkTypeBool);
225   vtkBooleanMacro(Moving, vtkTypeBool);
226   ///@}
227 
228   /**
229    * Define the various states that the representation can be in.
230    */
231   enum _InteractionState
232   {
233     Outside = 0,
234     Inside,
235     AdjustingP0,
236     AdjustingP1,
237     AdjustingP2,
238     AdjustingP3,
239     AdjustingE0,
240     AdjustingE1,
241     AdjustingE2,
242     AdjustingE3
243   };
244   vtkSetClampMacro(InteractionState, int, 0, AdjustingE3);
245 
246   /**
247    * Return the MTime of this object. It takes into account MTimes
248    * of position coordinates and border's property.
249    */
250   vtkMTimeType GetMTime() override;
251 
252   ///@{
253   /**
254    * Subclasses should implement these methods. See the superclasses'
255    * documentation for more information.
256    */
257   void BuildRepresentation() override;
258   void StartWidgetInteraction(double eventPos[2]) override;
259   void WidgetInteraction(double eventPos[2]) override;
GetSize(double size[2])260   virtual void GetSize(double size[2])
261   {
262     size[0] = 1.0;
263     size[1] = 1.0;
264   }
265   int ComputeInteractionState(int X, int Y, int modify = 0) override;
266   ///@}
267 
268   ///@{
269   /**
270    * These methods are necessary to make this representation behave as
271    * a vtkProp.
272    */
273   void GetActors2D(vtkPropCollection*) override;
274   void ReleaseGraphicsResources(vtkWindow*) override;
275   int RenderOverlay(vtkViewport*) override;
276   int RenderOpaqueGeometry(vtkViewport*) override;
277   int RenderTranslucentPolygonalGeometry(vtkViewport*) override;
278   vtkTypeBool HasTranslucentPolygonalGeometry() override;
279   ///@}
280 
281   void SetBWActorDisplayOverlay(bool);
282 
283   ///@{
284   /**
285    * Set/Get the RGB color of the border.
286    * Default is white (1.0, 1.0, 1.0).
287    */
288   vtkSetVector3Macro(BorderColor, double);
289   vtkGetVector3Macro(BorderColor, double);
290   ///@}
291 
292   ///@{
293   /**
294    * Set/Get the thickness of the border in screen units.
295    * Default is 1.0.
296    */
297   vtkSetClampMacro(BorderThickness, float, 0, VTK_FLOAT_MAX);
298   vtkGetMacro(BorderThickness, float);
299   ///@}
300 
301   ///@{
302   /**
303    * Set/Get the ratio between no radius and maximum radius.
304    * In order to compute round corners, we create 2 points
305    * in each side of the corner. The maximum radius is then
306    * the minimum length of the two sides of each corners.
307    * This maximum radius is scaled by the CornerRadiusStrength.
308    * Default is 0.0 (no radius).
309    */
310   vtkSetClampMacro(CornerRadiusStrength, double, 0.0, 1.0);
311   vtkGetMacro(CornerRadiusStrength, double);
312   ///@}
313 
314   ///@{
315   /**
316    * Set/Get the number of points that define each round corners.
317    * A high value increase the resolution of the corners.
318    * Default is 20.
319    */
320   vtkSetClampMacro(CornerResolution, int, 0, 1000);
321   vtkGetMacro(CornerResolution, int);
322   ///@}
323 
324   ///@{
325   /**
326    * Set/Get the RGB color of the background polygon.
327    * Default is white (1.0, 1.0, 1.0).
328    */
329   vtkSetVector3Macro(PolygonColor, double);
330   vtkGetVector3Macro(PolygonColor, double);
331   ///@}
332 
333   ///@{
334   /**
335    * Set/Get the opacity of the background color.
336    * Default is 0.0.
337    */
338   vtkSetClampMacro(PolygonOpacity, double, 0.0, 1.0);
339   vtkGetMacro(PolygonOpacity, double);
340   ///@}
341 
342   ///@{
343   /**
344    * Convenience method to set the background color and the opacity at once
345    */
346   void SetPolygonRGBA(double rgba[4]);
347   void SetPolygonRGBA(double r, double g, double b, double a);
348 
349   /**
350    * Convenience method to get the background color and the opacity at once
351    */
352   void GetPolygonRGBA(double rgba[4]);
353   void GetPolygonRGBA(double& r, double& g, double& b, double& a);
354   ///@}
355 
356 protected:
357   vtkBorderRepresentation();
358   ~vtkBorderRepresentation() override;
359 
360   // Ivars
361   int ShowVerticalBorder = BORDER_ON;
362   int ShowHorizontalBorder = BORDER_ON;
363   vtkNew<vtkProperty2D> BorderProperty;
364   vtkNew<vtkProperty2D> PolygonProperty;
365   vtkTypeBool EnforceNormalizedViewportBounds = 0;
366   vtkTypeBool ProportionalResize = 0;
367   int Tolerance = 3;
368   vtkTypeBool Moving = 0;
369   double SelectionPoint[2] = { 0.0, 0.0 };
370 
371   // Layout (position of lower left and upper right corners of border)
372   vtkNew<vtkCoordinate> PositionCoordinate;
373   vtkNew<vtkCoordinate> Position2Coordinate;
374 
375   // Sometimes subclasses must negotiate with their superclasses
376   // to achieve the correct layout.
377   int Negotiated;
378   virtual void NegotiateLayout();
379 
380   // Update the border visibility based on InteractionState.
381   // See Also: SetShowHorizontalBorder(), SetShowHorizontalBorder(),
382   // ComputeInteractionState()
383   virtual void UpdateShowBorder();
384 
385   // Keep track of start position when moving border
386   double StartPosition[2];
387 
388   // Border representation. Subclasses may use the BWTransform class
389   // to transform their geometry into the region surrounded by the border.
390   vtkNew<vtkPoints> BWPoints;
391   vtkNew<vtkPolyData> BWPolyData;
392   vtkNew<vtkPolyData> PolyDataEdges;
393   vtkNew<vtkPolyData> PolyDataPolygon;
394   vtkNew<vtkTransform> BWTransform;
395   vtkNew<vtkTransformPolyDataFilter> BWTransformFilter;
396   vtkNew<vtkPolyDataMapper2D> BWMapperEdges;
397   vtkNew<vtkPolyDataMapper2D> BWMapperPolygon;
398   vtkNew<vtkActor2D> BWActorEdges;
399   vtkNew<vtkActor2D> BWActorPolygon;
400 
401   // Constraints on size
402   double MinimumNormalizedViewportSize[2] = { 0.0, 0.0 };
403   int MinimumSize[2] = { 1, 1 };
404   int MaximumSize[2] = { VTK_INT_MAX, VTK_INT_MAX };
405 
406   // Properties of the border
407   double BorderColor[3] = { 1.0, 1.0, 1.0 };
408   float BorderThickness = 1.0;
409   double CornerRadiusStrength = 0.0;
410   int CornerResolution = 20;
411 
412   // Properties of the inner polygon (ie. the background)
413   double PolygonColor[3] = { 1.0, 1.0, 1.0 };
414   double PolygonOpacity = 0.0;
415 
416   /**
417    * Create all 4 round corners with the specified radius and resolution.
418    */
419   void ComputeRoundCorners();
420 
421   /**
422    * Create a quarter circle centered in point[idCenterX].x, point[idCenterY].y),
423    * of radius 'radius' with a starting angle 'startAngle' ending in
424    * 'startAngle + PI/2' with CornerResolution number of points.
425    * Computed points are stored in the vtkPoints 'points' and
426    * inserted in the vtkCellArray 'polys'
427    */
428   void ComputeOneRoundCorner(vtkCellArray* polys, vtkPoints* points, const double radius,
429     vtkIdType xPt, vtkIdType yPt, const double startAngle);
430 
431 private:
432   vtkBorderRepresentation(const vtkBorderRepresentation&) = delete;
433   void operator=(const vtkBorderRepresentation&) = delete;
434 };
435 
436 #endif
437