/*========================================================================= Program: Visualization Toolkit Module: vtkLinearTransform.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 "vtkLinearTransform.h" #include "vtkDataArray.h" #include "vtkMath.h" #include "vtkMatrix4x4.h" #include "vtkPoints.h" //------------------------------------------------------------------------ void vtkLinearTransform::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } //------------------------------------------------------------------------ template inline void vtkLinearTransformPoint(T1 matrix[4][4], T2 in[3], T3 out[3]) { T3 x = static_cast( matrix[0][0]*in[0]+matrix[0][1]*in[1]+matrix[0][2]*in[2]+matrix[0][3]); T3 y = static_cast( matrix[1][0]*in[0]+matrix[1][1]*in[1]+matrix[1][2]*in[2]+matrix[1][3]); T3 z = static_cast( matrix[2][0]*in[0]+matrix[2][1]*in[1]+matrix[2][2]*in[2]+matrix[2][3]); out[0] = x; out[1] = y; out[2] = z; } //------------------------------------------------------------------------ template inline void vtkLinearTransformDerivative(T1 matrix[4][4], T2 in[3], T3 out[3], T4 derivative[3][3]) { vtkLinearTransformPoint(matrix,in,out); for (int i = 0; i < 3; i++) { derivative[0][i] = static_cast(matrix[0][i]); derivative[1][i] = static_cast(matrix[1][i]); derivative[2][i] = static_cast(matrix[2][i]); } } //------------------------------------------------------------------------ template inline void vtkLinearTransformVector(T1 matrix[4][4], T2 in[3], T3 out[3]) { T3 x = static_cast( matrix[0][0]*in[0] + matrix[0][1]*in[1] + matrix[0][2]*in[2]); T3 y = static_cast( matrix[1][0]*in[0] + matrix[1][1]*in[1] + matrix[1][2]*in[2]); T3 z = static_cast( matrix[2][0]*in[0] + matrix[2][1]*in[1] + matrix[2][2]*in[2]); out[0] = x; out[1] = y; out[2] = z; } //------------------------------------------------------------------------ template inline void vtkLinearTransformNormal(T1 mat[4][4], T2 in[3], T3 out[3]) { // to transform the normal, multiply by the transposed inverse matrix T1 matrix[4][4]; memcpy(*matrix,*mat,16*sizeof(T1)); vtkMatrix4x4::Invert(*matrix,*matrix); vtkMatrix4x4::Transpose(*matrix,*matrix); vtkLinearTransformVector(matrix,in,out); vtkMath::Normalize(out); } //------------------------------------------------------------------------ template inline void vtkLinearTransformPoints( T1 matrix[4][4], T2 *in, T3 *out, vtkIdType n) { for (vtkIdType i = 0; i < n; i++) { vtkLinearTransformPoint(matrix, in, out); in += 3; out += 3; } } //------------------------------------------------------------------------ template inline void vtkLinearTransformVectors( T1 matrix[4][4], T2 *in, T3 *out, vtkIdType n) { for (vtkIdType i = 0; i < n; i++) { vtkLinearTransformVector(matrix, in, out); in += 3; out += 3; } } //------------------------------------------------------------------------ template inline void vtkLinearTransformNormals( T1 matrix[4][4], T2 *in, T3 *out, vtkIdType n) { for (vtkIdType i = 0; i < n; i++) { // matrix has been transposed & inverted, so use TransformVector vtkLinearTransformVector(matrix, in, out); vtkMath::Normalize(out); in += 3; out += 3; } } //------------------------------------------------------------------------ void vtkLinearTransform::InternalTransformPoint(const float in[3], float out[3]) { vtkLinearTransformPoint(this->Matrix->Element,in,out); } //------------------------------------------------------------------------ void vtkLinearTransform::InternalTransformPoint(const double in[3], double out[3]) { vtkLinearTransformPoint(this->Matrix->Element,in,out); } //------------------------------------------------------------------------ void vtkLinearTransform::InternalTransformNormal(const float in[3], float out[3]) { vtkLinearTransformNormal(this->Matrix->Element,in,out); } //------------------------------------------------------------------------ void vtkLinearTransform::InternalTransformNormal(const double in[3], double out[3]) { vtkLinearTransformNormal(this->Matrix->Element,in,out); } //------------------------------------------------------------------------ void vtkLinearTransform::InternalTransformVector(const float in[3], float out[3]) { vtkLinearTransformVector(this->Matrix->Element,in,out); } //------------------------------------------------------------------------ void vtkLinearTransform::InternalTransformVector(const double in[3], double out[3]) { vtkLinearTransformVector(this->Matrix->Element,in,out); } //---------------------------------------------------------------------------- void vtkLinearTransform::InternalTransformDerivative(const float in[3], float out[3], float derivative[3][3]) { vtkLinearTransformDerivative(this->Matrix->Element,in,out,derivative); } //---------------------------------------------------------------------------- void vtkLinearTransform::InternalTransformDerivative(const double in[3], double out[3], double derivative[3][3]) { vtkLinearTransformDerivative(this->Matrix->Element,in,out,derivative); } //---------------------------------------------------------------------------- // Transform the normals and vectors using the derivative of the // transformation. Either inNms or inVrs can be set to nullptr. // 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 vtkLinearTransform::TransformPointsNormalsVectors(vtkPoints *inPts, vtkPoints *outPts, vtkDataArray *inNms, vtkDataArray *outNms, vtkDataArray *inVrs, vtkDataArray *outVrs) { this->TransformPoints(inPts, outPts); if (inNms) { this->TransformNormals(inNms, outNms); } if (inVrs) { this->TransformVectors(inVrs, outVrs); } } //---------------------------------------------------------------------------- void vtkLinearTransform::TransformPoints(vtkPoints *inPts, vtkPoints *outPts) { vtkIdType n = inPts->GetNumberOfPoints(); vtkIdType m = outPts->GetNumberOfPoints(); double (*matrix)[4] = this->Matrix->Element; this->Update(); // operate directly on the memory to avoid GetPoint()/SetPoint() calls. vtkDataArray *inArray = inPts->GetData(); vtkDataArray *outArray = outPts->GetData(); int inType = inArray->GetDataType(); int outType = outArray->GetDataType(); void *inPtr = inArray->GetVoidPointer(0); void *outPtr = outArray->WriteVoidPointer(3*m, 3*n); if (inType == VTK_FLOAT && outType == VTK_FLOAT) { vtkLinearTransformPoints(matrix, static_cast(inPtr), static_cast(outPtr), n); } else if (inType == VTK_FLOAT && outType == VTK_DOUBLE) { vtkLinearTransformPoints(matrix, static_cast(inPtr), static_cast(outPtr), n); } else if (inType == VTK_DOUBLE && outType == VTK_FLOAT) { vtkLinearTransformPoints(matrix, static_cast(inPtr), static_cast(outPtr), n); } else if (inType == VTK_DOUBLE && outType == VTK_DOUBLE) { vtkLinearTransformPoints(matrix, static_cast(inPtr), static_cast(outPtr), n); } else { double point[3]; for (vtkIdType i = 0; i < n; i++) { inPts->GetPoint(i, point); vtkLinearTransformPoint(matrix, point, point); outPts->SetPoint(m + i, point); } } } //---------------------------------------------------------------------------- void vtkLinearTransform::TransformNormals(vtkDataArray *inNms, vtkDataArray *outNms) { vtkIdType n = inNms->GetNumberOfTuples(); vtkIdType m = outNms->GetNumberOfTuples(); double matrix[4][4]; this->Update(); // to transform the normal, multiply by the transposed inverse matrix vtkMatrix4x4::DeepCopy(*matrix,this->Matrix); vtkMatrix4x4::Invert(*matrix,*matrix); vtkMatrix4x4::Transpose(*matrix,*matrix); // operate directly on the memory to avoid GetTuple()/SetPoint() calls. int inType = inNms->GetDataType(); int outType = outNms->GetDataType(); void *inPtr = inNms->GetVoidPointer(0); void *outPtr = outNms->WriteVoidPointer(3*m, 3*n); if (inType == VTK_FLOAT && outType == VTK_FLOAT) { vtkLinearTransformNormals(matrix, static_cast(inPtr), static_cast(outPtr), n); } else if (inType == VTK_FLOAT && outType == VTK_DOUBLE) { vtkLinearTransformNormals(matrix, static_cast(inPtr), static_cast(outPtr), n); } else if (inType == VTK_DOUBLE && outType == VTK_FLOAT) { vtkLinearTransformNormals(matrix, static_cast(inPtr), static_cast(outPtr), n); } else if (inType == VTK_DOUBLE && outType == VTK_DOUBLE) { vtkLinearTransformNormals(matrix, static_cast(inPtr), static_cast(outPtr), n); } else { for (vtkIdType i = 0; i < n; i++) { double norm[3]; inNms->GetTuple(i, norm); // use TransformVector because matrix is already transposed & inverted vtkLinearTransformVector(matrix, norm, norm); vtkMath::Normalize(norm); outNms->SetTuple(m + i, norm); } } } //---------------------------------------------------------------------------- void vtkLinearTransform::TransformVectors(vtkDataArray *inVrs, vtkDataArray *outVrs) { vtkIdType n = inVrs->GetNumberOfTuples(); vtkIdType m = outVrs->GetNumberOfTuples(); double (*matrix)[4] = this->Matrix->Element; this->Update(); // operate directly on the memory to avoid GetTuple()/SetTuple() calls. int inType = inVrs->GetDataType(); int outType = outVrs->GetDataType(); void *inPtr = inVrs->GetVoidPointer(0); void *outPtr = outVrs->WriteVoidPointer(3*m, 3*n); if (inType == VTK_FLOAT && outType == VTK_FLOAT) { vtkLinearTransformVectors(matrix, static_cast(inPtr), static_cast(outPtr), n); } else if (inType == VTK_FLOAT && outType == VTK_DOUBLE) { vtkLinearTransformVectors(matrix, static_cast(inPtr), static_cast(outPtr), n); } else if (inType == VTK_DOUBLE && outType == VTK_FLOAT) { vtkLinearTransformVectors(matrix, static_cast(inPtr), static_cast(outPtr), n); } else if (inType == VTK_DOUBLE && outType == VTK_DOUBLE) { vtkLinearTransformVectors(matrix, static_cast(inPtr), static_cast(outPtr), n); } else { for (vtkIdType i = 0; i < n; i++) { double vec[3]; inVrs->GetTuple(i, vec); vtkLinearTransformVector(matrix, vec, vec); outVrs->SetTuple(m + i, vec); } } }