Skip to content

Commit d4d9fdf

Browse files
committed
Fix and augment v0.8 taxonomy wrapper
1 parent b3b14e8 commit d4d9fdf

File tree

3 files changed

+109
-24
lines changed

3 files changed

+109
-24
lines changed

src/ifcwrap/IfcGeomWrapper.i

Lines changed: 100 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ std::pair<char const*, size_t> vector_to_buffer(const T& t) {
117117
// @this is really annoying, but apparently inheritance
118118
// is lost in swig in the shared_ptr type hiearchy
119119
using namespace ifcopenshell::geometry::taxonomy;
120+
if (!$1) $1 = try_upcast<boolean_result>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__boolean_result_t);
120121
if (!$1) $1 = try_upcast<bspline_curve>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__bspline_curve_t);
121122
if (!$1) $1 = try_upcast<bspline_surface>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__bspline_surface_t);
122123
if (!$1) $1 = try_upcast<circle>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__circle_t);
@@ -154,6 +155,41 @@ std::string taxonomy_item_repr(ifcopenshell::geometry::taxonomy::item::ptr i) {
154155
}
155156
%}
156157

158+
%{
159+
160+
161+
namespace {
162+
// Helper function to create a Python tuple from an Eigen matrix/vector
163+
template <typename T>
164+
PyObject* eigen_to_python_tuple(const Eigen::MatrixBase<T>& mat) {
165+
constexpr auto rows = T::RowsAtCompileTime;
166+
constexpr auto cols = T::ColsAtCompileTime;
167+
168+
if constexpr (rows == 1 || cols == 1) {
169+
// Eigen::Vector (1D array)
170+
PyObject* tuple = PyTuple_New(rows * cols);
171+
for (int i = 0; i < mat.size(); ++i) {
172+
PyTuple_SetItem(tuple, i, PyFloat_FromDouble(mat(i)));
173+
}
174+
return tuple;
175+
} else {
176+
// Eigen::Matrix (2D array)
177+
PyObject* tuple = PyTuple_New(rows);
178+
for (int i = 0; i < rows; ++i) {
179+
PyObject* row = PyTuple_New(cols);
180+
for (int j = 0; j < cols; ++j) {
181+
PyTuple_SetItem(row, j, PyFloat_FromDouble(mat(i, j)));
182+
}
183+
PyTuple_SetItem(tuple, i, row);
184+
}
185+
return tuple;
186+
}
187+
}
188+
}
189+
190+
%}
191+
192+
%shared_ptr(ifcopenshell::geometry::taxonomy::boolean_result);
157193
%shared_ptr(ifcopenshell::geometry::taxonomy::item);
158194
%shared_ptr(ifcopenshell::geometry::taxonomy::implicit_item);
159195
%shared_ptr(ifcopenshell::geometry::taxonomy::piecewise_function);
@@ -223,46 +259,85 @@ std::string taxonomy_item_repr(ifcopenshell::geometry::taxonomy::item::ptr i) {
223259
}
224260
}
225261

226-
%extend ifcopenshell::geometry::taxonomy::point3 {
227-
PyObject* coords_() const {
228-
auto result = PyTuple_New(3);
229-
for (int i = 0; i < 3; ++i) {
230-
PyTuple_SET_ITEM(result, i, PyFloat_FromDouble($self->ccomponents().data()[i]));
231-
}
232-
return result;
262+
263+
%define assign_component_acccess(item_name)
264+
265+
%extend ifcopenshell::geometry::taxonomy::item_name {
266+
PyObject* components_() const {
267+
return eigen_to_python_tuple(self->ccomponents());
233268
}
234269

235270
%pythoncode %{
236-
coords = property(coords_)
271+
components = property(components_)
237272
%}
238-
}
273+
};
274+
275+
%enddef
276+
277+
assign_component_acccess(point3);
278+
assign_component_acccess(direction3);
279+
assign_component_acccess(matrix4);
280+
assign_component_acccess(colour);
281+
282+
%define assign_children_access(item_name, children_type)
283+
284+
%extend ifcopenshell::geometry::taxonomy::item_name {
285+
// swig does not accept auto here as the return type
286+
const std::vector<ifcopenshell::geometry::taxonomy::children_type::ptr>& children_() const {
287+
return $self->children;
288+
}
239289

240-
%extend ifcopenshell::geometry::taxonomy::direction3 {
241-
// @todo refactor in macro
242-
PyObject* coords_() const {
243-
auto result = PyTuple_New(3);
244-
for (int i = 0; i < 3; ++i) {
245-
PyTuple_SET_ITEM(result, i, PyFloat_FromDouble($self->ccomponents().data()[i]));
290+
const ifcopenshell::geometry::taxonomy::children_type::ptr& __getitem__(int index) const {
291+
if (index < 0 || index >= $self->children.size()) {
292+
throw std::runtime_error("Index " + std::to_string(index) + " is out of bounds for an array of length " + std::to_string($self->children.size()));
246293
}
247-
return result;
294+
return $self->children[index];
248295
}
249296

250297
%pythoncode %{
251-
coords = property(coords_)
298+
children = property(children_)
299+
def __iter__(self):
300+
return iter(self.children)
252301
%}
253-
}
302+
};
254303

304+
%enddef
255305

256-
%extend ifcopenshell::geometry::taxonomy::loop {
257-
const std::vector<ifcopenshell::geometry::taxonomy::edge::ptr>& children_() const {
258-
return $self->children;
306+
assign_children_access(collection, geom_item);
307+
assign_children_access(loop, edge);
308+
assign_children_access(face, loop);
309+
assign_children_access(shell, face);
310+
assign_children_access(solid, shell);
311+
assign_children_access(loft, face);
312+
assign_children_access(boolean_result, geom_item);
313+
314+
%define assign_matrix_access(item_name)
315+
316+
%extend ifcopenshell::geometry::taxonomy::item_name {
317+
// swig does not accept auto here as the return type
318+
const ifcopenshell::geometry::taxonomy::matrix4::ptr& matrix_() const {
319+
return $self->matrix;
259320
}
260321

261322
%pythoncode %{
262-
children = property(children_)
323+
matrix = property(matrix_)
263324
%}
264-
}
325+
};
265326

327+
%enddef
328+
329+
assign_matrix_access(line);
330+
assign_matrix_access(circle);
331+
assign_matrix_access(ellipse);
332+
assign_matrix_access(collection);
333+
assign_matrix_access(solid);
334+
assign_matrix_access(face);
335+
assign_matrix_access(plane);
336+
assign_matrix_access(cylinder);
337+
assign_matrix_access(sphere);
338+
assign_matrix_access(torus);
339+
assign_matrix_access(extrusion);
340+
assign_matrix_access(revolve);
266341

267342
%extend ifcopenshell::geometry::Settings {
268343
void set_(const std::string& name, bool val) {
@@ -1131,6 +1206,7 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
11311206

11321207
%enddef
11331208

1209+
assign_repr(ifcopenshell::geometry::taxonomy::boolean_result)
11341210
assign_repr(ifcopenshell::geometry::taxonomy::bspline_curve)
11351211
assign_repr(ifcopenshell::geometry::taxonomy::bspline_surface)
11361212
assign_repr(ifcopenshell::geometry::taxonomy::circle)
@@ -1159,4 +1235,5 @@ assign_repr(ifcopenshell::geometry::taxonomy::torus)
11591235
assign_repr(ifcopenshell::geometry::taxonomy::style)
11601236
assign_repr(ifcopenshell::geometry::taxonomy::sweep_along_curve)
11611237

1238+
11621239
#endif

src/ifcwrap/utils/type_conversion.i

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,8 @@ PyObject* item_to_pyobject(const ifcopenshell::geometry::taxonomy::item::ptr& i)
247247
auto kind = i->kind();
248248
// @todo this is not automatically generated :(
249249
// we can probably use the dispatch mechanism for this we already have in the kernel
250-
if (kind == BSPLINE_CURVE) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<bspline_curve>(std::static_pointer_cast<bspline_curve>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__bspline_curve_t, 0 | SWIG_POINTER_OWN); }
250+
if (kind == BOOLEAN_RESULT) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<boolean_result>(std::static_pointer_cast<boolean_result>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__boolean_result_t, 0 | SWIG_POINTER_OWN); }
251+
else if (kind == BSPLINE_CURVE) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<bspline_curve>(std::static_pointer_cast<bspline_curve>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__bspline_curve_t, 0 | SWIG_POINTER_OWN); }
251252
else if (kind == BSPLINE_SURFACE) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<bspline_surface>(std::static_pointer_cast<bspline_surface>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__bspline_surface_t, 0 | SWIG_POINTER_OWN); }
252253
else if (kind == CIRCLE) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<circle>(std::static_pointer_cast<circle>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__circle_t, 0 | SWIG_POINTER_OWN); }
253254
else if (kind == COLLECTION) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<collection>(std::static_pointer_cast<collection>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__collection_t, 0 | SWIG_POINTER_OWN); }

src/ifcwrap/utils/typemaps_out.i

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,14 @@ CREATE_VECTOR_TYPEMAP_OUT(IfcGeom::ConversionResultShape *)
112112
}
113113
};
114114

115+
%typemap(out) const item_name::ptr& {
116+
$result = item_to_pyobject(*$1);
117+
};
118+
115119
%enddef
116120

121+
vector_of_item(ifcopenshell::geometry::taxonomy::item)
122+
vector_of_item(ifcopenshell::geometry::taxonomy::boolean_result)
117123
vector_of_item(ifcopenshell::geometry::taxonomy::bspline_curve)
118124
vector_of_item(ifcopenshell::geometry::taxonomy::bspline_surface)
119125
vector_of_item(ifcopenshell::geometry::taxonomy::circle)
@@ -141,3 +147,4 @@ vector_of_item(ifcopenshell::geometry::taxonomy::sphere)
141147
vector_of_item(ifcopenshell::geometry::taxonomy::torus)
142148
vector_of_item(ifcopenshell::geometry::taxonomy::style)
143149
vector_of_item(ifcopenshell::geometry::taxonomy::sweep_along_curve)
150+
vector_of_item(ifcopenshell::geometry::taxonomy::geom_item)

0 commit comments

Comments
 (0)