You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

339 lines
10 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkExtractGeometry.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 "FITKExtractGeometry.h"
#include "vtkCell.h"
#include "vtkCellData.h"
#include "vtkCellIterator.h"
#include "vtkFloatArray.h"
#include "vtkIdList.h"
#include "vtkImplicitFunction.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"
#include "vtkUnstructuredGrid.h"
vtkStandardNewMacro(FITKExtractGeometry);
vtkCxxSetObjectMacro(FITKExtractGeometry, ImplicitFunction, vtkImplicitFunction);
//----------------------------------------------------------------------------
// Construct object with ExtractInside turned on.
FITKExtractGeometry::FITKExtractGeometry(vtkImplicitFunction* f)
{
this->ImplicitFunction = f;
if (this->ImplicitFunction)
{
this->ImplicitFunction->Register(this);
}
this->ExtractInside = 1;
this->ExtractBoundaryCells = 0;
this->ExtractOnlyBoundaryCells = 0;
}
//----------------------------------------------------------------------------
FITKExtractGeometry::~FITKExtractGeometry()
{
this->SetImplicitFunction(nullptr);
}
// Overload standard modified time function. If implicit function is modified,
// then this object is modified as well.
vtkMTimeType FITKExtractGeometry::GetMTime()
{
vtkMTimeType mTime = this->MTime.GetMTime();
vtkMTimeType impFuncMTime;
if (this->ImplicitFunction != nullptr)
{
impFuncMTime = this->ImplicitFunction->GetMTime();
mTime = (impFuncMTime > mTime ? impFuncMTime : mTime);
}
return mTime;
}
QList< int > FITKExtractGeometry::getSelectOriginalPoints() const
{
return _originalCurrentPointMap.keys();
}
QList< int > FITKExtractGeometry::getSelectOriginalCells() const
{
return _originalCurrentCellMap.keys();
}
const QHash< int, int >& FITKExtractGeometry::getPointMap() const
{
return _originalCurrentPointMap;
}
const QHash< int, int >& FITKExtractGeometry::getCellMap() const
{
return _originalCurrentCellMap;
}
//----------------------------------------------------------------------------
int FITKExtractGeometry::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 output
vtkDataSet* input = vtkDataSet::SafeDownCast(
inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkUnstructuredGrid* output = vtkUnstructuredGrid::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
// May be nullptr, check before dereferencing.
vtkUnstructuredGrid* gridInput = vtkUnstructuredGrid::SafeDownCast(input);
vtkIdType ptId, numPts, numCells, i, newCellId, newId, *pointMap;
vtkSmartPointer< vtkCellIterator > cellIter =
vtkSmartPointer< vtkCellIterator >::Take(input->NewCellIterator());
vtkIdList* pointIdList;
int cellType;
vtkIdType numCellPts;
double x[3];
double multiplier;
vtkPoints* newPts;
vtkIdList* newCellPts;
vtkPointData* pd = input->GetPointData();
vtkCellData* cd = input->GetCellData();
vtkPointData* outputPD = output->GetPointData();
vtkCellData* outputCD = output->GetCellData();
int npts;
vtkDebugMacro(<< "Extracting geometry");
if (!this->ImplicitFunction)
{
vtkErrorMacro(<< "No implicit function specified");
return 1;
}
// As this filter is doing a subsetting operation, set the Copy Tuple flag
// for GlobalIds array so that, if present, it will be copied to the output.
outputPD->CopyGlobalIdsOn();
outputCD->CopyGlobalIdsOn();
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.
//
numPts = input->GetNumberOfPoints();
numCells = input->GetNumberOfCells();
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 = nullptr;
if (!this->ExtractBoundaryCells)
{
for (ptId = 0; ptId < numPts; ptId++)
{
input->GetPoint(ptId, x);
if ((this->ImplicitFunction->FunctionValue(x) * multiplier) < 0.0)
{
newId = newPts->InsertNextPoint(x);
pointMap[ptId] = newId;
_originalCurrentPointMap.insert(ptId, newId);
outputPD->CopyData(pd, ptId, newId);
}
}
}
else
{
// To extract boundary cells, we have to create supplemental information
double val;
newScalars = vtkFloatArray::New();
newScalars->SetNumberOfValues(numPts);
for (ptId = 0; ptId < numPts; ptId++)
{
input->GetPoint(ptId, x);
val = this->ImplicitFunction->FunctionValue(x) * multiplier;
newScalars->SetValue(ptId, val);
}
}
// Now loop over all cells to see whether they are inside implicit
// function (or on boundary if ExtractBoundaryCells is on).
//
for (cellIter->InitTraversal(); !cellIter->IsDoneWithTraversal();
cellIter->GoToNextCell())
{
cellType = cellIter->GetCellType();
numCellPts = cellIter->GetNumberOfPoints();
pointIdList = cellIter->GetPointIds();
newCellPts->Reset();
if (!this->ExtractBoundaryCells) //requires less work
{
for (npts = 0, i = 0; i < numCellPts; i++, npts++)
{
ptId = pointIdList->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 = pointIdList->GetId(i);
if (newScalars->GetValue(ptId) <= 0.0)
{
npts++;
}
}
int extraction_condition = 0;
if (this->ExtractOnlyBoundaryCells)
{
if ((npts > 0) && (npts != numCellPts))
{
extraction_condition = 1;
}
}
else
{
if (npts > 0)
{
extraction_condition = 1;
}
}
if (extraction_condition)
{
for (i = 0; i < numCellPts; i++)
{
ptId = pointIdList->GetId(i);
if (pointMap[ptId] < 0)
{
input->GetPoint(ptId, x);
newId = newPts->InsertNextPoint(x);
pointMap[ptId] = newId;
_originalCurrentPointMap.insert(ptId, newId);
outputPD->CopyData(pd, ptId, newId);
}
newCellPts->InsertId(i, pointMap[ptId]);
}
} //a boundary or interior cell
} //if mapping boundary cells
int extraction_condition = 0;
if (this->ExtractOnlyBoundaryCells)
{
if (npts != numCellPts && (this->ExtractBoundaryCells && npts > 0))
{
extraction_condition = 1;
}
}
else
{
if (npts >= numCellPts || (this->ExtractBoundaryCells && npts > 0))
{
extraction_condition = 1;
}
}
if (extraction_condition)
{
// special handling for polyhedron cells
if (gridInput && cellType == VTK_POLYHEDRON)
{
newCellPts->Reset();
gridInput->GetFaceStream(cellIter->GetCellId(), newCellPts);
vtkUnstructuredGrid::ConvertFaceStreamPointIds(newCellPts, pointMap);
}
newCellId = output->InsertNextCell(cellType, newCellPts);
int orignalCellID = cellIter->GetCellId();
outputCD->CopyData(cd, orignalCellID, newCellId);
_originalCurrentCellMap.insert(orignalCellID, 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();
return 1;
}
//----------------------------------------------------------------------------
int FITKExtractGeometry::FillInputPortInformation(int, vtkInformation* info)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
return 1;
}
//----------------------------------------------------------------------------
void FITKExtractGeometry::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "Implicit Function: "
<< static_cast<void*>(this->ImplicitFunction) << "\n";
os << indent << "Extract Inside: "
<< (this->ExtractInside ? "On\n" : "Off\n");
os << indent << "Extract Boundary Cells: "
<< (this->ExtractBoundaryCells ? "On\n" : "Off\n");
os << indent << "Extract Only Boundary Cells: "
<< (this->ExtractOnlyBoundaryCells ? "On\n" : "Off\n");
}