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.
 
 
 
 
 
 

283 lines
8.4 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkApproximatingSubdivisionFilter.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 "vtkApproximatingSubdivisionFilter.h"
#include "vtkCell.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkEdgeTable.h"
#include "vtkIdList.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkUnsignedCharArray.h"
vtkCxxRevisionMacro(vtkApproximatingSubdivisionFilter, "$Revision: 1.30 $");
// Construct object with number of subdivisions set to 1.
vtkApproximatingSubdivisionFilter::vtkApproximatingSubdivisionFilter()
{
this->NumberOfSubdivisions = 1;
}
int vtkApproximatingSubdivisionFilter::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
vtkPolyData *input = vtkPolyData::SafeDownCast(
inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkPolyData *output = vtkPolyData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkIdType numCells, numPts;
int level;
vtkPoints *outputPts;
vtkCellArray *outputPolys;
vtkPointData *outputPD;
vtkCellData *outputCD;
vtkIntArray *edgeData;
vtkDebugMacro(<< "Generating subdivision surface using approximating scheme");
numPts=input->GetNumberOfPoints();
numCells=input->GetNumberOfCells();
if (numPts < 1 || numCells < 1)
{
vtkErrorMacro(<<"No data to approximate!");
return 1;
}
//
// Initialize and check input
//
vtkPolyData *inputDS = vtkPolyData::New();
inputDS->CopyStructure (input);
inputDS->GetPointData()->PassData(input->GetPointData());
inputDS->GetCellData()->PassData(input->GetCellData());
int abort=0;
for (level = 0; level < this->NumberOfSubdivisions && !abort; level++)
{
this->UpdateProgress((double)(level+1)/this->NumberOfSubdivisions);
abort = this->GetAbortExecute();
// Generate topology for the input dataset
inputDS->BuildLinks();
numCells = inputDS->GetNumberOfCells ();
numPts = inputDS->GetNumberOfPoints();
// The points for the subdivisions will
// include even points (computed from old points) and
// odd points (inserted on edges)
outputPts = vtkPoints::New();
outputPts->Allocate (numPts);
// Copy pointdata structure from input
outputPD = vtkPointData::New();
outputPD->CopyAllocate(inputDS->GetPointData(),2*inputDS->GetNumberOfPoints());
// Copy celldata structure from input
outputCD = vtkCellData::New();
outputCD->CopyAllocate(inputDS->GetCellData(),4*numCells);
// Create triangles
outputPolys = vtkCellArray::New();
outputPolys->Allocate(outputPolys->EstimateSize(4*numCells,3));
// Create an array to hold new location indices
edgeData = vtkIntArray::New();
edgeData->SetNumberOfComponents(3);
edgeData->SetNumberOfTuples(numCells);
this->GenerateSubdivisionPoints (inputDS, edgeData, outputPts, outputPD);
this->GenerateSubdivisionCells (inputDS, edgeData, outputPolys, outputCD);
// start the next iteration with the input set to the output we just created
edgeData->Delete();
inputDS->Delete();
inputDS = vtkPolyData::New();
inputDS->SetPoints(outputPts); outputPts->Delete();
inputDS->SetPolys(outputPolys); outputPolys->Delete();
inputDS->GetPointData()->PassData(outputPD); outputPD->Delete();
inputDS->GetCellData()->PassData(outputCD); outputCD->Delete();
inputDS->Squeeze();
} // each level
// Get rid of ghost cells if we have to.
unsigned char* ghostLevels=0;
vtkCellData* cd = inputDS->GetCellData();
if (cd)
{
vtkDataArray* temp = cd->GetArray("vtkGhostLevels");
if (temp)
{
ghostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0);
}
}
int updateGhostLevel = output->GetUpdateGhostLevel();
output->SetPoints(inputDS->GetPoints());
output->SetPolys(inputDS->GetPolys());
output->GetPointData()->PassData(inputDS->GetPointData());
output->GetCellData()->PassData(inputDS->GetCellData());
if (input->GetGhostLevel() > updateGhostLevel && ghostLevels != NULL)
{
output->RemoveGhostCells(updateGhostLevel+1);
}
inputDS->Delete();
return 1;
}
int vtkApproximatingSubdivisionFilter::FindEdge (vtkPolyData *mesh,
vtkIdType cellId,
vtkIdType p1, vtkIdType p2,
vtkIntArray *edgeData,
vtkIdList *cellIds)
{
int edgeId = 0;
vtkIdType currentCellId = 0;
vtkIdType i;
int numEdges;
vtkIdType tp1, tp2;
vtkCell *cell;
// get all the cells that use the edge (except for cellId)
mesh->GetCellEdgeNeighbors (cellId, p1, p2, cellIds);
// find the edge that has the point we are looking for
for ( i=0; i < cellIds->GetNumberOfIds(); i++)
{
currentCellId = cellIds->GetId(i);
cell = mesh->GetCell(currentCellId);
numEdges = cell->GetNumberOfEdges();
tp1 = cell->GetPointId(2);
tp2 = cell->GetPointId(0);
for (edgeId=0; edgeId < numEdges; edgeId++)
{
if ( (tp1 == p1 && tp2 == p2) ||
(tp2 == p1 && tp1 == p2))
{
break;
}
tp1 = tp2;
tp2 = cell->GetPointId(edgeId + 1);
}
}
// found the edge, return the stored value
return (int) edgeData->GetComponent(currentCellId,edgeId);
}
vtkIdType vtkApproximatingSubdivisionFilter::InterpolatePosition (
vtkPoints *inputPts, vtkPoints *outputPts,
vtkIdList *stencil, double *weights)
{
double xx[3], x[3];
vtkIdType i;
int j;
for (j = 0; j < 3; j++)
{
x[j] = 0.0;
}
for (i = 0; i < stencil->GetNumberOfIds(); i++)
{
inputPts->GetPoint(stencil->GetId(i), xx);
for (j = 0; j < 3; j++)
{
x[j] += xx[j] * weights[i];
}
}
return outputPts->InsertNextPoint (x);
}
void vtkApproximatingSubdivisionFilter::GenerateSubdivisionCells (
vtkPolyData *inputDS, vtkIntArray *edgeData, vtkCellArray *outputPolys,
vtkCellData *outputCD)
{
vtkIdType numCells = inputDS->GetNumberOfCells();
vtkIdType cellId, newId, id;
vtkIdType npts;
vtkIdType *pts;
double edgePts[3];
vtkIdType newCellPts[3];
vtkCellData *inputCD = inputDS->GetCellData();
// Now create new cells from existing points and generated edge points
for (cellId=0; cellId < numCells; cellId++)
{
if ( inputDS->GetCellType(cellId) != VTK_TRIANGLE )
{
continue;
}
// get the original point ids and the ids stored as edge data
inputDS->GetCellPoints(cellId, npts, pts);
edgeData->GetTuple(cellId, edgePts);
id = 0;
newCellPts[id++] = pts[0];
newCellPts[id++] = (int) edgePts[1];
newCellPts[id++] = (int) edgePts[0];
newId = outputPolys->InsertNextCell (3, newCellPts);
outputCD->CopyData (inputCD, cellId, newId);
id = 0;
newCellPts[id++] = (int) edgePts[1];
newCellPts[id++] = pts[1];
newCellPts[id++] = (int) edgePts[2];
newId = outputPolys->InsertNextCell (3, newCellPts);
outputCD->CopyData (inputCD, cellId, newId);
id = 0;
newCellPts[id++] = (int) edgePts[2];
newCellPts[id++] = pts[2];
newCellPts[id++] = (int) edgePts[0];
newId = outputPolys->InsertNextCell (3, newCellPts);
outputCD->CopyData (inputCD, cellId, newId);
id = 0;
newCellPts[id++] = (int) edgePts[1];
newCellPts[id++] = (int) edgePts[2];
newCellPts[id++] = (int) edgePts[0];
newId = outputPolys->InsertNextCell (3, newCellPts);
outputCD->CopyData (inputCD, cellId, newId);
}
}
void vtkApproximatingSubdivisionFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Number of subdivisions: "
<< this->NumberOfSubdivisions << endl;
}