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.
414 lines
13 KiB
C++
414 lines
13 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkSeedWidget.cxx
|
|
|
|
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.
|
|
|
|
=========================================================================*/
|
|
#include "vtkSeedWidget.h"
|
|
|
|
#include "vtkCallbackCommand.h"
|
|
#include "vtkCommand.h"
|
|
#include "vtkCoordinate.h"
|
|
#include "vtkEvent.h"
|
|
#include "vtkHandleRepresentation.h"
|
|
#include "vtkHandleWidget.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkRenderer.h"
|
|
#include "vtkRenderWindow.h"
|
|
#include "vtkRenderWindowInteractor.h"
|
|
#include "vtkSeedRepresentation.h"
|
|
#include "vtkWidgetCallbackMapper.h"
|
|
#include "vtkWidgetEvent.h"
|
|
#include <iterator>
|
|
#include <list>
|
|
|
|
vtkStandardNewMacro(vtkSeedWidget);
|
|
|
|
// The vtkSeedList is a PIMPLed list<T>.
|
|
class vtkSeedList : public std::list<vtkHandleWidget*> {};
|
|
typedef std::list<vtkHandleWidget*>::iterator vtkSeedListIterator;
|
|
|
|
//----------------------------------------------------------------------
|
|
vtkSeedWidget::vtkSeedWidget()
|
|
{
|
|
this->ManagesCursor = 1;
|
|
this->WidgetState = vtkSeedWidget::Start;
|
|
|
|
// The widgets for moving the seeds.
|
|
this->Seeds = new vtkSeedList;
|
|
|
|
// These are the event callbacks supported by this widget
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonPressEvent,
|
|
vtkWidgetEvent::AddPoint,
|
|
this, vtkSeedWidget::AddPointAction);
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::RightButtonPressEvent,
|
|
vtkWidgetEvent::Completed,
|
|
this, vtkSeedWidget::CompletedAction);
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::MouseMoveEvent,
|
|
vtkWidgetEvent::Move,
|
|
this, vtkSeedWidget::MoveAction);
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonReleaseEvent,
|
|
vtkWidgetEvent::EndSelect,
|
|
this, vtkSeedWidget::EndSelectAction);
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::KeyPressEvent,
|
|
vtkEvent::NoModifier, 127, 1, "Delete",
|
|
vtkWidgetEvent::Delete,
|
|
this, vtkSeedWidget::DeleteAction);
|
|
this->Defining = 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void vtkSeedWidget::DeleteSeed(int i)
|
|
{
|
|
if( this->Seeds->size() <= static_cast< size_t >(i) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
vtkSeedRepresentation *rep =
|
|
static_cast<vtkSeedRepresentation*>(this->WidgetRep);
|
|
if (rep)
|
|
{
|
|
rep->RemoveHandle( i );
|
|
}
|
|
|
|
vtkSeedListIterator iter = this->Seeds->begin();
|
|
std::advance(iter,i);
|
|
(*iter)->SetEnabled(0);
|
|
(*iter)->RemoveObservers(vtkCommand::StartInteractionEvent);
|
|
(*iter)->RemoveObservers(vtkCommand::InteractionEvent);
|
|
(*iter)->RemoveObservers(vtkCommand::EndInteractionEvent);
|
|
vtkHandleWidget * w = (*iter);
|
|
this->Seeds->erase( iter );
|
|
w->Delete();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
vtkSeedWidget::~vtkSeedWidget()
|
|
{
|
|
// Loop over all seeds releasing their observers and deleting them
|
|
while( !this->Seeds->empty() )
|
|
{
|
|
this->DeleteSeed(static_cast<int>(this->Seeds->size())-1);
|
|
}
|
|
delete this->Seeds;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
vtkHandleWidget * vtkSeedWidget::GetSeed(int i)
|
|
{
|
|
if( this->Seeds->size() <= static_cast< size_t >(i) )
|
|
{
|
|
return NULL;
|
|
}
|
|
vtkSeedListIterator iter = this->Seeds->begin();
|
|
std::advance(iter,i);
|
|
return *iter;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void vtkSeedWidget::CreateDefaultRepresentation()
|
|
{
|
|
if ( ! this->WidgetRep )
|
|
{
|
|
this->WidgetRep = vtkSeedRepresentation::New();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void vtkSeedWidget::SetEnabled(int enabling)
|
|
{
|
|
this->Superclass::SetEnabled( enabling );
|
|
|
|
vtkSeedListIterator iter;
|
|
for ( iter = this->Seeds->begin(); iter != this->Seeds->end(); ++iter )
|
|
{
|
|
(*iter)->SetEnabled( enabling );
|
|
}
|
|
|
|
if ( !enabling )
|
|
{
|
|
this->RequestCursorShape( VTK_CURSOR_DEFAULT );
|
|
this->WidgetState = vtkSeedWidget::Start;
|
|
}
|
|
|
|
this->Render();
|
|
}
|
|
|
|
// The following methods are the callbacks that the seed widget responds to.
|
|
//-------------------------------------------------------------------------
|
|
void vtkSeedWidget::AddPointAction(vtkAbstractWidget *w)
|
|
{
|
|
vtkSeedWidget *self = reinterpret_cast<vtkSeedWidget*>(w);
|
|
|
|
// Need to distinguish between placing handles and manipulating handles
|
|
if ( self->WidgetState == vtkSeedWidget::MovingSeed )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// compute some info we need for all cases
|
|
int X = self->Interactor->GetEventPosition()[0];
|
|
int Y = self->Interactor->GetEventPosition()[1];
|
|
|
|
// When a seed is placed, a new handle widget must be created and enabled.
|
|
int state = self->WidgetRep->ComputeInteractionState(X,Y);
|
|
if ( state == vtkSeedRepresentation::NearSeed )
|
|
{
|
|
self->WidgetState = vtkSeedWidget::MovingSeed;
|
|
|
|
// Invoke an event on ourself for the handles
|
|
self->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL);
|
|
self->Superclass::StartInteraction();
|
|
self->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
|
|
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
|
self->Render();
|
|
}
|
|
|
|
else if ( self->WidgetState != vtkSeedWidget::PlacedSeeds)
|
|
{
|
|
// we are placing a new seed. Just make sure we aren't in a mode which
|
|
// dictates we've placed all seeds.
|
|
|
|
self->WidgetState = vtkSeedWidget::PlacingSeeds;
|
|
double e[3]; e[2]=0.0;
|
|
e[0] = static_cast<double>(X);
|
|
e[1] = static_cast<double>(Y);
|
|
|
|
vtkSeedRepresentation *rep =
|
|
reinterpret_cast<vtkSeedRepresentation*>(self->WidgetRep);
|
|
// if the handle representation is constrained, check to see if
|
|
// the position follows the constraint.
|
|
if ( !rep->GetHandleRepresentation()->CheckConstraint(
|
|
self->GetCurrentRenderer(), e ) )
|
|
{
|
|
return ;
|
|
}
|
|
int currentHandleNumber = rep->CreateHandle(e);
|
|
vtkHandleWidget *currentHandle = self->CreateNewHandle();
|
|
rep->SetSeedDisplayPosition(currentHandleNumber,e);
|
|
currentHandle->SetEnabled(1);
|
|
self->InvokeEvent(vtkCommand::PlacePointEvent,&(currentHandleNumber));
|
|
self->InvokeEvent(vtkCommand::InteractionEvent,&(currentHandleNumber));
|
|
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
|
self->Render();
|
|
}
|
|
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void vtkSeedWidget::CompletedAction(vtkAbstractWidget *w)
|
|
{
|
|
vtkSeedWidget *self = reinterpret_cast<vtkSeedWidget*>(w);
|
|
|
|
// Do something only if we are in the middle of placing the seeds
|
|
if ( self->WidgetState == vtkSeedWidget::PlacingSeeds )
|
|
{
|
|
self->CompleteInteraction();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void vtkSeedWidget::CompleteInteraction()
|
|
{
|
|
this->WidgetState = vtkSeedWidget::PlacedSeeds;
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->Defining = 0;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void vtkSeedWidget::RestartInteraction()
|
|
{
|
|
this->WidgetState = vtkSeedWidget::Start;
|
|
this->Defining = 1;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void vtkSeedWidget::MoveAction(vtkAbstractWidget *w)
|
|
{
|
|
vtkSeedWidget *self = reinterpret_cast<vtkSeedWidget*>(w);
|
|
|
|
// Do nothing if outside
|
|
if ( self->WidgetState == vtkSeedWidget::Start )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// else we are moving a seed
|
|
|
|
self->InvokeEvent(vtkCommand::MouseMoveEvent, NULL);
|
|
|
|
// set the cursor shape to a hand if we are near a seed.
|
|
int X = self->Interactor->GetEventPosition()[0];
|
|
int Y = self->Interactor->GetEventPosition()[1];
|
|
int state = self->WidgetRep->ComputeInteractionState(X,Y);
|
|
|
|
// Change the cursor shape to a hand and invoke an interaction event if we
|
|
// are near the seed
|
|
if (state == vtkSeedRepresentation::NearSeed)
|
|
{
|
|
self->RequestCursorShape( VTK_CURSOR_HAND );
|
|
|
|
vtkSeedRepresentation *rep = static_cast<
|
|
vtkSeedRepresentation * >(self->WidgetRep);
|
|
int seedIdx = rep->GetActiveHandle();
|
|
self->InvokeEvent( vtkCommand::InteractionEvent, &seedIdx );
|
|
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
|
}
|
|
else
|
|
{
|
|
self->RequestCursorShape( VTK_CURSOR_DEFAULT );
|
|
}
|
|
|
|
self->Render();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void vtkSeedWidget::EndSelectAction(vtkAbstractWidget *w)
|
|
{
|
|
vtkSeedWidget *self = reinterpret_cast<vtkSeedWidget*>(w);
|
|
|
|
// Do nothing if outside
|
|
if ( self->WidgetState != vtkSeedWidget::MovingSeed )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Revert back to the mode we were in prior to selection.
|
|
self->WidgetState = self->Defining ?
|
|
vtkSeedWidget::PlacingSeeds : vtkSeedWidget::PlacedSeeds;
|
|
|
|
// Invoke event for seed handle
|
|
self->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL);
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
|
self->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
|
|
self->Superclass::EndInteraction();
|
|
self->Render();
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
void vtkSeedWidget::DeleteAction(vtkAbstractWidget *w)
|
|
{
|
|
vtkSeedWidget *self = reinterpret_cast<vtkSeedWidget*>(w);
|
|
|
|
// Do nothing if outside
|
|
if ( self->WidgetState != vtkSeedWidget::PlacingSeeds )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Remove last seed
|
|
vtkSeedRepresentation *rep =
|
|
reinterpret_cast<vtkSeedRepresentation*>(self->WidgetRep);
|
|
int removeId = rep->GetActiveHandle();
|
|
if ( removeId != -1 )
|
|
{
|
|
rep->RemoveActiveHandle();
|
|
}
|
|
else
|
|
{
|
|
rep->RemoveLastHandle();
|
|
removeId = static_cast<int>(self->Seeds->size())-1;
|
|
}
|
|
self->DeleteSeed(removeId);
|
|
// Got this event, abort processing if it
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
|
self->Render();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void vtkSeedWidget::SetProcessEvents(int pe)
|
|
{
|
|
this->Superclass::SetProcessEvents(pe);
|
|
|
|
vtkSeedListIterator iter = this->Seeds->begin();
|
|
for (; iter != this->Seeds->end(); ++iter )
|
|
{
|
|
(*iter)->SetProcessEvents(pe);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void vtkSeedWidget::SetInteractor( vtkRenderWindowInteractor *rwi )
|
|
{
|
|
this->Superclass::SetInteractor(rwi);
|
|
vtkSeedListIterator iter = this->Seeds->begin();
|
|
for (; iter != this->Seeds->end(); ++iter )
|
|
{
|
|
(*iter)->SetInteractor(rwi);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void vtkSeedWidget::SetCurrentRenderer( vtkRenderer *ren )
|
|
{
|
|
this->Superclass::SetCurrentRenderer(ren);
|
|
vtkSeedListIterator iter = this->Seeds->begin();
|
|
for (; iter != this->Seeds->end(); ++iter )
|
|
{
|
|
if (!ren)
|
|
{
|
|
// Disable widget if its being removed from the the renderer
|
|
(*iter)->EnabledOff();
|
|
}
|
|
(*iter)->SetCurrentRenderer(ren);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Programmatically create a new handle.
|
|
vtkHandleWidget * vtkSeedWidget::CreateNewHandle()
|
|
{
|
|
vtkSeedRepresentation *rep =
|
|
vtkSeedRepresentation::SafeDownCast(this->WidgetRep);
|
|
if (!rep)
|
|
{
|
|
vtkErrorMacro( << "Please set, or create a default seed representation "
|
|
<< "before adding requesting creation of a new handle." );
|
|
return NULL;
|
|
}
|
|
|
|
// Create the handle widget or reuse an old one
|
|
int currentHandleNumber = static_cast<int>(this->Seeds->size());
|
|
vtkHandleWidget *widget = vtkHandleWidget::New();
|
|
|
|
// Configure the handle widget
|
|
widget->SetParent(this);
|
|
widget->SetInteractor(this->Interactor);
|
|
vtkHandleRepresentation *handleRep = rep->GetHandleRepresentation(currentHandleNumber);
|
|
if (!handleRep)
|
|
{
|
|
widget->Delete();
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
handleRep->SetRenderer(this->CurrentRenderer);
|
|
widget->SetRepresentation(handleRep);
|
|
|
|
// Now place the widget into the list of handle widgets (if not already there)
|
|
this->Seeds->push_back( widget );
|
|
return widget;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void vtkSeedWidget::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
//Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << indent << "WidgetState: " << this->WidgetState << endl;
|
|
}
|