Cloned library of VTK-5.0.0 with extra build files for internal package management.
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.
 
 
 
 
 
 

608 lines
14 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkExtractCells.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.
=========================================================================*/
/*----------------------------------------------------------------------------
Copyright (c) Sandia Corporation
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/
#include "vtkExtractCells.h"
#include "vtkCellArray.h"
#include "vtkIntArray.h"
#include "vtkUnsignedCharArray.h"
#include "vtkUnstructuredGrid.h"
#include "vtkModelMetadata.h"
#include "vtkCell.h"
#include "vtkPoints.h"
#include "vtkPointData.h"
#include "vtkCellData.h"
#include "vtkIntArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
vtkCxxRevisionMacro(vtkExtractCells, "$Revision: 1.2 $");
vtkStandardNewMacro(vtkExtractCells);
#include <vtkstd/set>
#include <vtkstd/algorithm>
class vtkExtractCellsSTLCloak
{
public:
vtkstd::set<vtkIdType> IdTypeSet;
};
vtkExtractCells::vtkExtractCells()
{
this->SubSetUGridCellArraySize = 0;
this->InputIsUgrid = 0;
this->CellList = new vtkExtractCellsSTLCloak;
}
vtkExtractCells::~vtkExtractCells()
{
this->SetCellList(NULL);
}
void vtkExtractCells::SetCellList(vtkIdList *l)
{
delete this->CellList;
this->CellList = new vtkExtractCellsSTLCloak;
if (l != NULL)
{
this->AddCellList(l);
}
}
void vtkExtractCells::AddCellList(vtkIdList *l)
{
if (l == NULL)
{
return;
}
vtkIdType ncells = l->GetNumberOfIds();
if (ncells == 0)
{
return;
}
for (int i=0; i<ncells; i++)
{
this->CellList->IdTypeSet.insert(l->GetId(i));
}
this->Modified();
return;
}
void vtkExtractCells::AddCellRange(vtkIdType from, vtkIdType to)
{
if (to < from) return;
for (vtkIdType id=from; id <= to; id++)
{
this->CellList->IdTypeSet.insert(id);
}
this->Modified();
return;
}
int vtkExtractCells::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// get the input and ouptut
vtkDataSet *input = vtkDataSet::SafeDownCast(
inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
this->InputIsUgrid =
((vtkUnstructuredGrid::SafeDownCast(input)) != NULL);
vtkModelMetadata *extractMetadata = this->ExtractMetadata(input);
int numCellsInput = input->GetNumberOfCells();
int numCells = this->CellList->IdTypeSet.size();
if (numCells == numCellsInput)
{
#if 0
this->Copy(input, output);
if (extractMetadata)
{
vtkModelMetadata::RemoveMetadata((vtkDataSet *)output);
extractMetadata->Pack(output);
extractMetadata->Delete();
}
return;
#else
// The Copy method seems to have a bug, causing codes using ExtractCells to die
#endif
}
vtkPointData *PD = input->GetPointData();
vtkCellData *CD = input->GetCellData();
if (numCells == 0)
{
// set up a ugrid with same data arrays as input, but
// no points, cells or data.
output->Allocate(1);
output->GetPointData()->CopyAllocate(PD, VTK_CELL_SIZE);
output->GetCellData()->CopyAllocate(CD, 1);
vtkPoints *pts = vtkPoints::New();
pts->SetNumberOfPoints(0);
output->SetPoints(pts);
pts->Delete();
if (extractMetadata)
{
vtkModelMetadata::RemoveMetadata((vtkDataSet *)output);
extractMetadata->Pack(output);
extractMetadata->Delete();
}
return 1;
}
vtkPointData *newPD = output->GetPointData();
vtkCellData *newCD = output->GetCellData();
vtkIdList *ptIdMap = reMapPointIds(input);
vtkIdType numPoints = ptIdMap->GetNumberOfIds();
newPD->CopyAllocate(PD, numPoints);
newCD->CopyAllocate(CD, numCells);
vtkPoints *pts = vtkPoints::New();
pts->SetNumberOfPoints(numPoints);
for (vtkIdType newId =0; newId<numPoints; newId++)
{
vtkIdType oldId = ptIdMap->GetId(newId);
pts->SetPoint(newId, input->GetPoint(oldId));
newPD->CopyData(PD, oldId, newId);
}
output->SetPoints(pts);
pts->Delete();
if (this->InputIsUgrid)
{
this->CopyCellsUnstructuredGrid(ptIdMap, input, output);
}
else
{
this->CopyCellsDataSet(ptIdMap, input, output);
}
ptIdMap->Delete();
output->Squeeze();
if (extractMetadata)
{
vtkModelMetadata::RemoveMetadata((vtkDataSet *)output);
extractMetadata->Pack(output);
extractMetadata->Delete();
}
return 1;
}
vtkModelMetadata *vtkExtractCells::ExtractMetadata(vtkDataSet *input)
{
vtkModelMetadata *extractedMD = NULL;
int numCells = this->CellList->IdTypeSet.size();
if (vtkModelMetadata::HasMetadata(input))
{
if (numCells == input->GetNumberOfCells())
{
extractedMD = vtkModelMetadata::New();
extractedMD->Unpack(input, 0);
}
else
{
vtkDataArray *c = input->GetCellData()->GetArray("GlobalElementId");
vtkDataArray *p = input->GetPointData()->GetArray("GlobalNodeId");
if (c && p)
{
vtkIntArray *cgids = vtkIntArray::SafeDownCast(c);
if (cgids)
{
int *cids = cgids->GetPointer(0);
vtkIntArray *gids = vtkIntArray::New();
gids->SetNumberOfValues(numCells);
int next = 0;
vtkstd::set<vtkIdType>::iterator cellPtr;
for (cellPtr = this->CellList->IdTypeSet.begin();
cellPtr != this->CellList->IdTypeSet.end();
++cellPtr)
{
gids->SetValue(next++, cids[*cellPtr]); // global cell IDs
}
vtkModelMetadata *mmd = vtkModelMetadata::New();
mmd->Unpack(input, 0);
extractedMD = mmd->ExtractModelMetadata(gids,
input, "GlobalElementId", "GlobalNodeId");
gids->Delete();
mmd->Delete();
}
else
{
vtkWarningMacro(<<
"vtkExtractCells: metadata lost, GlobalElementId array is not a vtkIntArray");
}
}
else
{
vtkWarningMacro(<<
"vtkExtractCells: metadata lost, no GlobalElementId or GlobalNodeId array");
}
}
}
return extractedMD;
}
void vtkExtractCells::Copy(vtkDataSet *input, vtkUnstructuredGrid *output)
{
int i;
if (this->InputIsUgrid)
{
output->DeepCopy(vtkUnstructuredGrid::SafeDownCast(input));
return;
}
int numCells = input->GetNumberOfCells();
vtkPointData *PD = input->GetPointData();
vtkCellData *CD = input->GetCellData();
vtkPointData *newPD = output->GetPointData();
vtkCellData *newCD = output->GetCellData();
int numPoints = input->GetNumberOfPoints();
output->Allocate(numCells);
newPD->CopyAllocate(PD, numPoints);
newCD->CopyAllocate(CD, numCells);
vtkPoints *pts = vtkPoints::New();
pts->SetNumberOfPoints(numPoints);
for (i=0; i<numPoints; i++)
{
pts->SetPoint(i, input->GetPoint(i));
}
newPD->DeepCopy(PD);
output->SetPoints(pts);
pts->Delete();
vtkIdList *cellPoints = vtkIdList::New();
for (vtkIdType cellId=0; cellId < numCells; cellId++)
{
input->GetCellPoints(cellId, cellPoints);
output->InsertNextCell(input->GetCellType(cellId), cellPoints);
}
newCD->DeepCopy(CD);
cellPoints->Delete();
output->Squeeze();
return;
}
vtkIdType vtkExtractCells::findInSortedList(vtkIdList *idList, vtkIdType id)
{
vtkIdType numids = idList->GetNumberOfIds();
if (numids < 8) return idList->IsId(id);
int L, R, M;
L=0;
R=numids-1;
vtkIdType *ids = idList->GetPointer(0);
int loc = -1;
while (R > L)
{
if (R == L+1)
{
if (ids[R] == id)
{
loc = R;
}
else if (ids[L] == id)
{
loc = L;
}
break;
}
M = (R + L) / 2;
if (ids[M] > id)
{
R = M;
continue;
}
else if (ids[M] < id)
{
L = M;
continue;
}
else
{
loc = M;
break;
}
}
return loc;
}
vtkIdList *vtkExtractCells::reMapPointIds(vtkDataSet *grid)
{
int totalPoints = grid->GetNumberOfPoints();
char *temp = new char [totalPoints];
if (!temp)
{
vtkErrorMacro(<< "vtkExtractCells::reMapPointIds memory allocation");
return NULL;
}
memset(temp, 0, totalPoints);
int numberOfIds = 0;
int i;
vtkIdType id;
vtkIdList *ptIds = vtkIdList::New();
vtkstd::set<vtkIdType>::iterator cellPtr;
if (!this->InputIsUgrid)
{
for (cellPtr = this->CellList->IdTypeSet.begin();
cellPtr != this->CellList->IdTypeSet.end();
++cellPtr)
{
grid->GetCellPoints(*cellPtr, ptIds);
vtkIdType nIds = ptIds->GetNumberOfIds();
vtkIdType *ptId = ptIds->GetPointer(0);
for (i=0; i<nIds; i++)
{
id = *ptId++;
if (temp[id] == 0)
{
numberOfIds++;
temp[id] = 1;
}
}
}
}
else
{
vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::SafeDownCast(grid);
this->SubSetUGridCellArraySize = 0;
vtkIdType *cellArray = ugrid->GetCells()->GetPointer();
vtkIdType *locs = ugrid->GetCellLocationsArray()->GetPointer(0);
this->SubSetUGridCellArraySize = 0;
vtkIdType maxid = ugrid->GetCellLocationsArray()->GetMaxId();
for (cellPtr = this->CellList->IdTypeSet.begin();
cellPtr != this->CellList->IdTypeSet.end();
++cellPtr)
{
if (*cellPtr > maxid) continue;
int loc = locs[*cellPtr];
vtkIdType nIds = cellArray[loc++];
this->SubSetUGridCellArraySize += (1 + nIds);
for (i=0; i<nIds; i++)
{
id = cellArray[loc++];
if (temp[id] == 0)
{
numberOfIds++;
temp[id] = 1;
}
}
}
}
ptIds->SetNumberOfIds(numberOfIds);
int next=0;
for (id=0; id<totalPoints; id++)
{
if (temp[id]) ptIds->SetId(next++, id);
}
delete [] temp;
return ptIds;
}
void vtkExtractCells::CopyCellsDataSet(vtkIdList *ptMap, vtkDataSet *input,
vtkUnstructuredGrid *output)
{
output->Allocate(this->CellList->IdTypeSet.size());
vtkCellData *oldCD = input->GetCellData();
vtkCellData *newCD = output->GetCellData();
vtkIdList *cellPoints = vtkIdList::New();
vtkstd::set<vtkIdType>::iterator cellPtr;
for (cellPtr = this->CellList->IdTypeSet.begin();
cellPtr != this->CellList->IdTypeSet.end();
++cellPtr)
{
vtkIdType cellId = *cellPtr;
input->GetCellPoints(cellId, cellPoints);
for (int i=0; i < cellPoints->GetNumberOfIds(); i++)
{
vtkIdType oldId = cellPoints->GetId(i);
vtkIdType newId = vtkExtractCells::findInSortedList(ptMap, oldId);
cellPoints->SetId(i, newId);
}
int newId = output->InsertNextCell(input->GetCellType(cellId), cellPoints);
newCD->CopyData(oldCD, cellId, newId);
}
cellPoints->Delete();
return;
}
void vtkExtractCells::CopyCellsUnstructuredGrid(vtkIdList *ptMap,
vtkDataSet *input,
vtkUnstructuredGrid *output)
{
vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::SafeDownCast(input);
if (ugrid == NULL)
{
this->CopyCellsDataSet(ptMap, input, output);
return;
}
vtkCellData *oldCD = input->GetCellData();
vtkCellData *newCD = output->GetCellData();
int numCells = this->CellList->IdTypeSet.size();
vtkCellArray *cellArray = vtkCellArray::New(); // output
vtkIdTypeArray *newcells = vtkIdTypeArray::New();
newcells->SetNumberOfValues(this->SubSetUGridCellArraySize);
cellArray->SetCells(numCells, newcells);
int cellArrayIdx = 0;
vtkIdTypeArray *locationArray = vtkIdTypeArray::New();
locationArray->SetNumberOfValues(numCells);
vtkUnsignedCharArray *typeArray = vtkUnsignedCharArray::New();
typeArray->SetNumberOfValues(numCells);
int nextCellId = 0;
vtkstd::set<vtkIdType>::iterator cellPtr; // input
vtkIdType *cells = ugrid->GetCells()->GetPointer();
vtkIdType maxid = ugrid->GetCellLocationsArray()->GetMaxId();
vtkIdType *locs = ugrid->GetCellLocationsArray()->GetPointer(0);
vtkUnsignedCharArray *types = ugrid->GetCellTypesArray();
for (cellPtr = this->CellList->IdTypeSet.begin();
cellPtr != this->CellList->IdTypeSet.end();
++cellPtr)
{
if (*cellPtr > maxid) continue;
int oldCellId = *cellPtr;
int loc = locs[oldCellId];
int size = (int)cells[loc];
vtkIdType *pts = cells + loc + 1;
unsigned char type = types->GetValue(oldCellId);
locationArray->SetValue(nextCellId, cellArrayIdx);
typeArray->SetValue(nextCellId, type);
newcells->SetValue(cellArrayIdx++, size);
for (int i=0; i<size; i++)
{
vtkIdType oldId = *pts++;
vtkIdType newId = vtkExtractCells::findInSortedList(ptMap, oldId);
newcells->SetValue(cellArrayIdx++, newId);
}
newCD->CopyData(oldCD, oldCellId, nextCellId);
nextCellId++;
}
output->SetCells(typeArray, locationArray, cellArray);
typeArray->Delete();
locationArray->Delete();
newcells->Delete();
cellArray->Delete();
return;
}
int vtkExtractCells::FillInputPortInformation(int, vtkInformation *info)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
return 1;
}
void vtkExtractCells::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
}