diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index 099615fa18..08e62609e6 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -58,6 +58,15 @@ } } +%newobject IfcGeom::ConversionResultShape::halfspaces; +%newobject IfcGeom::ConversionResultShape::box; +%newobject IfcGeom::ConversionResultShape::solid; +%newobject IfcGeom::ConversionResultShape::add; +%newobject IfcGeom::ConversionResultShape::subtract; +%newobject IfcGeom::ConversionResultShape::intersect; +%newobject IfcGeom::ConversionResultShape::moved; +%newobject nary_union; + %include "../ifcgeom/ifc_geom_api.h" %include "../ifcgeom/Converter.h" %include "../ifcgeom/ConversionResult.h" @@ -631,16 +640,48 @@ struct ShapeRTTI : public boost::static_visitor %template(OpaqueCoordinate_3) IfcGeom::OpaqueCoordinate<3>; %template(OpaqueCoordinate_4) IfcGeom::OpaqueCoordinate<4>; -%{ - #include "../ifcgeom/kernels/cgal/CgalConversionResult.h" -%} - %inline %{ std::shared_ptr create_epeck(int i) { return std::make_shared(i); } %} +%inline %{ + IfcGeom::ConversionResultShape* nary_union(PyObject* sequence) { + CGAL::Nef_nary_union_3< CGAL::Nef_polyhedron_3 > accum; + for(Py_ssize_t i = 0; i < PySequence_Size(sequence); ++i) { + PyObject* element = PySequence_GetItem(sequence, i); + void* argp1 = nullptr; + auto res1 = SWIG_ConvertPtr(element, &argp1, SWIGTYPE_p_IfcGeom__ConversionResultShape, 0); + if (SWIG_IsOK(res1)) { + auto arg1 = reinterpret_cast(argp1); + auto cgs = dynamic_cast(arg1); + if (cgs) { + accum.add_polyhedron(cgs->nef()); + } + } + } + return new ifcopenshell::geometry::CgalShape(accum.get_union()); + } +%} + +%extend IfcGeom::ConversionResultShape { + std::string serialize_obj() { + std::ostringstream result; + auto cgs = dynamic_cast(self); + if (cgs) { + write_to_obj(cgs->nef(), result, std::numeric_limits::max()); + } + return result.str(); + } + + std::string serialize() { + std::string result; + ifcopenshell::geometry::taxonomy::matrix4 iden; + $self->Serialize(iden, result); + return result; + } +} %naturalvar svgfill::polygon_2::boundary; %naturalvar svgfill::polygon_2::inner_boundaries; diff --git a/src/ifcwrap/IfcPython.i b/src/ifcwrap/IfcPython.i index c5abadb467..a35b97c4d3 100644 --- a/src/ifcwrap/IfcPython.i +++ b/src/ifcwrap/IfcPython.i @@ -139,6 +139,10 @@ #include "../ifcgeom/ConversionResult.h" #include "../svgfill/src/svgfill.h" + +#ifdef IFOPSH_WITH_CGAL + #include "../ifcgeom/kernels/cgal/CgalConversionResult.h" +#endif %} // Create docstrings for generated python code. diff --git a/src/ifcwrap/utils/type_conversion.i b/src/ifcwrap/utils/type_conversion.i index b496ae0caa..67843cfcd2 100644 --- a/src/ifcwrap/utils/type_conversion.i +++ b/src/ifcwrap/utils/type_conversion.i @@ -138,7 +138,9 @@ PyObject* pythonize(const IfcParse::inverse_attribute* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcParse__inverse_attribute, 0); } PyObject* pythonize(const IfcParse::entity* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcParse__entity, 0); } PyObject* pythonize(const IfcParse::declaration* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), declaration_type_to_swig(t), 0); } - PyObject* pythonize(const IfcGeom::ConversionResultShape* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcGeom__ConversionResultShape, 0); } + // @nb ownership + PyObject* pythonize(const IfcGeom::ConversionResultShape* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcGeom__ConversionResultShape, SWIG_POINTER_OWN); } + // PyObject* pythonize(const IfcGeom::ConversionResultShape* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcGeom__ConversionResultShape, 0); } // NB: This cannot be temporary as a Python object is constructed from a pointer to the address of this object // PyObject* pythonize(const IfcGeom::Material& t) { return SWIG_NewPointerObj(SWIG_as_voidptr(&t), SWIGTYPE_p_IfcGeom__Material, 0); } diff --git a/src/ifcwrap/utils/typemaps_in.i b/src/ifcwrap/utils/typemaps_in.i index b8a95edec2..90a6a9fec2 100644 --- a/src/ifcwrap/utils/typemaps_in.i +++ b/src/ifcwrap/utils/typemaps_in.i @@ -317,4 +317,58 @@ CREATE_VECTOR_TYPEMAP_IN(std::string, STRING, str) CREATE_OPTIONAL_TYPEMAP_IN(int, integer, int) CREATE_OPTIONAL_TYPEMAP_IN(double, real, float) -CREATE_OPTIONAL_TYPEMAP_IN(std::string, string, str) \ No newline at end of file +CREATE_OPTIONAL_TYPEMAP_IN(std::string, string, str) + +%{ + bool check_aggregate_of_swig_type(PyObject* aggregate, swig_type_info* type_obj) { + if (!PySequence_Check(aggregate)) return false; + for(Py_ssize_t i = 0; i < PySequence_Size(aggregate); ++i) { + PyObject* element = PySequence_GetItem(aggregate, i); + + bool b = true; + void* argp1 = nullptr; + auto res1 = SWIG_ConvertPtr(element, &argp1, type_obj, 0); + if (!SWIG_IsOK(res1)) { + b = false; + } + + Py_DECREF(element); + if (!b) { + return false; + } + } + return true; + } + + template + std::vector python_sequence_as_swig_object_vector(PyObject* aggregate, swig_type_info* type_obj) { + std::vector result_vector; + result_vector.reserve(PySequence_Size(aggregate)); + for(Py_ssize_t i = 0; i < PySequence_Size(aggregate); ++i) { + PyObject* element = PySequence_GetItem(aggregate, i); + void* argp1 = nullptr; + auto res1 = SWIG_ConvertPtr(element, &argp1, type_obj, 0); + if (SWIG_IsOK(res1)) { + auto arg1 = reinterpret_cast*>(argp1); + result_vector.push_back(*arg1); + } + } + return result_vector; + } +%} + +%typemap(typecheck,precedence=SWIG_TYPECHECK_INTEGER) const std::vector>& { + $1 = check_aggregate_of_swig_type($input, SWIGTYPE_p_IfcGeom__OpaqueCoordinateT_4_t) ? 1 : 0; +} +%typemap(arginit) const std::vector>& { + $1 = new std::vector>(); +} +%typemap(in) const std::vector>& { + if (!check_aggregate_of_swig_type($input, SWIGTYPE_p_IfcGeom__OpaqueCoordinateT_4_t)) { + SWIG_exception(SWIG_TypeError, ""); + } + *$1 = python_sequence_as_swig_object_vector>($input, SWIGTYPE_p_IfcGeom__OpaqueCoordinateT_4_t); +} +%typemap(freearg) const std::vector>& { + delete $1; +}