ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ccObject.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include <pybind11/native_enum.h>
9 #include <pybind11/pybind11.h>
10 #include <pybind11/stl.h>
11 #include <pybind11/stl_bind.h>
12 
13 #include <ecvBBox.h>
14 #include <ecvGenericDisplayTools.h>
15 #include <ecvHObject.h>
16 #include <ecvObject.h>
17 #include <ecvShiftedObject.h>
18 
19 #include "../casters.h"
20 
21 namespace py = pybind11;
22 using namespace pybind11::literals;
23 
24 // TODO: This should be made into a proper Pull-Request for pybind11
25 // https://github.com/pybind/pybind11/issues/1708
26 void removePatient(py::object &nurse, py::object &patient)
27 {
28  py::detail::internals &internals = py::detail::get_internals();
29  const auto instance = reinterpret_cast<py::detail::instance *>(nurse.ptr());
30  if (!instance->has_patients)
31  {
32  return;
33  }
34  auto &nursePatients = internals.patients[nurse.ptr()];
35 
36  auto it = std::find(nursePatients.begin(), nursePatients.end(), patient.ptr());
37  if (it == std::end(nursePatients))
38  {
39  return;
40  }
41 
42  nursePatients.erase(it);
43  instance->has_patients = !nursePatients.empty();
44  if (!instance->has_patients)
45  {
46  internals.patients.erase(nurse.ptr());
47  }
48  patient.dec_ref();
49 }
50 
51 void setDeletable(py::object &object, bool state)
52 {
53  auto instance = reinterpret_cast<py::detail::instance *>(object.ptr());
54  instance->owned = state;
55  for (auto &v_h : py::detail::values_and_holders(instance))
56  {
57  if (v_h)
58  {
59  v_h.set_holder_constructed(state);
60  }
61  }
62 }
63 
70 template <typename T> py::object castToFakeOwnedObject(T &&obj)
71 {
72  py::object pyObj = py::cast(obj, py::return_value_policy::take_ownership);
73  setDeletable(pyObj, false);
74  return pyObj;
75 }
76 
77 void define_ccObject(py::module &m)
78 {
79  py::class_<ccObject>(m, "ccObject", R"pbdoc(
80  The base class of all ACloudViewer's data types
81 
82  - ccOjbects have a name that can be changed
83  - an 'enabled' state to control if the object should be displayed
84  - a metadata system
85 
86  Example
87  -------
88  >>> import pycc
89  >>> pc = pycc.ccPointCloud()
90  >>> pc.setName("Green Yoshi")
91  >>> pc.getName() == "Green Yoshi"
92  True
93  >>> pc.hasMetaData("Favorite Food")
94  False
95  >>> pc.getMetaData("Favorite Food") is None
96  True
97  >>> pc.setMetaData("Favorite Food", "Apples")
98  >>> pc.hasMetaData("Favorite Food")
99  True
100  >>> pc.getMetaData("Favorite Food") == "Apples"
101  True
102 
103 
104 )pbdoc")
105  .def("getName", &ccObject::getName, R"pbdoc(
106  Returns the name of the object
107 )pbdoc")
108  .def("setName", &ccObject::setName, "name"_a, R"pbdoc(
109  Sets the name of the object
110 
111  Parameters
112  ----------
113  name: str
114  The new name
115 )pbdoc")
116  // .def("getClassID", &ccObject::getClassID)
117  .def("getUniqueID", &ccObject::getUniqueID)
118  .def("isEnabled", &ccObject::isEnabled, R"pbdoc(
119  Returns whether the object is enabled
120 )pbdoc")
121  .def("setEnabled", &ccObject::setEnabled, "state"_a, R"pbdoc(
122  Sets the "enabled" state
123 
124  Parameters
125  ----------
126  state: bool
127  The new "enabled" state
128 )pbdoc")
129  .def("toggleActivation", &ccObject::toggleActivation)
130  .def("isLocked", &ccObject::isLocked, R"pbdoc(
131  Returns whether the object is locked
132 )pbdoc")
133  .def("setLocked", &ccObject::setLocked)
134  .def("isLeaf", &ccObject::isLeaf)
135  .def("isCustom", &ccObject::isCustom)
136  .def("isHierarchy", &ccObject::isHierarchy)
137  .def("getMetaData", &ccObject::getMetaData, "key"_a, R"pbdoc(
138  Returns the metadata associated to a key.
139 
140  Returns None if no metadata for the key is found
141 
142  Parameters
143  ----------
144  key: str
145  The key / name of the metadata to retrieve
146 )pbdoc")
147  .def("removeMetaData", &ccObject::removeMetaData, "key"_a, R"pbdoc(
148  Removes the metadata associated to a key.
149 
150  Parameters
151  ----------
152  key: str
153  The key / name of the metadata to remove
154 )pbdoc")
155  .def(
156  "setMetaData",
157  [](ccObject &obj, const QString &key, const QVariant &data)
158  { obj.setMetaData(key, data); },
159  "key"_a,
160  "data"_a,
161  R"pbdoc(
162  Sets the metadata associated to a key.
163 
164  Parameters
165  ----------
166  key: str
167  The key / name of the metadata to remove
168  data: str | int
169  The value
170 )pbdoc")
171  .def("hasMetaData", &ccObject::hasMetaData, "key"_a, R"pbdoc(
172  Returns True if the object has some metadata associated to the key
173 
174  Parameters
175  ----------
176  key: str
177  The key / name of the metadata to remove
178 )pbdoc");
179 
180  py::native_enum<ccHObject::DEPENDENCY_FLAGS>(
181  m, "DEPENDENCY_FLAGS", "enum.Enum", "ccHObject::DEPENDENCY_FLAGS.")
182  .value("DP_NONE", ccHObject::DEPENDENCY_FLAGS::DP_NONE)
183  .value("DP_NOTIFY_OTHER_ON_DELETE", ccHObject::DEPENDENCY_FLAGS::DP_NOTIFY_OTHER_ON_DELETE)
184  .value("DP_NOTIFY_OTHER_ON_UPDATE", ccHObject::DEPENDENCY_FLAGS::DP_NOTIFY_OTHER_ON_UPDATE)
185  .value("DP_DELETE_OTHER", ccHObject::DEPENDENCY_FLAGS::DP_DELETE_OTHER)
186  .value("DP_PARENT_OF_OTHER", ccHObject::DEPENDENCY_FLAGS::DP_PARENT_OF_OTHER)
187  .export_values()
188  .finalize();
189 
190  py::class_<ccHObject, ccObject, ccDrawableObject>(m, "ccHObject", R"pbdoc(
191  ACloudViewer's hierarchical object
192 
193  Hierarchical objects can have children forming a hierarchy tree
194 
195  Example
196  -------
197  >>> import pycc
198  >>> h = pycc.ccHObject("My Project Hierarchy")
199 
200  This new hierarchy has no parents, nor children:
201 
202  >>> h.getParent() is None
203  True
204  >>> h.getChildrenNumber(), h.getChildCountRecursive()
205  (0, 0)
206 )pbdoc")
207  .def(py::init<QString>(), "name"_a = QString())
208  .def("isGroup", &ccHObject::isGroup)
209  .def("getParent",
211  py::return_value_policy::reference_internal,
212  R"pbdoc(
213  Returns the parent of this object
214 
215  Returns None if the object has no parent
216 )pbdoc")
217  // Children management
218  .def("getChildrenNumber", &ccHObject::getChildrenNumber, R"pbdoc(
219  Returns the number of 'direct' children this object has
220 )pbdoc")
221  .def("getChildCountRecursive", &ccHObject::getChildCountRecursive, R"pbdoc(
222  Returns the recursive number of children
223 )pbdoc")
224  .def(
225  "getChild",
226  [](py::object &self, const unsigned int index)
227  {
228  auto *child = self.cast<ccHObject *>()->getChild(index);
229  return castToFakeOwnedObject(child);
230  },
231  py::keep_alive<0, 1>(),
232  "child"_a)
233  .def("find", &ccHObject::find, "uniqueID"_a, py::return_value_policy::reference_internal)
234  .def(
235  "detachChild",
236  [](py::object &self, py::object &child)
237  {
238  self.cast<ccHObject *>()->detachChild(child.cast<ccHObject *>());
239  removePatient(child, self);
240  setDeletable(child, true);
241  },
242  "child"_a)
243  .def("detachChild", &ccHObject::detachChild, "child"_a)
244  .def("detachAllChildren", &ccHObject::detachAllChildren)
245  .def("swapChildren", &ccHObject::swapChildren, "firstChildIndex"_a, "secondChildIndex"_a)
246  .def("getChildIndex", &ccHObject::getChildIndex, "child"_a)
247  .def("getIndex", &ccHObject::getIndex)
248  .def(
249  "addChild",
250  [](ccHObject &self,
251  ccHObject *child,
252  ccHObject::DEPENDENCY_FLAGS dependencyFlags,
253  int insertIndex) { return self.addChild(child, dependencyFlags, insertIndex); },
254  py::keep_alive<2, 1>(), // keep alive parent (1) while added child (2) is alive
255  "child"_a,
256  "dependencyFlags"_a = ccHObject::DEPENDENCY_FLAGS::DP_PARENT_OF_OTHER,
257  "insertIndex"_a = -1)
258  .def(
259  "getFirstChild",
260  [](ccHObject &self)
261  {
262  ccHObject *child = self.getFirstChild();
263  return castToFakeOwnedObject(child);
264  },
265  py::keep_alive<0, 1>())
266  .def(
267  "getLastChild",
268  [](ccHObject &self)
269  {
270  ccHObject *child = self.getLastChild();
271  return castToFakeOwnedObject(child);
272  },
273  py::keep_alive<0, 1>())
274  .def("isAncestorOf", &ccHObject::isAncestorOf, "anObject"_a)
275  // bounding-box
276  .def("getDisplayBB_recursive", &ccHObject::getDisplayBB_recursive, "relative"_a)
277 
278  // display
279  .def("applyGLTransformation_recursive",
281  "trans"_a = nullptr)
282  .def("getGLTransformationHistory", &ccHObject::getGLTransformationHistory)
283  .def("setGLTransformationHistory", &ccHObject::setGLTransformationHistory, "mat"_a)
284  .def("resetGLTransformationHistory", &ccHObject::resetGLTransformationHistory)
285  .def("notifyGeometryUpdate", &ccHObject::notifyGeometryUpdate, R"pbdoc(
286  Notifies all dependent entities that the geometry of this entity has changed
287 )pbdoc");
288 
289  py::class_<ccShiftedObject, ccHObject>(m, "ccShiftedObject")
290  .def("setGlobalShift",
291  (void(ccShiftedObject::*)(double, double, double))(&ccShiftedObject::setGlobalShift),
292  "x_"_a,
293  "y"_a,
294  "z"_a)
295  .def("setGlobalShift",
297  "shift"_a)
298  .def("getGlobalShift", &ccShiftedObject::getGlobalShift)
299  .def("setGlobalScale", &ccShiftedObject::setGlobalScale, "scale"_a)
300  .def("isShifted", &ccShiftedObject::isShifted)
301  .def("getGlobalScale", &ccShiftedObject::getGlobalScale)
302  .def("copyGlobalShiftAndScale", &ccShiftedObject::copyGlobalShiftAndScale, "s"_a);
303 }
void setDeletable(py::object &object, bool state)
Definition: ccObject.cpp:51
void removePatient(py::object &nurse, py::object &patient)
Definition: ccObject.cpp:26
void define_ccObject(py::module &m)
Definition: ccObject.cpp:77
py::object castToFakeOwnedObject(T &&obj)
Definition: ccObject.cpp:70
Hierarchical CLOUDVIEWER Object.
Definition: ecvHObject.h:25
virtual void notifyGeometryUpdate()
virtual const ccGLMatrix & getGLTransformationHistory() const
Returns the transformation 'history' matrix.
Definition: ecvHObject.h:631
ccHObject * find(unsigned uniqueID)
Finds an entity in this object hierarchy.
ccHObject * getLastChild() const
Shortcut: returns last child.
Definition: ecvHObject.h:400
int getChildIndex(const ccHObject *aChild) const
Returns child index.
int getIndex() const
Returns index relatively to its parent or -1 if no parent.
virtual ccBBox getDisplayBB_recursive(bool relative)
Returns the bounding-box of this entity and it's children WHEN DISPLAYED.
ccHObject * getFirstChild() const
Shortcut: returns first child.
Definition: ecvHObject.h:396
void detachChild(ccHObject *child)
Detaches a specific child.
bool isAncestorOf(const ccHObject *anObject) const
Returns true if the current object is an ancestor of the specified one.
void applyGLTransformation_recursive(const ccGLMatrix *trans=nullptr)
Applies the active OpenGL transformation to the entity (recursive)
unsigned getChildrenNumber() const
Returns the number of children.
Definition: ecvHObject.h:312
unsigned int getChildCountRecursive() const
Returns the total number of children under this object recursively.
virtual void setGLTransformationHistory(const ccGLMatrix &mat)
Sets the transformation 'history' matrix (handle with care!)
Definition: ecvHObject.h:635
DEPENDENCY_FLAGS
Dependency flags.
Definition: ecvHObject.h:257
ccHObject * getParent() const
Returns parent object.
Definition: ecvHObject.h:245
void detachAllChildren()
Removes a specific child.
void swapChildren(unsigned firstChildIndex, unsigned secondChildIndex)
Swaps two children.
virtual void resetGLTransformationHistory()
Resets the transformation 'history' matrix.
Definition: ecvHObject.h:639
bool isGroup() const
Returns whether the instance is a group.
Definition: ecvHObject.h:237
Generic "CLOUDVIEWER Object" template.
Definition: ecvObject.h:49
virtual void setLocked(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:117
virtual bool isLocked() const
Returns whether the object is locked or not.
Definition: ecvObject.h:112
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
virtual unsigned getUniqueID() const
Returns object unique ID.
Definition: ecvObject.h:86
void setMetaData(const QString &key, const QVariant &data)
Sets a meta-data element.
QVariant getMetaData(const QString &key) const
Returns a given associated meta data.
bool hasMetaData(const QString &key) const
Returns whether a meta-data element with the given key exists or not.
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
virtual void setEnabled(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:102
bool isCustom() const
Definition: ecvObject.h:123
bool isHierarchy() const
Definition: ecvObject.h:124
bool isLeaf() const
Definition: ecvObject.h:122
bool removeMetaData(const QString &key)
Removes a given associated meta-data.
virtual bool isEnabled() const
Returns whether the object is enabled or not.
Definition: ecvObject.h:97
virtual void toggleActivation()
Toggles the "enabled" property.
Definition: ecvObject.h:107
Shifted entity interface.
virtual void setGlobalScale(double scale)
bool isShifted() const
Returns whether the cloud is shifted or not.
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
virtual const CCVector3d & getGlobalShift() const
Returns the shift applied to original coordinates.
virtual double getGlobalScale() const
Returns the scale applied to original coordinates.
void copyGlobalShiftAndScale(const ccShiftedObject &s)
Copies the Global Shift and Scale from another entity.