mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-19 11:43:53 +00:00
Work towards v1.0 data model with encapsulated weak_ptr as basis for instances
This commit is contained in:
+96
-120
@@ -104,18 +104,18 @@ std::pair<char const*, size_t> vector_to_buffer(const T& t) {
|
||||
|
||||
%ignore ifcopenshell::geometry::taxonomy::item::print;
|
||||
|
||||
%typemap(out) boost::variant<boost::blank, ifcopenshell::geometry::taxonomy::point3::ptr, double> {
|
||||
if ($1.which() == 0) {
|
||||
%typemap(out) std::variant<boost::blank, ifcopenshell::geometry::taxonomy::point3::ptr, double> {
|
||||
if ($1.index() == 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
} else if ($1.which() == 1) {
|
||||
return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<ifcopenshell::geometry::taxonomy::point3>(boost::get<ifcopenshell::geometry::taxonomy::point3::ptr>($1))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__point3_t, 0 | SWIG_POINTER_OWN);
|
||||
} else if ($1.index() == 1) {
|
||||
return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<ifcopenshell::geometry::taxonomy::point3>(std::get<ifcopenshell::geometry::taxonomy::point3::ptr>($1))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__point3_t, 0 | SWIG_POINTER_OWN);
|
||||
} else {
|
||||
return PyFloat_FromDouble(boost::get<double>($1));
|
||||
return PyFloat_FromDouble(std::get<double>($1));
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(out) boost::optional<bool> {
|
||||
%typemap(out) std::optional<bool> {
|
||||
if ($1) {
|
||||
$result = PyBool_FromLong(*$1 ? 1 : 0);
|
||||
} else {
|
||||
@@ -279,14 +279,10 @@ namespace {
|
||||
|
||||
%extend ifcopenshell::geometry::taxonomy::style {
|
||||
size_t instance_id() const {
|
||||
if (self->instance == nullptr) {
|
||||
if (!self->instance) {
|
||||
return 0;
|
||||
}
|
||||
const IfcUtil::IfcBaseEntity* ent;
|
||||
if ((ent = self->instance->as<IfcUtil::IfcBaseEntity>()) == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return ent->id();
|
||||
return self->instance.id();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,63 +447,47 @@ assign_matrix_access(revolve);
|
||||
|
||||
%extend IfcGeom::tree {
|
||||
|
||||
static aggregate_of_instance::ptr vector_to_list(const std::vector<const IfcUtil::IfcBaseEntity*>& ps) {
|
||||
aggregate_of_instance::ptr r(new aggregate_of_instance);
|
||||
for (auto it = ps.begin(); it != ps.end(); ++it) {
|
||||
// @todo
|
||||
r->push(const_cast<IfcUtil::IfcBaseEntity*>(*it));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
aggregate_of_instance::ptr select_box(IfcUtil::IfcBaseClass* e, bool completely_within = false, double extend=-1.e-5) const {
|
||||
if (!e->declaration().is("IfcProduct")) {
|
||||
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 IfcParse::IfcException("Instance should be an IfcProduct");
|
||||
}
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> ps = $self->select_box((IfcUtil::IfcBaseEntity*)e, completely_within, extend);
|
||||
return IfcGeom_tree_vector_to_list(ps);
|
||||
return cast_vector<express::Base>($self->select_box(e.as<express::Entity>(), completely_within, extend));
|
||||
}
|
||||
|
||||
aggregate_of_instance::ptr select_box(const gp_Pnt& p) const {
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> ps = $self->select_box(p);
|
||||
return IfcGeom_tree_vector_to_list(ps);
|
||||
std::vector<express::Base> select_box(const gp_Pnt& p) const {
|
||||
return cast_vector<express::Base>($self->select_box(p));
|
||||
}
|
||||
|
||||
aggregate_of_instance::ptr select_box(const Bnd_Box& b, bool completely_within = false) const {
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> ps = $self->select_box(b, completely_within);
|
||||
return IfcGeom_tree_vector_to_list(ps);
|
||||
std::vector<express::Base> select_box(const Bnd_Box& b, bool completely_within = false) const {
|
||||
return cast_vector<express::Base>($self->select_box(b, completely_within));
|
||||
}
|
||||
|
||||
aggregate_of_instance::ptr select(IfcUtil::IfcBaseClass* e, bool completely_within = false, double extend = 0.0) const {
|
||||
if (!e->declaration().is("IfcProduct")) {
|
||||
std::vector<express::Base> select(const express::Base& e, bool completely_within = false, double extend = 0.0) const {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw IfcParse::IfcException("Instance should be an IfcProduct");
|
||||
}
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> ps = $self->select((IfcUtil::IfcBaseEntity*)e, completely_within, extend);
|
||||
return IfcGeom_tree_vector_to_list(ps);
|
||||
return cast_vector<express::Base>($self->select(e.as<express::Entity>(), completely_within, extend));
|
||||
}
|
||||
|
||||
aggregate_of_instance::ptr select(const gp_Pnt& p, double extend=0.0) const {
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> ps = $self->select(p, extend);
|
||||
return IfcGeom_tree_vector_to_list(ps);
|
||||
std::vector<express::Base> select(const gp_Pnt& p, double extend=0.0) const {
|
||||
return cast_vector<express::Base>($self->select(p, extend));
|
||||
}
|
||||
|
||||
aggregate_of_instance::ptr select(const std::string& shape_serialization, bool completely_within = false, double extend = -1.e-5) const {
|
||||
std::vector<express::Base> select(const std::string& shape_serialization, bool completely_within = false, double extend = -1.e-5) const {
|
||||
std::stringstream stream(shape_serialization);
|
||||
BRepTools_ShapeSet shapes;
|
||||
shapes.Read(stream);
|
||||
const TopoDS_Shape& shp = shapes.Shape(shapes.NbShapes());
|
||||
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> ps = $self->select(shp, completely_within, extend);
|
||||
return IfcGeom_tree_vector_to_list(ps);
|
||||
return cast_vector<express::Base>($self->select(shp, completely_within, extend));
|
||||
}
|
||||
|
||||
aggregate_of_instance::ptr select(const IfcGeom::BRepElement* elem, bool completely_within = false, double extend = -1.e-5) const {
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> ps = $self->select(elem, completely_within, extend);
|
||||
return IfcGeom_tree_vector_to_list(ps);
|
||||
std::vector<express::Base> select(const IfcGeom::BRepElement* elem, bool completely_within = false, double extend = -1.e-5) const {
|
||||
return cast_vector<express::Base>($self->select(elem, completely_within, extend));
|
||||
}
|
||||
|
||||
|
||||
%typemap(in) const std::vector<IfcUtil::IfcBaseClass*>& (std::vector<IfcUtil::IfcBaseClass*> temp) {
|
||||
/*
|
||||
%typemap(in) const std::vector<express::Base>& (std::vector<express::Base> temp) {
|
||||
if (!PyList_Check($input)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expected a list.");
|
||||
return NULL;
|
||||
@@ -517,65 +497,66 @@ assign_matrix_access(revolve);
|
||||
for (Py_ssize_t i = 0; i < PyList_Size($input); ++i) {
|
||||
PyObject* pyObj = PyList_GetItem($input, i);
|
||||
void* ptr = 0;
|
||||
int res = SWIG_ConvertPtr(pyObj, &ptr, SWIGTYPE_p_IfcUtil__IfcBaseClass, 0);
|
||||
int res = SWIG_ConvertPtr(pyObj, &ptr, SWIGTYPE_p_express__Base, 0);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
PyErr_SetString(PyExc_TypeError, "List item is not of type IfcBaseClass.");
|
||||
return NULL;
|
||||
}
|
||||
temp.push_back(reinterpret_cast<IfcUtil::IfcBaseClass*>(ptr));
|
||||
temp.push_back(reinterpret_cast<express::Base>(ptr));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
std::vector<clash> clash_intersection_many(const std::vector<IfcUtil::IfcBaseClass*>& set_a, const std::vector<IfcUtil::IfcBaseClass*>& set_b, double tolerance, bool check_all) const {
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> set_a_entities;
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> set_b_entities;
|
||||
for (auto* e : set_a) {
|
||||
if (!e->declaration().is("IfcProduct")) {
|
||||
std::vector<clash> clash_intersection_many(const std::vector<express::Base>& set_a, const std::vector<express::Base>& set_b, double tolerance, bool check_all) const {
|
||||
std::vector<express::Entity> set_a_entities;
|
||||
std::vector<express::Entity> set_b_entities;
|
||||
for (auto& e : set_a) {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw IfcParse::IfcException("All instances should be of type IfcProduct");
|
||||
}
|
||||
set_a_entities.push_back(static_cast<IfcUtil::IfcBaseEntity*>(e));
|
||||
set_a_entities.push_back(e.as<express::Entity>());
|
||||
}
|
||||
for (auto* e : set_b) {
|
||||
if (!e->declaration().is("IfcProduct")) {
|
||||
for (auto& e : set_b) {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw IfcParse::IfcException("All instances should be of type IfcProduct");
|
||||
}
|
||||
set_b_entities.push_back(static_cast<IfcUtil::IfcBaseEntity*>(e));
|
||||
set_b_entities.push_back(e.as<express::Entity>());
|
||||
}
|
||||
return $self->clash_intersection_many(set_a_entities, set_b_entities, tolerance, check_all);
|
||||
}
|
||||
|
||||
std::vector<clash> clash_collision_many(const std::vector<IfcUtil::IfcBaseClass*>& set_a, const std::vector<IfcUtil::IfcBaseClass*>& set_b, bool allow_touching) const {
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> set_a_entities;
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> set_b_entities;
|
||||
for (auto* e : set_a) {
|
||||
if (!e->declaration().is("IfcProduct")) {
|
||||
std::vector<clash> clash_collision_many(const std::vector<express::Base>& set_a, const std::vector<express::Base>& set_b, bool allow_touching) const {
|
||||
std::vector<express::Entity> set_a_entities;
|
||||
std::vector<express::Entity> set_b_entities;
|
||||
for (auto& e : set_a) {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw IfcParse::IfcException("All instances should be of type IfcProduct");
|
||||
}
|
||||
set_a_entities.push_back(static_cast<IfcUtil::IfcBaseEntity*>(e));
|
||||
set_a_entities.push_back(e.as<express::Entity>());
|
||||
}
|
||||
for (auto* e : set_b) {
|
||||
if (!e->declaration().is("IfcProduct")) {
|
||||
for (auto& e : set_b) {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw IfcParse::IfcException("All instances should be of type IfcProduct");
|
||||
}
|
||||
set_b_entities.push_back(static_cast<IfcUtil::IfcBaseEntity*>(e));
|
||||
set_b_entities.push_back(e.as<express::Entity>());
|
||||
}
|
||||
return $self->clash_collision_many(set_a_entities, set_b_entities, allow_touching);
|
||||
}
|
||||
|
||||
std::vector<clash> clash_clearance_many(const std::vector<IfcUtil::IfcBaseClass*>& set_a, const std::vector<IfcUtil::IfcBaseClass*>& set_b, double clearance, bool check_all) const {
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> set_a_entities;
|
||||
std::vector<const IfcUtil::IfcBaseEntity*> set_b_entities;
|
||||
for (auto* e : set_a) {
|
||||
if (!e->declaration().is("IfcProduct")) {
|
||||
std::vector<clash> clash_clearance_many(const std::vector<express::Base>& set_a, const std::vector<express::Base>& set_b, double clearance, bool check_all) const {
|
||||
std::vector<express::Entity> set_a_entities;
|
||||
std::vector<express::Entity> set_b_entities;
|
||||
for (auto& e : set_a) {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw IfcParse::IfcException("All instances should be of type IfcProduct");
|
||||
}
|
||||
set_a_entities.push_back(static_cast<IfcUtil::IfcBaseEntity*>(e));
|
||||
set_a_entities.push_back(e.as<express::Entity>());
|
||||
}
|
||||
for (auto* e : set_b) {
|
||||
if (!e->declaration().is("IfcProduct")) {
|
||||
for (auto& e : set_b) {
|
||||
if (!e.declaration().is("IfcProduct")) {
|
||||
throw IfcParse::IfcException("All instances should be of type IfcProduct");
|
||||
}
|
||||
set_b_entities.push_back(static_cast<IfcUtil::IfcBaseEntity*>(e));
|
||||
set_b_entities.push_back(e.as<express::Entity>());
|
||||
}
|
||||
return $self->clash_clearance_many(set_a_entities, set_b_entities, clearance, check_all);
|
||||
}
|
||||
@@ -624,9 +605,9 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
%}
|
||||
|
||||
// Note that these elements ARE to be owned by SWIG/Python
|
||||
%typemap(out) boost::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> {
|
||||
%typemap(out) std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> {
|
||||
// See which type is set and return appropriate
|
||||
$result = boost::apply_visitor(ShapeRTTI(), (boost::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*>) $1);
|
||||
$result = std::visit(ShapeRTTI(), (std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*>) $1);
|
||||
}
|
||||
|
||||
%newobject construct_iterator;
|
||||
@@ -773,7 +754,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
return { reinterpret_cast<const char*>(data), 16 * sizeof(double) };
|
||||
}
|
||||
|
||||
const IfcUtil::IfcBaseClass* product_() const {
|
||||
const express::Base product_() const {
|
||||
return $self->product();
|
||||
}
|
||||
|
||||
@@ -882,40 +863,39 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
}
|
||||
|
||||
template <typename Schema>
|
||||
static boost::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> helper_fn_create_shape(const std::string& geometry_library, ifcopenshell::geometry::Settings& st, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0) {
|
||||
IfcParse::IfcFile* file = instance->file_;
|
||||
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()) {
|
||||
IfcParse::IfcFile* file = instance.data()->file();
|
||||
|
||||
ifcopenshell::geometry::Converter kernel(ifcopenshell::geometry::kernels::construct(file, geometry_library, st), file, st);
|
||||
|
||||
if (typename Schema::IfcProduct* product = instance->as<typename Schema::IfcProduct>()) {
|
||||
if (auto product = instance.as<typename Schema::IfcProduct>()) {
|
||||
if (representation) {
|
||||
if (!representation->declaration().is(Schema::IfcRepresentation::Class())) {
|
||||
if (!representation.declaration().is(Schema::IfcRepresentation::Class())) {
|
||||
throw IfcParse::IfcException("Supplied representation not of type IfcRepresentation");
|
||||
}
|
||||
}
|
||||
|
||||
if (!representation && !product->Representation()) {
|
||||
if (!representation && !product.Representation()) {
|
||||
throw IfcParse::IfcException("Representation is NULL");
|
||||
}
|
||||
|
||||
typename Schema::IfcProductRepresentation* prodrep = product->Representation();
|
||||
typename Schema::IfcRepresentation::list::ptr reps = prodrep->Representations();
|
||||
typename Schema::IfcRepresentation* ifc_representation = representation ? representation->as<typename Schema::IfcRepresentation>() : nullptr;
|
||||
auto prodrep = product.Representation();
|
||||
auto reps = prodrep.Representations();
|
||||
auto ifc_representation = representation ? representation.as<typename Schema::IfcRepresentation>() : Schema::IfcRepresentation();
|
||||
|
||||
if (!ifc_representation) {
|
||||
// First, try to find a representation based on the settings
|
||||
for (typename Schema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
|
||||
typename Schema::IfcRepresentation* rep = *it;
|
||||
if (!rep->RepresentationIdentifier()) {
|
||||
for (auto& rep : reps) {
|
||||
if (!rep.RepresentationIdentifier()) {
|
||||
continue;
|
||||
}
|
||||
if (st.get<ifcopenshell::geometry::settings::OutputDimensionality>().get() != ifcopenshell::geometry::settings::CURVES) {
|
||||
if (*rep->RepresentationIdentifier() == "Body" || *rep->RepresentationIdentifier() == "Facetation") {
|
||||
if (*rep.RepresentationIdentifier() == "Body" || *rep.RepresentationIdentifier() == "Facetation") {
|
||||
ifc_representation = rep;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (*rep->RepresentationIdentifier() == "Plan" || *rep->RepresentationIdentifier() == "Axis") {
|
||||
if (*rep.RepresentationIdentifier() == "Plan" || *rep.RepresentationIdentifier() == "Axis") {
|
||||
ifc_representation = rep;
|
||||
break;
|
||||
}
|
||||
@@ -925,12 +905,11 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
|
||||
// Otherwise, find a representation within the 'Model' or 'Plan' context
|
||||
if (!ifc_representation) {
|
||||
for (typename Schema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
|
||||
typename Schema::IfcRepresentation* rep = *it;
|
||||
typename Schema::IfcRepresentationContext* context = rep->ContextOfItems();
|
||||
for (auto& rep : reps) {
|
||||
auto context = rep.ContextOfItems();
|
||||
|
||||
// TODO: Remove redundancy with IfcGeomIterator.h
|
||||
if (context->ContextType()) {
|
||||
if (context.ContextType()) {
|
||||
std::set<std::string> context_types;
|
||||
if (st.get<ifcopenshell::geometry::settings::OutputDimensionality>().get() != ifcopenshell::geometry::settings::CURVES) {
|
||||
context_types.insert("model");
|
||||
@@ -941,7 +920,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
context_types.insert("plan");
|
||||
}
|
||||
|
||||
std::string context_type_lc = *context->ContextType();
|
||||
std::string context_type_lc = *context.ContextType();
|
||||
for (std::string::iterator c = context_type_lc.begin(); c != context_type_lc.end(); ++c) {
|
||||
*c = tolower(*c);
|
||||
}
|
||||
@@ -953,9 +932,9 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
}
|
||||
|
||||
if (!ifc_representation) {
|
||||
if (reps->size()) {
|
||||
if (reps.size()) {
|
||||
// Return a random representation
|
||||
ifc_representation = *reps->begin();
|
||||
ifc_representation = reps.front();
|
||||
} else {
|
||||
throw IfcParse::IfcException("No suitable IfcRepresentation found");
|
||||
}
|
||||
@@ -964,8 +943,8 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
IfcGeom::BRepElement* brep = kernel.create_brep_for_representation_and_product(ifc_representation, product);
|
||||
if (!brep) {
|
||||
std::ostringstream oss_repr, oss_product;
|
||||
ifc_representation->toString(oss_repr);
|
||||
product->toString(oss_product);
|
||||
ifc_representation.toString(oss_repr);
|
||||
product.toString(oss_product);
|
||||
throw IfcParse::IfcException("Failed to process shape. Product: " + oss_product.str() + ", representation: " + oss_repr.str());
|
||||
}
|
||||
if (st.get<ifcopenshell::geometry::settings::IteratorOutput>().get() == ifcopenshell::geometry::settings::SERIALIZED) {
|
||||
@@ -979,7 +958,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
} else {
|
||||
return brep;
|
||||
}
|
||||
} else if (instance->as<typename Schema::IfcPlacement>() != nullptr || instance->as<typename Schema::IfcObjectPlacement>()) {
|
||||
} else if (instance.as<typename Schema::IfcPlacement>() || instance.as<typename Schema::IfcObjectPlacement>()) {
|
||||
auto item = ifcopenshell::geometry::taxonomy::cast<ifcopenshell::geometry::taxonomy::matrix4>(kernel.mapping()->map(instance));
|
||||
if (item == nullptr) {
|
||||
throw IfcParse::IfcException("Failed to convert placement");
|
||||
@@ -993,21 +972,21 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
return new IfcGeom::Transformation(kernel.settings(), item);
|
||||
} else {
|
||||
if (!representation) {
|
||||
if (instance->declaration().is(Schema::IfcRepresentationItem::Class()) ||
|
||||
instance->declaration().is(Schema::IfcRepresentation::Class()) ||
|
||||
if (instance.declaration().is(Schema::IfcRepresentationItem::Class()) ||
|
||||
instance.declaration().is(Schema::IfcRepresentation::Class()) ||
|
||||
// https://github.com/IfcOpenShell/IfcOpenShell/issues/1649
|
||||
instance->declaration().is(Schema::IfcProfileDef::Class())
|
||||
instance.declaration().is(Schema::IfcProfileDef::Class())
|
||||
) {
|
||||
IfcGeom::ConversionResults shapes;
|
||||
try {
|
||||
shapes = kernel.convert(instance);
|
||||
} catch (...) {
|
||||
std::ostringstream oss;
|
||||
instance->toString(oss);
|
||||
instance.toString(oss);
|
||||
throw IfcParse::IfcException("Failed to process shape. Instance: " + oss.str());
|
||||
}
|
||||
|
||||
IfcGeom::Representation::BRep brep(kernel.settings(), instance->declaration().name(), to_locale_invariant_string(instance->as<IfcUtil::IfcBaseEntity>()->id()), shapes);
|
||||
IfcGeom::Representation::BRep brep(kernel.settings(), instance.declaration().name(), to_locale_invariant_string(instance.id()), shapes);
|
||||
try {
|
||||
if (st.get<ifcopenshell::geometry::settings::IteratorOutput>().get() == ifcopenshell::geometry::settings::SERIALIZED) {
|
||||
return new IfcGeom::Representation::Serialization(brep);
|
||||
@@ -1022,7 +1001,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
throw IfcParse::IfcException("Invalid additional representation specified");
|
||||
}
|
||||
}
|
||||
return boost::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*>();
|
||||
return std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*>();
|
||||
}
|
||||
%}
|
||||
|
||||
@@ -1054,18 +1033,15 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
ifcopenshell::geometry::taxonomy::item::ptr map_shape(ifcopenshell::geometry::Settings& settings, IfcUtil::IfcBaseClass* instance) {
|
||||
if (instance->file_ == nullptr) {
|
||||
throw std::runtime_error("Unable to map instance without file");
|
||||
}
|
||||
std::unique_ptr<ifcopenshell::geometry::abstract_mapping> mapping(ifcopenshell::geometry::impl::mapping_implementations().construct(instance->file_, settings));
|
||||
ifcopenshell::geometry::taxonomy::item::ptr map_shape(ifcopenshell::geometry::Settings& settings, const express::Base& instance) {
|
||||
std::unique_ptr<ifcopenshell::geometry::abstract_mapping> mapping(ifcopenshell::geometry::impl::mapping_implementations().construct(instance.data()->file(), settings));
|
||||
return mapping->map(instance);
|
||||
}
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
static boost::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> create_shape(ifcopenshell::geometry::Settings& settings, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0, const char* const geometry_library="opencascade") {
|
||||
const std::string& schema_name = instance->declaration().schema()->name();
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> create_shape(ifcopenshell::geometry::Settings& settings, const express::Base& instance, const express::Base& representation = express::Base(), const char* const geometry_library="opencascade") {
|
||||
const std::string& schema_name = instance.declaration().schema()->name();
|
||||
|
||||
#ifdef HAS_SCHEMA_2x3
|
||||
if (schema_name == "IFC2X3") {
|
||||
@@ -1135,22 +1111,22 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
||||
|
||||
%inline %{
|
||||
IfcUtil::IfcBaseClass* serialise(const std::string& schema_name, const std::string& shape_str, bool advanced=true) {
|
||||
express::Base serialise(IfcParse::IfcFile& 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(schema_name, shp, advanced);
|
||||
return IfcGeom::serialise(f, shp, advanced);
|
||||
}
|
||||
|
||||
IfcUtil::IfcBaseClass* tesselate(const std::string& schema_name, const std::string& shape_str, double d) {
|
||||
express::Base tesselate(IfcParse::IfcFile& f, const std::string& shape_str, double d) {
|
||||
std::stringstream stream(shape_str);
|
||||
BRepTools_ShapeSet shapes;
|
||||
shapes.Read(stream);
|
||||
const TopoDS_Shape& shp = shapes.Shape(shapes.NbShapes());
|
||||
|
||||
return IfcGeom::tesselate(schema_name, shp, d);
|
||||
return IfcGeom::tesselate(f, shp, d);
|
||||
}
|
||||
%}
|
||||
|
||||
@@ -1260,7 +1236,7 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
%include "../svgfill/src/svgfill.h"
|
||||
|
||||
%inline %{
|
||||
std::vector<std::vector<svgfill::line_segment_2>> svg_to_line_segments(const std::string& data, const boost::optional<std::string>& class_name) {
|
||||
std::vector<std::vector<svgfill::line_segment_2>> svg_to_line_segments(const std::string& data, const std::optional<std::string>& class_name) {
|
||||
std::vector<std::vector<svgfill::line_segment_2>> r;
|
||||
if (svgfill::svg_to_line_segments(data, class_name, r)) {
|
||||
return r;
|
||||
@@ -1278,7 +1254,7 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<svgfill::polygon_2> svg_to_polygons(const std::string& data, const boost::optional<std::string>& class_name) {
|
||||
std::vector<svgfill::polygon_2> svg_to_polygons(const std::string& data, const std::optional<std::string>& class_name) {
|
||||
std::vector<svgfill::polygon_2> r;
|
||||
if (svgfill::svg_to_polygons(data, class_name, r)) {
|
||||
return r;
|
||||
|
||||
+427
-242
@@ -17,13 +17,6 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
// A class declaration to silence SWIG warning about base classes being
|
||||
// undefined, the constructor is private so that SWIG does not wrap them
|
||||
class IfcEntityInstanceData {
|
||||
private:
|
||||
IfcEntityInstanceData();
|
||||
};
|
||||
|
||||
%ignore IfcParse::IfcFile::register_inverse;
|
||||
%ignore IfcParse::IfcFile::unregister_inverse;
|
||||
%ignore IfcParse::IfcFile::schema;
|
||||
@@ -43,6 +36,10 @@ private:
|
||||
%ignore IfcParse::InstanceStreamer::readInstance;
|
||||
%ignore IfcParse::InstanceStreamer::stealInstances;
|
||||
|
||||
%ignore express::Entity;
|
||||
%ignore express::Select;
|
||||
%ignore express::DeclaredType;
|
||||
|
||||
%ignore in_memory_file_storage;
|
||||
%ignore rocks_db_file_storage;
|
||||
// Available as get_inverse().
|
||||
@@ -68,17 +65,18 @@ private:
|
||||
|
||||
%ignore IfcParse::IfcFile::type_iterator;
|
||||
|
||||
%ignore IfcUtil::IfcBaseClass::is;
|
||||
%ignore express::Base::is;
|
||||
|
||||
%rename("by_id") instance_by_id;
|
||||
%rename("by_guid") instance_by_guid;
|
||||
%rename("by_type") instances_by_type;
|
||||
%rename("by_type_excl_subtypes") instances_by_type_excl_subtypes;
|
||||
%rename("_by_type") instances_by_type;
|
||||
%rename("_by_type_excl_subtypes") instances_by_type_excl_subtypes;
|
||||
%rename("get_inverses_by_declaration") getInverse;
|
||||
%rename("get_total_inverses_by_id") getTotalInverses;
|
||||
%rename("entity_instance") IfcBaseClass;
|
||||
%rename("entity_instance") express::Base;
|
||||
%rename("file") IfcFile;
|
||||
%rename("add") addEntity;
|
||||
// _add() because mixin defined add which adds transaction logic
|
||||
%rename("_add") addEntity;
|
||||
%rename("remove") removeEntity;
|
||||
|
||||
class attribute_value_derived {};
|
||||
@@ -120,16 +118,17 @@ static const std::string& helper_fn_declaration_get_name(const IfcParse::declara
|
||||
return decl->name();
|
||||
}
|
||||
|
||||
static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClass* inst, unsigned i) {
|
||||
static IfcUtil::ArgumentType helper_fn_attribute_type(const express::Base* instp, unsigned i) {
|
||||
const auto& inst = *instp;
|
||||
const IfcParse::parameter_type* pt = 0;
|
||||
if (inst->declaration().as_entity()) {
|
||||
pt = inst->declaration().as_entity()->attribute_by_index(i)->type_of_attribute();
|
||||
if (inst->declaration().as_entity()->derived()[i]) {
|
||||
if (inst.declaration().as_entity()) {
|
||||
pt = inst.declaration().as_entity()->attribute_by_index(i)->type_of_attribute();
|
||||
if (inst.declaration().as_entity()->derived()[i]) {
|
||||
return IfcUtil::Argument_DERIVED;
|
||||
}
|
||||
} else if (inst->declaration().as_type_declaration() && i == 0) {
|
||||
pt = inst->declaration().as_type_declaration()->declared_type();
|
||||
} else if (inst->declaration().as_enumeration_type() && i == 0) {
|
||||
} else if (inst.declaration().as_type_declaration() && i == 0) {
|
||||
pt = inst.declaration().as_type_declaration()->declared_type();
|
||||
} else if (inst.declaration().as_enumeration_type() && i == 0) {
|
||||
// Enumeration is always from string in Python
|
||||
return IfcUtil::Argument_STRING;
|
||||
}
|
||||
@@ -190,31 +189,54 @@ private:
|
||||
%newobject IfcParse::IfcFile::key_value_store_iter;
|
||||
|
||||
%extend IfcParse::IfcFile {
|
||||
/*
|
||||
// Use to correlate to entity_instance.file_pointer, so that we
|
||||
// can trace file ownership of instances on the python side.
|
||||
size_t file_pointer() const {
|
||||
return reinterpret_cast<size_t>($self);
|
||||
}
|
||||
*/
|
||||
|
||||
aggregate_of_instance::ptr get_inverse(IfcUtil::IfcBaseClass* e) {
|
||||
if (auto e_ = e->as<IfcUtil::IfcBaseEntity>()) {
|
||||
return $self->getInverse(e_->id(), 0, -1);
|
||||
}
|
||||
throw IfcParse::IfcException("Only entities with ids are supported for get_inverse. Provided entity: '" + e->declaration().name() + "'.");
|
||||
IfcFile(const std::string& schema = "IFC4") {
|
||||
auto resolved_schema = schema;
|
||||
if (resolved_schema == "IFC4X3") {
|
||||
resolved_schema = "IFC4X3_ADD2";
|
||||
}
|
||||
return new IfcParse::IfcFile(IfcParse::schema_by_name(resolved_schema));
|
||||
}
|
||||
|
||||
std::vector<int> get_inverse_indices(IfcUtil::IfcBaseClass* e) {
|
||||
if (auto e_ = e->as<IfcUtil::IfcBaseEntity>()) {
|
||||
return $self->get_inverse_indices(e_->id());
|
||||
}
|
||||
throw IfcParse::IfcException("Only entities with ids are supported for get_inverse_indices. Provided entity: '" + e->declaration().name() + "'.");
|
||||
IfcFile(const std::vector<int>& schema_version) {
|
||||
static const char* prefixes[] = { "IFC", "X", "_ADD", "_TC" };
|
||||
|
||||
std::string resolved_schema;
|
||||
for (size_t i = 0; i < schema_version.size() && i < 4; ++i) {
|
||||
if (schema_version[i] != 0) {
|
||||
resolved_schema += prefixes[i];
|
||||
resolved_schema += std::to_string(schema_version[i]);
|
||||
}
|
||||
}
|
||||
return new IfcParse::IfcFile(IfcParse::schema_by_name(resolved_schema));
|
||||
}
|
||||
|
||||
int get_total_inverses(IfcUtil::IfcBaseClass* e) {
|
||||
if (auto e_ = e->as<IfcUtil::IfcBaseEntity>()) {
|
||||
return $self->getTotalInverses(e_->id());
|
||||
std::vector<express::Base> get_inverse(const express::Base& e) {
|
||||
if (auto e_ = e.as<express::Entity>()) {
|
||||
return cast_vector<express::Base>($self->getInverse(e_.id(), 0, -1));
|
||||
}
|
||||
throw IfcParse::IfcException("Only entities with ids are supported for get_total_inverses. Provided entity: '" + e->declaration().name() + "'.");
|
||||
throw IfcParse::IfcException("Only entities with ids are supported for get_inverse. Provided entity: '" + e.declaration().name() + "'.");
|
||||
}
|
||||
|
||||
std::vector<int> get_inverse_indices(const express::Base& e) {
|
||||
if (auto e_ = e.as<express::Entity>()) {
|
||||
return $self->get_inverse_indices(e_.id());
|
||||
}
|
||||
throw IfcParse::IfcException("Only entities with ids are supported for get_inverse_indices. Provided entity: '" + e.declaration().name() + "'.");
|
||||
}
|
||||
|
||||
int get_total_inverses(const express::Base& e) {
|
||||
if (auto e_ = e.as<express::Entity>()) {
|
||||
return $self->getTotalInverses(e_.id());
|
||||
}
|
||||
throw IfcParse::IfcException("Only entities with ids are supported for get_total_inverses. Provided entity: '" + e.declaration().name() + "'.");
|
||||
}
|
||||
|
||||
void write(const std::string& fn) {
|
||||
@@ -231,6 +253,14 @@ private:
|
||||
return s.str();
|
||||
}
|
||||
|
||||
express::Base create(const std::string& entity_name) {
|
||||
const IfcParse::declaration* decl = $self->schema()->declaration_by_name(entity_name);
|
||||
if (!decl || !decl->as_entity()) {
|
||||
throw IfcParse::IfcException("No such entity declaration: '" + entity_name + "' in schema '" + $self->schema()->name());
|
||||
}
|
||||
return $self->create(decl);
|
||||
}
|
||||
|
||||
std::vector<unsigned> entity_names() const {
|
||||
std::vector<unsigned> keys;
|
||||
keys.reserve(std::distance($self->begin(), $self->end()));
|
||||
@@ -312,19 +342,28 @@ private:
|
||||
|
||||
%pythoncode %{
|
||||
schema = property(schema_name)
|
||||
|
||||
old_init = __init__
|
||||
def __init__(self, schema=None, schema_version=None):
|
||||
self.old_init(*filter(None, (schema, schema_version)))
|
||||
self.post_init()
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcUtil::IfcBaseClass {
|
||||
%extend express::Base {
|
||||
|
||||
%pythoncode %{
|
||||
# Will be assigned when `ifcopenshell.entity_instance` is created.
|
||||
file = None
|
||||
%}
|
||||
|
||||
// 0 = not found
|
||||
// 1 = regular forward attribute
|
||||
// 2 = inverse attribute
|
||||
// 3 = derived attribute (redeclared in subtype as derived)
|
||||
int get_attribute_category(const std::string& name) const {
|
||||
if (!$self->declaration().as_entity()) {
|
||||
return name == "wrappedValue";
|
||||
return name == "wrappedValue" ? 1 : 0;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -332,7 +371,11 @@ private:
|
||||
std::vector<const IfcParse::attribute*>::const_iterator it = attrs.begin();
|
||||
for (; it != attrs.end(); ++it) {
|
||||
if ((*it)->name() == name) {
|
||||
return 1;
|
||||
if ($self->declaration().as_entity()->derived()[std::distance(attrs.begin(), it)]) {
|
||||
return 3;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,14 +393,18 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@todo determine if we want to reinstante id() availability only on Entity instances.
|
||||
|
||||
// id() is defined on IfcBaseEntity and not on IfcBaseClass, in order
|
||||
// to expose it to the Python wrapper it is simply duplicated here.
|
||||
// Same applies to the two methods reimplemented below.
|
||||
int id() const {
|
||||
return $self->as<IfcUtil::IfcBaseEntity>() != nullptr
|
||||
? $self->as<IfcUtil::IfcBaseEntity>()->id()
|
||||
return $self->as<express::Base>() != nullptr
|
||||
? $self->as<express::Base>()->id()
|
||||
: 0;
|
||||
}
|
||||
*/
|
||||
|
||||
int __len__() const {
|
||||
if ($self->declaration().as_entity()) {
|
||||
@@ -427,8 +474,8 @@ private:
|
||||
return $self->get_attribute_value((unsigned)i);
|
||||
}
|
||||
|
||||
bool __eq__(IfcUtil::IfcBaseClass* other) const {
|
||||
return $self->identity() == other->identity();
|
||||
bool __eq__(const express::Base& other) const {
|
||||
return $self->identity() == other.identity();
|
||||
}
|
||||
|
||||
std::string __repr__() const {
|
||||
@@ -443,10 +490,12 @@ private:
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/*
|
||||
// Just something to have a somewhat sensible value to hash
|
||||
size_t file_pointer() const {
|
||||
return reinterpret_cast<size_t>($self->file_);
|
||||
}
|
||||
*/
|
||||
|
||||
unsigned get_argument_index(const std::string& a) const {
|
||||
if ($self->declaration().as_entity()) {
|
||||
@@ -458,9 +507,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
aggregate_of_instance::ptr get_inverse(const std::string& a) {
|
||||
std::vector<express::Base> get_inverse(const std::string& a) {
|
||||
if ($self->declaration().as_entity()) {
|
||||
return ((IfcUtil::IfcBaseEntity*)$self)->get_inverse(a);
|
||||
return cast_vector<express::Base>($self->as<express::Entity>().get_inverse(a));
|
||||
} else {
|
||||
throw IfcParse::IfcException(a + " not found on " + $self->declaration().name());
|
||||
}
|
||||
@@ -481,153 +530,293 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsNull(unsigned int i) {
|
||||
bool is_optional = $self->declaration().as_entity()->attribute_by_index(i)->optional();
|
||||
if (is_optional) {
|
||||
void set_attribute_value_py(unsigned int i, PyObject* value) {
|
||||
if (value == Py_None) {
|
||||
// @nb we don't check anymore if the attribute is optional here, because it should be
|
||||
// possible to go back to the state at construction time.
|
||||
// bool is_optional = $self->declaration().as_entity()->attribute_by_index(i)->optional();
|
||||
self->set_attribute_value(i, Blank{});
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsInt(unsigned int i, int v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_INT) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else if ( (arg_type == IfcUtil::Argument_BOOL) && ( (v == 0) || (v == 1) ) ) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsBool(unsigned int i, bool v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_BOOL) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsLogical(unsigned int i, boost::logic::tribool v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_LOGICAL) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsDouble(unsigned int i, double v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_DOUBLE) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsString(unsigned int i, const std::string& a) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_STRING) {
|
||||
self->set_attribute_value(i, a);
|
||||
} else if (arg_type == IfcUtil::Argument_ENUMERATION) {
|
||||
const IfcParse::enumeration_type* enum_type = $self->declaration().schema()->declaration_by_name($self->declaration().type())->as_entity()->
|
||||
attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type();
|
||||
self->set_attribute_value(i, EnumerationReference(enum_type, enum_type->lookup_enum_offset(a)));
|
||||
} else if (arg_type == IfcUtil::Argument_BINARY) {
|
||||
if (IfcUtil::valid_binary_string(a)) {
|
||||
boost::dynamic_bitset<> bits(a);
|
||||
self->set_attribute_value(i, bits);
|
||||
} else {
|
||||
throw IfcParse::IfcException("String not a valid binary representation");
|
||||
auto to_index_long = [&](PyObject* o) -> long {
|
||||
PyObject* idx = PyNumber_Index(o); // accepts numpy ints, bools, etc.
|
||||
if (!idx) {
|
||||
PyErr_Clear();
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
long v = PyLong_AsLong(idx);
|
||||
Py_DECREF(idx);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
void setArgumentAsAggregateOfInt(unsigned int i, const std::vector<int>& v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_INT) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
auto to_double = [&](PyObject* o) -> double {
|
||||
double v = PyFloat_AsDouble(o); // accepts ints and float-like objects
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
void setArgumentAsAggregateOfDouble(unsigned int i, const std::vector<double>& v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
auto to_string = [&](PyObject* o) -> std::string {
|
||||
if (PyUnicode_Check(o)) {
|
||||
Py_ssize_t n = 0;
|
||||
const char* s = PyUnicode_AsUTF8AndSize(o, &n);
|
||||
if (!s) {
|
||||
PyErr_Clear();
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
return std::string(s, static_cast<size_t>(n));
|
||||
}
|
||||
if (PyBytes_Check(o)) {
|
||||
char* s = nullptr;
|
||||
Py_ssize_t n = 0;
|
||||
if (PyBytes_AsStringAndSize(o, &s, &n) == -1) {
|
||||
PyErr_Clear();
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
return std::string(s, static_cast<size_t>(n));
|
||||
}
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void setArgumentAsAggregateOfString(unsigned int i, const std::vector<std::string>& v) {
|
||||
auto seq_fast = [&](PyObject* o) -> PyObject* {
|
||||
PyObject* fast = PySequence_Fast(o, "expected a sequence");
|
||||
if (!fast) {
|
||||
PyErr_Clear();
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
return fast; // new ref
|
||||
};
|
||||
|
||||
auto to_vec_int = [&](PyObject* o) -> std::vector<int> {
|
||||
PyObject* fast = seq_fast(o);
|
||||
Py_ssize_t n = PySequence_Fast_GET_SIZE(fast);
|
||||
PyObject** items = PySequence_Fast_ITEMS(fast);
|
||||
|
||||
std::vector<int> out;
|
||||
out.reserve(static_cast<size_t>(n));
|
||||
for (Py_ssize_t k = 0; k < n; ++k) {
|
||||
out.push_back(static_cast<int>(to_index_long(items[k])));
|
||||
}
|
||||
|
||||
Py_DECREF(fast);
|
||||
return out;
|
||||
};
|
||||
|
||||
auto to_vec_double = [&](PyObject* o) -> std::vector<double> {
|
||||
PyObject* fast = seq_fast(o);
|
||||
Py_ssize_t n = PySequence_Fast_GET_SIZE(fast);
|
||||
PyObject** items = PySequence_Fast_ITEMS(fast);
|
||||
|
||||
std::vector<double> out;
|
||||
out.reserve(static_cast<size_t>(n));
|
||||
for (Py_ssize_t k = 0; k < n; ++k) {
|
||||
out.push_back(to_double(items[k]));
|
||||
}
|
||||
|
||||
Py_DECREF(fast);
|
||||
return out;
|
||||
};
|
||||
|
||||
auto to_vec_string = [&](PyObject* o) -> std::vector<std::string> {
|
||||
PyObject* fast = seq_fast(o);
|
||||
Py_ssize_t n = PySequence_Fast_GET_SIZE(fast);
|
||||
PyObject** items = PySequence_Fast_ITEMS(fast);
|
||||
|
||||
std::vector<std::string> out;
|
||||
out.reserve(static_cast<size_t>(n));
|
||||
for (Py_ssize_t k = 0; k < n; ++k) {
|
||||
out.push_back(to_string(items[k]));
|
||||
}
|
||||
|
||||
Py_DECREF(fast);
|
||||
return out;
|
||||
};
|
||||
|
||||
auto to_base = [&](PyObject* o) -> express::Base {
|
||||
void* vp = nullptr;
|
||||
|
||||
// Try non-const pointer first
|
||||
if (swig_type_info* ti = SWIG_TypeQuery("express::Base *")) {
|
||||
int res = SWIG_ConvertPtr(o, &vp, ti, 0);
|
||||
if (res >= 0 && vp) {
|
||||
return *static_cast<express::Base*>(vp);
|
||||
}
|
||||
}
|
||||
|
||||
// Then try const pointer
|
||||
vp = nullptr;
|
||||
if (swig_type_info* ti = SWIG_TypeQuery("express::Base const *")) {
|
||||
int res = SWIG_ConvertPtr(o, &vp, ti, 0);
|
||||
if (res >= 0 && vp) {
|
||||
return *static_cast<const express::Base*>(vp);
|
||||
}
|
||||
}
|
||||
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
};
|
||||
|
||||
auto to_vec_base = [&](PyObject* o) -> std::vector<express::Base> {
|
||||
PyObject* fast = seq_fast(o);
|
||||
Py_ssize_t n = PySequence_Fast_GET_SIZE(fast);
|
||||
PyObject** items = PySequence_Fast_ITEMS(fast);
|
||||
|
||||
std::vector<express::Base> out;
|
||||
out.reserve(static_cast<size_t>(n));
|
||||
for (Py_ssize_t k = 0; k < n; ++k) {
|
||||
out.push_back(to_base(items[k]));
|
||||
}
|
||||
|
||||
Py_DECREF(fast);
|
||||
return out;
|
||||
};
|
||||
|
||||
auto to_vec_vec_int = [&](PyObject* o) -> std::vector<std::vector<int>> {
|
||||
PyObject* fast = seq_fast(o);
|
||||
Py_ssize_t n = PySequence_Fast_GET_SIZE(fast);
|
||||
PyObject** items = PySequence_Fast_ITEMS(fast);
|
||||
|
||||
std::vector<std::vector<int>> out;
|
||||
out.reserve(static_cast<size_t>(n));
|
||||
for (Py_ssize_t k = 0; k < n; ++k) {
|
||||
out.push_back(to_vec_int(items[k]));
|
||||
}
|
||||
|
||||
Py_DECREF(fast);
|
||||
return out;
|
||||
};
|
||||
|
||||
auto to_vec_vec_double = [&](PyObject* o) -> std::vector<std::vector<double>> {
|
||||
PyObject* fast = seq_fast(o);
|
||||
Py_ssize_t n = PySequence_Fast_GET_SIZE(fast);
|
||||
PyObject** items = PySequence_Fast_ITEMS(fast);
|
||||
|
||||
std::vector<std::vector<double>> out;
|
||||
out.reserve(static_cast<size_t>(n));
|
||||
for (Py_ssize_t k = 0; k < n; ++k) {
|
||||
out.push_back(to_vec_double(items[k]));
|
||||
}
|
||||
|
||||
Py_DECREF(fast);
|
||||
return out;
|
||||
};
|
||||
|
||||
auto to_vec_vec_base = [&](PyObject* o) -> std::vector<std::vector<express::Base>> {
|
||||
PyObject* fast = seq_fast(o);
|
||||
Py_ssize_t n = PySequence_Fast_GET_SIZE(fast);
|
||||
PyObject** items = PySequence_Fast_ITEMS(fast);
|
||||
|
||||
std::vector<std::vector<express::Base>> out;
|
||||
out.reserve(static_cast<size_t>(n));
|
||||
for (Py_ssize_t k = 0; k < n; ++k) {
|
||||
out.push_back(to_vec_base(items[k]));
|
||||
}
|
||||
|
||||
Py_DECREF(fast);
|
||||
return out;
|
||||
};
|
||||
|
||||
// Dispatch based on the IFC argument type (same decision Python was making before)
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_STRING) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else if (arg_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) {
|
||||
std::vector< boost::dynamic_bitset<> > bits;
|
||||
bits.reserve(v.size());
|
||||
for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it) {
|
||||
if (IfcUtil::valid_binary_string(*it)) {
|
||||
bits.push_back(boost::dynamic_bitset<>(*it));
|
||||
|
||||
switch (arg_type) {
|
||||
case IfcUtil::Argument_INT: {
|
||||
self->set_attribute_value(i, static_cast<int>(to_index_long(value)));
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_BOOL: {
|
||||
if (PyBool_Check(value)) {
|
||||
self->set_attribute_value(i, value == Py_True);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_LOGICAL: {
|
||||
boost::logic::tribool t(boost::logic::indeterminate);
|
||||
if (PyBool_Check(value)) {
|
||||
t = (value == Py_True);
|
||||
} else {
|
||||
throw IfcParse::IfcException("String not a valid binary representation");
|
||||
}
|
||||
long v = to_index_long(value);
|
||||
if (v == 0) t = false;
|
||||
else if (v == 1) t = true;
|
||||
else if (v == -1 || v == 2) t = boost::logic::tribool(boost::logic::indeterminate);
|
||||
else throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
self->set_attribute_value(i, t);
|
||||
return;
|
||||
}
|
||||
self->set_attribute_value(i, bits);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsEntityInstance(unsigned int i, IfcUtil::IfcBaseClass* v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_ENTITY_INSTANCE) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsAggregateOfEntityInstance(unsigned int i, aggregate_of_instance::ptr v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsAggregateOfAggregateOfInt(unsigned int i, const std::vector< std::vector<int> >& v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsAggregateOfAggregateOfDouble(unsigned int i, const std::vector< std::vector<double> >& v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
|
||||
void setArgumentAsAggregateOfAggregateOfEntityInstance(unsigned int i, aggregate_of_aggregate_of_instance::ptr v) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
case IfcUtil::Argument_DOUBLE: {
|
||||
self->set_attribute_value(i, to_double(value));
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_STRING:
|
||||
self->set_attribute_value(i, to_string(value));
|
||||
return;
|
||||
case IfcUtil::Argument_ENUMERATION: {
|
||||
const IfcParse::enumeration_type* enum_type = $self->declaration().schema()->declaration_by_name($self->declaration().type())->as_entity()->
|
||||
attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type();
|
||||
self->set_attribute_value(i, EnumerationReference(enum_type, enum_type->lookup_enum_offset(to_string(value))));
|
||||
return;
|
||||
} case IfcUtil::Argument_BINARY: {
|
||||
std::string s = to_string(value);
|
||||
if (IfcUtil::valid_binary_string(s)) {
|
||||
boost::dynamic_bitset<> bits(s);
|
||||
self->set_attribute_value(i, bits);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_AGGREGATE_OF_INT: {
|
||||
self->set_attribute_value(i, to_vec_int(value));
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
|
||||
self->set_attribute_value(i, to_vec_double(value));
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_AGGREGATE_OF_STRING:
|
||||
self->set_attribute_value(i, to_vec_string(value));
|
||||
return;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_BINARY: {
|
||||
auto vs = to_vec_string(value);
|
||||
std::vector< boost::dynamic_bitset<> > bits;
|
||||
bits.reserve(vs.size());
|
||||
for (auto& v : vs) {
|
||||
if (IfcUtil::valid_binary_string(v)) {
|
||||
bits.push_back(boost::dynamic_bitset<>(v));
|
||||
} else {
|
||||
throw IfcParse::IfcException("String not a valid binary representation");
|
||||
}
|
||||
}
|
||||
self->set_attribute_value(i, bits);
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_ENTITY_INSTANCE: {
|
||||
self->set_attribute_value(i, to_base(value));
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
self->set_attribute_value(i, to_vec_base(value));
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
|
||||
self->set_attribute_value(i, to_vec_vec_int(value));
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
|
||||
self->set_attribute_value(i, to_vec_vec_double(value));
|
||||
return;
|
||||
}
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
self->set_attribute_value(i, to_vec_vec_base(value));
|
||||
return;
|
||||
}
|
||||
default:
|
||||
throw IfcParse::IfcException("Attribute not set");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -657,13 +846,13 @@ private:
|
||||
// it has no idea about the schema definitions.
|
||||
// The code to access these methods as attributes
|
||||
// is in file.py
|
||||
IfcUtil::IfcBaseClass* file_description_py() {
|
||||
express::Base file_description_py() {
|
||||
return $self->file_description();
|
||||
}
|
||||
IfcUtil::IfcBaseClass* file_name_py() {
|
||||
express::Base file_name_py() {
|
||||
return $self->file_name();
|
||||
}
|
||||
IfcUtil::IfcBaseClass* file_schema_py() {
|
||||
express::Base file_schema_py() {
|
||||
return $self->file_schema();
|
||||
}
|
||||
};
|
||||
@@ -697,9 +886,45 @@ private:
|
||||
|
||||
%include "../ifcparse/ifc_parse_api.h"
|
||||
%include "../ifcparse/IfcSpfHeader.h"
|
||||
|
||||
%pythoncode %{
|
||||
### hack hack hack
|
||||
### we trick swig into inheriting from our own extension class
|
||||
### that way we do not constantly need to decorate/undecorate
|
||||
# @todo is there no official way to do this?
|
||||
_old_object = object
|
||||
from .file import file_mixin as custom_base
|
||||
object = custom_base
|
||||
%}
|
||||
|
||||
%include "../ifcparse/IfcFile.h"
|
||||
|
||||
%pythoncode %{
|
||||
### hack hack hack
|
||||
### restore
|
||||
object = _old_object
|
||||
%}
|
||||
|
||||
%include "../ifcparse/file_open_status.h"
|
||||
%include "../ifcparse/IfcBaseClass.h"
|
||||
|
||||
%pythoncode %{
|
||||
### hack hack hack
|
||||
### we trick swig into inheriting from our own extension class
|
||||
### that way we do not constantly need to decorate/undecorate
|
||||
# @todo is there no official way to do this?
|
||||
_old_object = object
|
||||
from .entity_instance import entity_instance_mixin as custom_base
|
||||
object = custom_base
|
||||
%}
|
||||
|
||||
%include "../ifcparse/express.h"
|
||||
|
||||
%pythoncode %{
|
||||
### hack hack hack
|
||||
### restore
|
||||
object = _old_object
|
||||
%}
|
||||
|
||||
%include "../ifcparse/IfcSchema.h"
|
||||
%include "../serializers/RocksDbSerializer.h"
|
||||
|
||||
@@ -738,15 +963,8 @@ private:
|
||||
return IFCOPENSHELL_VERSION;
|
||||
}
|
||||
|
||||
IfcUtil::IfcBaseClass* new_IfcBaseClass(const std::string& schema_identifier, const std::string& name) {
|
||||
const IfcParse::schema_definition* schema = IfcParse::schema_by_name(schema_identifier);
|
||||
const IfcParse::declaration* decl = schema->declaration_by_name(name);
|
||||
IfcEntityInstanceData data(in_memory_attribute_storage(decl->as_entity() ? decl->as_entity()->attribute_count() : 1));
|
||||
auto inst = schema->instantiate(decl, std::move(data));
|
||||
if (auto entinst = inst->as<IfcUtil::IfcBaseEntity>()) {
|
||||
entinst->populate_derived();
|
||||
}
|
||||
return inst;
|
||||
express::Base new_IfcBaseClass(IfcParse::IfcFile* file, const std::string& name) {
|
||||
return file->create(file->schema()->declaration_by_name(name));
|
||||
}
|
||||
%}
|
||||
|
||||
@@ -905,12 +1123,12 @@ private:
|
||||
%}
|
||||
|
||||
%{
|
||||
PyObject* get_info_cpp(IfcUtil::IfcBaseClass* v, bool include_identifier);
|
||||
PyObject* get_info_cpp(const express::Base& v, bool include_identifier);
|
||||
|
||||
// @todo refactor this to remove duplication with the typemap.
|
||||
// except this is calls the above function in case of instances.
|
||||
PyObject* convert_cpp_attribute_to_python(IfcUtil::IfcBaseClass* instance, size_t attribute_index, bool include_identifier = true) {
|
||||
return instance->get_attribute_value(attribute_index).apply_visitor([include_identifier](const auto& v){
|
||||
PyObject* convert_cpp_attribute_to_python(const express::Base& instance, size_t attribute_index, bool include_identifier = true) {
|
||||
return instance.get_attribute_value(attribute_index).apply_visitor([include_identifier](const auto& v){
|
||||
using U = std::decay_t<decltype(v)>;
|
||||
if constexpr (is_std_vector_v<U>) {
|
||||
return pythonize_vector(v);
|
||||
@@ -923,25 +1141,8 @@ private:
|
||||
Py_INCREF(Py_None);
|
||||
return static_cast<PyObject*>(Py_None);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<U, IfcUtil::IfcBaseClass*>) {
|
||||
} else if constexpr (std::is_same_v<U, express::Base>) {
|
||||
return get_info_cpp(v, include_identifier);
|
||||
} else if constexpr (std::is_same_v<U, aggregate_of_instance::ptr>) {
|
||||
auto r = PyTuple_New(v->size());
|
||||
for (unsigned i = 0; i < v->size(); ++i) {
|
||||
PyTuple_SetItem(r, i, get_info_cpp((*v)[i], include_identifier));
|
||||
}
|
||||
return r;
|
||||
} else if constexpr (std::is_same_v<U, aggregate_of_aggregate_of_instance::ptr>) {
|
||||
auto rs = PyTuple_New(v->size());
|
||||
for (auto it = v->begin(); it != v->end(); ++it) {
|
||||
auto v_i = it;
|
||||
auto r = PyTuple_New(v_i->size());
|
||||
for (unsigned i = 0; i < v_i->size(); ++i) {
|
||||
PyTuple_SetItem(r, i, get_info_cpp((*v_i)[i], include_identifier));
|
||||
}
|
||||
PyTuple_SetItem(rs, std::distance(v->begin(), it), r);
|
||||
}
|
||||
return rs;
|
||||
} else if constexpr (std::is_same_v<U, empty_aggregate_t> || std::is_same_v<U, empty_aggregate_of_aggregate_t> || std::is_same_v<U, Blank>) {
|
||||
Py_INCREF(Py_None);
|
||||
return static_cast<PyObject*>(Py_None);
|
||||
@@ -952,13 +1153,13 @@ private:
|
||||
}
|
||||
%}
|
||||
%inline %{
|
||||
PyObject* get_info_cpp(IfcUtil::IfcBaseClass* v, bool include_identifier = true) {
|
||||
PyObject* get_info_cpp(const express::Base& v, bool include_identifier = true) {
|
||||
PyObject *d = PyDict_New();
|
||||
|
||||
if (v->declaration().as_entity()) {
|
||||
const std::vector<const IfcParse::attribute*> attrs = v->declaration().as_entity()->all_attributes();
|
||||
if (v.declaration().as_entity()) {
|
||||
const std::vector<const IfcParse::attribute*> attrs = v.declaration().as_entity()->all_attributes();
|
||||
std::vector<const IfcParse::attribute*>::const_iterator it = attrs.begin();
|
||||
auto dit = v->declaration().as_entity()->derived().begin();
|
||||
auto dit = v.declaration().as_entity()->derived().begin();
|
||||
for (; it != attrs.end(); ++it, ++dit) {
|
||||
const std::string& name_cpp = (*it)->name();
|
||||
auto name_py = pythonize(name_cpp);
|
||||
@@ -973,7 +1174,7 @@ private:
|
||||
if (include_identifier) {
|
||||
const std::string& id_cpp = "id";
|
||||
auto id_py = pythonize(id_cpp);
|
||||
auto id_v_py = pythonize(v->as<IfcUtil::IfcBaseEntity>()->id());
|
||||
auto id_v_py = pythonize(v.id());
|
||||
PyDict_SetItem(d, id_py, id_v_py);
|
||||
Py_DECREF(id_py);
|
||||
Py_DECREF(id_v_py);
|
||||
@@ -990,7 +1191,7 @@ private:
|
||||
// @todo type and id can be static?
|
||||
const std::string& type_cpp = "type";
|
||||
auto type_py = pythonize(type_cpp);
|
||||
const std::string& type_v_cpp = v->declaration().name();
|
||||
const std::string& type_v_cpp = v.declaration().name();
|
||||
auto type_v_py = pythonize(type_v_cpp);
|
||||
PyDict_SetItem(d, type_py, type_v_py);
|
||||
Py_DECREF(type_py);
|
||||
@@ -1002,9 +1203,9 @@ private:
|
||||
|
||||
%extend IfcParse::InstanceStreamer {
|
||||
PyObject* readInstancePy(bool type_as_declaration_instance=false) {
|
||||
auto simply_type_to_dictionary = [&](IfcUtil::IfcBaseClass* t) -> PyObject* {
|
||||
const auto& nm = t->declaration().name();
|
||||
auto ifc_val = t->get_attribute_value(0);
|
||||
auto simply_type_to_dictionary = [&](const express::Base& t) -> PyObject* {
|
||||
const auto& nm = t.declaration().name();
|
||||
auto ifc_val = t.get_attribute_value(0);
|
||||
auto attribute_val_py = ifc_val.apply_visitor([&](const auto& t) {
|
||||
using U = std::decay_t<decltype(t)>;
|
||||
|
||||
@@ -1019,14 +1220,6 @@ private:
|
||||
Py_INCREF(Py_None);
|
||||
return static_cast<PyObject*>(Py_None);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<U, aggregate_of_instance::ptr>) {
|
||||
// cannot occur in streaming mode
|
||||
Py_INCREF(Py_None);
|
||||
return static_cast<PyObject*>(Py_None);
|
||||
} else if constexpr (std::is_same_v<U, aggregate_of_aggregate_of_instance::ptr>) {
|
||||
// cannot occur in streaming mode
|
||||
Py_INCREF(Py_None);
|
||||
return static_cast<PyObject*>(Py_None);
|
||||
} else if constexpr (std::is_same_v<U, empty_aggregate_t> || std::is_same_v<U, empty_aggregate_of_aggregate_t> || std::is_same_v<U, Blank>) {
|
||||
Py_INCREF(Py_None);
|
||||
return static_cast<PyObject*>(Py_None);
|
||||
@@ -1103,13 +1296,13 @@ private:
|
||||
const auto& data = std::get<2>(*inst);
|
||||
|
||||
for (size_t i = 0; i < decl->as_entity()->attribute_count(); i++) {
|
||||
auto val = data.get_attribute_value(nullptr, decl, 0, i);
|
||||
auto val = data->get_attribute_value(i);
|
||||
|
||||
// sets dict member, returns void
|
||||
val.apply_visitor([&](const auto& t) -> void {
|
||||
using T = std::decay_t<decltype(t)>;
|
||||
PyObject* attribute_val_py;
|
||||
if constexpr (std::is_same_v<T, IfcUtil::IfcBaseClass*>) {
|
||||
if constexpr (std::is_same_v<T, express::Base>) {
|
||||
attribute_val_py = simply_type_to_dictionary(t);
|
||||
} else {
|
||||
using U = std::decay_t<decltype(t)>;
|
||||
@@ -1125,14 +1318,6 @@ private:
|
||||
Py_INCREF(Py_None);
|
||||
attribute_val_py = static_cast<PyObject*>(Py_None);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<U, aggregate_of_instance::ptr>) {
|
||||
// cannot occur in streaming mode
|
||||
Py_INCREF(Py_None);
|
||||
attribute_val_py = static_cast<PyObject*>(Py_None);
|
||||
} else if constexpr (std::is_same_v<U, aggregate_of_aggregate_of_instance::ptr>) {
|
||||
// cannot occur in streaming mode
|
||||
Py_INCREF(Py_None);
|
||||
attribute_val_py = static_cast<PyObject*>(Py_None);
|
||||
} else if constexpr (std::is_same_v<U, empty_aggregate_t> || std::is_same_v<U, empty_aggregate_of_aggregate_t> || std::is_same_v<U, Blank>) {
|
||||
Py_INCREF(Py_None);
|
||||
attribute_val_py = static_cast<PyObject*>(Py_None);
|
||||
@@ -1159,7 +1344,7 @@ private:
|
||||
using T = std::decay_t<decltype(v)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, IfcParse::reference_or_simple_type>) {
|
||||
if (auto* inst = std::get_if<IfcUtil::IfcBaseClass*>(&v)) {
|
||||
if (auto* inst = std::get_if<express::Base>(&v)) {
|
||||
// So this never happens?
|
||||
} else if (auto* name = std::get_if<IfcParse::InstanceReference>(&v)) {
|
||||
attribute_val_py = instance_reference_to_dict(*name);
|
||||
@@ -1168,7 +1353,7 @@ private:
|
||||
attribute_val_py = PyTuple_New(v.size());
|
||||
size_t idx = 0;
|
||||
for (auto const& inner : v) {
|
||||
if (auto* inst = std::get_if<IfcUtil::IfcBaseClass*>(&inner)) {
|
||||
if (auto* inst = std::get_if<express::Base>(&inner)) {
|
||||
PyTuple_SetItem(attribute_val_py, idx++, simply_type_to_dictionary(*inst));
|
||||
} else if (auto* name = std::get_if<IfcParse::InstanceReference>(&inner)) {
|
||||
PyTuple_SetItem(attribute_val_py, idx++, instance_reference_to_dict(*name));
|
||||
@@ -1181,7 +1366,7 @@ private:
|
||||
PyObject* inner_py = PyTuple_New(inner.size());
|
||||
size_t idx = 0;
|
||||
for (auto const& innermost : inner) {
|
||||
if (auto* inst = std::get_if<IfcUtil::IfcBaseClass*>(&innermost)) {
|
||||
if (auto* inst = std::get_if<express::Base>(&innermost)) {
|
||||
PyTuple_SetItem(inner_py, idx++, simply_type_to_dictionary(*inst));
|
||||
} else if (auto* name = std::get_if<IfcParse::InstanceReference>(&innermost)) {
|
||||
PyTuple_SetItem(inner_py, idx++, instance_reference_to_dict(*name));
|
||||
|
||||
@@ -69,8 +69,7 @@
|
||||
%ignore instance_factory;
|
||||
|
||||
// Not relevant for python usage
|
||||
%ignore IfcBaseInterface;
|
||||
%ignore IfcBaseClass::data;
|
||||
%ignore express::Base::data;
|
||||
%ignore *::references_to_resolve;
|
||||
|
||||
// SVG serializer internal
|
||||
@@ -248,7 +247,7 @@
|
||||
#include "../ifcparse/Ifc4x3_add2.h"
|
||||
#endif
|
||||
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/express.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#include "../ifcparse/utils.h"
|
||||
@@ -351,7 +350,7 @@ constexpr bool is_std_vector_vector_v = is_std_vector_vector<T>::value;
|
||||
#include "../ifcparse/Ifc4x3_add2.h"
|
||||
#endif
|
||||
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/express.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#include "../ifcparse/utils.h"
|
||||
|
||||
@@ -86,10 +86,10 @@
|
||||
}
|
||||
|
||||
template <>
|
||||
IfcUtil::IfcBaseClass* cast_pyobject(PyObject* element) {
|
||||
express::Base cast_pyobject(PyObject* element) {
|
||||
void *arg = 0;
|
||||
int res = SWIG_ConvertPtr(element, &arg, SWIGTYPE_p_IfcUtil__IfcBaseClass, 0);
|
||||
return static_cast<IfcUtil::IfcBaseClass*>(SWIG_IsOK(res) ? arg : 0);
|
||||
int res = SWIG_ConvertPtr(element, &arg, SWIGTYPE_p_express__Base, 0);
|
||||
return SWIG_IsOK(res) ? *reinterpret_cast<express::Base*>(arg) : express::Base{};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -162,7 +162,7 @@
|
||||
PyObject* pythonize(const boost::logic::tribool& t) { return boost::logic::indeterminate(t) ? PyUnicode_FromString("UNKNOWN") : PyBool_FromLong((bool)t) ;}
|
||||
PyObject* pythonize(const double& t) { return PyFloat_FromDouble(t); }
|
||||
PyObject* pythonize(const std::string& t) { return PyUnicode_FromString(t.c_str()); }
|
||||
PyObject* pythonize(const IfcUtil::IfcBaseClass* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcUtil__IfcBaseClass, 0); }
|
||||
PyObject* pythonize(const express::Base& t) { return SWIG_NewPointerObj(SWIG_as_voidptr(new express::Base(t)), SWIGTYPE_p_express__Base, SWIG_POINTER_OWN); }
|
||||
PyObject* pythonize(const IfcParse::attribute* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcParse__attribute, 0); }
|
||||
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); }
|
||||
@@ -179,15 +179,6 @@
|
||||
return pythonize(bitstring);
|
||||
}
|
||||
|
||||
PyObject* pythonize(const aggregate_of_instance::ptr& t) {
|
||||
unsigned int i = 0;
|
||||
PyObject* pyobj = PyTuple_New(t->size());
|
||||
for (aggregate_of_instance::it it = t->begin(); it != t->end(); ++it, ++i) {
|
||||
PyTuple_SetItem(pyobj, i, pythonize(*it));
|
||||
}
|
||||
return pyobj;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PyObject* pythonize_vector(const T& v) {
|
||||
const size_t size = v.size();
|
||||
@@ -202,15 +193,6 @@
|
||||
return pyobj;
|
||||
}
|
||||
|
||||
PyObject* pythonize(const aggregate_of_aggregate_of_instance::ptr& t) {
|
||||
unsigned int i = 0;
|
||||
PyObject* pyobj = PyTuple_New(t->size());
|
||||
for (aggregate_of_aggregate_of_instance::outer_it it = t->begin(); it != t->end(); ++it, ++i) {
|
||||
PyTuple_SetItem(pyobj, i, pythonize_vector(*it));
|
||||
}
|
||||
return pyobj;
|
||||
}
|
||||
|
||||
struct pythonizing_visitor {
|
||||
typedef PyObject* result_type;
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ CREATE_VECTOR_TYPEMAP_IN(std::string, STRING, str)
|
||||
$1 = aggregate_of_instance::ptr(new aggregate_of_instance());
|
||||
for(Py_ssize_t i = 0; i < PySequence_Size($input); ++i) {
|
||||
PyObject* element = PySequence_GetItem($input, i);
|
||||
IfcUtil::IfcBaseClass* inst = cast_pyobject<IfcUtil::IfcBaseClass*>(element);
|
||||
express::Base inst = cast_pyobject<express::Base>(element);
|
||||
Py_DECREF(element);
|
||||
if (inst) {
|
||||
$1->push(inst);
|
||||
@@ -192,11 +192,11 @@ CREATE_VECTOR_TYPEMAP_IN(std::string, STRING, str)
|
||||
bool b = false;
|
||||
if (PySequence_Check(element)) {
|
||||
b = true;
|
||||
std::vector<IfcUtil::IfcBaseClass*> vector;
|
||||
std::vector<express::Base> vector;
|
||||
vector.reserve(PySequence_Size(element));
|
||||
for(Py_ssize_t j = 0; j < PySequence_Size(element); ++j) {
|
||||
PyObject* element_element = PySequence_GetItem(element, j);
|
||||
IfcUtil::IfcBaseClass* inst = cast_pyobject<IfcUtil::IfcBaseClass*>(element_element);
|
||||
express::Base inst = cast_pyobject<express::Base>(element_element);
|
||||
Py_DECREF(element_element);
|
||||
if (inst) {
|
||||
vector.push_back(inst);
|
||||
@@ -291,9 +291,9 @@ CREATE_VECTOR_TYPEMAP_IN(std::string, STRING, str)
|
||||
|
||||
%define CREATE_OPTIONAL_TYPEMAP_IN(template_type, express_name, python_name)
|
||||
|
||||
%typemap(in) const boost::optional<template_type>& {
|
||||
%typemap(in) const std::optional<template_type>& {
|
||||
if ($input == Py_None) {
|
||||
(*$1) = boost::none;
|
||||
(*$1) = std::nullopt;
|
||||
} else if ($input->ob_type != get_python_type<template_type>()) {
|
||||
SWIG_exception(SWIG_TypeError, "Optional " #express_name " needs a " #python_name " or None");
|
||||
} else {
|
||||
@@ -301,15 +301,15 @@ CREATE_VECTOR_TYPEMAP_IN(std::string, STRING, str)
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(typecheck,precedence=SWIG_TYPECHECK_INTEGER) const boost::optional<template_type>& {
|
||||
%typemap(typecheck,precedence=SWIG_TYPECHECK_INTEGER) const std::optional<template_type>& {
|
||||
$1 = ($input == Py_None || $input->ob_type == get_python_type<template_type>()) ? 1 : 0;
|
||||
}
|
||||
|
||||
%typemap(arginit) const boost::optional<template_type>& {
|
||||
$1 = new boost::optional<template_type>();
|
||||
%typemap(arginit) const std::optional<template_type>& {
|
||||
$1 = new std::optional<template_type>();
|
||||
}
|
||||
|
||||
%typemap(freearg) const boost::optional<template_type>& {
|
||||
%typemap(freearg) const std::optional<template_type>& {
|
||||
delete $1;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,12 +111,12 @@ CREATE_VECTOR_TYPEMAP_OUT(IfcGeom::ConversionResultShape *)
|
||||
|
||||
%typemap(out) ifcopenshell::geometry::Settings::value_variant_t {
|
||||
pythonizing_visitor vis;
|
||||
$result = $1.apply_visitor(vis);
|
||||
$result = std::visit(vis, $1);
|
||||
}
|
||||
|
||||
%typemap(out) ifcopenshell::geometry::SerializerSettings::value_variant_t {
|
||||
pythonizing_visitor vis;
|
||||
$result = $1.apply_visitor(vis);
|
||||
$result = std::visit(vis, $1);
|
||||
}
|
||||
|
||||
%typemap(out) std::pair<const char*, size_t> {
|
||||
|
||||
Reference in New Issue
Block a user