[vtk-developers] ARB - feature addition

Dean Inglis dean.inglis at camris.ca
Fri Nov 21 11:14:19 EST 2003


Hi,

this is not a major architectural dilemma.
I've been tinkering for some time now on a
widget for tracing on 2D images, got it
up and running, and am happy to add it to
the VTK/Hybrid widget collection.  Enclosed
is the .h file so you can have peek at the
methods.  What is potentially more interesting
is that instead of 3D spherical handles,
this widget uses vtkGlyphSource2D to generate
the handle geometry, giving the users flexibility
in customizing the widget's appearance.  I have
also created a variant of vtkSplineWidget that
uses the same handle generation approach...So,
one could use these two widgets in concert:
a) define a traced line either continuously or by
discrete snap lines by point clicking
b) toggle between the two widgets and set the tracer
data to the spline so that one could have a smoothed
spline fit to the trace.

There are a few other widgets I have either in development
or already to go geared to the image processing field
based on some of the same common elements (2D handles etc.)

vtkImageROIWidget - a rotatable 2D rectangular region of interest
vtkImageWindowLevelWidget - 2D rectangle with histogram and
linear or spline transfer function generator tied to a vtkLookupTable
vtkVolumeTransferFunctionWidget - similar to above but more like
what you would see at http: //www . cs. utah . edu/~jmk/simian/
vtkImageSplineWidget - geared to 2D ortho image planes
vtkImageTracerWidget - can also be used for placing and moving landmarks
on images

So perhaps there should be a superclass somewhere between
vtk3DWidget and the above.

your thoughts anyone?  Shall I commit vtkImageTracerWidget?

Dean


// .NAME vtkImageTracerWidget - 3D widget for tracing a free-hand/snap line.
// .SECTION Description
// vtkImageTracerWidget works by firing picks at the input prop.  This
// widget is particulary useful for manually tracing on image data.  When
// the widget is tied to a plane source, the intersection between the
widget's
// picked spherical handle and the plane generates a visible ring for
enhanced
// viewing.

// .SECTION Thanks
// Thanks to Dean Inglis for developing and contributing this class.

// .SECTION Caveats
// Note that handles and line can be picked even when they are "behind"
other
// actors.  This is an intended feature and not a bug.

// .SECTION See Also
// vtk3DWidget vtkBoxWidget vtkLineWidget vtkPointWidget vtkSphereWidget
// vtkImagePlaneWidget vtkImplicitPlaneWidget vtkPlaneWidget


#ifndef __vtkPropTracerWidget_h
#define __vtkPropTracerWidget_h

#include "vtkLocalHybridWin32Header.h" // Include configuration header.
#include "vtk3DWidget.h"

class vtkAbstractPropPicker;
class vtkActor;
class vtkCellArray;
class vtkCellPicker;
class vtkFloatArray;
class vtkGlyphSource2D;
class vtkPoints;
class vtkPolyData;
class vtkPolyDataMapper;
class vtkProp;
class vtkProperty;
class vtkPropPicker;
class vtkTransform;
class vtkTransformPolyDataFilter;

#define VTK_ITW_PROJECTION_YZ 0
#define VTK_ITW_PROJECTION_XZ 1
#define VTK_ITW_PROJECTION_XY 2
#define VTK_ITW_SNAP_CELLS    0
#define VTK_ITW_SNAP_POINTS   1

class VTK_LOCAL_HYBRID_EXPORT vtkImageTracerWidget : public vtk3DWidget
{
public:
  // Description:
  // Instantiate the object.
  static vtkImageTracerWidget *New();

  vtkTypeRevisionMacro(vtkImageTracerWidget,vtk3DWidget);
  void PrintSelf(ostream& os, vtkIndent indent);

  // Description:
  // Methods that satisfy the superclass' API.
  virtual void SetEnabled(int);
  virtual void PlaceWidget(float bounds[6]);
  void PlaceWidget()
    {this->Superclass::PlaceWidget();}
  void PlaceWidget(float xmin, float xmax, float ymin, float ymax,
                   float zmin, float zmax)
    {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);}

  // Description:
  // Set/Get the handle properties (the little balls are the handles). The
  // properties of the handles when selected and normal can be manipulated.
  virtual void SetHandleProperty(vtkProperty*);
  vtkGetObjectMacro(HandleProperty, vtkProperty);
  virtual void SetSelectedHandleProperty(vtkProperty*);
  vtkGetObjectMacro(SelectedHandleProperty, vtkProperty);
  virtual void SetStaticHandleProperty(vtkProperty*);
  vtkGetObjectMacro(StaticHandleProperty, vtkProperty);

  // Description:
  // Igore: experimental.
  void SetTopologyParameters(float& factor, float& units);

  // Description:
  // Set/Get the line properties. The properties of the line when selected
  // and unselected can be manipulated.
  virtual void SetLineProperty(vtkProperty*);
  vtkGetObjectMacro(LineProperty, vtkProperty);
  virtual void SetSelectedLineProperty(vtkProperty*);
  vtkGetObjectMacro(SelectedLineProperty, vtkProperty);

  // Description:
  // Set the prop, usually a vtkImageActor, to trace over.
  void SetProp(vtkProp* prop);

  // Description:
  // Force handles to be on a specific ortho plane.
  vtkSetMacro(ProjectToPlane,int);
  vtkGetMacro(ProjectToPlane,int);
  vtkBooleanMacro(ProjectToPlane,int);

  // Description:
  // Set the projection normal.  The normal in SetProjectionNormal is 0,1,2
  // for YZ,XZ,XY planes respectively.

vtkSetClampMacro(ProjectionNormal,int,VTK_ITW_PROJECTION_YZ,VTK_ITW_PROJECTI
ON_XY);
  vtkGetMacro(ProjectionNormal,int);
  void SetProjectionNormalToXAxes()
    { this->SetProjectionNormal(0); }
  void SetProjectionNormalToYAxes()
    { this->SetProjectionNormal(1); }
  void SetProjectionNormalToZAxes()
    { this->SetProjectionNormal(2); }

  // Description:
  // Set the position of the widgets' handles in terms of a plane's
position.
  // e.g., if ProjectionNormal is 0, all of the x-coordinate values of the
  // handles are set to position. Any value can be passed (and is ignored)
  // to update the handle points when Projection normal is set to 3 for
  // arbritrary plane orientations.
  vtkSetMacro(ProjectionPosition, float);
  vtkGetMacro(ProjectionPosition, float);

   // Description:
  // Force snapping to image data.
  void SetSnapToImage(int snap);
  vtkGetMacro(SnapToImage,int);
  vtkBooleanMacro(SnapToImage,int);

  // Description:
  // In concert with a CaptureRadius value, automatically
  // form a closed path by connecting first to last path points.
  vtkSetMacro(AutoClose,int);
  vtkGetMacro(AutoClose,int);
  vtkBooleanMacro(AutoClose,int);

  // Description:
  // Set/Get the initial ortation of the glyph when first generated.
  vtkSetMacro(GlyphAngle,float);
  vtkGetMacro(GlyphAngle,float);

  // Description:
  // Set/Get the capture radius for automatic path closing.  For image
  // data, capture radius should be half the distance between voxel/pixel
  // centers.
  vtkSetMacro(CaptureRadius,float);
  vtkGetMacro(CaptureRadius,float);

  // Description:
  // Grab the the points that define the traced path. These point values
  // are guaranteed to be up-to-date when either the InteractionEvent or
  // EndInteraction events are invoked. The user provides the vtkPolyData
and
  // the points and polyline are added to it.
  void GetPolyData(vtkPolyData *pd);

  // Description:
  // Get the handles' geometric representation via vtkGlyphSource2D.
  vtkGlyphSource2D* GetGlyphSource() { return
this->HandleGeometryGenerator; }

  vtkSetClampMacro(SnapType,int,VTK_ITW_SNAP_CELLS,VTK_ITW_SNAP_POINTS);
  vtkGetMacro(SnapType,int);

  // Set/Get the handle position.
  void SetHandlePosition(const int& handle, float xyz[3]);
  void SetHandlePosition(const int& handle, float x, float y, float z);
  void GetHandlePosition(const int& handle, float xyz[3]);
  float* GetHandlePosition(const int& handle);

  vtkGetMacro(NumberOfHandles,int);

  // Description:
  // Enable/disable mouse interaction so the widget remains on display.
  void SetInteraction(int interact);
  vtkGetMacro(Interaction,int);
  vtkBooleanMacro(Interaction,int);


protected:
  vtkImageTracerWidget();
  ~vtkImageTracerWidget();

//BTX - manage the state of the widget
  int State;
  enum WidgetState
  {
    Start=0,
    Tracing,
    Snapping,
    Erasing,
    Inserting,
    Moving,
    Outside
  };
//ETX

  //handles the events
  static void ProcessEvents(vtkObject* object,
                            unsigned long event,
                            void* clientdata,
                            void* calldata);

  // ProcessEvents() dispatches to these methods.
  void OnLeftButtonDown();
  void OnLeftButtonUp();
  void OnMiddleButtonDown();
  void OnMiddleButtonUp();
  void OnRightButtonDown();
  void OnRightButtonUp();
  void OnMouseMove();

  void AddObservers();
  int Interaction;

  // Controlling vars
  int   ProjectionNormal;
  float ProjectionPosition;
  int   ProjectToPlane;

  void  Trace(int X, int Y);
  int   SnapToImage;
  int   IsSnapping;
  int   SnapType;
  void  Snap(float*);
  int   MouseMoved;

  float CaptureRadius;
  int   AutoClose;
  void  ClosePath();

  // Glyphs representing hot spots (e.g., handles)
  vtkActor          **Handle;
  vtkPolyDataMapper **HandleMapper;
  vtkPolyData       **HandleGeometry;
  vtkGlyphSource2D   *HandleGeometryGenerator;
  float GlyphAngle;  // pre-rotation of a glyph eg., a cross can be
pre-rotated 45 degrees

  // Transforms required as 2D glyphs are generated in x-y plane
  vtkTransformPolyDataFilter *TransformFilter;
  vtkTransform               *Transform;
  vtkFloatArray              *TemporaryHandlePoints;

  void AppendHandles(float*);
  void InitializeHandles();
  void SetNumberOfHandles(const int& nhandles);
  void AdjustHandlePosition(const int&, float*);
  int  HighlightHandle(vtkProp *prop); //returns handle index or -1 on fail
  void EraseHandle(const int&);
  virtual void SizeHandles();
  void InsertHandleOnLine(float*);

  int NumberOfHandles;
  vtkActor *CurrentHandle;
  int CurrentHandleIndex;

  vtkProp* Prop;      //the prop we want to pick on
  vtkPropPicker* PropPicker;//the prop's picker

  // Representation of the trace line
  vtkPoints         *LinePoints;
  vtkCellArray      *LineCells;
  vtkActor          *LineActor;
  vtkPolyDataMapper *LineMapper;
  vtkPolyData       *LineData;
  vtkIdType          CurrentPoints[2];

  void HighlightLine(const int&);
  void BuildLinesFromHandles();
  void InitializeLine(float*);
  void AppendLine(float*);
  int  PickCount;

  // Do the picking of the handles and the lines
  vtkCellPicker *HandlePicker;
  vtkCellPicker *LinePicker;
  vtkAbstractPropPicker* CurrentPicker;

  // Properties used to control the appearance of selected objects and
  // the manipulator in general.
  vtkProperty *HandleProperty;
  vtkProperty *StaticHandleProperty;
  vtkProperty *SelectedHandleProperty;
  vtkProperty *LineProperty;
  vtkProperty *SelectedLineProperty;
  void CreateDefaultProperties();

private:
  vtkImageTracerWidget(const vtkImageTracerWidget&);  //Not implemented
  void operator=(const vtkImageTracerWidget&);  //Not implemented
};

#endif


Dean

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dean Inglis, PhD
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~ Center for Appendicular ~~~~~
Magnetic Resonance Imaging Studies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
610 - 25 Charlton Ave. E.
Hamilton, Ontario, L8N 1Y2
tel: (905) 527-0028
fax: (905) 521-1297
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Adjunct Professor
Department of Civil Engineering
McMaster University
Hamilton, Ontario
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~







More information about the vtk-developers mailing list