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.
 
 
 
 
 
 

257 lines
8.8 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkGenericCellTessellator.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 "vtkGenericCellTessellator.h"
#include "vtkObjectFactory.h"
#include "vtkPoints.h"
#include "vtkIdList.h"
#include "vtkGenericAdaptorCell.h"
#include "vtkPointData.h"
#include "vtkDoubleArray.h"
#include "vtkMergePoints.h"
#include "vtkCellArray.h"
#include "vtkCollection.h"
#include "vtkGenericSubdivisionErrorMetric.h"
#include "vtkGenericAttribute.h"
#include "vtkGenericAttributeCollection.h"
#include "vtkGenericCellIterator.h"
#include <assert.h>
#include "vtkMath.h"
vtkCxxRevisionMacro(vtkGenericCellTessellator, "$Revision: 1.11 $");
vtkCxxSetObjectMacro(vtkGenericCellTessellator, ErrorMetrics, vtkCollection);
//-----------------------------------------------------------------------------
// Create the tessellator helper with a default of 0.25 for threshold
//
vtkGenericCellTessellator::vtkGenericCellTessellator()
{
this->ErrorMetrics = vtkCollection::New();
this->MaxErrorsCapacity=0;
this->MaxErrors=0;
this->Measurement=0;
}
//-----------------------------------------------------------------------------
vtkGenericCellTessellator::~vtkGenericCellTessellator()
{
this->SetErrorMetrics( 0 );
if(this->MaxErrors!=0)
{
delete[] this->MaxErrors;
}
}
//-----------------------------------------------------------------------------
void vtkGenericCellTessellator::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "ErrorMetrics: "
<< this->ErrorMetrics << endl;
}
//-----------------------------------------------------------------------------
// Description:
// If true, measure the quality of the fixed subdivision.
int vtkGenericCellTessellator::GetMeasurement()
{
return this->Measurement;
}
//-----------------------------------------------------------------------------
// Description:
// If true, measure the quality of the fixed subdivision.
void vtkGenericCellTessellator::SetMeasurement(int flag)
{
this->Measurement=flag;
}
//-----------------------------------------------------------------------------
// Description:
// Does the edge need to be subdivided according to at least one error
// metric? The edge is defined by its `leftPoint' and its `rightPoint'.
// `leftPoint', `midPoint' and `rightPoint' have to be initialized before
// calling RequiresEdgeSubdivision().
// Their format is global coordinates, parametric coordinates and
// point centered attributes: xyx rst abc de...
// `alpha' is the normalized abscissa of the midpoint along the edge.
// (close to 0 means close to the left point, close to 1 means close to the
// right point)
// \pre leftPoint_exists: leftPoint!=0
// \pre midPoint_exists: midPoint!=0
// \pre rightPoint_exists: rightPoint!=0
// \pre clamped_alpha: alpha>0 && alpha<1
// \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint)
// =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6
int vtkGenericCellTessellator::RequiresEdgeSubdivision(double *leftPoint,
double *midPoint,
double *rightPoint,
double alpha)
{
assert("pre: leftPoint_exists" && leftPoint!=0);
assert("pre: midPoint_exists" && midPoint!=0);
assert("pre: rightPoint_exists" && rightPoint!=0);
assert("pre: clamped_alpha" && alpha>0 && alpha<1);
int result=0;
this->ErrorMetrics->InitTraversal();
vtkGenericSubdivisionErrorMetric *e=static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
// Once we found at least one error metric that need subdivision,
// the subdivision has to be done and there is no need to check for other
// error metrics.
while(!result&&(e!=0))
{
result=e->RequiresEdgeSubdivision(leftPoint,midPoint,rightPoint,alpha);
e=static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
}
return result;
}
//-----------------------------------------------------------------------------
// Description:
// Update the max error of each error metric according to the error at the
// mid-point. The type of error depends on the state
// of the concrete error metric. For instance, it can return an absolute
// or relative error metric.
// See RequiresEdgeSubdivision() for a description of the arguments.
// \pre leftPoint_exists: leftPoint!=0
// \pre midPoint_exists: midPoint!=0
// \pre rightPoint_exists: rightPoint!=0
// \pre clamped_alpha: alpha>0 && alpha<1
// \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint)
// =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6
void vtkGenericCellTessellator::UpdateMaxError(double *leftPoint,
double *midPoint,
double *rightPoint,
double alpha)
{
assert("pre: leftPoint_exists" && leftPoint!=0);
assert("pre: midPoint_exists" && midPoint!=0);
assert("pre: rightPoint_exists" && rightPoint!=0);
assert("pre: clamped_alpha" && alpha>0 && alpha<1);
this->ErrorMetrics->InitTraversal();
vtkGenericSubdivisionErrorMetric *e=static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
// Once we found at least one error metric that need subdivision,
// the subdivision has to be done and there is no need to check for other
// error metrics.
int i=0;
while(e!=0)
{
double error=e->GetError(leftPoint,midPoint,rightPoint,alpha);
assert("check: positive_error" && error>=0);
if(error>this->MaxErrors[i])
{
this->MaxErrors[i]=error;
}
e=static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
++i;
}
}
//-----------------------------------------------------------------------------
// Description:
// Init the error metric with the dataset. Should be called in each filter
// before any tessellation of any cell.
void vtkGenericCellTessellator::InitErrorMetrics(vtkGenericDataSet *ds)
{
this->ErrorMetrics->InitTraversal();
vtkGenericSubdivisionErrorMetric *e=static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
while(e!=0)
{
e->SetDataSet(ds);
e=static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
}
if(this->Measurement)
{
this->ResetMaxErrors();
}
}
//-----------------------------------------------------------------------------
// Description:
// Reset the maximal error of each error metric. The purpose of the maximal
// error is to measure the quality of a fixed subdivision.
void vtkGenericCellTessellator::ResetMaxErrors()
{
int c=this->ErrorMetrics->GetNumberOfItems();
// Allocate the array.
if(c>this->MaxErrorsCapacity)
{
this->MaxErrorsCapacity=c;
if(this->MaxErrors!=0)
{
delete[] this->MaxErrors;
}
this->MaxErrors=new double[this->MaxErrorsCapacity];
}
int i=0;
while(i<c)
{
this->MaxErrors[i]=0;
++i;
}
}
//-----------------------------------------------------------------------------
// Description:
// Get the maximum error measured after the fixed subdivision.
// \pre errors_exists: errors!=0
// \pre valid_size: sizeof(errors)==GetErrorMetrics()->GetNumberOfItems()
void vtkGenericCellTessellator::GetMaxErrors(double *errors)
{
assert("pre: errors_exists" && errors!=0);
int c=this->ErrorMetrics->GetNumberOfItems();
int i=0;
while(i<c)
{
errors[i]=this->MaxErrors[i];
++i;
}
}
//-----------------------------------------------------------------------------
// Description:
// Send the current cell to error metrics. Should be called at the beginning
// of the implementation of Tessellate(), Triangulate()
// or TessellateTriangleFace()
// \pre cell_exists: cell!=0
void vtkGenericCellTessellator::SetGenericCell(vtkGenericAdaptorCell *cell)
{
assert("pre: cell_exists" && cell!=0);
this->ErrorMetrics->InitTraversal();
vtkGenericSubdivisionErrorMetric *e=static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
while(e!=0)
{
e->SetGenericCell(cell);
e=static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
}
}