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.
415 lines
14 KiB
C++
415 lines
14 KiB
C++
|
2 weeks ago
|
/*=========================================================================
|
||
|
|
|
||
|
|
Program: Visualization Toolkit
|
||
|
|
Module: vtkLineWidget2.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 "vtkLineWidget2.h"
|
||
|
|
#include "vtkLineRepresentation.h"
|
||
|
|
#include "vtkPointHandleRepresentation3D.h"
|
||
|
|
#include "vtkHandleWidget.h"
|
||
|
|
#include "vtkCommand.h"
|
||
|
|
#include "vtkCallbackCommand.h"
|
||
|
|
#include "vtkRenderWindowInteractor.h"
|
||
|
|
#include "vtkObjectFactory.h"
|
||
|
|
#include "vtkWidgetEventTranslator.h"
|
||
|
|
#include "vtkWidgetCallbackMapper.h"
|
||
|
|
#include "vtkEvent.h"
|
||
|
|
#include "vtkWidgetEvent.h"
|
||
|
|
#include "vtkRenderWindow.h"
|
||
|
|
|
||
|
|
|
||
|
|
vtkStandardNewMacro(vtkLineWidget2);
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
vtkLineWidget2::vtkLineWidget2()
|
||
|
|
{
|
||
|
|
this->WidgetState = vtkLineWidget2::Start;
|
||
|
|
this->ManagesCursor = 1;
|
||
|
|
this->CurrentHandle = 0;
|
||
|
|
|
||
|
|
// The widgets for moving the end points. They observe this widget (i.e.,
|
||
|
|
// this widget is the parent to the handles).
|
||
|
|
this->Point1Widget = vtkHandleWidget::New();
|
||
|
|
this->Point1Widget->SetPriority(this->Priority-0.01);
|
||
|
|
this->Point1Widget->SetParent(this);
|
||
|
|
this->Point1Widget->ManagesCursorOff();
|
||
|
|
|
||
|
|
this->Point2Widget = vtkHandleWidget::New();
|
||
|
|
this->Point2Widget->SetPriority(this->Priority-0.01);
|
||
|
|
this->Point2Widget->SetParent(this);
|
||
|
|
this->Point2Widget->ManagesCursorOff();
|
||
|
|
|
||
|
|
this->LineHandle = vtkHandleWidget::New();
|
||
|
|
this->LineHandle->SetPriority(this->Priority-0.01);
|
||
|
|
this->LineHandle->SetParent(this);
|
||
|
|
this->LineHandle->ManagesCursorOff();
|
||
|
|
|
||
|
|
// Define widget events
|
||
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonPressEvent,
|
||
|
|
vtkWidgetEvent::Select,
|
||
|
|
this, vtkLineWidget2::SelectAction);
|
||
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonReleaseEvent,
|
||
|
|
vtkWidgetEvent::EndSelect,
|
||
|
|
this, vtkLineWidget2::EndSelectAction);
|
||
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::MiddleButtonPressEvent,
|
||
|
|
vtkWidgetEvent::Translate,
|
||
|
|
this, vtkLineWidget2::TranslateAction);
|
||
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::MiddleButtonReleaseEvent,
|
||
|
|
vtkWidgetEvent::EndTranslate,
|
||
|
|
this, vtkLineWidget2::EndSelectAction);
|
||
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::RightButtonPressEvent,
|
||
|
|
vtkWidgetEvent::Scale,
|
||
|
|
this, vtkLineWidget2::ScaleAction);
|
||
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::RightButtonReleaseEvent,
|
||
|
|
vtkWidgetEvent::EndScale,
|
||
|
|
this, vtkLineWidget2::EndSelectAction);
|
||
|
|
this->CallbackMapper->SetCallbackMethod(vtkCommand::MouseMoveEvent,
|
||
|
|
vtkWidgetEvent::Move,
|
||
|
|
this, vtkLineWidget2::MoveAction);
|
||
|
|
|
||
|
|
this->ActiveKeyCode = 0;
|
||
|
|
this->KeyEventCallbackCommand = vtkCallbackCommand::New();
|
||
|
|
this->KeyEventCallbackCommand->SetClientData(this);
|
||
|
|
this->KeyEventCallbackCommand->SetCallback(vtkLineWidget2::ProcessKeyEvents);
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
vtkLineWidget2::~vtkLineWidget2()
|
||
|
|
{
|
||
|
|
this->Point1Widget->Delete();
|
||
|
|
this->Point2Widget->Delete();
|
||
|
|
this->LineHandle->Delete();
|
||
|
|
this->KeyEventCallbackCommand->Delete();
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::SetEnabled(int enabling)
|
||
|
|
{
|
||
|
|
int enabled = this->Enabled;
|
||
|
|
|
||
|
|
// We do this step first because it sets the CurrentRenderer
|
||
|
|
this->Superclass::SetEnabled(enabling);
|
||
|
|
|
||
|
|
// We defer enabling the handles until the selection process begins
|
||
|
|
if ( enabling && !enabled )
|
||
|
|
{
|
||
|
|
// Don't actually turn these on until cursor is near the end points or the line.
|
||
|
|
this->CreateDefaultRepresentation();
|
||
|
|
this->Point1Widget->SetRepresentation(reinterpret_cast<vtkLineRepresentation*>
|
||
|
|
(this->WidgetRep)->GetPoint1Representation());
|
||
|
|
this->Point1Widget->SetInteractor(this->Interactor);
|
||
|
|
this->Point1Widget->GetRepresentation()->SetRenderer(this->CurrentRenderer);
|
||
|
|
|
||
|
|
this->Point2Widget->SetRepresentation(reinterpret_cast<vtkLineRepresentation*>
|
||
|
|
(this->WidgetRep)->GetPoint2Representation());
|
||
|
|
this->Point2Widget->SetInteractor(this->Interactor);
|
||
|
|
this->Point2Widget->GetRepresentation()->SetRenderer(this->CurrentRenderer);
|
||
|
|
|
||
|
|
this->LineHandle->SetRepresentation(reinterpret_cast<vtkLineRepresentation*>
|
||
|
|
(this->WidgetRep)->GetLineHandleRepresentation());
|
||
|
|
this->LineHandle->SetInteractor(this->Interactor);
|
||
|
|
this->LineHandle->GetRepresentation()->SetRenderer(this->CurrentRenderer);
|
||
|
|
|
||
|
|
if (this->Parent)
|
||
|
|
{
|
||
|
|
this->Parent->AddObserver(vtkCommand::KeyPressEvent,
|
||
|
|
this->KeyEventCallbackCommand,
|
||
|
|
this->Priority);
|
||
|
|
this->Parent->AddObserver(vtkCommand::KeyReleaseEvent,
|
||
|
|
this->KeyEventCallbackCommand,
|
||
|
|
this->Priority);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
this->Interactor->AddObserver(vtkCommand::KeyPressEvent,
|
||
|
|
this->KeyEventCallbackCommand,
|
||
|
|
this->Priority);
|
||
|
|
this->Interactor->AddObserver(vtkCommand::KeyReleaseEvent,
|
||
|
|
this->KeyEventCallbackCommand,
|
||
|
|
this->Priority);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if ( !enabling && enabled )
|
||
|
|
{
|
||
|
|
this->Point1Widget->SetEnabled(0);
|
||
|
|
this->Point2Widget->SetEnabled(0);
|
||
|
|
this->LineHandle->SetEnabled(0);
|
||
|
|
|
||
|
|
if (this->Parent)
|
||
|
|
{
|
||
|
|
this->Parent->RemoveObserver(this->KeyEventCallbackCommand);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
this->Interactor->RemoveObserver(this->KeyEventCallbackCommand);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::SelectAction(vtkAbstractWidget *w)
|
||
|
|
{
|
||
|
|
vtkLineWidget2 *self = reinterpret_cast<vtkLineWidget2*>(w);
|
||
|
|
if ( self->WidgetRep->GetInteractionState() == vtkLineRepresentation::Outside )
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the event position
|
||
|
|
int X = self->Interactor->GetEventPosition()[0];
|
||
|
|
int Y = self->Interactor->GetEventPosition()[1];
|
||
|
|
|
||
|
|
// We are definitely selected
|
||
|
|
self->WidgetState = vtkLineWidget2::Active;
|
||
|
|
self->GrabFocus(self->EventCallbackCommand);
|
||
|
|
double e[2];
|
||
|
|
e[0] = static_cast<double>(X);
|
||
|
|
e[1] = static_cast<double>(Y);
|
||
|
|
reinterpret_cast<vtkLineRepresentation*>(self->WidgetRep)->
|
||
|
|
StartWidgetInteraction(e);
|
||
|
|
self->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL); //for the handles
|
||
|
|
self->StartInteraction();
|
||
|
|
self->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
|
||
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::TranslateAction(vtkAbstractWidget *w)
|
||
|
|
{
|
||
|
|
vtkLineWidget2 *self = reinterpret_cast<vtkLineWidget2*>(w);
|
||
|
|
if ( self->WidgetRep->GetInteractionState() == vtkLineRepresentation::Outside )
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Modify the state, we are selected
|
||
|
|
int state = self->WidgetRep->GetInteractionState();
|
||
|
|
if ( state == vtkLineRepresentation::OnP1 )
|
||
|
|
{
|
||
|
|
reinterpret_cast<vtkLineRepresentation*>(self->WidgetRep)->
|
||
|
|
SetInteractionState(vtkLineRepresentation::TranslatingP1);
|
||
|
|
}
|
||
|
|
else if ( state == vtkLineRepresentation::OnP2 )
|
||
|
|
{
|
||
|
|
reinterpret_cast<vtkLineRepresentation*>(self->WidgetRep)->
|
||
|
|
SetInteractionState(vtkLineRepresentation::TranslatingP2);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
reinterpret_cast<vtkLineRepresentation*>(self->WidgetRep)->
|
||
|
|
SetInteractionState(vtkLineRepresentation::OnLine);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the event position
|
||
|
|
int X = self->Interactor->GetEventPosition()[0];
|
||
|
|
int Y = self->Interactor->GetEventPosition()[1];
|
||
|
|
|
||
|
|
// We are definitely selected
|
||
|
|
self->WidgetState = vtkLineWidget2::Active;
|
||
|
|
self->GrabFocus(self->EventCallbackCommand);
|
||
|
|
double eventPos[2];
|
||
|
|
eventPos[0] = static_cast<double>(X);
|
||
|
|
eventPos[1] = static_cast<double>(Y);
|
||
|
|
reinterpret_cast<vtkLineRepresentation*>(self->WidgetRep)->
|
||
|
|
StartWidgetInteraction(eventPos);
|
||
|
|
self->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL); //for the handles
|
||
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
||
|
|
self->StartInteraction();
|
||
|
|
self->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::ScaleAction(vtkAbstractWidget *w)
|
||
|
|
{
|
||
|
|
vtkLineWidget2 *self = reinterpret_cast<vtkLineWidget2*>(w);
|
||
|
|
if ( self->WidgetRep->GetInteractionState() == vtkLineRepresentation::Outside )
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
reinterpret_cast<vtkLineRepresentation*>(self->WidgetRep)->
|
||
|
|
SetInteractionState(vtkLineRepresentation::Scaling);
|
||
|
|
self->Interactor->Disable();
|
||
|
|
self->LineHandle->SetEnabled(0);
|
||
|
|
self->Interactor->Enable();
|
||
|
|
|
||
|
|
// Get the event position
|
||
|
|
int X = self->Interactor->GetEventPosition()[0];
|
||
|
|
int Y = self->Interactor->GetEventPosition()[1];
|
||
|
|
|
||
|
|
// We are definitely selected
|
||
|
|
self->WidgetState = vtkLineWidget2::Active;
|
||
|
|
self->GrabFocus(self->EventCallbackCommand);
|
||
|
|
double eventPos[2];
|
||
|
|
eventPos[0] = static_cast<double>(X);
|
||
|
|
eventPos[1] = static_cast<double>(Y);
|
||
|
|
reinterpret_cast<vtkLineRepresentation*>(self->WidgetRep)->
|
||
|
|
StartWidgetInteraction(eventPos);
|
||
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
||
|
|
self->StartInteraction();
|
||
|
|
self->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::MoveAction(vtkAbstractWidget *w)
|
||
|
|
{
|
||
|
|
vtkLineWidget2 *self = reinterpret_cast<vtkLineWidget2*>(w);
|
||
|
|
// compute some info we need for all cases
|
||
|
|
int X = self->Interactor->GetEventPosition()[0];
|
||
|
|
int Y = self->Interactor->GetEventPosition()[1];
|
||
|
|
|
||
|
|
// See whether we're active
|
||
|
|
if ( self->WidgetState == vtkLineWidget2::Start )
|
||
|
|
{
|
||
|
|
self->Interactor->Disable(); //avoid extra renders
|
||
|
|
self->Point1Widget->SetEnabled(0);
|
||
|
|
self->Point2Widget->SetEnabled(0);
|
||
|
|
self->LineHandle->SetEnabled(0);
|
||
|
|
|
||
|
|
int oldState = self->WidgetRep->GetInteractionState();
|
||
|
|
int state = self->WidgetRep->ComputeInteractionState(X,Y);
|
||
|
|
int changed;
|
||
|
|
// Determine if we are near the end points or the line
|
||
|
|
if ( state == vtkLineRepresentation::Outside )
|
||
|
|
{
|
||
|
|
changed = self->RequestCursorShape(VTK_CURSOR_DEFAULT);
|
||
|
|
}
|
||
|
|
else //must be near something
|
||
|
|
{
|
||
|
|
changed = self->RequestCursorShape(VTK_CURSOR_HAND);
|
||
|
|
if ( state == vtkLineRepresentation::OnP1 )
|
||
|
|
{
|
||
|
|
self->Point1Widget->SetEnabled(1);
|
||
|
|
}
|
||
|
|
else if ( state == vtkLineRepresentation::OnP2 )
|
||
|
|
{
|
||
|
|
self->Point2Widget->SetEnabled(1);
|
||
|
|
}
|
||
|
|
else //if ( state == vtkLineRepresentation::OnLine )
|
||
|
|
{
|
||
|
|
self->LineHandle->SetEnabled(1);
|
||
|
|
changed = 1; //movement along the line always needs render
|
||
|
|
}
|
||
|
|
}
|
||
|
|
self->Interactor->Enable(); //avoid extra renders
|
||
|
|
if ( changed || oldState != state )
|
||
|
|
{
|
||
|
|
self->Render();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else //if ( self->WidgetState == vtkLineWidget2::Active )
|
||
|
|
{
|
||
|
|
// moving something
|
||
|
|
double e[2];
|
||
|
|
e[0] = static_cast<double>(X);
|
||
|
|
e[1] = static_cast<double>(Y);
|
||
|
|
self->InvokeEvent(vtkCommand::MouseMoveEvent,NULL); //handles observe this
|
||
|
|
reinterpret_cast<vtkLineRepresentation*>(self->WidgetRep)->
|
||
|
|
WidgetInteraction(e);
|
||
|
|
self->InvokeEvent(vtkCommand::InteractionEvent,NULL);
|
||
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
||
|
|
self->Render();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::EndSelectAction(vtkAbstractWidget *w)
|
||
|
|
{
|
||
|
|
vtkLineWidget2 *self = reinterpret_cast<vtkLineWidget2*>(w);
|
||
|
|
if ( self->WidgetState == vtkLineWidget2::Start )
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Return state to not active
|
||
|
|
self->WidgetState = vtkLineWidget2::Start;
|
||
|
|
self->ReleaseFocus();
|
||
|
|
self->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL); //handles observe this
|
||
|
|
self->EventCallbackCommand->SetAbortFlag(1);
|
||
|
|
self->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
|
||
|
|
self->Superclass::EndInteraction();
|
||
|
|
self->Render();
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::CreateDefaultRepresentation()
|
||
|
|
{
|
||
|
|
if ( ! this->WidgetRep )
|
||
|
|
{
|
||
|
|
this->WidgetRep = vtkLineRepresentation::New();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::SetProcessEvents(int pe)
|
||
|
|
{
|
||
|
|
this->Superclass::SetProcessEvents(pe);
|
||
|
|
|
||
|
|
this->Point1Widget->SetProcessEvents(pe);
|
||
|
|
this->Point2Widget->SetProcessEvents(pe);
|
||
|
|
this->LineHandle->SetProcessEvents(pe);
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::ProcessKeyEvents(vtkObject* , unsigned long event,
|
||
|
|
void* clientdata, void* )
|
||
|
|
{
|
||
|
|
vtkLineWidget2 *self = static_cast<vtkLineWidget2*>(clientdata);
|
||
|
|
vtkRenderWindowInteractor *iren = self->GetInteractor();
|
||
|
|
switch (event)
|
||
|
|
{
|
||
|
|
case vtkCommand::KeyPressEvent:
|
||
|
|
if (self->ActiveKeyCode == 0)
|
||
|
|
{
|
||
|
|
self->ActiveKeyCode = iren->GetKeyCode();
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case vtkCommand::KeyReleaseEvent:
|
||
|
|
if (self->ActiveKeyCode == iren->GetKeyCode())
|
||
|
|
{
|
||
|
|
self->ActiveKeyCode = 0;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
vtkLineRepresentation *rep = vtkLineRepresentation::SafeDownCast(self->WidgetRep);
|
||
|
|
switch (self->ActiveKeyCode)
|
||
|
|
{
|
||
|
|
case 'x':
|
||
|
|
case 'X':
|
||
|
|
rep->SetRestrictFlag(vtkLineRepresentation::RestrictToX);
|
||
|
|
break;
|
||
|
|
case 'y':
|
||
|
|
case 'Y':
|
||
|
|
rep->SetRestrictFlag(vtkLineRepresentation::RestrictToY);
|
||
|
|
break;
|
||
|
|
case 'z':
|
||
|
|
case 'Z':
|
||
|
|
rep->SetRestrictFlag(vtkLineRepresentation::RestrictToZ);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
rep->SetRestrictFlag(vtkLineRepresentation::RestrictNone);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------------------------------------------------------------------------
|
||
|
|
void vtkLineWidget2::PrintSelf(ostream& os, vtkIndent indent)
|
||
|
|
{
|
||
|
|
this->Superclass::PrintSelf(os,indent);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|