/*========================================================================= Program: Visualization Toolkit Module: vtkProjectedTerrainPath.h 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. =========================================================================*/ /** * @class vtkProjectedTerrainPath * @brief project a polyline onto a terrain * * vtkProjectedTerrainPath projects an input polyline onto a terrain. (The * terrain is defined by a 2D height image and is the second input to the * filter.) The polyline projection is controlled via several modes as * follows. 1) Simple mode projects the polyline points onto the terrain, * taking into account the height offset instance variable. 2) Non-occluded * mode insures that no parts of the polyline are occluded by the terrain * (e.g. a line passes through a mountain). This may require recursive * subdivision of the polyline. 3) Hug mode insures that the polyine points * remain within a constant distance from the surface. This may also require * recursive subdivision of the polyline. Note that both non-occluded mode * and hug mode also take into account the height offset, so it is possible * to create paths that hug terrain a certain distance above it. To use this * filter, define two inputs: 1) a polyline, and 2) an image whose scalar * values represent a height field. Then specify the mode, and the height * offset to use. * * An description of the algorithm is as follows. The filter begins by * projecting the polyline points to the image (offset by the specified * height offset). If the mode is non-occluded or hug, then the maximum * error along each line segment is computed and placed into a priority * queue. Each line segment is then split at the point of maximum error, and * the two new line segments are evaluated for maximum error. This process * continues until the line is not occluded by the terrain (non-occluded * mode) or satisfies the error on variation from the surface (hug * mode). (Note this process is repeated for each polyline in the * input. Also, the maximum error is computed in two parts: a maximum * positive error and maximum negative error. If the polyline is above the * terrain--i.e., the height offset is positive--in non-occluded or hug mode * all negative errors are eliminated. If the polyline is below the * terrain--i.e., the height offset is negative--in non-occluded or hug mode * all positive errors are eliminated.) * * @warning * This algorithm requires the entire input image to be in memory, hence it * may not work for extremely large images. * * @warning * The input height image is assumed to be positioned in the x-y plane so the * scalar value is the z-coordinate, height value. * * @warning * A priority queue is used so that the 1) the total number of line segments * can be controlled, and 2) the algorithm can terminate when the errors in * the queue are less than the specified error tolerance. * * @sa * vtkGreedyTerrainDecimation */ #ifndef vtkProjectedTerrainPath_h #define vtkProjectedTerrainPath_h #include "vtkFiltersHybridModule.h" // For export macro #include "vtkPolyDataAlgorithm.h" class vtkPriorityQueue; class vtkImageData; class vtkEdgeList; class vtkPoints; class VTKFILTERSHYBRID_EXPORT vtkProjectedTerrainPath : public vtkPolyDataAlgorithm { public: //@{ /** * Standard methids for printing and determining type information. */ vtkTypeMacro(vtkProjectedTerrainPath,vtkPolyDataAlgorithm); void PrintSelf(ostream& os, vtkIndent indent); //@} /** * Instantiate the class. */ static vtkProjectedTerrainPath* New(); //@{ /** * Specify the second input (the terrain) onto which the polyline(s) should be projected. * Note: This assigns a data object as the input terrain. * To establish a pipeline connection, use * SetSourceConnection() method. */ void SetSourceData(vtkImageData *source); vtkImageData *GetSource(); //@} /** * Specify the second input (the terrain) onto which the polyline(s) should be projected. * Note: vtkImageData* is required */ void SetSourceConnection(vtkAlgorithmOutput* algOutput); enum {SIMPLE_PROJECTION=0,NONOCCLUDED_PROJECTION,HUG_PROJECTION}; //@{ /** * Determine how to control the projection process. Simple projection * just projects the original polyline points. Non-occluded projection * insures that the polyline does not intersect the terrain surface. * Hug projection is similar to non-occulded projection except that * produces a path that is nearly parallel to the terrain (within the * user specified height tolerance). */ vtkSetClampMacro(ProjectionMode,int,SIMPLE_PROJECTION,HUG_PROJECTION); vtkGetMacro(ProjectionMode,int); void SetProjectionModeToSimple() {this->SetProjectionMode(SIMPLE_PROJECTION);} void SetProjectionModeToNonOccluded() {this->SetProjectionMode(NONOCCLUDED_PROJECTION);} void SetProjectionModeToHug() {this->SetProjectionMode(HUG_PROJECTION);} //@} //@{ /** * This is the height above (or below) the terrain that the projected * path should be. Positive values indicate distances above the terrain; * negative values indicate distances below the terrain. */ vtkSetMacro(HeightOffset,double); vtkGetMacro(HeightOffset,double); //@} //@{ /** * This is the allowable variation in the altitude of the path * with respect to the variation in the terrain. It only comes * into play if the hug projection mode is enabled. */ vtkSetClampMacro(HeightTolerance,double,0.0,VTK_FLOAT_MAX); vtkGetMacro(HeightTolerance,double); //@} //@{ /** * This instance variable can be used to limit the total number of line * segments created during subdivision. Note that the number of input line * segments will be the minimum number that cab be output. */ vtkSetClampMacro(MaximumNumberOfLines,vtkIdType,1,VTK_ID_MAX); vtkGetMacro(MaximumNumberOfLines,vtkIdType); //@} protected: vtkProjectedTerrainPath(); ~vtkProjectedTerrainPath(); virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); virtual int FillInputPortInformation(int port, vtkInformation *info); // Supporting methods void GetImageIndex(double x[3], double loc[2], int ij[2]); double GetHeight(double loc[2], int ij[2]); void ComputeError(vtkIdType edgeId); void RemoveOcclusions(); void HugTerrain(); void SplitEdge(vtkIdType eId, double t); //ivars that the API addresses int ProjectionMode; double HeightOffset; double HeightTolerance; vtkIdType MaximumNumberOfLines; //Bookeeping arrays int Dimensions[3]; int Extent[6]; double Origin[3]; double Spacing[3]; vtkDataArray *Heights; vtkPoints *Points; vtkIdType NumLines; //Errors above/below terrain. In both instances, negative values are //inserted because the priority queue puts smallest values on top. vtkPriorityQueue *PositiveLineError; //errors above terrain vtkPriorityQueue *NegativeLineError; //errors below terrain //This is a PIMPL'd vector representing edges vtkEdgeList *EdgeList; private: vtkProjectedTerrainPath(const vtkProjectedTerrainPath&) VTK_DELETE_FUNCTION; void operator=(const vtkProjectedTerrainPath&) VTK_DELETE_FUNCTION; }; #endif