1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
//##########################################################################
//# #
//# CLOUDCOMPARE #
//# #
//# This program is free software; you can redistribute it and/or modify #
//# it under the terms of the GNU General Public License as published by #
//# the Free Software Foundation; version 2 or later of the License. #
//# #
//# This program is distributed in the hope that it will be useful, #
//# but WITHOUT ANY WARRANTY; without even the implied warranty of #
//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
//# GNU General Public License for more details. #
//# #
//# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) #
//# #
//##########################################################################
#ifndef CC_NORMAL_VECTORS_HEADER
#define CC_NORMAL_VECTORS_HEADER
//CCLib
#include <GeometricalAnalysisTools.h>
//Local
#include "ccGenericPointCloud.h"
//System
#include <vector>
//! Compressed normal vectors handler
class QCC_DB_LIB_API ccNormalVectors
{
public:
//! Returns unique instance
static ccNormalVectors* GetUniqueInstance();
//! Releases unique instance
/** Call to this method is now optional.
**/
static void ReleaseUniqueInstance();
//! Returns the number of compressed normal vectors
static inline unsigned GetNumberOfVectors() { return static_cast<unsigned>(GetUniqueInstance()->m_theNormalVectors.size()); }
//! Static access to ccNormalVectors::getNormal
static inline const CCVector3& GetNormal(unsigned normIndex) { return GetUniqueInstance()->getNormal(normIndex); }
//! Returns the precomputed normal corresponding to a given compressed index
inline const CCVector3& getNormal(unsigned normIndex) const { return m_theNormalVectors[normIndex]; }
//! Returns the compressed index corresponding to a normal vector
static CompressedNormType GetNormIndex(const PointCoordinateType N[]);
//! Returns the compressed index corresponding to a normal vector (shortcut)
static inline CompressedNormType GetNormIndex(const CCVector3& N) { return GetNormIndex(N.u); }
//! 'Default' orientations
enum Orientation {
PLUS_X = 0,
MINUS_X = 1,
PLUS_Y = 2,
MINUS_Y = 3,
PLUS_Z = 4,
MINUS_Z = 5,
PLUS_BARYCENTER = 6,
MINUS_BARYCENTER = 7,
PLUS_ZERO = 8,
MINUS_ZERO = 9,
PREVIOUS = 10,
UNDEFINED = 255
};
//! Computes normal at each point of a given cloud
/** \param cloud point cloud on which to process the normals.
\param theNormsCodes array in which the normals indexes are stored
\param localModel which kind of model to use for the computation (LS = plane, QUADRIC = quadratic Height Function, TRI = triangulation)
\param localRadius local neighborhood radius (not necessary for TRI)
\param preferredOrientation specifies a preferred orientation for normals (optional)
\param progressCb progress notification (optional)
\param inputOctree inputOctree input cloud octree (optional).
\return success
**/
static bool ComputeCloudNormals(ccGenericPointCloud* cloud,
NormsIndexesTableType& theNormsCodes,
CC_LOCAL_MODEL_TYPES localModel,
PointCoordinateType localRadius,
Orientation preferredOrientation = UNDEFINED,
CCLib::GenericProgressCallback* progressCb = 0,
CCLib::DgmOctree* inputOctree = 0);
//! Tries to guess a very naive 'local radius' for normals computation (see ComputeCloudNormals)
/** \param cloud point cloud on which to process the normals.
\return naive radius (percentage of the cloud bounding-box)
**/
static PointCoordinateType GuessNaiveRadius(ccGenericPointCloud* cloud);
//! Tries to guess the best 'local radius' for normals computation (see ComputeCloudNormals)
/** \param cloud point cloud on which to process the normals.
\param cloudOctree input cloud octree (optional)
\param progressCb progress notification (optional)
\return the best radius (strictly positive value) or 0 if an error occurred
**/
static PointCoordinateType GuessBestRadius( ccGenericPointCloud* cloud,
CCLib::DgmOctree* cloudOctree = 0,
CCLib::GenericProgressCallback* progressCb = 0);
//! Updates normals orientation based on a preferred orientation
/** \param theCloud point cloud on which to process the normals.
\param theNormsCodes array in which the normals indexes are stored
\param preferredOrientation specifies a preferred orientation for normals
\return success
**/
static bool UpdateNormalOrientations( ccGenericPointCloud* theCloud,
NormsIndexesTableType& theNormsCodes,
Orientation preferredOrientation);
//! Converts a normal vector to geological 'strike & dip' parameters (N[dip]°E - [strike]°)
/** \param[in] N normal (should be normalized!)
\param[out] strike_deg strike value (in degrees)
\param[out] dip_deg dip value (in degrees)
**/
static void ConvertNormalToStrikeAndDip(const CCVector3& N, PointCoordinateType& strike_deg, PointCoordinateType& dip_deg);
//! Converts a normal vector to geological 'dip direction & dip' parameters
/** See http://en.wikipedia.org/wiki/Strike_and_dip
The dip direction is the azimuth of the direction (in [0,360[).
The dip is always in [0,90].
\param[in] N normal (should be normalized!)
\param[out] dip_deg value (in degrees)
\param[out] dipDir_deg dip direction value (in degrees)
**/
static void ConvertNormalToDipAndDipDir(const CCVector3& N, PointCoordinateType& dip_deg, PointCoordinateType& dipDir_deg);
//! Converts a couple of geological 'dip direction & dip' parameters to a unit normal vector
/** \param[in] dip_deg value (in degrees)
\param[in] dipDir_deg dip direction value(in degrees)
\param[in] upward whether the output normal vector should point towards Z+ (true) or Z- (false)
\return unit normal vector
**/
static CCVector3 ConvertDipAndDipDirToNormal(PointCoordinateType dip_deg, PointCoordinateType dipDir_deg, bool upward = true);
//! Converts geological 'strike & dip' parameters (N[dip]°E - [strike]°) to a string
/** \param[in] strike_deg strike value (in degrees)
\param[in] dip_deg dip value (in degrees)
\return formatted string "N[strike]°E - [dip]°"
**/
static QString ConvertStrikeAndDipToString(double& strike_deg, double& dip_deg);
//! Converts geological 'dip direction & dip' parameters to a string
/** \param[in] dip_deg dip angle value (in degrees)
\param[in] dipDir_deg dip direction value (in degrees)
\return formatted string "Dip direction: [dipDir]° - Dip angle: [dip]°"
**/
static QString ConvertDipAndDipDirToString(PointCoordinateType dip_deg, PointCoordinateType dipDir_deg);
//! Converts a normal vector to HSV color space
/** Uses 'strike & dip' parameters (H=strike, S=dip, V=constant)
\param[in] N normal (should be normalized!)
\param[out] H hue [0;360[
\param[out] S saturation [0;1]
\param[out] V value [0;1]
**/
static void ConvertNormalToHSV(const CCVector3& N, float& H, float& S, float& V);
//! Converts a normal vector to RGB color space
/** Uses 'ConvertNormalToHSV' then converts HSV to RGB.
\param[in] N normal (should be normalized!)
\return RGB value (components between 0 and MAX_COLOR_COMP)
**/
static ccColor::Rgb ConvertNormalToRGB(const CCVector3& N);
public:
//! Default destructor
virtual ~ccNormalVectors();
//! Allocates normal HSV colors array
/** Mandatory for HSV color related methods (getNormalHSVColor, etc.)
**/
bool enableNormalHSVColorsArray();
//! Returns the HSV color equivalent to a given compressed normal index
const ccColor::Rgb& getNormalHSVColor(unsigned index) const;
//! Returns the HSV color array
inline const std::vector<ccColor::Rgb>& getNormalHSVColorArray() const { return m_theNormalHSVColors; }
//! Helper: computes the normal (with best LS fit)
static bool ComputeNormalWithLS(CCLib::GenericIndexedCloudPersist* pointAndNeighbors, CCVector3& N);
//! Helper: computes the normal (with Delaunay 2.5D)
/** The normal is computed at the first point (assuming the others are its neighbors).
**/
static bool ComputeNormalWithTri(CCLib::GenericIndexedCloudPersist* pointAndNeighbors, CCVector3& N);
//! Helper: computes the normal (with Delaunay 2.5D)
/** The normal is computed at the first point (assuming the others are its neighbors).
**/
static bool ComputeNormalWithQuadric(CCLib::GenericIndexedCloudPersist* points, const CCVector3& P, CCVector3& N);
protected:
//! Default constructor
/** Shouldn't be called directly. Use 'GetUniqueInstance' instead.
**/
ccNormalVectors();
//! Inits internal structures
bool init();
//! Compressed normal vectors
std::vector<CCVector3> m_theNormalVectors;
//! 'HSV' colors corresponding to each compressed normal index
/** In fact, HSV color has already been converted to RGB here for faster display.
**/
std::vector<ccColor::Rgb> m_theNormalHSVColors;
//! Cellular method for octree-based normal computation
static bool ComputeNormsAtLevelWithQuadric(const CCLib::DgmOctree::octreeCell& cell, void** additionalParameters, CCLib::NormalizedProgress* nProgress = 0);
//! Cellular method for octree-based normal computation
static bool ComputeNormsAtLevelWithLS(const CCLib::DgmOctree::octreeCell& cell, void** additionalParameters, CCLib::NormalizedProgress* nProgress = 0);
//! Cellular method for octree-based normal computation
static bool ComputeNormsAtLevelWithTri(const CCLib::DgmOctree::octreeCell& cell, void** additionalParameters, CCLib::NormalizedProgress* nProgress = 0);
};
#endif //CC_NORMAL_VECTORS_HEADER
|