ccNormalVectors.h 11 KB

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