diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index 8e832ab0ed..7fc6c62d60 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -79,6 +79,11 @@ if ( it != cache.T.end() ) { e = it->second; return true; } #define MAKE_TYPE_NAME_(a, b) MAKE_TYPE_NAME__(a, b) #define MAKE_TYPE_NAME(t) MAKE_TYPE_NAME_(t, IfcSchema) +#define STRINGIFY_(x) #x +#define STRINGIFY(x) STRINGIFY_(x) +#define INCLUDE(x) STRINGIFY(../ifcparse/x.h) +#include INCLUDE(IfcSchema) + namespace IfcGeom { class IFC_GEOM_API MAKE_TYPE_NAME(Cache) { @@ -178,8 +183,7 @@ public: bool closest(const gp_Pnt&, const std::vector&, gp_Pnt&); bool project(const Handle_Geom_Curve&, const gp_Pnt&, gp_Pnt& p, double& u, double& d); bool project(const Handle_Geom_Surface&, const TopoDS_Shape&, double& u1, double& v1, double& u2, double& v2, double widen=0.1); - static int count(const TopoDS_Shape&, TopAbs_ShapeEnum); - + bool find_wall_end_points(const IfcSchema::IfcWall*, gp_Pnt& start, gp_Pnt& end); IfcSchema::IfcSurfaceStyleShading* get_surface_style(IfcSchema::IfcRepresentationItem* item); @@ -194,8 +198,6 @@ public: const TopoDS_Shape& ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid); bool profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Shape& face); void apply_tolerance(TopoDS_Shape& s, double t); - void setValue(GeomValue var, double value); - double getValue(GeomValue var) const; bool fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape); void remove_duplicate_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.); void remove_collinear_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.); @@ -230,7 +232,7 @@ public: template IfcGeom::BRepElement

* create_brep_for_processed_representation( const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::BRepElement

*); - + const IfcSchema::IfcMaterial* get_single_material_association(const IfcSchema::IfcProduct*); IfcSchema::IfcRepresentation* representation_mapped_to(const IfcSchema::IfcRepresentation* representation); IfcSchema::IfcProduct::list::ptr products_represented_by(const IfcSchema::IfcRepresentation*); @@ -299,6 +301,25 @@ public: #include "IfcRegisterGeomHeader.h" + virtual void setValue(GeomValue var, double value); + virtual double getValue(GeomValue var) const; + + virtual IfcGeom::BRepElement* convert( + const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation, + IfcUtil::IfcBaseClass* product) + { + return create_brep_for_representation_and_product(settings, (IfcSchema::IfcRepresentation*) representation, (IfcSchema::IfcProduct*) product); + } + + virtual IfcRepresentationShapeItems convert(IfcUtil::IfcBaseClass* item) { + IfcRepresentationShapeItems items; + bool success = convert_shapes(item, items); + if (!success) { + throw IfcParse::IfcException("Failed to process representation item"); + } + return items; + } + }; IFC_GEOM_API IfcSchema::IfcProductDefinitionShape* tesselate(const TopoDS_Shape& shape, double deflection); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 4f4bdc2857..9bf02beafe 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -145,6 +145,68 @@ #endif #endif + +#define MAKE_INIT_FN__(a, b) init_ ## a ## b +#define MAKE_INIT_FN_(a, b) MAKE_INIT_FN__(a, b) +#define MAKE_INIT_FN(t) MAKE_INIT_FN_(t, IfcSchema) + +void MAKE_INIT_FN(Kernel)(IfcGeom::impl::KernelFactoryImplementation* mapping) { + static const std::string schema_name = STRINGIFY(IfcSchema); + + struct { + IfcGeom::Kernel* operator()(IfcParse::IfcFile* file) const { + IfcGeom::MAKE_TYPE_NAME(Kernel)* k = new IfcGeom::MAKE_TYPE_NAME(Kernel); + if (file) { + double unit_magnitude = 1.; + + // Set unit information from file + + IfcSchema::IfcProject::list::ptr projects = file->instances_by_type(); + if (projects->size() == 1) { + IfcSchema::IfcProject* project = *projects->begin(); + std::pair unit_info = k->initializeUnits(project->UnitsInContext()); + unit_magnitude = unit_info.second; + } + + // Set precision from file + + double lowest_precision_encountered = std::numeric_limits::infinity(); + bool any_precision_encountered = false; + + IfcSchema::IfcGeometricRepresentationContext::list::it it; + IfcSchema::IfcGeometricRepresentationContext::list::ptr contexts = + file->instances_by_type(); + + for (it = contexts->begin(); it != contexts->end(); ++it) { + IfcSchema::IfcGeometricRepresentationContext* context = *it; + if (context->hasPrecision() && context->Precision() < lowest_precision_encountered) { + // Some arbitrary factor that has proven to work better for the models in the set of test files. + lowest_precision_encountered = context->Precision() * unit_magnitude * 10.; + any_precision_encountered = true; + } + } + + double precision_to_set = 1.e-5; + + if (any_precision_encountered) { + if (lowest_precision_encountered < 1.e-7) { + Logger::Message(Logger::LOG_WARNING, "Precision lower than 0.0000001 meter not enforced"); + precision_to_set = 1.e-7; + } else { + precision_to_set = lowest_precision_encountered; + } + } + + k->setValue(IfcGeom::Kernel::GV_PRECISION, precision_to_set); + } + return k; + } + } factory; + + mapping->bind(schema_name, factory); +} + + #define Kernel MAKE_TYPE_NAME(Kernel) bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) { @@ -1785,15 +1847,6 @@ bool IfcGeom::Kernel::project(const Handle_Geom_Curve& crv, const gp_Pnt& pt, gp return true; } -int IfcGeom::Kernel::count(const TopoDS_Shape& s, TopAbs_ShapeEnum t) { - int i = 0; - TopExp_Explorer exp(s, t); - for (; exp.More(); exp.Next()) { - ++i; - } - return i; -} - bool IfcGeom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pnt& start, gp_Pnt& end) { IfcSchema::IfcRepresentation* axis_representation = find_representation(wall, "Axis"); if (!axis_representation) { diff --git a/src/ifcgeom/IfcGeomIteratorImplementation.cpp b/src/ifcgeom/IfcGeomIteratorImplementation.cpp index 61099544b0..d8cca8dd5f 100644 --- a/src/ifcgeom/IfcGeomIteratorImplementation.cpp +++ b/src/ifcgeom/IfcGeomIteratorImplementation.cpp @@ -10,12 +10,9 @@ namespace IfcGeom { #define MAKE_INIT_FN_(a, b) MAKE_INIT_FN__(a, b) #define MAKE_INIT_FN(t) MAKE_INIT_FN_(t, IfcSchema) -#define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) - template void MAKE_INIT_FN(IteratorImplementation_)(IteratorFactoryImplementation

* mapping) { - static const std::string schema_name = TOSTRING(IfcSchema); + static const std::string schema_name = STRINGIFY(IfcSchema); struct { IfcGeom::IteratorImplementation

* operator()(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file) const { @@ -27,4 +24,4 @@ void MAKE_INIT_FN(IteratorImplementation_)(IteratorFactoryImplementation

* map } template void MAKE_INIT_FN(IteratorImplementation_)(IteratorFactoryImplementation*); -template void MAKE_INIT_FN(IteratorImplementation_)(IteratorFactoryImplementation*); \ No newline at end of file +template void MAKE_INIT_FN(IteratorImplementation_)(IteratorFactoryImplementation*); diff --git a/src/ifcgeom/IfcGeomRepresentation.h b/src/ifcgeom/IfcGeomRepresentation.h index 84a025d057..db6b6cdeca 100644 --- a/src/ifcgeom/IfcGeomRepresentation.h +++ b/src/ifcgeom/IfcGeomRepresentation.h @@ -27,8 +27,9 @@ #include #include -#include +#include #include +#include #include #include @@ -203,13 +204,13 @@ namespace IfcGeom { gp_Vec normal_direction; prop.Normal(uv.X(),uv.Y(),p,normal_direction); gp_Vec normal(0., 0., 0.); - if (normal_direction.Magnitude() > ALMOST_ZERO) { + if (normal_direction.Magnitude() > 1.e-9) { normal = gp_Dir(normal_direction.XYZ() * rotation_matrix); } else { Handle_Geom_Surface surf = BRep_Tool::Surface(face); // Special case the normal at the poles of a spherical surface if (surf->DynamicType() == STANDARD_TYPE(Geom_SphericalSurface)) { - if (ALMOST_THE_SAME(fabs(uv.Y()), M_PI / 2.)) { + if (fabs(fabs(uv.Y()) - M_PI / 2.) < 1.e-9) { const bool is_top = uv.Y() > 0; const bool is_forward = face.Orientation() == TopAbs_FORWARD; const double z = (is_top == is_forward) ? 1. : -1.; diff --git a/src/ifcgeom/IfcGeomTree.h b/src/ifcgeom/IfcGeomTree.h index 7d93417052..8911183b58 100644 --- a/src/ifcgeom/IfcGeomTree.h +++ b/src/ifcgeom/IfcGeomTree.h @@ -21,7 +21,9 @@ #define IFCGEOMTREE_H #include "../ifcparse/IfcFile.h" -#include "../ifcgeom/IfcGeomIterator.h" +#include "../ifcgeom/IfcGeomElement.h" +#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h" +#include "../ifcgeom_schema_agnostic/Kernel.h" #include #include @@ -243,7 +245,7 @@ namespace IfcGeom { }; } - class tree : public impl::tree { + class tree : public impl::tree { public: tree() {}; @@ -267,7 +269,7 @@ namespace IfcGeom { if (it.initialize()) { do { IfcGeom::BRepElement* elem = (IfcGeom::BRepElement*)it.get(); - add((IfcSchema::IfcProduct*)f.entityById(elem->id()), elem->geometry().as_compound()); + add((IfcUtil::IfcBaseEntity*)f.instance_by_id(elem->id()), elem->geometry().as_compound()); } while (it.next()); } } diff --git a/src/ifcgeom_schema_agnostic/IteratorImplementation.h b/src/ifcgeom_schema_agnostic/IteratorImplementation.h index 70992f1419..ddcac38439 100644 --- a/src/ifcgeom_schema_agnostic/IteratorImplementation.h +++ b/src/ifcgeom_schema_agnostic/IteratorImplementation.h @@ -47,14 +47,6 @@ public: template IteratorFactoryImplementation

& iterator_implementations(); -template -class Registrar { -public: - Registrar(const std::string& schema_name, const typename get_factory_type::type& fn) { - iterator_implementations().bind(schema_name, fn); - } -}; - namespace IfcGeom { template diff --git a/src/ifcgeom_schema_agnostic/Kernel.cpp b/src/ifcgeom_schema_agnostic/Kernel.cpp new file mode 100644 index 0000000000..79637f6638 --- /dev/null +++ b/src/ifcgeom_schema_agnostic/Kernel.cpp @@ -0,0 +1,49 @@ +#include "Kernel.h" + +IfcGeom::Kernel::Kernel(IfcParse::IfcFile* file) { + if (file != 0) { + if (file->schema() == 0) { + throw IfcParse::IfcException("No schema associated with file"); + } + + const std::string& schema_name = file->schema()->name(); + impl::kernel_implementations().construct(schema_name, file); + } +} + +int IfcGeom::Kernel::count(const TopoDS_Shape& s, TopAbs_ShapeEnum t) { + int i = 0; + TopExp_Explorer exp(s, t); + for (; exp.More(); exp.Next()) { + ++i; + } + return i; +} + +IfcGeom::impl::KernelFactoryImplementation& IfcGeom::impl::kernel_implementations() { + static KernelFactoryImplementation impl; + return impl; +} + +extern void init_KernelImplementation_Ifc2x3(IfcGeom::impl::KernelFactoryImplementation*); +extern void init_KernelImplementation_Ifc4(IfcGeom::impl::KernelFactoryImplementation*); + +IfcGeom::impl::KernelFactoryImplementation::KernelFactoryImplementation() { + init_KernelImplementation_Ifc2x3(this); + init_KernelImplementation_Ifc4(this); +} + +void IfcGeom::impl::KernelFactoryImplementation::bind(const std::string& schema_name, IfcGeom::impl::kernel_fn fn) { + const std::string schema_name_lower = boost::to_lower_copy(schema_name); + this->insert(std::make_pair(schema_name_lower, fn)); +} + +IfcGeom::Kernel* IfcGeom::impl::KernelFactoryImplementation::construct(const std::string& schema_name, IfcParse::IfcFile* file) { + const std::string schema_name_lower = boost::to_lower_copy(schema_name); + std::map::const_iterator it; + it = this->find(schema_name_lower); + if (it == end()) { + throw IfcParse::IfcException("No geometry kernel registered for " + schema_name); + } + return it->second(file); +} diff --git a/src/ifcgeom_schema_agnostic/Kernel.h b/src/ifcgeom_schema_agnostic/Kernel.h index 8d3451f86c..a9632ea7de 100644 --- a/src/ifcgeom_schema_agnostic/Kernel.h +++ b/src/ifcgeom_schema_agnostic/Kernel.h @@ -1,8 +1,23 @@ #ifndef ITERATOR_KERNEL_H #define ITERATOR_KERNEL_H +#include "../ifcparse/IfcFile.h" +#include "../ifcgeom/IfcGeomIteratorSettings.h" +#include "../ifcgeom/IfcRepresentationShapeItem.h" + +#include + +#include + namespace IfcGeom { + + template + class BRepElement; + class Kernel { + private: + Kernel* implementation_; + public: // Tolerances and settings for various geometrical operations: enum GeomValue { @@ -37,9 +52,45 @@ namespace IfcGeom { // Whether to process shapes of type Face or higher (1) Wire or lower (-1) or all (0) GV_DIMENSIONALITY }; + + Kernel(IfcParse::IfcFile* file_ = 0); virtual ~Kernel() {} + + virtual void setValue(GeomValue var, double value) { + implementation_->setValue(var, value); + } + + virtual double getValue(GeomValue var) const { + return implementation_->getValue(var); + } + + virtual BRepElement* convert( + const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation, + IfcUtil::IfcBaseClass* product) + { + return implementation_->convert(settings, representation, product); + } + + virtual IfcRepresentationShapeItems convert(IfcUtil::IfcBaseClass* item) { + return implementation_->convert(item); + } + + static int count(const TopoDS_Shape&, TopAbs_ShapeEnum); }; + + namespace impl { + typedef boost::function1 kernel_fn; + + class KernelFactoryImplementation : public std::map { + public: + KernelFactoryImplementation(); + void bind(const std::string& schema_name, kernel_fn); + Kernel* construct(const std::string& schema_name, IfcParse::IfcFile*); + }; + + KernelFactoryImplementation& kernel_implementations(); + } } #endif \ No newline at end of file diff --git a/src/ifcparse/IfcLogger.cpp b/src/ifcparse/IfcLogger.cpp index 62d05ce8e3..fd7276e89e 100644 --- a/src/ifcparse/IfcLogger.cpp +++ b/src/ifcparse/IfcLogger.cpp @@ -18,7 +18,9 @@ ********************************************************************************/ #include "IfcLogger.h" + #include "../ifcparse/IfcException.h" +#include "../ifcparse/Argument.h" #include #include diff --git a/src/ifcparse/IfcLogger.h b/src/ifcparse/IfcLogger.h index e440934fd7..a403240c58 100644 --- a/src/ifcparse/IfcLogger.h +++ b/src/ifcparse/IfcLogger.h @@ -20,6 +20,8 @@ #ifndef IFCLOGGER_H #define IFCLOGGER_H +#include "../ifcparse/IfcBaseClass.h" + #include #include #include @@ -27,12 +29,6 @@ #include #include -#ifdef USE_IFC4 -#include "../ifcparse/Ifc4.h" -#else -#include "../ifcparse/Ifc2x3.h" -#endif - #include #include "ifc_parse_api.h" diff --git a/src/ifcparse/IfcParse.h b/src/ifcparse/IfcParse.h index ff892ee5cf..555396f77f 100644 --- a/src/ifcparse/IfcParse.h +++ b/src/ifcparse/IfcParse.h @@ -47,12 +47,6 @@ #include "../ifcparse/IfcLogger.h" #include "../ifcparse/Argument.h" -#ifdef USE_IFC4 -#include "../ifcparse/Ifc4.h" -#else -#include "../ifcparse/Ifc2x3.h" -#endif - #include "../ifcparse/IfcSpfStream.h" namespace IfcParse { diff --git a/src/ifcparse/IfcSchema.cpp b/src/ifcparse/IfcSchema.cpp index 72b2aef164..733df0406e 100644 --- a/src/ifcparse/IfcSchema.cpp +++ b/src/ifcparse/IfcSchema.cpp @@ -44,7 +44,9 @@ IfcParse::schema_definition::schema_definition(const std::string& name, const st , factory_(factory) { std::sort(declarations_.begin(), declarations_.end(), declaration_by_index_sort()); - for (std::vector::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) { + for (std::vector::iterator it = declarations_.begin(); it != declarations_.end(); ++it) { + (**it).schema_ = this; + if ((**it).as_type_declaration()) type_declarations_.push_back((**it).as_type_declaration()); if ((**it).as_select_type()) select_types_.push_back((**it).as_select_type()); if ((**it).as_enumeration_type()) enumeration_types_.push_back((**it).as_enumeration_type()); diff --git a/src/ifcparse/IfcSchema.h b/src/ifcparse/IfcSchema.h index 2b626c0df6..87bc67912c 100644 --- a/src/ifcparse/IfcSchema.h +++ b/src/ifcparse/IfcSchema.h @@ -55,6 +55,8 @@ namespace IfcParse { class simple_type; class aggregation_type; + class schema_definition; + class parameter_type { public: virtual const named_type* as_named_type() const { return static_cast(0); } @@ -118,19 +120,23 @@ namespace IfcParse { }; class declaration { + friend class schema_definition; + protected: std::string name_, name_lower_; int index_in_schema_; + mutable const schema_definition* schema_; public: declaration(const std::string& name, int index_in_schema) : name_(name) , name_lower_(boost::to_lower_copy(name)) , index_in_schema_(index_in_schema) + , schema_(0) {} - std::string name() const { return name_; } - std::string name_lc() const { return name_lower_; } + const std::string& name() const { return name_; } + const std::string& name_lc() const { return name_lower_; } virtual const type_declaration* as_type_declaration() const { return static_cast(0); } virtual const select_type* as_select_type() const { return static_cast(0); } @@ -143,6 +149,8 @@ namespace IfcParse { int index_in_schema() const { return index_in_schema_; } int type() const { return index_in_schema_; } + + const schema_definition* schema() const { return schema_; } }; class type_declaration : public declaration { diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index 794a6ef1cf..df13b77d4a 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -43,7 +43,7 @@ %include "../ifcgeom/IfcGeomElement.h" %include "../ifcgeom/IfcGeomMaterial.h" %include "../ifcgeom/IfcGeomRepresentation.h" -%include "../ifcgeom/IfcGeomIterator.h" +%include "../ifcgeom_schema_agnostic/IfcGeomIterator.h" // A Template instantantation should be defined before it is used as a base class. // But frankly I don't care as most methods are subtlely different anyway. @@ -51,42 +51,42 @@ %extend IfcGeom::tree { - static IfcEntityList::ptr vector_to_list(const std::vector& ps) const { + static IfcEntityList::ptr vector_to_list(const std::vector& ps) const { IfcEntityList::ptr r(new IfcEntityList); - for (std::vector::const_iterator it = ps.begin(); it != ps.end(); ++it) { + for (std::vector::const_iterator it = ps.begin(); it != ps.end(); ++it) { r->push(*it); } return r; } IfcEntityList::ptr select_box(IfcUtil::IfcBaseClass* e, bool completely_within = false, double extend=-1.e-5) const { - if (!e->declaration().is(IfcSchema::Type::IfcProduct)) { + if (!e->declaration().is("IfcProduct")) { throw IfcParse::IfcException("Instance should be an IfcProduct"); } - std::vector ps = $self->select_box((IfcSchema::IfcProduct*)e, completely_within, extend); + std::vector ps = $self->select_box((IfcUtil::IfcBaseEntity*)e, completely_within, extend); return IfcGeom_tree_vector_to_list(ps); } IfcEntityList::ptr select_box(const gp_Pnt& p) const { - std::vector ps = $self->select_box(p); + std::vector ps = $self->select_box(p); return IfcGeom_tree_vector_to_list(ps); } IfcEntityList::ptr select_box(const Bnd_Box& b, bool completely_within = false) const { - std::vector ps = $self->select_box(b, completely_within); + std::vector ps = $self->select_box(b, completely_within); return IfcGeom_tree_vector_to_list(ps); } IfcEntityList::ptr select(IfcUtil::IfcBaseClass* e, bool completely_within = false) const { - if (!e->declaration().is(IfcSchema::Type::IfcProduct)) { + if (!e->declaration().is("IfcProduct")) { throw IfcParse::IfcException("Instance should be an IfcProduct"); } - std::vector ps = $self->select((IfcSchema::IfcProduct*)e, completely_within); + std::vector ps = $self->select((IfcUtil::IfcBaseEntity*)e, completely_within); return IfcGeom_tree_vector_to_list(ps); } IfcEntityList::ptr select(const gp_Pnt& p) const { - std::vector ps = $self->select(p); + std::vector ps = $self->select(p); return IfcGeom_tree_vector_to_list(ps); } @@ -96,7 +96,7 @@ shapes.Read(stream); const TopoDS_Shape& shp = shapes.Shape(shapes.NbShapes()); - std::vector ps = $self->select(shp); + std::vector ps = $self->select(shp); return IfcGeom_tree_vector_to_list(ps); } @@ -299,41 +299,36 @@ struct ShapeRTTI : public boost::static_visitor %} }; -%inline %{ - boost::variant*, IfcGeom::Representation::Representation*> create_shape(IfcGeom::IteratorSettings& settings, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0) { +%{ + template + static boost::variant*, IfcGeom::Representation::Representation*> helper_fn_create_shape(IfcGeom::IteratorSettings& settings, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0) { IfcParse::IfcFile* file = instance->data().file; - IfcSchema::IfcProject::list::ptr projects = file->entitiesByType(); - if (projects->size() != 1) { - throw IfcParse::IfcException("Not a single IfcProject instance"); - } - IfcSchema::IfcProject* project = *projects->begin(); - IfcGeom::Kernel kernel; + IfcGeom::Kernel kernel(file); kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.get(IfcGeom::IteratorSettings::SEW_SHELLS) ? 1000 : -1); kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IfcGeom::IteratorSettings::INCLUDE_CURVES) ? (settings.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.)); - std::pair length_unit = kernel.initializeUnits(project->UnitsInContext()); - if (instance->declaration().is(IfcSchema::Type::IfcProduct)) { + if (instance->declaration().is(Schema::IfcProduct::Class())) { if (representation) { - if (!representation->declaration().is(IfcSchema::Type::IfcRepresentation)) { + if (!representation->declaration().is(Schema::IfcRepresentation::Class())) { throw IfcParse::IfcException("Supplied representation not of type IfcRepresentation"); } } - IfcSchema::IfcProduct* product = (IfcSchema::IfcProduct*) instance; + typename Schema::IfcProduct* product = (typename Schema::IfcProduct*) instance; if (!representation && !product->hasRepresentation()) { throw IfcParse::IfcException("Representation is NULL"); } - IfcSchema::IfcProductRepresentation* prodrep = product->Representation(); - IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations(); - IfcSchema::IfcRepresentation* ifc_representation = (IfcSchema::IfcRepresentation*) representation; + typename Schema::IfcProductRepresentation* prodrep = product->Representation(); + typename Schema::IfcRepresentation::list::ptr reps = prodrep->Representations(); + typename Schema::IfcRepresentation* ifc_representation = (typename Schema::IfcRepresentation*) representation; if (!ifc_representation) { // First, try to find a representation based on the settings - for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { - IfcSchema::IfcRepresentation* rep = *it; + for (typename Schema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { + typename Schema::IfcRepresentation* rep = *it; if (!rep->hasRepresentationIdentifier()) { continue; } @@ -354,9 +349,9 @@ struct ShapeRTTI : public boost::static_visitor // Otherwise, find a representation within the 'Model' or 'Plan' context if (!ifc_representation) { - for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { - IfcSchema::IfcRepresentation* rep = *it; - IfcSchema::IfcRepresentationContext* context = rep->ContextOfItems(); + for (typename Schema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { + typename Schema::IfcRepresentation* rep = *it; + typename Schema::IfcRepresentationContext* context = rep->ContextOfItems(); // TODO: Remove redundancy with IfcGeomIterator.h if (context->hasContextType()) { @@ -391,28 +386,7 @@ struct ShapeRTTI : public boost::static_visitor } } - IfcSchema::IfcRepresentationContext* ctx = ifc_representation->ContextOfItems(); - if (!ctx->declaration().is(IfcSchema::Type::IfcGeometricRepresentationContext)) { - throw IfcParse::IfcException("Context not of type IfcGeometricRepresentationContext"); - } - IfcSchema::IfcGeometricRepresentationContext* context = (IfcSchema::IfcGeometricRepresentationContext*) ctx; - if (context->declaration().is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) { - IfcSchema::IfcGeometricRepresentationSubContext* subcontext = (IfcSchema::IfcGeometricRepresentationSubContext*) context; - context = subcontext->ParentContext(); - } - - double precision = 1.e-6; - if (context->hasPrecision()) { - precision = context->Precision(); - } - precision *= length_unit.second; - - // Some arbitrary factor that has proven to work better for the models in the set of test files. - precision *= 10.; - - kernel.setValue(IfcGeom::Kernel::GV_PRECISION, precision); - - IfcGeom::BRepElement* brep = kernel.create_brep_for_representation_and_product(settings, ifc_representation, product); + IfcGeom::BRepElement* brep = kernel.convert(settings, ifc_representation, product); if (!brep) { throw IfcParse::IfcException("Failed to process shape"); } @@ -429,22 +403,19 @@ struct ShapeRTTI : public boost::static_visitor } } else { if (!representation) { - if (instance->declaration().is(IfcSchema::Type::IfcRepresentationItem) || instance->declaration().is(IfcSchema::Type::IfcRepresentation)) { - IfcGeom::IfcRepresentationShapeItems shapes; - if (kernel.convert_shapes(instance, shapes)) { - IfcGeom::ElementSettings element_settings(settings, kernel.getValue(IfcGeom::Kernel::GV_LENGTH_UNIT), IfcSchema::Type::ToString(instance->declaration().type())); - IfcGeom::Representation::BRep brep(element_settings, boost::lexical_cast(instance->data().id()), shapes); - try { - if (settings.get(IfcGeom::IteratorSettings::USE_BREP_DATA)) { - return new IfcGeom::Representation::Serialization(brep); - } else if (!settings.get(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION)) { - return new IfcGeom::Representation::Triangulation(brep); - } - } catch (...) { - throw IfcParse::IfcException("Error during shape serialization"); + if (instance->declaration().is(Schema::IfcRepresentationItem::Class()) || instance->declaration().is(Schema::IfcRepresentation::Class())) { + IfcGeom::IfcRepresentationShapeItems shapes = kernel.convert(instance); + + IfcGeom::ElementSettings element_settings(settings, kernel.getValue(IfcGeom::Kernel::GV_LENGTH_UNIT), instance->declaration().name()); + IfcGeom::Representation::BRep brep(element_settings, boost::lexical_cast(instance->data().id()), shapes); + try { + if (settings.get(IfcGeom::IteratorSettings::USE_BREP_DATA)) { + return new IfcGeom::Representation::Serialization(brep); + } else if (!settings.get(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION)) { + return new IfcGeom::Representation::Triangulation(brep); } - } else { - throw IfcParse::IfcException("Geometrical element not understood"); + } catch (...) { + throw IfcParse::IfcException("Error during shape serialization"); } } } else { @@ -453,7 +424,23 @@ struct ShapeRTTI : public boost::static_visitor } return boost::variant*, IfcGeom::Representation::Representation*>(); } +%} +%inline %{ + static boost::variant*, IfcGeom::Representation::Representation*> create_shape(IfcGeom::IteratorSettings& settings, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0) { + const std::string& schema_name = instance->declaration().schema()->name(); + if (schema_name == "IFC2X3") { + return helper_fn_create_shape(settings, instance, representation); + } else if (schema_name == "IFC4") { + return helper_fn_create_shape(settings, instance, representation); + } else { + throw IfcParse::IfcException("No geometry support for " + schema_name); + } + } +%} + +/* +%inline %{ IfcUtil::IfcBaseClass* serialise(const std::string& s, bool advanced=true) { std::stringstream stream(s); BRepTools_ShapeSet shapes; @@ -472,6 +459,7 @@ struct ShapeRTTI : public boost::static_visitor return IfcGeom::tesselate(shp, d); } %} +*/ namespace IfcGeom { %template(iterator_single_precision) Iterator; diff --git a/src/ifcwrap/IfcParseWrapper.i b/src/ifcwrap/IfcParseWrapper.i index eefa58e813..0836722e96 100644 --- a/src/ifcwrap/IfcParseWrapper.i +++ b/src/ifcwrap/IfcParseWrapper.i @@ -58,12 +58,18 @@ private: %rename("add") addEntity; %rename("remove") removeEntity; +%{ +static const std::string& helper_fn_declaration_get_name(const IfcParse::declaration* decl) { + return decl->name(); +} +%} + %extend IfcParse::IfcFile { IfcUtil::IfcBaseClass* by_guid(const std::string& guid) { - return $self->entityByGuid(guid); + return $self->instance_by_guid(guid); } IfcEntityList::ptr get_inverse(IfcUtil::IfcBaseClass* e) { - return $self->getInverse(e->data().id(), IfcSchema::Type::UNDEFINED, -1); + return $self->getInverse(e->data().id(), 0, -1); } void write(const std::string& fn) { @@ -84,7 +90,7 @@ private: const size_t n = std::distance($self->types_begin(), $self->types_end()); std::vector ts; ts.reserve(n); - std::transform($self->types_begin(), $self->types_end(), std::back_inserter(ts), IfcSchema::Type::ToString); + std::transform($self->types_begin(), $self->types_end(), std::back_inserter(ts), helper_fn_declaration_get_name); return ts; } @@ -92,7 +98,7 @@ private: const size_t n = std::distance($self->types_incl_super_begin(), $self->types_incl_super_end()); std::vector ts; ts.reserve(n); - std::transform($self->types_incl_super_begin(), $self->types_incl_super_end(), std::back_inserter(ts), IfcSchema::Type::ToString); + std::transform($self->types_incl_super_begin(), $self->types_incl_super_end(), std::back_inserter(ts), helper_fn_declaration_get_name); return ts; } @@ -106,7 +112,7 @@ private: %extend IfcUtil::IfcBaseClass { int get_attribute_category(const std::string& name) const { - if (IfcSchema::Type::IsSimple($self->declaration().type())) { + if (!$self->declaration().as_entity()) { return name == "wrappedValue"; } @@ -177,7 +183,7 @@ private: } bool is_a(const std::string& s) { - return self->declaration().is(IfcSchema::Type::FromString(boost::to_upper_copy(s))); + return self->declaration().is(s); } std::string is_a() const { @@ -197,7 +203,7 @@ private: if ($self == other) { return true; } - if (IfcSchema::Type::IsSimple($self->declaration().type()) || IfcSchema::Type::IsSimple(other->declaration().type())) { + if (!$self->declaration().as_entity() || !other->declaration().as_entity()) { /// @todo return false; } else { @@ -226,7 +232,7 @@ private: for (; it != attrs.end(); ++it) { if ((*it)->name() == a) { return self->data().getInverse( - (*it)->entity_reference()->type(), + (*it)->entity_reference(), (*it)->entity_reference()->attribute_index((*it)->attribute_reference())); } } @@ -286,7 +292,7 @@ private: arg->set(a); self->data().setArgument(i, arg); } else if (arg_type == IfcUtil::Argument_ENUMERATION) { - const IfcParse::enumeration_type* enum_type = get_schema().declaration_by_name($self->declaration().type())->as_entity()-> + 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(); std::vector::const_iterator it = std::find( @@ -489,48 +495,35 @@ private: %inline %{ IfcParse::IfcFile* open(const std::string& fn) { - IfcParse::IfcFile* f = new IfcParse::IfcFile(); - f->Init(fn); + IfcParse::IfcFile* f = new IfcParse::IfcFile(fn); return f; } + IfcParse::IfcFile* read(const std::string& data) { char* copiedData = new char[data.length()]; memcpy(copiedData, data.c_str(), data.length()); - IfcParse::IfcFile* f = new IfcParse::IfcFile(); - f->Init((void *)copiedData, data.length()); + IfcParse::IfcFile* f = new IfcParse::IfcFile((void *)copiedData, data.length()); return f; } - const char* schema_identifier() { - return IfcSchema::Identifier; - } const char* version() { return IFCOPENSHELL_VERSION; } - std::string get_supertype(std::string n) { - boost::to_upper(n); - IfcSchema::Type::Enum t = IfcSchema::Type::FromString(n); - if (IfcSchema::Type::Parent(t)) { - return IfcSchema::Type::ToString(*IfcSchema::Type::Parent(t)); - } else { - return ""; - } - } - - IfcUtil::IfcBaseClass* new_IfcBaseClass(const std::string& s) { - IfcSchema::Type::Enum ty = IfcSchema::Type::FromString(boost::to_upper_copy(s)); - IfcEntityInstanceData* data = new IfcEntityInstanceData(ty); + 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 = new IfcEntityInstanceData(decl); size_t attr_count = 1; - if (get_schema().declaration_by_name(ty)->as_entity()) { - attr_count = get_schema().declaration_by_name(ty)->as_entity()->attribute_count(); + if (decl->as_entity()) { + attr_count = decl->as_entity()->attribute_count(); } data->setArgument(attr_count - 1, new IfcWrite::IfcWriteArgument()); - if (get_schema().declaration_by_name(ty)->as_entity()) { - const std::vector& derived = get_schema().declaration_by_name(ty)->as_entity()->derived(); + if (decl->as_entity()) { + const std::vector& derived = decl->as_entity()->derived(); std::vector::const_iterator it = derived.begin(); size_t index = 0; @@ -543,7 +536,7 @@ private: } } - return IfcSchema::SchemaEntity(data); + return schema->instantiate(data); } %} diff --git a/src/ifcwrap/IfcPython.i b/src/ifcwrap/IfcPython.i index 9dd6311559..76d666b219 100644 --- a/src/ifcwrap/IfcPython.i +++ b/src/ifcwrap/IfcPython.i @@ -70,10 +70,11 @@ } %module ifcopenshell_wrapper %{ - #include "../ifcgeom/IfcGeom.h" - #include "../ifcgeom/IfcGeomIterator.h" + #include "../ifcgeom_schema_agnostic/IfcGeomIterator.h" #include "../ifcgeom/IfcGeomTree.h" + #include "../ifcparse/Ifc2x3.h" + #include "../ifcparse/Ifc4.h" #include "../ifcparse/IfcBaseClass.h" #include "../ifcparse/IfcFile.h"