// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org #include "SMESH_ExtractGeometry.h" #include "vtkCell.h" #include "vtkCellData.h" #include "vtkFloatArray.h" #include "vtkIdList.h" #include "vtkImplicitFunction.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkUnstructuredGrid.h" using namespace std; #ifdef _DEBUG_ static int MYDEBUG = 0; #else static int MYDEBUG = 0; #endif #if defined __GNUC__ #if __GNUC__ == 2 #define __GNUC_2__ #endif #endif vtkStandardNewMacro(SMESH_ExtractGeometry); SMESH_ExtractGeometry::SMESH_ExtractGeometry() {} SMESH_ExtractGeometry::~SMESH_ExtractGeometry(){} vtkIdType SMESH_ExtractGeometry::GetElemObjId(int theVtkID){ if(myElemVTK2ObjIds.empty() || theVtkID > myElemVTK2ObjIds.size()) return -1; #if defined __GNUC_2__ return myElemVTK2ObjIds[theVtkID]; #else return myElemVTK2ObjIds.at(theVtkID); #endif } vtkIdType SMESH_ExtractGeometry::GetNodeObjId(int theVtkID){ if(myNodeVTK2ObjIds.empty() || theVtkID > myNodeVTK2ObjIds.size()) return -1; #if defined __GNUC_2__ return myNodeVTK2ObjIds[theVtkID]; #else return myNodeVTK2ObjIds.at(theVtkID); #endif } void SMESH_ExtractGeometry::Execute() { vtkIdType ptId, numPts, numCells, i, cellId, newCellId, newId, *pointMap; vtkIdList *cellPts; vtkCell *cell; int numCellPts; float *x; float multiplier; vtkPoints *newPts; vtkIdList *newCellPts; vtkDataSet *input = this->GetInput(); vtkPointData *pd = input->GetPointData(); vtkCellData *cd = input->GetCellData(); vtkUnstructuredGrid *output = this->GetOutput(); vtkPointData *outputPD = output->GetPointData(); vtkCellData *outputCD = output->GetCellData(); int npts; numCells = input->GetNumberOfCells(); numPts = input->GetNumberOfPoints(); vtkDebugMacro(<< "Extracting geometry"); if ( ! this->ImplicitFunction ) { vtkErrorMacro(<<"No implicit function specified"); return; } newCellPts = vtkIdList::New(); newCellPts->Allocate(VTK_CELL_SIZE); if ( this->ExtractInside ) { multiplier = 1.0; } else { multiplier = -1.0; } // Loop over all points determining whether they are inside the // implicit function. Copy the points and point data if they are. // pointMap = new vtkIdType[numPts]; // maps old point ids into new for (i=0; i < numPts; i++) { pointMap[i] = -1; } output->Allocate(numCells/4); //allocate storage for geometry/topology newPts = vtkPoints::New(); newPts->Allocate(numPts/4,numPts); outputPD->CopyAllocate(pd); outputCD->CopyAllocate(cd); vtkFloatArray *newScalars = NULL; if(myStoreMapping){ myElemVTK2ObjIds.clear(); myElemVTK2ObjIds.reserve(numCells); myNodeVTK2ObjIds.clear(); myNodeVTK2ObjIds.reserve(numPts); } if ( ! this->ExtractBoundaryCells ) { for ( ptId=0; ptId < numPts; ptId++ ) { x = input->GetPoint(ptId); if ( (this->ImplicitFunction->FunctionValue(x)*multiplier) < 0.0 ) { newId = newPts->InsertNextPoint(x); pointMap[ptId] = newId; myNodeVTK2ObjIds.push_back(ptId); outputPD->CopyData(pd,ptId,newId); } } } else { // To extract boundary cells, we have to create supplemental information if ( this->ExtractBoundaryCells ) { float val; newScalars = vtkFloatArray::New(); newScalars->SetNumberOfValues(numPts); for (ptId=0; ptId < numPts; ptId++ ) { x = input->GetPoint(ptId); val = this->ImplicitFunction->FunctionValue(x) * multiplier; newScalars->SetValue(ptId, val); if ( val < 0.0 ) { newId = newPts->InsertNextPoint(x); pointMap[ptId] = newId; myNodeVTK2ObjIds.push_back(ptId); outputPD->CopyData(pd,ptId,newId); } } } } // Now loop over all cells to see whether they are inside implicit // function (or on boundary if ExtractBoundaryCells is on). // for (cellId=0; cellId < numCells; cellId++) { cell = input->GetCell(cellId); cellPts = cell->GetPointIds(); numCellPts = cell->GetNumberOfPoints(); newCellPts->Reset(); if ( ! this->ExtractBoundaryCells ) //requires less work { for ( npts=0, i=0; i < numCellPts; i++, npts++) { ptId = cellPts->GetId(i); if ( pointMap[ptId] < 0 ) { break; //this cell won't be inserted } else { newCellPts->InsertId(i,pointMap[ptId]); } } } //if don't want to extract boundary cells else //want boundary cells { for ( npts=0, i=0; i < numCellPts; i++ ) { ptId = cellPts->GetId(i); if ( newScalars->GetValue(ptId) <= 0.0 ) { npts++; } } if ( npts > 0 ) { for ( i=0; i < numCellPts; i++ ) { ptId = cellPts->GetId(i); if ( pointMap[ptId] < 0 ) { x = input->GetPoint(ptId); newId = newPts->InsertNextPoint(x); pointMap[ptId] = newId; myNodeVTK2ObjIds.push_back(ptId); outputPD->CopyData(pd,ptId,newId); } newCellPts->InsertId(i,pointMap[ptId]); } }//a boundary or interior cell }//if mapping boundary cells if ( npts >= numCellPts || (this->ExtractBoundaryCells && npts > 0) ) { newCellId = output->InsertNextCell(cell->GetCellType(),newCellPts); myElemVTK2ObjIds.push_back(cellId); outputCD->CopyData(cd,cellId,newCellId); } }//for all cells // Update ourselves and release memory // delete [] pointMap; newCellPts->Delete(); output->SetPoints(newPts); newPts->Delete(); if ( this->ExtractBoundaryCells ) { newScalars->Delete(); } output->Squeeze(); }