1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkImageTracerWidget.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 vtkImageTracerWidget 17 * @brief 3D widget for tracing on planar props. 18 * 19 * vtkImageTracerWidget is different from other widgets in three distinct ways: 20 * 1) any sub-class of vtkProp can be input rather than just vtkProp3D, so that 21 * vtkImageActor can be set as the prop and then traced over, 2) the widget fires 22 * pick events at the input prop to decide where to move its handles, 3) the 23 * widget has 2D glyphs for handles instead of 3D spheres as is done in other 24 * sub-classes of vtk3DWidget. This widget is primarily designed for manually 25 * tracing over image data. 26 * The button actions and key modifiers are as follows for controlling the 27 * widget: 28 * 1) left button click over the image, hold and drag draws a free hand line. 29 * 2) left button click and release erases the widget line, 30 * if it exists, and repositions the first handle. 31 * 3) middle button click starts a snap drawn line. The line is terminated by 32 * clicking the middle button while depressing the ctrl key. 33 * 4) when tracing a continuous or snap drawn line, if the last cursor position 34 * is within a specified tolerance to the first handle, the widget line will form 35 * a closed loop. 36 * 5) right button clicking and holding on any handle that is part of a snap 37 * drawn line allows handle dragging: existing line segments are updated 38 * accordingly. If the path is open and AutoClose is set to On, the path can 39 * be closed by repositioning the first and last points over one another. 40 * 6) ctrl key + right button down on any handle will erase it: existing 41 * snap drawn line segments are updated accordingly. If the line was formed by 42 * continuous tracing, the line is deleted leaving one handle. 43 * 7) shift key + right button down on any snap drawn line segment will insert 44 * a handle at the cursor position. The line segment is split accordingly. 45 * 46 * @warning 47 * the input vtkDataSet should be vtkImageData. 48 * 49 * @sa 50 * vtk3DWidget vtkBoxWidget vtkLineWidget vtkPointWidget vtkSphereWidget 51 * vtkImagePlaneWidget vtkImplicitPlaneWidget vtkPlaneWidget 52 */ 53 54 #ifndef vtkImageTracerWidget_h 55 #define vtkImageTracerWidget_h 56 57 #include "vtk3DWidget.h" 58 #include "vtkInteractionWidgetsModule.h" // For export macro 59 60 class vtkAbstractPropPicker; 61 class vtkActor; 62 class vtkCellArray; 63 class vtkCellPicker; 64 class vtkFloatArray; 65 class vtkGlyphSource2D; 66 class vtkPoints; 67 class vtkPolyData; 68 class vtkProp; 69 class vtkProperty; 70 class vtkPropPicker; 71 class vtkTransform; 72 class vtkTransformPolyDataFilter; 73 74 #define VTK_ITW_PROJECTION_YZ 0 75 #define VTK_ITW_PROJECTION_XZ 1 76 #define VTK_ITW_PROJECTION_XY 2 77 #define VTK_ITW_SNAP_CELLS 0 78 #define VTK_ITW_SNAP_POINTS 1 79 80 class VTKINTERACTIONWIDGETS_EXPORT vtkImageTracerWidget : public vtk3DWidget 81 { 82 public: 83 /** 84 * Instantiate the object. 85 */ 86 static vtkImageTracerWidget* New(); 87 88 vtkTypeMacro(vtkImageTracerWidget, vtk3DWidget); 89 void PrintSelf(ostream& os, vtkIndent indent) override; 90 91 ///@{ 92 /** 93 * Methods that satisfy the superclass' API. 94 */ 95 void SetEnabled(int) override; 96 void PlaceWidget(double bounds[6]) override; PlaceWidget()97 void PlaceWidget() override { this->Superclass::PlaceWidget(); } PlaceWidget(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax)98 void PlaceWidget( 99 double xmin, double xmax, double ymin, double ymax, double zmin, double zmax) override 100 { 101 this->Superclass::PlaceWidget(xmin, xmax, ymin, ymax, zmin, zmax); 102 } 103 ///@} 104 105 ///@{ 106 /** 107 * Set/Get the handle properties (the 2D glyphs are the handles). The 108 * properties of the handles when selected and normal can be manipulated. 109 */ 110 virtual void SetHandleProperty(vtkProperty*); 111 vtkGetObjectMacro(HandleProperty, vtkProperty); 112 virtual void SetSelectedHandleProperty(vtkProperty*); 113 vtkGetObjectMacro(SelectedHandleProperty, vtkProperty); 114 ///@} 115 116 ///@{ 117 /** 118 * Set/Get the line properties. The properties of the line when selected 119 * and unselected can be manipulated. 120 */ 121 virtual void SetLineProperty(vtkProperty*); 122 vtkGetObjectMacro(LineProperty, vtkProperty); 123 virtual void SetSelectedLineProperty(vtkProperty*); 124 vtkGetObjectMacro(SelectedLineProperty, vtkProperty); 125 ///@} 126 127 /** 128 * Set the prop, usually a vtkImageActor, to trace over. 129 */ 130 void SetViewProp(vtkProp* prop); 131 132 ///@{ 133 /** 134 * Force handles to be on a specific ortho plane. Default is Off. 135 */ 136 vtkSetMacro(ProjectToPlane, vtkTypeBool); 137 vtkGetMacro(ProjectToPlane, vtkTypeBool); 138 vtkBooleanMacro(ProjectToPlane, vtkTypeBool); 139 ///@} 140 141 ///@{ 142 /** 143 * Set the projection normal. The normal in SetProjectionNormal is 0,1,2 144 * for YZ,XZ,XY planes respectively. Since the handles are 2D glyphs, it is 145 * necessary to specify a plane on which to generate them, even though 146 * ProjectToPlane may be turned off. 147 */ 148 vtkSetClampMacro(ProjectionNormal, int, VTK_ITW_PROJECTION_YZ, VTK_ITW_PROJECTION_XY); 149 vtkGetMacro(ProjectionNormal, int); SetProjectionNormalToXAxes()150 void SetProjectionNormalToXAxes() { this->SetProjectionNormal(0); } SetProjectionNormalToYAxes()151 void SetProjectionNormalToYAxes() { this->SetProjectionNormal(1); } SetProjectionNormalToZAxes()152 void SetProjectionNormalToZAxes() { this->SetProjectionNormal(2); } 153 ///@} 154 155 ///@{ 156 /** 157 * Set the position of the widgets' handles in terms of a plane's position. 158 * e.g., if ProjectionNormal is 0, all of the x-coordinate values of the 159 * handles are set to ProjectionPosition. No attempt is made to ensure that 160 * the position is within the bounds of either the underlying image data or 161 * the prop on which tracing is performed. 162 */ 163 void SetProjectionPosition(double position); 164 vtkGetMacro(ProjectionPosition, double); 165 ///@} 166 167 ///@{ 168 /** 169 * Force snapping to image data while tracing. Default is Off. 170 */ 171 void SetSnapToImage(vtkTypeBool snap); 172 vtkGetMacro(SnapToImage, vtkTypeBool); 173 vtkBooleanMacro(SnapToImage, vtkTypeBool); 174 ///@} 175 176 ///@{ 177 /** 178 * In concert with a CaptureRadius value, automatically 179 * form a closed path by connecting first to last path points. 180 * Default is Off. 181 */ 182 vtkSetMacro(AutoClose, vtkTypeBool); 183 vtkGetMacro(AutoClose, vtkTypeBool); 184 vtkBooleanMacro(AutoClose, vtkTypeBool); 185 ///@} 186 187 ///@{ 188 /** 189 * Set/Get the capture radius for automatic path closing. For image 190 * data, capture radius should be half the distance between voxel/pixel 191 * centers. 192 * Default is 1.0 193 */ 194 vtkSetMacro(CaptureRadius, double); 195 vtkGetMacro(CaptureRadius, double); 196 ///@} 197 198 /** 199 * Grab the points and lines that define the traced path. These point values 200 * are guaranteed to be up-to-date when either the InteractionEvent or 201 * EndInteraction events are invoked. The user provides the vtkPolyData and 202 * the points and cells representing the line are added to it. 203 */ 204 void GetPath(vtkPolyData* pd); 205 206 /** 207 * Get the handles' geometric representation via vtkGlyphSource2D. 208 */ GetGlyphSource()209 vtkGlyphSource2D* GetGlyphSource() { return this->HandleGenerator; } 210 211 ///@{ 212 /** 213 * Set/Get the type of snapping to image data: center of a pixel/voxel or 214 * nearest point defining a pixel/voxel. 215 */ 216 vtkSetClampMacro(ImageSnapType, int, VTK_ITW_SNAP_CELLS, VTK_ITW_SNAP_POINTS); 217 vtkGetMacro(ImageSnapType, int); 218 ///@} 219 220 ///@{ 221 /** 222 * Set/Get the handle position in terms of a zero-based array of handles. 223 */ 224 void SetHandlePosition(int handle, double xyz[3]); 225 void SetHandlePosition(int handle, double x, double y, double z); 226 void GetHandlePosition(int handle, double xyz[3]); 227 double* GetHandlePosition(int handle) VTK_SIZEHINT(3); 228 ///@} 229 230 ///@{ 231 /** 232 * Get the number of handles. 233 */ 234 vtkGetMacro(NumberOfHandles, int); 235 ///@} 236 237 ///@{ 238 /** 239 * Enable/disable mouse interaction when the widget is visible. 240 */ 241 void SetInteraction(vtkTypeBool interact); 242 vtkGetMacro(Interaction, vtkTypeBool); 243 vtkBooleanMacro(Interaction, vtkTypeBool); 244 ///@} 245 246 /** 247 * Initialize the widget with a set of points and generate 248 * lines between them. If AutoClose is on it will handle the 249 * case wherein the first and last points are congruent. 250 */ 251 void InitializeHandles(vtkPoints*); 252 253 /** 254 * Is the path closed or open? 255 */ 256 int IsClosed(); 257 258 ///@{ 259 /** 260 * Enable/Disable mouse button events 261 */ 262 vtkSetMacro(HandleLeftMouseButton, vtkTypeBool); 263 vtkGetMacro(HandleLeftMouseButton, vtkTypeBool); 264 vtkBooleanMacro(HandleLeftMouseButton, vtkTypeBool); 265 vtkSetMacro(HandleMiddleMouseButton, vtkTypeBool); 266 vtkGetMacro(HandleMiddleMouseButton, vtkTypeBool); 267 vtkBooleanMacro(HandleMiddleMouseButton, vtkTypeBool); 268 vtkSetMacro(HandleRightMouseButton, vtkTypeBool); 269 vtkGetMacro(HandleRightMouseButton, vtkTypeBool); 270 vtkBooleanMacro(HandleRightMouseButton, vtkTypeBool); 271 ///@} 272 273 protected: 274 vtkImageTracerWidget(); 275 ~vtkImageTracerWidget() override; 276 277 // Manage the state of the widget 278 int State; 279 enum WidgetState 280 { 281 Start = 0, 282 Tracing, 283 Snapping, 284 Erasing, 285 Inserting, 286 Moving, 287 Translating, 288 Outside 289 }; 290 291 // handles the events 292 static void ProcessEvents( 293 vtkObject* object, unsigned long event, void* clientdata, void* calldata); 294 295 // ProcessEvents() dispatches to these methods. 296 void OnLeftButtonDown(); 297 void OnLeftButtonUp(); 298 void OnMiddleButtonDown(); 299 void OnMiddleButtonUp(); 300 void OnRightButtonDown(); 301 void OnRightButtonUp(); 302 void OnMouseMove(); 303 304 void AddObservers(); 305 306 // Controlling ivars 307 vtkTypeBool Interaction; 308 int ProjectionNormal; 309 double ProjectionPosition; 310 vtkTypeBool ProjectToPlane; 311 int ImageSnapType; 312 vtkTypeBool SnapToImage; 313 double CaptureRadius; // tolerance for auto path close 314 vtkTypeBool AutoClose; 315 int IsSnapping; 316 int LastX; 317 int LastY; 318 319 void Trace(int, int); 320 void Snap(double*); 321 void MovePoint(const double*, const double*); 322 void Translate(const double*, const double*); 323 void ClosePath(); 324 325 // 2D glyphs representing hot spots (e.g., handles) 326 vtkActor** Handle; 327 vtkPolyData** HandleGeometry; 328 vtkGlyphSource2D* HandleGenerator; 329 330 // Transforms required as 2D glyphs are generated in the x-y plane 331 vtkTransformPolyDataFilter* TransformFilter; 332 vtkTransform* Transform; 333 vtkFloatArray* TemporaryHandlePoints; 334 335 void AppendHandles(double*); 336 void ResetHandles(); 337 void AllocateHandles(const int&); 338 void AdjustHandlePosition(const int&, double*); 339 int HighlightHandle(vtkProp*); // returns handle index or -1 on fail 340 void EraseHandle(const int&); 341 void SizeHandles() override; 342 void InsertHandleOnLine(double*); 343 344 int NumberOfHandles; 345 vtkActor* CurrentHandle; 346 int CurrentHandleIndex; 347 348 vtkProp* ViewProp; // the prop we want to pick on 349 vtkPropPicker* PropPicker; // the prop's picker 350 351 // Representation of the line 352 vtkPoints* LinePoints; 353 vtkCellArray* LineCells; 354 vtkActor* LineActor; 355 vtkPolyData* LineData; 356 vtkIdType CurrentPoints[2]; 357 358 void HighlightLine(const int&); 359 void BuildLinesFromHandles(); 360 void ResetLine(double*); 361 void AppendLine(double*); 362 int PickCount; 363 364 // Do the picking of the handles and the lines 365 vtkCellPicker* HandlePicker; 366 vtkCellPicker* LinePicker; 367 vtkAbstractPropPicker* CurrentPicker; 368 369 // Register internal Pickers within PickingManager 370 void RegisterPickers() override; 371 372 // Properties used to control the appearance of selected objects and 373 // the manipulator in general. 374 vtkProperty* HandleProperty; 375 vtkProperty* SelectedHandleProperty; 376 vtkProperty* LineProperty; 377 vtkProperty* SelectedLineProperty; 378 void CreateDefaultProperties(); 379 380 // Enable/Disable mouse button events 381 vtkTypeBool HandleLeftMouseButton; 382 vtkTypeBool HandleMiddleMouseButton; 383 vtkTypeBool HandleRightMouseButton; 384 385 private: 386 vtkImageTracerWidget(const vtkImageTracerWidget&) = delete; 387 void operator=(const vtkImageTracerWidget&) = delete; 388 }; 389 390 #endif 391