You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1075 lines
29 KiB
1075 lines
29 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkLineWidget.cxx,v $
|
|
|
|
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 "vtkLineWidget.h"
|
|
|
|
#include "vtkActor.h"
|
|
#include "vtkAssemblyNode.h"
|
|
#include "vtkAssemblyPath.h"
|
|
#include "vtkCallbackCommand.h"
|
|
#include "vtkCamera.h"
|
|
#include "vtkCellPicker.h"
|
|
#include "vtkCommand.h"
|
|
#include "vtkDoubleArray.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPlanes.h"
|
|
#include "vtkPointWidget.h"
|
|
#include "vtkPolyData.h"
|
|
#include "vtkPolyDataMapper.h"
|
|
#include "vtkProperty.h"
|
|
#include "vtkRenderWindow.h"
|
|
#include "vtkRenderWindowInteractor.h"
|
|
#include "vtkRenderer.h"
|
|
#include "vtkSphereSource.h"
|
|
|
|
vtkCxxRevisionMacro(vtkLineWidget, "$Revision: 1.1 $");
|
|
vtkStandardNewMacro(vtkLineWidget);
|
|
|
|
// This class is used to coordinate the interaction between the point widget
|
|
// at the center of the line and the line widget. When the line is selected
|
|
// (as compared to the handles), a point widget appears at the selection
|
|
// point, which can be manipulated in the usual way.
|
|
class vtkPWCallback : public vtkCommand
|
|
{
|
|
public:
|
|
static vtkPWCallback *New()
|
|
{ return new vtkPWCallback; }
|
|
virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long, void*)
|
|
{
|
|
double x[3];
|
|
this->PointWidget->GetPosition(x);
|
|
this->LineWidget->SetLinePosition(x);
|
|
}
|
|
vtkPWCallback():LineWidget(0),PointWidget(0) {}
|
|
vtkLineWidget *LineWidget;
|
|
vtkPointWidget *PointWidget;
|
|
};
|
|
|
|
// This class is used to coordinate the interaction between the point widget
|
|
// (point 1) and the line widget.
|
|
class vtkPW1Callback : public vtkCommand
|
|
{
|
|
public:
|
|
static vtkPW1Callback *New()
|
|
{ return new vtkPW1Callback; }
|
|
virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long, void*)
|
|
{
|
|
double x[3];
|
|
this->PointWidget->GetPosition(x);
|
|
this->LineWidget->SetPoint1(x);
|
|
}
|
|
vtkPW1Callback():LineWidget(0),PointWidget(0) {}
|
|
vtkLineWidget *LineWidget;
|
|
vtkPointWidget *PointWidget;
|
|
};
|
|
|
|
// This class is used to coordinate the interaction between the point widget
|
|
// (point 2) and the line widget.
|
|
class vtkPW2Callback : public vtkCommand
|
|
{
|
|
public:
|
|
static vtkPW2Callback *New()
|
|
{ return new vtkPW2Callback; }
|
|
virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long, void*)
|
|
{
|
|
double x[3];
|
|
this->PointWidget->GetPosition(x);
|
|
this->LineWidget->SetPoint2(x);
|
|
}
|
|
vtkPW2Callback():LineWidget(0),PointWidget(0) {}
|
|
vtkLineWidget *LineWidget;
|
|
vtkPointWidget *PointWidget;
|
|
};
|
|
|
|
// Begin the definition of the vtkLineWidget methods
|
|
//
|
|
vtkLineWidget::vtkLineWidget()
|
|
{
|
|
this->State = vtkLineWidget::Start;
|
|
this->EventCallbackCommand->SetCallback(vtkLineWidget::ProcessEvents);
|
|
|
|
this->Align = vtkLineWidget::XAxis;
|
|
|
|
//Build the representation of the widget
|
|
int i;
|
|
// Represent the line
|
|
this->LineSource = vtkLineSource::New();
|
|
this->LineSource->SetResolution(5);
|
|
this->LineMapper = vtkPolyDataMapper::New();
|
|
this->LineMapper->SetInput(this->LineSource->GetOutput());
|
|
this->LineActor = vtkActor::New();
|
|
this->LineActor->SetMapper(this->LineMapper);
|
|
|
|
// Create the handles
|
|
this->Handle = new vtkActor* [2];
|
|
this->HandleMapper = new vtkPolyDataMapper* [2];
|
|
this->HandleGeometry = new vtkSphereSource* [2];
|
|
for (i=0; i<2; i++)
|
|
{
|
|
this->HandleGeometry[i] = vtkSphereSource::New();
|
|
this->HandleGeometry[i]->SetThetaResolution(16);
|
|
this->HandleGeometry[i]->SetPhiResolution(8);
|
|
this->HandleMapper[i] = vtkPolyDataMapper::New();
|
|
this->HandleMapper[i]->SetInput(this->HandleGeometry[i]->GetOutput());
|
|
this->Handle[i] = vtkActor::New();
|
|
this->Handle[i]->SetMapper(this->HandleMapper[i]);
|
|
}
|
|
|
|
// Define the point coordinates
|
|
double bounds[6];
|
|
bounds[0] = -0.5;
|
|
bounds[1] = 0.5;
|
|
bounds[2] = -0.5;
|
|
bounds[3] = 0.5;
|
|
bounds[4] = -0.5;
|
|
bounds[5] = 0.5;
|
|
this->PlaceFactor = 1.0; //overload parent's value
|
|
|
|
// Initial creation of the widget, serves to initialize it
|
|
this->PlaceWidget(bounds);
|
|
this->ClampToBounds = 0;
|
|
|
|
//Manage the picking stuff
|
|
this->HandlePicker = vtkCellPicker::New();
|
|
this->HandlePicker->SetTolerance(0.001);
|
|
for (i=0; i<2; i++)
|
|
{
|
|
this->HandlePicker->AddPickList(this->Handle[i]);
|
|
}
|
|
this->HandlePicker->PickFromListOn();
|
|
|
|
this->LinePicker = vtkCellPicker::New();
|
|
this->LinePicker->SetTolerance(0.005); //need some fluff
|
|
this->LinePicker->AddPickList(this->LineActor);
|
|
this->LinePicker->PickFromListOn();
|
|
|
|
this->CurrentHandle = NULL;
|
|
|
|
// Set up the initial properties
|
|
this->CreateDefaultProperties();
|
|
|
|
// Create the point widgets and associated callbacks
|
|
this->PointWidget = vtkPointWidget::New();
|
|
this->PointWidget->AllOff();
|
|
this->PointWidget->SetHotSpotSize(0.5);
|
|
|
|
this->PointWidget1 = vtkPointWidget::New();
|
|
this->PointWidget1->AllOff();
|
|
this->PointWidget1->SetHotSpotSize(0.5);
|
|
|
|
this->PointWidget2 = vtkPointWidget::New();
|
|
this->PointWidget2->AllOff();
|
|
this->PointWidget2->SetHotSpotSize(0.5);
|
|
|
|
this->PWCallback = vtkPWCallback::New();
|
|
this->PWCallback->LineWidget = this;
|
|
this->PWCallback->PointWidget = this->PointWidget;
|
|
this->PW1Callback = vtkPW1Callback::New();
|
|
this->PW1Callback->LineWidget = this;
|
|
this->PW1Callback->PointWidget = this->PointWidget1;
|
|
this->PW2Callback = vtkPW2Callback::New();
|
|
this->PW2Callback->LineWidget = this;
|
|
this->PW2Callback->PointWidget = this->PointWidget2;
|
|
|
|
// Very tricky, the point widgets watch for their own
|
|
// interaction events.
|
|
this->PointWidget->AddObserver(vtkCommand::InteractionEvent,
|
|
this->PWCallback, 0.0);
|
|
this->PointWidget1->AddObserver(vtkCommand::InteractionEvent,
|
|
this->PW1Callback, 0.0);
|
|
this->PointWidget2->AddObserver(vtkCommand::InteractionEvent,
|
|
this->PW2Callback, 0.0);
|
|
this->CurrentPointWidget = NULL;
|
|
}
|
|
|
|
vtkLineWidget::~vtkLineWidget()
|
|
{
|
|
this->LineActor->Delete();
|
|
this->LineMapper->Delete();
|
|
this->LineSource->Delete();
|
|
|
|
for (int i=0; i<2; i++)
|
|
{
|
|
this->HandleGeometry[i]->Delete();
|
|
this->HandleMapper[i]->Delete();
|
|
this->Handle[i]->Delete();
|
|
}
|
|
delete [] this->Handle;
|
|
delete [] this->HandleMapper;
|
|
delete [] this->HandleGeometry;
|
|
|
|
this->HandlePicker->Delete();
|
|
this->LinePicker->Delete();
|
|
|
|
this->HandleProperty->Delete();
|
|
this->SelectedHandleProperty->Delete();
|
|
this->LineProperty->Delete();
|
|
this->SelectedLineProperty->Delete();
|
|
|
|
this->PointWidget->RemoveObserver(this->PWCallback);
|
|
this->PointWidget1->RemoveObserver(this->PW1Callback);
|
|
this->PointWidget2->RemoveObserver(this->PW2Callback);
|
|
this->PointWidget->Delete();
|
|
this->PointWidget1->Delete();
|
|
this->PointWidget2->Delete();
|
|
this->PWCallback->Delete();
|
|
this->PW1Callback->Delete();
|
|
this->PW2Callback->Delete();
|
|
}
|
|
|
|
void vtkLineWidget::SetEnabled(int enabling)
|
|
{
|
|
if ( ! this->Interactor )
|
|
{
|
|
vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget");
|
|
return;
|
|
}
|
|
|
|
if ( enabling ) //-----------------------------------------------------------
|
|
{
|
|
vtkDebugMacro(<<"Enabling line widget");
|
|
|
|
if ( this->Enabled ) //already enabled, just return
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( ! this->CurrentRenderer )
|
|
{
|
|
this->SetCurrentRenderer(
|
|
this->Interactor->FindPokedRenderer(
|
|
this->Interactor->GetLastEventPosition()[0],
|
|
this->Interactor->GetLastEventPosition()[1]));
|
|
if (this->CurrentRenderer == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
this->PointWidget->SetCurrentRenderer(this->CurrentRenderer);
|
|
this->PointWidget1->SetCurrentRenderer(this->CurrentRenderer);
|
|
this->PointWidget2->SetCurrentRenderer(this->CurrentRenderer);
|
|
|
|
this->Enabled = 1;
|
|
|
|
// listen for the following events
|
|
vtkRenderWindowInteractor *i = this->Interactor;
|
|
i->AddObserver(vtkCommand::MouseMoveEvent,
|
|
this->EventCallbackCommand, this->Priority);
|
|
i->AddObserver(vtkCommand::LeftButtonPressEvent,
|
|
this->EventCallbackCommand, this->Priority);
|
|
i->AddObserver(vtkCommand::LeftButtonReleaseEvent,
|
|
this->EventCallbackCommand, this->Priority);
|
|
i->AddObserver(vtkCommand::MiddleButtonPressEvent,
|
|
this->EventCallbackCommand, this->Priority);
|
|
i->AddObserver(vtkCommand::MiddleButtonReleaseEvent,
|
|
this->EventCallbackCommand, this->Priority);
|
|
i->AddObserver(vtkCommand::RightButtonPressEvent,
|
|
this->EventCallbackCommand, this->Priority);
|
|
i->AddObserver(vtkCommand::RightButtonReleaseEvent,
|
|
this->EventCallbackCommand, this->Priority);
|
|
|
|
// Add the line
|
|
this->CurrentRenderer->AddActor(this->LineActor);
|
|
this->LineActor->SetProperty(this->LineProperty);
|
|
|
|
// turn on the handles
|
|
for (int j=0; j<2; j++)
|
|
{
|
|
this->CurrentRenderer->AddActor(this->Handle[j]);
|
|
this->Handle[j]->SetProperty(this->HandleProperty);
|
|
}
|
|
|
|
this->BuildRepresentation();
|
|
this->SizeHandles();
|
|
|
|
this->InvokeEvent(vtkCommand::EnableEvent,NULL);
|
|
}
|
|
|
|
else //disabling----------------------------------------------------------
|
|
{
|
|
vtkDebugMacro(<<"Disabling line widget");
|
|
|
|
if ( ! this->Enabled ) //already disabled, just return
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->Enabled = 0;
|
|
|
|
// don't listen for events any more
|
|
this->Interactor->RemoveObserver(this->EventCallbackCommand);
|
|
|
|
// turn off the line
|
|
this->CurrentRenderer->RemoveActor(this->LineActor);
|
|
|
|
// turn off the handles
|
|
for (int i=0; i<2; i++)
|
|
{
|
|
this->CurrentRenderer->RemoveActor(this->Handle[i]);
|
|
}
|
|
|
|
if (this->CurrentPointWidget)
|
|
{
|
|
this->CurrentPointWidget->EnabledOff();
|
|
}
|
|
|
|
this->CurrentHandle = NULL;
|
|
this->InvokeEvent(vtkCommand::DisableEvent,NULL);
|
|
this->SetCurrentRenderer(NULL);
|
|
}
|
|
|
|
this->Interactor->Render();
|
|
}
|
|
|
|
void vtkLineWidget::ProcessEvents(vtkObject* vtkNotUsed(object),
|
|
unsigned long event,
|
|
void* clientdata,
|
|
void* vtkNotUsed(calldata))
|
|
{
|
|
vtkLineWidget* self = reinterpret_cast<vtkLineWidget *>( clientdata );
|
|
|
|
//okay, let's do the right thing
|
|
switch(event)
|
|
{
|
|
case vtkCommand::LeftButtonPressEvent:
|
|
self->OnLeftButtonDown();
|
|
break;
|
|
case vtkCommand::LeftButtonReleaseEvent:
|
|
self->OnLeftButtonUp();
|
|
break;
|
|
case vtkCommand::MiddleButtonPressEvent:
|
|
self->OnMiddleButtonDown();
|
|
break;
|
|
case vtkCommand::MiddleButtonReleaseEvent:
|
|
self->OnMiddleButtonUp();
|
|
break;
|
|
case vtkCommand::RightButtonPressEvent:
|
|
self->OnRightButtonDown();
|
|
break;
|
|
case vtkCommand::RightButtonReleaseEvent:
|
|
self->OnRightButtonUp();
|
|
break;
|
|
case vtkCommand::MouseMoveEvent:
|
|
self->OnMouseMove();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void vtkLineWidget::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
if ( this->HandleProperty )
|
|
{
|
|
os << indent << "Handle Property: " << this->HandleProperty << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "Handle Property: (none)\n";
|
|
}
|
|
if ( this->SelectedHandleProperty )
|
|
{
|
|
os << indent << "Selected Handle Property: "
|
|
<< this->SelectedHandleProperty << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "Selected Handle Property: (none)\n";
|
|
}
|
|
|
|
if ( this->LineProperty )
|
|
{
|
|
os << indent << "Line Property: " << this->LineProperty << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "Line Property: (none)\n";
|
|
}
|
|
if ( this->SelectedLineProperty )
|
|
{
|
|
os << indent << "Selected Line Property: "
|
|
<< this->SelectedLineProperty << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "Selected Line Property: (none)\n";
|
|
}
|
|
|
|
os << indent << "Constrain To Bounds: "
|
|
<< (this->ClampToBounds ? "On\n" : "Off\n");
|
|
|
|
os << indent << "Align with: ";
|
|
switch ( this->Align )
|
|
{
|
|
case XAxis:
|
|
os << "X Axis";
|
|
break;
|
|
case YAxis:
|
|
os << "Y Axis";
|
|
break;
|
|
case ZAxis:
|
|
os << "Z Axis";
|
|
break;
|
|
default:
|
|
os << "None";
|
|
}
|
|
int res = this->LineSource->GetResolution();
|
|
double *pt1 = this->LineSource->GetPoint1();
|
|
double *pt2 = this->LineSource->GetPoint2();
|
|
|
|
os << indent << "Resolution: " << res << "\n";
|
|
os << indent << "Point 1: (" << pt1[0] << ", "
|
|
<< pt1[1] << ", "
|
|
<< pt1[2] << ")\n";
|
|
os << indent << "Point 2: (" << pt2[0] << ", "
|
|
<< pt2[1] << ", "
|
|
<< pt2[2] << ")\n";
|
|
}
|
|
|
|
void vtkLineWidget::BuildRepresentation()
|
|
{
|
|
//int res = this->LineSource->GetResolution();
|
|
double *pt1 = this->LineSource->GetPoint1();
|
|
double *pt2 = this->LineSource->GetPoint2();
|
|
|
|
this->HandleGeometry[0]->SetCenter(pt1);
|
|
this->HandleGeometry[1]->SetCenter(pt2);
|
|
}
|
|
|
|
void vtkLineWidget::SizeHandles()
|
|
{
|
|
double radius = this->vtk3DWidget::SizeHandles(1.0);
|
|
this->HandleGeometry[0]->SetRadius(radius);
|
|
this->HandleGeometry[1]->SetRadius(radius);
|
|
}
|
|
|
|
int vtkLineWidget::HighlightHandle(vtkProp *prop)
|
|
{
|
|
// first unhighlight anything picked
|
|
if ( this->CurrentHandle )
|
|
{
|
|
this->CurrentHandle->SetProperty(this->HandleProperty);
|
|
}
|
|
|
|
// set the current handle
|
|
this->CurrentHandle = (vtkActor *)prop;
|
|
|
|
// find the current handle
|
|
if ( this->CurrentHandle )
|
|
{
|
|
this->ValidPick = 1;
|
|
this->HandlePicker->GetPickPosition(this->LastPickPosition);
|
|
this->CurrentHandle->SetProperty(this->SelectedHandleProperty);
|
|
return (this->CurrentHandle == this->Handle[0] ? 0 : 1);
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int vtkLineWidget::ForwardEvent(unsigned long event)
|
|
{
|
|
if ( ! this->CurrentPointWidget )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
this->CurrentPointWidget->ProcessEvents(this,event,
|
|
this->CurrentPointWidget,NULL);
|
|
|
|
return 1;
|
|
}
|
|
|
|
// assumed current handle is set
|
|
void vtkLineWidget::EnablePointWidget()
|
|
{
|
|
// Set up the point widgets
|
|
double x[3];
|
|
if ( this->CurrentHandle ) //picking the handles
|
|
{
|
|
if ( this->CurrentHandle == this->Handle[0] )
|
|
{
|
|
this->CurrentPointWidget = this->PointWidget1;
|
|
this->LineSource->GetPoint1(x);
|
|
}
|
|
else
|
|
{
|
|
this->CurrentPointWidget = this->PointWidget2;
|
|
this->LineSource->GetPoint2(x);
|
|
}
|
|
}
|
|
else //picking the line
|
|
{
|
|
this->CurrentPointWidget = this->PointWidget;
|
|
this->LinePicker->GetPickPosition(x);
|
|
this->LastPosition[0] = x[0];
|
|
this->LastPosition[1] = x[1];
|
|
this->LastPosition[2] = x[2];
|
|
}
|
|
|
|
double bounds[6];
|
|
for (int i=0; i<3; i++)
|
|
{
|
|
bounds[2*i] = x[i] - 0.1*this->InitialLength;
|
|
bounds[2*i+1] = x[i] + 0.1*this->InitialLength;
|
|
}
|
|
|
|
// Note: translation mode is disabled and enabled to control
|
|
// the proper positioning of the bounding box.
|
|
this->CurrentPointWidget->SetInteractor(this->Interactor);
|
|
this->CurrentPointWidget->TranslationModeOff();
|
|
this->CurrentPointWidget->SetPlaceFactor(1.0);
|
|
this->CurrentPointWidget->PlaceWidget(bounds);
|
|
this->CurrentPointWidget->TranslationModeOn();
|
|
this->CurrentPointWidget->SetPosition(x);
|
|
this->CurrentPointWidget->SetCurrentRenderer(this->CurrentRenderer);
|
|
this->CurrentPointWidget->On();
|
|
}
|
|
|
|
// assumed current handle is set
|
|
void vtkLineWidget::DisablePointWidget()
|
|
{
|
|
if (this->CurrentPointWidget)
|
|
{
|
|
this->CurrentPointWidget->Off();
|
|
}
|
|
this->CurrentPointWidget = NULL;
|
|
}
|
|
|
|
void vtkLineWidget::HighlightHandles(int highlight)
|
|
{
|
|
if ( highlight )
|
|
{
|
|
this->ValidPick = 1;
|
|
this->HandlePicker->GetPickPosition(this->LastPickPosition);
|
|
this->Handle[0]->SetProperty(this->SelectedHandleProperty);
|
|
this->Handle[1]->SetProperty(this->SelectedHandleProperty);
|
|
}
|
|
else
|
|
{
|
|
this->Handle[0]->SetProperty(this->HandleProperty);
|
|
this->Handle[1]->SetProperty(this->HandleProperty);
|
|
}
|
|
}
|
|
|
|
void vtkLineWidget::HighlightLine(int highlight)
|
|
{
|
|
if ( highlight )
|
|
{
|
|
this->ValidPick = 1;
|
|
this->LinePicker->GetPickPosition(this->LastPickPosition);
|
|
this->LineActor->SetProperty(this->SelectedLineProperty);
|
|
}
|
|
else
|
|
{
|
|
this->LineActor->SetProperty(this->LineProperty);
|
|
}
|
|
}
|
|
|
|
void vtkLineWidget::OnLeftButtonDown()
|
|
{
|
|
int forward=0;
|
|
|
|
int X = this->Interactor->GetEventPosition()[0];
|
|
int Y = this->Interactor->GetEventPosition()[1];
|
|
|
|
// Okay, make sure that the pick is in the current renderer
|
|
if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
|
|
{
|
|
this->State = vtkLineWidget::Outside;
|
|
return;
|
|
}
|
|
|
|
// Okay, we can process this. Try to pick handles first;
|
|
// if no handles picked, then try to pick the line.
|
|
vtkAssemblyPath *path;
|
|
this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer);
|
|
path = this->HandlePicker->GetPath();
|
|
if ( path != NULL )
|
|
{
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->StartInteraction();
|
|
this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
|
|
this->State = vtkLineWidget::MovingHandle;
|
|
this->HighlightHandle(path->GetFirstNode()->GetViewProp());
|
|
this->EnablePointWidget();
|
|
forward = this->ForwardEvent(vtkCommand::LeftButtonPressEvent);
|
|
}
|
|
else
|
|
{
|
|
this->LinePicker->Pick(X,Y,0.0,this->CurrentRenderer);
|
|
path = this->LinePicker->GetPath();
|
|
if ( path != NULL )
|
|
{
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->StartInteraction();
|
|
this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
|
|
this->State = vtkLineWidget::MovingLine;
|
|
this->HighlightLine(1);
|
|
this->EnablePointWidget();
|
|
forward = this->ForwardEvent(vtkCommand::LeftButtonPressEvent);
|
|
}
|
|
else
|
|
{
|
|
this->State = vtkLineWidget::Outside;
|
|
this->HighlightHandle(NULL);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( ! forward )
|
|
{
|
|
this->Interactor->Render();
|
|
}
|
|
}
|
|
|
|
void vtkLineWidget::OnLeftButtonUp()
|
|
{
|
|
if ( this->State == vtkLineWidget::Outside ||
|
|
this->State == vtkLineWidget::Start )
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->State = vtkLineWidget::Start;
|
|
this->HighlightHandle(NULL);
|
|
this->HighlightLine(0);
|
|
|
|
this->SizeHandles();
|
|
|
|
int forward = this->ForwardEvent(vtkCommand::LeftButtonReleaseEvent);
|
|
this->DisablePointWidget();
|
|
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->EndInteraction();
|
|
this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
|
|
if ( ! forward )
|
|
{
|
|
this->Interactor->Render();
|
|
}
|
|
}
|
|
|
|
void vtkLineWidget::OnMiddleButtonDown()
|
|
{
|
|
int forward=0;
|
|
|
|
int X = this->Interactor->GetEventPosition()[0];
|
|
int Y = this->Interactor->GetEventPosition()[1];
|
|
|
|
// Okay, make sure that the pick is in the current renderer
|
|
if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
|
|
{
|
|
this->State = vtkLineWidget::Outside;
|
|
return;
|
|
}
|
|
|
|
// Okay, we can process this. Try to pick handles first;
|
|
// if no handles picked, then pick the bounding box.
|
|
vtkAssemblyPath *path;
|
|
this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer);
|
|
path = this->HandlePicker->GetPath();
|
|
if ( path != NULL )
|
|
{
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->StartInteraction();
|
|
this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
|
|
this->State = vtkLineWidget::MovingLine;
|
|
this->HighlightHandles(1);
|
|
this->HighlightLine(1);
|
|
this->EnablePointWidget();
|
|
this->ForwardEvent(vtkCommand::LeftButtonPressEvent);
|
|
}
|
|
else
|
|
{
|
|
this->LinePicker->Pick(X,Y,0.0,this->CurrentRenderer);
|
|
path = this->LinePicker->GetPath();
|
|
if ( path != NULL )
|
|
{
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->StartInteraction();
|
|
this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
|
|
//The highlight methods set the LastPickPosition, so they are ordered
|
|
this->HighlightHandles(1);
|
|
this->HighlightLine(1);
|
|
this->State = vtkLineWidget::MovingLine;
|
|
this->EnablePointWidget();
|
|
this->ForwardEvent(vtkCommand::LeftButtonPressEvent);
|
|
}
|
|
else
|
|
{
|
|
this->State = vtkLineWidget::Outside;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( ! forward )
|
|
{
|
|
this->Interactor->Render();
|
|
}
|
|
}
|
|
|
|
void vtkLineWidget::OnMiddleButtonUp()
|
|
{
|
|
if ( this->State == vtkLineWidget::Outside ||
|
|
this->State == vtkLineWidget::Start )
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->State = vtkLineWidget::Start;
|
|
this->HighlightLine(0);
|
|
this->HighlightHandles(0);
|
|
|
|
this->SizeHandles();
|
|
|
|
int forward = this->ForwardEvent(vtkCommand::LeftButtonReleaseEvent);
|
|
this->DisablePointWidget();
|
|
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->EndInteraction();
|
|
this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
|
|
if ( ! forward )
|
|
{
|
|
this->Interactor->Render();
|
|
}
|
|
}
|
|
|
|
void vtkLineWidget::OnRightButtonDown()
|
|
{
|
|
int X = this->Interactor->GetEventPosition()[0];
|
|
int Y = this->Interactor->GetEventPosition()[1];
|
|
|
|
// Okay, make sure that the pick is in the current renderer
|
|
if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
|
|
{
|
|
this->State = vtkLineWidget::Outside;
|
|
return;
|
|
}
|
|
|
|
// Okay, we can process this. Try to pick handles first;
|
|
// if no handles picked, then pick the bounding box.
|
|
vtkAssemblyPath *path;
|
|
this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer);
|
|
path = this->HandlePicker->GetPath();
|
|
if ( path != NULL )
|
|
{
|
|
this->HighlightLine(1);
|
|
this->HighlightHandles(1);
|
|
this->State = vtkLineWidget::Scaling;
|
|
}
|
|
else
|
|
{
|
|
this->LinePicker->Pick(X,Y,0.0,this->CurrentRenderer);
|
|
path = this->LinePicker->GetPath();
|
|
if ( path != NULL )
|
|
{
|
|
this->HighlightHandles(1);
|
|
this->HighlightLine(1);
|
|
this->State = vtkLineWidget::Scaling;
|
|
}
|
|
else
|
|
{
|
|
this->State = vtkLineWidget::Outside;
|
|
this->HighlightLine(0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->StartInteraction();
|
|
this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
|
|
this->Interactor->Render();
|
|
}
|
|
|
|
void vtkLineWidget::OnRightButtonUp()
|
|
{
|
|
if ( this->State == vtkLineWidget::Outside ||
|
|
this->State == vtkLineWidget::Start )
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->State = vtkLineWidget::Start;
|
|
this->HighlightLine(0);
|
|
this->HighlightHandles(0);
|
|
|
|
this->SizeHandles();
|
|
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->EndInteraction();
|
|
this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
|
|
this->Interactor->Render();
|
|
}
|
|
|
|
void vtkLineWidget::OnMouseMove()
|
|
{
|
|
// See whether we're active
|
|
if ( this->State == vtkLineWidget::Outside ||
|
|
this->State == vtkLineWidget::Start )
|
|
{
|
|
return;
|
|
}
|
|
|
|
int X = this->Interactor->GetEventPosition()[0];
|
|
int Y = this->Interactor->GetEventPosition()[1];
|
|
|
|
// Do different things depending on state
|
|
// Calculations everybody does
|
|
double focalPoint[4], pickPoint[4], prevPickPoint[4];
|
|
double z;
|
|
|
|
vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
|
|
if ( ! camera )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Compute the two points defining the motion vector
|
|
this->ComputeWorldToDisplay(this->LastPickPosition[0],
|
|
this->LastPickPosition[1],
|
|
this->LastPickPosition[2], focalPoint);
|
|
z = focalPoint[2];
|
|
this->ComputeDisplayToWorld(
|
|
double(this->Interactor->GetLastEventPosition()[0]),
|
|
double(this->Interactor->GetLastEventPosition()[1]),
|
|
z, prevPickPoint);
|
|
this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
|
|
|
|
// Process the motion
|
|
int forward=0;
|
|
if ( this->State == vtkLineWidget::MovingHandle )
|
|
{
|
|
forward = this->ForwardEvent(vtkCommand::MouseMoveEvent);
|
|
}
|
|
else if ( this->State == vtkLineWidget::MovingLine )
|
|
{
|
|
forward = this->ForwardEvent(vtkCommand::MouseMoveEvent);
|
|
}
|
|
else if ( this->State == vtkLineWidget::Scaling )
|
|
{
|
|
this->Scale(prevPickPoint, pickPoint, X, Y);
|
|
}
|
|
|
|
// Interact, if desired
|
|
this->EventCallbackCommand->SetAbortFlag(1);
|
|
this->InvokeEvent(vtkCommand::InteractionEvent,NULL);
|
|
if ( ! forward )
|
|
{
|
|
this->Interactor->Render();
|
|
}
|
|
}
|
|
|
|
void vtkLineWidget::Scale(double *p1, double *p2, int vtkNotUsed(X), int Y)
|
|
{
|
|
//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];
|
|
|
|
//int res = this->LineSource->GetResolution();
|
|
double *pt1 = this->LineSource->GetPoint1();
|
|
double *pt2 = this->LineSource->GetPoint2();
|
|
|
|
double center[3];
|
|
center[0] = (pt1[0]+pt2[0]) / 2.0;
|
|
center[1] = (pt1[1]+pt2[1]) / 2.0;
|
|
center[2] = (pt1[2]+pt2[2]) / 2.0;
|
|
|
|
// Compute the scale factor
|
|
double sf =
|
|
vtkMath::Norm(v) / sqrt(vtkMath::Distance2BetweenPoints(pt1,pt2));
|
|
if ( Y > this->Interactor->GetLastEventPosition()[1] )
|
|
{
|
|
sf = 1.0 + sf;
|
|
}
|
|
else
|
|
{
|
|
sf = 1.0 - sf;
|
|
}
|
|
|
|
// Move the end points
|
|
double point1[3], point2[3];
|
|
for (int i=0; i<3; i++)
|
|
{
|
|
point1[i] = sf * (pt1[i] - center[i]) + center[i];
|
|
point2[i] = sf * (pt2[i] - center[i]) + center[i];
|
|
}
|
|
|
|
this->LineSource->SetPoint1(point1);
|
|
this->LineSource->SetPoint2(point2);
|
|
this->LineSource->Update();
|
|
|
|
this->BuildRepresentation();
|
|
}
|
|
|
|
void vtkLineWidget::CreateDefaultProperties()
|
|
{
|
|
// Handle properties
|
|
this->HandleProperty = vtkProperty::New();
|
|
this->HandleProperty->SetColor(1,1,1);
|
|
|
|
this->SelectedHandleProperty = vtkProperty::New();
|
|
this->SelectedHandleProperty->SetColor(1,0,0);
|
|
|
|
// Line properties
|
|
this->LineProperty = vtkProperty::New();
|
|
this->LineProperty->SetRepresentationToWireframe();
|
|
this->LineProperty->SetAmbient(1.0);
|
|
this->LineProperty->SetAmbientColor(1.0,1.0,1.0);
|
|
this->LineProperty->SetLineWidth(2.0);
|
|
|
|
this->SelectedLineProperty = vtkProperty::New();
|
|
this->SelectedLineProperty->SetRepresentationToWireframe();
|
|
this->SelectedLineProperty->SetAmbient(1.0);
|
|
this->SelectedLineProperty->SetAmbientColor(0.0,1.0,0.0);
|
|
this->SelectedLineProperty->SetLineWidth(2.0);
|
|
}
|
|
|
|
void vtkLineWidget::PlaceWidget(double bds[6])
|
|
{
|
|
int i;
|
|
double bounds[6], center[3];
|
|
|
|
this->AdjustBounds(bds, bounds, center);
|
|
|
|
if ( this->Align == vtkLineWidget::YAxis )
|
|
{
|
|
this->LineSource->SetPoint1(center[0],bounds[2],center[2]);
|
|
this->LineSource->SetPoint2(center[0],bounds[3],center[2]);
|
|
}
|
|
else if ( this->Align == vtkLineWidget::ZAxis )
|
|
{
|
|
this->LineSource->SetPoint1(center[0],center[1],bounds[4]);
|
|
this->LineSource->SetPoint2(center[0],center[1],bounds[5]);
|
|
}
|
|
else if ( this->Align == vtkLineWidget::XAxis )//default or x-aligned
|
|
{
|
|
this->LineSource->SetPoint1(bounds[0],center[1],center[2]);
|
|
this->LineSource->SetPoint2(bounds[1],center[1],center[2]);
|
|
}
|
|
this->LineSource->Update();
|
|
|
|
for (i=0; i<6; i++)
|
|
{
|
|
this->InitialBounds[i] = bounds[i];
|
|
}
|
|
this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
|
|
(bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
|
|
(bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
|
|
|
|
// Position the handles at the end of the lines
|
|
this->BuildRepresentation();
|
|
this->SizeHandles();
|
|
}
|
|
|
|
void vtkLineWidget::SetPoint1(double x, double y, double z)
|
|
{
|
|
double xyz[3];
|
|
xyz[0] = x; xyz[1] = y; xyz[2] = z;
|
|
|
|
if ( this->ClampToBounds )
|
|
{
|
|
this->ClampPosition(xyz);
|
|
this->PointWidget1->SetPosition(xyz);
|
|
}
|
|
this->LineSource->SetPoint1(xyz);
|
|
this->BuildRepresentation();
|
|
}
|
|
|
|
void vtkLineWidget::SetPoint2(double x, double y, double z)
|
|
{
|
|
double xyz[3];
|
|
xyz[0] = x; xyz[1] = y; xyz[2] = z;
|
|
|
|
if ( this->ClampToBounds )
|
|
{
|
|
this->ClampPosition(xyz);
|
|
this->PointWidget2->SetPosition(xyz);
|
|
}
|
|
this->LineSource->SetPoint2(xyz);
|
|
this->BuildRepresentation();
|
|
}
|
|
|
|
void vtkLineWidget::SetLinePosition(double x[3])
|
|
{
|
|
double p1[3], p2[3], v[3];
|
|
|
|
// vector of motion
|
|
v[0] = x[0] - this->LastPosition[0];
|
|
v[1] = x[1] - this->LastPosition[1];
|
|
v[2] = x[2] - this->LastPosition[2];
|
|
|
|
// update position
|
|
this->GetPoint1(p1);
|
|
this->GetPoint2(p2);
|
|
for (int i=0; i<3; i++)
|
|
{
|
|
p1[i] += v[i];
|
|
p2[i] += v[i];
|
|
}
|
|
|
|
// See whether we can move
|
|
if ( this->ClampToBounds && (!this->InBounds(p1) || !this->InBounds(p2)) )
|
|
{
|
|
this->PointWidget->SetPosition(this->LastPosition);
|
|
return;
|
|
}
|
|
|
|
this->SetPoint1(p1);
|
|
this->SetPoint2(p2);
|
|
|
|
// remember last position
|
|
this->LastPosition[0] = x[0];
|
|
this->LastPosition[1] = x[1];
|
|
this->LastPosition[2] = x[2];
|
|
}
|
|
|
|
|
|
void vtkLineWidget::ClampPosition(double x[3])
|
|
{
|
|
for (int i=0; i<3; i++)
|
|
{
|
|
if ( x[i] < this->InitialBounds[2*i] )
|
|
{
|
|
x[i] = this->InitialBounds[2*i];
|
|
}
|
|
if ( x[i] > this->InitialBounds[2*i+1] )
|
|
{
|
|
x[i] = this->InitialBounds[2*i+1];
|
|
}
|
|
}
|
|
}
|
|
|
|
int vtkLineWidget::InBounds(double x[3])
|
|
{
|
|
for (int i=0; i<3; i++)
|
|
{
|
|
if ( x[i] < this->InitialBounds[2*i] ||
|
|
x[i] > this->InitialBounds[2*i+1] )
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void vtkLineWidget::GetPolyData(vtkPolyData *pd)
|
|
{
|
|
pd->ShallowCopy(this->LineSource->GetOutput());
|
|
}
|
|
|