Commit be5771a4 authored by Utkarsh Ayachit's avatar Utkarsh Ayachit Committed by Code Review
Browse files

Merge topic '13082_fix_log_lut' into master

16543376 Cleanup logic for indexed colors.
37a10c60 Release graphics resources properly.
1509669d Cleaning up transfer function widgets.
parents 1fb3bd99 16543376
c3b8ad563805adbd17676dcfc6b9c488
cb1c16066e465328005012e8db8254d9
......@@ -46,6 +46,7 @@ vtkColorTransferControlPointsItem::~vtkColorTransferControlPointsItem()
{
if (this->ColorTransferFunction)
{
this->ColorTransferFunction->RemoveObserver(this->Callback);
this->ColorTransferFunction->Delete();
this->ColorTransferFunction = 0;
}
......@@ -134,7 +135,8 @@ void vtkColorTransferControlPointsItem::GetControlPoint(vtkIdType index, double*
double xrgbms[6];
vtkColorTransferFunction* thisTF = const_cast<vtkColorTransferFunction*>(
this->ColorTransferFunction);
if(thisTF)
if (thisTF)
{
thisTF->GetNodeValue(index, xrgbms);
pos[0] = xrgbms[0];
......@@ -157,6 +159,7 @@ void vtkColorTransferControlPointsItem::SetControlPoint(vtkIdType index, double*
xrgbms[4] = newPos[2];
xrgbms[5] = newPos[3];
this->ColorTransferFunction->SetNodeValue(index, xrgbms);
this->InvokeEvent(vtkControlPointsItem::PointsModifiedEvent);
}
}
......@@ -178,6 +181,7 @@ void vtkColorTransferControlPointsItem::EditPoint(float tX, float tY)
xrgbms[4] += tX;
xrgbms[5] += tY;
this->ColorTransferFunction->SetNodeValue(this->CurrentPoint - 1, xrgbms);
this->InvokeEvent(vtkControlPointsItem::PointsModifiedEvent);
}
}
......@@ -188,11 +192,14 @@ vtkIdType vtkColorTransferControlPointsItem::AddPoint(double* newPos)
{
return -1;
}
double posX = newPos[0];
double rgb[3] = {0., 0., 0.};
this->ColorTransferFunction->GetColor(newPos[0], rgb);
this->ColorTransferFunction->GetColor(posX, rgb);
vtkIdType addedPoint =
this->ColorTransferFunction->AddRGBPoint(newPos[0], rgb[0], rgb[1], rgb[2]);
this->ColorTransferFunction->AddRGBPoint(posX, rgb[0], rgb[1], rgb[2]);
this->vtkControlPointsItem::AddPointId(addedPoint);
this->InvokeEvent(vtkControlPointsItem::PointsModifiedEvent);
return addedPoint;
}
......@@ -211,5 +218,30 @@ vtkIdType vtkColorTransferControlPointsItem::RemovePoint(double* currentPoint)
vtkIdType removedPoint =
this->ColorTransferFunction->RemovePoint(currentPoint[0]);
assert(removedPoint == expectedPoint);
this->InvokeEvent(vtkControlPointsItem::PointsModifiedEvent);
return removedPoint;
}
//-----------------------------------------------------------------------------
void vtkColorTransferControlPointsItem::ComputeBounds(double* bounds)
{
if (this->ColorTransferFunction)
{
const double* range = this->ColorTransferFunction->GetRange();
bounds[0] = range[0];
bounds[1] = range[1];
bounds[2] = 0.5;
bounds[3] = 0.5;
}
else
{
this->Superclass::ComputeBounds(bounds);
}
}
//-----------------------------------------------------------------------------
bool vtkColorTransferControlPointsItem::UsingLogScale()
{
return (this->ColorTransferFunction?
(this->ColorTransferFunction->UsingLogScale() != 0) : false);
}
......@@ -86,6 +86,12 @@ protected:
vtkColorTransferControlPointsItem();
virtual ~vtkColorTransferControlPointsItem();
// Description:
// Returns true if control points are to be rendered in log-space. This is
// true when vtkScalarsToColors is using log-scale, for example. Default
// implementation always return false.
virtual bool UsingLogScale();
virtual void emitEvent(unsigned long event, void* params);
virtual unsigned long int GetControlPointsMTime();
......@@ -93,6 +99,11 @@ protected:
virtual void DrawPoint(vtkContext2D* painter, vtkIdType index);
virtual void EditPoint(float tX, float tY);
// Description:
// Compute the bounds for this item. Overridden to use the
// vtkColorTransferFunction range.
virtual void ComputeBounds(double* bounds);
vtkColorTransferFunction* ColorTransferFunction;
bool ColorFill;
......
......@@ -12,7 +12,6 @@
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkBrush.h"
#include "vtkCallbackCommand.h"
#include "vtkContext2D.h"
......@@ -25,6 +24,7 @@
#include "vtkPoints2D.h"
#include <cassert>
#include <math.h>
//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkColorTransferFunctionItem);
......@@ -40,6 +40,7 @@ vtkColorTransferFunctionItem::~vtkColorTransferFunctionItem()
{
if (this->ColorTransferFunction)
{
this->ColorTransferFunction->RemoveObserver(this->Callback);
this->ColorTransferFunction->Delete();
this->ColorTransferFunction = 0;
}
......@@ -115,10 +116,22 @@ void vtkColorTransferFunctionItem::ComputeTexture()
0, 0,
0, 0);
this->Texture->AllocateScalars(VTK_UNSIGNED_CHAR, 4);
bool isLogTable = this->UsingLogScale();
double logBoundsMin = bounds[0] > 0.0 ? log10(bounds[0]) : 0.0;
double logBoundsDelta = (bounds[0] > 0.0 && bounds[1] > 0.0)?
(log10(bounds[1])-log10(bounds[0])) : 0.0;
for (int i = 0; i < dimension; ++i)
{
values[i] = bounds[0] + i * (bounds[1] - bounds[0]) / (dimension - 1);
if (isLogTable)
{
double normVal = i/(dimension-1.0);
double lval = logBoundsMin + normVal*logBoundsDelta;
values[i] = pow(10.0, lval);
}
else
{
values[i] = bounds[0] + i * (bounds[1] - bounds[0]) / (dimension - 1);
}
}
unsigned char* ptr =
reinterpret_cast<unsigned char*>(this->Texture->GetScalarPointer(0,0,0));
......@@ -135,3 +148,10 @@ void vtkColorTransferFunctionItem::ComputeTexture()
delete [] values;
return;
}
//-----------------------------------------------------------------------------
bool vtkColorTransferFunctionItem::UsingLogScale()
{
return this->ColorTransferFunction?
(this->ColorTransferFunction->UsingLogScale() != 0) : false;
}
......@@ -39,6 +39,11 @@ protected:
vtkColorTransferFunctionItem();
virtual ~vtkColorTransferFunctionItem();
// Description:
// Returns true if we are rendering in log space.
virtual bool UsingLogScale();
// Description:
// Reimplemented to return the range of the lookup table
virtual void ComputeBounds(double bounds[4]);
......
......@@ -51,6 +51,7 @@ vtkCompositeControlPointsItem::~vtkCompositeControlPointsItem()
{
if (this->OpacityFunction)
{
this->OpacityFunction->RemoveObserver(this->Callback);
this->OpacityFunction->Delete();
this->OpacityFunction = 0;
}
......@@ -153,6 +154,13 @@ void vtkCompositeControlPointsItem::SetColorTransferFunction(vtkColorTransferFun
this->Superclass::SetColorTransferFunction(c);
}
//-----------------------------------------------------------------------------
bool vtkCompositeControlPointsItem::UsingLogScale()
{
return (this->ColorTransferFunction &&
this->ColorTransferFunction->UsingLogScale());
}
//-----------------------------------------------------------------------------
void vtkCompositeControlPointsItem::DrawPoint(vtkContext2D* painter, vtkIdType index)
{
......
......@@ -103,6 +103,11 @@ protected:
vtkCompositeControlPointsItem();
virtual ~vtkCompositeControlPointsItem();
// Description:
// Returns true if control points are to be rendered in log-space. This is
// true when vtkScalarsToColors is using log-scale, for example.
virtual bool UsingLogScale();
virtual void emitEvent(unsigned long event, void* params);
virtual unsigned long int GetControlPointsMTime();
......
......@@ -43,6 +43,7 @@ vtkCompositeTransferFunctionItem::~vtkCompositeTransferFunctionItem()
{
if (this->OpacityFunction)
{
this->OpacityFunction->RemoveObserver(this->Callback);
this->OpacityFunction->Delete();
this->OpacityFunction = 0;
}
......
......@@ -37,6 +37,12 @@ protected:
vtkCompositeTransferFunctionItem();
virtual ~vtkCompositeTransferFunctionItem();
// Description:
// Returns true if we are rendering in log space.
// Since vtkPiecewiseFunction doesn't support log, we show this transfer
// function in non-log space always.
virtual bool UsingLogScale() { return false; }
// Description:
// Reimplemented to return the range of the piecewise function
virtual void ComputeBounds(double bounds[4]);
......
......@@ -13,6 +13,7 @@
=========================================================================*/
#include "vtkAxis.h"
#include "vtkBrush.h"
#include "vtkCallbackCommand.h"
#include "vtkContext2D.h"
......@@ -84,11 +85,15 @@ vtkControlPointsItem::vtkControlPointsItem()
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();
......@@ -119,6 +124,7 @@ void vtkControlPointsItem::PrintSelf(ostream &os, vtkIndent 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;
}
//-----------------------------------------------------------------------------
......@@ -334,12 +340,49 @@ void vtkControlPointsItem::ComputePoints()
this->Modified();
}
//-----------------------------------------------------------------------------
void vtkControlPointsItem::TransformScreenToData(const vtkVector2f& in, vtkVector2f& out)
{
out = in;
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);
}
}
//-----------------------------------------------------------------------------
bool vtkControlPointsItem::Hit(const vtkContextMouseEvent &mouse)
{
vtkVector2f vpos = mouse.GetPos();
this->TransformScreenToData(vpos, vpos);
double pos[2];
pos[0] = mouse.GetPos()[0];
pos[1] = mouse.GetPos()[1];
pos[0] = vpos.GetX();
pos[1] = vpos.GetY();
double bounds[4];
this->GetBounds(bounds);
bool clamped = this->ClampPos(pos, bounds);
......@@ -349,8 +392,8 @@ bool vtkControlPointsItem::Hit(const vtkContextMouseEvent &mouse)
}
// maybe the cursor is over the first or last point (which could be outside
// the bounds because of the screen point size).
pos[0] = mouse.GetPos()[0];
pos[1] = mouse.GetPos()[1];
pos[0] = vpos.GetX();
pos[1] = vpos.GetY();
for (int i = 0; i < this->GetNumberOfPoints(); ++i)
{
if (this->IsOverPoint(pos, i))
......@@ -364,6 +407,11 @@ bool vtkControlPointsItem::Hit(const vtkContextMouseEvent &mouse)
//-----------------------------------------------------------------------------
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])
{
......@@ -437,6 +485,11 @@ void vtkControlPointsItem::DrawPoint(vtkContext2D* painter, vtkIdType index)
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);
......@@ -508,6 +561,51 @@ void vtkControlPointsItem::DrawPoint(vtkContext2D* painter, vtkIdType index)
}
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);
......@@ -711,11 +809,16 @@ bool vtkControlPointsItem::IsOverPoint(double* pos, vtkIdType pointId)
}
//-----------------------------------------------------------------------------
vtkIdType vtkControlPointsItem::FindPoint(double* pos)
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;
......@@ -725,6 +828,11 @@ vtkIdType vtkControlPointsItem::FindPoint(double* pos)
{
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 =
......@@ -868,9 +976,12 @@ bool vtkControlPointsItem::MouseButtonPressEvent(const vtkContextMouseEvent &mou
this->MouseMoved = false;
this->PointToToggle = -1;
this->PointToDelete = -1;
vtkVector2f vpos = mouse.GetPos();
this->TransformScreenToData(vpos, vpos);
double pos[2];
pos[0] = mouse.GetPos()[0];
pos[1] = mouse.GetPos()[1];
pos[0] = vpos.GetX();
pos[1] = vpos.GetY();
vtkIdType pointUnderMouse = this->FindPoint(pos);
if (mouse.GetButton() == vtkContextMouseEvent::LEFT_BUTTON)
......@@ -884,7 +995,7 @@ bool vtkControlPointsItem::MouseButtonPressEvent(const vtkContextMouseEvent &mou
&& this->Selection->GetNumberOfTuples() <= 1
&& !this->StrokeMode)
{
this->ClampPos(pos, this->GetValidBounds());
this->ClampValidPos(pos);
vtkIdType addedPoint = this->AddPoint(pos);
this->SetCurrentPoint(addedPoint);
return true;
......@@ -945,13 +1056,16 @@ bool vtkControlPointsItem::MouseDoubleClickEvent(const vtkContextMouseEvent &mou
//-----------------------------------------------------------------------------
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(mouse.GetPos());
this->Stroke(mousePos);
this->Interaction();
}
......@@ -985,7 +1099,7 @@ bool vtkControlPointsItem::MouseMoveEvent(const vtkContextMouseEvent &mouse)
}
else if (this->CurrentPoint != -1)
{
vtkVector2f curPos(mouse.GetPos());
vtkVector2f curPos(mousePos);
if(this->IsEndPointPicked())
{
double currentPoint[4] = {0.0, 0.0, 0.0, 0.0};
......@@ -1017,8 +1131,8 @@ bool vtkControlPointsItem::MouseMoveEvent(const vtkContextMouseEvent &mouse)
return false;
}
double pos[2];
pos[0] = mouse.GetPos()[0];
pos[1] = mouse.GetPos()[1];
pos[0] = mousePos[0];
pos[1] = mousePos[1];
vtkIdType pointUnderCursor = this->FindPoint(pos);
if ((pointUnderCursor == this->PointToToggle) != this->PointAboutToBeToggled)
{
......@@ -1035,8 +1149,8 @@ bool vtkControlPointsItem::MouseMoveEvent(const vtkContextMouseEvent &mouse)
return false;
}
double pos[2];
pos[0] = mouse.GetPos()[0];
pos[1] = mouse.GetPos()[1];
pos[0] = mousePos[0];
pos[1] = mousePos[1];
vtkIdType pointUnderCursor = this->FindPoint(pos);
if ((pointUnderCursor == this->PointToDelete) != this->PointAboutToBeDeleted)
{
......@@ -1051,6 +1165,10 @@ bool vtkControlPointsItem::MouseMoveEvent(const vtkContextMouseEvent &mouse)
{
return false;
}
if (mouse.GetButton() == vtkContextMouseEvent::NO_BUTTON)
{
return false;
}
return true;
}
......@@ -1677,3 +1795,19 @@ bool vtkControlPointsItem::IsPointRemovable(vtkIdType pointId)
}
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;
}
......@@ -43,7 +43,9 @@ public:
enum {
CurrentPointChangedEvent = vtkCommand::UserEvent,
CurrentPointEditEvent
CurrentPointEditEvent,
PointsModifiedEvent // fired when the control points are changed by
// user-interaction.
};
// Description:
......@@ -175,6 +177,17 @@ public:
vtkSetMacro(EndPointsRemovable, bool);
vtkGetMacro(EndPointsRemovable, bool);
// Description:
// When set to true, labels are shown on the current control point and the end
// points. Default is false.
vtkSetMacro(ShowLabels, bool);
vtkGetMacro(ShowLabels, bool);
// Description:
// Get/Set the label format. Default is "%.4f, %.4f".
vtkSetStringMacro(LabelFormat);
vtkGetStringMacro(LabelFormat);
// Description:
// Add a point to the function. Returns the index of the point (0 based),
// or -1 on error.
......@@ -301,6 +314,12 @@ protected:
// Returns true if the supplied x, y coordinate is on a control point.
virtual bool Hit(const vtkContextMouseEvent &mouse);
// Description:
// Transform the mouse event in the control-points space. This is needed when
// ColorTransferFunction is using log-scale.
virtual void TransformScreenToData(const vtkVector2f& in, vtkVector2f& out);
virtual void TransformDataToScreen(const vtkVector2f& in, vtkVector2f& out);
// Description:
// Clamp the given 2D pos into the bounds of the function.
// Return true if the pos has been clamped, false otherwise.
......@@ -328,6 +347,10 @@ protected:
// Mouse button release event.
virtual bool MouseButtonReleaseEvent(const vtkContextMouseEvent &mouse);
// Description:
// Generate label for a control point.
virtual vtkStdString GetControlPointLabel(vtkIdType index);
void AddPointId(vtkIdType addedPointId);
// Description:
......@@ -339,6 +362,19 @@ protected:
// Return true if the point is removable
bool IsPointRemovable(vtkIdType pointId);
// Description:
// Compute the bounds for this item. Typically, the bounds should be aligned
// to the range of the vtkScalarsToColors or vtkPiecewiseFunction that is
// being controlled by the subclasses.
// Default implementation uses the range of the control points themselves. </