You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

358 lines
13 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkBoxWidget.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkBoxWidget
* @brief orthogonal hexahedron 3D widget
*
* This 3D widget defines a region of interest that is represented by an
* arbitrarily oriented hexahedron with interior face angles of 90 degrees
* (orthogonal faces). The object creates 7 handles that can be moused on and
* manipulated. The first six correspond to the six faces, the seventh is in
* the center of the hexahedron. In addition, a bounding box outline is shown,
* the "faces" of which can be selected for object rotation or scaling. A
* nice feature of the object is that the vtkBoxWidget, like any 3D widget,
* will work with the current interactor style. That is, if vtkBoxWidget does
* not handle an event, then all other registered observers (including the
* interactor style) have an opportunity to process the event. Otherwise, the
* vtkBoxWidget will terminate the processing of the event that it handles.
*
* To use this object, just invoke SetInteractor() with the argument of the
* method a vtkRenderWindowInteractor. You may also wish to invoke
* "PlaceWidget()" to initially position the widget. The interactor will act
* normally until the "i" key (for "interactor") is pressed, at which point the
* vtkBoxWidget will appear. (See superclass documentation for information
* about changing this behavior.) By grabbing the six face handles (use the
* left mouse button), faces can be moved. By grabbing the center handle
* (with the left mouse button), the entire hexahedron can be
* translated. (Translation can also be employed by using the
* "shift-left-mouse-button" combination inside of the widget.) Scaling is
* achieved by using the right mouse button "up" the render window (makes the
* widget bigger) or "down" the render window (makes the widget smaller). To
* rotate vtkBoxWidget, pick a face (but not a face handle) and move the left
* mouse. (Note: the mouse button must be held down during manipulation.)
* Events that occur outside of the widget (i.e., no part of the widget is
* picked) are propagated to any other registered obsevers (such as the
* interaction style). Turn off the widget by pressing the "i" key again.
* (See the superclass documentation on key press activiation.)
*
* The vtkBoxWidget is very flexible. It can be used to select, cut, clip, or
* perform any other operation that depends on an implicit function (use the
* GetPlanes() method); or it can be used to transform objects using a linear
* transformation (use the GetTransform() method). Typical usage of the
* widget is to make use of the StartInteractionEvent, InteractionEvent, and
* EndInteractionEvent events. The InteractionEvent is called on mouse
* motion; the other two events are called on button down and button up
* (either left or right button).
*
* Some additional features of this class include the ability to control the
* rendered properties of the widget. You can set the properties of the
* selected and unselected representations of the parts of the widget. For
* example, you can set the property for the handles, faces, and outline in
* their normal and selected states.
*
* The box widget can be oriented by specifying a transformation matrix.
* This transformation is applied to the initial bounding box as defined by
* the PlaceWidget() method. DO NOT ASSUME that the transformation is applied
* to a unit box centered at the origin; this is wrong!
*
* @sa
* vtk3DWidget vtkPointWidget vtkLineWidget vtkPlaneWidget
* vtkImplicitPlaneWidget vtkImagePlaneWidget
*/
#ifndef vtkBoxWidget_h
#define vtkBoxWidget_h
#include "vtk3DWidget.h"
#include "vtkInteractionWidgetsModule.h" // For export macro
class vtkActor;
class vtkCellPicker;
class vtkPlanes;
class vtkPoints;
class vtkPolyData;
class vtkPolyDataMapper;
class vtkProp;
class vtkProperty;
class vtkSphereSource;
class vtkTransform;
class VTKINTERACTIONWIDGETS_EXPORT vtkBoxWidget : public vtk3DWidget
{
public:
/**
* Instantiate the object.
*/
static vtkBoxWidget* New();
vtkTypeMacro(vtkBoxWidget, vtk3DWidget);
void PrintSelf(ostream& os, vtkIndent indent) override;
//@{
/**
* Methods that satisfy the superclass' API.
*/
void SetEnabled(int) override;
void PlaceWidget(double bounds[6]) override;
void PlaceWidget() override { this->Superclass::PlaceWidget(); }
void PlaceWidget(
double xmin, double xmax, double ymin, double ymax, double zmin, double zmax) override
{
this->Superclass::PlaceWidget(xmin, xmax, ymin, ymax, zmin, zmax);
}
//@}
/**
* Get the planes describing the implicit function defined by the box
* widget. The user must provide the instance of the class vtkPlanes. Note
* that vtkPlanes is a subclass of vtkImplicitFunction, meaning that it can
* be used by a variety of filters to perform clipping, cutting, and
* selection of data. (The direction of the normals of the planes can be
* reversed enabling the InsideOut flag.)
*/
void GetPlanes(vtkPlanes* planes);
//@{
/**
* Set/Get the InsideOut flag. When off, the normals point out of the
* box. When on, the normals point into the hexahedron. InsideOut
* is off by default.
*/
vtkSetMacro(InsideOut, vtkTypeBool);
vtkGetMacro(InsideOut, vtkTypeBool);
vtkBooleanMacro(InsideOut, vtkTypeBool);
//@}
/**
* Retrieve a linear transform characterizing the transformation of the
* box. Note that the transformation is relative to where PlaceWidget
* was initially called. This method modifies the transform provided. The
* transform can be used to control the position of vtkProp3D's, as well as
* other transformation operations (e.g., vtkTransformPolyData).
*/
virtual void GetTransform(vtkTransform* t);
/**
* Set the position, scale and orientation of the box widget using the
* transform specified. Note that the transformation is relative to
* where PlaceWidget was initially called (i.e., the original bounding
* box).
*/
virtual void SetTransform(vtkTransform* t);
/**
* Grab the polydata (including points) that define the box widget. The
* polydata consists of 6 quadrilateral faces and 15 points. The first
* eight points define the eight corner vertices; the next six define the
* -x,+x, -y,+y, -z,+z face points; and the final point (the 15th out of 15
* points) defines the center of the hexahedron. These point values are
* guaranteed to be up-to-date when either the InteractionEvent or
* EndInteractionEvent events are invoked. The user provides the
* vtkPolyData and the points and cells are added to it.
*/
void GetPolyData(vtkPolyData* pd);
//@{
/**
* Get the handle properties (the little balls are the handles). The
* properties of the handles when selected and normal can be
* set.
*/
vtkGetObjectMacro(HandleProperty, vtkProperty);
vtkGetObjectMacro(SelectedHandleProperty, vtkProperty);
//@}
//@{
/**
* Switches handles (the spheres) on or off by manipulating the actor
* visibility.
*/
void HandlesOn();
void HandlesOff();
//@}
//@{
/**
* Get the face properties (the faces of the box). The
* properties of the face when selected and normal can be
* set.
*/
vtkGetObjectMacro(FaceProperty, vtkProperty);
vtkGetObjectMacro(SelectedFaceProperty, vtkProperty);
//@}
//@{
/**
* Get the outline properties (the outline of the box). The
* properties of the outline when selected and normal can be
* set.
*/
vtkGetObjectMacro(OutlineProperty, vtkProperty);
vtkGetObjectMacro(SelectedOutlineProperty, vtkProperty);
//@}
//@{
/**
* Control the representation of the outline. This flag enables
* face wires. By default face wires are off.
*/
void SetOutlineFaceWires(int);
vtkGetMacro(OutlineFaceWires, int);
void OutlineFaceWiresOn() { this->SetOutlineFaceWires(1); }
void OutlineFaceWiresOff() { this->SetOutlineFaceWires(0); }
//@}
//@{
/**
* Control the representation of the outline. This flag enables
* the cursor lines running between the handles. By default cursor
* wires are on.
*/
void SetOutlineCursorWires(int);
vtkGetMacro(OutlineCursorWires, int);
void OutlineCursorWiresOn() { this->SetOutlineCursorWires(1); }
void OutlineCursorWiresOff() { this->SetOutlineCursorWires(0); }
//@}
//@{
/**
* Control the behavior of the widget. Translation, rotation, and
* scaling can all be enabled and disabled.
*/
vtkSetMacro(TranslationEnabled, vtkTypeBool);
vtkGetMacro(TranslationEnabled, vtkTypeBool);
vtkBooleanMacro(TranslationEnabled, vtkTypeBool);
vtkSetMacro(ScalingEnabled, vtkTypeBool);
vtkGetMacro(ScalingEnabled, vtkTypeBool);
vtkBooleanMacro(ScalingEnabled, vtkTypeBool);
vtkSetMacro(RotationEnabled, vtkTypeBool);
vtkGetMacro(RotationEnabled, vtkTypeBool);
vtkBooleanMacro(RotationEnabled, vtkTypeBool);
//@}
protected:
vtkBoxWidget();
~vtkBoxWidget() override;
// Manage the state of the widget
int State;
enum WidgetState
{
Start = 0,
Moving,
Scaling,
Outside
};
// Handles the events
static void ProcessEvents(
vtkObject* object, unsigned long event, void* clientdata, void* calldata);
// ProcessEvents() dispatches to these methods.
virtual void OnMouseMove();
virtual void OnLeftButtonDown();
virtual void OnLeftButtonUp();
virtual void OnMiddleButtonDown();
virtual void OnMiddleButtonUp();
virtual void OnRightButtonDown();
virtual void OnRightButtonUp();
// the hexahedron (6 faces)
vtkActor* HexActor;
vtkPolyDataMapper* HexMapper;
vtkPolyData* HexPolyData;
vtkPoints* Points; // used by others as well
double N[6][3]; // the normals of the faces
// A face of the hexahedron
vtkActor* HexFace;
vtkPolyDataMapper* HexFaceMapper;
vtkPolyData* HexFacePolyData;
// glyphs representing hot spots (e.g., handles)
vtkActor** Handle;
vtkPolyDataMapper** HandleMapper;
vtkSphereSource** HandleGeometry;
virtual void PositionHandles();
int HighlightHandle(vtkProp* prop); // returns cell id
void HighlightFace(int cellId);
void HighlightOutline(int highlight);
void ComputeNormals();
void SizeHandles() override;
// wireframe outline
vtkActor* HexOutline;
vtkPolyDataMapper* OutlineMapper;
vtkPolyData* OutlinePolyData;
// Do the picking
vtkCellPicker* HandlePicker;
vtkCellPicker* HexPicker;
vtkActor* CurrentHandle;
int CurrentHexFace;
// Register internal Pickers within PickingManager
void RegisterPickers() override;
// Methods to manipulate the hexahedron.
virtual void Translate(double* p1, double* p2);
virtual void Scale(double* p1, double* p2, int X, int Y);
virtual void Rotate(int X, int Y, double* p1, double* p2, double* vpn);
void MovePlusXFace(double* p1, double* p2);
void MoveMinusXFace(double* p1, double* p2);
void MovePlusYFace(double* p1, double* p2);
void MoveMinusYFace(double* p1, double* p2);
void MovePlusZFace(double* p1, double* p2);
void MoveMinusZFace(double* p1, double* p2);
//"dir" is the direction in which the face can be moved i.e. the axis passing
// through the center
void MoveFace(double* p1, double* p2, double* dir, double* x1, double* x2, double* x3, double* x4,
double* x5);
// Helper method to obtain the direction in which the face is to be moved.
// Handles special cases where some of the scale factors are 0.
void GetDirection(const double Nx[3], const double Ny[3], const double Nz[3], double dir[3]);
// Transform the hexahedral points (used for rotations)
vtkTransform* Transform;
// Properties used to control the appearance of selected objects and
// the manipulator in general.
vtkProperty* HandleProperty;
vtkProperty* SelectedHandleProperty;
vtkProperty* FaceProperty;
vtkProperty* SelectedFaceProperty;
vtkProperty* OutlineProperty;
vtkProperty* SelectedOutlineProperty;
void CreateDefaultProperties();
// Control the orientation of the normals
vtkTypeBool InsideOut;
int OutlineFaceWires;
int OutlineCursorWires;
void GenerateOutline();
// Control whether scaling, rotation, and translation are supported
vtkTypeBool TranslationEnabled;
vtkTypeBool ScalingEnabled;
vtkTypeBool RotationEnabled;
private:
vtkBoxWidget(const vtkBoxWidget&) = delete;
void operator=(const vtkBoxWidget&) = delete;
};
#endif