File: ccHObject.h

package info (click to toggle)
cloudcompare 2.10.1-2
  • links: PTS
  • area: main
  • in suites: buster
  • size: 55,916 kB
  • sloc: cpp: 219,837; ansic: 29,944; makefile: 67; sh: 45
file content (494 lines) | stat: -rw-r--r-- 18,979 bytes parent folder | download | duplicates (2)
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
//##########################################################################
//#                                                                        #
//#                              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_HIERARCHY_OBJECT_HEADER
#define CC_HIERARCHY_OBJECT_HEADER

//Local
#include "ccObject.h"
#include "ccBBox.h"

class QIcon;

//! Hierarchical CloudCompare Object
class QCC_DB_LIB_API ccHObject : public ccObject, public ccDrawableObject
{
public: //construction

	//! Default constructor
	/** \param name object name (optional)
	**/
	ccHObject(QString name = QString());
	//! Copy constructor
	ccHObject(const ccHObject& object);

	//! Default destructor
	virtual ~ccHObject() override;

	//! Static factory
	/** Warning: objects depending on other structures (such as meshes 
		or polylines that should be linked with point clouds playing the
		role of vertices) are returned 'naked'.
		\param objectType object type
		\param name object name (optional)
		\return instantiated object (if type is valid) or 0
	**/
	static ccHObject* New(CC_CLASS_ENUM objectType, const char* name = nullptr);

	//! Static factory (version to be used by external plugin factories)
	/** Two strings are used as keys, one for the plugin name and one for the class name.
		Those strings will typically be saved as metadata of a custom object
	**/
	static ccHObject* New(const QString& pluginId, const QString& classId, const char* name = nullptr);

public: //base members access

	//! Returns class ID
	/** \return class unique ID
	**/
	inline CC_CLASS_ENUM getClassID() const override { return CC_TYPES::HIERARCHY_OBJECT; }

	//! Returns whether the instance is a group
	inline bool isGroup() const { return getClassID() == CC_TYPES::HIERARCHY_OBJECT; }

	//! Returns parent object
	/** \return parent object (nullptr if no parent)
	**/
	inline ccHObject* getParent() const { return m_parent; }

	//! Returns the icon associated to this entity
	/** ccDBRoot will call this method: if an invalid icon is returned
		the default icon for that type will be used instead.
		\return invalid icon by default (to be re-implemented by child class)
	**/
	virtual QIcon getIcon() const;
	
public: //dependencies management

	//! Dependency flags
	enum DEPENDENCY_FLAGS {	DP_NONE						= 0,	/**< no dependency **/
							DP_NOTIFY_OTHER_ON_DELETE	= 1,	/**< notify 'other' when deleted (will call ccHObject::onDeletionOf) **/
							DP_NOTIFY_OTHER_ON_UPDATE	= 2,	/**< notify 'other' when its geometry is modified (will call ccHObject::onUpdateOf) **/
							//DP_NOTIFY_XXX				= 4, 
							DP_DELETE_OTHER				= 8,	/**< delete 'other' before deleting itself **/
							DP_PARENT_OF_OTHER			= 24,	/**< same as DP_DELETE_OTHER + declares itself as parent of 'other' **/
	};

	//! Adds a new dependence (additive or not)
	/** \param otherObject other object
		\param flags dependency flags (see DEPENDENCY_FLAGS)
		\param additive whether we should 'add' the flag(s) if there's already a dependence with the other object or not
	**/
	void addDependency(ccHObject* otherObject, int flags, bool additive = true);

	//! Returns the dependency flags with a given object
	/** \param otherObject other object
	**/
	int getDependencyFlagsWith(const ccHObject* otherObject);

	//! Removes any dependency flags with a given object
	/** \param otherObject other object
	**/
	void removeDependencyWith(ccHObject* otherObject);

	//! Removes a given dependency flag
	/** \param otherObject other object
		\param flag dependency flag to remove (see DEPENDENCY_FLAGS)
	**/
	void removeDependencyFlag(ccHObject* otherObject, DEPENDENCY_FLAGS flag);

public: //children management

	//! Adds a child
	/** \warning by default (i.e. with the DP_PARENT_OF_OTHER flag) the child's parent
		will be automatically replaced by this instance. Moreover the child will be deleted

		\param child child instance
		\param dependencyFlags dependency flags
		\param insertIndex insertion index (if <0, child is simply appended to the children list)
		\return success
	**/
	virtual bool addChild(ccHObject* child, int dependencyFlags = DP_PARENT_OF_OTHER, int insertIndex = -1);

	//! Returns the number of children
	/** \return children number
	**/
	inline unsigned getChildrenNumber() const { return static_cast<unsigned>(m_children.size()); }
	
	//! Returns the total number of children under this object recursively
	/** \return Number of children
	**/
	unsigned int getChildCountRecursive() const;

	//! Returns the ith child
	/** \param childPos child position
		\return child object (or nullptr if wrong position)
	**/
	inline ccHObject* getChild(unsigned childPos) const { return (childPos < getChildrenNumber() ? m_children[childPos] : nullptr); }

	//! Finds an entity in this object hierarchy
	/** \param uniqueID child unique ID
		\return child (or nullptr if not found)
	**/
	ccHObject* find(unsigned uniqueID);

	//! Standard instances container (for children, etc.)
	using Container = std::vector<ccHObject *>;

	//! Shared pointer
	using Shared = QSharedPointer<ccHObject>;

	//! Shared instances container (for children, etc.)
	using SharedContainer = std::vector<Shared>;

	//! Collects the children corresponding to a certain pattern
	/** \param filteredChildren result container
		\param recursive specifies if the search should be recursive
		\param filter pattern for children selection
		\param strict whether the search is strict on the type (i.e 'isA') or not (i.e. 'isKindOf')
		\param inDisplay [optional] display in which the children are displayed
		\return number of collected children
	**/
	unsigned filterChildren(Container& filteredChildren,
							bool recursive = false,
							CC_CLASS_ENUM filter = CC_TYPES::OBJECT,
							bool strict = false,
							ccGenericGLDisplay* inDisplay = nullptr) const;

	//! Detaches a specific child
	/** This method does not delete the child.
		Removes any dependency between the flag and this object
	**/
	void detachChild(ccHObject* child);
	//! Removes a specific child
	/** \warning This method may delete the child if the DP_PARENT_OF_OTHER
		dependency flag is set for this child (use detachChild if you
		want to avoid deletion).
	**/
	//! Detaches all children
	void detatchAllChildren();

	void removeChild(ccHObject* child);
	//! Removes a specific child given its index
	/** \warning This method may delete the child if the DP_PARENT_OF_OTHER
		dependency flag is set for this child (use detachChild if you
		want to avoid deletion).
	**/
	void removeChild(int pos);
	//! Removes all children
	void removeAllChildren();
	//! Returns child index
	int getChildIndex(const ccHObject* aChild) const;
	//! Swaps two children
	void swapChildren(unsigned firstChildIndex, unsigned secondChildIndex);
	//! Returns index relatively to its parent or -1 if no parent
	int getIndex() const;

	//! Transfer a given child to another parent
	void transferChild(ccHObject* child, ccHObject& newParent);
	//! Transfer all children to another parent
	void transferChildren(ccHObject& newParent, bool forceFatherDependent = false);

	//! Shortcut: returns first child
	ccHObject* getFirstChild() const { return (m_children.empty() ? nullptr : m_children.front()); }
	//! Shortcut: returns last child
	ccHObject* getLastChild() const { return (m_children.empty() ? nullptr : m_children.back()); }

	//! Returns true if the current object is an ancestor of the specified one
	bool isAncestorOf(const ccHObject *anObject) const;

public: //bounding-box

	//! Returns the entity's own bounding-box
	/** Children bboxes are ignored.
		\param withGLFeatures whether to take into account display-only elements (if any)
		\return bounding-box
	**/
	virtual ccBBox getOwnBB(bool withGLFeatures = false);

	//! Returns the bounding-box of this entity and it's children
	/** \param withGLFeatures whether to take into account display-only elements (if any)
		\param onlyEnabledChildren only consider the 'enabled' children
		\return bounding-box
	**/
	virtual ccBBox getBB_recursive(bool withGLFeatures = false, bool onlyEnabledChildren = true);

	//! Returns the bounding-box of this entity and it's children WHEN DISPLAYED
	/** Children's GL transformation is taken into account (if enabled).
		\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)
		\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)
		\return bounding-box
	**/
	virtual ccBBox getDisplayBB_recursive(bool relative, const ccGenericGLDisplay* display = nullptr);

	//! Returns best-fit bounding-box (if available)
	/** \warning Only suitable for leaf objects (i.e. without children)
		Therefore children bboxes are always ignored.
		\warning This method is not supported by all entities!
		(returns the axis-aligned bounding-box by default).
		\param[out] trans associated transformation (so that the bounding-box can be displayed in the right position!)
		\return fit bounding-box
	**/
	inline virtual ccBBox getOwnFitBB(ccGLMatrix& trans) { trans.toIdentity(); return getOwnBB(); }

	//! Returns the entity's own global bounding-box
	/** Children bboxes are ignored.
		May differ from the (local) bounding-box if the entity is shifted
		\param[out] minCorner min global bounding-box corner
		\param[out] maxCorner max global bounding-box corner
		\return whether the bounding box is valid or not
	**/
	virtual bool getGlobalBB(CCVector3d& minCorner, CCVector3d& maxCorner)
	{
		//by default this method returns the local bounding-box!
		ccBBox box = getOwnBB(false);
		minCorner = CCVector3d::fromArray(box.minCorner().u);
		maxCorner = CCVector3d::fromArray(box.maxCorner().u);
		return box.isValid();
	}

	//! Draws the entity (and its children) bounding-box
	virtual void drawBB(CC_DRAW_CONTEXT& context, const ccColor::Rgb& col);

public: //display

	//Inherited from ccDrawableObject
	void draw(CC_DRAW_CONTEXT& context) override;

	//! Returns the absolute transformation (i.e. the actual displayed GL transforamtion) of an entity
	/** \param[out] trans absolute transformation
		\return whether a GL transformation is actually enabled or not
	**/
	bool getAbsoluteGLTransformation(ccGLMatrix& trans) const;

	//! Returns whether the object is actually displayed (visible) or not
	virtual bool isDisplayed() const;

	//! Returns whether the object is actually displayed (visible) in a given display or not
	virtual bool isDisplayedIn(ccGenericGLDisplay* display) const;

	//! Returns whether the object and all its ancestors are enabled
	virtual bool isBranchEnabled() const;

	/*** RECURSIVE CALL SCRIPTS ***/
	
	//0 parameter
	#define ccHObject_recursive_call0(baseName,recursiveName) \
	inline virtual void recursiveName() \
	{ \
		baseName(); \
		for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) \
			(*it)->recursiveName(); \
	} \

	//1 parameter
	#define ccHObject_recursive_call1(baseName,param1Type,recursiveName) \
	inline virtual void recursiveName(param1Type p) \
	{ \
		baseName(p); \
		for (Container::iterator it = m_children.begin(); it != m_children.end(); ++it) \
			(*it)->recursiveName(p); \
	} \

	//recursive equivalents of some of ccDrawableObject methods
	ccHObject_recursive_call1(setSelected, bool, setSelected_recursive)
	ccHObject_recursive_call1(setDisplay, ccGenericGLDisplay*, setDisplay_recursive)
	ccHObject_recursive_call1(removeFromDisplay, ccGenericGLDisplay*, removeFromDisplay_recursive)
	ccHObject_recursive_call0(prepareDisplayForRefresh, prepareDisplayForRefresh_recursive)
	ccHObject_recursive_call1(refreshDisplay, bool, refreshDisplay_recursive)
	ccHObject_recursive_call0(resetGLTransformationHistory, resetGLTransformationHistory_recursive)
	ccHObject_recursive_call0(toggleActivation, toggleActivation_recursive)
	ccHObject_recursive_call0(toggleVisibility, toggleVisibility_recursive)
	ccHObject_recursive_call0(toggleColors, toggleColors_recursive)
	ccHObject_recursive_call0(toggleNormals, toggleNormals_recursive)
	ccHObject_recursive_call0(toggleSF, toggleSF_recursive)
	ccHObject_recursive_call0(toggleShowName, toggleShowName_recursive)
	ccHObject_recursive_call0(toggleMaterials, toggleMaterials_recursive)

	//! Transfers the entity from one display to the other
	inline virtual void transferDisplay(ccGenericGLDisplay* oldDisplay, ccGenericGLDisplay* newDisplay)
	{
		if (getDisplay() == oldDisplay)
		{
			setDisplay(newDisplay);
		}
	
		for (auto child : m_children)
		{
			child->transferDisplay(oldDisplay, newDisplay);
		}
	} 

	//! Returns the max 'unique ID' of this entity and its siblings
	unsigned findMaxUniqueID_recursive() const;

	//! Applies the active OpenGL transformation to the entity (recursive)
	/** The input ccGLMatrix should be left to 0, unless you want to apply
		a pre-transformation.
		\param trans a ccGLMatrix structure (reference to)
	**/
	void applyGLTransformation_recursive(const ccGLMatrix* trans = nullptr);

	//! Notifies all dependent entities that the geometry of this entity has changed
	virtual void notifyGeometryUpdate();

	//inherited from ccSerializableObject
	bool isSerializable() const override;
	bool toFile(QFile& out) const override;
	bool fromFile(QFile& in, short dataVersion, int flags) override;

	//! Custom version of ccSerializableObject::fromFile
	/** This is used to load only the object's part of a stream (and not its children)
		\param in input file (already opened)
		\param dataVersion file version
		\param flags deserialization flags (see ccSerializableObject::DeserializationFlags)
		\return success
	**/
	bool fromFileNoChildren(QFile& in, short dataVersion, int flags);

	//! Returns whether object is shareable or not
	/** If object is father dependent and 'shared', it won't
		be deleted but 'released' instead.
	**/
	virtual inline bool isShareable() const { return false; }

	//! Behavior when selected
	enum SelectionBehavior { SELECTION_AA_BBOX,
							 SELECTION_FIT_BBOX,
							 SELECTION_IGNORED };

	//! Sets selection behavior (when displayed)
	/** WARNING: SELECTION_FIT_BBOX relies on the
		'ccDrawableObject::getFitBB' method (which
		is not supported by all entities).
	**/
	virtual inline void setSelectionBehavior(SelectionBehavior mode) { m_selectionBehavior = mode; }

	//! Returns selection behavior
	virtual inline SelectionBehavior getSelectionBehavior() const { return m_selectionBehavior; }

	//! Returns object unqiue ID used for display
	virtual inline unsigned getUniqueIDForDisplay() const { return getUniqueID(); }

	//! Returns the transformation 'history' matrix
	virtual inline const ccGLMatrix& getGLTransformationHistory() const { return m_glTransHistory; }
	//! Sets the transformation 'history' matrix (handle with care!)
	virtual inline void setGLTransformationHistory(const ccGLMatrix& mat) { m_glTransHistory = mat; }
	//! Resets the transformation 'history' matrix
	virtual inline void resetGLTransformationHistory() { m_glTransHistory.toIdentity(); }

protected:

	//! Sets parent object
	virtual inline void setParent(ccHObject* anObject) { m_parent = anObject; }

	//! Draws the entity only (not its children)
	virtual void drawMeOnly(CC_DRAW_CONTEXT& context) { /*does nothing by default*/ }

	//! Applies a GL transformation to the entity
	/** this = rotMat*(this-rotCenter)+(rotCenter+trans)
		\param trans a ccGLMatrix structure
	**/
	virtual void applyGLTransformation(const ccGLMatrix& trans);

	//! Save own object data
	/** Called by 'toFile' (recursive scheme)
		To be overloaded (but still called;) by subclass.
	**/
	virtual bool toFile_MeOnly(QFile& out) const;

	//! Loads own object data
	/** Called by 'fromFile' (recursive scheme)
		To be overloaded (but still called;) by subclass.
		\param in input file
		\param dataVersion file version
		\param flags deserialization flags (see ccSerializableObject::DeserializationFlags)
	**/
	virtual bool fromFile_MeOnly(QFile& in, short dataVersion, int flags);

	//! Draws the entity name in 3D
	/** Names is displayed at the center of the bounding box by default.
	**/
	virtual void drawNameIn3D(CC_DRAW_CONTEXT& context);

	//! This method is called when another object is deleted
	/** For internal use.
	**/
	virtual void onDeletionOf(const ccHObject* obj);

	//! This method is called when another object (geometry) is updated
	/** For internal use.
	**/
	virtual void onUpdateOf(ccHObject* obj) { /*does nothing by default*/ }

	//! Parent
	ccHObject* m_parent;

	//! Children
	Container m_children;

	//! Selection behavior
	SelectionBehavior m_selectionBehavior;

	//! Dependencies map
	/** First parameter: other object
		Second parameter: dependency flags (see DEPENDENCY_FLAGS)
	**/
	std::map<ccHObject*, int> m_dependencies;

	//! Cumulative GL transformation
	/** History of all the applied transformations since the creation of the object
		as a single transformation.
	**/
	ccGLMatrix m_glTransHistory;

	//! Flag to safely handle dependencies when the object is being deleted
	bool m_isDeleting;
};

/*** Helpers ***/

//! Puts all entities inside a container in a group
/** Automatically removes siblings so as to get a valid hierarchy object.
	\param origin origin container
	\param dest destination group
	\param dependencyFlags default dependency link for the children added to the group
**/
inline void ConvertToGroup(const ccHObject::Container& origin, ccHObject& dest, int dependencyFlags = ccHObject::DP_NONE)
{
	size_t count = origin.size();
	for (size_t i = 0; i < count; ++i)
	{
		//we don't take objects that are siblings of others
		bool isSiblingOfAnotherOne = false;
		for (size_t j = 0; j < count; ++j)
		{
			if (i != j && origin[j]->isAncestorOf(origin[i]))
			{
				isSiblingOfAnotherOne = true;
				break;
			}
		}

		if (!isSiblingOfAnotherOne)
		{
			dest.addChild(origin[i], dependencyFlags);
		}
	}
}

#endif //CC_HIERARCHY_OBJECT_HEADER