ccPointCloud.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976
  1. #pragma once
  2. //##########################################################################
  3. //# #
  4. //# CLOUDCOMPARE #
  5. //# #
  6. //# This program is free software; you can redistribute it and/or modify #
  7. //# it under the terms of the GNU General Public License as published by #
  8. //# the Free Software Foundation; version 2 or later of the License. #
  9. //# #
  10. //# This program is distributed in the hope that it will be useful, #
  11. //# but WITHOUT ANY WARRANTY; without even the implied warranty of #
  12. //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
  13. //# GNU General Public License for more details. #
  14. //# #
  15. //# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) #
  16. //# #
  17. //##########################################################################
  18. #ifdef _MSC_VER
  19. //To get rid of the warnings about dominant inheritance
  20. #pragma warning( disable: 4250 )
  21. #endif
  22. //CCCoreLib
  23. #include <PointCloudTpl.h>
  24. //Local
  25. #include "ccColorScale.h"
  26. #include "ccNormalVectors.h"
  27. #include "ccWaveform.h"
  28. //Qt
  29. #include <QGLBuffer>
  30. class ccScalarField;
  31. class ccPolyline;
  32. class ccMesh;
  33. class QGLBuffer;
  34. class ccProgressDialog;
  35. class ccPointCloudLOD;
  36. /***************************************************
  37. ccPointCloud
  38. ***************************************************/
  39. //! Max number of points per cloud (point cloud will be chunked above this limit)
  40. #if defined(CC_ENV_32)
  41. const unsigned CC_MAX_NUMBER_OF_POINTS_PER_CLOUD = 128000000;
  42. #else //CC_ENV_64 (but maybe CC_ENV_128 one day ;)
  43. const unsigned CC_MAX_NUMBER_OF_POINTS_PER_CLOUD = 2000000000; //we must keep it below MAX_INT to avoid probable issues ;)
  44. #endif
  45. //! A 3D cloud and its associated features (color, normals, scalar fields, etc.)
  46. /** A point cloud can have multiple features:
  47. - colors (RGB)
  48. - normals (compressed)
  49. - scalar fields
  50. - an octree structure
  51. - per-point visibility information (to hide/display subsets of points)
  52. - other children objects (meshes, calibrated pictures, etc.)
  53. **/
  54. class QCC_DB_LIB_API ccPointCloud : public CCCoreLib::PointCloudTpl<ccGenericPointCloud, QString>
  55. {
  56. public:
  57. //! Base class (shortcut)
  58. using BaseClass = CCCoreLib::PointCloudTpl<ccGenericPointCloud, QString>;
  59. //! Default constructor
  60. /** Creates an empty cloud without any feature. Each of them should be
  61. specifically instantiated/created (once the points have been
  62. added to this cloud, at least partially).
  63. \param name cloud name (optional)
  64. \param uniqueID unique ID (handle with care)
  65. **/
  66. ccPointCloud(QString name = QString(), unsigned uniqueID = ccUniqueIDGenerator::InvalidUniqueID) throw();
  67. //! Default destructor
  68. ~ccPointCloud() override;
  69. //! Returns class ID
  70. CC_CLASS_ENUM getClassID() const override { return CC_TYPES::POINT_CLOUD; }
  71. public: //clone, copy, etc.
  72. //! Creates a new point cloud object from a GenericIndexedCloud
  73. /** "GenericIndexedCloud" is an extension of GenericCloud (from CCCoreLib)
  74. which provides a const random accessor to points.
  75. See CClib documentation for more information about GenericIndexedCloud.
  76. As the GenericIndexedCloud interface is very simple, only points are imported.
  77. Note: throws an 'int' exception in case of error (see CTOR_ERRORS)
  78. \param cloud a GenericIndexedCloud structure
  79. \param sourceCloud cloud from which main parameters will be imported (optional)
  80. **/
  81. static ccPointCloud* From(const CCCoreLib::GenericIndexedCloud* cloud, const ccGenericPointCloud* sourceCloud = nullptr);
  82. //! Creates a new point cloud object from a GenericCloud
  83. /** "GenericCloud" is a very simple and light interface from CCCoreLib. It is
  84. meant to give access to points coordinates of any cloud (on the
  85. condition it implements the GenericCloud interface of course).
  86. See CClib documentation for more information about GenericClouds.
  87. As the GenericCloud interface is very simple, only points are imported.
  88. Note: throws an 'int' exception in case of error (see CTOR_ERRORS)
  89. \param cloud a GenericCloud structure
  90. \param sourceCloud cloud from which main parameters will be imported (optional)
  91. **/
  92. static ccPointCloud* From(CCCoreLib::GenericCloud* cloud, const ccGenericPointCloud* sourceCloud = nullptr);
  93. //! Warnings for the partialClone method (bit flags)
  94. enum CLONE_WARNINGS { WRN_OUT_OF_MEM_FOR_COLORS = 1,
  95. WRN_OUT_OF_MEM_FOR_NORMALS = 2,
  96. WRN_OUT_OF_MEM_FOR_SFS = 4,
  97. WRN_OUT_OF_MEM_FOR_FWF = 8
  98. };
  99. //! Creates a new point cloud object from a ReferenceCloud (selection)
  100. /** "Reference clouds" are a set of indexes referring to a real point cloud.
  101. See CClib documentation for more information about ReferenceClouds.
  102. Warning: the ReferenceCloud structure must refer to this cloud.
  103. \param[in] selection a ReferenceCloud structure (pointing to source)
  104. \param[out] warnings [optional] to determine if warnings (CTOR_ERRORS) occurred during the duplication process
  105. \param[in] withChildEntities whether child entities should be transferred as well (see ccHObjectCaster::CloneChildren)
  106. **/
  107. ccPointCloud* partialClone(const CCCoreLib::ReferenceCloud* selection, int* warnings = nullptr, bool withChildEntities = true) const;
  108. //! Clones this entity
  109. /** All the main features of the entity are cloned, except from the octree and
  110. the points visibility information.
  111. \param destCloud [optional] the destination cloud can be provided here
  112. \param ignoreChildren [optional] whether to ignore the cloud's children or not (in which case they will be cloned as well)
  113. \return a copy of this entity
  114. **/
  115. ccPointCloud* cloneThis(ccPointCloud* destCloud = nullptr, bool ignoreChildren = false);
  116. //inherited from ccGenericPointCloud
  117. ccGenericPointCloud* clone(ccGenericPointCloud* destCloud = nullptr, bool ignoreChildren = false) override;
  118. //! Fuses another 3D entity with this one
  119. /** All the main features of the given entity are added, except from the octree and
  120. the points visibility information. Those features are deleted on this cloud.
  121. **/
  122. const ccPointCloud& operator +=(ccPointCloud*);
  123. public: //features deletion/clearing
  124. //! Clears the entity from all its points and features
  125. /** Display parameters are also reset to their default values.
  126. **/
  127. void clear() override;
  128. //! Erases the cloud points
  129. /** Prefer ccPointCloud::clear by default.
  130. \warning DANGEROUS
  131. **/
  132. void unallocatePoints();
  133. //! Erases the cloud colors
  134. void unallocateColors();
  135. //! Erases the cloud normals
  136. void unallocateNorms();
  137. //! Notify a modification of color / scalar field display parameters or contents
  138. inline void colorsHaveChanged() { m_vboManager.updateFlags |= vboSet::UPDATE_COLORS; }
  139. //! Notify a modification of normals display parameters or contents
  140. inline void normalsHaveChanged() { m_vboManager.updateFlags |= vboSet::UPDATE_NORMALS; decompressNormals();}
  141. //! Notify a modification of points display parameters or contents
  142. inline void pointsHaveChanged() { m_vboManager.updateFlags |= vboSet::UPDATE_POINTS; }
  143. public: //features allocation/resize
  144. //! Reserves memory to store the points coordinates
  145. /** Before adding points to the cloud (with addPoint())
  146. be sure to reserve the necessary amount of memory
  147. with this method. If the number of new elements is
  148. smaller than the actual one, nothing will happen.
  149. \param _numberOfPoints number of points to reserve the memory for
  150. \return true if ok, false if there's not enough memory
  151. **/
  152. bool reserveThePointsTable(unsigned _numberOfPoints);
  153. //! Reserves memory to store the RGB colors
  154. /** Before adding colors to the cloud (with addColor())
  155. be sure to reserve the necessary amount of memory
  156. with this method. This method reserves memory for as
  157. many colors as the number of points in the cloud
  158. (effectively stored or reserved).
  159. \return true if ok, false if there's not enough memory
  160. **/
  161. bool reserveTheRGBTable();
  162. //! Resizes the RGB colors array
  163. /** If possible, the colors array is resized to fit exactly the number
  164. of points in the cloud (effectively stored or reserved). If the
  165. new size is inferior to the actual one, the last elements will be
  166. deleted. Otherwise, the array is filled with zeros (default behavior)
  167. or "white" colors (is fillWithWhite).
  168. \warning don't try to "add" any element on a resized array...
  169. \param fillWithWhite whether to fill new array elements with zeros (false) or white color (true)
  170. \return true if ok, false if there's not enough memory
  171. **/
  172. bool resizeTheRGBTable(bool fillWithWhite = false);
  173. //! Reserves memory to store the compressed normals
  174. /** Before adding normals to the cloud (with addNorm())
  175. be sure to reserve the necessary amount of memory
  176. with this method. This method reserves memory for as
  177. many normals as the number of points in the cloud
  178. (effectively stored or reserved).
  179. \return true if ok, false if there's not enough memory
  180. **/
  181. bool reserveTheNormsTable();
  182. //! Resizes the compressed normals array
  183. /** If possible, the normals array is resized to fit exactly the number
  184. of points in the cloud (effectively stored or reserved). If the
  185. new size is inferior to the actual one, the last elements will be
  186. deleted. Otherwise, the array is filled with blank elements.
  187. \warning don't try to "add" any element on a resized array...
  188. \return true if ok, false if there's not enough memory
  189. **/
  190. bool resizeTheNormsTable();
  191. //! Reserves memory for all the active features
  192. /** This method is meant to be called before increasing the cloud
  193. population. Only the already allocated features will be re-reserved.
  194. \return true if ok, false if there's not enough memory
  195. **/
  196. bool reserve(unsigned numberOfPoints) override;
  197. //! Resizes all the active features arrays
  198. /** This method is meant to be called after having increased the cloud
  199. population (if the final number of inserted point is lower than the
  200. reserved size). Otherwise, it fills all new elements with blank values.
  201. \return true if ok, false if there's not enough memory
  202. **/
  203. bool resize(unsigned numberOfPoints) override;
  204. //! Removes unused capacity
  205. inline void shrinkToFit() { if (size() < capacity()) resize(size()); }
  206. public: //scalar-fields management
  207. //! Returns the currently displayed scalar (or 0 if none)
  208. ccScalarField* getCurrentDisplayedScalarField() const;
  209. //! Returns the currently displayed scalar field index (or -1 if none)
  210. int getCurrentDisplayedScalarFieldIndex() const;
  211. //! Sets the currently displayed scalar field
  212. /** Warning: this scalar field will automatically be set as the OUTPUT one!
  213. **/
  214. void setCurrentDisplayedScalarField(int index);
  215. //inherited from base class
  216. void deleteScalarField(int index) override;
  217. void deleteAllScalarFields() override;
  218. int addScalarField(const std::string& uniqueName) override;
  219. //! Returns whether color scale should be displayed or not
  220. bool sfColorScaleShown() const;
  221. //! Sets whether color scale should be displayed or not
  222. void showSFColorsScale(bool state);
  223. public: //associated (scan) grid structure
  224. //! Grid structure
  225. struct QCC_DB_LIB_API Grid : public ccSerializableObject
  226. {
  227. //! Shared type
  228. using Shared = QSharedPointer<Grid>;
  229. //! Default constructor
  230. Grid();
  231. //! Copy constructor
  232. /** \warning May throw a bad_alloc exception
  233. **/
  234. Grid(const Grid& grid) = default;
  235. //! Inits the grid
  236. bool init(unsigned rowCount, unsigned colCount, bool withRGB = false);
  237. //! Sets an index at a given position inside the grid
  238. void setIndex(unsigned row, unsigned col, int index);
  239. //! Sets a color at a given position inside the grid
  240. void setColor(unsigned row, unsigned col, const ccColor::Rgb& rgb);
  241. //! Updates the min and max valid indexes
  242. void updateMinAndMaxValidIndexes();
  243. //! Converts the grid to an RGB image (needs colors)
  244. QImage toImage() const;
  245. //inherited from ccSerializableObject
  246. inline bool isSerializable() const override { return true; }
  247. bool toFile(QFile& out, short dataVersion) const override;
  248. bool fromFile(QFile& in, short dataVersion, int flags, LoadedIDMap& oldToNewIDMap) override;
  249. short minimumFileVersion() const override;
  250. //! Grid width
  251. unsigned w;
  252. //! Grid height
  253. unsigned h;
  254. //! Number of valid indexes
  255. unsigned validCount;
  256. //! Minimum valid index
  257. unsigned minValidIndex;
  258. //! Maximum valid index
  259. unsigned maxValidIndex;
  260. //! Grid indexes (size: w x h)
  261. std::vector<int> indexes;
  262. //! Grid colors (size: w x h, or 0 = no color)
  263. std::vector<ccColor::Rgb> colors;
  264. //! Sensor position (expressed relatively to the cloud points)
  265. ccGLMatrixd sensorPosition;
  266. };
  267. //! Returns the number of associated grids
  268. size_t gridCount() const { return m_grids.size(); }
  269. //! Returns an associated grid
  270. inline Grid::Shared& grid(size_t gridIndex) { return m_grids[gridIndex]; }
  271. //! Returns an associated grid (const version)
  272. inline const Grid::Shared& grid(size_t gridIndex) const { return m_grids[gridIndex]; }
  273. //! Adds an associated grid
  274. inline bool addGrid(Grid::Shared grid) { try{ m_grids.push_back(grid); } catch (const std::bad_alloc&) { return false; } return true; }
  275. //! Remove all associated grids
  276. inline void removeGrids() { m_grids.resize(0); }
  277. //! Meshes a scan grid
  278. /** \warning The mesh vertices will be this cloud instance!
  279. **/
  280. ccMesh* triangulateGrid(const Grid& grid, double minTriangleAngle_deg = 0.0) const;
  281. public: //normals computation/orientation
  282. //! Compute the normals with the associated grid structure(s)
  283. /** Can also orient the normals in the same run.
  284. **/
  285. bool computeNormalsWithGrids( double minTriangleAngle_deg = 1.0,
  286. ccProgressDialog* pDlg = nullptr );
  287. //! Orient the normals with the associated grid structure(s)
  288. bool orientNormalsWithGrids( ccProgressDialog* pDlg = nullptr );
  289. //! Normals are forced to point to O
  290. bool orientNormalsTowardViewPoint( CCVector3 & VP, ccProgressDialog* pDlg = nullptr);
  291. //! Compute the normals by approximating the local surface around each point
  292. bool computeNormalsWithOctree( CCCoreLib::LOCAL_MODEL_TYPES model,
  293. ccNormalVectors::Orientation preferredOrientation,
  294. PointCoordinateType defaultRadius,
  295. ccProgressDialog* pDlg = nullptr );
  296. //! Orient the normals with a Minimum Spanning Tree
  297. bool orientNormalsWithMST( unsigned kNN = 6,
  298. ccProgressDialog* pDlg = nullptr );
  299. //! Orient normals with Fast Marching
  300. bool orientNormalsWithFM( unsigned char level,
  301. ccProgressDialog* pDlg = nullptr);
  302. //! Toggle the drawing of normals as small lines
  303. void showNormalsAsLines(bool state);
  304. //! Are normals drawn as vectors?
  305. bool normalsAreDrawn() const;
  306. //! Set the length of the normals
  307. void setNormalLength(const float& value);
  308. //! Get the length of the normals
  309. const float& getNormalLength() {return m_normalLineParameters.length;}
  310. //! Colors of the normals when they are displayed
  311. enum NormalLineColors{
  312. YELLOW,
  313. RED,
  314. GREEN,
  315. BLUE,
  316. BLACK
  317. };
  318. //! Set the color of the normals
  319. void setNormalLineColor(int colorIdx);
  320. //! Get the color of the normals
  321. const int& getNormalLineColor() {return m_normalLineParameters.colorIdx;}
  322. //! Do the drawing of normals
  323. void drawNormalsAsLines(CC_DRAW_CONTEXT& context);
  324. //! Update the decompressed normals which are used by drawNormalsAsLines
  325. void decompressNormals();
  326. public: //waveform (e.g. from airborne scanners)
  327. //! Returns whether the cloud has associated Full WaveForm data
  328. bool hasFWF() const;
  329. //! Returns a proxy on a given waveform
  330. ccWaveformProxy waveformProxy(unsigned index) const;
  331. //! Waveform descriptors set
  332. using FWFDescriptorSet = QMap<uint8_t, WaveformDescriptor>;
  333. //! Waveform data container
  334. using FWFDataContainer = std::vector<uint8_t>;
  335. using SharedFWFDataContainer = QSharedPointer<const FWFDataContainer>;
  336. //! Gives access to the FWF descriptors
  337. FWFDescriptorSet& fwfDescriptors() { return m_fwfDescriptors; }
  338. //! Gives access to the FWF descriptors (const version)
  339. const FWFDescriptorSet& fwfDescriptors() const { return m_fwfDescriptors; }
  340. //! Gives access to the associated FWF data
  341. std::vector<ccWaveform>& waveforms() { return m_fwfWaveforms; }
  342. //! Gives access to the associated FWF data (const version)
  343. const std::vector<ccWaveform>& waveforms() const { return m_fwfWaveforms; }
  344. //! Reserves the FWF table
  345. bool reserveTheFWFTable();
  346. //! Resizes the FWF table
  347. bool resizeTheFWFTable();
  348. //! Gives access to the associated FWF data container
  349. SharedFWFDataContainer& fwfData() { return m_fwfData; }
  350. //! Gives access to the associated FWF data container (const version)
  351. const SharedFWFDataContainer& fwfData() const { return m_fwfData; }
  352. //! Compresses the associated FWF data container
  353. /** As the container is shared, the compressed version will be potentially added to the memory
  354. resulting in a decrease of the available memory...
  355. **/
  356. bool compressFWFData();
  357. //! Computes the maximum amplitude of all associated waveforms
  358. bool computeFWFAmplitude(double& minVal, double& maxVal, ccProgressDialog* pDlg = nullptr) const;
  359. //! Clears all associated FWF data
  360. void clearFWFData();
  361. public: //other methods
  362. //! Returns the cloud gravity center
  363. /** \return gravity center
  364. **/
  365. CCVector3 computeGravityCenter();
  366. //inherited from base class
  367. void invalidateBoundingBox() override;
  368. //inherited from ccHObject
  369. void getDrawingParameters(glDrawParams& params) const override;
  370. //inherited from ccDrawableObject
  371. bool hasColors() const override;
  372. bool hasNormals() const override;
  373. bool hasScalarFields() const override;
  374. bool hasDisplayedScalarField() const override;
  375. void removeFromDisplay(const ccGenericGLDisplay* win) override; //for proper VBO release
  376. void setDisplay(ccGenericGLDisplay* win) override;
  377. //inherited from CCCoreLib::GenericCloud
  378. unsigned char testVisibility(const CCVector3& P) const override;
  379. //inherited from CCCoreLib::GenericIndexedCloud
  380. bool normalsAvailable() const override { return hasNormals(); }
  381. const CCVector3* getNormal(unsigned pointIndex) const override; //equivalent to getPointNormal, but for CCCoreLib
  382. //inherited from ccGenericPointCloud
  383. const ccColor::Rgb* geScalarValueColor(ScalarType d) const override;
  384. const ccColor::Rgb* getPointScalarValueColor(unsigned pointIndex) const override;
  385. ScalarType getPointDisplayedDistance(unsigned pointIndex) const override;
  386. const ccColor::Rgba& getPointColor(unsigned pointIndex) const override;
  387. const CompressedNormType& getPointNormalIndex(unsigned pointIndex) const override;
  388. const CCVector3& getPointNormal(unsigned pointIndex) const override;
  389. CCCoreLib::ReferenceCloud* crop(const ccBBox& box, bool inside = true) override;
  390. void scale(PointCoordinateType fx, PointCoordinateType fy, PointCoordinateType fz, CCVector3 center = CCVector3(0,0,0)) override;
  391. /** \warning if removeSelectedPoints is true, any attached octree will be deleted, as well as the visibility table. **/
  392. ccGenericPointCloud* createNewCloudFromVisibilitySelection( bool removeSelectedPoints = false,
  393. VisibilityTableType* visTable = nullptr,
  394. std::vector<int>* newIndexesOfRemainingPoints = nullptr,
  395. bool silent = false,
  396. CCCoreLib::ReferenceCloud* selection = nullptr) override;
  397. bool removeVisiblePoints(VisibilityTableType* visTable = nullptr, std::vector<int>* newIndexes = nullptr) override;
  398. void applyRigidTransformation(const ccGLMatrix& trans) override;
  399. inline void refreshBB() override { invalidateBoundingBox(); }
  400. //! Sets whether visibility check is enabled or not (e.g. during distances computation)
  401. /** See ccPointCloud::testVisibility.
  402. **/
  403. inline void enableVisibilityCheck(bool state) { m_visibilityCheckEnabled = state; }
  404. //! Returns whether the mesh as an associated sensor or not
  405. bool hasSensor() const;
  406. //! Comptes the closest point of this cloud relatively to another cloud
  407. /** The output (reference) clouds will have as many points as this cloud
  408. (with the indexes pointing on the closest point in the other cloud)
  409. **/
  410. QSharedPointer<CCCoreLib::ReferenceCloud> computeCPSet( ccGenericPointCloud& otherCloud,
  411. CCCoreLib::GenericProgressCallback* progressCb = nullptr,
  412. unsigned char octreeLevel = 0);
  413. //! Interpolate colors from another cloud (nearest neighbor only)
  414. bool interpolateColorsFrom( ccGenericPointCloud* cloud,
  415. CCCoreLib::GenericProgressCallback* progressCb = nullptr,
  416. unsigned char octreeLevel = 0);
  417. //! Sets a particular point color
  418. /** \warning colors must be enabled.
  419. **/
  420. void setPointColor(unsigned pointIndex, const ccColor::Rgba& col);
  421. //! Sets a particular point color
  422. /** \warning colors must be enabled.
  423. **/
  424. inline void setPointColor(unsigned pointIndex, const ccColor::Rgb& col) { setPointColor(pointIndex, ccColor::Rgba(col, ccColor::MAX)); }
  425. //! Sets a particular point compressed normal
  426. /** \warning normals must be enabled.
  427. **/
  428. void setPointNormalIndex(unsigned pointIndex, CompressedNormType norm);
  429. //! Sets a particular point normal (shortcut)
  430. /** \warning normals must be enabled.
  431. Normal is automatically compressed before storage.
  432. **/
  433. void setPointNormal(unsigned pointIndex, const CCVector3& N);
  434. //! Pushes a compressed normal vector
  435. /** \param index compressed normal vector
  436. **/
  437. void addNormIndex(CompressedNormType index);
  438. //! Pushes a normal vector on stack (shortcut)
  439. /** \param N normal vector
  440. **/
  441. void addNorm(const CCVector3& N);
  442. //! Adds a normal vector to the one at a specific index
  443. /** The resulting sum is automatically normalized and compressed.
  444. \param N normal vector to add (size: 3)
  445. \param index normal index to modify
  446. **/
  447. void addNormAtIndex(const PointCoordinateType* N, unsigned index);
  448. //! Sets the (compressed) normals table
  449. void setNormsTable(NormsIndexesTableType* norms);
  450. //! Converts normals to RGB colors
  451. /** See ccNormalVectors::ConvertNormalToRGB
  452. \return success
  453. **/
  454. bool convertNormalToRGB();
  455. //! Converts normals to two scalar fields: 'dip' and 'dip direction'
  456. /** One input scalar field may be empty if the corresponding value is not required
  457. \param[out] dipSF dip values
  458. \param[out] dipDirSF dip direction values
  459. \return success
  460. **/
  461. bool convertNormalToDipDirSFs(ccScalarField* dipSF, ccScalarField* dipDirSF);
  462. //! Pushes an RGBA color on stack
  463. /** \param C RGBA color
  464. **/
  465. void addColor(const ccColor::Rgba& C);
  466. //! Pushes an RGB color on stack
  467. /** Will be converted to an RGBA color automatically.
  468. \param C RGB color
  469. **/
  470. inline void addColor(const ccColor::Rgb& C) { addColor(ccColor::Rgba(C, ccColor::MAX)); }
  471. //! Pushes an RGB color on stack (shortcut)
  472. /** \param r red component
  473. \param g green component
  474. \param b blue component
  475. \param a alpha component
  476. **/
  477. inline void addColor(ColorCompType r, ColorCompType g, ColorCompType b, ColorCompType a = ccColor::MAX) { addColor(ccColor::Rgba(r, g, b, a)); }
  478. //! Pushes a grey color on stack (shortcut)
  479. /** Shortcut: color is converted to RGB(g, g, g)
  480. \param g grey component
  481. **/
  482. inline void addGreyColor(ColorCompType g) { addColor(ccColor::Rgba(g, g, g, ccColor::MAX)); }
  483. //! Converts RGB to grey scale colors
  484. /** \return success
  485. **/
  486. bool convertRGBToGreyScale();
  487. //! Multiplies all color components of all points by coefficients
  488. /** If the cloud has no color, all points are considered white and
  489. the color array is automatically allocated.
  490. \param r red component
  491. \param g green component
  492. \param b blue component
  493. \param a alpha component
  494. \return success
  495. **/
  496. bool colorize(float r, float g, float b, float a = 1.0f);
  497. enum RGB_FILTER_TYPES
  498. {
  499. NONE,
  500. BILATERAL,
  501. GAUSSIAN,
  502. MEAN,
  503. MEDIAN
  504. };
  505. struct RgbFilterOptions
  506. {
  507. bool applyToSFduringRGB = false;
  508. RGB_FILTER_TYPES filterType = RGB_FILTER_TYPES::NONE;
  509. unsigned char burntOutColorThreshold = 0;
  510. bool commandLine = false;
  511. double sigmaSF = -1;
  512. double spatialSigma = -1;
  513. bool blendGrayscale = false;
  514. unsigned char blendGrayscaleThreshold = 0;
  515. double blendGrayscalePercent = 0.5;
  516. };
  517. //! Applies a spatial Gaussian filter on RGB colors
  518. /** The "amplitutde" of the Gaussian filter must be specified (sigma).
  519. As 99% of the Gaussian distribution is between -3*sigma and +3*sigma around the mean value,
  520. this filter will only look for neighbors within a sphere of radius 3*sigma.
  521. One can also use the filter as a Bilateral filter. In this case the weights are computed considering the
  522. difference of the neighbors SF values with the current point SF value (also following a Gaussian distribution).
  523. Warning: this method assumes the output scalar field is set.
  524. \param sigma filter variance
  525. \param sigmaRGB if strictly positive, the variance for the Bilateral filter
  526. \param applyToSF if true, it will apply filter to the displayed scalar field as well
  527. \param burntOutColorThreshold if >0 color values which are outside of the [threshold:255-threshold] range will be filtered out
  528. \param progressCb the client application can get some notification of the process progress through this callback mechanism (see GenericProgressCallback)
  529. \return success
  530. **/
  531. bool applyFilterToRGB( PointCoordinateType sigma,
  532. PointCoordinateType sigmaSF,
  533. RgbFilterOptions filterParams,
  534. CCCoreLib::GenericProgressCallback* progressCb = nullptr);
  535. //! Assigns color to points proportionally to their 'height'
  536. /** Height is defined wrt to the specified dimension (heightDim).
  537. Color array is automatically allocated if necessary.
  538. \param heightDim ramp dimension (0:X, 1:Y, 2:Z)
  539. \param colorScale color scale to use
  540. \return success
  541. **/
  542. bool setRGBColorByHeight(unsigned char heightDim, ccColorScale::Shared colorScale);
  543. //! Assigns color to points by 'banding'
  544. /** Banding is performed along the specified dimension
  545. Color array is automatically allocated if necessary.
  546. \param dim banding dimension (0:X, 1:Y, 2:Z)
  547. \param freq banding frequency
  548. \return success
  549. **/
  550. bool setRGBColorByBanding(unsigned char dim, double freq);
  551. //! Converts current scalar field (values & display parameters) to RGB colors
  552. /** \return success
  553. **/
  554. bool convertCurrentScalarFieldToColors(bool mixWithExistingColor = false);
  555. //! Set a unique color for the whole cloud (shortcut)
  556. /** Color array is automatically allocated if necessary.
  557. \param r red component
  558. \param g green component
  559. \param b blue component
  560. \param a alpha component
  561. \return success
  562. **/
  563. inline bool setColor(ColorCompType r, ColorCompType g, ColorCompType b, ColorCompType a = ccColor::MAX) { return setColor(ccColor::Rgba(r, g, b, a)); }
  564. //! Set a unique color for the whole cloud (RGB version)
  565. /** Color array is automatically allocated if necessary.
  566. \param col RGB color
  567. \return success
  568. **/
  569. inline bool setColor(const ccColor::Rgb& col) { return setColor(ccColor::Rgba(col, ccColor::MAX)); }
  570. //! Set a unique color for the whole cloud (RGBA version)
  571. /** Color array is automatically allocated if necessary.
  572. \param col RGBA color
  573. \return success
  574. **/
  575. bool setColor(const ccColor::Rgba& col);
  576. //! Inverts normals (if any)
  577. void invertNormals();
  578. //! Translates cloud
  579. /** \param T translation vector
  580. **/
  581. void translate(const CCVector3& T);
  582. //! Filters out points whose scalar values falls into an interval
  583. /** Threshold values should be expressed relatively to the current displayed scalar field.
  584. \param minVal minimum value
  585. \param maxVal maximum value
  586. \param outside whether to select the points inside or outside of the specified interval
  587. \return resulting cloud (remaining points) or the cloud itself if all points fall inside the input range
  588. **/
  589. ccPointCloud* filterPointsByScalarValue(ScalarType minVal, ScalarType maxVal, bool outside = false);
  590. //! Hides points whose scalar values falls into an interval
  591. /** Values are taken from the current OUTPUT scalar field.
  592. \param minVal minimum value (below, points are hidden)
  593. \param maxVal maximum value (above, points are hidden)
  594. **/
  595. void hidePointsByScalarValue(ScalarType minVal, ScalarType maxVal);
  596. //! Unrolling mode (see ccPointCloud::unroll)
  597. enum UnrollMode { CYLINDER = 0, CONE_CONICAL = 1, CONE_CYLINDRICAL_FIXED_RADIUS = 2, CONE_CYLINDRICAL_ADAPTIVE_RADIUS = 3 };
  598. //! Base unrolling parameters
  599. struct UnrollBaseParams
  600. {
  601. PointCoordinateType radius = 0; //!< Unrolling cylinder radius (or cone base radius)
  602. CCVector3 axisDir; //!< Unrolling cylinder/cone axis direction
  603. };
  604. //! Cylinder unrolling parameters
  605. struct UnrollCylinderParams : public UnrollBaseParams
  606. {
  607. CCVector3 center; //!< A point belonging to the cylinder axis
  608. };
  609. //! Cone unrolling parameters
  610. struct UnrollConeParams : public UnrollBaseParams
  611. {
  612. CCVector3 apex; //!< Cone apex
  613. double coneAngle_deg = 0.0; //!< Cone aperture angle (in degrees)
  614. double spanRatio = 0.5; //!< Conical projection span ratio
  615. };
  616. //! Unrolls the cloud and its normals on a cylinder or a cone
  617. /** This method is redundant with the "developCloudOnCylinder" method of CCCoreLib,
  618. apart that it can also handle the cloud normals.
  619. \param mode unrolling mode
  620. \param params unrolling parameters (must match the unrolling mode)
  621. \param exportDeviationSF to export the deviations from the ideal shape as a scalar field
  622. \param startAngle_deg start angle (in degrees) - 0 corresponds to +X (east)
  623. \param stopAngle_deg stop angle (in degrees)
  624. \param arbitraryOutputCS whether the output cloud should be exported in an arbitrary coordinate system or not
  625. \param progressCb for progress notification
  626. \return the unrolled point cloud
  627. **/
  628. ccPointCloud* unroll( UnrollMode mode,
  629. UnrollBaseParams* params,
  630. bool exportDeviationSF = false,
  631. double startAngle_deg = 0.0,
  632. double stopAngle_deg = 360.0,
  633. bool arbitraryOutputCS = false,
  634. CCCoreLib::GenericProgressCallback* progressCb = nullptr) const;
  635. //! Adds associated SF color ramp info to current GL context
  636. void addColorRampInfo(CC_DRAW_CONTEXT& context);
  637. //! Adds an existing scalar field to this cloud
  638. /** Warning: the cloud takes ownership of it!
  639. \param sf existing scalar field
  640. \return index of added scalar field (or -1 if an error occurred)
  641. **/
  642. int addScalarField(ccScalarField* sf);
  643. //! Returns pointer on RGBA colors table
  644. RGBAColorsTableType* rgbaColors() const { return m_rgbaColors; }
  645. //! Returns pointer on compressed normals indexes table
  646. NormsIndexesTableType* normals() const { return m_normals; }
  647. //! Crops the cloud inside (or outside) a 2D polyline
  648. /** \warning Always returns a selection (potentially empty) if successful.
  649. \param poly cropping polyline
  650. \param orthoDim dimension orthogonal to the plane in which the segmentation should occur (X=0, Y=1, Z=2)
  651. \param inside whether selected points are inside or outside the polyline
  652. \return points falling inside (or outside) as a selection
  653. **/
  654. CCCoreLib::ReferenceCloud* crop2D(const ccPolyline* poly, unsigned char orthoDim, bool inside = true);
  655. //! Appends a cloud to this one
  656. /** Same as the += operator with pointCountBefore == size()
  657. \param cloud cloud to be added
  658. \param pointCountBefore the number of points previously contained in this cloud
  659. \param ignoreChildren whether to copy input cloud's children or not
  660. \param recomputeMinAndMax whether to compute min and max of scalar fields after append or not
  661. \return the resulting point cloud
  662. **/
  663. const ccPointCloud& append(ccPointCloud* cloud, unsigned pointCountBefore, bool ignoreChildren = false, bool recomputeMinAndMax = true);
  664. //! Enhances the RGB colors with the current scalar field (assuming it's intensities)
  665. bool enhanceRGBWithIntensitySF(int sfIdx, bool useCustomIntensityRange = false, double minI = 0.0, double maxI = 1.0);
  666. //! Exports the specified coordinate dimension(s) to scalar field(s)
  667. bool exportCoordToSF(bool exportDims[3]);
  668. //! Sets coordinate(s) from a scalar field
  669. bool setCoordFromSF(bool importDims[3], CCCoreLib::ScalarField* sf, PointCoordinateType defaultValueForNaN);
  670. //! Exports the specified normal dimension(s) to scalar field(s)
  671. bool exportNormalToSF(bool exportDims[3]);
  672. //! Release VBOs
  673. void releaseVBOs();
  674. //! Returns the VBOs size (if any)
  675. size_t vboSize() const;
  676. //! Removes the duplicate points and return the corresponding cloud (if any, or the same cloud if there's no duplicate point)
  677. ccPointCloud* removeDuplicatePoints(double minDistanceBetweenPoints, ccProgressDialog* pDlg = nullptr);
  678. //! Shift the points of a given quantity along their normals
  679. bool shiftPointsAlongNormals(PointCoordinateType shift);
  680. //! Set the path for shaders
  681. static void SetShaderPath(const QString &path);
  682. //! Release shaders (if any)
  683. /** Must be called before the OpenGL context is released.
  684. **/
  685. static void ReleaseShaders();
  686. protected:
  687. //inherited from ccHObject
  688. void drawMeOnly(CC_DRAW_CONTEXT& context) override;
  689. void applyGLTransformation(const ccGLMatrix& trans) override;
  690. bool toFile_MeOnly(QFile& out, short dataVersion) const override;
  691. bool fromFile_MeOnly(QFile& in, short dataVersion, int flags, LoadedIDMap& oldToNewIDMap) override;
  692. short minimumFileVersion_MeOnly() const override;
  693. void notifyGeometryUpdate() override;
  694. //inherited from PointCloud
  695. /** \warning Doesn't handle scan grids!
  696. **/
  697. void swapPoints(unsigned firstIndex, unsigned secondIndex) override;
  698. protected: // variable members
  699. //! Colors
  700. RGBAColorsTableType* m_rgbaColors;
  701. //! Normals (compressed)
  702. NormsIndexesTableType* m_normals;
  703. //! Used for drawing normals if needed
  704. std::vector<CCVector3> m_decompressedNormals;
  705. //! Specifies whether current scalar field color scale should be displayed or not
  706. bool m_sfColorScaleDisplayed;
  707. //! Currently displayed scalar field
  708. ccScalarField* m_currentDisplayedScalarField;
  709. //! Currently displayed scalar field index
  710. int m_currentDisplayedScalarFieldIndex;
  711. //! Associated grid structure
  712. std::vector<Grid::Shared> m_grids;
  713. //! Whether visibility check is available or not (during comparison)
  714. /** See ccPointCloud::testVisibility
  715. **/
  716. bool m_visibilityCheckEnabled;
  717. protected: // VBO
  718. //! Init/updates VBOs
  719. bool updateVBOs(const CC_DRAW_CONTEXT& context, const glDrawParams& glParams);
  720. class VBO : public QGLBuffer
  721. {
  722. public:
  723. int rgbShift;
  724. int normalShift;
  725. //! Inits the VBO
  726. /** \return the number of allocated bytes (or -1 if an error occurred)
  727. **/
  728. int init(int count, bool withColors, bool withNormals, bool* reallocated = nullptr);
  729. VBO()
  730. : QGLBuffer(QGLBuffer::VertexBuffer)
  731. , rgbShift(0)
  732. , normalShift(0)
  733. {}
  734. };
  735. //! VBO set
  736. struct vboSet
  737. {
  738. //! States of the VBO(s)
  739. enum STATES { NEW, INITIALIZED, FAILED };
  740. //! Update flags
  741. enum UPDATE_FLAGS {
  742. UPDATE_POINTS = 1,
  743. UPDATE_COLORS = 2,
  744. UPDATE_NORMALS = 4,
  745. UPDATE_ALL = UPDATE_POINTS | UPDATE_COLORS | UPDATE_NORMALS
  746. };
  747. vboSet()
  748. : hasColors(false)
  749. , colorIsSF(false)
  750. , sourceSF(nullptr)
  751. , hasNormals(false)
  752. , totalMemSizeBytes(0)
  753. , updateFlags(0)
  754. , state(NEW)
  755. {}
  756. std::vector<VBO*> vbos;
  757. bool hasColors;
  758. bool colorIsSF;
  759. ccScalarField* sourceSF;
  760. bool hasNormals;
  761. size_t totalMemSizeBytes;
  762. int updateFlags;
  763. //! Current state
  764. STATES state;
  765. };
  766. //! Set of VBOs attached to this cloud
  767. vboSet m_vboManager;
  768. //per-block data transfer to the GPU (VBO or standard mode)
  769. void glChunkVertexPointer(const CC_DRAW_CONTEXT& context, size_t chunkIndex, unsigned decimStep, bool useVBOs);
  770. void glChunkColorPointer (const CC_DRAW_CONTEXT& context, size_t chunkIndex, unsigned decimStep, bool useVBOs);
  771. void glChunkSFPointer (const CC_DRAW_CONTEXT& context, size_t chunkIndex, unsigned decimStep, bool useVBOs);
  772. void glChunkNormalPointer(const CC_DRAW_CONTEXT& context, size_t chunkIndex, unsigned decimStep, bool useVBOs);
  773. public: //Level of Detail (LOD)
  774. //! Initializes the LOD structure
  775. /** \return success
  776. **/
  777. bool initLOD();
  778. //! Clears the LOD structure
  779. void clearLOD();
  780. protected: //Level of Detail (LOD)
  781. //! L.O.D. structure
  782. ccPointCloudLOD* m_lod;
  783. protected: //waveform (e.g. from airborne scanners)
  784. //! General waveform descriptors
  785. FWFDescriptorSet m_fwfDescriptors;
  786. //! Per-point waveform accessors
  787. std::vector<ccWaveform> m_fwfWaveforms;
  788. //! Waveforms raw data storage
  789. SharedFWFDataContainer m_fwfData;
  790. bool m_normalsDrawnAsLines;
  791. struct NormalLineParameters
  792. {
  793. float length = 1.0f;
  794. ccColor::Rgba color = ccColor::yellow;
  795. int colorIdx = YELLOW;
  796. } m_normalLineParameters;
  797. };