/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkQuadricDecimation.h,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. =========================================================================*/ // .NAME vtkQuadricDecimation - reduce the number of triangles in a mesh // .SECTION Description // vtkQuadricDecimation is a filter to reduce the number of triangles in // a triangle mesh, forming a good approximation to the original geometry. // The input to vtkQuadricDecimation is a vtkPolyData object, and only // triangles are treated. If you desire to decimate polygonal meshes, first // triangulate the polygons with vtkTriangleFilter. // // The algorithm is based on repeated edge collapses until the requested mesh // reduction is achieved. Edges are placed in a priority queue based on the // "cost" to delete the edge. The cost is an approximate measure of error // (distance to the original surface)--described by the so-called quadric // error measure. The quadric error measure is associated with each vertex of // the mesh and represents a matrix of planes incident on that vertex. The // distance of the planes to the vertex is the error in the position of the // vertex (originally the vertex error iz zero). As edges are deleted, the // quadric error measure associated with the two end points of the edge are // summed (this combines the plane equations) and an optimal collapse point // can be computed. Edges connected to the collapse point are then reinserted // into the queue after computing the new cost to delete them. The process // continues until the desired reduction level is reached or topological // constraints prevent further reduction. Note that this basic algorithm can // be extended to higher dimensions by // taking into account variation in attributes (i.e., scalars, vectors, and // so on). // // This paper is based on the work of Garland and Heckbert who first // presented the quadric error measure at Siggraph '97 "Surface // Simplification Using Quadric Error Metrics". For details of the algorithm // Michael Garland's Ph.D. thesis is also recommended. Hughues Hoppe's Vis // '99 paper, "New Quadric Metric for Simplifying Meshes with Appearance // Attributes" is also a good take on the subject especially as it pertains // to the error metric applied to attributes. // // .SECTION Thanks // Thanks to Bradley Lowekamp of the National Library of Medicine/NIH for // contributing this class. #ifndef __vtkQuadricDecimation_h #define __vtkQuadricDecimation_h #include "vtkPolyDataAlgorithm.h" class vtkEdgeTable; class vtkIdList; class vtkPointData; class vtkPriorityQueue; class vtkDoubleArray; class VTK_GRAPHICS_EXPORT vtkQuadricDecimation : public vtkPolyDataAlgorithm { public: vtkTypeRevisionMacro(vtkQuadricDecimation, vtkPolyDataAlgorithm); void PrintSelf(ostream& os, vtkIndent indent); static vtkQuadricDecimation *New(); // Description: // Set/Get the desired reduction (expressed as a fraction of the original // number of triangles). The actual reduction may be less depending on // triangulation and topological constraints. vtkSetClampMacro(TargetReduction, double, 0.0, 1.0); vtkGetMacro(TargetReduction, double); // Description: // Decide whether to include data attributes in the error metric. If off, // then only geometric error is used to control the decimation. By default // the attribute errors are off. vtkSetMacro(AttributeErrorMetric, int); vtkGetMacro(AttributeErrorMetric, int); vtkBooleanMacro(AttributeErrorMetric, int); // Description: // If attribute errors are to be included in the metric (i.e., // AttributeErrorMetric is on), then the following flags control which // attributes are to be included in the error calculation. By default all // of these are on. vtkSetMacro(ScalarsAttribute, int); vtkGetMacro(ScalarsAttribute, int); vtkBooleanMacro(ScalarsAttribute, int); vtkSetMacro(VectorsAttribute, int); vtkGetMacro(VectorsAttribute, int); vtkBooleanMacro(VectorsAttribute, int); vtkSetMacro(NormalsAttribute, int); vtkGetMacro(NormalsAttribute, int); vtkBooleanMacro(NormalsAttribute, int); vtkSetMacro(TCoordsAttribute, int); vtkGetMacro(TCoordsAttribute, int); vtkBooleanMacro(TCoordsAttribute, int); vtkSetMacro(TensorsAttribute, int); vtkGetMacro(TensorsAttribute, int); vtkBooleanMacro(TensorsAttribute, int); // Description: // Set/Get the scaling weight contribution of the attribute. These // values are used to weight the contribution of the attributes // towards the error metric. vtkSetMacro(ScalarsWeight, double); vtkSetMacro(VectorsWeight, double); vtkSetMacro(NormalsWeight, double); vtkSetMacro(TCoordsWeight, double); vtkSetMacro(TensorsWeight, double); vtkGetMacro(ScalarsWeight, double); vtkGetMacro(VectorsWeight, double); vtkGetMacro(NormalsWeight, double); vtkGetMacro(TCoordsWeight, double); vtkGetMacro(TensorsWeight, double); // Description: // Get the actual reduction. This value is only valid after the // filter has executed. vtkGetMacro(ActualReduction, double); protected: vtkQuadricDecimation(); ~vtkQuadricDecimation(); int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); // Description: // Do the dirty work of eliminating the edge; return the number of // triangles deleted. int CollapseEdge(vtkIdType pt0Id, vtkIdType pt1Id); // Description: // Compute quadric for all vertices void InitializeQuadrics(vtkIdType numPts); // Description: // Free boundary edges are weighted void AddBoundaryConstraints(void); // Description: // Compute quadric for this vertex. void ComputeQuadric(vtkIdType pointId); // Description: // Add the quadrics for these 2 points since the edge between them has // been collapsed. void AddQuadric(vtkIdType oldPtId, vtkIdType newPtId); // Description: // Compute cost for contracting this edge and the point that gives us this // cost. double ComputeCost(vtkIdType edgeId, double *x); double ComputeCost2(vtkIdType edgeId, double *x); // Description: // Find all edges that will have an endpoint change ids because of an edge // collapse. p1Id and p2Id are the endpoints of the edge. p2Id is the // pointId being removed. void FindAffectedEdges(vtkIdType p1Id, vtkIdType p2Id, vtkIdList *edges); // Description: // Find a cell that uses this edge. vtkIdType GetEdgeCellId(vtkIdType p1Id, vtkIdType p2Id); int IsGoodPlacement(vtkIdType pt0Id, vtkIdType pt1Id, const double *x); int TrianglePlaneCheck(const double t0[3], const double t1[3], const double t2[3], const double *x); void ComputeNumberOfComponents(void); void UpdateEdgeData(vtkIdType ptoId, vtkIdType pt1Id); // Description: // Helper function to set and get the point and it's attributes as an array void SetPointAttributeArray(vtkIdType ptId, const double *x); void GetPointAttributeArray(vtkIdType ptId, double *x); // Description: // Find out how many components there are for each attribute for this // poly data. void GetAttributeComponents(); double TargetReduction; double ActualReduction; int AttributeErrorMetric; int ScalarsAttribute; int VectorsAttribute; int NormalsAttribute; int TCoordsAttribute; int TensorsAttribute; double ScalarsWeight; double VectorsWeight; double NormalsWeight; double TCoordsWeight; double TensorsWeight; int NumberOfEdgeCollapses; vtkEdgeTable *Edges; vtkIdList *EndPoint1List; vtkIdList *EndPoint2List; vtkPriorityQueue *EdgeCosts; vtkDoubleArray *TargetPoints; int NumberOfComponents; vtkPolyData *Mesh; //BTX struct ErrorQuadric { double *Quadric; }; //ETX ErrorQuadric *ErrorQuadrics; int AttributeComponents[6]; double AttributeScale[6]; // Temporary variables for performance vtkIdList *CollapseCellIds; double *TempX; double *TempQuad; double *TempB; double **TempA; double *TempData; private: vtkQuadricDecimation(const vtkQuadricDecimation&); // Not implemented. void operator=(const vtkQuadricDecimation&); // Not implemented. }; #endif