Commit ccdaad8e authored by Michael Jeulin-L's avatar Michael Jeulin-L
Browse files

BUG: Fix vtkImplicitPlaneRepresentation, redesign widget implementation:

 - Re-implement the Automatic plan orientation
 - Arrows (right, left, top, bottom) shift origin instead of '<' and '>'
 - Don't observe the representation but the camera directly
 - BuildRepresentation only when needed (if rep is changed)
 - Expose to API the edge color
 - Fix active/inactive mode with change cursor
 - Avoid highlighting cut plane and changing the mouse pointer in lockToCamera mode.
 - Reactivate rescaling.
 - Add a test for trying: Press ctrl key to change the mode when interacting.

Change-Id: I9c8b8b2ccd04baf32b75178b59afc1fd0e148948
parent dd214570
......@@ -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,12 +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);
......@@ -50,7 +53,7 @@ vtkImplicitPlaneRepresentation::vtkImplicitPlaneRepresentation()
this->NormalToYAxis = 0;
this->NormalToZAxis = 0;
this->SlaveNormalToCamera = 0;
this->LockNormalToCamera = 0;
// Handle size is in pixels for this widget
this->HandleSize = 5.0;
......@@ -234,33 +237,36 @@ vtkImplicitPlaneRepresentation::~vtkImplicitPlaneRepresentation()
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::UpdateSlavedNormal()
void vtkImplicitPlaneRepresentation::SetLockNormalToCamera(int lock)
{
if ( this->Renderer )
vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting "
<< LockNormalToCamera << " to " << lock);
if ( lock == this->LockNormalToCamera )
{
double n[3], n2[3];
vtkCamera *cam = this->Renderer->GetActiveCamera();
cam->GetViewPlaneNormal(n);
this->Plane->GetNormal(n2);
if ( n[0] != n2[0] || n[1] != n2[1] || n[2] != n2[2] )
{
this->Plane->SetNormal(n);
this->InvokeEvent(vtkCommand::InteractionEvent,NULL);
}
return;
}
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneRepresentation::SetSlaveNormalToCamera(int lock)
{
vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting "
<< SlaveNormalToCamera << " to " << lock);
if ( lock != this->SlaveNormalToCamera )
if (lock)
{
this->UpdateSlavedNormal();
this->SlaveNormalToCamera = lock;
this->Modified();
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();
}
//----------------------------------------------------------------------------
......@@ -272,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;
......@@ -295,9 +301,8 @@ int vtkImplicitPlaneRepresentation::ComputeInteractionState(int X, int Y,
}
else if ( prop == this->CutActor )
{
// if ( 0 )
if ( this->SlaveNormalToCamera )
{//allow camera to work
if(this->LockNormalToCamera)
{ // Allow camera to work
this->InteractionState = vtkImplicitPlaneRepresentation::Outside;
this->SetRepresentationState(vtkImplicitPlaneRepresentation::Outside);
}
......@@ -327,19 +332,8 @@ int vtkImplicitPlaneRepresentation::ComputeInteractionState(int X, int Y,
}
}
else if ( this->InteractionState == vtkImplicitPlaneRepresentation::Scaling )
{
if ( this->SlaveNormalToCamera )
{//allow camera to work
this->InteractionState = vtkImplicitPlaneRepresentation::Outside;
this->SetRepresentationState(vtkImplicitPlaneRepresentation::Outside);
}
else
{
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;
}
......@@ -456,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];
......@@ -517,7 +516,7 @@ int vtkImplicitPlaneRepresentation::RenderOpaqueGeometry(vtkViewport *v)
this->BuildRepresentation();
count += this->OutlineActor->RenderOpaqueGeometry(v);
count += this->EdgesActor->RenderOpaqueGeometry(v);
if ( ! this->SlaveNormalToCamera )
if ( ! this->LockNormalToCamera )
{
count += this->ConeActor->RenderOpaqueGeometry(v);
count += this->LineActor->RenderOpaqueGeometry(v);
......@@ -541,7 +540,7 @@ int vtkImplicitPlaneRepresentation::RenderTranslucentPolygonalGeometry(
this->BuildRepresentation();
count += this->OutlineActor->RenderTranslucentPolygonalGeometry(v);
count += this->EdgesActor->RenderTranslucentPolygonalGeometry(v);
if ( ! this->SlaveNormalToCamera )
if ( ! this->LockNormalToCamera )
{
count += this->ConeActor->RenderTranslucentPolygonalGeometry(v);
count += this->LineActor->RenderTranslucentPolygonalGeometry(v);
......@@ -563,7 +562,7 @@ int vtkImplicitPlaneRepresentation::HasTranslucentPolygonalGeometry()
int result=0;
result |= this->OutlineActor->HasTranslucentPolygonalGeometry();
result |= this->EdgesActor->HasTranslucentPolygonalGeometry();
if ( ! this->SlaveNormalToCamera )
if ( ! this->LockNormalToCamera )
{
result |= this->ConeActor->HasTranslucentPolygonalGeometry();
result |= this->LineActor->HasTranslucentPolygonalGeometry();
......@@ -779,9 +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();
this->SetNormal(nNew);
}
//----------------------------------------------------------------------------
......@@ -935,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])
{
......@@ -1031,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();
}
}
//----------------------------------------------------------------------------
......@@ -1182,7 +1210,6 @@ void vtkImplicitPlaneRepresentation::BuildRepresentation()
this->Plane->GetMTime() > this->BuildTime )
{
double *origin = this->Plane->GetOrigin();
this->UpdateSlavedNormal();
double *normal = this->Plane->GetNormal();
double p2[3];
......@@ -1235,9 +1262,11 @@ void vtkImplicitPlaneRepresentation::BuildRepresentation()
{
this->EdgesMapper->SetInput(this->Edges->GetOutput());
}
this->SizeHandles();
this->BuildTime.Modified();
}
this->SizeHandles();
}
//----------------------------------------------------------------------------
......@@ -1255,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]);
......@@ -100,11 +102,11 @@ public:
// Description:
// If enabled, and a vtkCamera is available through the renderer, then
// SlaveNormalToCamera will cause the normal to follow the camera's
// notmal.
virtual void SetSlaveNormalToCamera(int);
vtkGetMacro(SlaveNormalToCamera,int);
vtkBooleanMacro(SlaveNormalToCamera,int);
// 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
......@@ -184,6 +186,11 @@ 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
......@@ -269,8 +276,7 @@ protected:
int NormalToZAxis;
// Locking normal to camera
int SlaveNormalToCamera;
void UpdateSlavedNormal();
int LockNormalToCamera;
// Controlling the push operation
double BumpDistance;
......
......@@ -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"
......@@ -39,7 +42,7 @@ public:
{
switch (eventId)
{
case vtkCommand::InteractionEvent:
case vtkCommand::ModifiedEvent:
this->ImplicitPlaneWidget->InvokeInteractionCallback();
break;
}
......@@ -75,11 +78,19 @@ vtkImplicitPlaneWidget2::vtkImplicitPlaneWidget2()
vtkWidgetEvent::Move,
this, vtkImplicitPlaneWidget2::MoveAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::KeyPressEvent,
vtkEvent::AnyModifier, 60, 1, "less",
vtkEvent::AnyModifier, 30, 1, "Up",
vtkWidgetEvent::Up,
this, vtkImplicitPlaneWidget2::MovePlaneAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::KeyPressEvent,
vtkEvent::AnyModifier, 62, 1, "greater",
vtkEvent::AnyModifier, 28, 1, "Right",
vtkWidgetEvent::Up,
this, vtkImplicitPlaneWidget2::MovePlaneAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::KeyPressEvent,
vtkEvent::AnyModifier, 31, 1, "Down",
vtkWidgetEvent::Down,
this, vtkImplicitPlaneWidget2::MovePlaneAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::KeyPressEvent,
vtkEvent::AnyModifier, 29, 1, "Left",
vtkWidgetEvent::Down,
this, vtkImplicitPlaneWidget2::MovePlaneAction);
......@@ -90,10 +101,6 @@ vtkImplicitPlaneWidget2::vtkImplicitPlaneWidget2()
//----------------------------------------------------------------------------
vtkImplicitPlaneWidget2::~vtkImplicitPlaneWidget2()
{
if ( this->WidgetRep )
{
this->WidgetRep->RemoveObserver(this->InteractionCallback);
}
this->InteractionCallback->Delete();
}
......@@ -212,10 +219,10 @@ void vtkImplicitPlaneWidget2::MoveAction(vtkAbstractWidget *w)
int Y = self->Interactor->GetEventPosition()[1];
int changed = 0;
if (self->ManagesCursor)
if (self->ManagesCursor && self->WidgetState != vtkImplicitPlaneWidget2::Active)
{
int oldInteractionState = reinterpret_cast<vtkImplicitPlaneRepresentation*>(
self->WidgetRep)->GetInteractionState();
self->WidgetRep)->GetInteractionState();
reinterpret_cast<vtkImplicitPlaneRepresentation*>(self->WidgetRep)->
SetInteractionState(vtkImplicitPlaneRepresentation::Moving);
......@@ -223,6 +230,7 @@ void vtkImplicitPlaneWidget2::MoveAction(vtkAbstractWidget *w)
changed = self->UpdateCursorShape(state);
reinterpret_cast<vtkImplicitPlaneRepresentation*>(self->WidgetRep)->
SetInteractionState(oldInteractionState);
changed = (changed || state != oldInteractionState) ? 1 : 0;
}
// See whether we're active
......@@ -264,6 +272,10 @@ void vtkImplicitPlaneWidget2::EndSelectAction(vtkAbstractWidget *w)
self->WidgetState = vtkImplicitPlaneWidget2::Start;
self->ReleaseFocus();
// Update cursor if managed
self->UpdateCursorShape(reinterpret_cast<vtkImplicitPlaneRepresentation*>
(self->WidgetRep)->GetRepresentationState());
self->EventCallbackCommand->SetAbortFlag(1);
self->EndInteraction();
self->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
......@@ -280,15 +292,12 @@ void vtkImplicitPlaneWidget2::MovePlaneAction(vtkAbstractWidget *w)
int X = self->Interactor->GetEventPosition()[0];
int Y = self->Interactor->GetEventPosition()[1];
int interactionState = self->WidgetRep->ComputeInteractionState(X, Y);
// if ( interactionState == vtkImplicitPlaneRepresentation::Outside )
// {
// return;
// }
self->WidgetRep->ComputeInteractionState(X, Y);
// Move the plane
double factor = ( self->Interactor->GetControlKey() ? 0.5 : 1.0);
if ( self->Interactor->GetKeyCode() == '<' )
if (vtkStdString( self->Interactor->GetKeySym() ) == vtkStdString("Down") ||
vtkStdString( self->Interactor->GetKeySym() ) == vtkStdString("Left"))
{
self->GetImplicitPlaneRepresentation()->BumpPlane(-1,factor);
}
......@@ -303,21 +312,19 @@ void vtkImplicitPlaneWidget2::MovePlaneAction(vtkAbstractWidget *w)
}
//----------------------------------------------------------------------
void vtkImplicitPlaneWidget2::
SetRepresentation(vtkImplicitPlaneRepresentation *r)
void vtkImplicitPlaneWidget2::SetEnabled(int enabling)
{
// Add observer to support normal locking
if ( this->WidgetRep != NULL )
if(this->Enabled == enabling)
{
this->WidgetRep->RemoveObserver(this->InteractionCallback);
return;
}
if ( r != NULL )
if(this->GetCurrentRenderer() && !enabling)
{
r->AddObserver(vtkCommand::InteractionEvent, this->InteractionCallback,
this->Priority);
this->GetCurrentRenderer()->GetActiveCamera()->RemoveObserver(this->InteractionCallback);
}
this->Superclass::SetWidgetRepresentation(reinterpret_cast<vtkWidgetRepresentation*>(r));
Superclass::SetEnabled(enabling);
}
//----------------------------------------------------------------------
......@@ -329,6 +336,14 @@ void vtkImplicitPlaneWidget2::CreateDefaultRepresentation()
}
}
//----------------------------------------------------------------------
void vtkImplicitPlaneWidget2::
SetRepresentation(vtkImplicitPlaneRepresentation*rep)
{
this->Superclass::SetWidgetRepresentation(
reinterpret_cast<vtkWidgetRepresentation*>(rep));
}
//----------------------------------------------------------------------
int vtkImplicitPlaneWidget2::UpdateCursorShape( int state )
{
......@@ -353,17 +368,57 @@ int vtkImplicitPlaneWidget2::UpdateCursorShape( int state )
return 0;
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneWidget2::SetLockNormalToCamera(int lock)
{
if (!this->GetImplicitPlaneRepresentation() ||
!this->Enabled ||
!this->GetCurrentRenderer())
{
return;
}
this->GetImplicitPlaneRepresentation()->SetLockNormalToCamera(lock);
// We assume that the renderer of the Widget cannot be changed without
// previously being disabled.
if (lock)
{
// We Observe the Camera && make the update
this->GetCurrentRenderer()->GetActiveCamera()->AddObserver(
vtkCommand::ModifiedEvent, this->InteractionCallback, this->Priority);
this->GetImplicitPlaneRepresentation()->SetNormalToCamera();
this->InvokeEvent(vtkCommand::InteractionEvent,NULL);
}
else
{
this->GetCurrentRenderer()->GetActiveCamera()->RemoveObserver(
this->InteractionCallback);
}
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneWidget2::InvokeInteractionCallback()
{
this->InvokeEvent(vtkCommand::InteractionEvent,NULL);
unsigned long previousMtime;
vtkImplicitPlaneRepresentation* widgetRep =
reinterpret_cast<vtkImplicitPlaneRepresentation*>(this->WidgetRep);
if(widgetRep->GetLockNormalToCamera())
{
previousMtime = widgetRep->GetMTime();
this->GetImplicitPlaneRepresentation()->SetNormalToCamera();
if(widgetRep->GetMTime() > previousMtime)
{
this->InvokeEvent(vtkCommand::InteractionEvent,NULL);
}
}
}
//----------------------------------------------------------------------------
void vtkImplicitPlaneWidget2::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
}
......@@ -45,8 +45,8 @@
// LeftButtonReleaseEvent - release slider (if selected)
// MouseMoveEvent - move the outline
// If the keypress characters are used
// '<' Move plane down
// '>' Move plane up
// 'Down/Left' Move plane down
// 'Up/Right' Move plane up
// In all the cases, independent of what is picked, the widget responds to the
// following VTK events:
// MiddleButtonPressEvent - move the plane
......@@ -113,7 +113,17 @@ public:
// Specify an instance of vtkWidgetRepresentation used to represent this
// widget in the scene. Note that the representation is a subclass of vtkProp
// so it can be added to the renderer independent of the widget.
void SetRepresentation(vtkImplicitPlaneRepresentation *r);
void SetRepresentation( vtkImplicitPlaneRepresentation *rep );
// Descritpion:
// Disable/Enable the widget if needed.
// Unobserved the camera if the widget is disabled.
void SetEnabled(int enabling);
// Description:
// Observe/Unobserve the camera if the widget is locked/unlocked to update the
// vtkImplicitePlaneRepresentation's normal.
void SetLockNormalToCamera(int lock);
// Description:
// Return the representation as a vtkImplicitPlaneRepresentation.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment