209 lines
7.5 KiB
C
209 lines
7.5 KiB
C
|
|
/*=========================================================================
|
||
|
|
|
||
|
|
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 methods for printing and determining type information.
|
||
|
|
*/
|
||
|
|
vtkTypeMacro(vtkProjectedTerrainPath, vtkPolyDataAlgorithm);
|
||
|
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
||
|
|
///@}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 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() override;
|
||
|
|
|
||
|
|
int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
|
||
|
|
int FillInputPortInformation(int port, vtkInformation* info) override;
|
||
|
|
|
||
|
|
// 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;
|
||
|
|
|
||
|
|
// Bookkeeping 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&) = delete;
|
||
|
|
void operator=(const vtkProjectedTerrainPath&) = delete;
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif
|