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.
 
 
 
 
 
 

425 lines
12 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkLinearExtrusionFilter.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 "vtkLinearExtrusionFilter.h"
#include "vtkCell.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkGenericCell.h"
#include "vtkIdList.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
vtkCxxRevisionMacro(vtkLinearExtrusionFilter, "$Revision: 1.62 $");
vtkStandardNewMacro(vtkLinearExtrusionFilter);
// Create object with normal extrusion type, capping on, scale factor=1.0,
// vector (0,0,1), and extrusion point (0,0,0).
vtkLinearExtrusionFilter::vtkLinearExtrusionFilter()
{
this->ExtrusionType = VTK_NORMAL_EXTRUSION;
this->Capping = 1;
this->ScaleFactor = 1.0;
this->Vector[0] = this->Vector[1] = 0.0; this->Vector[2] = 1.0;
this->ExtrusionPoint[0] = this->ExtrusionPoint[1] = this->ExtrusionPoint[2] = 0.0;
}
double *vtkLinearExtrusionFilter::ViaNormal(double x[3], vtkIdType id,
vtkDataArray *n)
{
static double xNew[3], normal[3];
int i;
n->GetTuple(id, normal);
for (i=0; i<3; i++)
{
xNew[i] = x[i] + this->ScaleFactor*normal[i];
}
return xNew;
}
double *vtkLinearExtrusionFilter::ViaVector(double x[3],
vtkIdType vtkNotUsed(id),
vtkDataArray *vtkNotUsed(n))
{
static double xNew[3];
int i;
for (i=0; i<3; i++)
{
xNew[i] = x[i] + this->ScaleFactor*this->Vector[i];
}
return xNew;
}
double *vtkLinearExtrusionFilter::ViaPoint(double x[3], vtkIdType vtkNotUsed(id),
vtkDataArray *vtkNotUsed(n))
{
static double xNew[3];
int i;
for (i=0; i<3; i++)
{
xNew[i] = x[i] + this->ScaleFactor*(x[i] - this->ExtrusionPoint[i]);
}
return xNew;
}
int vtkLinearExtrusionFilter::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 numPts, numCells;
vtkPointData *pd=input->GetPointData();
vtkDataArray *inNormals=NULL;
vtkPolyData *mesh;
vtkPoints *inPts;
vtkCellArray *inVerts, *inLines, *inPolys, *inStrips;
vtkIdType inCellId, outCellId;
int numEdges, dim;
vtkIdType *pts = 0;
vtkIdType npts = 0;
vtkIdType ptId, ncells, p1, p2;
int i, j;
double x[3];
vtkPoints *newPts;
vtkCellArray *newLines=NULL, *newPolys=NULL, *newStrips;
vtkCell *edge;
vtkIdList *cellIds, *cellPts;
vtkPointData *outputPD = output->GetPointData();
// Here is a big pain about ordering of cells. (Copy CellData)
vtkIdList *lineIds;
vtkIdList *polyIds;
vtkIdList *stripIds;
// Initialize / check input
//
vtkDebugMacro(<<"Linearly extruding data");
numPts=input->GetNumberOfPoints();
numCells=input->GetNumberOfCells();
if (numPts < 1 || numCells < 1)
{
vtkErrorMacro(<<"No data to extrude!");
return 1;
}
//
// Decide which vector to use for extrusion
//
if ( this->ExtrusionType == VTK_POINT_EXTRUSION )
{
this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaPoint;
}
else if ( this->ExtrusionType == VTK_NORMAL_EXTRUSION &&
(inNormals = pd->GetNormals()) != NULL )
{
this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaNormal;
inNormals = pd->GetNormals();
}
else // VTK_VECTOR_EXTRUSION
{
this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaVector;
}
// Build cell data structure.
//
mesh = vtkPolyData::New();
inPts = input->GetPoints();
inVerts = input->GetVerts();
inLines = input->GetLines();
inPolys = input->GetPolys();
inStrips = input->GetStrips();
mesh->SetPoints(inPts);
mesh->SetVerts(inVerts);
mesh->SetLines(inLines);
mesh->SetPolys(inPolys);
mesh->SetStrips(inStrips);
if (inPolys->GetNumberOfCells() || inStrips->GetNumberOfCells())
{
mesh->BuildLinks();
}
cellIds = vtkIdList::New();
cellIds->Allocate(VTK_CELL_SIZE);
// Allocate memory for output. We don't copy normals because surface geometry
// is modified. Copy all points - this is the usual requirement and it makes
// creation of skirt much easier.
//
output->GetCellData()->CopyNormalsOff();
output->GetCellData()->CopyAllocate(input->GetCellData(),
3*input->GetNumberOfCells());
outputPD->CopyNormalsOff();
outputPD->CopyAllocate(pd,2*numPts);
newPts = vtkPoints::New(); newPts->SetNumberOfPoints(2*numPts);
if ( (ncells=inVerts->GetNumberOfCells()) > 0 )
{
newLines = vtkCellArray::New();
newLines->Allocate(newLines->EstimateSize(ncells,2));
}
// arbitrary initial allocation size
ncells = inLines->GetNumberOfCells() + inPolys->GetNumberOfCells()/10 +
inStrips->GetNumberOfCells()/10;
ncells = (ncells < 100 ? 100 : ncells);
newStrips = vtkCellArray::New();
newStrips->Allocate(newStrips->EstimateSize(ncells,4));
vtkIdType progressInterval=numPts/10+1;
int abort=0;
// copy points
for (ptId=0; ptId < numPts; ptId++)
{
if ( ! (ptId % progressInterval) ) //manage progress / early abort
{
this->UpdateProgress (0.25*ptId/numPts);
}
inPts->GetPoint(ptId, x);
newPts->SetPoint(ptId,x);
newPts->SetPoint(ptId+numPts,
(this->*(this->ExtrudePoint))(x,ptId,inNormals));
outputPD->CopyData(pd,ptId,ptId);
outputPD->CopyData(pd,ptId,ptId+numPts);
}
// We need the cellid to copy cell data. Skip points and lines.
inCellId = outCellId =0;
if (input->GetVerts())
{
inCellId += input->GetVerts()->GetNumberOfCells();
}
if (input->GetLines())
{
inCellId += input->GetLines()->GetNumberOfCells();
}
// We need to keep track of input cell ids used to generate
// output cells so that we can copy cell data at the end.
// We do not know how many lines, polys and strips we will get
// before hand.
lineIds = vtkIdList::New();
polyIds = vtkIdList::New();
stripIds = vtkIdList::New();
// If capping is on, copy 2D cells to output (plus create cap)
//
if ( this->Capping )
{
if ( inPolys->GetNumberOfCells() > 0 )
{
newPolys = vtkCellArray::New();
newPolys->Allocate(inPolys->GetSize());
for ( inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); )
{
newPolys->InsertNextCell(npts,pts);
polyIds->InsertNextId(inCellId);
newPolys->InsertNextCell(npts);
for (i=0; i < npts; i++)
{
newPolys->InsertCellPoint(pts[i] + numPts);
}
polyIds->InsertNextId(inCellId);
++inCellId;
}
}
if ( inStrips->GetNumberOfCells() > 0 )
{
for ( inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
{
newStrips->InsertNextCell(npts,pts);
stripIds->InsertNextId(inCellId);
newStrips->InsertNextCell(npts);
for (i=0; i < npts; i++)
{
newStrips->InsertCellPoint(pts[i] + numPts);
}
stripIds->InsertNextId(inCellId);
++inCellId;
}
}
}
this->UpdateProgress (0.4);
// Loop over all polygons and triangle strips searching for boundary edges.
// If boundary edge found, extrude triangle strip.
//
progressInterval=numCells/10+1;
vtkGenericCell *cell = vtkGenericCell::New();
for ( inCellId=0; inCellId < numCells && !abort; inCellId++)
{
if ( ! (inCellId % progressInterval) ) //manage progress / early abort
{
this->UpdateProgress (0.4 + 0.6*inCellId/numCells);
abort = this->GetAbortExecute();
}
mesh->GetCell(inCellId,cell);
cellPts = cell->GetPointIds();
if ( (dim=cell->GetCellDimension()) == 0 ) //create lines from points
{
for (i=0; i<cellPts->GetNumberOfIds(); i++)
{
newLines->InsertNextCell(2);
ptId = cellPts->GetId(i);
newLines->InsertCellPoint(ptId);
newLines->InsertCellPoint(ptId+numPts);
lineIds->InsertNextId(inCellId);
}
}
else if ( dim == 1 ) // create strips from lines
{
for (i=0; i < (cellPts->GetNumberOfIds()-1); i++)
{
p1 = cellPts->GetId(i);
p2 = cellPts->GetId(i+1);
newStrips->InsertNextCell(4);
newStrips->InsertCellPoint(p1);
newStrips->InsertCellPoint(p2);
newStrips->InsertCellPoint(p1+numPts);
newStrips->InsertCellPoint(p2+numPts);
stripIds->InsertNextId(inCellId);
}
}
else if ( dim == 2 ) // create strips from boundary edges
{
numEdges = cell->GetNumberOfEdges();
for (i=0; i<numEdges; i++)
{
edge = cell->GetEdge(i);
for (j=0; j<(edge->GetNumberOfPoints()-1); j++)
{
p1 = edge->PointIds->GetId(j);
p2 = edge->PointIds->GetId(j+1);
mesh->GetCellEdgeNeighbors(inCellId, p1, p2, cellIds);
if ( cellIds->GetNumberOfIds() < 1 ) //generate strip
{
newStrips->InsertNextCell(4);
newStrips->InsertCellPoint(p1);
newStrips->InsertCellPoint(p2);
newStrips->InsertCellPoint(p1+numPts);
newStrips->InsertCellPoint(p2+numPts);
stripIds->InsertNextId(inCellId);
}
} //for each sub-edge
} //for each edge
} //for each polygon or triangle strip
} //for each cell
cell->Delete();
// Now Copy cell data.
outCellId = 0;
j = lineIds->GetNumberOfIds();
for (i = 0; i < j; ++i)
{
output->GetCellData()->CopyData(input->GetCellData(),
lineIds->GetId(i),outCellId);
++outCellId;
}
j = polyIds->GetNumberOfIds();
for (i = 0; i < j; ++i)
{
output->GetCellData()->CopyData(input->GetCellData(),
polyIds->GetId(i),outCellId);
++outCellId;
}
j = stripIds->GetNumberOfIds();
for (i = 0; i < j; ++i)
{
output->GetCellData()->CopyData(input->GetCellData(),
stripIds->GetId(i),outCellId);
++outCellId;
}
lineIds->Delete();
stripIds->Delete();
polyIds->Delete();
polyIds = NULL;
// Send data to output and release memory
//
output->SetPoints(newPts);
newPts->Delete();
cellIds->Delete();
mesh->Delete();
if ( newLines )
{
output->SetLines(newLines);
newLines->Delete();
}
if ( newPolys )
{
output->SetPolys(newPolys);
newPolys->Delete();
}
output->SetStrips(newStrips);
newStrips->Delete();
output->Squeeze();
return 1;
}
void vtkLinearExtrusionFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
if ( this->ExtrusionType == VTK_VECTOR_EXTRUSION )
{
os << indent << "Extrusion Type: Extrude along vector\n";
os << indent << "Vector: (" << this->Vector[0] << ", "
<< this->Vector[1] << ", " << this->Vector[2] << ")\n";
}
else if ( this->ExtrusionType == VTK_NORMAL_EXTRUSION )
{
os << indent << "Extrusion Type: Extrude along vertex normals\n";
}
else //POINT_EXTRUSION
{
os << indent << "Extrusion Type: Extrude towards point\n";
os << indent << "Extrusion Point: (" << this->ExtrusionPoint[0] << ", "
<< this->ExtrusionPoint[1] << ", " << this->ExtrusionPoint[2] << ")\n";
}
os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
}