mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-24 15:07:38 +00:00
Minimize passing STL objects past dynamic library boundaries to improve stability of IfcOpenShell-Python
This commit is contained in:
@@ -43,9 +43,11 @@ class entity_instance(object):
|
|||||||
def __init__(self, e):
|
def __init__(self, e):
|
||||||
super(entity_instance, self).__setattr__('wrapped_data', e)
|
super(entity_instance, self).__setattr__('wrapped_data', e)
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name in self.wrapped_data.get_attribute_names():
|
INVALID, FORWARD, INVERSE = range(3)
|
||||||
|
attr_cat = self.wrapped_data.get_attribute_category(name)
|
||||||
|
if attr_cat == FORWARD:
|
||||||
return entity_instance.wrap_value(self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name)))
|
return entity_instance.wrap_value(self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name)))
|
||||||
elif name in self.wrapped_data.get_inverse_attribute_names():
|
elif attr_cat == INVERSE:
|
||||||
return entity_instance.wrap_value(self.wrapped_data.get_inverse(name))
|
return entity_instance.wrap_value(self.wrapped_data.get_inverse(name))
|
||||||
else: raise AttributeError("entity instance of type '%s' has no attribute '%s'"%(self.wrapped_data.is_a(), name))
|
else: raise AttributeError("entity instance of type '%s' has no attribute '%s'"%(self.wrapped_data.is_a(), name))
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -93,6 +93,47 @@
|
|||||||
%ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, void*, int);
|
%ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, void*, int);
|
||||||
%ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, std::istream&, int);
|
%ignore IfcGeom::Iterator<double>::Iterator(const IfcGeom::IteratorSettings&, std::istream&, int);
|
||||||
|
|
||||||
|
// Ignore the std::vector accessors and replace them to pairs that will
|
||||||
|
// be expanded to Python tuples by means of typemaps. This in order to
|
||||||
|
// minimize passing STL objects across dynamic library boundaries.
|
||||||
|
%ignore IfcGeom::Representation::Triangulation::verts;
|
||||||
|
%ignore IfcGeom::Representation::Triangulation::faces;
|
||||||
|
%ignore IfcGeom::Representation::Triangulation::edges;
|
||||||
|
%ignore IfcGeom::Representation::Triangulation::normals;
|
||||||
|
%ignore IfcGeom::Representation::Triangulation::material_ids;
|
||||||
|
%ignore IfcGeom::Representation::Triangulation::materials;
|
||||||
|
%extend IfcGeom::Representation::Triangulation {
|
||||||
|
std::pair<const int*, unsigned> get_faces() {
|
||||||
|
return std::make_pair(&$self->faces()[0], $self->faces().size());
|
||||||
|
}
|
||||||
|
std::pair<const int*, unsigned> get_edges() {
|
||||||
|
return std::make_pair(&$self->edges()[0], $self->edges().size());
|
||||||
|
}
|
||||||
|
std::pair<const int*, unsigned> get_material_ids() {
|
||||||
|
return std::make_pair(&$self->material_ids()[0], $self->material_ids().size());
|
||||||
|
}
|
||||||
|
std::pair<const IfcGeom::Material*, unsigned> get_materials() {
|
||||||
|
return std::make_pair(&$self->materials()[0], $self->materials().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%extend IfcGeom::Representation::Triangulation<float> {
|
||||||
|
std::pair<const float*, unsigned> get_verts() {
|
||||||
|
return std::make_pair(&$self->verts()[0], $self->verts().size());
|
||||||
|
}
|
||||||
|
std::pair<const float*, unsigned> get_normals() {
|
||||||
|
return std::make_pair(&$self->normals()[0], $self->normals().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%extend IfcGeom::Representation::Triangulation<double> {
|
||||||
|
std::pair<const double*, unsigned> get_verts() {
|
||||||
|
return std::make_pair(&$self->verts()[0], $self->verts().size());
|
||||||
|
}
|
||||||
|
std::pair<const double*, unsigned> get_normals() {
|
||||||
|
return std::make_pair(&$self->normals()[0], $self->normals().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
%extend IfcGeom::IteratorSettings {
|
%extend IfcGeom::IteratorSettings {
|
||||||
%pythoncode %{
|
%pythoncode %{
|
||||||
attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices")
|
attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices")
|
||||||
@@ -114,17 +155,34 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcGeom::Representation::Triangulation {
|
%extend IfcGeom::Representation::Triangulation {
|
||||||
%pythoncode %{
|
%pythoncode %{
|
||||||
if _newclass:
|
if _newclass:
|
||||||
# Hide the getters with read-only property implementations
|
# Hide the getters with read-only property implementations
|
||||||
id = property(id)
|
id = property(id)
|
||||||
verts = property(verts)
|
faces = property(get_faces)
|
||||||
faces = property(faces)
|
edges = property(get_edges)
|
||||||
edges = property(edges)
|
material_ids = property(get_material_ids)
|
||||||
normals = property(normals)
|
materials = property(get_materials)
|
||||||
material_ids = property(material_ids)
|
%}
|
||||||
materials = property(materials)
|
};
|
||||||
%}
|
|
||||||
|
// Specialized accessors follow later, for otherwise property definitions
|
||||||
|
// would appear before templated getter functions are defined.
|
||||||
|
%extend IfcGeom::Representation::Triangulation<float> {
|
||||||
|
%pythoncode %{
|
||||||
|
if _newclass:
|
||||||
|
# Hide the getters with read-only property implementations
|
||||||
|
verts = property(get_verts)
|
||||||
|
normals = property(get_normals)
|
||||||
|
%}
|
||||||
|
};
|
||||||
|
%extend IfcGeom::Representation::Triangulation<double> {
|
||||||
|
%pythoncode %{
|
||||||
|
if _newclass:
|
||||||
|
# Hide the getters with read-only property implementations
|
||||||
|
verts = property(get_verts)
|
||||||
|
normals = property(get_normals)
|
||||||
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcGeom::Representation::Serialization {
|
%extend IfcGeom::Representation::Serialization {
|
||||||
@@ -133,7 +191,7 @@
|
|||||||
# Hide the getters with read-only property implementations
|
# Hide the getters with read-only property implementations
|
||||||
id = property(id)
|
id = property(id)
|
||||||
brep_data = property(brep_data)
|
brep_data = property(brep_data)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcGeom::Element {
|
%extend IfcGeom::Element {
|
||||||
@@ -148,7 +206,7 @@
|
|||||||
context = property(context)
|
context = property(context)
|
||||||
unique_id = property(unique_id)
|
unique_id = property(unique_id)
|
||||||
transformation = property(transformation)
|
transformation = property(transformation)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcGeom::TriangulationElement {
|
%extend IfcGeom::TriangulationElement {
|
||||||
@@ -156,7 +214,7 @@
|
|||||||
if _newclass:
|
if _newclass:
|
||||||
# Hide the getters with read-only property implementations
|
# Hide the getters with read-only property implementations
|
||||||
geometry = property(geometry)
|
geometry = property(geometry)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcGeom::SerializedElement {
|
%extend IfcGeom::SerializedElement {
|
||||||
@@ -164,7 +222,7 @@
|
|||||||
if _newclass:
|
if _newclass:
|
||||||
# Hide the getters with read-only property implementations
|
# Hide the getters with read-only property implementations
|
||||||
geometry = property(geometry)
|
geometry = property(geometry)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcGeom::Material {
|
%extend IfcGeom::Material {
|
||||||
@@ -180,7 +238,7 @@
|
|||||||
transparency = property(transparency)
|
transparency = property(transparency)
|
||||||
specularity = property(specularity)
|
specularity = property(specularity)
|
||||||
name = property(name)
|
name = property(name)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcGeom::Transformation {
|
%extend IfcGeom::Transformation {
|
||||||
@@ -188,7 +246,7 @@
|
|||||||
if _newclass:
|
if _newclass:
|
||||||
# Hide the getters with read-only property implementations
|
# Hide the getters with read-only property implementations
|
||||||
matrix = property(matrix)
|
matrix = property(matrix)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcGeom::Matrix {
|
%extend IfcGeom::Matrix {
|
||||||
@@ -196,7 +254,7 @@
|
|||||||
if _newclass:
|
if _newclass:
|
||||||
# Hide the getters with read-only property implementations
|
# Hide the getters with read-only property implementations
|
||||||
data = property(data)
|
data = property(data)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
|
|||||||
@@ -216,8 +216,8 @@ namespace IfcUtil {
|
|||||||
std::ofstream f(fn.c_str());
|
std::ofstream f(fn.c_str());
|
||||||
f << (*$self);
|
f << (*$self);
|
||||||
}
|
}
|
||||||
std::vector<int> entity_names() const {
|
std::vector<unsigned> entity_names() const {
|
||||||
std::vector<int> keys;
|
std::vector<unsigned> keys;
|
||||||
keys.reserve(std::distance($self->begin(), $self->end()));
|
keys.reserve(std::distance($self->begin(), $self->end()));
|
||||||
for (IfcParse::IfcFile::entity_by_id_t::const_iterator it = $self->begin(); it != $self->end(); ++ it) {
|
for (IfcParse::IfcFile::entity_by_id_t::const_iterator it = $self->begin(); it != $self->end(); ++ it) {
|
||||||
keys.push_back(it->first);
|
keys.push_back(it->first);
|
||||||
@@ -228,10 +228,23 @@ namespace IfcUtil {
|
|||||||
if _newclass:
|
if _newclass:
|
||||||
# Hide the getters with read-only property implementations
|
# Hide the getters with read-only property implementations
|
||||||
header = property(header)
|
header = property(header)
|
||||||
%}
|
%}
|
||||||
}
|
}
|
||||||
|
|
||||||
%extend IfcParse::IfcLateBoundEntity {
|
%extend IfcParse::IfcLateBoundEntity {
|
||||||
|
int get_attribute_category(const std::string& name) const {
|
||||||
|
const std::vector<std::string> names = $self->getAttributeNames();
|
||||||
|
if (std::find(names.begin(), names.end(), name) != names.end()) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
const std::vector<std::string> names = $self->getInverseAttributeNames();
|
||||||
|
if (std::find(names.begin(), names.end(), name) != names.end()) {
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
%pythoncode %{
|
%pythoncode %{
|
||||||
set_argument = lambda self,x,y: self._set_argument(x) if y is None else self._set_argument(x,y)
|
set_argument = lambda self,x,y: self._set_argument(x) if y is None else self._set_argument(x,y)
|
||||||
%}
|
%}
|
||||||
@@ -244,7 +257,7 @@ namespace IfcUtil {
|
|||||||
file_description = property(file_description)
|
file_description = property(file_description)
|
||||||
file_name = property(file_name)
|
file_name = property(file_name)
|
||||||
file_schema = property(file_schema)
|
file_schema = property(file_schema)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcParse::FileDescription {
|
%extend IfcParse::FileDescription {
|
||||||
@@ -257,7 +270,7 @@ namespace IfcUtil {
|
|||||||
__swig_getmethods__["implementation_level"] = implementation_level
|
__swig_getmethods__["implementation_level"] = implementation_level
|
||||||
__swig_setmethods__["implementation_level"] = implementation_level
|
__swig_setmethods__["implementation_level"] = implementation_level
|
||||||
implementation_level = property(implementation_level, implementation_level)
|
implementation_level = property(implementation_level, implementation_level)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcParse::FileName {
|
%extend IfcParse::FileName {
|
||||||
@@ -285,7 +298,7 @@ namespace IfcUtil {
|
|||||||
__swig_getmethods__["authorization"] = authorization
|
__swig_getmethods__["authorization"] = authorization
|
||||||
__swig_setmethods__["authorization"] = authorization
|
__swig_setmethods__["authorization"] = authorization
|
||||||
authorization = property(authorization, authorization)
|
authorization = property(authorization, authorization)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend IfcParse::FileSchema {
|
%extend IfcParse::FileSchema {
|
||||||
@@ -295,7 +308,7 @@ namespace IfcUtil {
|
|||||||
__swig_getmethods__["schema_identifiers"] = schema_identifiers
|
__swig_getmethods__["schema_identifiers"] = schema_identifiers
|
||||||
__swig_setmethods__["schema_identifiers"] = schema_identifiers
|
__swig_setmethods__["schema_identifiers"] = schema_identifiers
|
||||||
schema_identifiers = property(schema_identifiers, schema_identifiers)
|
schema_identifiers = property(schema_identifiers, schema_identifiers)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%include "../ifcparse/IfcSpfHeader.h"
|
%include "../ifcparse/IfcSpfHeader.h"
|
||||||
|
|||||||
+41
-8
@@ -41,13 +41,46 @@
|
|||||||
#include "../ifcparse/IfcLateBoundEntity.h"
|
#include "../ifcparse/IfcLateBoundEntity.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
// The following typemaps are an alternative for the read-only std::vector
|
||||||
|
// implementations provided by SWIG, as passing STL objects across dynamic
|
||||||
|
// library boundaries can be problematic.
|
||||||
|
%typemap(out) std::pair<const float*, unsigned> {
|
||||||
|
$result = PyTuple_New($1.second);
|
||||||
|
for (unsigned i = 0; i < $1.second; ++i) {
|
||||||
|
PyTuple_SetItem($result, i, PyFloat_FromDouble($1.first[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%typemap(out) std::pair<const double*, unsigned> {
|
||||||
|
$result = PyTuple_New($1.second);
|
||||||
|
for (unsigned i = 0; i < $1.second; ++i) {
|
||||||
|
PyTuple_SetItem($result, i, PyFloat_FromDouble($1.first[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%typemap(out) std::pair<const int*, unsigned> {
|
||||||
|
$result = PyTuple_New($1.second);
|
||||||
|
for (unsigned i = 0; i < $1.second; ++i) {
|
||||||
|
PyTuple_SetItem($result, i, PyLong_FromLong($1.first[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%typemap(out) std::pair<const std::string*, unsigned> {
|
||||||
|
$result = PyTuple_New($1.second);
|
||||||
|
for (unsigned i = 0; i < $1.second; ++i) {
|
||||||
|
PyTuple_SetItem($result, i, PyUnicode_FromString($1.first[i]->c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%typemap(out) std::pair<const IfcGeom::Material*, unsigned> {
|
||||||
|
$result = PyTuple_New($1.second);
|
||||||
|
for (unsigned i = 0; i < $1.second; ++i) {
|
||||||
|
PyTuple_SetItem($result, i, SWIG_NewPointerObj(SWIG_as_voidptr(&$1.first[i]), SWIGTYPE_p_IfcGeom__Material, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%typemap(out) std::vector<unsigned> {
|
||||||
|
$result = PyTuple_New($1.size());
|
||||||
|
unsigned i = 0;
|
||||||
|
for (std::vector<unsigned>::const_iterator it = $1.begin(); it != $1.end(); ++it) {
|
||||||
|
PyTuple_SetItem($result, i++, PyLong_FromLong(*it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
%include "IfcGeomWrapper.i"
|
%include "IfcGeomWrapper.i"
|
||||||
%include "IfcParseWrapper.i"
|
%include "IfcParseWrapper.i"
|
||||||
|
|
||||||
namespace std {
|
|
||||||
%template(int_vector) vector<int>;
|
|
||||||
%template(float_vector) vector<float>;
|
|
||||||
%template(double_vector) vector<double>;
|
|
||||||
%template(string_vector) vector<std::string>;
|
|
||||||
%template(material_vector) vector<IfcGeom::Material>;
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user