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.
740 lines
22 KiB
740 lines
22 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkAppendPolyData.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 "vtkAppendPolyData.h"
|
|
|
|
#include "vtkAlgorithmOutput.h"
|
|
#include "vtkCellArray.h"
|
|
#include "vtkCellData.h"
|
|
#include "vtkDataSetAttributes.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkPolyData.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
|
|
vtkCxxRevisionMacro(vtkAppendPolyData, "$Revision: 1.98 $");
|
|
vtkStandardNewMacro(vtkAppendPolyData);
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkAppendPolyData::vtkAppendPolyData()
|
|
{
|
|
this->ParallelStreaming = 0;
|
|
this->UserManagedInputs = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkAppendPolyData::~vtkAppendPolyData()
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Add a dataset to the list of data to append.
|
|
void vtkAppendPolyData::AddInput(vtkPolyData *ds)
|
|
{
|
|
if (this->UserManagedInputs)
|
|
{
|
|
vtkErrorMacro(<<
|
|
"AddInput is not supported if UserManagedInputs is true");
|
|
return;
|
|
}
|
|
this->Superclass::AddInput(ds);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Remove a dataset from the list of data to append.
|
|
void vtkAppendPolyData::RemoveInput(vtkPolyData *ds)
|
|
{
|
|
if (this->UserManagedInputs)
|
|
{
|
|
vtkErrorMacro(<<
|
|
"RemoveInput is not supported if UserManagedInputs is true");
|
|
return;
|
|
}
|
|
|
|
vtkAlgorithmOutput *algOutput = 0;
|
|
if (ds)
|
|
{
|
|
algOutput = ds->GetProducerPort();
|
|
}
|
|
|
|
this->RemoveInputConnection(0, algOutput);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// make ProcessObject function visible
|
|
// should only be used when UserManagedInputs is true.
|
|
void vtkAppendPolyData::SetNumberOfInputs(int num)
|
|
{
|
|
if (!this->UserManagedInputs)
|
|
{
|
|
vtkErrorMacro(<<
|
|
"SetNumberOfInputs is not supported if UserManagedInputs is false");
|
|
return;
|
|
}
|
|
|
|
// Ask the superclass to set the number of connections.
|
|
this->SetNumberOfInputConnections(0, num);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Set Nth input, should only be used when UserManagedInputs is true.
|
|
void vtkAppendPolyData::SetInputByNumber(int num, vtkPolyData *input)
|
|
{
|
|
if (!this->UserManagedInputs)
|
|
{
|
|
vtkErrorMacro(<<
|
|
"SetInputByNumber is not supported if UserManagedInputs is false");
|
|
return;
|
|
}
|
|
|
|
// Ask the superclass to connect the input.
|
|
this->SetNthInputConnection(0, num, input? input->GetProducerPort() : 0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This method is much too long, and has to be broken up!
|
|
// Append data sets into single polygonal data set.
|
|
int vtkAppendPolyData::RequestData(vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **inputVector,
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the info object
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
// get the ouptut
|
|
vtkPolyData *output = vtkPolyData::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
int idx;
|
|
vtkPolyData *ds;
|
|
vtkPoints *inPts;
|
|
vtkPoints *newPts;
|
|
vtkCellArray *inVerts, *newVerts;
|
|
vtkCellArray *inLines, *newLines;
|
|
vtkCellArray *inPolys, *newPolys;
|
|
vtkIdType sizePolys, numPolys;
|
|
vtkCellArray *inStrips, *newStrips;
|
|
vtkIdType numPts, numCells;
|
|
vtkPointData *inPD = NULL;
|
|
vtkCellData *inCD = NULL;
|
|
vtkPointData *outputPD = output->GetPointData();
|
|
vtkCellData *outputCD = output->GetCellData();
|
|
vtkDataArray *newPtScalars = NULL;
|
|
vtkDataArray *newPtVectors = NULL;
|
|
vtkDataArray *newPtNormals = NULL;
|
|
vtkDataArray *newPtTCoords = NULL;
|
|
vtkDataArray *newPtTensors = NULL;
|
|
int i;
|
|
vtkIdType *pts = 0;
|
|
vtkIdType *pPolys;
|
|
vtkIdType npts = 0;
|
|
vtkIdType ptId, cellId;
|
|
|
|
vtkDebugMacro(<<"Appending polydata");
|
|
|
|
// loop over all data sets, checking to see what point data is available.
|
|
numPts = 0;
|
|
numCells = 0;
|
|
sizePolys = numPolys = 0;
|
|
|
|
int countPD=0;
|
|
int countCD=0;
|
|
|
|
int numInputs = this->GetNumberOfInputConnections(0);
|
|
vtkInformation *inInfo;
|
|
|
|
// These Field lists are very picky. Count the number of non empty inputs
|
|
// so we can initialize them properly.
|
|
for (idx = 0; idx < numInputs; ++idx)
|
|
{
|
|
inInfo = inputVector[0]->GetInformationObject(idx);
|
|
ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
if (ds != NULL)
|
|
{
|
|
if ( ds->GetNumberOfPoints() > 0)
|
|
{
|
|
++countPD;
|
|
}
|
|
if (ds->GetNumberOfCells() > 0 )
|
|
{
|
|
++countCD;
|
|
} // for a data set that has cells
|
|
} // for a non NULL input
|
|
} // for each input
|
|
|
|
// These are used to determine which fields are available for appending
|
|
vtkDataSetAttributes::FieldList ptList(countPD);
|
|
vtkDataSetAttributes::FieldList cellList(countCD);
|
|
|
|
countPD = countCD = 0;
|
|
for (idx = 0; idx < numInputs; ++idx)
|
|
{
|
|
inInfo = inputVector[0]->GetInformationObject(idx);
|
|
ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
if (ds != NULL)
|
|
{
|
|
// Skip points and cells if there are no points. Empty inputs may have no arrays.
|
|
if ( ds->GetNumberOfPoints() > 0)
|
|
{
|
|
numPts += ds->GetNumberOfPoints();
|
|
// Take intersection of available point data fields.
|
|
inPD = ds->GetPointData();
|
|
if ( countPD == 0 )
|
|
{
|
|
ptList.InitializeFieldList(inPD);
|
|
}
|
|
else
|
|
{
|
|
ptList.IntersectFieldList(inPD);
|
|
}
|
|
++countPD;
|
|
} // for a data set that has points
|
|
|
|
// Although we cannot have cells without points ... let's not nest.
|
|
if (ds->GetNumberOfCells() > 0 )
|
|
{
|
|
// keep track of the size of the poly cell array
|
|
if (ds->GetPolys())
|
|
{
|
|
numPolys += ds->GetPolys()->GetNumberOfCells();
|
|
sizePolys += ds->GetPolys()->GetNumberOfConnectivityEntries();
|
|
}
|
|
numCells += ds->GetNumberOfCells();
|
|
|
|
inCD = ds->GetCellData();
|
|
if ( countCD == 0 )
|
|
{
|
|
cellList.InitializeFieldList(inCD);
|
|
}
|
|
else
|
|
{
|
|
cellList.IntersectFieldList(inCD);
|
|
}
|
|
++countCD;
|
|
} // for a data set that has cells
|
|
} // for a non NULL input
|
|
} // for each input
|
|
|
|
if ( numPts < 1 || numCells < 1 )
|
|
{
|
|
vtkDebugMacro(<<"No data to append!");
|
|
return 1;
|
|
}
|
|
this->UpdateProgress(0.10);
|
|
|
|
// Examine the points and check if they're the same type. If not,
|
|
// use highest (double probably), otherwise the type of the first
|
|
// array (float no doubt). Depends on defs in vtkSetGet.h - Warning.
|
|
int ttype, firstType=1, AllSame=1;
|
|
int pointtype = 0;
|
|
|
|
// Keep track of types for fast point append
|
|
for (idx = 0; idx < numInputs; ++idx)
|
|
{
|
|
inInfo = inputVector[0]->GetInformationObject(idx);
|
|
ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
if (ds != NULL && ds->GetNumberOfPoints()>0)
|
|
{
|
|
if ( firstType )
|
|
{
|
|
firstType = 0;
|
|
pointtype = ds->GetPoints()->GetData()->GetDataType();
|
|
}
|
|
ttype = ds->GetPoints()->GetData()->GetDataType();
|
|
|
|
if ( ttype != pointtype )
|
|
{
|
|
AllSame = 0;
|
|
vtkDebugMacro(<<"Different point data types");
|
|
}
|
|
pointtype = pointtype > ttype ? pointtype : ttype;
|
|
}
|
|
}
|
|
|
|
// Allocate geometry/topology
|
|
newPts = vtkPoints::New(pointtype);
|
|
newPts->SetNumberOfPoints(numPts);
|
|
|
|
newVerts = vtkCellArray::New();
|
|
newVerts->Allocate(numCells*4);
|
|
|
|
newLines = vtkCellArray::New();
|
|
newLines->Allocate(numCells*4);
|
|
|
|
newStrips = vtkCellArray::New();
|
|
newStrips->Allocate(numCells*4);
|
|
|
|
newPolys = vtkCellArray::New();
|
|
pPolys = newPolys->WritePointer(numPolys, sizePolys);
|
|
|
|
// These are created manually for faster execution
|
|
// Uses the properties of the last input
|
|
if ( ptList.IsAttributePresent(vtkDataSetAttributes::SCALARS) > -1 )
|
|
{
|
|
outputPD->CopyScalarsOff();
|
|
newPtScalars = inPD->GetScalars()->NewInstance();
|
|
newPtScalars->SetNumberOfComponents(inPD->GetScalars()->GetNumberOfComponents());
|
|
newPtScalars->SetName(inPD->GetScalars()->GetName());
|
|
newPtScalars->SetNumberOfTuples(numPts);
|
|
}
|
|
if ( ptList.IsAttributePresent(vtkDataSetAttributes::VECTORS) > -1 )
|
|
{
|
|
outputPD->CopyVectorsOff();
|
|
newPtVectors = inPD->GetVectors()->NewInstance();
|
|
newPtVectors->SetNumberOfComponents(inPD->GetVectors()->GetNumberOfComponents());
|
|
newPtVectors->SetName(inPD->GetVectors()->GetName());
|
|
newPtVectors->SetNumberOfTuples(numPts);
|
|
}
|
|
if ( ptList.IsAttributePresent(vtkDataSetAttributes::TENSORS) > -1 )
|
|
{
|
|
outputPD->CopyTensorsOff();
|
|
newPtTensors = inPD->GetTensors()->NewInstance();
|
|
newPtTensors->SetNumberOfComponents(inPD->GetTensors()->GetNumberOfComponents());
|
|
newPtTensors->SetName(inPD->GetTensors()->GetName());
|
|
newPtTensors->SetNumberOfTuples(numPts);
|
|
}
|
|
if ( ptList.IsAttributePresent(vtkDataSetAttributes::NORMALS) > -1 )
|
|
{
|
|
outputPD->CopyNormalsOff();
|
|
newPtNormals = inPD->GetNormals()->NewInstance();
|
|
newPtNormals->SetNumberOfComponents(inPD->GetNormals()->GetNumberOfComponents());
|
|
newPtNormals->SetName(inPD->GetNormals()->GetName());
|
|
newPtNormals->SetNumberOfTuples(numPts);
|
|
}
|
|
if ( ptList.IsAttributePresent(vtkDataSetAttributes::TCOORDS) > -1 )
|
|
{
|
|
outputPD->CopyTCoordsOff();
|
|
newPtTCoords = inPD->GetTCoords()->NewInstance();
|
|
newPtTCoords->SetNumberOfComponents(inPD->GetTCoords()->GetNumberOfComponents());
|
|
newPtTCoords->SetName(inPD->GetTCoords()->GetName());
|
|
newPtTCoords->SetNumberOfTuples(numPts);
|
|
}
|
|
|
|
// Allocate the point and cell data
|
|
outputPD->CopyAllocate(ptList,numPts);
|
|
outputCD->CopyAllocate(cellList,numCells);
|
|
|
|
// loop over all input sets
|
|
vtkIdType ptOffset = 0;
|
|
vtkIdType cellOffset = 0;
|
|
countPD = countCD = 0;
|
|
for (idx = 0; idx < numInputs; ++idx)
|
|
{
|
|
this->UpdateProgress(0.2 + 0.8*idx/numInputs);
|
|
inInfo = inputVector[0]->GetInformationObject(idx);
|
|
ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
// this check is not necessary, but I'll put it in anyway
|
|
if (ds != NULL)
|
|
{
|
|
numPts = ds->GetNumberOfPoints();
|
|
numCells = ds->GetNumberOfCells();
|
|
if ( numPts <= 0 && numCells <= 0 )
|
|
{
|
|
continue; //no input, just skip
|
|
}
|
|
|
|
inPD = ds->GetPointData();
|
|
inCD = ds->GetCellData();
|
|
|
|
inPts = ds->GetPoints();
|
|
inVerts = ds->GetVerts();
|
|
inLines = ds->GetLines();
|
|
inPolys = ds->GetPolys();
|
|
inStrips = ds->GetStrips();
|
|
|
|
if (ds->GetNumberOfPoints() > 0)
|
|
{
|
|
// copy points directly
|
|
if (AllSame)
|
|
{
|
|
this->AppendData(newPts->GetData(),
|
|
inPts->GetData(), ptOffset);
|
|
}
|
|
else
|
|
{
|
|
this->AppendDifferentPoints(newPts->GetData(),
|
|
inPts->GetData(), ptOffset);
|
|
}
|
|
// copy scalars directly
|
|
if (newPtScalars)
|
|
{
|
|
this->AppendData(newPtScalars,inPD->GetScalars(), ptOffset);
|
|
}
|
|
// copy normals directly
|
|
if (newPtNormals)
|
|
{
|
|
this->AppendData(newPtNormals, inPD->GetNormals(), ptOffset);
|
|
}
|
|
// copy vectors directly
|
|
if (newPtVectors)
|
|
{
|
|
this->AppendData(newPtVectors, inPD->GetVectors(), ptOffset);
|
|
}
|
|
// copy tcoords directly
|
|
if (newPtTCoords)
|
|
{
|
|
this->AppendData(newPtTCoords, inPD->GetTCoords() , ptOffset);
|
|
}
|
|
// copy tensors directly
|
|
if (newPtTensors)
|
|
{
|
|
this->AppendData(newPtTensors, inPD->GetTensors(), ptOffset);
|
|
}
|
|
// append the remainder of the field data
|
|
for (ptId=0; ptId < numPts; ptId++)
|
|
{
|
|
outputPD->CopyData(ptList,inPD,countPD,ptId,ptId+ptOffset);
|
|
}
|
|
++countPD;
|
|
}
|
|
|
|
if (ds->GetNumberOfCells() > 0)
|
|
{
|
|
// cell data could be made efficient like the point data,
|
|
// but I will wait on that.
|
|
// copy cell data
|
|
for (cellId=0; cellId < numCells; cellId++)
|
|
{
|
|
outputCD->CopyData(cellList,inCD,countCD,cellId,cellId+cellOffset);
|
|
}
|
|
++countCD;
|
|
|
|
// copy the cells
|
|
pPolys = this->AppendCells(pPolys, inPolys, ptOffset);
|
|
|
|
// These other cell arrays could be made efficient like polys ...
|
|
for (inVerts->InitTraversal(); inVerts->GetNextCell(npts,pts); )
|
|
{
|
|
newVerts->InsertNextCell(npts);
|
|
for (i=0; i < npts; i++)
|
|
{
|
|
newVerts->InsertCellPoint(pts[i]+ptOffset);
|
|
}
|
|
}
|
|
|
|
for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); )
|
|
{
|
|
newLines->InsertNextCell(npts);
|
|
for (i=0; i < npts; i++)
|
|
{
|
|
newLines->InsertCellPoint(pts[i]+ptOffset);
|
|
}
|
|
}
|
|
|
|
for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
|
|
{
|
|
newStrips->InsertNextCell(npts);
|
|
for (i=0; i < npts; i++)
|
|
{
|
|
newStrips->InsertCellPoint(pts[i]+ptOffset);
|
|
}
|
|
}
|
|
}
|
|
ptOffset += numPts;
|
|
cellOffset += numCells;
|
|
}
|
|
}
|
|
|
|
// Update ourselves and release memory
|
|
//
|
|
output->SetPoints(newPts);
|
|
newPts->Delete();
|
|
|
|
if (newPtScalars)
|
|
{
|
|
output->GetPointData()->SetScalars(newPtScalars);
|
|
newPtScalars->Delete();
|
|
}
|
|
if (newPtNormals)
|
|
{
|
|
output->GetPointData()->SetNormals(newPtNormals);
|
|
newPtNormals->Delete();
|
|
}
|
|
if (newPtVectors)
|
|
{
|
|
output->GetPointData()->SetVectors(newPtVectors);
|
|
newPtVectors->Delete();
|
|
}
|
|
if (newPtTCoords)
|
|
{
|
|
output->GetPointData()->SetTCoords(newPtTCoords);
|
|
newPtTCoords->Delete();
|
|
}
|
|
if (newPtTensors)
|
|
{
|
|
output->GetPointData()->SetTensors(newPtTensors);
|
|
newPtTensors->Delete();
|
|
}
|
|
|
|
if ( newVerts->GetNumberOfCells() > 0 )
|
|
{
|
|
output->SetVerts(newVerts);
|
|
}
|
|
newVerts->Delete();
|
|
|
|
if ( newLines->GetNumberOfCells() > 0 )
|
|
{
|
|
output->SetLines(newLines);
|
|
}
|
|
newLines->Delete();
|
|
|
|
if ( newPolys->GetNumberOfCells() > 0 )
|
|
{
|
|
output->SetPolys(newPolys);
|
|
}
|
|
newPolys->Delete();
|
|
|
|
if ( newStrips->GetNumberOfCells() > 0 )
|
|
{
|
|
output->SetStrips(newStrips);
|
|
}
|
|
newStrips->Delete();
|
|
|
|
// When all optimizations are complete, this squeeze will be unecessary.
|
|
// (But it does not seem to cost much.)
|
|
output->Squeeze();
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkAppendPolyData::RequestUpdateExtent(vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **inputVector,
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the output info object
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
int piece, numPieces, ghostLevel;
|
|
int idx;
|
|
|
|
piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
|
|
numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
|
|
ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
|
|
|
|
// make sure piece is valid
|
|
if (piece < 0 || piece >= numPieces)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int numInputs = this->GetNumberOfInputConnections(0);
|
|
if (this->ParallelStreaming)
|
|
{
|
|
piece = piece * numInputs;
|
|
numPieces = numPieces * numInputs;
|
|
}
|
|
|
|
vtkInformation *inInfo;
|
|
// just copy the Update extent as default behavior.
|
|
for (idx = 0; idx < numInputs; ++idx)
|
|
{
|
|
inInfo = inputVector[0]->GetInformationObject(idx);
|
|
if (inInfo)
|
|
{
|
|
if (this->ParallelStreaming)
|
|
{
|
|
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
|
|
piece + idx);
|
|
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
|
|
numPieces);
|
|
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
|
|
ghostLevel);
|
|
}
|
|
else
|
|
{
|
|
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
|
|
piece);
|
|
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
|
|
numPieces);
|
|
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
|
|
ghostLevel);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkPolyData *vtkAppendPolyData::GetInput(int idx)
|
|
{
|
|
return vtkPolyData::SafeDownCast(
|
|
this->GetExecutive()->GetInputData(0, idx));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAppendPolyData::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << "ParallelStreaming:" << (this->ParallelStreaming?"On":"Off") << endl;
|
|
os << "UserManagedInputs:" << (this->UserManagedInputs?"On":"Off") << endl;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class T>
|
|
size_t vtkAppendPolyDataGetTypeSize(T*)
|
|
{
|
|
return sizeof(T);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAppendPolyData::AppendData(vtkDataArray *dest, vtkDataArray *src,
|
|
vtkIdType offset)
|
|
{
|
|
void *pSrc, *pDest;
|
|
vtkIdType length;
|
|
|
|
// sanity checks
|
|
if (src->GetDataType() != dest->GetDataType())
|
|
{
|
|
vtkErrorMacro("Data type mismatch.");
|
|
return;
|
|
}
|
|
if (src->GetNumberOfComponents() != dest->GetNumberOfComponents())
|
|
{
|
|
vtkErrorMacro("NumberOfComponents mismatch.");
|
|
return;
|
|
}
|
|
if (src->GetNumberOfTuples() + offset > dest->GetNumberOfTuples())
|
|
{
|
|
vtkErrorMacro("Destination not big enough");
|
|
return;
|
|
}
|
|
|
|
// convert from tuples to components.
|
|
offset *= src->GetNumberOfComponents();
|
|
length = src->GetMaxId() + 1;
|
|
|
|
switch (src->GetDataType())
|
|
{
|
|
vtkTemplateMacro(
|
|
length *= vtkAppendPolyDataGetTypeSize(static_cast<VTK_TT*>(0))
|
|
);
|
|
default:
|
|
vtkErrorMacro("Unknown data type " << src->GetDataType());
|
|
}
|
|
|
|
pSrc = src->GetVoidPointer(0);
|
|
pDest = dest->GetVoidPointer(offset);
|
|
|
|
memcpy(pDest, pSrc, length);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkAppendPolyData::AppendDifferentPoints(vtkDataArray *dest,
|
|
vtkDataArray *src,
|
|
vtkIdType offset)
|
|
{
|
|
float *fSrc;
|
|
double *dSrc, *dDest;
|
|
vtkIdType p;
|
|
|
|
if (src->GetNumberOfTuples() + offset > dest->GetNumberOfTuples())
|
|
{
|
|
vtkErrorMacro("Destination not big enough");
|
|
return;
|
|
}
|
|
|
|
vtkIdType vals = src->GetMaxId()+1;
|
|
switch (dest->GetDataType())
|
|
{
|
|
//
|
|
// Dest is FLOAT - if sources are not all same type, dest ought to
|
|
// be double. (assuming float and double are the only choices)
|
|
//
|
|
case VTK_FLOAT:
|
|
vtkErrorMacro("Dest type should be double? "
|
|
<< dest->GetDataType());
|
|
break;
|
|
//
|
|
// Dest is DOUBLE - sources may be mixed float/double combinations
|
|
//
|
|
|
|
case VTK_DOUBLE:
|
|
dDest = (double*)(dest->GetVoidPointer(offset*src->GetNumberOfComponents()));
|
|
//
|
|
switch (src->GetDataType())
|
|
{
|
|
case VTK_FLOAT:
|
|
fSrc = (float*)(src->GetVoidPointer(0));
|
|
for (p=0; p<vals; p++)
|
|
{
|
|
dDest[p] = (double) fSrc[p];
|
|
}
|
|
break;
|
|
case VTK_DOUBLE:
|
|
dSrc = (double*)(src->GetVoidPointer(0));
|
|
memcpy(dDest, dSrc, vals*sizeof(double));
|
|
break;
|
|
default:
|
|
vtkErrorMacro("Unknown data type " << dest->GetDataType());
|
|
}
|
|
break;
|
|
//
|
|
default:
|
|
vtkErrorMacro("Unknown data type " << dest->GetDataType());
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// returns the next pointer in dest
|
|
vtkIdType *vtkAppendPolyData::AppendCells(vtkIdType *pDest, vtkCellArray *src,
|
|
vtkIdType offset)
|
|
{
|
|
vtkIdType *pSrc, *end, *pNum;
|
|
|
|
if (src == NULL)
|
|
{
|
|
return pDest;
|
|
}
|
|
|
|
pSrc = (vtkIdType*)(src->GetPointer());
|
|
end = pSrc + src->GetNumberOfConnectivityEntries();
|
|
pNum = pSrc;
|
|
|
|
while (pSrc < end)
|
|
{
|
|
if (pSrc == pNum)
|
|
{
|
|
// move cell pointer to next cell
|
|
pNum += 1+*pSrc;
|
|
// copy the number of cells
|
|
*pDest++ = *pSrc++;
|
|
}
|
|
else
|
|
{
|
|
// offset the point index
|
|
*pDest++ = offset + *pSrc++;
|
|
}
|
|
}
|
|
|
|
return pDest;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkAppendPolyData::FillInputPortInformation(int port, vtkInformation *info)
|
|
{
|
|
if (!this->Superclass::FillInputPortInformation(port, info))
|
|
{
|
|
return 0;
|
|
}
|
|
info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
|
|
return 1;
|
|
}
|
|
|