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