mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-29 08:13:14 +00:00
Merge remote-tracking branch 'origin/v0.8.0' into datamodel-v1.0
This commit is contained in:
+254
-253
@@ -50,7 +50,7 @@
|
||||
$result = PyBool_FromLong(static_cast<long>(*$1));
|
||||
}
|
||||
|
||||
// Using RTTI return a more specialized type of Element
|
||||
// Using RTTI return a more specialized type of Element
|
||||
// Note that these elements are not to be owned by SWIG/Python as they will be freed automatically upon the next iteration
|
||||
// except for the IfcGeom::Element instances which are returned by Iterator::getObject() calls
|
||||
%typemap(out) IfcGeom::Element* {
|
||||
@@ -253,11 +253,11 @@ namespace {
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::extrusion);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::revolve);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::sweep_along_curve);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::node);
|
||||
|
||||
%include "../ifcgeom/ifc_geom_api.h"
|
||||
%include "../ifcgeom/ConversionResult.h"
|
||||
%include "../ifcgeom/ConversionSettings.h"
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::node);
|
||||
|
||||
%include "../ifcgeom/ifc_geom_api.h"
|
||||
%include "../ifcgeom/ConversionResult.h"
|
||||
%include "../ifcgeom/ConversionSettings.h"
|
||||
%include "../ifcgeom/IfcGeomElement.h"
|
||||
%include "../ifcgeom/IfcGeomRepresentation.h"
|
||||
%include "../ifcgeom/Iterator.h"
|
||||
@@ -432,72 +432,72 @@ assign_matrix_access(revolve);
|
||||
}
|
||||
}
|
||||
|
||||
%template(ray_intersection_results) std::vector<IfcGeom::ray_intersection_result>;
|
||||
|
||||
%template(clashes) std::vector<IfcGeom::clash>;
|
||||
|
||||
%include "../ifcgeom/tree.h"
|
||||
|
||||
%extend IfcGeom::tree {
|
||||
|
||||
std::vector<express::Base> select_box(const express::Base& e, bool completely_within = false, double extend=-1.e-5) const {
|
||||
%template(ray_intersection_results) std::vector<IfcGeom::ray_intersection_result>;
|
||||
|
||||
%template(clashes) std::vector<IfcGeom::clash>;
|
||||
|
||||
%include "../ifcgeom/tree.h"
|
||||
|
||||
%extend IfcGeom::tree {
|
||||
|
||||
std::vector<express::Base> select_box(const express::Base& e, bool completely_within = false, double extend=-1.e-5) const {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw ifcopenshell::exception("Instance should be an IfcProduct");
|
||||
}
|
||||
return cast_vector<express::Base>($self->select_box(e.as<express::Entity>(), completely_within, extend));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select_box(const std::vector<double>& p) const {
|
||||
if (p.size() != 3) {
|
||||
throw ifcopenshell::exception("Point should be a sequence of 3 floats");
|
||||
}
|
||||
IfcGeom::tree_point point = {{ p[0], p[1], p[2] }};
|
||||
return cast_vector<express::Base>($self->select_box(point));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select_box(const std::vector<std::vector<double>>& b, bool completely_within = false) const {
|
||||
if (b.size() != 2 || b[0].size() != 3 || b[1].size() != 3) {
|
||||
throw ifcopenshell::exception("Bounding box should be a sequence of 2 x 3 floats");
|
||||
}
|
||||
IfcGeom::tree_box box = {{
|
||||
{ b[0][0], b[0][1], b[0][2] },
|
||||
{ b[1][0], b[1][1], b[1][2] }
|
||||
}};
|
||||
return cast_vector<express::Base>($self->select_box(box, completely_within));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select(const express::Base& e, bool completely_within = false, double extend = 0.0) const {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw ifcopenshell::exception("Instance should be an IfcProduct");
|
||||
}
|
||||
return cast_vector<express::Base>($self->select(e.as<express::Entity>(), completely_within, extend));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select(const std::vector<double>& p, double extend=0.0) const {
|
||||
if (p.size() != 3) {
|
||||
throw ifcopenshell::exception("Point should be a sequence of 3 floats");
|
||||
}
|
||||
IfcGeom::tree_point point = {{ p[0], p[1], p[2] }};
|
||||
return cast_vector<express::Base>($self->select(point, extend));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select(const IfcGeom::Element* elem, bool completely_within = false, double extend = -1.e-5) const {
|
||||
return cast_vector<express::Base>($self->select(elem, completely_within, extend));
|
||||
}
|
||||
|
||||
std::vector<IfcGeom::ray_intersection_result> select_ray(const std::vector<double>& p0, const std::vector<double>& d, double length = 1000.) const {
|
||||
if (p0.size() != 3 || d.size() != 3) {
|
||||
throw ifcopenshell::exception("Origin and direction should be sequences of 3 floats");
|
||||
}
|
||||
IfcGeom::tree_point origin = {{ p0[0], p0[1], p0[2] }};
|
||||
IfcGeom::tree_point direction = {{ d[0], d[1], d[2] }};
|
||||
return $self->select_ray(origin, direction, length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// A visitor
|
||||
%{
|
||||
}
|
||||
return cast_vector<express::Base>($self->select_box(e.as<express::Entity>(), completely_within, extend));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select_box(const std::vector<double>& p) const {
|
||||
if (p.size() != 3) {
|
||||
throw ifcopenshell::exception("Point should be a sequence of 3 floats");
|
||||
}
|
||||
IfcGeom::tree_point point = {{ p[0], p[1], p[2] }};
|
||||
return cast_vector<express::Base>($self->select_box(point));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select_box(const std::vector<std::vector<double>>& b, bool completely_within = false) const {
|
||||
if (b.size() != 2 || b[0].size() != 3 || b[1].size() != 3) {
|
||||
throw ifcopenshell::exception("Bounding box should be a sequence of 2 x 3 floats");
|
||||
}
|
||||
IfcGeom::tree_box box = {{
|
||||
{ b[0][0], b[0][1], b[0][2] },
|
||||
{ b[1][0], b[1][1], b[1][2] }
|
||||
}};
|
||||
return cast_vector<express::Base>($self->select_box(box, completely_within));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select(const express::Base& e, bool completely_within = false, double extend = 0.0) const {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw ifcopenshell::exception("Instance should be an IfcProduct");
|
||||
}
|
||||
return cast_vector<express::Base>($self->select(e.as<express::Entity>(), completely_within, extend));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select(const std::vector<double>& p, double extend=0.0) const {
|
||||
if (p.size() != 3) {
|
||||
throw ifcopenshell::exception("Point should be a sequence of 3 floats");
|
||||
}
|
||||
IfcGeom::tree_point point = {{ p[0], p[1], p[2] }};
|
||||
return cast_vector<express::Base>($self->select(point, extend));
|
||||
}
|
||||
|
||||
std::vector<express::Base> select(const IfcGeom::Element* elem, bool completely_within = false, double extend = -1.e-5) const {
|
||||
return cast_vector<express::Base>($self->select(elem, completely_within, extend));
|
||||
}
|
||||
|
||||
std::vector<IfcGeom::ray_intersection_result> select_ray(const std::vector<double>& p0, const std::vector<double>& d, double length = 1000.) const {
|
||||
if (p0.size() != 3 || d.size() != 3) {
|
||||
throw ifcopenshell::exception("Origin and direction should be sequences of 3 floats");
|
||||
}
|
||||
IfcGeom::tree_point origin = {{ p0[0], p0[1], p0[2] }};
|
||||
IfcGeom::tree_point direction = {{ d[0], d[1], d[2] }};
|
||||
return $self->select_ray(origin, direction, length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// A visitor
|
||||
%{
|
||||
struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
{
|
||||
PyObject* operator()(IfcGeom::Element* elem) const {
|
||||
@@ -783,70 +783,70 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
%}
|
||||
};
|
||||
|
||||
%{
|
||||
template <typename T>
|
||||
std::string to_locale_invariant_string(const T& t) {
|
||||
std::ostringstream oss;
|
||||
oss.imbue(std::locale::classic());
|
||||
oss << t;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> helper_fn_create_shape(const std::string& geometry_library, ifcopenshell::geometry::Settings& st, const express::Base& instance, const express::Base& representation = express::Base()) {
|
||||
ifcopenshell::file* file = instance.file();
|
||||
|
||||
ifcopenshell::geometry::Converter kernel(ifcopenshell::geometry::kernels::construct(file, geometry_library, st), file, st);
|
||||
if (instance.declaration().is("IfcProduct")) {
|
||||
if (representation && !representation.declaration().is("IfcRepresentation")) {
|
||||
throw ifcopenshell::exception("Supplied representation not of type IfcRepresentation");
|
||||
}
|
||||
|
||||
auto selected_representation = representation ? representation : kernel.mapping()->representation_of(instance);
|
||||
if (!selected_representation) {
|
||||
throw ifcopenshell::exception("No suitable IfcRepresentation found");
|
||||
}
|
||||
|
||||
IfcGeom::BRepElement* brep = kernel.create_brep_for_representation_and_product(selected_representation, instance);
|
||||
if (!brep) {
|
||||
std::ostringstream oss_repr, oss_product;
|
||||
selected_representation.to_string(oss_repr);
|
||||
instance.to_string(oss_product);
|
||||
throw ifcopenshell::exception("Failed to process shape. Product: " + oss_product.str() + ", representation: " + oss_repr.str());
|
||||
}
|
||||
if (st.get<ifcopenshell::geometry::settings::IteratorOutput>().get() == ifcopenshell::geometry::settings::SERIALIZED) {
|
||||
IfcGeom::SerializedElement* serialization = new IfcGeom::SerializedElement(*brep);
|
||||
delete brep;
|
||||
%{
|
||||
template <typename T>
|
||||
std::string to_locale_invariant_string(const T& t) {
|
||||
std::ostringstream oss;
|
||||
oss.imbue(std::locale::classic());
|
||||
oss << t;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> helper_fn_create_shape(const std::string& geometry_library, ifcopenshell::geometry::Settings& st, const express::Base& instance, const express::Base& representation = express::Base()) {
|
||||
ifcopenshell::file* file = instance.file();
|
||||
|
||||
ifcopenshell::geometry::Converter kernel(ifcopenshell::geometry::kernels::construct(file, geometry_library, st), file, st);
|
||||
if (instance.declaration().is("IfcProduct")) {
|
||||
if (representation && !representation.declaration().is("IfcRepresentation")) {
|
||||
throw ifcopenshell::exception("Supplied representation not of type IfcRepresentation");
|
||||
}
|
||||
|
||||
auto selected_representation = representation ? representation : kernel.mapping()->representation_of(instance);
|
||||
if (!selected_representation) {
|
||||
throw ifcopenshell::exception("No suitable IfcRepresentation found");
|
||||
}
|
||||
|
||||
IfcGeom::BRepElement* brep = kernel.create_brep_for_representation_and_product(selected_representation, instance);
|
||||
if (!brep) {
|
||||
std::ostringstream oss_repr, oss_product;
|
||||
selected_representation.to_string(oss_repr);
|
||||
instance.to_string(oss_product);
|
||||
throw ifcopenshell::exception("Failed to process shape. Product: " + oss_product.str() + ", representation: " + oss_repr.str());
|
||||
}
|
||||
if (st.get<ifcopenshell::geometry::settings::IteratorOutput>().get() == ifcopenshell::geometry::settings::SERIALIZED) {
|
||||
IfcGeom::SerializedElement* serialization = new IfcGeom::SerializedElement(*brep);
|
||||
delete brep;
|
||||
return serialization;
|
||||
} else if (st.get<ifcopenshell::geometry::settings::IteratorOutput>().get() == ifcopenshell::geometry::settings::TRIANGULATED) {
|
||||
IfcGeom::TriangulationElement* triangulation = new IfcGeom::TriangulationElement(*brep);
|
||||
delete brep;
|
||||
return triangulation;
|
||||
} else {
|
||||
return brep;
|
||||
}
|
||||
} else if (instance.declaration().is("IfcPlacement") || instance.declaration().is("IfcObjectPlacement")) {
|
||||
auto item = ifcopenshell::geometry::taxonomy::cast<ifcopenshell::geometry::taxonomy::matrix4>(kernel.mapping()->map(instance));
|
||||
if (item == nullptr) {
|
||||
throw ifcopenshell::exception("Failed to convert placement");
|
||||
}
|
||||
if (st.get<ifcopenshell::geometry::settings::ConvertBackUnits>().get()) {
|
||||
} else {
|
||||
return brep;
|
||||
}
|
||||
} else if (instance.declaration().is("IfcPlacement") || instance.declaration().is("IfcObjectPlacement")) {
|
||||
auto item = ifcopenshell::geometry::taxonomy::cast<ifcopenshell::geometry::taxonomy::matrix4>(kernel.mapping()->map(instance));
|
||||
if (item == nullptr) {
|
||||
throw ifcopenshell::exception("Failed to convert placement");
|
||||
}
|
||||
if (st.get<ifcopenshell::geometry::settings::ConvertBackUnits>().get()) {
|
||||
// we pass the settings to the Transformation object, but access the data just offloads to the
|
||||
// generic cartesian_base<Matrix4> so there's no time to apply the settings to the translation part.
|
||||
item = ifcopenshell::geometry::taxonomy::matrix4::ptr(item->clone_());
|
||||
item->components().col(3).head<3>() /= kernel.settings().get<ifcopenshell::geometry::settings::LengthUnit>().get();
|
||||
}
|
||||
return new IfcGeom::Transformation(kernel.settings(), item);
|
||||
} else {
|
||||
if (!representation) {
|
||||
if (instance.declaration().is("IfcRepresentationItem") ||
|
||||
instance.declaration().is("IfcRepresentation") ||
|
||||
// https://github.com/IfcOpenShell/IfcOpenShell/issues/1649
|
||||
instance.declaration().is("IfcProfileDef")
|
||||
) {
|
||||
IfcGeom::ConversionResults shapes;
|
||||
try {
|
||||
shapes = kernel.convert(instance);
|
||||
} catch (...) {
|
||||
}
|
||||
return new IfcGeom::Transformation(kernel.settings(), item);
|
||||
} else {
|
||||
if (!representation) {
|
||||
if (instance.declaration().is("IfcRepresentationItem") ||
|
||||
instance.declaration().is("IfcRepresentation") ||
|
||||
// https://github.com/IfcOpenShell/IfcOpenShell/issues/1649
|
||||
instance.declaration().is("IfcProfileDef")
|
||||
) {
|
||||
IfcGeom::ConversionResults shapes;
|
||||
try {
|
||||
shapes = kernel.convert(instance);
|
||||
} catch (...) {
|
||||
std::ostringstream oss;
|
||||
instance.to_string(oss);
|
||||
throw ifcopenshell::exception("Failed to process shape. Instance: " + oss.str());
|
||||
@@ -903,12 +903,12 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
std::unique_ptr<ifcopenshell::geometry::abstract_mapping> mapping(ifcopenshell::geometry::impl::mapping_implementations().construct(instance.file(), settings));
|
||||
return mapping->map(instance);
|
||||
}
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> create_shape(ifcopenshell::geometry::Settings& settings, const express::Base& instance, const express::Base& representation, const char* const geometry_library="opencascade") {
|
||||
return helper_fn_create_shape(geometry_library, settings, instance, representation);
|
||||
}
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> create_shape(ifcopenshell::geometry::Settings& settings, const express::Base& instance, const express::Base& representation, const char* const geometry_library="opencascade") {
|
||||
return helper_fn_create_shape(geometry_library, settings, instance, representation);
|
||||
}
|
||||
|
||||
// Manual definition of overload without representation argument
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> create_shape(ifcopenshell::geometry::Settings& settings, const express::Base& instance, const char* const geometry_library="opencascade") {
|
||||
@@ -916,15 +916,15 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
}
|
||||
%}
|
||||
|
||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
||||
|
||||
%inline %{
|
||||
#include <BRepTools_ShapeSet.hxx>
|
||||
|
||||
express::Base serialise(ifcopenshell::file& f, const std::string& shape_str, bool advanced=true) {
|
||||
std::stringstream stream(shape_str);
|
||||
BRepTools_ShapeSet shapes;
|
||||
shapes.Read(stream);
|
||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
||||
|
||||
%inline %{
|
||||
#include <BRepTools_ShapeSet.hxx>
|
||||
|
||||
express::Base serialise(ifcopenshell::file& f, const std::string& shape_str, bool advanced=true) {
|
||||
std::stringstream stream(shape_str);
|
||||
BRepTools_ShapeSet shapes;
|
||||
shapes.Read(stream);
|
||||
const TopoDS_Shape& shp = shapes.Shape(shapes.NbShapes());
|
||||
|
||||
return IfcGeom::serialise(f, shp, advanced);
|
||||
@@ -942,95 +942,95 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
|
||||
#endif
|
||||
|
||||
%template(OpaqueCoordinate_3) IfcGeom::OpaqueCoordinate<3>;
|
||||
%template(OpaqueCoordinate_4) IfcGeom::OpaqueCoordinate<4>;
|
||||
|
||||
%newobject create_epeck;
|
||||
|
||||
%inline %{
|
||||
IfcGeom::OpaqueNumber* create_epeck(int i) {
|
||||
return new IfcGeom::NumberNativeDouble(i);
|
||||
}
|
||||
IfcGeom::OpaqueNumber* create_epeck(double d) {
|
||||
return new IfcGeom::NumberNativeDouble(d);
|
||||
}
|
||||
IfcGeom::OpaqueNumber* create_epeck(const std::string& s) {
|
||||
return new IfcGeom::NumberNativeDouble(std::stod(s));
|
||||
}
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
IfcGeom::ConversionResultShape* nary_union(PyObject* sequence) {
|
||||
IfcGeom::ConversionResultShape* result = nullptr;
|
||||
std::string backend_id;
|
||||
auto identity = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::matrix4>();
|
||||
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<IfcGeom::ConversionResultShape*>(argp1);
|
||||
auto element_backend_id = std::string(arg1->backend_id());
|
||||
if (backend_id.empty()) {
|
||||
backend_id = element_backend_id;
|
||||
result = arg1->moved(identity);
|
||||
} else {
|
||||
if (element_backend_id != backend_id) {
|
||||
delete result;
|
||||
throw ifcopenshell::exception("nary_union requires shapes from the same geometry backend");
|
||||
}
|
||||
auto next = result->add(arg1);
|
||||
if (!next) {
|
||||
delete result;
|
||||
throw ifcopenshell::exception("nary_union failed for backend " + backend_id);
|
||||
}
|
||||
delete result;
|
||||
result = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
throw ifcopenshell::exception("nary_union requires at least one shape");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
%}
|
||||
|
||||
%extend IfcGeom::ConversionResultShape {
|
||||
std::string serialize_obj() {
|
||||
ifcopenshell::geometry::Settings settings;
|
||||
std::unique_ptr<IfcGeom::Representation::Triangulation> triangulation($self->Triangulate(settings));
|
||||
std::ostringstream result;
|
||||
|
||||
for (auto it = triangulation->verts().begin(); it != triangulation->verts().end();) {
|
||||
result << "v " << *(it++) << " " << *(it++) << " " << *(it++) << "\n";
|
||||
}
|
||||
for (auto it = triangulation->normals().begin(); it != triangulation->normals().end();) {
|
||||
result << "vn " << *(it++) << " " << *(it++) << " " << *(it++) << "\n";
|
||||
}
|
||||
|
||||
const bool has_normals = !triangulation->normals().empty();
|
||||
for (auto it = triangulation->faces().begin(); it != triangulation->faces().end();) {
|
||||
const auto v1 = *(it++) + 1;
|
||||
const auto v2 = *(it++) + 1;
|
||||
const auto v3 = *(it++) + 1;
|
||||
if (has_normals) {
|
||||
result << "f "
|
||||
<< v1 << "//" << v1 << " "
|
||||
<< v2 << "//" << v2 << " "
|
||||
<< v3 << "//" << v3 << "\n";
|
||||
} else {
|
||||
result << "f " << v1 << " " << v2 << " " << v3 << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void convex_tag(bool b) {
|
||||
(void)b;
|
||||
throw ifcopenshell::exception("convex_tag is not available through the generic conversion result interface");
|
||||
}
|
||||
%template(OpaqueCoordinate_3) IfcGeom::OpaqueCoordinate<3>;
|
||||
%template(OpaqueCoordinate_4) IfcGeom::OpaqueCoordinate<4>;
|
||||
|
||||
%newobject create_epeck;
|
||||
|
||||
%inline %{
|
||||
IfcGeom::OpaqueNumber* create_epeck(int i) {
|
||||
return new IfcGeom::NumberNativeDouble(i);
|
||||
}
|
||||
IfcGeom::OpaqueNumber* create_epeck(double d) {
|
||||
return new IfcGeom::NumberNativeDouble(d);
|
||||
}
|
||||
IfcGeom::OpaqueNumber* create_epeck(const std::string& s) {
|
||||
return new IfcGeom::NumberNativeDouble(std::stod(s));
|
||||
}
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
IfcGeom::ConversionResultShape* nary_union(PyObject* sequence) {
|
||||
IfcGeom::ConversionResultShape* result = nullptr;
|
||||
std::string backend_id;
|
||||
auto identity = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::matrix4>();
|
||||
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<IfcGeom::ConversionResultShape*>(argp1);
|
||||
auto element_backend_id = std::string(arg1->backend_id());
|
||||
if (backend_id.empty()) {
|
||||
backend_id = element_backend_id;
|
||||
result = arg1->moved(identity);
|
||||
} else {
|
||||
if (element_backend_id != backend_id) {
|
||||
delete result;
|
||||
throw ifcopenshell::exception("nary_union requires shapes from the same geometry backend");
|
||||
}
|
||||
auto next = result->add(arg1);
|
||||
if (!next) {
|
||||
delete result;
|
||||
throw ifcopenshell::exception("nary_union failed for backend " + backend_id);
|
||||
}
|
||||
delete result;
|
||||
result = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
throw ifcopenshell::exception("nary_union requires at least one shape");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
%}
|
||||
|
||||
%extend IfcGeom::ConversionResultShape {
|
||||
std::string serialize_obj() {
|
||||
ifcopenshell::geometry::Settings settings;
|
||||
std::unique_ptr<IfcGeom::Representation::Triangulation> triangulation($self->Triangulate(settings));
|
||||
std::ostringstream result;
|
||||
|
||||
for (auto it = triangulation->verts().begin(); it != triangulation->verts().end();) {
|
||||
result << "v " << *(it++) << " " << *(it++) << " " << *(it++) << "\n";
|
||||
}
|
||||
for (auto it = triangulation->normals().begin(); it != triangulation->normals().end();) {
|
||||
result << "vn " << *(it++) << " " << *(it++) << " " << *(it++) << "\n";
|
||||
}
|
||||
|
||||
const bool has_normals = !triangulation->normals().empty();
|
||||
for (auto it = triangulation->faces().begin(); it != triangulation->faces().end();) {
|
||||
const auto v1 = *(it++) + 1;
|
||||
const auto v2 = *(it++) + 1;
|
||||
const auto v3 = *(it++) + 1;
|
||||
if (has_normals) {
|
||||
result << "f "
|
||||
<< v1 << "//" << v1 << " "
|
||||
<< v2 << "//" << v2 << " "
|
||||
<< v3 << "//" << v3 << "\n";
|
||||
} else {
|
||||
result << "f " << v1 << " " << v2 << " " << v3 << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void convex_tag(bool b) {
|
||||
(void)b;
|
||||
throw ifcopenshell::exception("convex_tag is not available through the generic conversion result interface");
|
||||
}
|
||||
|
||||
std::string serialize() {
|
||||
std::string result;
|
||||
@@ -1045,28 +1045,29 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
r = $self->solid();
|
||||
Py_END_ALLOW_THREADS;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IFOPSH_WITH_CGAL
|
||||
|
||||
%ignore hlr_writer;
|
||||
%ignore hlr_calc;
|
||||
%ignore occt_join;
|
||||
%ignore prefiltered_hlr;
|
||||
%ignore svgfill::svg_to_line_segments;
|
||||
%ignore svgfill::line_segments_to_polygons;
|
||||
%ignore svgfill::svg_to_polygons;
|
||||
%ignore svgfill::arrange_polygons;
|
||||
|
||||
%template(svg_line_segments) std::vector<std::array<svgfill::point_2, 2>>;
|
||||
%template(svg_groups_of_line_segments) std::vector<std::vector<std::array<svgfill::point_2, 2>>>;
|
||||
%template(svg_point) std::array<double, 2>;
|
||||
%template(line_segment) std::array<svgfill::point_2, 2>;
|
||||
%template(svg_polygons) std::vector<svgfill::polygon_2>;
|
||||
%template(svg_groups_of_polygons) std::vector<std::vector<svgfill::polygon_2>>;
|
||||
%template(svg_loop) std::vector<std::array<double, 2>>;
|
||||
%template(svg_loops) std::vector<std::vector<std::array<double, 2>>>;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IFOPSH_WITH_CGAL
|
||||
|
||||
%ignore hlr_writer;
|
||||
%ignore hlr_calc;
|
||||
%ignore occt_join;
|
||||
%ignore prefiltered_hlr;
|
||||
%ignore svgfill::svg_to_line_segments;
|
||||
%ignore svgfill::line_segments_to_polygons;
|
||||
%ignore svgfill::svg_to_polygons;
|
||||
%ignore svgfill::arrange_polygons;
|
||||
%ignore svgfill::abstract_arrangement;
|
||||
|
||||
%template(svg_line_segments) std::vector<std::array<svgfill::point_2, 2>>;
|
||||
%template(svg_groups_of_line_segments) std::vector<std::vector<std::array<svgfill::point_2, 2>>>;
|
||||
%template(svg_point) std::array<double, 2>;
|
||||
%template(line_segment) std::array<svgfill::point_2, 2>;
|
||||
%template(svg_polygons) std::vector<svgfill::polygon_2>;
|
||||
%template(svg_groups_of_polygons) std::vector<std::vector<svgfill::polygon_2>>;
|
||||
%template(svg_loop) std::vector<std::array<double, 2>>;
|
||||
%template(svg_loops) std::vector<std::vector<std::array<double, 2>>>;
|
||||
|
||||
%naturalvar svgfill::polygon_2::boundary;
|
||||
%naturalvar svgfill::polygon_2::inner_boundaries;
|
||||
@@ -1102,9 +1103,9 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<svgfill::polygon_2> arrange_polygons(const std::vector<svgfill::polygon_2>& polygons) {
|
||||
std::vector<svgfill::polygon_2> arrange_polygons(svgfill::arrange_polygon_settings settings, svgfill::arrange_polygon_settings settings, const std::vector<svgfill::polygon_2>& polygons) {
|
||||
std::vector<svgfill::polygon_2> r;
|
||||
if (svgfill::arrange_polygons(polygons, r)) {
|
||||
if (svgfill::arrange_polygons(settings, polygons, r)) {
|
||||
return r;
|
||||
} else {
|
||||
throw std::runtime_error("Failed to arrange polygons");
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
%ignore FloatingPointDigits;
|
||||
%ignore BaseUri;
|
||||
%ignore WktUseSection;
|
||||
%ignore SeparateZUpNode;
|
||||
// ConversionSettings.h
|
||||
%ignore MesherLinearDeflection;
|
||||
%ignore MesherAngularDeflection;
|
||||
@@ -157,11 +158,11 @@
|
||||
%ignore CgalEmitOriginalEdges;
|
||||
%ignore OcctNoCleanTriangulation;
|
||||
%ignore CacheShapes;
|
||||
%ignore MakeVolume;
|
||||
%ignore DeferProcessingFirstElement;
|
||||
%ignore MaxOffset;
|
||||
%ignore MaxOffsetDeviation;
|
||||
%ignore ApplyOffset;
|
||||
%ignore SeparateZUpNode;
|
||||
|
||||
// Triangulated representation helper struct
|
||||
%ignore EdgeKey;
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
|
||||
bool check_aggregate_of_type(PyObject* aggregate, void* type_obj) {
|
||||
if (!PySequence_Check(aggregate)) return false;
|
||||
if (PySequence_Size(aggregate) == -1) return false;
|
||||
for(Py_ssize_t i = 0; i < PySequence_Size(aggregate); ++i) {
|
||||
PyObject* element = PySequence_GetItem(aggregate, i);
|
||||
// This is equivalent to the PyFloat_CheckExact macro. This means
|
||||
@@ -69,6 +70,7 @@
|
||||
|
||||
bool check_aggregate_of_aggregate_of_type(PyObject* aggregate, void* type_obj) {
|
||||
if (!PySequence_Check(aggregate)) return false;
|
||||
if (PySequence_Size(aggregate) == -1) return false;
|
||||
for(Py_ssize_t i = 0; i < PySequence_Size(aggregate); ++i) {
|
||||
PyObject* element = PySequence_GetItem(aggregate, i);
|
||||
bool b = check_aggregate_of_type(element, type_obj);
|
||||
|
||||
Reference in New Issue
Block a user