Commit 639e7585 authored by Dave DeMarle's avatar Dave DeMarle Committed by Code Review
Browse files

Merge topic 'ImplicitPlaneWidget2' into master

ccdaad8e BUG: Fix vtkImplicitPlaneRepresentation, redesign widget implementation:
dd214570 ENH: Automatic plan orientation in vtkImplicitPlaneWidget2
parents 8af11a6b ccdaad8e
......@@ -77,6 +77,7 @@ IF (VTK_DATA_ROOT)
TestImplicitPlaneWidget.cxx
TestImplicitPlaneWidget2.cxx
TestImplicitPlaneWidget2b.cxx
TestImplicitPlaneWidget2LockNormalToCamera.cxx
TestLineWidget.cxx
TestLineWidget2.cxx
TestLogoWidgetAlphaBlending.cxx
......
......@@ -25,6 +25,7 @@
#include "vtkFeatureEdges.h"
#include "vtkImageData.h"
#include "vtkLineSource.h"
#include "vtkLookupTable.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkOutlineFilter.h"
......@@ -34,11 +35,14 @@
#include "vtkProperty.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
#include "vtkSphereSource.h"
#include "vtkTransform.h"
#include "vtkTubeFilter.h"
#include "vtkInteractorObserver.h"
#include "vtkBox.h"
#include "vtkCommand.h"
#include "vtkWindow.h"
vtkStandardNewMacro(vtkImplicitPlaneRepresentation);
......@@ -49,9 +53,14 @@ vtkImplicitPlaneRepresentation::vtkImplicitPlaneRepresentation()
this->NormalToYAxis = 0;
this->NormalToZAxis = 0;
this->LockNormalToCamera = 0;
// Handle size is in pixels for this widget
this->HandleSize = 5.0;
// Pushing operation
this->BumpDistance = 0.01;
// Build the representation of the widget
//
this->Plane = vtkPlane::New();
......@@ -227,6 +236,39 @@ vtkImplicitPlaneRepresentation::~vtkImplicitPlaneRepresentation()
this->BoundingBox->Delete();
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::SetLockNormalToCamera(int lock)
{
vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting "
<< LockNormalToCamera << " to " << lock);
if ( lock == this->LockNormalToCamera )
{
return;
}
if (lock)
{
this->Picker->DeletePickList(this->LineActor);
this->Picker->DeletePickList(this->ConeActor);
this->Picker->DeletePickList(this->LineActor2);
this->Picker->DeletePickList(this->ConeActor2);
this->Picker->DeletePickList(this->SphereActor);
this->SetNormalToCamera();
}
else
{
this->Picker->AddPickList(this->LineActor);
this->Picker->AddPickList(this->ConeActor);
this->Picker->AddPickList(this->LineActor2);
this->Picker->AddPickList(this->ConeActor2);
this->Picker->AddPickList(this->SphereActor);
}
this->LockNormalToCamera = lock;
this->Modified();
}
//----------------------------------------------------------------------------
int vtkImplicitPlaneRepresentation::ComputeInteractionState(int X, int Y,
int vtkNotUsed(modify))
......@@ -236,7 +278,7 @@ int vtkImplicitPlaneRepresentation::ComputeInteractionState(int X, int Y,
this->Picker->Pick(X,Y,0.0,this->Renderer);
path = this->Picker->GetPath();
if ( path == NULL ) //not picking this widget
if ( path == NULL ) // Not picking this widget
{
this->SetRepresentationState(vtkImplicitPlaneRepresentation::Outside);
this->InteractionState = vtkImplicitPlaneRepresentation::Outside;
......@@ -259,8 +301,16 @@ int vtkImplicitPlaneRepresentation::ComputeInteractionState(int X, int Y,
}
else if ( prop == this->CutActor )
{
this->InteractionState = vtkImplicitPlaneRepresentation::Pushing;
this->SetRepresentationState(vtkImplicitPlaneRepresentation::Pushing);
if(this->LockNormalToCamera)
{ // Allow camera to work
this->InteractionState = vtkImplicitPlaneRepresentation::Outside;
this->SetRepresentationState(vtkImplicitPlaneRepresentation::Outside);
}
else
{
this->InteractionState = vtkImplicitPlaneRepresentation::Pushing;
this->SetRepresentationState(vtkImplicitPlaneRepresentation::Pushing);
}
}
else if ( prop == this->SphereActor )
{
......@@ -282,17 +332,8 @@ int vtkImplicitPlaneRepresentation::ComputeInteractionState(int X, int Y,
}
}
else if ( this->InteractionState == vtkImplicitPlaneRepresentation::MovingPlane )
{
return this->InteractionState;
}
else if ( this->InteractionState == vtkImplicitPlaneRepresentation::Scaling )
{
return this->InteractionState;
}
else
// We may add a condition to allow the camera to work IO scaling
else if ( this->InteractionState != vtkImplicitPlaneRepresentation::Scaling )
{
this->InteractionState = vtkImplicitPlaneRepresentation::Outside;
}
......@@ -324,6 +365,7 @@ void vtkImplicitPlaneRepresentation::SetRepresentationState(int state)
}
else if ( state == vtkImplicitPlaneRepresentation::Pushing )
{
this->HighlightNormal(1);
this->HighlightPlane(1);
}
else if ( state == vtkImplicitPlaneRepresentation::MovingOrigin )
......@@ -334,11 +376,6 @@ void vtkImplicitPlaneRepresentation::SetRepresentationState(int state)
{
this->HighlightOutline(1);
}
else if ( state == vtkImplicitPlaneRepresentation::MovingPlane )
{
this->HighlightNormal(1);
this->HighlightPlane(1);
}
else if ( state == vtkImplicitPlaneRepresentation::Scaling &&
this->ScaleEnabled )
{
......@@ -391,11 +428,7 @@ void vtkImplicitPlaneRepresentation::WidgetInteraction(double e[2])
vtkInteractorObserver::ComputeDisplayToWorld(this->Renderer, e[0], e[1], z, pickPoint);
// Process the motion
if ( this->InteractionState == vtkImplicitPlaneRepresentation::MovingPlane )
{
this->TranslatePlane(prevPickPoint, pickPoint);
}
else if ( this->InteractionState == vtkImplicitPlaneRepresentation::MovingOutline )
if ( this->InteractionState == vtkImplicitPlaneRepresentation::MovingOutline )
{
this->TranslateOutline(prevPickPoint, pickPoint);
}
......@@ -417,6 +450,11 @@ void vtkImplicitPlaneRepresentation::WidgetInteraction(double e[2])
camera->GetViewPlaneNormal(vpn);
this->Rotate(e[0], e[1], prevPickPoint, pickPoint, vpn);
}
else if( this->InteractionState == vtkImplicitPlaneRepresentation::Outside &&
this->LockNormalToCamera )
{
this->SetNormalToCamera();
}
this->LastEventPosition[0] = e[0];
this->LastEventPosition[1] = e[1];
......@@ -478,11 +516,14 @@ int vtkImplicitPlaneRepresentation::RenderOpaqueGeometry(vtkViewport *v)
this->BuildRepresentation();
count += this->OutlineActor->RenderOpaqueGeometry(v);
count += this->EdgesActor->RenderOpaqueGeometry(v);
count += this->ConeActor->RenderOpaqueGeometry(v);
count += this->LineActor->RenderOpaqueGeometry(v);
count += this->ConeActor2->RenderOpaqueGeometry(v);
count += this->LineActor2->RenderOpaqueGeometry(v);
count += this->SphereActor->RenderOpaqueGeometry(v);
if ( ! this->LockNormalToCamera )
{
count += this->ConeActor->RenderOpaqueGeometry(v);
count += this->LineActor->RenderOpaqueGeometry(v);
count += this->ConeActor2->RenderOpaqueGeometry(v);
count += this->LineActor2->RenderOpaqueGeometry(v);
count += this->SphereActor->RenderOpaqueGeometry(v);
}
if ( this->DrawPlane )
{
count += this->CutActor->RenderOpaqueGeometry(v);
......@@ -499,11 +540,14 @@ int vtkImplicitPlaneRepresentation::RenderTranslucentPolygonalGeometry(
this->BuildRepresentation();
count += this->OutlineActor->RenderTranslucentPolygonalGeometry(v);
count += this->EdgesActor->RenderTranslucentPolygonalGeometry(v);
count += this->ConeActor->RenderTranslucentPolygonalGeometry(v);
count += this->LineActor->RenderTranslucentPolygonalGeometry(v);
count += this->ConeActor2->RenderTranslucentPolygonalGeometry(v);
count += this->LineActor2->RenderTranslucentPolygonalGeometry(v);
count += this->SphereActor->RenderTranslucentPolygonalGeometry(v);
if ( ! this->LockNormalToCamera )
{
count += this->ConeActor->RenderTranslucentPolygonalGeometry(v);
count += this->LineActor->RenderTranslucentPolygonalGeometry(v);
count += this->ConeActor2->RenderTranslucentPolygonalGeometry(v);
count += this->LineActor2->RenderTranslucentPolygonalGeometry(v);
count += this->SphereActor->RenderTranslucentPolygonalGeometry(v);
}
if ( this->DrawPlane )
{
count += this->CutActor->RenderTranslucentPolygonalGeometry(v);
......@@ -518,11 +562,14 @@ int vtkImplicitPlaneRepresentation::HasTranslucentPolygonalGeometry()
int result=0;
result |= this->OutlineActor->HasTranslucentPolygonalGeometry();
result |= this->EdgesActor->HasTranslucentPolygonalGeometry();
result |= this->ConeActor->HasTranslucentPolygonalGeometry();
result |= this->LineActor->HasTranslucentPolygonalGeometry();
result |= this->ConeActor2->HasTranslucentPolygonalGeometry();
result |= this->LineActor2->HasTranslucentPolygonalGeometry();
result |= this->SphereActor->HasTranslucentPolygonalGeometry();
if ( ! this->LockNormalToCamera )
{
result |= this->ConeActor->HasTranslucentPolygonalGeometry();
result |= this->LineActor->HasTranslucentPolygonalGeometry();
result |= this->ConeActor2->HasTranslucentPolygonalGeometry();
result |= this->LineActor2->HasTranslucentPolygonalGeometry();
result |= this->SphereActor->HasTranslucentPolygonalGeometry();
}
if ( this->DrawPlane )
{
result |= this->CutActor->HasTranslucentPolygonalGeometry();
......@@ -614,6 +661,7 @@ void vtkImplicitPlaneRepresentation::PrintSelf(ostream& os, vtkIndent indent)
os << indent << "Scale Enabled: "
<< (this->ScaleEnabled ? "On" : "Off") << "\n";
os << indent << "Draw Plane: " << (this->DrawPlane ? "On" : "Off") << "\n";
os << indent << "Bump Distance: " << this->BumpDistance << "\n";
os << indent << "Representation State: ";
switch ( this->RepresentationState )
......@@ -636,9 +684,6 @@ void vtkImplicitPlaneRepresentation::PrintSelf(ostream& os, vtkIndent indent)
case Pushing:
os << "Pushing\n";
break;
case MovingPlane:
os << "MovingPlane\n";
break;
case Scaling:
os << "Scaling\n";
break;
......@@ -733,30 +778,7 @@ void vtkImplicitPlaneRepresentation::Rotate(double X, double Y,
//Set the new normal
double nNew[3];
this->Transform->TransformNormal(normal,nNew);
this->Plane->SetNormal(nNew);
this->BuildRepresentation();
}
//----------------------------------------------------------------------------
// Loop through all points and translate them
void vtkImplicitPlaneRepresentation::TranslatePlane(double *p1, double *p2)
{
//Get the motion vector
double v[3];
v[0] = p2[0] - p1[0];
v[1] = p2[1] - p1[1];
v[2] = p2[2] - p1[2];
//Translate the plane
double oNew[3];
double *origin = this->Plane->GetOrigin();
oNew[0] = origin[0] + v[0];
oNew[1] = origin[1] + v[1];
oNew[2] = origin[2] + v[2];
this->Plane->SetOrigin(oNew);
this->BuildRepresentation();
this->SetNormal(nNew);
}
//----------------------------------------------------------------------------
......@@ -910,6 +932,32 @@ void vtkImplicitPlaneRepresentation::CreateDefaultProperties()
this->EdgesProperty->SetAmbientColor(1.0,1.0,1.0);
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::SetEdgeColor(vtkLookupTable* lut)
{
this->EdgesMapper->SetLookupTable(lut);
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::SetEdgeColor(double r, double g, double b)
{
vtkSmartPointer<vtkLookupTable> lookupTable =
vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetTableRange(0.0, 1.0);
lookupTable->SetNumberOfTableValues(1);
lookupTable->SetTableValue(0, r, g, b);
lookupTable->Build();
this->SetEdgeColor(lookupTable);
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::SetEdgeColor(double c[3])
{
this->SetEdgeColor(c[0], c[1], c[2]);
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::PlaceWidget(double bds[6])
{
......@@ -1006,13 +1054,18 @@ void vtkImplicitPlaneRepresentation::GetOrigin(double xyz[3])
// Set the normal to the plane.
void vtkImplicitPlaneRepresentation::SetNormal(double x, double y, double z)
{
double n[3];
double n[3], n2[3];
n[0] = x;
n[1] = y;
n[2] = z;
vtkMath::Normalize(n);
this->Plane->SetNormal(n);
this->BuildRepresentation();
this->Plane->GetNormal(n2);
if ( n[0] != n2[0] || n[1] != n2[1] || n[2] != n2[2] )
{
this->Plane->SetNormal(n);
this->Modified();
}
}
//----------------------------------------------------------------------------
......@@ -1128,6 +1181,23 @@ void vtkImplicitPlaneRepresentation::UpdatePlacement()
this->BuildRepresentation();
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::BumpPlane(int dir, double factor)
{
// Compute the distance
double d = this->InitialLength * this->BumpDistance * factor;
// Push the plane
this->PushPlane( (dir > 0 ? d : -d) );
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::PushPlane(double d)
{
this->Plane->Push(d);
this->BuildRepresentation();
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::BuildRepresentation()
{
......@@ -1136,60 +1206,67 @@ void vtkImplicitPlaneRepresentation::BuildRepresentation()
return;
}
double *origin = this->Plane->GetOrigin();
double *normal = this->Plane->GetNormal();
double p2[3];
if( !this->OutsideBounds )
if ( this->GetMTime() > this->BuildTime ||
this->Plane->GetMTime() > this->BuildTime )
{
double *bounds = this->InitialBounds;
for (int i=0; i<3; i++)
double *origin = this->Plane->GetOrigin();
double *normal = this->Plane->GetNormal();
double p2[3];
if( !this->OutsideBounds )
{
if ( origin[i] < bounds[2*i] )
{
origin[i] = bounds[2*i];
}
else if ( origin[i] > bounds[2*i+1] )
double *bounds = this->InitialBounds;
for (int i=0; i<3; i++)
{
origin[i] = bounds[2*i+1];
if ( origin[i] < bounds[2*i] )
{
origin[i] = bounds[2*i];
}
else if ( origin[i] > bounds[2*i+1] )
{
origin[i] = bounds[2*i+1];
}
}
}
}
// Setup the plane normal
double d = this->Outline->GetOutput()->GetLength();
// Setup the plane normal
double d = this->Outline->GetOutput()->GetLength();
p2[0] = origin[0] + 0.30 * d * normal[0];
p2[1] = origin[1] + 0.30 * d * normal[1];
p2[2] = origin[2] + 0.30 * d * normal[2];
p2[0] = origin[0] + 0.30 * d * normal[0];
p2[1] = origin[1] + 0.30 * d * normal[1];
p2[2] = origin[2] + 0.30 * d * normal[2];
this->LineSource->SetPoint1(origin);
this->LineSource->SetPoint2(p2);
this->ConeSource->SetCenter(p2);
this->ConeSource->SetDirection(normal);
this->LineSource->SetPoint1(origin);
this->LineSource->SetPoint2(p2);
this->ConeSource->SetCenter(p2);
this->ConeSource->SetDirection(normal);
p2[0] = origin[0] - 0.30 * d * normal[0];
p2[1] = origin[1] - 0.30 * d * normal[1];
p2[2] = origin[2] - 0.30 * d * normal[2];
p2[0] = origin[0] - 0.30 * d * normal[0];
p2[1] = origin[1] - 0.30 * d * normal[1];
p2[2] = origin[2] - 0.30 * d * normal[2];
this->LineSource2->SetPoint1(origin[0],origin[1],origin[2]);
this->LineSource2->SetPoint2(p2);
this->ConeSource2->SetCenter(p2);
this->ConeSource2->SetDirection(normal[0],normal[1],normal[2]);
this->LineSource2->SetPoint1(origin[0],origin[1],origin[2]);
this->LineSource2->SetPoint2(p2);
this->ConeSource2->SetCenter(p2);
this->ConeSource2->SetDirection(normal[0],normal[1],normal[2]);
// Set up the position handle
this->Sphere->SetCenter(origin[0],origin[1],origin[2]);
// Set up the position handle
this->Sphere->SetCenter(origin[0],origin[1],origin[2]);
// Control the look of the edges
if ( this->Tubing )
{
this->EdgesMapper->SetInput(this->EdgesTuber->GetOutput());
}
else
{
this->EdgesMapper->SetInput(this->Edges->GetOutput());
// Control the look of the edges
if ( this->Tubing )
{
this->EdgesMapper->SetInput(this->EdgesTuber->GetOutput());
}
else
{
this->EdgesMapper->SetInput(this->Edges->GetOutput());
}
this->SizeHandles();
this->BuildTime.Modified();
}
this->SizeHandles();
}
//----------------------------------------------------------------------------
......@@ -1207,3 +1284,16 @@ void vtkImplicitPlaneRepresentation::SizeHandles()
this->EdgesTuber->SetRadius(0.25*radius);
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::SetNormalToCamera()
{
if( !this->Renderer )
{
return;
}
double normal[3];
this->Renderer->GetActiveCamera()->GetViewPlaneNormal(normal);
this->SetNormal(normal);
}
......@@ -55,6 +55,7 @@ class vtkPolyData;
class vtkPolyDataAlgorithm;
class vtkTransform;
class vtkBox;
class vtkLookupTable;
class VTK_WIDGETS_EXPORT vtkImplicitPlaneRepresentation : public vtkWidgetRepresentation
{
......@@ -79,6 +80,7 @@ public:
// Get the normal to the plane.
void SetNormal(double x, double y, double z);
void SetNormal(double x[3]);
void SetNormalToCamera();
double* GetNormal();
void GetNormal(double xyz[3]);
......@@ -98,6 +100,14 @@ public:
vtkGetMacro(NormalToZAxis,int);
vtkBooleanMacro(NormalToZAxis,int);
// Description:
// If enabled, and a vtkCamera is available through the renderer, then
// LockNormalToCamera will cause the normal to follow the camera's
// normal.
virtual void SetLockNormalToCamera(int);
vtkGetMacro(LockNormalToCamera,int);
vtkBooleanMacro(LockNormalToCamera,int);
// Description:
// Turn on/off tubing of the wire outline of the plane. The tube thickens
// the line by wrapping with a vtkTubeFilter.
......@@ -176,6 +186,34 @@ public:
// Get the property of the intersection edges. (This property also
// applies to the edges when tubed.)
vtkGetObjectMacro(EdgesProperty,vtkProperty);
// Description
// Set color to the edge
void SetEdgeColor(vtkLookupTable*);
void SetEdgeColor(double, double, double);
void SetEdgeColor(double x[3]);
// Description:
// Specify a translation distance used by the BumpPlane() method. Note that the
// distance is normalized; it is the fraction of the length of the bounding
// box of the wire outline.
vtkSetClampMacro(BumpDistance,double,0.000001,1);
vtkGetMacro(BumpDistance,double);
// Description:
// Translate the plane in the direction of the normal by the
// specified BumpDistance. The dir parameter controls which
// direction the pushing occurs, either in the same direction
// as the normal, or when negative, in the opposite direction.
// The factor controls whether what percentage of the bump is
// used.
void BumpPlane(int dir, double factor);
// Description:
// Push the plane the distance specified along the normal. Positive
// values are in the direction of the normal; negative values are
// in the opposite direction of the normal. The distance value is
// expressed in world coordinates.
void PushPlane(double distance);
// Description:
// Methods to interface with the vtkSliderWidget.
......@@ -185,7 +223,6 @@ public:
virtual void StartWidgetInteraction(double eventPos[2]);
virtual void WidgetInteraction(double newEventPos[2]);
virtual void EndWidgetInteraction(double newEventPos[2]);
// Decsription:
// Methods supporting the rendering process.
virtual double *GetBounds();
......@@ -204,7 +241,6 @@ public:
MovingOrigin,
Rotating,
Pushing,
MovingPlane,
Scaling
};
//ETX
......@@ -239,6 +275,12 @@ protected:
int NormalToYAxis;
int NormalToZAxis;
// Locking normal to camera
int LockNormalToCamera;
// Controlling the push operation
double BumpDistance;
// The actual plane which is being manipulated
vtkPlane *Plane;
......
......@@ -17,6 +17,9 @@
#include "vtkCommand.h"
#include "vtkCallbackCommand.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkStdString.h"
#include "vtkCamera.h"
#include "vtkRenderer.h"
#include "vtkObjectFactory.h"
#include "vtkWidgetEventTranslator.h"
#include "vtkWidgetCallbackMapper.h"
......@@ -27,6 +30,26 @@
vtkStandardNewMacro(vtkImplicitPlaneWidget2);
// The implicit plane widget observes its representation. The representation
// may invoke an InteractionEvent when the camera moves when LockedNormalToCamera
// is enabled.
class vtkInteractionCallback : public vtkCommand
{
public:
static vtkInteractionCallback *New()
{ return new vtkInteractionCallback; }
virtual void Execute(vtkObject*, unsigned long eventId, void*)
{
switch (eventId)
{