ccHObject.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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_HIERARCHY_OBJECT_HEADER
  18. #define CC_HIERARCHY_OBJECT_HEADER
  19. //Local
  20. #include "ccObject.h"
  21. #include "ccBBox.h"
  22. class QIcon;
  23. //! Hierarchical CloudCompare Object
  24. class QCC_DB_LIB_API ccHObject : public ccObject, public ccDrawableObject
  25. {
  26. public: //construction
  27. //! Default constructor
  28. /** \param name object name (optional)
  29. \param uniqueID unique ID (handle with care)
  30. **/
  31. ccHObject(const QString& name = QString(), unsigned uniqueID = ccUniqueIDGenerator::InvalidUniqueID);
  32. //! Copy constructor
  33. ccHObject(const ccHObject& object);
  34. //! Default destructor
  35. ~ccHObject() override;
  36. //! Static factory
  37. /** \warning Objects depending on other structures (such as meshes
  38. or polylines that should be linked with point clouds playing the
  39. role of vertices) are returned 'naked'.
  40. \param objectType object type
  41. \param name object name (optional)
  42. \return instantiated object (if type is valid) or 0
  43. **/
  44. static ccHObject* New(CC_CLASS_ENUM objectType, const char* name = nullptr);
  45. //! Static factory (version to be used by external plugin factories)
  46. /** Two strings are used as keys, one for the plugin name and one for the class name.
  47. Those strings will typically be saved as metadata of a custom object
  48. **/
  49. static ccHObject* New(const QString& pluginId, const QString& classId, const char* name = nullptr);
  50. public: //base members access
  51. //! Returns class ID
  52. /** \return class unique ID
  53. **/
  54. inline CC_CLASS_ENUM getClassID() const override { return CC_TYPES::HIERARCHY_OBJECT; }
  55. //! Returns whether the instance is a group
  56. inline bool isGroup() const { return getClassID() == static_cast<CC_CLASS_ENUM>(CC_TYPES::HIERARCHY_OBJECT); }
  57. //! Returns parent object
  58. /** \return parent object (nullptr if no parent)
  59. **/
  60. inline ccHObject* getParent() const { return m_parent; }
  61. //! Returns the icon associated to this entity
  62. /** ccDBRoot will call this method: if an invalid icon is returned
  63. the default icon for that type will be used instead.
  64. \return invalid icon by default (to be re-implemented by child class)
  65. **/
  66. virtual QIcon getIcon() const;
  67. public: //dependencies management
  68. //! Dependency flags
  69. enum DEPENDENCY_FLAGS { DP_NONE = 0, /**< no dependency **/
  70. DP_NOTIFY_OTHER_ON_DELETE = 1, /**< notify 'other' when deleted (will call ccHObject::onDeletionOf) **/
  71. DP_NOTIFY_OTHER_ON_UPDATE = 2, /**< notify 'other' when its geometry is modified (will call ccHObject::onUpdateOf) **/
  72. //DP_NOTIFY_XXX = 4,
  73. DP_DELETE_OTHER = 8, /**< delete 'other' before deleting itself **/
  74. DP_PARENT_OF_OTHER = 24, /**< same as DP_DELETE_OTHER + declares itself as parent of 'other' **/
  75. };
  76. //! Adds a new dependence (additive or not)
  77. /** \param otherObject other object
  78. \param flags dependency flags (see DEPENDENCY_FLAGS)
  79. \param additive whether we should 'add' the flag(s) if there's already a dependence with the other object or not
  80. **/
  81. void addDependency(ccHObject* otherObject, int flags, bool additive = true);
  82. //! Returns the dependency flags with a given object
  83. /** \param otherObject other object
  84. **/
  85. int getDependencyFlagsWith(const ccHObject* otherObject) const;
  86. //! Removes any dependency flags with a given object
  87. /** \param otherObject other object
  88. **/
  89. void removeDependencyWith(ccHObject* otherObject);
  90. //! Removes a given dependency flag
  91. /** \param otherObject other object
  92. \param flag dependency flag to remove (see DEPENDENCY_FLAGS)
  93. **/
  94. void removeDependencyFlag(ccHObject* otherObject, DEPENDENCY_FLAGS flag);
  95. public: //children management
  96. //! Adds a child
  97. /** \warning by default (i.e. with the DP_PARENT_OF_OTHER flag) the child's parent
  98. will be automatically replaced by this instance. Moreover the child will be deleted
  99. \param child child instance
  100. \param dependencyFlags dependency flags
  101. \param insertIndex insertion index (if <0, child is simply appended to the children list)
  102. \return success
  103. **/
  104. virtual bool addChild(ccHObject* child, int dependencyFlags = DP_PARENT_OF_OTHER, int insertIndex = -1);
  105. //! Returns the number of children
  106. /** \return children number
  107. **/
  108. inline unsigned getChildrenNumber() const { return static_cast<unsigned>(m_children.size()); }
  109. //! Returns the total number of children under this object recursively
  110. /** \return Number of children
  111. **/
  112. unsigned int getChildCountRecursive() const;
  113. //! Returns the ith child
  114. /** \param childPos child position
  115. \return child object (or nullptr if wrong position)
  116. **/
  117. inline ccHObject* getChild(unsigned childPos) const { return (childPos < getChildrenNumber() ? m_children[childPos] : nullptr); }
  118. //! Finds an entity in this object hierarchy
  119. /** \param uniqueID child unique ID
  120. \return child (or nullptr if not found)
  121. **/
  122. ccHObject* find(unsigned uniqueID) const;
  123. //! Standard instances container (for children, etc.)
  124. using Container = std::vector<ccHObject *>;
  125. //! Shared pointer
  126. using Shared = QSharedPointer<ccHObject>;
  127. //! Shared instances container (for children, etc.)
  128. using SharedContainer = std::vector<Shared>;
  129. //! Collects the children corresponding to a certain pattern
  130. /** \param filteredChildren result container
  131. \param recursive specifies if the search should be recursive
  132. \param filter pattern for children selection
  133. \param strict whether the search is strict on the type (i.e 'isA') or not (i.e. 'isKindOf')
  134. \param inDisplay [optional] display in which the children are displayed
  135. \return number of collected children
  136. **/
  137. unsigned filterChildren(Container& filteredChildren,
  138. bool recursive = false,
  139. CC_CLASS_ENUM filter = CC_TYPES::OBJECT,
  140. bool strict = false,
  141. ccGenericGLDisplay* inDisplay = nullptr) const;
  142. //! Detaches a specific child
  143. /** This method does not delete the child.
  144. Removes any dependency between the flag and this object
  145. **/
  146. void detachChild(ccHObject* child);
  147. //! Detaches all children
  148. void detachAllChildren();
  149. //! Removes a specific child
  150. /** \warning This method may delete the child if the DP_PARENT_OF_OTHER
  151. dependency flag is set for this child (use detachChild if you
  152. want to avoid deletion).
  153. **/
  154. void removeChild(ccHObject* child);
  155. //! Removes a specific child given its index
  156. /** \warning This method may delete the child if the DP_PARENT_OF_OTHER
  157. dependency flag is set for this child (use detachChild if you
  158. want to avoid deletion).
  159. **/
  160. void removeChild(int pos);
  161. //! Removes all children
  162. void removeAllChildren();
  163. //! Returns child index
  164. int getChildIndex(const ccHObject* aChild) const;
  165. //! Swaps two children
  166. void swapChildren(unsigned firstChildIndex, unsigned secondChildIndex);
  167. //! Returns index relatively to its parent or -1 if no parent
  168. int getIndex() const;
  169. //! Transfer a given child to another parent
  170. void transferChild(ccHObject* child, ccHObject& newParent);
  171. //! Transfer all children to another parent
  172. void transferChildren(ccHObject& newParent, bool forceFatherDependent = false);
  173. //! Shortcut: returns first child
  174. inline ccHObject* getFirstChild() const { return (m_children.empty() ? nullptr : m_children.front()); }
  175. //! Shortcut: returns last child
  176. inline ccHObject* getLastChild() const { return (m_children.empty() ? nullptr : m_children.back()); }
  177. //! Returns true if the current object is an ancestor of the specified one
  178. bool isAncestorOf(const ccHObject *anObject) const;
  179. public: //bounding-box
  180. //! Returns the entity's own bounding-box (with local/shifted coordinates)
  181. /** Children bounding-boxes are ignored.
  182. \param withGLFeatures whether to take into account display-only elements (if any)
  183. \return bounding-box
  184. **/
  185. virtual ccBBox getOwnBB(bool withGLFeatures = false);
  186. //! Returns the local bounding-box of this entity and it's children
  187. /** \param withGLFeatures whether to take into account display-only elements (if any)
  188. \param onlyEnabledChildren only consider the 'enabled' children
  189. \return bounding-box
  190. **/
  191. virtual ccBBox getBB_recursive(bool withGLFeatures = false, bool onlyEnabledChildren = true);
  192. //! Global (non-shifted) bounding-box
  193. using GlobalBoundingBox = CCCoreLib::BoundingBoxTpl<double>;
  194. //! Returns the entity's own global bounding-box (with global/non-shifted coordinates - if relevant)
  195. /** Children bounding-boxes are ignored.
  196. May differ from the (local) bounding-box if the entity is shifted
  197. \param withGLFeatures whether to take into account display-only elements (if any)
  198. \return global bounding-box
  199. **/
  200. virtual GlobalBoundingBox getOwnGlobalBB(bool withGLFeatures = false);
  201. //! Returns the entity's own global bounding-box (with global/non-shifted coordinates - if relevant)
  202. /** Children bounding-boxes are ignored.
  203. By default this method returns the local bounding-box!
  204. But it may differ from the (local) bounding-box if the entity is shifted.
  205. \param[out] minCorner min global bounding-box corner
  206. \param[out] maxCorner max global bounding-box corner
  207. \return whether the bounding box is valid or not
  208. **/
  209. virtual bool getOwnGlobalBB(CCVector3d& minCorner, CCVector3d& maxCorner);
  210. //! Returns the global bounding-box of this entity and it's children
  211. /** \param withGLFeatures whether to take into account display-only elements (if any)
  212. \param onlyEnabledChildren only consider the 'enabled' children
  213. \return bounding-box
  214. **/
  215. virtual GlobalBoundingBox getGlobalBB_recursive(bool withGLFeatures = false, bool onlyEnabledChildren = true);
  216. //! Returns the bounding-box of this entity and it's children WHEN DISPLAYED
  217. /** Children's GL transformation is taken into account (if enabled).
  218. \param relative whether the bounding-box is relative (i.e. in the entity's local coordinate system) or absolute (in which case the parent's GL transformation will be taken into account)
  219. \param display if not null, this method will return the bounding-box of this entity (and its children) in the specified 3D view (i.e. potentially not visible)
  220. \return bounding-box
  221. **/
  222. virtual ccBBox getDisplayBB_recursive(bool relative, const ccGenericGLDisplay* display = nullptr);
  223. //! Returns best-fit bounding-box (if available)
  224. /** \warning Only suitable for leaf objects (i.e. without children)
  225. Therefore children bboxes are always ignored.
  226. \warning This method is not supported by all entities!
  227. (returns the axis-aligned bounding-box by default).
  228. \param[out] trans associated transformation (so that the bounding-box can be displayed in the right position!)
  229. \return fit bounding-box
  230. **/
  231. inline virtual ccBBox getOwnFitBB(ccGLMatrix& trans) { trans.toIdentity(); return getOwnBB(); }
  232. //! Draws the entity (and its children) bounding-box
  233. virtual void drawBB(CC_DRAW_CONTEXT& context, const ccColor::Rgb& col);
  234. public: //display
  235. //Inherited from ccDrawableObject
  236. void draw(CC_DRAW_CONTEXT& context) override;
  237. //! Returns the absolute transformation (i.e. the actual displayed GL transformation) of an entity
  238. /** \param[out] trans absolute transformation
  239. \return whether a GL transformation is actually enabled or not
  240. **/
  241. bool getAbsoluteGLTransformation(ccGLMatrix& trans) const;
  242. //! Returns whether the object is actually displayed (visible) or not
  243. virtual bool isDisplayed() const;
  244. //! Returns whether the object is actually displayed (visible) in a given display or not
  245. virtual bool isDisplayedIn(const ccGenericGLDisplay* display) const;
  246. //! Returns whether the object and all its ancestors are enabled
  247. virtual bool isBranchEnabled() const;
  248. /*** RECURSIVE CALL SCRIPTS ***/
  249. //0 parameter
  250. #define ccHObject_recursive_call0(baseName,recursiveName) \
  251. inline virtual void recursiveName() \
  252. { \
  253. baseName(); \
  254. for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) \
  255. (*it)->recursiveName(); \
  256. } \
  257. //1 parameter
  258. #define ccHObject_recursive_call1(baseName,param1Type,recursiveName) \
  259. inline virtual void recursiveName(param1Type p) \
  260. { \
  261. baseName(p); \
  262. for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) \
  263. (*it)->recursiveName(p); \
  264. } \
  265. //recursive equivalents of some of ccDrawableObject methods
  266. ccHObject_recursive_call1(setSelected, bool, setSelected_recursive)
  267. ccHObject_recursive_call1(setDisplay, ccGenericGLDisplay*, setDisplay_recursive)
  268. ccHObject_recursive_call1(removeFromDisplay, ccGenericGLDisplay*, removeFromDisplay_recursive)
  269. ccHObject_recursive_call0(prepareDisplayForRefresh, prepareDisplayForRefresh_recursive)
  270. ccHObject_recursive_call1(refreshDisplay, bool, refreshDisplay_recursive)
  271. ccHObject_recursive_call0(resetGLTransformationHistory, resetGLTransformationHistory_recursive)
  272. ccHObject_recursive_call0(toggleActivation, toggleActivation_recursive)
  273. ccHObject_recursive_call0(toggleVisibility, toggleVisibility_recursive)
  274. ccHObject_recursive_call0(toggleColors, toggleColors_recursive)
  275. ccHObject_recursive_call0(toggleNormals, toggleNormals_recursive)
  276. ccHObject_recursive_call0(toggleSF, toggleSF_recursive)
  277. ccHObject_recursive_call0(toggleShowName, toggleShowName_recursive)
  278. ccHObject_recursive_call0(toggleMaterials, toggleMaterials_recursive)
  279. //! Transfers the entity from one display to the other
  280. inline virtual void transferDisplay(ccGenericGLDisplay* oldDisplay, ccGenericGLDisplay* newDisplay)
  281. {
  282. if (getDisplay() == oldDisplay)
  283. {
  284. setDisplay(newDisplay);
  285. }
  286. for (auto child : m_children)
  287. {
  288. child->transferDisplay(oldDisplay, newDisplay);
  289. }
  290. }
  291. //! Returns the max 'unique ID' of this entity and its siblings
  292. unsigned findMaxUniqueID_recursive() const;
  293. //! Applies the active OpenGL transformation to the entity (recursive)
  294. /** The input ccGLMatrix should be left to 0, unless you want to apply
  295. a pre-transformation.
  296. \param trans a ccGLMatrix structure (reference to)
  297. **/
  298. void applyGLTransformation_recursive(const ccGLMatrix* trans = nullptr);
  299. //! Notifies all dependent entities that the geometry of this entity has changed
  300. virtual void notifyGeometryUpdate();
  301. //inherited from ccSerializableObject
  302. bool isSerializable() const override;
  303. bool toFile(QFile& out, short dataVersion) const override;
  304. bool fromFile(QFile& in, short dataVersion, int flags, LoadedIDMap& oldToNewIDMap) override;
  305. short minimumFileVersion() const override;
  306. //! Custom version of ccSerializableObject::fromFile
  307. /** This is used to load only the object's part of a stream (and not its children)
  308. \param in input file (already opened)
  309. \param dataVersion file version
  310. \param flags deserialization flags (see ccSerializableObject::DeserializationFlags)
  311. \param oldToNewIDMap map to convert old IDs to new ones
  312. \return success
  313. **/
  314. bool fromFileNoChildren(QFile& in, short dataVersion, int flags, LoadedIDMap& oldToNewIDMap);
  315. //! Returns whether object is shareable or not
  316. /** If object is father dependent and 'shared', it won't
  317. be deleted but 'released' instead.
  318. **/
  319. virtual inline bool isShareable() const { return false; }
  320. //! Behavior when selected
  321. enum SelectionBehavior { SELECTION_AA_BBOX,
  322. SELECTION_FIT_BBOX,
  323. SELECTION_IGNORED };
  324. //! Sets selection behavior (when displayed)
  325. /** \warning SELECTION_FIT_BBOX relies on the
  326. 'ccDrawableObject::getFitBB' method (which
  327. is not supported by all entities).
  328. **/
  329. virtual inline void setSelectionBehavior(SelectionBehavior mode) { m_selectionBehavior = mode; }
  330. //! Returns selection behavior
  331. virtual inline SelectionBehavior getSelectionBehavior() const { return m_selectionBehavior; }
  332. //! Returns the transformation 'history' matrix
  333. virtual inline const ccGLMatrix& getGLTransformationHistory() const { return m_glTransHistory; }
  334. //! Sets the transformation 'history' matrix (handle with care!)
  335. virtual inline void setGLTransformationHistory(const ccGLMatrix& mat) { m_glTransHistory = mat; }
  336. //! Resets the transformation 'history' matrix
  337. virtual inline void resetGLTransformationHistory() { m_glTransHistory.toIdentity(); }
  338. public:
  339. //! Pushes the current display state (overridden)
  340. bool pushDisplayState() override;
  341. //! Pops the last pushed display state (overridden)
  342. void popDisplayState(bool apply = true) override;
  343. protected:
  344. //! Sets parent object
  345. virtual inline void setParent(ccHObject* anObject) { m_parent = anObject; }
  346. //! Draws the entity only (not its children)
  347. virtual void drawMeOnly(CC_DRAW_CONTEXT& context) { /*does nothing by default*/ }
  348. //! Applies a GL transformation to the entity
  349. /** this = rotMat*(this-rotCenter)+(rotCenter+trans)
  350. \param trans a ccGLMatrix structure
  351. **/
  352. virtual void applyGLTransformation(const ccGLMatrix& trans);
  353. //! Save own object data
  354. /** Called by 'toFile' (recursive scheme)
  355. To be overloaded (but still called ;) by subclass.
  356. \param out output file
  357. \param dataVersion target file version
  358. **/
  359. virtual bool toFile_MeOnly(QFile& out, short dataVersion) const;
  360. //! Loads own object data
  361. /** Called by 'fromFile' (recursive scheme)
  362. To be overloaded (but still called ;) by subclass.
  363. \param in input file
  364. \param dataVersion file version
  365. \param flags deserialization flags (see ccSerializableObject::DeserializationFlags)
  366. \param oldToNewIDMap map to link old IDs with new IDs
  367. **/
  368. virtual bool fromFile_MeOnly(QFile& in, short dataVersion, int flags, LoadedIDMap& oldToNewIDMap);
  369. //! Returns the minimum file version required to save this instance
  370. /** To be overloaded (but still called ;) by subclass.
  371. **/
  372. virtual short minimumFileVersion_MeOnly() const;
  373. //! Draws the entity name in 3D
  374. /** Names is displayed at the center of the bounding box by default.
  375. **/
  376. virtual void drawNameIn3D(CC_DRAW_CONTEXT& context);
  377. //! This method is called when another object is deleted
  378. /** For internal use.
  379. **/
  380. virtual void onDeletionOf(const ccHObject* obj);
  381. //! This method is called when another object (geometry) is updated
  382. /** For internal use.
  383. **/
  384. virtual void onUpdateOf(ccHObject* obj) { /*does nothing by default*/ }
  385. //! Parent
  386. ccHObject* m_parent;
  387. //! Children
  388. Container m_children;
  389. //! Selection behavior
  390. SelectionBehavior m_selectionBehavior;
  391. //! Dependencies map
  392. /** First parameter: other object
  393. Second parameter: dependency flags (see DEPENDENCY_FLAGS)
  394. **/
  395. std::map<ccHObject*, int> m_dependencies;
  396. //! Cumulative GL transformation
  397. /** History of all the applied transformations since the creation of the object
  398. as a single transformation.
  399. **/
  400. ccGLMatrix m_glTransHistory;
  401. //! Flag to safely handle dependencies when the object is being deleted
  402. bool m_isDeleting;
  403. };
  404. /*** Helpers ***/
  405. //! Puts all entities inside a container in a group
  406. /** Automatically removes siblings so as to get a valid hierarchy object.
  407. \param origin origin container
  408. \param dest destination group
  409. \param dependencyFlags default dependency link for the children added to the group
  410. **/
  411. inline void ConvertToGroup(const ccHObject::Container& origin, ccHObject& dest, int dependencyFlags = ccHObject::DP_NONE)
  412. {
  413. size_t count = origin.size();
  414. for (size_t i = 0; i < count; ++i)
  415. {
  416. //we don't take objects that are siblings of others
  417. bool isSiblingOfAnotherOne = false;
  418. for (size_t j = 0; j < count; ++j)
  419. {
  420. if (i != j && origin[j]->isAncestorOf(origin[i]))
  421. {
  422. isSiblingOfAnotherOne = true;
  423. break;
  424. }
  425. }
  426. if (!isSiblingOfAnotherOne)
  427. {
  428. dest.addChild(origin[i], dependencyFlags);
  429. }
  430. }
  431. }
  432. #endif //CC_HIERARCHY_OBJECT_HEADER