/*========================================================================= 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 #include class vtkExtractCellsSTLCloak { public: vtkstd::set 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; iCellList->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; newIdGetId(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::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; iSetPoint(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::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; iSubSetUGridCellArraySize = 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; iSetNumberOfIds(numberOfIds); int next=0; for (id=0; idSetId(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::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::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; iSetValue(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); }