/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkGreedyTerrainDecimation.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 vtkGreedyTerrainDecimation - reduce height field (represented as image) to reduced TIN // .SECTION Description // vtkGreedyTerrainDecimation approximates a height field with a triangle // mesh (triangulated irregular network - TIN) using a greedy insertion // algorithm similar to that described by Garland and Heckbert in their paper // "Fast Polygonal Approximations of Terrain and Height Fields" (Technical // Report CMU-CS-95-181). The input to the filter is a height field // (represented by a image whose scalar values are height) and the output of // the filter is polygonal data consisting of triangles. The number of // triangles in the output is reduced in number as compared to a naive // tessellation of the input height field. This filter copies point data // from the input to the output for those points present in the output. // // An brief description of the algorithm is as follows. The algorithm uses a // top-down decimation approach that initially represents the height field // with two triangles (whose vertices are at the four corners of the // image). These two triangles form a Delaunay triangulation. In an iterative // fashion, the point in the image with the greatest error (as compared to // the original height field) is injected into the triangulation. (Note that // the single point with the greatest error per triangle is identified and // placed into a priority queue. As the triangulation is modified, the errors // from the deleted triangles are removed from the queue, error values from // the new triangles are added.) The point whose error is at the top of the // queue is added to the triangulaion modifying it using the standard // incremental Delaunay point insertion (see vtkDelaunay2D) algorithm. Points // are repeatedly inserted until the appropriate (user-specified) error // criterion is met. // // To use this filter, set the input and specify the error measure to be // used. The error measure options are 1) the absolute number of triangles // to be produced; 2) a fractional reduction of the mesh (numTris/maxTris) // where maxTris is the largest possible number of triangles // 2*(dims[0]-1)*(dims[1]-1); 3) an absolute measure on error (maximum // difference in height field to reduced TIN); and 4) relative error (the // absolute error is normalized by the diagonal of the bounding box of the // height field). // // .SECTION Caveats // This algorithm requires the entire input dataset to be in memory, hence it // may not work for extremely large images. Invoking BoundaryVertexDeletionOff // will allow you to stitch together images with matching boundaries. // // The input height image is assumed to be positioned in the x-y plane so the // scalar value is the z-coordinate, height value. // // .SECTION See Also // vtkDecimatePro vtkQuadricDecimation vtkQuadricClustering #ifndef __vtkGreedyTerrainDecimation_h #define __vtkGreedyTerrainDecimation_h #include "vtkPolyDataAlgorithm.h" class vtkPriorityQueue; class vtkDataArray; class vtkPointData; class vtkIdList; class vtkDoubleArray; class vtkFloatArray; //PIMPL Encapsulation for STL containers class vtkGreedyTerrainDecimationTerrainInfoType; class vtkGreedyTerrainDecimationPointInfoType; #define VTK_ERROR_NUMBER_OF_TRIANGLES 0 #define VTK_ERROR_SPECIFIED_REDUCTION 1 #define VTK_ERROR_ABSOLUTE 2 #define VTK_ERROR_RELATIVE 3 class VTK_HYBRID_EXPORT vtkGreedyTerrainDecimation : public vtkPolyDataAlgorithm { public: vtkTypeRevisionMacro(vtkGreedyTerrainDecimation,vtkPolyDataAlgorithm); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Instantiate the class. static vtkGreedyTerrainDecimation* New(); // Description: // Specify how to terminate the algorithm: either as an absolute number of // triangles, a relative number of triangles (normalized by the full // resolution mesh), an absolute error (in the height field), or relative // error (normalized by the length of the diagonal of the image). vtkSetClampMacro(ErrorMeasure,int,VTK_ERROR_NUMBER_OF_TRIANGLES,VTK_ERROR_RELATIVE); vtkGetMacro(ErrorMeasure,int); void SetErrorMeasureToNumberOfTriangles() {this->SetErrorMeasure(VTK_ERROR_NUMBER_OF_TRIANGLES);} void SetErrorMeasureToSpecifiedReduction() {this->SetErrorMeasure(VTK_ERROR_SPECIFIED_REDUCTION);} void SetErrorMeasureToAbsoluteError() {this->SetErrorMeasure(VTK_ERROR_ABSOLUTE);} void SetErrorMeasureToRelativeError() {this->SetErrorMeasure(VTK_ERROR_RELATIVE);} // Description: // Specify the number of triangles to produce on output. (It is a // good idea to make sure this is less than a tessellated mesh // at full resolution.) You need to set this value only when // the error measure is set to NumberOfTriangles. vtkSetClampMacro(NumberOfTriangles,vtkIdType,2,VTK_LARGE_ID); vtkGetMacro(NumberOfTriangles,vtkIdType); // Description: // Specify the reduction of the mesh (represented as a fraction). Note // that a value of 0.10 means a 10% reduction. You need to set this value // only when the error measure is set to SpecifiedReduction. vtkSetClampMacro(Reduction,double,0.0,1.0); vtkGetMacro(Reduction,double); // Description: // Specify the absolute error of the mesh; that is, the error in height // between the decimated mesh and the original height field. You need to // set this value only when the error measure is set to AbsoluteError. vtkSetClampMacro(AbsoluteError,double,0.0,VTK_DOUBLE_MAX); vtkGetMacro(AbsoluteError,double); // Description: // Specify the relative error of the mesh; that is, the error in height // between the decimated mesh and the original height field normalized by // the diagonal of the image. You need to set this value only when the // error measure is set to RelativeError. vtkSetClampMacro(RelativeError,double,0.0,VTK_DOUBLE_MAX); vtkGetMacro(RelativeError,double); // Description: // Turn on/off the deletion of vertices on the boundary of a mesh. This // may limit the maximum reduction that may be achieved. vtkSetMacro(BoundaryVertexDeletion,int); vtkGetMacro(BoundaryVertexDeletion,int); vtkBooleanMacro(BoundaryVertexDeletion,int); // Description: // Compute normals based on the input image. Off by default. vtkSetMacro(ComputeNormals, int); vtkGetMacro(ComputeNormals, int); vtkBooleanMacro(ComputeNormals, int); protected: vtkGreedyTerrainDecimation(); ~vtkGreedyTerrainDecimation(); virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); virtual int FillInputPortInformation(int port, vtkInformation *info); int ComputeNormals; vtkFloatArray* Normals; void ComputePointNormal(int i, int j, float n[3]); //ivars that the API addresses int ErrorMeasure; vtkIdType NumberOfTriangles; double Reduction; double AbsoluteError; double RelativeError; int BoundaryVertexDeletion; //Can we delete boundary vertices? //Used for convenience vtkPolyData *Mesh; vtkPointData *InputPD; vtkPointData *OutputPD; vtkDoubleArray *Points; vtkDataArray *Heights; vtkIdType CurrentPointId; double Tolerance; vtkIdList *Neighbors; int Dimensions[3]; double Origin[3]; double Spacing[3]; vtkIdType MaximumNumberOfTriangles; double Length; //Bookeeping arrays vtkPriorityQueue *TerrainError; //errors for each pt in height field vtkGreedyTerrainDecimationTerrainInfoType *TerrainInfo; //owning triangle for each pt vtkGreedyTerrainDecimationPointInfoType *PointInfo; //map mesh pt id to input pt id //Make a guess at initial allocation void EstimateOutputSize(const vtkIdType numInputPts, vtkIdType &numPts, vtkIdType &numTris); //Returns non-zero if the error measure is satisfied. virtual int SatisfiesErrorMeasure(double error); //Insert all the boundary vertices into the TIN void InsertBoundaryVertices(); //Insert a point into the triangulation; get a point from the triangulation vtkIdType AddPointToTriangulation(vtkIdType inputPtId); vtkIdType InsertNextPoint(vtkIdType inputPtId, double x[3]); double *GetPoint(vtkIdType id); void GetPoint(vtkIdType id, double x[3]); //Helper functions void GetTerrainPoint(int i, int j, double x[3]); void ComputeImageCoordinates(vtkIdType inputPtId, int ij[2]); int InCircle (double x[3], double x1[3], double x2[3], double x3[3]); vtkIdType FindTriangle(double x[3], vtkIdType ptIds[3], vtkIdType tri, double tol, vtkIdType nei[3], vtkIdList *neighbors, int& status); void CheckEdge(vtkIdType ptId, double x[3], vtkIdType p1, vtkIdType p2, vtkIdType tri, int depth); void UpdateTriangles(vtkIdType meshPtId); //update all points connected to this point void UpdateTriangle(vtkIdType triId, vtkIdType p1, vtkIdType p2, vtkIdType p3); void UpdateTriangle(vtkIdType triId, int ij1[2], int ij2[2], int ij3[2], double h[4]); int CharacterizeTriangle(int ij1[2], int ij2[2], int ij[3], int* &min, int* &max, int* &midL, int* &midR, int* &mid, int mid2[2], double h[3], double &hMin, double &hMax, double &hL, double &hR); private: vtkGreedyTerrainDecimation(const vtkGreedyTerrainDecimation&); // Not implemented. void operator=(const vtkGreedyTerrainDecimation&); // Not implemented. }; #endif