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