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.
1131 lines
32 KiB
1131 lines
32 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkAbstractTransform.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 "vtkAbstractTransform.h"
|
|
|
|
#include "vtkCriticalSection.h"
|
|
#include "vtkDataArray.h"
|
|
#include "vtkDebugLeaks.h"
|
|
#include "vtkHomogeneousTransform.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkMatrix4x4.h"
|
|
#include "vtkPoints.h"
|
|
|
|
vtkCxxRevisionMacro(vtkAbstractTransform, "$Revision: 1.26 $");
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkAbstractTransform::vtkAbstractTransform()
|
|
{
|
|
this->MyInverse = NULL;
|
|
this->DependsOnInverse = 0;
|
|
this->InUnRegister = 0;
|
|
this->UpdateMutex = vtkSimpleCriticalSection::New();
|
|
this->InverseMutex = vtkSimpleCriticalSection::New();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkAbstractTransform::~vtkAbstractTransform()
|
|
{
|
|
if (this->MyInverse)
|
|
{
|
|
this->MyInverse->Delete();
|
|
}
|
|
if (this->UpdateMutex)
|
|
{
|
|
this->UpdateMutex->Delete();
|
|
}
|
|
if (this->InverseMutex)
|
|
{
|
|
this->InverseMutex->Delete();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAbstractTransform::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
os << indent << "Inverse: (" << this->MyInverse << ")\n";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAbstractTransform::TransformNormalAtPoint(const double point[3],
|
|
const double in[3],
|
|
double out[3])
|
|
{
|
|
this->Update();
|
|
|
|
double matrix[3][3];
|
|
double coord[3];
|
|
|
|
this->InternalTransformDerivative(point,coord,matrix);
|
|
vtkMath::Transpose3x3(matrix,matrix);
|
|
vtkMath::LinearSolve3x3(matrix,in,out);
|
|
vtkMath::Normalize(out);
|
|
}
|
|
|
|
void vtkAbstractTransform::TransformNormalAtPoint(const float point[3],
|
|
const float in[3],
|
|
float out[3])
|
|
{
|
|
double coord[3];
|
|
double normal[3];
|
|
|
|
coord[0] = point[0];
|
|
coord[1] = point[1];
|
|
coord[2] = point[2];
|
|
|
|
normal[0] = in[0];
|
|
normal[1] = in[1];
|
|
normal[2] = in[2];
|
|
|
|
this->TransformNormalAtPoint(coord,normal,normal);
|
|
|
|
out[0] = normal[0];
|
|
out[1] = normal[1];
|
|
out[2] = normal[2];
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAbstractTransform::TransformVectorAtPoint(const double point[3],
|
|
const double in[3],
|
|
double out[3])
|
|
{
|
|
this->Update();
|
|
|
|
double matrix[3][3];
|
|
double coord[3];
|
|
|
|
this->InternalTransformDerivative(point,coord,matrix);
|
|
vtkMath::Multiply3x3(matrix,in,out);
|
|
}
|
|
|
|
void vtkAbstractTransform::TransformVectorAtPoint(const float point[3],
|
|
const float in[3],
|
|
float out[3])
|
|
{
|
|
double coord[3];
|
|
double vector[3];
|
|
|
|
coord[0] = point[0];
|
|
coord[1] = point[1];
|
|
coord[2] = point[2];
|
|
|
|
vector[0] = in[0];
|
|
vector[1] = in[1];
|
|
vector[2] = in[2];
|
|
|
|
this->TransformVectorAtPoint(coord,vector,vector);
|
|
|
|
out[0] = vector[0];
|
|
out[1] = vector[1];
|
|
out[2] = vector[2];
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Transform a series of points.
|
|
void vtkAbstractTransform::TransformPoints(vtkPoints *in, vtkPoints *out)
|
|
{
|
|
this->Update();
|
|
|
|
double point[3];
|
|
vtkIdType i;
|
|
vtkIdType n = in->GetNumberOfPoints();
|
|
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
in->GetPoint(i,point);
|
|
this->InternalTransformPoint(point,point);
|
|
out->InsertNextPoint(point);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Transform the normals and vectors using the derivative of the
|
|
// transformation. Either inNms or inVrs can be set to NULL.
|
|
// Normals are multiplied by the inverse transpose of the transform
|
|
// derivative, while vectors are simply multiplied by the derivative.
|
|
// Note that the derivative of the inverse transform is simply the
|
|
// inverse of the derivative of the forward transform.
|
|
|
|
void vtkAbstractTransform::TransformPointsNormalsVectors(vtkPoints *inPts,
|
|
vtkPoints *outPts,
|
|
vtkDataArray *inNms,
|
|
vtkDataArray *outNms,
|
|
vtkDataArray *inVrs,
|
|
vtkDataArray *outVrs)
|
|
{
|
|
this->Update();
|
|
|
|
double matrix[3][3];
|
|
double coord[3];
|
|
|
|
vtkIdType i;
|
|
vtkIdType n = inPts->GetNumberOfPoints();
|
|
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
inPts->GetPoint(i,coord);
|
|
this->InternalTransformDerivative(coord,coord,matrix);
|
|
outPts->InsertNextPoint(coord);
|
|
|
|
if (inVrs)
|
|
{
|
|
inVrs->GetTuple(i,coord);
|
|
vtkMath::Multiply3x3(matrix,coord,coord);
|
|
outVrs->InsertNextTuple(coord);
|
|
}
|
|
|
|
if (inNms)
|
|
{
|
|
inNms->GetTuple(i,coord);
|
|
vtkMath::Transpose3x3(matrix,matrix);
|
|
vtkMath::LinearSolve3x3(matrix,coord,coord);
|
|
vtkMath::Normalize(coord);
|
|
outNms->InsertNextTuple(coord);
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkAbstractTransform *vtkAbstractTransform::GetInverse()
|
|
{
|
|
this->InverseMutex->Lock();
|
|
if (this->MyInverse == NULL)
|
|
{
|
|
// we create a circular reference here, it is dealt with in UnRegister
|
|
this->MyInverse = this->MakeTransform();
|
|
this->MyInverse->SetInverse(this);
|
|
}
|
|
this->InverseMutex->Unlock();
|
|
return this->MyInverse;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAbstractTransform::SetInverse(vtkAbstractTransform *transform)
|
|
{
|
|
if (this->MyInverse == transform)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// check type first
|
|
if (!transform->IsA(this->GetClassName()))
|
|
{
|
|
vtkErrorMacro("SetInverse: requires a " << this->GetClassName() << ", a "
|
|
<< transform->GetClassName() << " is not compatible.");
|
|
return;
|
|
}
|
|
|
|
if (transform->CircuitCheck(this))
|
|
{
|
|
vtkErrorMacro("SetInverse: this would create a circular reference.");
|
|
return;
|
|
}
|
|
|
|
if (this->MyInverse)
|
|
{
|
|
this->MyInverse->Delete();
|
|
}
|
|
|
|
transform->Register(this);
|
|
this->MyInverse = transform;
|
|
|
|
// we are now a special 'inverse transform'
|
|
this->DependsOnInverse = (transform != 0);
|
|
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAbstractTransform::DeepCopy(vtkAbstractTransform *transform)
|
|
{
|
|
// check whether we're trying to copy a transform to itself
|
|
if (transform == this)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// check to see if the transform is the same type as this one
|
|
if (!transform->IsA(this->GetClassName()))
|
|
{
|
|
vtkErrorMacro("DeepCopy: can't copy a " << transform->GetClassName()
|
|
<< " into a " << this->GetClassName() << ".");
|
|
return;
|
|
}
|
|
|
|
if (transform->CircuitCheck(this))
|
|
{
|
|
vtkErrorMacro("DeepCopy: this would create a circular reference.");
|
|
return;
|
|
}
|
|
|
|
// call InternalDeepCopy for subtype
|
|
this->InternalDeepCopy(transform);
|
|
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAbstractTransform::Update()
|
|
{
|
|
// locking is require to ensure that the class is thread-safe
|
|
this->UpdateMutex->Lock();
|
|
|
|
// check to see if we are a special 'inverse' transform
|
|
if (this->DependsOnInverse &&
|
|
this->MyInverse->GetMTime() >= this->UpdateTime.GetMTime())
|
|
{
|
|
vtkDebugMacro("Updating transformation from its inverse");
|
|
this->InternalDeepCopy(this->MyInverse);
|
|
this->Inverse();
|
|
vtkDebugMacro("Calling InternalUpdate on the transformation");
|
|
this->InternalUpdate();
|
|
}
|
|
// otherwise just check our MTime against our last update
|
|
else if (this->GetMTime() >= this->UpdateTime.GetMTime())
|
|
{
|
|
// do internal update for subclass
|
|
vtkDebugMacro("Calling InternalUpdate on the transformation");
|
|
this->InternalUpdate();
|
|
}
|
|
|
|
this->UpdateTime.Modified();
|
|
this->UpdateMutex->Unlock();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkAbstractTransform::CircuitCheck(vtkAbstractTransform *transform)
|
|
{
|
|
return (transform == this || (this->DependsOnInverse &&
|
|
this->MyInverse->CircuitCheck(transform)));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Need to check inverse's MTime if we are an inverse transform
|
|
unsigned long vtkAbstractTransform::GetMTime()
|
|
{
|
|
unsigned long mtime = this->vtkObject::GetMTime();
|
|
if (this->DependsOnInverse)
|
|
{
|
|
unsigned long inverseMTime = this->MyInverse->GetMTime();
|
|
if (inverseMTime > mtime)
|
|
{
|
|
return inverseMTime;
|
|
}
|
|
}
|
|
|
|
return mtime;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// We need to handle the circular reference between a transform and its
|
|
// inverse.
|
|
void vtkAbstractTransform::UnRegister(vtkObjectBase *o)
|
|
{
|
|
if (this->InUnRegister)
|
|
{ // we don't want to go into infinite recursion...
|
|
vtkDebugMacro(<<"UnRegister: circular reference eliminated");
|
|
this->ReferenceCount--;
|
|
return;
|
|
}
|
|
|
|
// check to see if the only reason our reference count is not 1
|
|
// is the circular reference from MyInverse
|
|
if (this->MyInverse && this->ReferenceCount == 2 &&
|
|
this->MyInverse->ReferenceCount == 1)
|
|
{ // break the cycle
|
|
vtkDebugMacro(<<"UnRegister: eliminating circular reference");
|
|
this->InUnRegister = 1;
|
|
this->MyInverse->UnRegister(this);
|
|
this->MyInverse = NULL;
|
|
this->InUnRegister = 0;
|
|
}
|
|
|
|
this->vtkObject::UnRegister(o);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
// All of the following methods are for vtkTransformConcatenation
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
// A very, very minimal transformation
|
|
class vtkSimpleTransform : public vtkHomogeneousTransform
|
|
{
|
|
public:
|
|
vtkTypeRevisionMacro(vtkSimpleTransform,vtkHomogeneousTransform);
|
|
static vtkSimpleTransform *New() {
|
|
#ifdef VTK_DEBUG_LEAKS
|
|
vtkDebugLeaks::ConstructClass("vtkSimpleTransform");
|
|
#endif
|
|
return new vtkSimpleTransform; };
|
|
vtkAbstractTransform *MakeTransform() { return vtkSimpleTransform::New(); };
|
|
void Inverse() { this->Matrix->Invert(); this->Modified(); };
|
|
protected:
|
|
vtkSimpleTransform() {};
|
|
vtkSimpleTransform(const vtkSimpleTransform&);
|
|
void operator=(const vtkSimpleTransform&);
|
|
};
|
|
|
|
vtkCxxRevisionMacro(vtkSimpleTransform, "$Revision: 1.26 $");
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkTransformConcatenation::vtkTransformConcatenation()
|
|
{
|
|
this->PreMatrix = NULL;
|
|
this->PostMatrix = NULL;
|
|
this->PreMatrixTransform = NULL;
|
|
this->PostMatrixTransform = NULL;
|
|
|
|
this->PreMultiplyFlag = 1;
|
|
this->InverseFlag = 0;
|
|
|
|
this->NumberOfTransforms = 0;
|
|
this->NumberOfPreTransforms = 0;
|
|
this->MaxNumberOfTransforms = 0;
|
|
|
|
// The transform list is the list of the transforms to be concatenated.
|
|
this->TransformList = NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkTransformConcatenation::~vtkTransformConcatenation()
|
|
{
|
|
if (this->NumberOfTransforms > 0)
|
|
{
|
|
for (int i = 0; i < this->NumberOfTransforms; i++)
|
|
{
|
|
vtkTransformPair *tuple = &this->TransformList[i];
|
|
if (tuple->ForwardTransform)
|
|
{
|
|
tuple->ForwardTransform->Delete();
|
|
}
|
|
if (tuple->InverseTransform)
|
|
{
|
|
tuple->InverseTransform->Delete();
|
|
}
|
|
}
|
|
}
|
|
if (this->TransformList)
|
|
{
|
|
delete [] this->TransformList;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenation::Concatenate(vtkAbstractTransform *trans)
|
|
{
|
|
// in case either PreMatrix or PostMatrix is going to be pushed
|
|
// into the concatenation from their position at the end
|
|
if (this->PreMultiplyFlag && this->PreMatrix)
|
|
{
|
|
this->PreMatrix = NULL;
|
|
this->PreMatrixTransform = NULL;
|
|
}
|
|
else if (!this->PreMultiplyFlag && this->PostMatrix)
|
|
{
|
|
this->PostMatrix = NULL;
|
|
this->PostMatrixTransform = NULL;
|
|
}
|
|
|
|
vtkTransformPair *transList = this->TransformList;
|
|
int n = this->NumberOfTransforms;
|
|
this->NumberOfTransforms++;
|
|
|
|
// check to see if we need to allocate more space
|
|
if (this->NumberOfTransforms > this->MaxNumberOfTransforms)
|
|
{
|
|
int nMax = this->MaxNumberOfTransforms + 5;
|
|
transList = new vtkTransformPair[nMax];
|
|
for (int i = 0; i < n; i++)
|
|
{
|
|
transList[i].ForwardTransform = this->TransformList[i].ForwardTransform;
|
|
transList[i].InverseTransform = this->TransformList[i].InverseTransform;
|
|
}
|
|
if (this->TransformList)
|
|
{
|
|
delete [] this->TransformList;
|
|
}
|
|
this->TransformList = transList;
|
|
this->MaxNumberOfTransforms = nMax;
|
|
}
|
|
|
|
// add the transform either the beginning or end of the list,
|
|
// according to flags
|
|
if (this->PreMultiplyFlag ^ this->InverseFlag)
|
|
{
|
|
for (int i = n; i > 0; i--)
|
|
{
|
|
transList[i].ForwardTransform = transList[i-1].ForwardTransform;
|
|
transList[i].InverseTransform = transList[i-1].InverseTransform;
|
|
}
|
|
n = 0;
|
|
this->NumberOfPreTransforms++;
|
|
}
|
|
|
|
trans->Register(NULL);
|
|
|
|
if (this->InverseFlag)
|
|
{
|
|
transList[n].ForwardTransform = NULL;
|
|
transList[n].InverseTransform = trans;
|
|
}
|
|
else
|
|
{
|
|
transList[n].ForwardTransform = trans;
|
|
transList[n].InverseTransform = NULL;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenation::Concatenate(const double elements[16])
|
|
{
|
|
// concatenate the matrix with either the Pre- or PostMatrix
|
|
if (this->PreMultiplyFlag)
|
|
{
|
|
if (this->PreMatrix == NULL)
|
|
{
|
|
// add the matrix to the concatenation
|
|
vtkSimpleTransform *mtrans = vtkSimpleTransform::New();
|
|
this->Concatenate(mtrans);
|
|
mtrans->Delete();
|
|
this->PreMatrixTransform = mtrans;
|
|
this->PreMatrix = mtrans->GetMatrix();
|
|
}
|
|
vtkMatrix4x4::Multiply4x4(*this->PreMatrix->Element, elements,
|
|
*this->PreMatrix->Element);
|
|
this->PreMatrix->Modified();
|
|
this->PreMatrixTransform->Modified();
|
|
}
|
|
else
|
|
{
|
|
if (this->PostMatrix == NULL)
|
|
{
|
|
// add the matrix to the concatenation
|
|
vtkSimpleTransform *mtrans = vtkSimpleTransform::New();
|
|
this->Concatenate(mtrans);
|
|
mtrans->Delete();
|
|
this->PostMatrixTransform = mtrans;
|
|
this->PostMatrix = mtrans->GetMatrix();
|
|
}
|
|
vtkMatrix4x4::Multiply4x4(elements, *this->PostMatrix->Element,
|
|
*this->PostMatrix->Element);
|
|
this->PostMatrix->Modified();
|
|
this->PostMatrixTransform->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenation::Translate(double x, double y, double z)
|
|
{
|
|
if (x == 0.0 && y == 0.0 && z == 0.0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
double matrix[4][4];
|
|
vtkMatrix4x4::Identity(*matrix);
|
|
|
|
matrix[0][3] = x;
|
|
matrix[1][3] = y;
|
|
matrix[2][3] = z;
|
|
|
|
this->Concatenate(*matrix);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenation::Rotate(double angle,
|
|
double x, double y, double z)
|
|
{
|
|
if (angle == 0.0 || (x == 0.0 && y == 0.0 && z == 0.0))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// convert to radians
|
|
angle = angle*vtkMath::DoubleDegreesToRadians();
|
|
|
|
// make a normalized quaternion
|
|
double w = cos(0.5*angle);
|
|
double f = sin(0.5*angle)/sqrt(x*x+y*y+z*z);
|
|
x *= f;
|
|
y *= f;
|
|
z *= f;
|
|
|
|
// convert the quaternion to a matrix
|
|
double matrix[4][4];
|
|
vtkMatrix4x4::Identity(*matrix);
|
|
|
|
double ww = w*w;
|
|
double wx = w*x;
|
|
double wy = w*y;
|
|
double wz = w*z;
|
|
|
|
double xx = x*x;
|
|
double yy = y*y;
|
|
double zz = z*z;
|
|
|
|
double xy = x*y;
|
|
double xz = x*z;
|
|
double yz = y*z;
|
|
|
|
double s = ww - xx - yy - zz;
|
|
|
|
matrix[0][0] = xx*2 + s;
|
|
matrix[1][0] = (xy + wz)*2;
|
|
matrix[2][0] = (xz - wy)*2;
|
|
|
|
matrix[0][1] = (xy - wz)*2;
|
|
matrix[1][1] = yy*2 + s;
|
|
matrix[2][1] = (yz + wx)*2;
|
|
|
|
matrix[0][2] = (xz + wy)*2;
|
|
matrix[1][2] = (yz - wx)*2;
|
|
matrix[2][2] = zz*2 + s;
|
|
|
|
this->Concatenate(*matrix);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenation::Scale(double x, double y, double z)
|
|
{
|
|
if (x == 1.0 && y == 1.0 && z == 1.0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
double matrix[4][4];
|
|
vtkMatrix4x4::Identity(*matrix);
|
|
|
|
matrix[0][0] = x;
|
|
matrix[1][1] = y;
|
|
matrix[2][2] = z;
|
|
|
|
this->Concatenate(*matrix);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenation::Inverse()
|
|
{
|
|
// invert the matrices
|
|
if (this->PreMatrix)
|
|
{
|
|
this->PreMatrix->Invert();
|
|
this->PreMatrixTransform->Modified();
|
|
int i = (this->InverseFlag ? this->NumberOfTransforms-1 : 0);
|
|
this->TransformList[i].SwapForwardInverse();
|
|
}
|
|
|
|
if (this->PostMatrix)
|
|
{
|
|
this->PostMatrix->Invert();
|
|
this->PostMatrixTransform->Modified();
|
|
int i = (this->InverseFlag ? 0 : this->NumberOfTransforms-1);
|
|
this->TransformList[i].SwapForwardInverse();
|
|
}
|
|
|
|
// swap the pre- and post-matrices
|
|
vtkMatrix4x4 *tmp = this->PreMatrix;
|
|
vtkAbstractTransform *tmp2 = this->PreMatrixTransform;
|
|
this->PreMatrix = this->PostMatrix;
|
|
this->PreMatrixTransform = this->PostMatrixTransform;
|
|
this->PostMatrix = tmp;
|
|
this->PostMatrixTransform = tmp2;
|
|
|
|
// what used to be pre-transforms are now post-transforms
|
|
this->NumberOfPreTransforms =
|
|
this->NumberOfTransforms - this->NumberOfPreTransforms;
|
|
|
|
this->InverseFlag = !this->InverseFlag;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenation::Identity()
|
|
{
|
|
// forget the Pre- and PostMatrix
|
|
this->PreMatrix = NULL;
|
|
this->PostMatrix = NULL;
|
|
this->PreMatrixTransform = NULL;
|
|
this->PostMatrixTransform = NULL;
|
|
|
|
// delete all the transforms
|
|
if (this->NumberOfTransforms > 0)
|
|
{
|
|
for (int i = 0; i < this->NumberOfTransforms; i++)
|
|
{
|
|
vtkTransformPair *tuple = &this->TransformList[i];
|
|
if (tuple->ForwardTransform)
|
|
{
|
|
tuple->ForwardTransform->Delete();
|
|
}
|
|
if (tuple->InverseTransform)
|
|
{
|
|
tuple->InverseTransform->Delete();
|
|
}
|
|
}
|
|
}
|
|
this->NumberOfTransforms = 0;
|
|
this->NumberOfPreTransforms = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkAbstractTransform *vtkTransformConcatenation::GetTransform(int i)
|
|
{
|
|
// we walk through the list in reverse order if InverseFlag is set
|
|
if (this->InverseFlag)
|
|
{
|
|
int j = this->NumberOfTransforms-i-1;
|
|
vtkTransformPair *tuple = &this->TransformList[j];
|
|
// if inverse is NULL, then get it from the forward transform
|
|
if (tuple->InverseTransform == NULL)
|
|
{
|
|
tuple->InverseTransform = tuple->ForwardTransform->GetInverse();
|
|
tuple->InverseTransform->Register(NULL);
|
|
}
|
|
return tuple->InverseTransform;
|
|
}
|
|
else
|
|
{
|
|
vtkTransformPair *tuple = &this->TransformList[i];
|
|
// if transform is NULL, then get it from its inverse
|
|
if (tuple->ForwardTransform == NULL)
|
|
{
|
|
tuple->ForwardTransform = tuple->InverseTransform->GetInverse();
|
|
tuple->ForwardTransform->Register(NULL);
|
|
}
|
|
return tuple->ForwardTransform;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
unsigned long vtkTransformConcatenation::GetMaxMTime()
|
|
{
|
|
unsigned long result = 0;
|
|
unsigned long mtime;
|
|
|
|
for (int i = 0; i < this->NumberOfTransforms; i++)
|
|
{
|
|
vtkTransformPair *tuple = &this->TransformList[i];
|
|
if (tuple->ForwardTransform)
|
|
{
|
|
mtime = tuple->ForwardTransform->GetMTime();
|
|
}
|
|
else
|
|
{
|
|
mtime = tuple->InverseTransform->GetMTime();
|
|
}
|
|
|
|
if (mtime > result)
|
|
{
|
|
result = mtime;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenation::DeepCopy(vtkTransformConcatenation *concat)
|
|
{
|
|
// allocate a larger list if necessary
|
|
if (this->MaxNumberOfTransforms < concat->NumberOfTransforms)
|
|
{
|
|
int newMax = concat->NumberOfTransforms;
|
|
vtkTransformPair *newList = new vtkTransformPair[newMax];
|
|
// copy items onto new list
|
|
int i = 0;
|
|
for (; i < this->NumberOfTransforms; i++)
|
|
{
|
|
newList[i].ForwardTransform = this->TransformList[i].ForwardTransform;
|
|
newList[i].InverseTransform = this->TransformList[i].InverseTransform;
|
|
}
|
|
for (; i < concat->NumberOfTransforms; i++)
|
|
{
|
|
newList[i].ForwardTransform = NULL;
|
|
newList[i].InverseTransform = NULL;
|
|
}
|
|
if (this->TransformList)
|
|
{
|
|
delete [] this->TransformList;
|
|
}
|
|
this->MaxNumberOfTransforms = newMax;
|
|
this->TransformList = newList;
|
|
}
|
|
|
|
// save the PreMatrix and PostMatrix in case they can be re-used
|
|
vtkSimpleTransform *oldPreMatrixTransform = NULL;
|
|
vtkSimpleTransform *oldPostMatrixTransform = NULL;
|
|
|
|
if (this->PreMatrix)
|
|
{
|
|
vtkTransformPair *tuple;
|
|
if (this->InverseFlag)
|
|
{
|
|
tuple = &this->TransformList[this->NumberOfTransforms-1];
|
|
tuple->SwapForwardInverse();
|
|
}
|
|
else
|
|
{
|
|
tuple = &this->TransformList[0];
|
|
}
|
|
tuple->ForwardTransform = NULL;
|
|
if (tuple->InverseTransform)
|
|
{
|
|
tuple->InverseTransform->Delete();
|
|
tuple->InverseTransform = NULL;
|
|
}
|
|
oldPreMatrixTransform = (vtkSimpleTransform *)this->PreMatrixTransform;
|
|
this->PreMatrixTransform = NULL;
|
|
this->PreMatrix = NULL;
|
|
}
|
|
|
|
if (this->PostMatrix)
|
|
{
|
|
vtkTransformPair *tuple;
|
|
if (this->InverseFlag)
|
|
{
|
|
tuple = &this->TransformList[0];
|
|
tuple->SwapForwardInverse();
|
|
}
|
|
else
|
|
{
|
|
tuple = &this->TransformList[this->NumberOfTransforms-1];
|
|
}
|
|
tuple->ForwardTransform = NULL;
|
|
if (tuple->InverseTransform)
|
|
{
|
|
tuple->InverseTransform->Delete();
|
|
tuple->InverseTransform = NULL;
|
|
}
|
|
oldPostMatrixTransform = (vtkSimpleTransform *)this->PostMatrixTransform;
|
|
this->PostMatrixTransform = NULL;
|
|
this->PostMatrix = NULL;
|
|
}
|
|
|
|
// the PreMatrix and PostMatrix transforms must be DeepCopied,
|
|
// not copied by reference, so adjust the copy loop accordingly
|
|
int i = 0;
|
|
int n = concat->NumberOfTransforms;
|
|
if (concat->PreMatrix)
|
|
{
|
|
if (concat->InverseFlag) { n--; } else { i++; }
|
|
}
|
|
if (concat->PostMatrix)
|
|
{
|
|
if (concat->InverseFlag) { i++; } else { n--; }
|
|
}
|
|
|
|
// copy the transforms by reference
|
|
for (; i < n; i++)
|
|
{
|
|
vtkTransformPair *pair = &this->TransformList[i];
|
|
vtkTransformPair *pair2 = &concat->TransformList[i];
|
|
|
|
if (pair->ForwardTransform != pair2->ForwardTransform)
|
|
{
|
|
if (pair->ForwardTransform && i < this->NumberOfTransforms)
|
|
{
|
|
pair->ForwardTransform->Delete();
|
|
}
|
|
pair->ForwardTransform = pair2->ForwardTransform;
|
|
if (pair->ForwardTransform)
|
|
{
|
|
pair->ForwardTransform->Register(NULL);
|
|
}
|
|
}
|
|
if (pair->InverseTransform != pair2->InverseTransform)
|
|
{
|
|
if (pair->InverseTransform && i < this->NumberOfTransforms)
|
|
{
|
|
pair->InverseTransform->Delete();
|
|
}
|
|
pair->InverseTransform = pair2->InverseTransform;
|
|
if (pair->InverseTransform)
|
|
{
|
|
pair->InverseTransform->Register(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
// delete surplus items from the list
|
|
for (i = concat->NumberOfTransforms; i < this->NumberOfTransforms; i++)
|
|
{
|
|
if (this->TransformList[i].ForwardTransform)
|
|
{
|
|
this->TransformList[i].ForwardTransform->Delete();
|
|
}
|
|
if (this->TransformList[i].InverseTransform)
|
|
{
|
|
this->TransformList[i].InverseTransform->Delete();
|
|
}
|
|
}
|
|
|
|
// make a DeepCopy of the PreMatrix transform
|
|
if (concat->PreMatrix)
|
|
{
|
|
i = (concat->InverseFlag ? concat->NumberOfTransforms-1 : 0);
|
|
vtkTransformPair *pair = &this->TransformList[i];
|
|
vtkSimpleTransform *mtrans;
|
|
|
|
if (concat->InverseFlag == this->InverseFlag)
|
|
{
|
|
mtrans = (oldPreMatrixTransform ? oldPreMatrixTransform :
|
|
vtkSimpleTransform::New());
|
|
oldPreMatrixTransform = NULL;
|
|
}
|
|
else
|
|
{
|
|
mtrans = (oldPostMatrixTransform ? oldPostMatrixTransform :
|
|
vtkSimpleTransform::New());
|
|
oldPostMatrixTransform = NULL;
|
|
}
|
|
|
|
this->PreMatrix = mtrans->GetMatrix();
|
|
this->PreMatrix->DeepCopy(concat->PreMatrix);
|
|
this->PreMatrixTransform = mtrans;
|
|
this->PreMatrixTransform->Modified();
|
|
|
|
if (pair->ForwardTransform)
|
|
{
|
|
pair->ForwardTransform->Delete();
|
|
pair->ForwardTransform = NULL;
|
|
}
|
|
if (pair->InverseTransform)
|
|
{
|
|
pair->InverseTransform->Delete();
|
|
pair->InverseTransform = NULL;
|
|
}
|
|
|
|
if (concat->InverseFlag)
|
|
{
|
|
pair->ForwardTransform = NULL;
|
|
pair->InverseTransform = this->PreMatrixTransform;
|
|
}
|
|
else
|
|
{
|
|
pair->ForwardTransform = this->PreMatrixTransform;
|
|
pair->InverseTransform = NULL;
|
|
}
|
|
}
|
|
|
|
// make a DeepCopy of the PostMatrix transform
|
|
if (concat->PostMatrix)
|
|
{
|
|
i = (concat->InverseFlag ? 0 : concat->NumberOfTransforms-1);
|
|
vtkTransformPair *pair = &this->TransformList[i];
|
|
vtkSimpleTransform *mtrans;
|
|
|
|
if (concat->InverseFlag == this->InverseFlag)
|
|
{
|
|
mtrans = (oldPostMatrixTransform ? oldPostMatrixTransform :
|
|
vtkSimpleTransform::New());
|
|
oldPostMatrixTransform = NULL;
|
|
}
|
|
else
|
|
{
|
|
mtrans = (oldPreMatrixTransform ? oldPreMatrixTransform :
|
|
vtkSimpleTransform::New());
|
|
oldPreMatrixTransform = NULL;
|
|
}
|
|
|
|
this->PostMatrix = mtrans->GetMatrix();
|
|
this->PostMatrix->DeepCopy(concat->PostMatrix);
|
|
this->PostMatrixTransform = mtrans;
|
|
this->PostMatrixTransform->Modified();
|
|
|
|
if (pair->ForwardTransform)
|
|
{
|
|
pair->ForwardTransform->Delete();
|
|
pair->ForwardTransform = NULL;
|
|
}
|
|
if (pair->InverseTransform)
|
|
{
|
|
pair->InverseTransform->Delete();
|
|
pair->InverseTransform = NULL;
|
|
}
|
|
if (concat->InverseFlag)
|
|
{
|
|
pair->ForwardTransform = NULL;
|
|
pair->InverseTransform = this->PostMatrixTransform;
|
|
}
|
|
else
|
|
{
|
|
pair->ForwardTransform = this->PostMatrixTransform;
|
|
pair->InverseTransform = NULL;
|
|
}
|
|
}
|
|
|
|
// delete the old PreMatrix and PostMatrix transforms if not re-used
|
|
if (oldPreMatrixTransform)
|
|
{
|
|
oldPreMatrixTransform->Delete();
|
|
}
|
|
if (oldPostMatrixTransform)
|
|
{
|
|
oldPostMatrixTransform->Delete();
|
|
}
|
|
|
|
// copy misc. ivars
|
|
this->InverseFlag = concat->InverseFlag;
|
|
this->PreMultiplyFlag = concat->PreMultiplyFlag;
|
|
|
|
this->NumberOfTransforms = concat->NumberOfTransforms;
|
|
this->NumberOfPreTransforms = concat->NumberOfPreTransforms;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenation::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
os << indent << "InverseFlag: " << this->InverseFlag << "\n";
|
|
os << indent << (this->PreMultiplyFlag ? "PreMultiply\n" : "PostMultiply\n");
|
|
os << indent << "NumberOfPreTransforms: " <<
|
|
this->GetNumberOfPreTransforms() << "\n";
|
|
os << indent << "NumberOfPostTransforms: " <<
|
|
this->GetNumberOfPostTransforms() << "\n";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
// All of the following methods are for vtkTransformConcatenationStack
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkTransformConcatenationStack::vtkTransformConcatenationStack()
|
|
{
|
|
this->StackSize = 0;
|
|
this->StackBottom = NULL;
|
|
this->Stack = NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkTransformConcatenationStack::~vtkTransformConcatenationStack()
|
|
{
|
|
int n = this->Stack-this->StackBottom;
|
|
for (int i = 0; i < n; i++)
|
|
{
|
|
this->StackBottom[i]->Delete();
|
|
}
|
|
|
|
if (this->StackBottom)
|
|
{
|
|
delete [] this->StackBottom;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenationStack::Pop(vtkTransformConcatenation **concat)
|
|
{
|
|
// if we're at the bottom of the stack, don't pop
|
|
if (this->Stack == this->StackBottom)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// get the previous PreMultiplyFlag
|
|
int preMultiplyFlag = (*concat)->GetPreMultiplyFlag();
|
|
|
|
// delete the previous item
|
|
(*concat)->Delete();
|
|
|
|
// pop new item off the stack
|
|
*concat = *--this->Stack;
|
|
|
|
// re-set the PreMultiplyFlag
|
|
(*concat)->SetPreMultiplyFlag(preMultiplyFlag);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenationStack::Push(vtkTransformConcatenation **concat)
|
|
{
|
|
// check stack size and grow if necessary
|
|
if ((this->Stack - this->StackBottom) == this->StackSize)
|
|
{
|
|
int newStackSize = this->StackSize + 10;
|
|
vtkTransformConcatenation **newStackBottom =
|
|
new vtkTransformConcatenation *[newStackSize];
|
|
for (int i = 0; i < this->StackSize; i++)
|
|
{
|
|
newStackBottom[i] = this->StackBottom[i];
|
|
}
|
|
if (this->StackBottom)
|
|
{
|
|
delete [] this->StackBottom;
|
|
}
|
|
this->StackBottom = newStackBottom;
|
|
this->Stack = this->StackBottom+this->StackSize;
|
|
this->StackSize = newStackSize;
|
|
}
|
|
|
|
// add item to the stack
|
|
*this->Stack++ = *concat;
|
|
|
|
// make a copy of that item the current item
|
|
*concat = vtkTransformConcatenation::New();
|
|
(*concat)->DeepCopy(*(this->Stack-1));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkTransformConcatenationStack::DeepCopy(
|
|
vtkTransformConcatenationStack *stack)
|
|
{
|
|
int n = stack->Stack - stack->StackBottom;
|
|
int m = this->Stack - this->StackBottom;
|
|
|
|
// check to see if we have to grow the stack
|
|
if (n > this->StackSize)
|
|
{
|
|
int newStackSize = n + n%10;
|
|
vtkTransformConcatenation **newStackBottom =
|
|
new vtkTransformConcatenation *[newStackSize];
|
|
for (int j = 0; j < m; j++)
|
|
{
|
|
newStackBottom[j] = this->StackBottom[j];
|
|
}
|
|
if (this->StackBottom)
|
|
{
|
|
delete [] this->StackBottom;
|
|
}
|
|
this->StackBottom = newStackBottom;
|
|
this->Stack = this->StackBottom+this->StackSize;
|
|
this->StackSize = newStackSize;
|
|
}
|
|
|
|
// delete surplus items
|
|
for (int l = n; l < m; l++)
|
|
{
|
|
(*--this->Stack)->Delete();
|
|
}
|
|
|
|
// allocate new items
|
|
for (int i = m; i < n; i++)
|
|
{
|
|
*this->Stack++ = vtkTransformConcatenation::New();
|
|
}
|
|
|
|
// deep copy the items
|
|
for (int k = 0; k < n; k++)
|
|
{
|
|
this->StackBottom[k]->DeepCopy(stack->StackBottom[k]);
|
|
}
|
|
}
|
|
|
|
#ifndef VTK_LEGACY_REMOVE
|
|
void vtkAbstractTransform::Identity()
|
|
{
|
|
vtkWarningMacro("vtkAbstractTransform::Identity() is deprecated");
|
|
}
|
|
#endif
|
|
|