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.
409 lines
12 KiB
409 lines
12 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkGenericContourFilter.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 "vtkGenericContourFilter.h"
|
|
#include "vtkCell.h"
|
|
#include "vtkLine.h"
|
|
#include "vtkCellArray.h"
|
|
#include "vtkMergePoints.h"
|
|
#include "vtkContourValues.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkTimerLog.h"
|
|
#include "vtkUnstructuredGrid.h"
|
|
#include "vtkContourGrid.h"
|
|
#include "vtkDoubleArray.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkGenericCellIterator.h"
|
|
#include "vtkCellData.h"
|
|
#include "vtkGenericAdaptorCell.h"
|
|
#include "vtkPolyData.h"
|
|
#include "vtkGenericDataSet.h"
|
|
#include "vtkGenericAttributeCollection.h"
|
|
#include "vtkGenericAttribute.h"
|
|
#include "vtkGenericCellTessellator.h"
|
|
|
|
vtkCxxRevisionMacro(vtkGenericContourFilter, "$Revision: 1.7 $");
|
|
vtkStandardNewMacro(vtkGenericContourFilter);
|
|
|
|
// Construct object with initial range (0,1) and single contour value
|
|
// of 0.0.
|
|
vtkGenericContourFilter::vtkGenericContourFilter()
|
|
{
|
|
this->ContourValues = vtkContourValues::New();
|
|
|
|
this->ComputeNormals = 1;
|
|
this->ComputeGradients = 0;
|
|
this->ComputeScalars = 1;
|
|
|
|
this->Locator = NULL;
|
|
|
|
this->InputScalarsSelection = NULL;
|
|
|
|
this->internalPD=vtkPointData::New();
|
|
this->secondaryPD=vtkPointData::New();
|
|
this->secondaryCD=vtkCellData::New();
|
|
}
|
|
|
|
vtkGenericContourFilter::~vtkGenericContourFilter()
|
|
{
|
|
this->ContourValues->Delete();
|
|
if ( this->Locator )
|
|
{
|
|
this->Locator->UnRegister(this);
|
|
this->Locator = NULL;
|
|
}
|
|
this->SetInputScalarsSelection(NULL);
|
|
this->internalPD->Delete();
|
|
this->secondaryPD->Delete();
|
|
this->secondaryCD->Delete();
|
|
}
|
|
|
|
// Overload standard modified time function. If contour values are modified,
|
|
// then this object is modified as well.
|
|
unsigned long vtkGenericContourFilter::GetMTime()
|
|
{
|
|
unsigned long mTime = this->Superclass::GetMTime();
|
|
unsigned long time;
|
|
|
|
if (this->ContourValues)
|
|
{
|
|
time = this->ContourValues->GetMTime();
|
|
mTime = ( time > mTime ? time : mTime );
|
|
}
|
|
if (this->Locator)
|
|
{
|
|
time = this->Locator->GetMTime();
|
|
mTime = ( time > mTime ? time : mTime );
|
|
}
|
|
|
|
// mTime should also take into account the fact that tesselator is view
|
|
// dependant
|
|
|
|
return mTime;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// General contouring filter. Handles arbitrary input.
|
|
int vtkGenericContourFilter::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
|
|
vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast(
|
|
inInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
vtkPolyData *output = vtkPolyData::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
vtkDebugMacro(<< "Executing contour filter");
|
|
|
|
if(input==0)
|
|
{
|
|
vtkErrorMacro("No input specified");
|
|
return 1;
|
|
}
|
|
vtkPointData *outPd = output->GetPointData();
|
|
vtkCellData *outCd = output->GetCellData();
|
|
|
|
// Create objects to hold output of contour operation. First estimate
|
|
// allocation size.
|
|
vtkIdType numCells=input->GetNumberOfCells();
|
|
vtkIdType estimatedSize=input->GetEstimatedSize();
|
|
estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024
|
|
if (estimatedSize < 1024)
|
|
{
|
|
estimatedSize = 1024;
|
|
}
|
|
|
|
vtkPoints *newPts = vtkPoints::New();
|
|
newPts->Allocate(estimatedSize,estimatedSize);
|
|
vtkCellArray *newVerts = vtkCellArray::New();
|
|
newVerts->Allocate(estimatedSize,estimatedSize);
|
|
vtkCellArray *newLines = vtkCellArray::New();
|
|
newLines->Allocate(estimatedSize,estimatedSize);
|
|
vtkCellArray *newPolys = vtkCellArray::New();
|
|
newPolys->Allocate(estimatedSize,estimatedSize);
|
|
|
|
output->Allocate(numCells);
|
|
|
|
// locator used to merge potentially duplicate points
|
|
if(this->Locator==0)
|
|
{
|
|
this->CreateDefaultLocator();
|
|
}
|
|
this->Locator->InitPointInsertion(newPts,input->GetBounds(),estimatedSize);
|
|
|
|
// prepare the output attributes
|
|
vtkGenericAttributeCollection *attributes=input->GetAttributes();
|
|
vtkGenericAttribute *attribute;
|
|
vtkDataArray *attributeArray;
|
|
|
|
int c=attributes->GetNumberOfAttributes();
|
|
vtkDataSetAttributes *secondaryAttributes;
|
|
|
|
int attributeType;
|
|
|
|
vtkIdType i=0;
|
|
while(i<c)
|
|
{
|
|
attribute=attributes->GetAttribute(i);
|
|
attributeType=attribute->GetType();
|
|
if(attribute->GetCentering()==vtkPointCentered)
|
|
{
|
|
secondaryAttributes=this->secondaryPD;
|
|
|
|
attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType());
|
|
attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents());
|
|
attributeArray->SetName(attribute->GetName());
|
|
this->internalPD->AddArray(attributeArray);
|
|
attributeArray->Delete();
|
|
if(this->internalPD->GetAttribute(attributeType)==0)
|
|
{
|
|
this->internalPD->SetActiveAttribute(this->internalPD->GetNumberOfArrays()-1,attributeType);
|
|
}
|
|
}
|
|
else // vtkCellCentered
|
|
{
|
|
secondaryAttributes=this->secondaryCD;
|
|
}
|
|
|
|
attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType());
|
|
attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents());
|
|
attributeArray->SetName(attribute->GetName());
|
|
secondaryAttributes->AddArray(attributeArray);
|
|
attributeArray->Delete();
|
|
|
|
if(secondaryAttributes->GetAttribute(attributeType)==0)
|
|
{
|
|
secondaryAttributes->SetActiveAttribute(secondaryAttributes->GetNumberOfArrays()-1,
|
|
attributeType);
|
|
}
|
|
++i;
|
|
}
|
|
|
|
outPd->InterpolateAllocate(this->secondaryPD,estimatedSize,estimatedSize);
|
|
outCd->CopyAllocate(this->secondaryCD,estimatedSize,estimatedSize);
|
|
|
|
|
|
vtkGenericAdaptorCell *cell;
|
|
|
|
//----------- Begin of contouring algorithm --------------------//
|
|
vtkGenericCellIterator *cellIt = input->NewCellIterator();
|
|
|
|
if(this->InputScalarsSelection!=0)
|
|
{
|
|
int attrib=input->GetAttributes()->FindAttribute(this->InputScalarsSelection);
|
|
if(attrib!=-1)
|
|
{
|
|
vtkGenericAttribute *a=input->GetAttributes()->GetAttribute(attrib);
|
|
if(a->GetNumberOfComponents()==1)
|
|
{
|
|
input->GetAttributes()->SetActiveAttribute(attrib,0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
vtkIdType updateCount = numCells/20 + 1; // update roughly every 5%
|
|
vtkIdType count = 0;
|
|
int abortExecute=0;
|
|
|
|
input->GetTessellator()->InitErrorMetrics(input);
|
|
|
|
for(cellIt->Begin(); !cellIt->IsAtEnd() && !abortExecute; cellIt->Next())
|
|
{
|
|
if ( !(count % updateCount) )
|
|
{
|
|
this->UpdateProgress((double)count / numCells);
|
|
abortExecute = this->GetAbortExecute();
|
|
}
|
|
|
|
cell = cellIt->GetCell();
|
|
cell->Contour(this->ContourValues, NULL, input->GetAttributes(),
|
|
input->GetTessellator(),
|
|
this->Locator, newVerts, newLines, newPolys, outPd, outCd,
|
|
this->internalPD,this->secondaryPD,this->secondaryCD);
|
|
++count;
|
|
} // for each cell
|
|
cellIt->Delete();
|
|
|
|
vtkDebugMacro(<<"Created: "
|
|
<< newPts->GetNumberOfPoints() << " points, "
|
|
<< newVerts->GetNumberOfCells() << " verts, "
|
|
<< newLines->GetNumberOfCells() << " lines, "
|
|
<< newPolys->GetNumberOfCells() << " triangles");
|
|
|
|
//----------- End of contouring algorithm ----------------------//
|
|
|
|
// Update ourselves. Because we don't know up front how many verts, lines,
|
|
// polys we've created, take care to reclaim memory.
|
|
//
|
|
output->SetPoints(newPts);
|
|
newPts->Delete();
|
|
|
|
if (newVerts->GetNumberOfCells()>0)
|
|
{
|
|
output->SetVerts(newVerts);
|
|
}
|
|
newVerts->Delete();
|
|
|
|
if (newLines->GetNumberOfCells()>0)
|
|
{
|
|
output->SetLines(newLines);
|
|
}
|
|
newLines->Delete();
|
|
|
|
if (newPolys->GetNumberOfCells()>0)
|
|
{
|
|
output->SetPolys(newPolys);
|
|
}
|
|
newPolys->Delete();
|
|
|
|
this->Locator->Initialize();//releases leftover memory
|
|
output->Squeeze();
|
|
return 1;
|
|
}
|
|
|
|
|
|
// Specify a spatial locator for merging points. By default,
|
|
// an instance of vtkMergePoints is used.
|
|
void vtkGenericContourFilter::SetLocator(vtkPointLocator *locator)
|
|
{
|
|
if ( this->Locator == locator )
|
|
{
|
|
return;
|
|
}
|
|
if ( this->Locator )
|
|
{
|
|
this->Locator->UnRegister(this);
|
|
this->Locator = NULL;
|
|
}
|
|
if ( locator )
|
|
{
|
|
locator->Register(this);
|
|
}
|
|
this->Locator = locator;
|
|
this->Modified();
|
|
}
|
|
|
|
void vtkGenericContourFilter::CreateDefaultLocator()
|
|
{
|
|
if ( this->Locator == NULL )
|
|
{
|
|
this->Locator = vtkMergePoints::New();
|
|
this->Locator->Register(this);
|
|
this->Locator->Delete();
|
|
}
|
|
}
|
|
|
|
void vtkGenericContourFilter::SelectInputScalars(const char *fieldName)
|
|
{
|
|
this->SetInputScalarsSelection(fieldName);
|
|
}
|
|
|
|
void vtkGenericContourFilter::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
if (this->InputScalarsSelection)
|
|
{
|
|
os << indent << "InputScalarsSelection: "
|
|
<< this->InputScalarsSelection << endl;
|
|
}
|
|
|
|
os << indent << "Compute Gradients: "
|
|
<< (this->ComputeGradients ? "On\n" : "Off\n");
|
|
os << indent << "Compute Normals: "
|
|
<< (this->ComputeNormals ? "On\n" : "Off\n");
|
|
os << indent << "Compute Scalars: "
|
|
<< (this->ComputeScalars ? "On\n" : "Off\n");
|
|
|
|
this->ContourValues->PrintSelf(os,indent.GetNextIndent());
|
|
|
|
if ( this->Locator )
|
|
{
|
|
os << indent << "Locator: " << this->Locator << "\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "Locator: (none)\n";
|
|
}
|
|
}
|
|
|
|
// Description:
|
|
// Set a particular contour value at contour number i. The index i ranges
|
|
// between 0<=i<NumberOfContours.
|
|
void vtkGenericContourFilter::SetValue(int i, float value)
|
|
{this->ContourValues->SetValue(i,value);}
|
|
|
|
// Description:
|
|
// Get the ith contour value.
|
|
double vtkGenericContourFilter::GetValue(int i)
|
|
{return this->ContourValues->GetValue(i);}
|
|
|
|
// Description:
|
|
// Get a pointer to an array of contour values. There will be
|
|
// GetNumberOfContours() values in the list.
|
|
double *vtkGenericContourFilter::GetValues()
|
|
{return this->ContourValues->GetValues();}
|
|
|
|
// Description:
|
|
// Fill a supplied list with contour values. There will be
|
|
// GetNumberOfContours() values in the list. Make sure you allocate
|
|
// enough memory to hold the list.
|
|
void vtkGenericContourFilter::GetValues(double *contourValues)
|
|
{this->ContourValues->GetValues(contourValues);}
|
|
|
|
// Description:
|
|
// Set the number of contours to place into the list. You only really
|
|
// need to use this method to reduce list size. The method SetValue()
|
|
// will automatically increase list size as needed.
|
|
void vtkGenericContourFilter::SetNumberOfContours(int number)
|
|
{this->ContourValues->SetNumberOfContours(number);}
|
|
|
|
// Description:
|
|
// Get the number of contours in the list of contour values.
|
|
int vtkGenericContourFilter::GetNumberOfContours()
|
|
{return this->ContourValues->GetNumberOfContours();}
|
|
|
|
// Description:
|
|
// Generate numContours equally spaced contour values between specified
|
|
// range. Contour values will include min/max range values.
|
|
void vtkGenericContourFilter::GenerateValues(int numContours, double range[2])
|
|
{this->ContourValues->GenerateValues(numContours, range);}
|
|
|
|
// Description:
|
|
// Generate numContours equally spaced contour values between specified
|
|
// range. Contour values will include min/max range values.
|
|
void vtkGenericContourFilter::GenerateValues(int numContours, double
|
|
rangeStart, double rangeEnd)
|
|
{this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkGenericContourFilter::FillInputPortInformation(int port,
|
|
vtkInformation* info)
|
|
{
|
|
if(!this->Superclass::FillInputPortInformation(port, info))
|
|
{
|
|
return 0;
|
|
}
|
|
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet");
|
|
return 1;
|
|
}
|
|
|