mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
1858 lines
55 KiB
C++
1858 lines
55 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkControlPointsItem.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 "vtkAxis.h"
|
|
#include "vtkBrush.h"
|
|
#include "vtkCallbackCommand.h"
|
|
#include "vtkContext2D.h"
|
|
#include "vtkContextDevice2D.h"
|
|
#include "vtkContextKeyEvent.h"
|
|
#include "vtkContextMouseEvent.h"
|
|
#include "vtkContextScene.h"
|
|
#include "vtkControlPointsItem.h"
|
|
#include "vtkIdTypeArray.h"
|
|
#include "vtkNew.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPen.h"
|
|
#include "vtkPoints2D.h"
|
|
#include "vtkRenderWindowInteractor.h"
|
|
#include "vtkSmartPointer.h"
|
|
#include "vtkTransform2D.h"
|
|
#include "vtkVectorOperators.h"
|
|
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <limits>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkControlPointsItem::vtkControlPointsItem()
|
|
{
|
|
this->Pen->SetLineType(vtkPen::SOLID_LINE);
|
|
this->Pen->SetWidth(2.);
|
|
this->Pen->SetColor(140, 144, 125, 200);
|
|
this->Brush->SetColor(125, 135, 144, 200);
|
|
|
|
this->SelectedPointPen = vtkPen::New();
|
|
this->SelectedPointPen->SetWidth(2.);
|
|
// 98, 140, 178
|
|
this->SelectedPointPen->SetColor(63, 90, 115, 200);
|
|
//this->SelectedPointPen->SetColor(98, 140, 178, 200);
|
|
this->SelectedPointBrush = vtkBrush::New();
|
|
this->SelectedPointBrush->SetColor(58, 121, 178, 200);
|
|
|
|
this->Selection = vtkIdTypeArray::New();
|
|
this->CurrentPoint = -1;
|
|
|
|
this->BlockUpdates = 0;
|
|
this->StartedInteractions = 0;
|
|
this->StartedChanges = 0;
|
|
|
|
this->Callback = vtkCallbackCommand::New();
|
|
this->Callback->SetClientData(this);
|
|
this->Callback->SetCallback(
|
|
vtkControlPointsItem::CallComputePoints);
|
|
|
|
this->Bounds[0] = this->Bounds[2] = 0.;
|
|
this->Bounds[1] = this->Bounds[3] = -1.;
|
|
this->UserBounds[0] = this->UserBounds[2] = 0.;
|
|
this->UserBounds[1] = this->UserBounds[3] = -1.;
|
|
this->ValidBounds[0] = this->ValidBounds[2] = 0.;
|
|
this->ValidBounds[1] = this->ValidBounds[3] = -1.;
|
|
|
|
this->ScreenPointRadius = 6.f;
|
|
this->Transform = vtkTransform2D::New();
|
|
|
|
this->StrokeMode = false;
|
|
this->SwitchPointsMode = false;
|
|
this->MouseMoved = false;
|
|
this->EnforceValidFunction = true;
|
|
this->PointToDelete = -1;
|
|
this->PointAboutToBeDeleted = false;
|
|
this->PointToToggle = -1;
|
|
this->PointAboutToBeToggled = false;
|
|
this->InvertShadow = false;
|
|
this->EndPointsXMovable = true;
|
|
this->EndPointsYMovable = true;
|
|
this->EndPointsRemovable = true;
|
|
this->ShowLabels = false;
|
|
this->LabelFormat = NULL;
|
|
this->SetLabelFormat("%.3f, %.3f");
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkControlPointsItem::~vtkControlPointsItem()
|
|
{
|
|
this->SetLabelFormat(NULL);
|
|
if (this->Callback)
|
|
{
|
|
this->Callback->Delete();
|
|
this->Callback = 0;
|
|
}
|
|
if (this->SelectedPointPen)
|
|
{
|
|
this->SelectedPointPen->Delete();
|
|
this->SelectedPointPen = 0;
|
|
}
|
|
if (this->SelectedPointBrush)
|
|
{
|
|
this->SelectedPointBrush->Delete();
|
|
this->SelectedPointBrush = 0;
|
|
}
|
|
if (this->Transform)
|
|
{
|
|
this->Transform->Delete();
|
|
this->Transform = 0;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::PrintSelf(ostream &os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
|
|
os << indent << "EndPointsXMovable: " << this->EndPointsXMovable << endl;
|
|
os << indent << "EndPointsYMovable: " << this->EndPointsYMovable << endl;
|
|
os << indent << "EndPointsRemovable: " << this->EndPointsRemovable << endl;
|
|
os << indent << "ShowLabels: " << this->ShowLabels << endl;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::GetBounds(double bounds[4])
|
|
{
|
|
// valid user bounds ? use them
|
|
if (this->UserBounds[0] <= this->UserBounds[1] &&
|
|
this->UserBounds[2] <= this->UserBounds[3])
|
|
{
|
|
bounds[0] = this->UserBounds[0];
|
|
bounds[1] = this->UserBounds[1];
|
|
bounds[2] = this->UserBounds[2];
|
|
bounds[3] = this->UserBounds[3];
|
|
return;
|
|
}
|
|
// invalid bounds ? compute them
|
|
if (!(this->Bounds[0] <= this->Bounds[1] &&
|
|
this->Bounds[2] > this->Bounds[3]))
|
|
{
|
|
this->ComputeBounds();
|
|
}
|
|
bounds[0] = this->Bounds[0];
|
|
bounds[1] = this->Bounds[1];
|
|
bounds[2] = this->Bounds[2];
|
|
bounds[3] = this->Bounds[3];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::ResetBounds()
|
|
{
|
|
this->Bounds[0] = 0.;
|
|
this->Bounds[1] = -1.;
|
|
this->Bounds[2] = 0.;
|
|
this->Bounds[3] = -1.;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::ComputeBounds()
|
|
{
|
|
double oldBounds[4];
|
|
oldBounds[0] = this->Bounds[0];
|
|
oldBounds[1] = this->Bounds[1];
|
|
oldBounds[2] = this->Bounds[2];
|
|
oldBounds[3] = this->Bounds[3];
|
|
|
|
this->ComputeBounds(this->Bounds);
|
|
|
|
if (this->Bounds[0] != oldBounds[0] ||
|
|
this->Bounds[1] != oldBounds[1] ||
|
|
this->Bounds[2] != oldBounds[2] ||
|
|
this->Bounds[3] != oldBounds[3])
|
|
{
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::ComputeBounds( double* bounds)
|
|
{
|
|
bounds[0] = bounds[2] = VTK_DOUBLE_MAX;
|
|
bounds[1] = bounds[3] = -VTK_DOUBLE_MAX;
|
|
for (vtkIdType i=0; i < this->GetNumberOfPoints(); ++i)
|
|
{
|
|
double point[4];
|
|
this->GetControlPoint(i, point);
|
|
bounds[0] = std::min(bounds[0], point[0]);
|
|
bounds[1] = std::max(bounds[1], point[0]);
|
|
bounds[2] = std::min(bounds[2], point[1]);
|
|
bounds[3] = std::max(bounds[3], point[1]);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::Paint(vtkContext2D* painter)
|
|
{
|
|
painter->GetDevice()->EnableClipping(false);
|
|
painter->ApplyPen(this->Pen);
|
|
painter->ApplyBrush(this->Brush);
|
|
this->InvertShadow = false;
|
|
this->DrawUnselectedPoints(painter);
|
|
|
|
painter->GetPen()->SetLineType(vtkPen::SOLID_LINE);
|
|
//painter->GetPen()->SetColorF(0.87, 0.87, 1.);
|
|
//painter->GetBrush()->SetColorF(0.75, 0.75, 0.95, 0.65);
|
|
//float oldPenWidth = painter->GetPen()->GetWidth();
|
|
painter->ApplyPen(this->SelectedPointPen);
|
|
painter->ApplyBrush(this->SelectedPointBrush);
|
|
this->InvertShadow = true;
|
|
float oldScreenPointRadius = this->ScreenPointRadius;
|
|
if (this->Selection && this->Selection->GetNumberOfTuples())
|
|
{
|
|
//painter->GetPen()->SetWidth(oldPenWidth * 1.4);
|
|
//this->ScreenPointRadius = oldScreenPointRadius * 1.1;
|
|
this->DrawSelectedPoints(painter);
|
|
}
|
|
this->ScreenPointRadius = oldScreenPointRadius;
|
|
this->Transform->SetMatrix(painter->GetTransform()->GetMatrix());
|
|
|
|
painter->GetDevice()->EnableClipping(true);
|
|
this->PaintChildren(painter);
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::StartChanges()
|
|
{
|
|
++this->StartedChanges;
|
|
if (this->StartedChanges == 1)
|
|
{
|
|
this->InvokeEvent(vtkCommand::StartEvent);
|
|
this->emitEvent(vtkCommand::StartEvent);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::EndChanges()
|
|
{
|
|
--this->StartedChanges;
|
|
assert(this->StartedChanges >=0);
|
|
if (this->StartedChanges == 0)
|
|
{
|
|
this->emitEvent(vtkCommand::EndEvent);
|
|
this->InvokeEvent(vtkCommand::EndEvent);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::StartInteraction()
|
|
{
|
|
++this->StartedInteractions;
|
|
this->emitEvent(vtkCommand::StartInteractionEvent);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::StartInteractionIfNotStarted()
|
|
{
|
|
if (this->GetInteractionsCount() == 0)
|
|
{
|
|
this->StartInteraction();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::Interaction()
|
|
{
|
|
assert(this->StartedInteractions > 0);
|
|
this->emitEvent(vtkCommand::InteractionEvent);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::EndInteraction()
|
|
{
|
|
--this->StartedInteractions;
|
|
assert(this->StartedInteractions >= 0);
|
|
this->emitEvent(vtkCommand::EndInteractionEvent);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int vtkControlPointsItem::GetInteractionsCount()const
|
|
{
|
|
return this->StartedInteractions;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//void vtkControlPointsItem::emitEvent(unsigned long event, void* params);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::CallComputePoints(
|
|
vtkObject* vtkNotUsed(sender), unsigned long event,
|
|
void* receiver, void* vtkNotUsed(params))
|
|
{
|
|
vtkControlPointsItem* item =
|
|
reinterpret_cast<vtkControlPointsItem*>(receiver);
|
|
switch(event)
|
|
{
|
|
case vtkCommand::StartEvent:
|
|
++item->BlockUpdates;
|
|
break;
|
|
case vtkCommand::EndEvent:
|
|
--item->BlockUpdates;
|
|
if (item->BlockUpdates == 0)
|
|
{
|
|
item->ComputePoints();
|
|
}
|
|
break;
|
|
case vtkCommand::ModifiedEvent:
|
|
item->ComputePoints();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::ComputePoints()
|
|
{
|
|
if (this->BlockUpdates > 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (this->Selection && this->GetNumberOfPoints() == 0)
|
|
{
|
|
this->Selection->SetNumberOfTuples(0);
|
|
}
|
|
|
|
const int selectedPointCount = this->Selection ?
|
|
this->Selection->GetNumberOfTuples() : 0;
|
|
if (selectedPointCount)
|
|
{
|
|
vtkIdTypeArray* oldSelection = this->Selection;
|
|
this->Selection = vtkIdTypeArray::New();
|
|
for (vtkIdType i = 0; i < selectedPointCount; ++i)
|
|
{
|
|
if (oldSelection->GetValue(i) < this->GetNumberOfPoints())
|
|
{
|
|
this->SelectPoint(oldSelection->GetValue(i));
|
|
}
|
|
}
|
|
oldSelection->Delete();
|
|
}
|
|
|
|
if (this->GetScene())
|
|
{
|
|
this->GetScene()->SetDirty(true);
|
|
}
|
|
this->Modified();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::TransformScreenToData(const vtkVector2f& in, vtkVector2f& out)
|
|
{
|
|
out = in;
|
|
|
|
// inverse shift/scale from screen space.
|
|
const vtkRectd& ss = this->ShiftScale;
|
|
out.SetX(static_cast<float>((out.GetX() / ss[2]) - ss[0]));
|
|
out.SetY(static_cast<float>((out.GetY() / ss[3]) - ss[1]));
|
|
|
|
if (this->UsingLogScale())
|
|
{
|
|
// using log scale.
|
|
double bounds[4];
|
|
this->ComputeBounds(bounds);
|
|
|
|
double posX = in.GetX();
|
|
double normVal = (posX - bounds[0])/(bounds[1] - bounds[0]);
|
|
double lval = log10(bounds[0]) + normVal*(log10(bounds[1]) - log10(bounds[0]));
|
|
posX = pow(10.0, lval);
|
|
out.SetX(posX);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::TransformDataToScreen(const vtkVector2f& in, vtkVector2f& out)
|
|
{
|
|
out = in;
|
|
if (this->UsingLogScale())
|
|
{
|
|
double bounds[4];
|
|
this->ComputeBounds(bounds);
|
|
|
|
double posX = in.GetX();
|
|
double lnormVal = (log10(posX) - log10(bounds[0])) /
|
|
(log10(bounds[1]) - log10(bounds[0]));
|
|
posX = bounds[0] + lnormVal * (bounds[1] - bounds[0]);
|
|
out.SetX(posX);
|
|
}
|
|
|
|
// now, shift/scale to screen space.
|
|
const vtkRectd& ss = this->ShiftScale;
|
|
out.SetX(static_cast<float>((out.GetX() + ss[0]) * ss[2]));
|
|
out.SetY(static_cast<float>((out.GetY() + ss[1]) * ss[3]));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::Hit(const vtkContextMouseEvent &mouse)
|
|
{
|
|
vtkVector2f vpos = mouse.GetPos();
|
|
this->TransformScreenToData(vpos, vpos);
|
|
double pos[2];
|
|
pos[0] = vpos.GetX();
|
|
pos[1] = vpos.GetY();
|
|
double bounds[4];
|
|
this->GetBounds(bounds);
|
|
bool clamped = this->ClampPos(pos, bounds);
|
|
if (!clamped)
|
|
{
|
|
return true;
|
|
}
|
|
// maybe the cursor is over the first or last point (which could be outside
|
|
// the bounds because of the screen point size).
|
|
pos[0] = vpos.GetX();
|
|
pos[1] = vpos.GetY();
|
|
for (int i = 0; i < this->GetNumberOfPoints(); ++i)
|
|
{
|
|
if (this->IsOverPoint(pos, i))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::ClampPos(double pos[2], double bounds[4])
|
|
{
|
|
if (bounds[1] < bounds[0] || bounds[3] < bounds[2])
|
|
{
|
|
// bounds are not valid. Don't clamp.
|
|
return false;
|
|
}
|
|
bool clamped = false;
|
|
if (pos[0] < bounds[0])
|
|
{
|
|
pos[0] = bounds[0];
|
|
clamped = true;
|
|
}
|
|
if (pos[0] > bounds[1])
|
|
{
|
|
pos[0] = bounds[1];
|
|
clamped = true;
|
|
}
|
|
if (pos[1] < 0.)
|
|
{
|
|
pos[1] = 0.;
|
|
clamped = true;
|
|
}
|
|
if (pos[1] > 1.)
|
|
{
|
|
pos[1] = 1.;
|
|
clamped = true;
|
|
}
|
|
return clamped;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::ClampValidPos(double pos[2])
|
|
{
|
|
double validBounds[4];
|
|
this->GetValidBounds(validBounds);
|
|
if (validBounds[0] > this->ValidBounds[1] ||
|
|
validBounds[2] > this->ValidBounds[3])
|
|
{
|
|
double bounds[4];
|
|
this->GetBounds(bounds);
|
|
return this->ClampPos(pos, bounds);
|
|
}
|
|
return this->ClampPos(pos, validBounds);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::DrawUnselectedPoints(vtkContext2D* painter)
|
|
{
|
|
const int count = this->GetNumberOfPoints();
|
|
for (vtkIdType i = 0; i < count; ++i)
|
|
{
|
|
vtkIdType idx = this->Selection ? this->Selection->LookupValue(i) : -1;
|
|
if (idx != -1)
|
|
{
|
|
continue;
|
|
}
|
|
this->DrawPoint(painter, i);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::DrawSelectedPoints(vtkContext2D* painter)
|
|
{
|
|
const int count = this->Selection ? this->Selection->GetNumberOfTuples() : 0;
|
|
for (vtkIdType i = 0; i < count; ++i)
|
|
{
|
|
vtkIdType index = this->Selection->GetValue(i);
|
|
assert(index != -1);
|
|
this->DrawPoint(painter, index);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::DrawPoint(vtkContext2D* painter, vtkIdType index)
|
|
{
|
|
assert(index != -1);
|
|
double point[4];
|
|
this->GetControlPoint(index, point);
|
|
|
|
vtkVector2f vpoint(point[0], point[1]);
|
|
this->TransformDataToScreen(vpoint, vpoint);
|
|
point[0] = vpoint.GetX();
|
|
point[1] = vpoint.GetY();
|
|
|
|
double pointInScene[2];
|
|
vtkTransform2D* sceneTransform = painter->GetTransform();
|
|
sceneTransform->TransformPoints(point, pointInScene, 1);
|
|
|
|
vtkSmartPointer<vtkTransform2D> translation =
|
|
vtkSmartPointer<vtkTransform2D>::New();
|
|
translation->Translate(pointInScene[0], pointInScene[1]);
|
|
|
|
painter->PushMatrix();
|
|
painter->SetTransform(translation);
|
|
|
|
unsigned char brushOpacity = painter->GetBrush()->GetOpacity();
|
|
unsigned char penColor[3];
|
|
painter->GetPen()->GetColor(penColor);
|
|
unsigned char penOpacity = painter->GetPen()->GetOpacity();
|
|
//float width = painter->GetPen()->GetWidth();
|
|
|
|
float radius = this->ScreenPointRadius;
|
|
bool invertShadow = this->InvertShadow;
|
|
unsigned char color[3] = {penColor[0], penColor[1], penColor[2]};
|
|
|
|
if (this->PointToToggle == index && this->PointAboutToBeToggled)
|
|
{
|
|
invertShadow = !invertShadow;
|
|
}
|
|
if (this->PointToDelete == index && this->PointAboutToBeDeleted)
|
|
{
|
|
invertShadow = !invertShadow;
|
|
color[0] = 255;
|
|
color[1] = 0;
|
|
color[2] = 0;
|
|
}
|
|
if (this->CurrentPoint == index)
|
|
{
|
|
radius = this->ScreenPointRadius * 1.3;
|
|
color[0] = 255;
|
|
color[1] = 0;
|
|
color[2] = 255;
|
|
}
|
|
|
|
painter->GetPen()->SetColor(color);
|
|
painter->DrawArc(0.f, 0.f, radius, 0.f, 360.f);
|
|
|
|
painter->GetBrush()->SetOpacity(0);
|
|
//painter->GetPen()->SetWidth(2.0f);
|
|
|
|
unsigned char lightPenColor[4];
|
|
lightPenColor[0] = std::min(color[0] + 100, 255);
|
|
lightPenColor[1] = std::min(color[1] + 100, 255);
|
|
lightPenColor[2] = std::min(color[2] + 100, 255);
|
|
lightPenColor[3] = penOpacity;
|
|
|
|
unsigned char darkPenColor[4];
|
|
darkPenColor[0] = std::max(color[0] - 50, 0);
|
|
darkPenColor[1] = std::max(color[1] - 50, 0);
|
|
darkPenColor[2] = std::max(color[2] - 50, 0);
|
|
darkPenColor[3] = penOpacity;
|
|
|
|
painter->GetPen()->SetColor(invertShadow ? lightPenColor : darkPenColor);
|
|
painter->DrawArc(0.f, 0.f, radius - 1.0, 200.f, 380.f);
|
|
painter->GetPen()->SetColor(invertShadow ? darkPenColor : lightPenColor);
|
|
painter->DrawArc(0.f, 0.f, radius - 1.0, 20.f, 200.f);
|
|
|
|
painter->GetPen()->SetColor(color);
|
|
if (this->PointToDelete == index && this->PointAboutToBeDeleted)
|
|
{
|
|
painter->DrawLine(-radius, -radius, radius, radius);
|
|
painter->DrawLine(-radius, radius, radius, -radius);
|
|
}
|
|
|
|
painter->GetPen()->SetColor(penColor);
|
|
|
|
if (this->ShowLabels && (/*index == 0 ||
|
|
index == this->GetNumberOfPoints()-1 || */
|
|
this->GetCurrentPoint() == index))
|
|
{
|
|
translation->Translate(0, radius+5);
|
|
painter->SetTransform(translation);
|
|
vtkStdString label = this->GetControlPointLabel(index);
|
|
|
|
vtkVector2f bounds[2];
|
|
painter->ComputeStringBounds(label, bounds[0].GetData());
|
|
if (bounds[1].GetX() != 0.0f && bounds[1].GetY() != 0.0f)
|
|
{
|
|
float scale[2];
|
|
float position[2];
|
|
painter->GetTransform()->GetScale(scale);
|
|
painter->GetTransform()->GetPosition(position);
|
|
|
|
double brushColor[4];
|
|
painter->GetBrush()->GetColorF(brushColor);
|
|
painter->GetBrush()->SetColorF(1, 1, 1, 1);
|
|
painter->GetBrush()->SetOpacityF(0.75);
|
|
painter->GetPen()->SetOpacity(0);
|
|
bounds[0] = vtkVector2f(-5/scale[0], -3/scale[1]);
|
|
bounds[1] = vtkVector2f(bounds[1].GetX()+10/scale[0],
|
|
bounds[1].GetY()+10/scale[1]);
|
|
|
|
// Pull the tooltip back in if it will go off the edge of the screen.
|
|
float maxX = (this->Scene->GetViewWidth() - position[0])/scale[0];
|
|
if (bounds[0].GetX() >= maxX - bounds[1].GetX())
|
|
{
|
|
bounds[0].SetX(maxX - bounds[1].GetX());
|
|
}
|
|
// Pull the tooltip down in if it will go off the edge of the screen.
|
|
float maxY = (this->Scene->GetViewHeight() - position[1])/scale[1];
|
|
if (bounds[0].GetY() >= maxY - bounds[1].GetY())
|
|
{
|
|
bounds[0].SetY(maxY - bounds[1].GetY());
|
|
}
|
|
painter->DrawRect(bounds[0].GetX(), bounds[0].GetY(), bounds[1].GetX(), bounds[1].GetY());
|
|
painter->DrawString(bounds[0].GetX()+5/scale[0], bounds[0].GetY()+3/scale[1], label);
|
|
painter->GetBrush()->SetColorF(brushColor);
|
|
}
|
|
}
|
|
|
|
painter->GetPen()->SetOpacity(penOpacity);
|
|
//painter->GetPen()->SetWidth(width);
|
|
painter->GetBrush()->SetOpacity(brushOpacity);
|
|
|
|
painter->PopMatrix();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::SelectPoint(double* currentPoint)
|
|
{
|
|
vtkIdType pointId = this->FindPoint(currentPoint);
|
|
if (pointId == -1)
|
|
{
|
|
vtkErrorMacro( << "try to select a point that doesn't exist");
|
|
return;
|
|
}
|
|
this->SelectPoint(pointId);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::SelectPoint(vtkIdType pointId)
|
|
{
|
|
if (!this->Selection || this->Selection->LookupValue(pointId) != -1)
|
|
{
|
|
return;
|
|
}
|
|
this->Selection->InsertNextValue(pointId);
|
|
this->GetScene()->SetDirty(true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::SelectAllPoints()
|
|
{
|
|
this->DeselectAllPoints();
|
|
const int count = this->GetNumberOfPoints();
|
|
for (vtkIdType i = 0; i < count; ++i)
|
|
{
|
|
this->SelectPoint(i);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::DeselectPoint(double* point)
|
|
{
|
|
// make sure the point belongs to the list of points
|
|
vtkIdType pointId = this->FindPoint(point);
|
|
if (pointId == -1)
|
|
{
|
|
vtkErrorMacro( << "try to deselect a point that doesn't exist");
|
|
return;
|
|
}
|
|
this->DeselectPoint(pointId);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::DeselectPoint(vtkIdType pointId)
|
|
{
|
|
vtkIdType selectionPointId = this->Selection
|
|
? this->Selection->LookupValue(pointId) : -1;
|
|
if (selectionPointId == -1)
|
|
{
|
|
//vtkErrorMacro(<< "Point:" << pointId << " was not selected");
|
|
return;
|
|
}
|
|
this->Selection->RemoveTuple(selectionPointId);
|
|
this->GetScene()->SetDirty(true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::DeselectAllPoints()
|
|
{
|
|
if (this->GetNumberOfSelectedPoints() == 0)
|
|
{
|
|
return;
|
|
}
|
|
this->Selection->SetNumberOfTuples(0);
|
|
this->GetScene()->SetDirty(true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::ToggleSelectPoint(double* currentPoint)
|
|
{
|
|
// make sure the point belongs to the list of points
|
|
vtkIdType pointId = this->FindPoint(currentPoint);
|
|
if (pointId == -1)
|
|
{
|
|
vtkErrorMacro( << "try to toggle a point that doesn't exist");
|
|
return;
|
|
}
|
|
this->ToggleSelectPoint(pointId);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::ToggleSelectPoint(vtkIdType pointId)
|
|
{
|
|
vtkIdType selectionId = this->Selection
|
|
? this->Selection->LookupValue(pointId) : -1;
|
|
if (selectionId != -1)
|
|
{
|
|
this->DeselectPoint(pointId);
|
|
return;
|
|
}
|
|
this->SelectPoint(pointId);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::SelectPoints(const vtkVector2f& min, const vtkVector2f& max)
|
|
{
|
|
bool atLeast1PointSelected = false;
|
|
const int numberOfPoints = this->GetNumberOfPoints();
|
|
for(vtkIdType i = 0; i < numberOfPoints; ++i)
|
|
{
|
|
double point[4];
|
|
this->GetControlPoint(i, point);
|
|
if (point[0] >= min.GetX() && point[0] <= max.GetX() &&
|
|
point[1] >= min.GetY() && point[1] <= max.GetY())
|
|
{
|
|
this->SelectPoint(i);
|
|
atLeast1PointSelected = true;
|
|
}
|
|
else
|
|
{
|
|
this->DeselectPoint(i);
|
|
}
|
|
}
|
|
return atLeast1PointSelected;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::GetNumberOfSelectedPoints()const
|
|
{
|
|
return this->Selection ? this->Selection->GetNumberOfTuples() : 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::GetCurrentPoint()const
|
|
{
|
|
return this->CurrentPoint;
|
|
}
|
|
/*
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::FindPoint(double* pos, double tolerance)
|
|
{
|
|
if (tolerance < std::numeric_limits<float>::epsilon())
|
|
{
|
|
tolerance = std::numeric_limits<float>::epsilon();
|
|
}
|
|
// make sure the point belongs to the list of points
|
|
vtkIdType pointId = -1;
|
|
double minDist = VTK_DOUBLE_MAX;
|
|
const int numberOfPoints = this->GetNumberOfPoints();
|
|
for(vtkIdType i = 0; i < numberOfPoints; ++i)
|
|
{
|
|
double point[4];
|
|
this->GetControlPoint(i, point);
|
|
double distance = (point[0] - pos[0]) * (point[0] - pos[0]) +
|
|
(point[1] - pos[1]) * (point[1] - pos[1]);
|
|
if (distance <= tolerance)
|
|
{
|
|
if (distance == 0.)
|
|
{// we found the best match ever
|
|
return i;
|
|
}
|
|
else if (distance < minDist)
|
|
{// we found something not too bad, we maybe we can find closer
|
|
pointId = i;
|
|
minDist = distance;
|
|
}
|
|
}
|
|
// don't search any further if the x is already too large
|
|
//if (point[0] > pos[0] + this->ItemPointRadius2)
|
|
// {
|
|
// break;
|
|
// }
|
|
}
|
|
return pointId;
|
|
}
|
|
*/
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::IsOverPoint(double* pos, vtkIdType pointId)
|
|
{
|
|
if (pointId < 0 || pointId >= this->GetNumberOfPoints())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
double screenPos[2];
|
|
this->Transform->TransformPoints(pos, screenPos, 1);
|
|
|
|
double point[4];
|
|
this->GetControlPoint(pointId, point);
|
|
double screenPoint[2];
|
|
this->Transform->TransformPoints(point, screenPoint, 1);
|
|
|
|
double distance2 =
|
|
(screenPoint[0] - screenPos[0]) * (screenPoint[0] - screenPos[0]) +
|
|
(screenPoint[1] - screenPos[1]) * (screenPoint[1] - screenPos[1]);
|
|
double tolerance = 1.3;
|
|
double radius2 = this->ScreenPointRadius * this->ScreenPointRadius
|
|
* tolerance * tolerance;
|
|
return distance2 <= radius2;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::FindPoint(double* _pos)
|
|
{
|
|
vtkVector2f vpos(_pos[0], _pos[1]);
|
|
this->TransformDataToScreen(vpos, vpos);
|
|
double pos[2] = {vpos.GetX(), vpos.GetY()};
|
|
|
|
double tolerance = 1.3;
|
|
double radius2 = this->ScreenPointRadius * this->ScreenPointRadius
|
|
* tolerance * tolerance;
|
|
|
|
double screenPos[2];
|
|
this->Transform->TransformPoints(pos, screenPos, 1);
|
|
vtkIdType pointId = -1;
|
|
double minDist = VTK_DOUBLE_MAX;
|
|
const int numberOfPoints = this->GetNumberOfPoints();
|
|
for(vtkIdType i = 0; i < numberOfPoints; ++i)
|
|
{
|
|
double point[4];
|
|
this->GetControlPoint(i, point);
|
|
vtkVector2f vpos1(point[0], point[1]);
|
|
this->TransformDataToScreen(vpos1, vpos1);
|
|
point[0] = vpos1.GetX();
|
|
point[1] = vpos1.GetY();
|
|
|
|
double screenPoint[2];
|
|
this->Transform->TransformPoints(point, screenPoint, 1);
|
|
double distance2 =
|
|
(screenPoint[0] - screenPos[0]) * (screenPoint[0] - screenPos[0]) +
|
|
(screenPoint[1] - screenPos[1]) * (screenPoint[1] - screenPos[1]);
|
|
if (distance2 <= radius2)
|
|
{
|
|
if (distance2 == 0.)
|
|
{// we found the best match ever
|
|
return i;
|
|
}
|
|
else if (distance2 < minDist)
|
|
{// we found something not too bad, maybe we can find closer
|
|
pointId = i;
|
|
minDist = distance2;
|
|
}
|
|
}
|
|
// don't search any further if the x is already too large
|
|
if (screenPoint[0] > (screenPos[0] + this->ScreenPointRadius * tolerance))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return pointId;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::GetControlPointId(double* point)
|
|
{
|
|
const int numberOfPoints = this->GetNumberOfPoints();
|
|
for(vtkIdType i = 0; i < numberOfPoints; ++i)
|
|
{
|
|
double controlPoint[4];
|
|
this->GetControlPoint(i, controlPoint);
|
|
if (controlPoint[0] == point[0])
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem
|
|
::GetControlPointsIds(vtkIdTypeArray* points, bool excludeFirstAndLast)const
|
|
{
|
|
assert(points != 0);
|
|
int numberOfPoints = this->GetNumberOfPoints();
|
|
if (excludeFirstAndLast)
|
|
{
|
|
numberOfPoints -= 2;
|
|
}
|
|
numberOfPoints = std::max(numberOfPoints, 0);
|
|
points->SetNumberOfTuples(numberOfPoints);
|
|
vtkIdType pointId = excludeFirstAndLast ? 1 : 0;
|
|
for(vtkIdType i = 0; i < numberOfPoints; ++i)
|
|
{
|
|
points->SetValue(i, pointId++);
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::AddPointId(vtkIdType addedPointId)
|
|
{
|
|
assert(addedPointId != -1);
|
|
// offset all the point ids
|
|
const int selectionCount = this->GetNumberOfSelectedPoints();
|
|
for (vtkIdType i = 0; i < selectionCount; ++i)
|
|
{
|
|
vtkIdType pointId = this->Selection->GetValue(i);
|
|
if (pointId >= addedPointId)
|
|
{
|
|
this->Selection->SetValue(i, ++pointId);
|
|
}
|
|
}
|
|
if (this->CurrentPoint >= addedPointId)
|
|
{
|
|
this->SetCurrentPoint(this->CurrentPoint + 1);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::RemovePoint(double* point)
|
|
{
|
|
return this->RemovePointId(this->GetControlPointId(point));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::RemovePoint(vtkIdType pointId)
|
|
{
|
|
double point[4];
|
|
this->GetControlPoint(pointId, point);
|
|
return this->RemovePoint(point);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::RemovePointId(vtkIdType pointId)
|
|
{
|
|
if(!this->IsPointRemovable(pointId))
|
|
{
|
|
return pointId;
|
|
}
|
|
|
|
this->StartChanges();
|
|
|
|
assert(pointId != -1);
|
|
// Useless to remove the point here as it will be removed anyway in ComputePoints
|
|
this->DeselectPoint(pointId);
|
|
|
|
const vtkIdType selectionCount = this->GetNumberOfSelectedPoints();
|
|
for (vtkIdType i = 0; i < selectionCount; ++i)
|
|
{
|
|
vtkIdType selectedPointId = this->Selection->GetValue(i);
|
|
if (selectedPointId > pointId)
|
|
{
|
|
this->Selection->SetValue(i, --selectedPointId);
|
|
}
|
|
}
|
|
|
|
if (this->CurrentPoint > pointId ||
|
|
this->CurrentPoint == this->GetNumberOfPoints() - 1)
|
|
{
|
|
this->SetCurrentPoint(this->CurrentPoint - 1);
|
|
}
|
|
|
|
this->EndChanges();
|
|
return pointId;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::SetCurrentPoint(vtkIdType index)
|
|
{
|
|
if (index == this->CurrentPoint)
|
|
{
|
|
return;
|
|
}
|
|
this->CurrentPoint = index;
|
|
this->InvokeEvent(vtkControlPointsItem::CurrentPointChangedEvent,
|
|
reinterpret_cast<void *>(this->CurrentPoint));
|
|
this->GetScene()->SetDirty(true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::MouseButtonPressEvent(const vtkContextMouseEvent &mouse)
|
|
{
|
|
this->MouseMoved = false;
|
|
this->PointToToggle = -1;
|
|
this->PointToDelete = -1;
|
|
|
|
vtkVector2f vpos = mouse.GetPos();
|
|
this->TransformScreenToData(vpos, vpos);
|
|
double pos[2];
|
|
pos[0] = vpos.GetX();
|
|
pos[1] = vpos.GetY();
|
|
vtkIdType pointUnderMouse = this->FindPoint(pos);
|
|
|
|
if (mouse.GetButton() == vtkContextMouseEvent::LEFT_BUTTON)
|
|
{
|
|
if (pointUnderMouse != -1)
|
|
{
|
|
this->SetCurrentPoint(pointUnderMouse);
|
|
return true;
|
|
}
|
|
else if (pointUnderMouse == -1
|
|
&& this->GetNumberOfSelectedPoints() <= 1
|
|
&& !this->StrokeMode)
|
|
{
|
|
this->ClampValidPos(pos);
|
|
vtkIdType addedPoint = this->AddPoint(pos);
|
|
this->SetCurrentPoint(addedPoint);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
this->SetCurrentPoint(-1);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (mouse.GetButton() == vtkContextMouseEvent::RIGHT_BUTTON
|
|
&& pointUnderMouse != -1)
|
|
{
|
|
this->PointToToggle = pointUnderMouse;
|
|
this->PointAboutToBeToggled = true;
|
|
this->GetScene()->SetDirty(true);
|
|
return true;
|
|
}
|
|
|
|
if (mouse.GetButton() == vtkContextMouseEvent::MIDDLE_BUTTON
|
|
&& pointUnderMouse != -1)
|
|
{
|
|
this->PointToDelete = pointUnderMouse;
|
|
this->PointAboutToBeDeleted = true;
|
|
this->GetScene()->SetDirty(true);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::MouseDoubleClickEvent(const vtkContextMouseEvent &mouse)
|
|
{
|
|
if (mouse.GetButton() == vtkContextMouseEvent::RIGHT_BUTTON)
|
|
{
|
|
if (this->Selection->GetNumberOfTuples())
|
|
{
|
|
this->DeselectAllPoints();
|
|
}
|
|
else
|
|
{
|
|
this->SelectAllPoints();
|
|
}
|
|
return true;
|
|
}
|
|
bool res = this->MouseButtonPressEvent(mouse);
|
|
if (mouse.GetButton() == vtkContextMouseEvent::LEFT_BUTTON
|
|
&& this->CurrentPoint != -1)
|
|
{
|
|
this->InvokeEvent(vtkControlPointsItem::CurrentPointEditEvent,
|
|
reinterpret_cast<void *>(this->CurrentPoint));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::MouseMoveEvent(const vtkContextMouseEvent &mouse)
|
|
{
|
|
vtkVector2f mousePos = mouse.GetPos();
|
|
this->TransformScreenToData(mousePos, mousePos);
|
|
|
|
if (mouse.GetButton() == vtkContextMouseEvent::LEFT_BUTTON)
|
|
{
|
|
if (this->StrokeMode)
|
|
{
|
|
this->StartInteractionIfNotStarted();
|
|
|
|
this->Stroke(mousePos);
|
|
|
|
this->Interaction();
|
|
}
|
|
else if (this->CurrentPoint == -1 && this->GetNumberOfSelectedPoints() > 1)
|
|
{
|
|
vtkVector2f deltaPos = mouse.GetPos() - mouse.GetLastPos();
|
|
if(this->IsEndPointPicked())
|
|
{
|
|
if(!this->GetEndPointsMovable())
|
|
{
|
|
return false;
|
|
}
|
|
else if(this->GetEndPointsXMovable())
|
|
{
|
|
deltaPos.SetY(0);
|
|
}
|
|
else if(this->GetEndPointsYMovable())
|
|
{
|
|
deltaPos.SetX(0);
|
|
}
|
|
}
|
|
|
|
this->StartInteractionIfNotStarted();
|
|
|
|
if (vtkIdTypeArray* points = this->GetSelection())
|
|
{
|
|
// must stay valid after each individual point move
|
|
points->Register(this);
|
|
this->MovePoints(deltaPos, points);
|
|
points->UnRegister(this);
|
|
}
|
|
|
|
this->Interaction();
|
|
}
|
|
else if (this->CurrentPoint != -1)
|
|
{
|
|
vtkVector2f curPos(mousePos);
|
|
if(this->IsEndPointPicked())
|
|
{
|
|
double currentPoint[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(this->CurrentPoint, currentPoint);
|
|
if(!this->GetEndPointsMovable())
|
|
{
|
|
return false;
|
|
}
|
|
else if(this->GetEndPointsXMovable())
|
|
{
|
|
curPos.SetY(currentPoint[1]);
|
|
}
|
|
else if(this->GetEndPointsYMovable())
|
|
{
|
|
curPos.SetX(currentPoint[0]);
|
|
}
|
|
}
|
|
this->StartInteractionIfNotStarted();
|
|
|
|
this->SetCurrentPointPos(curPos);
|
|
|
|
this->Interaction();
|
|
}
|
|
}
|
|
if (mouse.GetButton() == vtkContextMouseEvent::RIGHT_BUTTON)
|
|
{
|
|
if (this->PointToToggle == -1)
|
|
{
|
|
return false;
|
|
}
|
|
double pos[2];
|
|
pos[0] = mousePos[0];
|
|
pos[1] = mousePos[1];
|
|
vtkIdType pointUnderCursor = this->FindPoint(pos);
|
|
if ((pointUnderCursor == this->PointToToggle) != this->PointAboutToBeToggled)
|
|
{
|
|
this->PointAboutToBeToggled = !this->PointAboutToBeToggled;
|
|
this->GetScene()->SetDirty(true);
|
|
}
|
|
}
|
|
this->MouseMoved = true;
|
|
if (mouse.GetButton() == vtkContextMouseEvent::MIDDLE_BUTTON)
|
|
{
|
|
if (this->PointToDelete == -1)
|
|
{
|
|
// allow chart ruber band to work
|
|
return false;
|
|
}
|
|
double pos[2];
|
|
pos[0] = mousePos[0];
|
|
pos[1] = mousePos[1];
|
|
vtkIdType pointUnderCursor = this->FindPoint(pos);
|
|
if ((pointUnderCursor == this->PointToDelete) != this->PointAboutToBeDeleted)
|
|
{
|
|
this->PointAboutToBeDeleted = !this->PointAboutToBeDeleted;
|
|
this->GetScene()->SetDirty(true);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (mouse.GetButton() == vtkContextMouseEvent::RIGHT_BUTTON
|
|
&& this->CurrentPoint == -1)
|
|
{
|
|
return false;
|
|
}
|
|
if (mouse.GetButton() == vtkContextMouseEvent::NO_BUTTON)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::SetCurrentPointPos(const vtkVector2f& newPos)
|
|
{
|
|
vtkIdType movedPoint = this->SetPointPos(this->CurrentPoint, newPos);
|
|
// If the moved point was not CurrentPoint then make it current.
|
|
this->SetCurrentPoint(movedPoint);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::SetPointPos(vtkIdType point, const vtkVector2f& newPos)
|
|
{
|
|
if (point == -1)
|
|
{
|
|
return point;
|
|
}
|
|
|
|
// Make sure the new point is inside the boundaries of the function
|
|
double boundedPos[2];
|
|
boundedPos[0] = newPos[0];
|
|
boundedPos[1] = newPos[1];
|
|
this->ClampValidPos(boundedPos);
|
|
|
|
if (!this->SwitchPointsMode)
|
|
{
|
|
// Stop mode.
|
|
// You can't move a point past another point.
|
|
if (point > 0)
|
|
{
|
|
double previousPoint[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(point - 1, previousPoint);
|
|
boundedPos[0] = std::max(previousPoint[0], boundedPos[0]);
|
|
}
|
|
if (point < this->GetNumberOfPoints() - 1)
|
|
{
|
|
double nextPoint[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(point + 1, nextPoint);
|
|
boundedPos[0] = std::min(boundedPos[0], nextPoint[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Switch mode.
|
|
// Moving a point to the right of the next one, makes it current.
|
|
// and moving a point to the left of the previous one makes it current.
|
|
if (point > 0)
|
|
{
|
|
double previousPoint[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(point - 1, previousPoint);
|
|
while (boundedPos[0] < previousPoint[0])
|
|
{
|
|
point = point - 1;
|
|
if (point == 0)
|
|
{
|
|
break;
|
|
}
|
|
// maybe the move is that important that it went over multiple points
|
|
this->GetControlPoint(point - 1, previousPoint);
|
|
}
|
|
}
|
|
if (point < this->GetNumberOfPoints() - 1)
|
|
{
|
|
double nextPoint[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(point + 1, nextPoint);
|
|
while (boundedPos[0] > nextPoint[0])
|
|
{
|
|
point = point + 1;
|
|
if (point == this->GetNumberOfPoints() - 1)
|
|
{
|
|
break;
|
|
}
|
|
this->GetControlPoint(point + 1, nextPoint);
|
|
}
|
|
}
|
|
}
|
|
double currentPoint[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(point, currentPoint);
|
|
currentPoint[0] = boundedPos[0];
|
|
currentPoint[1] = boundedPos[1];
|
|
|
|
// SetControlPoint will call StartChanges/EndChanges correctly, so we don't
|
|
// need to call it here.
|
|
this->SetControlPoint(point, currentPoint);
|
|
return point;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::MoveCurrentPoint(const vtkVector2f& translation)
|
|
{
|
|
this->MovePoint(this->CurrentPoint, translation);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkIdType vtkControlPointsItem::MovePoint(vtkIdType pointId, const vtkVector2f& translation)
|
|
{
|
|
double point[4];
|
|
this->GetControlPoint(pointId, point);
|
|
return this->SetPointPos(pointId, vtkVector2f(point[0] + translation.GetX(), point[1] + translation.GetY()));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::MovePoints(const vtkVector2f& translation, vtkIdTypeArray* pointIds)
|
|
{
|
|
assert(pointIds);
|
|
this->StartChanges();
|
|
// don't support 'switch' mode yet
|
|
//vtkIdTypeArray* addedSelection = vtkIdTypeArray::New();
|
|
bool oldSwitchPoints = this->SwitchPointsMode;
|
|
this->SwitchPointsMode = false;
|
|
// end "don't support 'switch' mode yet"
|
|
const int count = pointIds->GetNumberOfTuples();
|
|
float tX = translation.GetX();
|
|
float tY = translation.GetY();
|
|
int start = tX < 0.f ? 0 : count - 1;
|
|
int end = tX < 0.f ? count : -1;
|
|
int step = tX < 0.f ? 1 : -1;
|
|
for (vtkIdType i = start; i != end; i+=step)
|
|
{
|
|
vtkIdType pointId = pointIds->GetValue(i);
|
|
double currentPoint[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(pointId, currentPoint);
|
|
vtkVector2f newPos(currentPoint[0] + tX, currentPoint[1] + tY);
|
|
//vtkIdType newIdx =
|
|
this->SetPointPos(pointId, newPos);
|
|
// don't support 'switch' mode yet
|
|
//if (newIdx != point)
|
|
// {
|
|
// int next = (newIdx > point) ? 1 : -1;
|
|
// for (int i = point + next; i != newIdx; i+=next)
|
|
// {
|
|
// addedSelection->InsertNextValue(i);
|
|
// }
|
|
// addedSelection->InsertNextValue(newIdx);
|
|
// }
|
|
// end "don't support 'switch' mode yet"
|
|
}
|
|
// don't support 'switch' mode yet
|
|
//this->SelectPoints(addedSelection);
|
|
this->SwitchPointsMode = oldSwitchPoints;
|
|
// end "don't support 'switch' mode yet"
|
|
this->EndChanges();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::MovePoints(const vtkVector2f& translation,
|
|
bool dontMoveFirstAndLast)
|
|
{
|
|
vtkNew<vtkIdTypeArray> points;
|
|
this->GetControlPointsIds(points.GetPointer(), dontMoveFirstAndLast);
|
|
this->MovePoints(translation, points.GetPointer());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::SpreadPoints(float factor, vtkIdTypeArray* pointIds)
|
|
{
|
|
assert(pointIds);
|
|
if (pointIds->GetNumberOfTuples() == 0)
|
|
{
|
|
return;
|
|
}
|
|
this->StartChanges();
|
|
|
|
double min[2], max[2], center[2];
|
|
double point[4];
|
|
vtkIdType minPointId = pointIds->GetValue(0);
|
|
this->GetControlPoint(minPointId, point);
|
|
min[0] = point[0];
|
|
min[1] = point[1];
|
|
vtkIdType maxPointId = pointIds->GetValue(pointIds->GetNumberOfTuples() - 1);
|
|
this->GetControlPoint(maxPointId, point);
|
|
max[0] = point[0];
|
|
max[1] = point[1];
|
|
center[0] = (min[0] + max[0]) / 2.;
|
|
center[1] = (min[1] + max[1]) / 2.;
|
|
|
|
// Left part
|
|
vtkIdType start = 0;
|
|
vtkIdType end = pointIds->GetNumberOfTuples();
|
|
vtkIdType step = 1;
|
|
vtkIdType median = -1; // not needed when factor >= 0
|
|
if (factor < 0.f)
|
|
{
|
|
// search median
|
|
for (vtkIdType i = 0; i < end; ++i)
|
|
{
|
|
vtkIdType pointId = pointIds->GetValue(i);
|
|
this->GetControlPoint(pointId, point);
|
|
if (point[0] > center[0])
|
|
{
|
|
median = i;
|
|
break;
|
|
}
|
|
}
|
|
if (median == -1)
|
|
{
|
|
median = pointIds->GetNumberOfTuples() - 1;
|
|
}
|
|
start = median - 1;
|
|
end = -1;
|
|
step = -1;
|
|
}
|
|
vtkIdType i;
|
|
for (i = start; i != end; i+=step)
|
|
{
|
|
vtkIdType pointId = pointIds->GetValue(i);
|
|
this->GetControlPoint(pointId, point);
|
|
if (point[0] > center[0] ||
|
|
(i != start && point[0] == center[0]))
|
|
{
|
|
break;
|
|
}
|
|
double tX = -factor;
|
|
tX *= (min[0] != center[0]) ?
|
|
(center[0] - point[0]) / (center[0] - min[0]) :
|
|
fabs(point[0]) / 100.;
|
|
vtkVector2f newPos(std::min(point[0] + tX, center[0]), point[1]);
|
|
this->SetPointPos(pointId, newPos);
|
|
}
|
|
// Right part
|
|
start = pointIds->GetNumberOfTuples() - 1;
|
|
end = i - 1;
|
|
step = -1;
|
|
if (factor < 0.f)
|
|
{
|
|
start = median;
|
|
end = pointIds->GetNumberOfTuples();
|
|
step = 1;
|
|
}
|
|
for (i = start; i != end; i+=step)
|
|
{
|
|
vtkIdType pointId = pointIds->GetValue(i);
|
|
this->GetControlPoint(pointId, point);
|
|
assert(point[0] >= center[0]);
|
|
double tX = factor;
|
|
tX *= (max[0] != center[0]) ?
|
|
(point[0] - center[0]) / (max[0] - center[0]) :
|
|
fabs(point[0]) / 100.;
|
|
vtkVector2f newPos(std::max(point[0] + tX, center[0]), point[1]);
|
|
this->SetPointPos(pointId, newPos);
|
|
}
|
|
this->EndChanges();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::SpreadPoints(float factor, bool dontSpreadFirstAndLast)
|
|
{
|
|
vtkNew<vtkIdTypeArray> points;
|
|
this->GetControlPointsIds(points.GetPointer(), dontSpreadFirstAndLast);
|
|
this->SpreadPoints(factor, points.GetPointer());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkVector2f vtkControlPointsItem::GetCenterOfMass(vtkIdTypeArray* pointIDs)const
|
|
{
|
|
double average[4] = {0., 0., 0., 0.};
|
|
const vtkIdType pointCount = pointIDs->GetNumberOfTuples();
|
|
for (vtkIdType i = 0; i < pointCount; ++i)
|
|
{
|
|
double point[4];
|
|
this->GetControlPoint(pointIDs->GetValue(i), point);
|
|
average[0] += point[0]; // x
|
|
average[1] += point[1]; // y
|
|
average[2] += point[2]; // midpoint
|
|
average[3] += point[3]; // sharpness
|
|
}
|
|
average[0] /= pointCount; // x
|
|
average[1] /= pointCount; // y
|
|
average[2] /= pointCount; // midpoint
|
|
average[3] /= pointCount; // sharpness
|
|
return vtkVector2f(average[0], average[1]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::Stroke(const vtkVector2f& newPos)
|
|
{
|
|
double pos[2];
|
|
pos[0] = newPos[0];
|
|
pos[1] = newPos[1];
|
|
this->ClampValidPos(pos);
|
|
|
|
// last point
|
|
if (this->CurrentPoint != -1)
|
|
{
|
|
vtkIdType lastPointId = this->CurrentPoint;
|
|
double lastPoint[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(lastPointId, lastPoint);
|
|
const double pointSpacing = 1.15;
|
|
float oldScreenPointRadius = this->ScreenPointRadius;
|
|
this->ScreenPointRadius *= pointSpacing;
|
|
// ignore the stroke if it is too close from the last point
|
|
if (this->FindPoint(pos) == lastPointId)
|
|
{
|
|
this->ScreenPointRadius = oldScreenPointRadius;
|
|
return;
|
|
}
|
|
this->ScreenPointRadius = oldScreenPointRadius;
|
|
// For the first case or when the new pos share the same X (but not the
|
|
// same y) then we just have to modify the last point
|
|
if (!this->MouseMoved || lastPoint[0] == pos[0])
|
|
{
|
|
lastPoint[0] = pos[0];
|
|
lastPoint[1] = pos[1];
|
|
this->SetControlPoint(this->CurrentPoint, lastPoint);
|
|
return;
|
|
}
|
|
assert(lastPoint[0] != pos[0]);
|
|
// CurrentPoint != -1 && MouseMoved
|
|
// Starting from the last point, we search points (forward or backward) to see
|
|
// if there are points that can be removed.
|
|
int count = this->GetNumberOfPoints();
|
|
if (pos[0] > lastPoint[0] && lastPointId < count - 1)
|
|
{
|
|
// search if there are points between pos and lastPoint
|
|
double point[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(lastPointId + 1, point);
|
|
while (pos[0] >= point[0])
|
|
{
|
|
this->RemovePoint(point);
|
|
count = this->GetNumberOfPoints();
|
|
if (lastPointId == count - 1)
|
|
{
|
|
break;
|
|
}
|
|
this->GetControlPoint(lastPointId + 1, point);
|
|
}
|
|
}
|
|
else if (pos[0] < lastPoint[0] && lastPointId > 0)
|
|
{
|
|
// search if there are points between pos and lastPoint
|
|
double point[4] = {0.0, 0.0, 0.0, 0.0};
|
|
this->GetControlPoint(lastPointId - 1, point);
|
|
while (pos[0] <= point[0])
|
|
{
|
|
this->RemovePoint(point);
|
|
--lastPointId;
|
|
if (lastPointId == 0)
|
|
{
|
|
break;
|
|
}
|
|
this->GetControlPoint(lastPointId - 1, point);
|
|
}
|
|
}
|
|
}
|
|
#ifndef NDEBUG
|
|
const int oldNumberOfPoints = this->GetNumberOfPoints();
|
|
#endif
|
|
vtkIdType addedPoint = this->AddPoint(pos);
|
|
this->SetCurrentPoint(addedPoint);
|
|
assert(oldNumberOfPoints + 1 == this->GetNumberOfPoints());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkControlPointsItem::EditPoint(float vtkNotUsed(tX), float vtkNotUsed(tY))
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::MouseButtonReleaseEvent(const vtkContextMouseEvent &mouse)
|
|
{
|
|
if (this->GetInteractionsCount())
|
|
{
|
|
this->EndInteraction();
|
|
}
|
|
if (mouse.GetButton() == vtkContextMouseEvent::LEFT_BUTTON)
|
|
{
|
|
return true;
|
|
}
|
|
if (mouse.GetButton() == vtkContextMouseEvent::RIGHT_BUTTON
|
|
&& this->PointToToggle != -1)
|
|
{
|
|
if (this->PointAboutToBeToggled)
|
|
{
|
|
this->ToggleSelectPoint(this->PointToToggle);
|
|
this->PointToToggle = -1;
|
|
this->PointAboutToBeToggled = false;
|
|
}
|
|
return true;
|
|
}
|
|
if (mouse.GetButton() == vtkContextMouseEvent::MIDDLE_BUTTON
|
|
&& this->PointToDelete != -1)
|
|
{
|
|
if (this->PointAboutToBeDeleted)
|
|
{
|
|
// If EnforceValidFunction is true, we don't want less than 2 points
|
|
if (this->IsPointRemovable(this->PointToDelete))
|
|
{
|
|
double point[4];
|
|
this->GetControlPoint(this->PointToDelete, point);
|
|
this->RemovePoint(point);
|
|
this->PointToDelete = -1;
|
|
this->PointAboutToBeDeleted = false;
|
|
}
|
|
else
|
|
{
|
|
this->PointToDelete = -1;
|
|
this->PointAboutToBeDeleted = false;
|
|
this->GetScene()->SetDirty(true);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::KeyPressEvent(const vtkContextKeyEvent &key)
|
|
{
|
|
bool move = key.GetInteractor()->GetAltKey() != 0 ||
|
|
key.GetInteractor()->GetKeySym() == vtkStdString("plus") ||
|
|
key.GetInteractor()->GetKeySym() == vtkStdString("minus");
|
|
bool select = !move && key.GetInteractor()->GetShiftKey() != 0;
|
|
bool control = key.GetInteractor()->GetControlKey() != 0;
|
|
bool current = !select && !move && !control;
|
|
if (current)
|
|
{
|
|
if (key.GetInteractor()->GetKeySym() == vtkStdString("Right") ||
|
|
key.GetInteractor()->GetKeySym() == vtkStdString("Up"))
|
|
{
|
|
this->SetCurrentPoint(
|
|
std::min(this->GetNumberOfPoints() -1, this->GetCurrentPoint() + 1));
|
|
}
|
|
else if (key.GetInteractor()->GetKeySym() == vtkStdString("Left") ||
|
|
key.GetInteractor()->GetKeySym() == vtkStdString("Down"))
|
|
{
|
|
this->SetCurrentPoint(
|
|
std::max(0, static_cast<int>(this->GetCurrentPoint()) - 1));
|
|
}
|
|
else if (key.GetInteractor()->GetKeySym() == vtkStdString("End"))
|
|
{
|
|
this->SetCurrentPoint(this->GetNumberOfPoints() - 1);
|
|
}
|
|
else if (key.GetInteractor()->GetKeySym() == vtkStdString("Home"))
|
|
{
|
|
this->SetCurrentPoint(0);
|
|
}
|
|
}
|
|
else if (select)
|
|
{
|
|
if (key.GetInteractor()->GetKeySym() == std::string("Right") ||
|
|
key.GetInteractor()->GetKeySym() == std::string("Up"))
|
|
{
|
|
this->SelectPoint(this->CurrentPoint);
|
|
this->SetCurrentPoint(
|
|
std::min(this->GetNumberOfPoints() -1, this->GetCurrentPoint() + 1));
|
|
this->SelectPoint(this->CurrentPoint);
|
|
}
|
|
else if (key.GetInteractor()->GetKeySym() == std::string("Left") ||
|
|
key.GetInteractor()->GetKeySym() == std::string("Down"))
|
|
{
|
|
this->SelectPoint(this->CurrentPoint);
|
|
this->SetCurrentPoint(
|
|
std::max(0, static_cast<int>(this->GetCurrentPoint()) - 1));
|
|
this->SelectPoint(this->CurrentPoint);
|
|
}
|
|
else if (key.GetInteractor()->GetKeySym() == vtkStdString("End"))
|
|
{
|
|
vtkIdType newCurrentPointId = this->GetNumberOfPoints() - 1;
|
|
for (vtkIdType pointId = this->CurrentPoint; pointId < newCurrentPointId; ++pointId)
|
|
{
|
|
this->SelectPoint(pointId);
|
|
}
|
|
this->SelectPoint(newCurrentPointId);
|
|
this->SetCurrentPoint(newCurrentPointId);
|
|
}
|
|
else if (key.GetInteractor()->GetKeySym() == vtkStdString("Home"))
|
|
{
|
|
vtkIdType newCurrentPointId = 0;
|
|
for (vtkIdType pointId = this->CurrentPoint; pointId > newCurrentPointId; --pointId)
|
|
{
|
|
this->SelectPoint(pointId);
|
|
}
|
|
this->SelectPoint(newCurrentPointId);
|
|
this->SetCurrentPoint(newCurrentPointId);
|
|
}
|
|
}
|
|
else if (move)
|
|
{
|
|
vtkVector2f translate(0,0);
|
|
if (key.GetInteractor()->GetKeySym() == std::string("Up"))
|
|
{
|
|
translate = translate + vtkVector2f(0., 1.);
|
|
}
|
|
if (key.GetInteractor()->GetKeySym() == std::string("Down"))
|
|
{
|
|
translate = translate + vtkVector2f(0., -1.);
|
|
}
|
|
if (key.GetInteractor()->GetKeySym() == std::string("Right"))
|
|
{
|
|
translate = translate + vtkVector2f(1., 0.);
|
|
}
|
|
if (key.GetInteractor()->GetKeySym() == std::string("Left"))
|
|
{
|
|
translate = translate + vtkVector2f(-1., 0.);
|
|
}
|
|
if (translate.GetX() != 0.f || translate.GetY() != 0.f)
|
|
{
|
|
double bounds[4];
|
|
this->GetBounds(bounds);
|
|
float step = control ? 0.001 : 0.01;
|
|
translate.SetX( translate.GetX() * (bounds[1] - bounds[0]) * step);
|
|
translate.SetY( translate.GetY() * (bounds[3] - bounds[2]) * step);
|
|
if (this->GetNumberOfSelectedPoints())
|
|
{
|
|
this->StartInteractionIfNotStarted();
|
|
|
|
if (vtkIdTypeArray* points = this->GetSelection())
|
|
{
|
|
points->Register(this); // must stay valid after each individual move
|
|
this->MovePoints(translate, points);
|
|
points->UnRegister(this);
|
|
}
|
|
|
|
this->Interaction();
|
|
}
|
|
else
|
|
{
|
|
this->StartInteractionIfNotStarted();
|
|
|
|
this->MoveCurrentPoint(translate);
|
|
|
|
this->Interaction();
|
|
}
|
|
}
|
|
else if (key.GetInteractor()->GetKeySym() == std::string("plus"))
|
|
{
|
|
this->StartInteractionIfNotStarted();
|
|
|
|
if (vtkIdTypeArray* pointIds = this->GetSelection())
|
|
{
|
|
pointIds->Register(this); // must stay valid after each individual move
|
|
this->SpreadPoints(1., pointIds);
|
|
pointIds->UnRegister(this);
|
|
}
|
|
|
|
this->Interaction();
|
|
}
|
|
else if (key.GetInteractor()->GetKeySym() == std::string("minus"))
|
|
{
|
|
this->StartInteractionIfNotStarted();
|
|
|
|
if (vtkIdTypeArray* pointIds = this->GetSelection())
|
|
{
|
|
pointIds->Register(this); // must stay valid after each individual move
|
|
this->SpreadPoints(-1., pointIds);
|
|
pointIds->UnRegister(this);
|
|
}
|
|
|
|
this->Interaction();
|
|
}
|
|
}
|
|
else if (control)
|
|
{
|
|
if (key.GetInteractor()->GetKeySym() == std::string("a"))
|
|
{
|
|
this->SelectAllPoints();
|
|
}
|
|
}
|
|
if (key.GetInteractor()->GetKeySym() == vtkStdString("space"))
|
|
{
|
|
this->ToggleSelectPoint(this->GetCurrentPoint());
|
|
}
|
|
else if (key.GetInteractor()->GetKeySym() == vtkStdString("Escape"))
|
|
{
|
|
this->DeselectAllPoints();
|
|
}
|
|
return this->Superclass::KeyPressEvent(key);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::KeyReleaseEvent(const vtkContextKeyEvent &key)
|
|
{
|
|
if (key.GetInteractor()->GetKeySym() == std::string("Delete") ||
|
|
key.GetInteractor()->GetKeySym() == std::string("BackSpace"))
|
|
{
|
|
vtkIdType removedPoint = this->RemovePoint(this->GetCurrentPoint());
|
|
if (key.GetInteractor()->GetKeySym() == std::string("BackSpace"))
|
|
{
|
|
this->SetCurrentPoint(removedPoint > 0 ? removedPoint - 1 : 0);
|
|
}
|
|
return true;
|
|
}
|
|
return this->Superclass::KeyPressEvent(key);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::GetEndPointsMovable()
|
|
{
|
|
return (this->GetEndPointsXMovable() || this->GetEndPointsYMovable());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::IsEndPointPicked()
|
|
{
|
|
int numPts = this->GetNumberOfPoints();
|
|
if(numPts<=0)
|
|
{
|
|
return false;
|
|
}
|
|
if(this->CurrentPoint==0 || this->CurrentPoint==numPts-1)
|
|
{
|
|
return true;
|
|
}
|
|
vtkIdTypeArray* selection = this->GetSelection();
|
|
if(selection && selection->GetNumberOfTuples()>0)
|
|
{
|
|
vtkIdType pid;
|
|
for (vtkIdType i = 0; i < selection->GetNumberOfTuples(); ++i)
|
|
{
|
|
pid=selection->GetValue(i);
|
|
if(pid==0 || pid==numPts-1)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool vtkControlPointsItem::IsPointRemovable(vtkIdType pointId)
|
|
{
|
|
vtkIdType numPts = this->GetNumberOfPoints();
|
|
if (this->EnforceValidFunction && numPts<= 2)
|
|
{
|
|
return false;
|
|
}
|
|
if(pointId != -1 && !this->GetEndPointsRemovable() &&
|
|
(pointId==0 || pointId==numPts-1))
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkStdString vtkControlPointsItem::GetControlPointLabel(vtkIdType pointId)
|
|
{
|
|
vtkStdString result;
|
|
if (this->LabelFormat)
|
|
{
|
|
char *buffer = new char[1024];
|
|
double point[4];
|
|
this->GetControlPoint(pointId, point);
|
|
sprintf(buffer, this->LabelFormat, point[0], point[1], point[2], point[3]);
|
|
result = buffer;
|
|
delete []buffer;
|
|
}
|
|
return result;
|
|
}
|