From 2a403e240db4455744e006960bcf051e965e0b33 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 19 Dec 2014 12:14:36 +0000 Subject: [PATCH] *** See: https://sourceforge.net/p/ifcopenshell/discussion/1782718/thread/6bd0f843/ *** Massive refactor of the IfcGeomObjects module, which is now the IfcGeom::Iterator class. --- .../io_import_scene_ifc/__init__.py | 35 +- src/ifcconvert/ColladaSerializer.cpp | 51 +- src/ifcconvert/ColladaSerializer.h | 36 +- src/ifcconvert/GeometrySerializer.h | 6 +- src/ifcconvert/IfcConvert.cpp | 51 +- src/ifcconvert/IgesSerializer.h | 2 +- src/ifcconvert/OpenCascadeBasedSerializer.cpp | 12 +- src/ifcconvert/OpenCascadeBasedSerializer.h | 6 +- src/ifcconvert/StepSerializer.h | 2 +- src/ifcconvert/WavefrontObjSerializer.cpp | 17 +- src/ifcconvert/WavefrontObjSerializer.h | 6 +- src/ifcgeom/IfcGeom.h | 67 +- src/ifcgeom/IfcGeomCurves.cpp | 24 +- src/ifcgeom/IfcGeomElement.h | 144 +++ src/ifcgeom/IfcGeomFaces.cpp | 240 ++--- src/ifcgeom/IfcGeomFunctions.cpp | 94 +- src/ifcgeom/IfcGeomHelpers.cpp | 99 +- src/ifcgeom/IfcGeomIterator.h | 635 +++++++++++++ src/ifcgeom/IfcGeomIteratorSettings.h | 171 ++++ src/ifcgeom/IfcGeomMaterial.cpp | 34 + src/ifcgeom/IfcGeomMaterial.h | 50 + src/ifcgeom/IfcGeomObjects.cpp | 858 ------------------ src/ifcgeom/IfcGeomObjects.h | 286 ------ src/ifcgeom/IfcGeomRenderStyles.cpp | 29 +- src/ifcgeom/IfcGeomRenderStyles.h | 98 +- src/ifcgeom/IfcGeomRepresentation.cpp | 59 ++ src/ifcgeom/IfcGeomRepresentation.h | 270 ++++++ src/ifcgeom/IfcGeomShapes.cpp | 200 ++-- src/ifcgeom/IfcGeomUtils.cpp | 42 + src/ifcgeom/IfcGeomUtils.h | 30 + src/ifcgeom/IfcGeomWires.cpp | 66 +- src/ifcgeom/IfcRegister.cpp | 40 +- src/ifcgeom/IfcRegister.h | 2 - src/ifcgeom/IfcRegisterConvertShapes.h | 2 +- src/ifcgeom/IfcRegisterGeomHeader.h | 2 +- src/ifcgeomserver/IfcGeomServer.cpp | 46 +- src/ifcmax/IfcMax.cpp | 47 +- src/ifcparse/IfcParse.h | 2 - src/ifcwrap/IfcPython.i | 156 +++- win/IfcGeom.vcproj | 42 +- win/IfcWrap.vcproj | 4 +- 41 files changed, 2227 insertions(+), 1836 deletions(-) create mode 100644 src/ifcgeom/IfcGeomElement.h create mode 100644 src/ifcgeom/IfcGeomIterator.h create mode 100644 src/ifcgeom/IfcGeomIteratorSettings.h create mode 100644 src/ifcgeom/IfcGeomMaterial.cpp create mode 100644 src/ifcgeom/IfcGeomMaterial.h delete mode 100644 src/ifcgeom/IfcGeomObjects.cpp delete mode 100644 src/ifcgeom/IfcGeomObjects.h create mode 100644 src/ifcgeom/IfcGeomRepresentation.cpp create mode 100644 src/ifcgeom/IfcGeomRepresentation.h create mode 100644 src/ifcgeom/IfcGeomUtils.cpp create mode 100644 src/ifcgeom/IfcGeomUtils.h diff --git a/src/ifcblender/io_import_scene_ifc/__init__.py b/src/ifcblender/io_import_scene_ifc/__init__.py index 730618f5dc..93e7cc1fe8 100644 --- a/src/ifcblender/io_import_scene_ifc/__init__.py +++ b/src/ifcblender/io_import_scene_ifc/__init__.py @@ -41,8 +41,8 @@ bl_info = { if "bpy" in locals(): import imp - if "IfcImport" in locals(): - imp.reload(IfcImport) + if "ifcopenshell" in locals(): + imp.reload(ifcopenshell) import bpy import mathutils @@ -63,11 +63,12 @@ bpy.types.Object.ifc_type = StringProperty(name="IFC Entity Type", def import_ifc(filename, use_names, process_relations): - from . import IfcImport + from . import ifcopenshell print("Reading %s..."%bpy.path.basename(filename)) - valid_file = IfcImport.Init(filename) + settings = ifcopenshell.IteratorSettings() + iterator = ifcopenshell.Iterator(settings, filename) + valid_file = iterator.findContext() if not valid_file: - IfcImport.CleanUp() return False print("Done reading file") id_to_object = {} @@ -76,13 +77,13 @@ def import_ifc(filename, use_names, process_relations): old_progress = -1 print("Creating geometry...") while True: - ob = IfcImport.Get() + ob = iterator.get() - f = ob.mesh.faces - v = ob.mesh.verts - mats = ob.mesh.materials - matids = ob.mesh.material_ids - m = ob.matrix + f = ob.geometry.faces + v = ob.geometry.verts + mats = ob.geometry.materials + matids = ob.geometry.material_ids + m = ob.transformation.matrix.data t = ob.type[0:21] nm = ob.name if len(ob.name) and use_names else ob.guid @@ -91,7 +92,7 @@ def import_ifc(filename, use_names, process_relations): faces = [[f[i], f[i + 1], f[i + 2]] \ for i in range(0, len(f), 3)] - me = bpy.data.meshes.new('mesh%d' % ob.mesh.id) + me = bpy.data.meshes.new('mesh%d' % ob.geometry.id) me.from_pydata(verts, [], faces) def add_material(mname, props): @@ -152,11 +153,11 @@ def import_ifc(filename, use_names, process_relations): for face, matid in zip(faces, matids): face.material_index = matid + (1 if needs_default else 0) - progress = IfcImport.Progress() // 2 + progress = iterator.progress() // 2 if progress > old_progress: print("\r[" + "#" * progress + " " * (50 - progress) + "]", end="") old_progress = progress - if not IfcImport.Next(): + if not iterator.next(): break print("\rDone creating geometry" + " " * 30) @@ -172,7 +173,7 @@ def import_ifc(filename, use_names, process_relations): if parent_id in id_to_object: bob = id_to_object[parent_id][0] else: - parent_ob = IfcImport.GetObject(parent_id) + parent_ob = iterator.GetObject(parent_id) if parent_ob.id == -1: bob = None else: @@ -220,10 +221,8 @@ def import_ifc(filename, use_names, process_relations): print("Done processing relations") txt = bpy.data.texts.new("%s.log"%bpy.path.basename(filename)) - txt.from_string(IfcImport.GetLog()) + txt.from_string(iterator.getLog()) - IfcImport.CleanUp() - return True diff --git a/src/ifcconvert/ColladaSerializer.cpp b/src/ifcconvert/ColladaSerializer.cpp index 908022a7ff..7f69d2d7bf 100644 --- a/src/ifcconvert/ColladaSerializer.cpp +++ b/src/ifcconvert/ColladaSerializer.cpp @@ -35,7 +35,7 @@ std::string collada_id(const std::string& s) { return id; } -void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector& floats, const char* coords /* = "XYZ" */) { +void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector& floats, const char* coords /* = "XYZ" */) { COLLADASW::FloatSource source(mSW); source.setId(mesh_id + suffix); source.setArrayId(mesh_id + suffix + COLLADASW::LibraryGeometries::ARRAY_ID_SUFFIX); @@ -45,13 +45,18 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const source.getParameterNameList().push_back(std::string(1, coords[i])); } source.prepareToAppendValues(); - for (std::vector::const_iterator it = floats.begin(); it != floats.end(); ++it) { + for (std::vector::const_iterator it = floats.begin(); it != floats.end(); ++it) { source.appendValues(*it); } source.finish(); } -void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::string mesh_id, const std::string& default_material_name, const std::vector& positions, const std::vector& normals, const std::vector& indices, const std::vector material_ids, const std::vector& materials) { +void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::string mesh_id, const std::string& default_material_name, const std::vector& positions, const std::vector& normals, const std::vector& indices, const std::vector material_ids, const std::vector& materials) { + // The goal of the IfcGeom::Iterator is to filter out empty geometries, but + // since this function would crash trying to deference the material_ids in + // that case, a hard return statement is added just in case. + if (indices.empty()) return; + openMesh(mesh_id); // The normals vector can be empty for example when the WELD_VERTICES setting is used. @@ -70,17 +75,13 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::str std::vector::const_iterator index_range_start = indices.begin(); std::vector::const_iterator material_it = material_ids.begin(); - int previous_material_id = -2; + int previous_material_id = -1; for (std::vector::const_iterator it = indices.begin(); ; it += 3) { - const int current_material_id = material_it == material_ids.end() - ? -3 - : *(material_it++); + const int current_material_id = *(material_it++); const int num_triangles = std::distance(index_range_start, it) / 3; if ((previous_material_id != current_material_id && num_triangles > 0) || (it == indices.end())) { COLLADASW::Triangles triangles(mSW); - triangles.setMaterial(collada_id(previous_material_id < 0 - ? default_material_name - : materials[previous_material_id].name())); + triangles.setMaterial(materials[previous_material_id].name()); triangles.setCount(num_triangles); int offset = 0; triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX,"#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++ ) ); @@ -113,7 +114,7 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::close() { closeLibrary(); } -void ColladaSerializer::ColladaExporter::ColladaScene::add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector& material_ids, const std::vector& matrix) { +void ColladaSerializer::ColladaExporter::ColladaScene::add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector& material_ids, const std::vector& matrix) { if (!scene_opened) { openVisualScene(scene_id); scene_opened = true; @@ -155,7 +156,7 @@ void ColladaSerializer::ColladaExporter::ColladaScene::write() { } } -void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeomObjects::Material& material) { +void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeom::Material& material) { openEffect(collada_id(material.name()) + "-fx"); COLLADASW::EffectProfile effect(mSW); effect.setShaderType(COLLADASW::EffectProfile::LAMBERT); @@ -186,20 +187,20 @@ void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::close closeLibrary(); } -void ColladaSerializer::ColladaExporter::ColladaMaterials::add(const IfcGeomObjects::Material& material) { +void ColladaSerializer::ColladaExporter::ColladaMaterials::add(const IfcGeom::Material& material) { if (!contains(material)) { effects.write(material); materials.push_back(material); } } -bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const IfcGeomObjects::Material& material) { +bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const IfcGeom::Material& material) { return std::find(materials.begin(), materials.end(), material) != materials.end(); } void ColladaSerializer::ColladaExporter::ColladaMaterials::write() { effects.close(); - for (std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it) { + for (std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it) { const std::string& material_name = collada_id((*it).name()); openMaterial(material_name); addInstanceEffect("#" + material_name + "-fx"); @@ -218,18 +219,10 @@ void ColladaSerializer::ColladaExporter::startDocument(const std::string& unit_n asset.add(); } -void ColladaSerializer::ColladaExporter::writeTesselated(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector& matrix, const std::vector& vertices, const std::vector& normals, const std::vector& indices, const std::vector& material_ids, const std::vector& _materials) { - const IfcGeomObjects::Material default_for_type = IfcGeomObjects::Material(IfcGeom::get_default_style(type)); +void ColladaSerializer::ColladaExporter::write(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector& matrix, const std::vector& vertices, const std::vector& normals, const std::vector& indices, const std::vector& material_ids, const std::vector& _materials) { std::vector material_references; - const bool needs_default = std::find(material_ids.begin(), material_ids.end(), -1) != material_ids.end(); - if (needs_default) { - if (!materials.contains(default_for_type)) { - materials.add(default_for_type); - } - material_references.push_back(collada_id(default_for_type.name())); - } - for (std::vector::const_iterator it = _materials.begin(); it != _materials.end(); ++it) { - const IfcGeomObjects::Material& material = *it; + for (std::vector::const_iterator it = _materials.begin(); it != _materials.end(); ++it) { + const IfcGeom::Material& material = *it; if (!materials.contains(material)) { materials.add(material); } @@ -273,9 +266,9 @@ void ColladaSerializer::writeHeader() { exporter.startDocument(unit_name, unit_magnitude); } -void ColladaSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject* o) { - const IfcGeomObjects::IfcRepresentationTriangulation& mesh = o->mesh(); - exporter.writeTesselated(o->guid(), o->name(), o->type(), o->id(), o->matrix(), mesh.verts(), mesh.normals(), mesh.faces(), mesh.material_ids(), mesh.materials()); +void ColladaSerializer::write(const IfcGeom::TriangulationElement* o) { + const IfcGeom::Representation::Triangulation& mesh = o->geometry(); + exporter.write(o->guid(), o->name(), o->type(), o->id(), o->transformation().matrix().data(), mesh.verts(), mesh.normals(), mesh.faces(), mesh.material_ids(), mesh.materials()); } void ColladaSerializer::finalize() { diff --git a/src/ifcconvert/ColladaSerializer.h b/src/ifcconvert/ColladaSerializer.h index 7bb7f80e6d..3a34875b9e 100644 --- a/src/ifcconvert/ColladaSerializer.h +++ b/src/ifcconvert/ColladaSerializer.h @@ -35,7 +35,7 @@ #include #include -#include "../ifcgeom/IfcGeomObjects.h" +#include "../ifcgeom/IfcGeomIterator.h" #include "../ifcconvert/GeometrySerializer.h" @@ -51,8 +51,8 @@ private: explicit ColladaGeometries(COLLADASW::StreamWriter& stream) : COLLADASW::LibraryGeometries(&stream) {} - void addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector& floats, const char* coords = "XYZ"); - void write(const std::string mesh_id, const std::string& default_material_name, const std::vector& positions, const std::vector& normals, const std::vector& indices, const std::vector material_ids, const std::vector& materials); + void addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector& floats, const char* coords = "XYZ"); + void write(const std::string mesh_id, const std::string& default_material_name, const std::vector& positions, const std::vector& normals, const std::vector& indices, const std::vector material_ids, const std::vector& materials); void close(); }; class ColladaScene : public COLLADASW::LibraryVisualScenes @@ -66,7 +66,7 @@ private: , scene_id(scene_id) , scene_opened(false) {} - void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector& material_ids, const std::vector& matrix); + void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector& material_ids, const std::vector& matrix); void write(); }; class ColladaMaterials : public COLLADASW::LibraryMaterials @@ -78,34 +78,34 @@ private: explicit ColladaEffects(COLLADASW::StreamWriter& stream) : COLLADASW::LibraryEffects(&stream) {} - void write(const IfcGeomObjects::Material& material); + void write(const IfcGeom::Material& material); void close(); }; - std::vector materials; + std::vector materials; ColladaEffects effects; public: explicit ColladaMaterials(COLLADASW::StreamWriter& stream) : COLLADASW::LibraryMaterials(&stream) , effects(stream) {} - void add(const IfcGeomObjects::Material& material); - bool contains(const IfcGeomObjects::Material& material); + void add(const IfcGeom::Material& material); + bool contains(const IfcGeom::Material& material); void write(); }; class DeferredObject { public: std::string guid, name, type; int obj_id; - std::vector matrix; - std::vector vertices; - std::vector normals; + std::vector matrix; + std::vector vertices; + std::vector normals; std::vector indices; std::vector material_ids; - std::vector materials; + std::vector materials; std::vector material_references; - DeferredObject(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector& matrix, const std::vector& vertices, - const std::vector& normals, const std::vector& indices, const std::vector& material_ids, - const std::vector& materials, const std::vector& material_references) + DeferredObject(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector& matrix, const std::vector& vertices, + const std::vector& normals, const std::vector& indices, const std::vector& material_ids, + const std::vector& materials, const std::vector& material_references) : guid(guid) , name(name) , type(type) @@ -136,7 +136,7 @@ private: std::vector deferreds; virtual ~ColladaExporter() {} void startDocument(const std::string& unit_name, float unit_magnitude); - void writeTesselated(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector& matrix, const std::vector& vertices, const std::vector& normals, const std::vector& indices, const std::vector& material_ids, const std::vector& materials); + void write(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector& matrix, const std::vector& vertices, const std::vector& normals, const std::vector& indices, const std::vector& material_ids, const std::vector& materials); void endDocument(); }; ColladaExporter exporter; @@ -149,8 +149,8 @@ public: {} bool ready(); void writeHeader(); - void writeTesselated(const IfcGeomObjects::IfcGeomObject* o); - void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {} + void write(const IfcGeom::TriangulationElement* o); + void write(const IfcGeom::ShapeModelElement* o) {} void finalize(); bool isTesselated() const { return true; } void setUnitNameAndMagnitude(const std::string& name, float magnitude) { diff --git a/src/ifcconvert/GeometrySerializer.h b/src/ifcconvert/GeometrySerializer.h index c4895069a0..9310479237 100644 --- a/src/ifcconvert/GeometrySerializer.h +++ b/src/ifcconvert/GeometrySerializer.h @@ -20,7 +20,7 @@ #ifndef GEOMETRYSERIALIZER_H #define GEOMETRYSERIALIZER_H -#include "../ifcgeom/IfcGeomObjects.h" +#include "../ifcgeom/IfcGeomIterator.h" class GeometrySerializer { public: @@ -29,8 +29,8 @@ public: virtual void finalize() = 0; virtual bool isTesselated() const = 0; virtual ~GeometrySerializer() {} - virtual void writeTesselated(const IfcGeomObjects::IfcGeomObject* o) = 0; - virtual void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) = 0; + virtual void write(const IfcGeom::TriangulationElement* o) = 0; + virtual void write(const IfcGeom::ShapeModelElement* o) = 0; virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) = 0; }; diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 5cb7a04316..584f6c61e6 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -33,7 +33,7 @@ #include -#include "../ifcgeom/IfcGeomObjects.h" +#include "../ifcgeom/IfcGeomIterator.h" #include "../ifcconvert/ColladaSerializer.h" #include "../ifcconvert/IgesSerializer.h" @@ -177,13 +177,16 @@ int main(int argc, char** argv) { return 1; } - IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS, use_world_coords); - IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES, weld_vertices); - IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS, sew_shells); - IfcGeomObjects::Settings(IfcGeomObjects::CONVERT_BACK_UNITS, convert_back_units); - IfcGeomObjects::Settings(IfcGeomObjects::FASTER_BOOLEANS, merge_boolean_operands); - IfcGeomObjects::Settings(IfcGeomObjects::FORCE_CCW_FACE_ORIENTATION, force_ccw_face_orientation); - IfcGeomObjects::Settings(IfcGeomObjects::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions); + IfcGeom::IteratorSettings settings; + + settings.set(IfcGeom::IteratorSettings::APPLY_DEFAULT_MATERIALS, true); + settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, use_world_coords); + settings.set(IfcGeom::IteratorSettings::WELD_VERTICES, weld_vertices); + settings.set(IfcGeom::IteratorSettings::SEW_SHELLS, sew_shells); + settings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, convert_back_units); + settings.set(IfcGeom::IteratorSettings::FASTER_BOOLEANS, merge_boolean_operands); + settings.set(IfcGeom::IteratorSettings::FORCE_CCW_FACE_ORIENTATION, force_ccw_face_orientation); + settings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions); std::string output_extension = output_filename.substr(output_filename.size()-4); for (std::string::iterator c = output_extension.begin(); c != output_extension.end(); ++c) { @@ -198,7 +201,7 @@ int main(int argc, char** argv) { const std::string mtl_filename = output_filename.substr(0,output_filename.size()-3) + "mtl"; if (!use_world_coords) { Logger::Message(Logger::LOG_NOTICE, "Using world coords when writing WaveFront OBJ files"); - IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS, true); + settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true); } serializer = new WaveFrontOBJSerializer(output_filename, mtl_filename); #ifdef WITH_OPENCOLLADA @@ -219,6 +222,8 @@ int main(int argc, char** argv) { return 1; } + IfcGeom::Iterator context_iterator(settings, input_filename); + if (!serializer->ready()) { Logger::Message(Logger::LOG_ERROR, "Unable to open output file for writing"); write_log(); @@ -226,7 +231,7 @@ int main(int argc, char** argv) { } if (!serializer->isTesselated()) { - IfcGeomObjects::Settings(IfcGeomObjects::DISABLE_TRIANGULATION, true); + if (weld_vertices) { Logger::Message(Logger::LOG_NOTICE, "Weld vertices setting ignored when writing STEP or IGES files"); } @@ -235,14 +240,14 @@ int main(int argc, char** argv) { time_t start,end; time(&start); // Parse the file supplied in argv[1]. Returns true on succes. - if ( ! IfcGeomObjects::Init(input_filename, &std::cout, &log_stream) ) { + if (!context_iterator.findContext()) { Logger::Message(Logger::LOG_ERROR, "Unable to parse .ifc file or no geometrical entities found"); write_log(); return 1; } if (convert_back_units) { - serializer->setUnitNameAndMagnitude(IfcGeomObjects::GetUnitName(), IfcGeomObjects::GetUnitMagnitude()); + serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), context_iterator.getUnitMagnitude()); } else { serializer->setUnitNameAndMagnitude("METER", 1.0f); } @@ -255,16 +260,10 @@ int main(int argc, char** argv) { Logger::Status("Creating geometry..."); // The functions IfcGeomObjects::Get() and IfcGeomObjects::Next() wrap an iterator of all geometrical entities in the Ifc file. - // IfcGeomObjects::Get() returns an IfcGeomObjects::IfcGeomObject (see IfcGeomObjects.h for definition) + // IfcGeomObjects::Get() returns an IfcGeom::TriangulationElement (see IfcGeomIterator.h for definition) // IfcGeomObjects::Next() is used to poll whether more geometrical entities are available do { - const IfcGeomObjects::IfcObject* geom_object; - - if (serializer->isTesselated()) { - geom_object = IfcGeomObjects::Get(); - } else { - geom_object = IfcGeomObjects::GetShapeModel(); - } + const IfcGeom::Element* geom_object = context_iterator.get(); std::string lowercase_type = geom_object->type(); for (std::string::iterator c = lowercase_type.begin(); c != lowercase_type.end(); ++c) { @@ -273,16 +272,16 @@ int main(int argc, char** argv) { if (ignore_types.find(lowercase_type) != ignore_types.end()) continue; if (serializer->isTesselated()) { - serializer->writeTesselated(static_cast(geom_object)); + serializer->write(static_cast*>(geom_object)); } else { - serializer->writeShapeModel(static_cast(geom_object)); + serializer->write(static_cast*>(geom_object)); } - - const int progress = IfcGeomObjects::Progress() / 2; - if ( old_progress!= progress ) Logger::ProgressBar(progress); + + const int progress = context_iterator.progress() / 2; + if (old_progress!= progress) Logger::ProgressBar(progress); old_progress = progress; - } while ( IfcGeomObjects::Next() ); + } while (context_iterator.next()); serializer->finalize(); delete serializer; diff --git a/src/ifcconvert/IgesSerializer.h b/src/ifcconvert/IgesSerializer.h index d18082c642..8591af9902 100644 --- a/src/ifcconvert/IgesSerializer.h +++ b/src/ifcconvert/IgesSerializer.h @@ -24,7 +24,7 @@ #include #include -#include "../ifcgeom/IfcGeomObjects.h" +#include "../ifcgeom/IfcGeomIterator.h" #include "../ifcconvert/OpenCascadeBasedSerializer.h" diff --git a/src/ifcconvert/OpenCascadeBasedSerializer.cpp b/src/ifcconvert/OpenCascadeBasedSerializer.cpp index a141f5cab0..abff28b2e1 100644 --- a/src/ifcconvert/OpenCascadeBasedSerializer.cpp +++ b/src/ifcconvert/OpenCascadeBasedSerializer.cpp @@ -34,17 +34,19 @@ bool OpenCascadeBasedSerializer::ready() { return succeeded; } -void OpenCascadeBasedSerializer::writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) { - for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->mesh().begin(); it != o->mesh().end(); ++ it) { +void OpenCascadeBasedSerializer::write(const IfcGeom::ShapeModelElement* o) { + for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) { gp_GTrsf gtrsf = it->Placement(); + + const std::vector& matrix = o->transformation().matrix().data(); // Convert the matrix back into a transformation object. The tolerance values // are taken into consideration to reconstruct the form of the transformation. gp_Trsf o_trsf; o_trsf.SetValues( - o->matrix()[0], o->matrix()[3], o->matrix()[6], o->matrix()[ 9], - o->matrix()[1], o->matrix()[4], o->matrix()[7], o->matrix()[10], - o->matrix()[2], o->matrix()[5], o->matrix()[8], o->matrix()[11], + matrix[0], matrix[3], matrix[6], matrix[ 9], + matrix[1], matrix[4], matrix[7], matrix[10], + matrix[2], matrix[5], matrix[8], matrix[11], 1e-5, 1e-5 ); gtrsf.PreMultiply(o_trsf); diff --git a/src/ifcconvert/OpenCascadeBasedSerializer.h b/src/ifcconvert/OpenCascadeBasedSerializer.h index 15472363bd..78de4bcb1b 100644 --- a/src/ifcconvert/OpenCascadeBasedSerializer.h +++ b/src/ifcconvert/OpenCascadeBasedSerializer.h @@ -20,7 +20,7 @@ #ifndef OPENCASCADEBASEDSERIALIZER_H #define OPENCASCADEBASEDSERIALIZER_H -#include "../ifcgeom/IfcGeomObjects.h" +#include "../ifcgeom/IfcGeomIterator.h" #include "../ifcconvert/GeometrySerializer.h" @@ -38,8 +38,8 @@ public: void writeMaterial(const IfcGeom::SurfaceStyle& style) {} bool ready(); virtual void writeShape(const TopoDS_Shape& shape) = 0; - void writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {} - void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o); + void write(const IfcGeom::TriangulationElement* o) {} + void write(const IfcGeom::ShapeModelElement* o); bool isTesselated() const { return false; } }; diff --git a/src/ifcconvert/StepSerializer.h b/src/ifcconvert/StepSerializer.h index d0db600704..4667104a38 100644 --- a/src/ifcconvert/StepSerializer.h +++ b/src/ifcconvert/StepSerializer.h @@ -24,7 +24,7 @@ #include #include -#include "../ifcgeom/IfcGeomObjects.h" +#include "../ifcgeom/IfcGeomIterator.h" #include "../ifcconvert/OpenCascadeBasedSerializer.h" diff --git a/src/ifcconvert/WavefrontObjSerializer.cpp b/src/ifcconvert/WavefrontObjSerializer.cpp index 60dea650dc..a931a3028b 100644 --- a/src/ifcconvert/WavefrontObjSerializer.cpp +++ b/src/ifcconvert/WavefrontObjSerializer.cpp @@ -43,7 +43,7 @@ void WaveFrontOBJSerializer::writeHeader() { mtl_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << "\n"; } -void WaveFrontOBJSerializer::writeMaterial(const IfcGeomObjects::Material& style) { +void WaveFrontOBJSerializer::writeMaterial(const IfcGeom::Material& style) { mtl_stream << "newmtl " << style.name() << "\n"; if (style.hasDiffuse()) { const double* diffuse = style.diffuse(); @@ -65,7 +65,7 @@ void WaveFrontOBJSerializer::writeMaterial(const IfcGeomObjects::Material& style } } } -void WaveFrontOBJSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject* o) { +void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o) { std::string tmp = o->name().empty() ? o->guid() : o->name(); @@ -74,16 +74,16 @@ void WaveFrontOBJSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject obj_stream << "g " << name << "\n"; obj_stream << "s 1" << "\n"; - const IfcGeomObjects::IfcRepresentationTriangulation& mesh = o->mesh(); + const IfcGeom::Representation::Triangulation& mesh = o->geometry(); const int vcount = mesh.verts().size() / 3; - for ( std::vector::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) { + for ( std::vector::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) { const double x = *(it++); const double y = *(it++); const double z = *(it++); obj_stream << "v " << x << " " << y << " " << z << "\n"; } - for ( std::vector::const_iterator it = mesh.normals().begin(); it != mesh.normals().end(); ) { + for ( std::vector::const_iterator it = mesh.normals().begin(); it != mesh.normals().end(); ) { const double x = *(it++); const double y = *(it++); const double z = *(it++); @@ -97,12 +97,7 @@ void WaveFrontOBJSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject const int material_id = *(material_it++); if (material_id != previous_material_id) { - IfcGeomObjects::Material material(0); - if (material_id >= 0) { - material = mesh.materials()[material_id]; - } else { - material = IfcGeomObjects::Material(IfcGeom::get_default_style(o->type())); - } + const IfcGeom::Material& material = mesh.materials()[material_id]; const std::string material_name = material.name(); obj_stream << "usemtl " << material_name << "\n"; if (materials.find(material_name) == materials.end()) { diff --git a/src/ifcconvert/WavefrontObjSerializer.h b/src/ifcconvert/WavefrontObjSerializer.h index b31dcc1c94..0f6d3b220d 100644 --- a/src/ifcconvert/WavefrontObjSerializer.h +++ b/src/ifcconvert/WavefrontObjSerializer.h @@ -44,9 +44,9 @@ public: virtual ~WaveFrontOBJSerializer() {} bool ready(); void writeHeader(); - void writeMaterial(const IfcGeomObjects::Material& style); - void writeTesselated(const IfcGeomObjects::IfcGeomObject* o); - void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {} + void writeMaterial(const IfcGeom::Material& style); + void write(const IfcGeom::TriangulationElement* o); + void write(const IfcGeom::ShapeModelElement* o) {} void finalize() {} bool isTesselated() const { return true; } void setUnitNameAndMagnitude(const std::string& name, float magnitude) {} diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index d1081477ca..26580d190a 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -43,8 +43,23 @@ #include "../ifcgeom/IfcRepresentationShapeItem.h" +#define IN_CACHE(T,E,t,e) std::map::const_iterator it = cache.T.find(E->entity->id());\ +if ( it != cache.T.end() ) { e = it->second; return true; } +#define CACHE(T,E,e) cache.T[E->entity->id()] = e; + namespace IfcGeom { +class Cache { +public: +#include "IfcRegisterCreateCache.h" + std::map Style; + std::map Shape; +}; + +class Kernel { +private: + Cache cache; +public: // Tolerances and settings for various geometrical operations: enum GeomValue { // Specifies the deflection of the mesher @@ -103,17 +118,57 @@ namespace IfcGeom { double shape_volume(const TopoDS_Shape& s); double face_area(const TopoDS_Face& f); void apply_tolerance(TopoDS_Shape& s, double t); - void SetValue(GeomValue var, double value); - double GetValue(GeomValue var); + void setValue(GeomValue var, double value); + double getValue(GeomValue var); bool fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape); IfcSchema::IfcProductDefinitionShape* tesselate(TopoDS_Shape& shape, double deflection, IfcEntityList::ptr es); void remove_redundant_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.); + + const SurfaceStyle* get_style(const IfcSchema::IfcRepresentationItem* representation_item); - - namespace Cache { - void Purge(); - void PurgeShapeCache(); + template std::pair get_surface_style(const IfcSchema::IfcRepresentationItem* representation_item) { + IfcSchema::IfcStyledItem::list::ptr styled_items = representation_item->StyledByItem(); + for (IfcSchema::IfcStyledItem::list::it jt = styled_items->begin(); jt != styled_items->end(); ++jt) { +#ifdef USE_IFC4 + IfcUtil::IfcAbstractSelect::list::ptr style_assignments = (*jt)->Styles(); + for (IfcUtil::IfcAbstractSelect::list::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) { + if (!(*kt)->is(IfcSchema::Type::IfcPresentationStyleAssignment)) { + continue; + } + IfcSchema::IfcPresentationStyleAssignment* style_assignment = (IfcSchema::IfcPresentationStyleAssignment*) *kt; +#else + IfcSchema::IfcPresentationStyleAssignment::list::ptr style_assignments = (*jt)->Styles(); + for (IfcSchema::IfcPresentationStyleAssignment::list::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) { + IfcSchema::IfcPresentationStyleAssignment* style_assignment = *kt; +#endif + IfcUtil::IfcAbstractSelect::list::ptr styles = style_assignment->Styles(); + for (IfcUtil::IfcAbstractSelect::list::it lt = styles->begin(); lt != styles->end(); ++lt) { + IfcUtil::IfcAbstractSelect* style = *lt; + if (style->is(IfcSchema::Type::IfcSurfaceStyle)) { + IfcSchema::IfcSurfaceStyle* surface_style = (IfcSchema::IfcSurfaceStyle*) style; + if (surface_style->Side() != IfcSchema::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE) { + IfcUtil::IfcAbstractSelect::list::ptr styles_elements = surface_style->Styles(); + for (IfcUtil::IfcAbstractSelect::list::it mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) { + if ((*mt)->is(T::Class())) { + return std::make_pair(surface_style, (T*) *mt); + } + } + } + } + } + } + + // StyledByItem is a SET [0:1] OF IfcStyledItem, so we + // break after encountering the first IfcStyledItem + break; + } + + return std::make_pair(0,0); } + #include "IfcRegisterGeomHeader.h" + +}; + } #endif diff --git a/src/ifcgeom/IfcGeomCurves.cpp b/src/ifcgeom/IfcGeomCurves.cpp index 56ee23e6bb..7dfe8780b0 100644 --- a/src/ifcgeom/IfcGeomCurves.cpp +++ b/src/ifcgeom/IfcGeomCurves.cpp @@ -79,8 +79,8 @@ #include "../ifcgeom/IfcGeom.h" -bool IfcGeom::convert(const IfcSchema::IfcCircle* l, Handle(Geom_Curve)& curve) { - const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircle* l, Handle(Geom_Curve)& curve) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); if ( r < ALMOST_ZERO ) { Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", l->entity); return false; @@ -88,19 +88,19 @@ bool IfcGeom::convert(const IfcSchema::IfcCircle* l, Handle(Geom_Curve)& curve) gp_Trsf trsf; IfcSchema::IfcAxis2Placement placement = l->Position(); if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { - IfcGeom::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); + IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); } else { gp_Trsf2d trsf2d; - IfcGeom::convert((IfcAxis2Placement2D*)placement,trsf2d); + IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d); trsf = trsf2d; } gp_Ax2 ax = gp_Ax2().Transformed(trsf); curve = new Geom_Circle(ax, r); return true; } -bool IfcGeom::convert(const IfcSchema::IfcEllipse* l, Handle(Geom_Curve)& curve) { - double x = l->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT); - double y = l->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcEllipse* l, Handle(Geom_Curve)& curve) { + double x = l->SemiAxis1() * getValue(GV_LENGTH_UNIT); + double y = l->SemiAxis2() * getValue(GV_LENGTH_UNIT); if (x < ALMOST_ZERO || y < ALMOST_ZERO) { Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", l->entity); return false; @@ -113,10 +113,10 @@ bool IfcGeom::convert(const IfcSchema::IfcEllipse* l, Handle(Geom_Curve)& curve) gp_Trsf trsf; IfcSchema::IfcAxis2Placement placement = l->Position(); if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { - IfcGeom::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); + convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); } else { gp_Trsf2d trsf2d; - IfcGeom::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d); + convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d); trsf = trsf2d; } gp_Ax2 ax = gp_Ax2(); @@ -128,10 +128,10 @@ bool IfcGeom::convert(const IfcSchema::IfcEllipse* l, Handle(Geom_Curve)& curve) curve = new Geom_Ellipse(ax, x, y); return true; } -bool IfcGeom::convert(const IfcSchema::IfcLine* l, Handle(Geom_Curve)& curve) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcLine* l, Handle(Geom_Curve)& curve) { gp_Pnt pnt;gp_Vec vec; - IfcGeom::convert(l->Pnt(),pnt); - IfcGeom::convert(l->Dir(),vec); + convert(l->Pnt(),pnt); + convert(l->Dir(),vec); // See note at IfcGeomWires.cpp:237 curve = new Geom_Line(pnt,vec); return true; diff --git a/src/ifcgeom/IfcGeomElement.h b/src/ifcgeom/IfcGeomElement.h new file mode 100644 index 0000000000..c301f8d17c --- /dev/null +++ b/src/ifcgeom/IfcGeomElement.h @@ -0,0 +1,144 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +#ifndef IFCGEOMELEMENT_H +#define IFCGEOMELEMENT_H + +#include "../ifcgeom/IfcGeomRepresentation.h" +#include "../ifcgeom/IfcGeomIteratorSettings.h" + + +namespace IfcGeom { + + template + class Matrix { + private: + std::vector

_data; + public: + Matrix(const ElementSettings& settings, const gp_Trsf& trsf) { + // Convert the gp_Trsf into a 4x3 Matrix + // Note that in case the CONVERT_BACK_UNITS setting is enabled + // the translation component of the matrix needs to be divided + // by the magnitude of the IFC model length unit because + // internally in IfcOpenShell everything is measured in meters. + for(int i = 1; i < 5; ++i) { + for (int j = 1; j < 4; ++j) { + const double trsf_value = trsf.Value(j,i); + const double matrix_value = i == 4 && settings.convert_back_units() + ? trsf_value / settings.unit_magnitude() + : trsf_value; + _data.push_back(static_cast

(matrix_value)); + } + } + } + const std::vector

& data() const { return _data; } + }; + + template + class Transformation { + private: + gp_Trsf trsf; + Matrix

_matrix; + public: + Transformation(const ElementSettings& settings, const gp_Trsf& trsf) + : trsf(trsf) + , _matrix(settings, trsf) + {} + const gp_Trsf& data() const { return trsf; } + const Matrix

& matrix() const { return _matrix; } + }; + + template + class Element { + private: + int _id; + int _parent_id; + std::string _name; + std::string _type; + std::string _guid; + Transformation

_transformation; + public: + int id() const { return _id; } + int parent_id() const { return _parent_id; } + const std::string& name() const { return _name; } + const std::string& type() const { return _type; } + const std::string& guid() const { return _guid; } + const Transformation

& transformation() const { return _transformation; } + Element(const ElementSettings& settings, int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf) + : _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _transformation(settings, trsf) + {} + virtual ~Element() {} + }; + + template + class ShapeModelElement : public Element

{ + private: + Representation::BRep* _geometry; + public: + const Representation::BRep& geometry() const { return *_geometry; } + ShapeModelElement(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf, Representation::BRep* geometry) + : Element(geometry->settings(),id,parent_id,name,type,guid,trsf) + , _geometry(geometry) + {} + virtual ~ShapeModelElement() { + delete _geometry; + } + private: + ShapeModelElement(const ShapeModelElement& other); + ShapeModelElement& operator=(const ShapeModelElement& other); + }; + + template + class TriangulationElement : public Element

{ + private: + Representation::Triangulation

* _geometry; + public: + const Representation::Triangulation

& geometry() const { return *_geometry; } + TriangulationElement(const ShapeModelElement

& shape_model) + : Element

(shape_model) + , _geometry(new Representation::Triangulation

(shape_model.geometry())) + {} + virtual ~TriangulationElement() { + delete _geometry; + } + private: + TriangulationElement(const TriangulationElement& other); + TriangulationElement& operator=(const TriangulationElement& other); + }; + + template + class SerializedElement : public Element

{ + private: + Representation::Serialization* _geometry; + public: + const Representation::Serialization& geometry() const { return *_geometry; } + SerializedElement(const ShapeModelElement

& shape_model) + : Element

(shape_model) + , _geometry(new Representation::Serialization(shape_model.geometry())) + {} + virtual ~SerializedElement() { + delete _geometry; + } + private: + SerializedElement(const SerializedElement& other); + SerializedElement& operator=(const SerializedElement& other); + }; +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomFaces.cpp b/src/ifcgeom/IfcGeomFaces.cpp index 910586a02f..6e90ea84bc 100644 --- a/src/ifcgeom/IfcGeomFaces.cpp +++ b/src/ifcgeom/IfcGeomFaces.cpp @@ -97,12 +97,12 @@ #include "../ifcgeom/IfcGeom.h" -bool IfcGeom::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds(); IfcSchema::IfcFaceBound::list::it it = bounds->begin(); IfcSchema::IfcLoop* loop = (*it)->Bound(); TopoDS_Wire outer_wire; - if ( ! IfcGeom::convert_wire(loop,outer_wire) ) return false; + if ( ! convert_wire(loop,outer_wire) ) return false; BRepBuilderAPI_MakeFace mf (outer_wire); BRepBuilderAPI_FaceError er = mf.Error(); if ( er == BRepBuilderAPI_NotPlanar ) { @@ -119,7 +119,7 @@ bool IfcGeom::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { for( ++it; it != bounds->end(); ++ it) { IfcSchema::IfcLoop* loop = (*it)->Bound(); TopoDS_Wire wire; - if ( ! IfcGeom::convert_wire(loop,wire) ) return false; + if ( ! convert_wire(loop,wire) ) return false; mf.Add(wire); } if ( mf.IsDone() ) { @@ -137,7 +137,7 @@ bool IfcGeom::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { } } - if ( IfcGeom::GetValue(GV_FORCE_CCW_FACE_ORIENTATION)>0 ) { + if ( getValue(GV_FORCE_CCW_FACE_ORIENTATION)>0 ) { // Check the orientation of the face by comparing the // normal of the topological surface to the Newell's Method's // normal. Newell's Method is used for the normal calculation @@ -206,24 +206,24 @@ bool IfcGeom::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { return true; } -bool IfcGeom::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, TopoDS_Shape& face) { TopoDS_Wire wire; - if ( ! IfcGeom::convert_wire(l->OuterCurve(),wire) ) return false; + if ( ! convert_wire(l->OuterCurve(),wire) ) return false; TopoDS_Face f; - bool success = IfcGeom::convert_wire_to_face(wire, f); + bool success = convert_wire_to_face(wire, f); if (success) face = f; return success; } -bool IfcGeom::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids* l, TopoDS_Shape& face) { TopoDS_Wire profile; - if ( ! IfcGeom::convert_wire(l->OuterCurve(),profile) ) return false; + if ( ! convert_wire(l->OuterCurve(),profile) ) return false; BRepBuilderAPI_MakeFace mf(profile); IfcSchema::IfcCurve::list::ptr voids = l->InnerCurves(); for( IfcSchema::IfcCurve::list::it it = voids->begin(); it != voids->end(); ++ it ) { TopoDS_Wire hole; - if ( IfcGeom::convert_wire(*it,hole) ) { + if ( convert_wire(*it,hole) ) { mf.Add(hole); } } @@ -233,9 +233,9 @@ bool IfcGeom::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids* l, TopoD return true; } -bool IfcGeom::convert(const IfcSchema::IfcRectangleProfileDef* l, TopoDS_Shape& face) { - const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleProfileDef* l, TopoDS_Shape& face) { + const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); @@ -243,15 +243,15 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangleProfileDef* l, TopoDS_Shape& } gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + IfcGeom::Kernel::convert(l->Position(),trsf2d); double coords[8] = {-x,-y,x,-y,x,y,-x,y}; - return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face); + return profile_helper(4,coords,0,0,0,trsf2d,face); } -bool IfcGeom::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, TopoDS_Shape& face) { - const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double r = l->RoundingRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, TopoDS_Shape& face) { + const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double r = l->RoundingRadius() * getValue(GV_LENGTH_UNIT); if ( x < ALMOST_ZERO || y < ALMOST_ZERO || r < ALMOST_ZERO ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); @@ -259,23 +259,23 @@ bool IfcGeom::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, TopoDS_ } gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + IfcGeom::Kernel::convert(l->Position(),trsf2d); double coords[8] = {-x,-y, x,-y, x,y, -x,y}; int fillets[4] = {0,1,2,3}; double radii[4] = {r,r,r,r}; - return IfcGeom::profile_helper(4,coords,4,fillets,radii,trsf2d,face); + return profile_helper(4,coords,4,fillets,radii,trsf2d,face); } -bool IfcGeom::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, TopoDS_Shape& face) { - const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double d = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, TopoDS_Shape& face) { + const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d = l->WallThickness() * getValue(GV_LENGTH_UNIT); const bool fr1 = l->hasOuterFilletRadius(); const bool fr2 = l->hasInnerFilletRadius(); - const double r1 = fr1 ? l->OuterFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT) : 0.; - const double r2 = fr2 ? l->InnerFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT) : 0.; + const double r1 = fr1 ? l->OuterFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.; + const double r2 = fr2 ? l->InnerFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.; if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); @@ -286,15 +286,15 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, TopoDS_S TopoDS_Face f2; gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + IfcGeom::Kernel::convert(l->Position(),trsf2d); double coords1[8] = {-x ,-y, x ,-y, x, y, -x, y }; double coords2[8] = {-x+d,-y+d, x-d,-y+d, x-d,y-d, -x+d,y-d}; double radii1[4] = {r1,r1,r1,r1}; double radii2[4] = {r2,r2,r2,r2}; int fillets[4] = {0,1,2,3}; - bool s1 = IfcGeom::profile_helper(4,coords1,fr1 ? 4 : 0,fillets,radii1,trsf2d,f1); - bool s2 = IfcGeom::profile_helper(4,coords2,fr2 ? 4 : 0,fillets,radii2,trsf2d,f2); + bool s1 = profile_helper(4,coords1,fr1 ? 4 : 0,fillets,radii1,trsf2d,f1); + bool s2 = profile_helper(4,coords2,fr2 ? 4 : 0,fillets,radii2,trsf2d,f2); if (!s1 || !s2) return false; @@ -313,11 +313,11 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, TopoDS_S return true; } -bool IfcGeom::convert(const IfcSchema::IfcTrapeziumProfileDef* l, TopoDS_Shape& face) { - const double x1 = l->BottomXDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double w = l->TopXDim() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double dx = l->TopXOffset() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrapeziumProfileDef* l, TopoDS_Shape& face) { + const double x1 = l->BottomXDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double w = l->TopXDim() * getValue(GV_LENGTH_UNIT); + const double dx = l->TopXOffset() * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); if ( x1 < ALMOST_ZERO || w < ALMOST_ZERO || y < ALMOST_ZERO ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); @@ -325,21 +325,21 @@ bool IfcGeom::convert(const IfcSchema::IfcTrapeziumProfileDef* l, TopoDS_Shape& } gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + IfcGeom::Kernel::convert(l->Position(),trsf2d); double coords[8] = {-x1,-y, x1,-y, dx+w-x1,y, dx-x1,y}; - return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face); + return profile_helper(4,coords,0,0,0,trsf2d,face); } -bool IfcGeom::convert(const IfcSchema::IfcIShapeProfileDef* l, TopoDS_Shape& face) { - const double x1 = l->OverallWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double y = l->OverallDepth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double d1 = l->WebThickness() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double dy1 = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcIShapeProfileDef* l, TopoDS_Shape& face) { + const double x1 = l->OverallWidth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double y = l->OverallDepth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d1 = l->WebThickness() / 2.0f * getValue(GV_LENGTH_UNIT); + const double dy1 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT); bool doFillet1 = l->hasFilletRadius(); double f1 = 0.; if ( doFillet1 ) { - f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); } bool doFillet2 = doFillet1; @@ -347,13 +347,13 @@ bool IfcGeom::convert(const IfcSchema::IfcIShapeProfileDef* l, TopoDS_Shape& fac if (l->is(IfcSchema::Type::IfcAsymmetricIShapeProfileDef)) { IfcSchema::IfcAsymmetricIShapeProfileDef* assym = (IfcSchema::IfcAsymmetricIShapeProfileDef*) l; - x2 = assym->TopFlangeWidth() / 2. * IfcGeom::GetValue(GV_LENGTH_UNIT); + x2 = assym->TopFlangeWidth() / 2. * getValue(GV_LENGTH_UNIT); doFillet2 = assym->hasTopFlangeFilletRadius(); if (doFillet2) { - f2 = assym->TopFlangeFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f2 = assym->TopFlangeFilletRadius() * getValue(GV_LENGTH_UNIT); } if (assym->hasTopFlangeThickness()) { - dy2 = assym->TopFlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); + dy2 = assym->TopFlangeThickness() * getValue(GV_LENGTH_UNIT); } } @@ -363,19 +363,19 @@ bool IfcGeom::convert(const IfcSchema::IfcIShapeProfileDef* l, TopoDS_Shape& fac } gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + convert(l->Position(),trsf2d); double coords[24] = {-x1,-y, x1,-y, x1,-y+dy1, d1,-y+dy1, d1,y-dy2, x2,y-dy2, x2,y, -x2,y, -x2,y-dy2, -d1,y-dy2, -d1,-y+dy1, -x1,-y+dy1}; int fillets[4] = {3,4,9,10}; double radii[4] = {f1,f1,f2,f2}; - return IfcGeom::profile_helper(12,coords,(doFillet1||doFillet2) ? 4 : 0,fillets,radii,trsf2d,face); + return profile_helper(12,coords,(doFillet1||doFillet2) ? 4 : 0,fillets,radii,trsf2d,face); } -bool IfcGeom::convert(const IfcSchema::IfcZShapeProfileDef* l, TopoDS_Shape& face) { - const double x = l->FlangeWidth() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double dx = l->WebThickness() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double dy = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcZShapeProfileDef* l, TopoDS_Shape& face) { + const double x = l->FlangeWidth() * getValue(GV_LENGTH_UNIT); + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double dx = l->WebThickness() / 2.0f * getValue(GV_LENGTH_UNIT); + const double dy = l->FlangeThickness() * getValue(GV_LENGTH_UNIT); bool doFillet = l->hasFilletRadius(); bool doEdgeFillet = l->hasEdgeRadius(); @@ -384,10 +384,10 @@ bool IfcGeom::convert(const IfcSchema::IfcZShapeProfileDef* l, TopoDS_Shape& fac double f2 = 0.; if ( doFillet ) { - f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); } if ( doEdgeFillet ) { - f2 = l->EdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f2 = l->EdgeRadius() * getValue(GV_LENGTH_UNIT); } if ( x == 0.0f || y == 0.0f || dx == 0.0f || dy == 0.0f ) { @@ -396,24 +396,24 @@ bool IfcGeom::convert(const IfcSchema::IfcZShapeProfileDef* l, TopoDS_Shape& fac } gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + IfcGeom::Kernel::convert(l->Position(),trsf2d); double coords[16] = {-dx,-y, x,-y, x,-y+dy, dx,-y+dy, dx,y, -x,y, -x,y-dy, -dx,y-dy}; int fillets[4] = {2,3,6,7}; double radii[4] = {f2,f1,f2,f1}; - return IfcGeom::profile_helper(8,coords,(doFillet || doEdgeFillet) ? 4 : 0,fillets,radii,trsf2d,face); + return profile_helper(8,coords,(doFillet || doEdgeFillet) ? 4 : 0,fillets,radii,trsf2d,face); } -bool IfcGeom::convert(const IfcSchema::IfcCShapeProfileDef* l, TopoDS_Shape& face) { - const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double x = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double d1 = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double d2 = l->Girth() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCShapeProfileDef* l, TopoDS_Shape& face) { + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double x = l->Width() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d1 = l->WallThickness() * getValue(GV_LENGTH_UNIT); + const double d2 = l->Girth() * getValue(GV_LENGTH_UNIT); bool doFillet = l->hasInternalFilletRadius(); double f1 = 0; double f2 = 0; if ( doFillet ) { - f1 = l->InternalFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f1 = l->InternalFilletRadius() * getValue(GV_LENGTH_UNIT); f2 = f1 + d1; } @@ -423,31 +423,31 @@ bool IfcGeom::convert(const IfcSchema::IfcCShapeProfileDef* l, TopoDS_Shape& fac } gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + IfcGeom::Kernel::convert(l->Position(),trsf2d); double coords[24] = {-x,-y,x,-y,x,-y+d2,x-d1,-y+d2,x-d1,-y+d1,-x+d1,-y+d1,-x+d1,y-d1,x-d1,y-d1,x-d1,y-d2,x,y-d2,x,y,-x,y}; int fillets[8] = {0,1,4,5,6,7,10,11}; double radii[8] = {f2,f2,f1,f1,f1,f1,f2,f2}; - return IfcGeom::profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face); + return profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face); } -bool IfcGeom::convert(const IfcSchema::IfcLShapeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcLShapeProfileDef* l, TopoDS_Shape& face) { const bool hasSlope = l->hasLegSlope(); const bool doEdgeFillet = l->hasEdgeRadius(); const bool doFillet = l->hasFilletRadius(); - const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double x = (l->hasWidth() ? l->Width() : l->Depth()) / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double d = l->Thickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double slope = hasSlope ? (l->LegSlope() * IfcGeom::GetValue(GV_PLANEANGLE_UNIT)) : 0.; + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double x = (l->hasWidth() ? l->Width() : l->Depth()) / 2.0f * getValue(GV_LENGTH_UNIT); + const double d = l->Thickness() * getValue(GV_LENGTH_UNIT); + const double slope = hasSlope ? (l->LegSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.; double f1 = 0.0f; double f2 = 0.0f; if (doFillet) { - f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); } if ( doEdgeFillet) { - f2 = l->EdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f2 = l->EdgeRadius() * getValue(GV_LENGTH_UNIT); } if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d < ALMOST_ZERO ) { @@ -492,24 +492,24 @@ bool IfcGeom::convert(const IfcSchema::IfcLShapeProfileDef* l, TopoDS_Shape& fac } gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + convert(l->Position(),trsf2d); double coords[12] = {-x,-y, x,-y, x,-y+d-dy1, xx, xy, -x+d-dx1,y, -x,y}; int fillets[3] = {2,3,4}; double radii[3] = {f2,f1,f2}; - return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face); + return profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face); } -bool IfcGeom::convert(const IfcSchema::IfcUShapeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcUShapeProfileDef* l, TopoDS_Shape& face) { const bool doEdgeFillet = l->hasEdgeRadius(); const bool doFillet = l->hasFilletRadius(); const bool hasSlope = l->hasFlangeSlope(); - const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double x = l->FlangeWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double d1 = l->WebThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double d2 = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double slope = hasSlope ? (l->FlangeSlope() * IfcGeom::GetValue(GV_PLANEANGLE_UNIT)) : 0.; + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double x = l->FlangeWidth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d1 = l->WebThickness() * getValue(GV_LENGTH_UNIT); + const double d2 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT); + const double slope = hasSlope ? (l->FlangeSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.; double dy1 = 0.0f; double dy2 = 0.0f; @@ -517,10 +517,10 @@ bool IfcGeom::convert(const IfcSchema::IfcUShapeProfileDef* l, TopoDS_Shape& fac double f2 = 0.0f; if (doFillet) { - f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); } if (doEdgeFillet) { - f2 = l->EdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f2 = l->EdgeRadius() * getValue(GV_LENGTH_UNIT); } if (hasSlope) { @@ -534,27 +534,27 @@ bool IfcGeom::convert(const IfcSchema::IfcUShapeProfileDef* l, TopoDS_Shape& fac } gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + convert(l->Position(),trsf2d); double coords[16] = {-x,-y, x,-y, x,-y+d2-dy2, -x+d1,-y+d2+dy1, -x+d1,y-d2-dy1, x,y-d2+dy2, x,y, -x,y}; int fillets[4] = {2,3,4,5}; double radii[4] = {f2,f1,f1,f2}; - return IfcGeom::profile_helper(8, coords, (doFillet || doEdgeFillet) ? 4 : 0, fillets, radii, trsf2d, face); + return profile_helper(8, coords, (doFillet || doEdgeFillet) ? 4 : 0, fillets, radii, trsf2d, face); } -bool IfcGeom::convert(const IfcSchema::IfcTShapeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcTShapeProfileDef* l, TopoDS_Shape& face) { const bool doFlangeEdgeFillet = l->hasFlangeEdgeRadius(); const bool doWebEdgeFillet = l->hasWebEdgeRadius(); const bool doFillet = l->hasFilletRadius(); const bool hasFlangeSlope = l->hasFlangeSlope(); const bool hasWebSlope = l->hasWebSlope(); - const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double x = l->FlangeWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double d1 = l->WebThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double d2 = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double flangeSlope = hasFlangeSlope ? (l->FlangeSlope() * IfcGeom::GetValue(GV_PLANEANGLE_UNIT)) : 0.; - const double webSlope = hasWebSlope ? (l->WebSlope() * IfcGeom::GetValue(GV_PLANEANGLE_UNIT)) : 0.; + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double x = l->FlangeWidth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d1 = l->WebThickness() * getValue(GV_LENGTH_UNIT); + const double d2 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT); + const double flangeSlope = hasFlangeSlope ? (l->FlangeSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.; + const double webSlope = hasWebSlope ? (l->WebSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.; if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); @@ -570,13 +570,13 @@ bool IfcGeom::convert(const IfcSchema::IfcTShapeProfileDef* l, TopoDS_Shape& fac double f3 = 0.0f; if (doFillet) { - f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); } if (doWebEdgeFillet) { - f2 = l->WebEdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f2 = l->WebEdgeRadius() * getValue(GV_LENGTH_UNIT); } if (doFlangeEdgeFillet) { - f3 = l->FlangeEdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + f3 = l->FlangeEdgeRadius() * getValue(GV_LENGTH_UNIT); } double xx, xy; @@ -617,23 +617,23 @@ bool IfcGeom::convert(const IfcSchema::IfcTShapeProfileDef* l, TopoDS_Shape& fac } gp_Trsf2d trsf2d; - IfcGeom::convert(l->Position(),trsf2d); + convert(l->Position(),trsf2d); double coords[16] = {d1/2.-dx2,-y, xx,xy, x,y-d2+dy2, x,y, -x,y, -x,y-d2+dy2, -xx,xy, -d1/2.+dx2,-y}; int fillets[6] = {0,1,2,5,6,7}; double radii[6] = {f2,f1,f3,f3,f1,f2}; - return IfcGeom::profile_helper(8, coords, (doFillet || doWebEdgeFillet || doFlangeEdgeFillet) ? 6 : 0, fillets, radii, trsf2d, face); + return profile_helper(8, coords, (doFillet || doWebEdgeFillet || doFlangeEdgeFillet) ? 6 : 0, fillets, radii, trsf2d, face); } -bool IfcGeom::convert(const IfcSchema::IfcCircleProfileDef* l, TopoDS_Shape& face) { - const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleProfileDef* l, TopoDS_Shape& face) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); if ( r == 0.0f ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); return false; } gp_Trsf2d trsf; - IfcGeom::convert(l->Position(),trsf); + convert(l->Position(),trsf); BRepBuilderAPI_MakeWire w; gp_Ax2 ax = gp_Ax2().Transformed(trsf); @@ -642,14 +642,14 @@ bool IfcGeom::convert(const IfcSchema::IfcCircleProfileDef* l, TopoDS_Shape& fac w.Add(edge); TopoDS_Face f; - bool success = IfcGeom::convert_wire_to_face(w, f); + bool success = convert_wire_to_face(w, f); if (success) face = f; return success; } -bool IfcGeom::convert(const IfcSchema::IfcCircleHollowProfileDef* l, TopoDS_Shape& face) { - const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double t = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, TopoDS_Shape& face) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); + const double t = l->WallThickness() * getValue(GV_LENGTH_UNIT); if ( r == 0.0f || t == 0.0f ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); @@ -657,7 +657,7 @@ bool IfcGeom::convert(const IfcSchema::IfcCircleHollowProfileDef* l, TopoDS_Shap } gp_Trsf2d trsf; - IfcGeom::convert(l->Position(),trsf); + convert(l->Position(),trsf); gp_Ax2 ax = gp_Ax2().Transformed(trsf); BRepBuilderAPI_MakeWire outer; @@ -676,9 +676,9 @@ bool IfcGeom::convert(const IfcSchema::IfcCircleHollowProfileDef* l, TopoDS_Shap return true; } -bool IfcGeom::convert(const IfcSchema::IfcEllipseProfileDef* l, TopoDS_Shape& face) { - double rx = l->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT); - double ry = l->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcEllipseProfileDef* l, TopoDS_Shape& face) { + double rx = l->SemiAxis1() * getValue(GV_LENGTH_UNIT); + double ry = l->SemiAxis2() * getValue(GV_LENGTH_UNIT); if ( rx < ALMOST_ZERO || ry < ALMOST_ZERO ) { Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); @@ -687,7 +687,7 @@ bool IfcGeom::convert(const IfcSchema::IfcEllipseProfileDef* l, TopoDS_Shape& fa const bool rotated = ry > rx; gp_Trsf2d trsf; - IfcGeom::convert(l->Position(),trsf); + convert(l->Position(),trsf); gp_Ax2 ax = gp_Ax2(); if (rotated) { @@ -702,16 +702,16 @@ bool IfcGeom::convert(const IfcSchema::IfcEllipseProfileDef* l, TopoDS_Shape& fa w.Add(edge); TopoDS_Face f; - bool success = IfcGeom::convert_wire_to_face(w, f); + bool success = convert_wire_to_face(w, f); if (success) face = f; return success; } -bool IfcGeom::convert(const IfcSchema::IfcCenterLineProfileDef* l, TopoDS_Shape& face) { - const double d = l->Thickness() * IfcGeom::GetValue(GV_LENGTH_UNIT) / 2.; +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCenterLineProfileDef* l, TopoDS_Shape& face) { + const double d = l->Thickness() * getValue(GV_LENGTH_UNIT) / 2.; TopoDS_Wire wire; - if (!IfcGeom::convert_wire(l->Curve(), wire)) return false; + if (!convert_wire(l->Curve(), wire)) return false; // BRepOffsetAPI_MakeOffset insists on creating circular arc // segments for joining the curves that constitute the center @@ -756,7 +756,7 @@ bool IfcGeom::convert(const IfcSchema::IfcCenterLineProfileDef* l, TopoDS_Shape& return true; } -bool IfcGeom::convert(const IfcSchema::IfcCompositeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeProfileDef* l, TopoDS_Shape& face) { // BRepBuilderAPI_MakeFace mf; TopoDS_Compound compound; @@ -767,7 +767,7 @@ bool IfcGeom::convert(const IfcSchema::IfcCompositeProfileDef* l, TopoDS_Shape& bool first = true; for (IfcSchema::IfcProfileDef::list::it it = profiles->begin(); it != profiles->end(); ++it) { TopoDS_Face f; - if (IfcGeom::convert_face(*it, f)) { + if (convert_face(*it, f)) { builder.Add(compound, f); /* TopExp_Explorer exp(f, TopAbs_WIRE); for (; exp.More(); exp.Next()) { @@ -786,10 +786,10 @@ bool IfcGeom::convert(const IfcSchema::IfcCompositeProfileDef* l, TopoDS_Shape& return !face.IsNull(); } -bool IfcGeom::convert(const IfcSchema::IfcDerivedProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcDerivedProfileDef* l, TopoDS_Shape& face) { TopoDS_Face f; gp_Trsf2d trsf2d; - if (IfcGeom::convert_face(l->ParentProfile(), f) && IfcGeom::convert(l->Operator(), trsf2d)) { + if (convert_face(l->ParentProfile(), f) && IfcGeom::Kernel::convert(l->Operator(), trsf2d)) { gp_Trsf trsf = trsf2d; face = TopoDS::Face(BRepBuilderAPI_Transform(f, trsf)); return true; @@ -821,7 +821,7 @@ bool convert_surf(IfcSchema::IfcBSplineSurfaceWithKnots* l, Handle_Geom_Surface& for (IfcTemplatedEntityListList::inner_it jt = (*it).begin(); jt != (*it).end(); ++jt, ++j) { IfcSchema::IfcCartesianPoint* p = *jt; gp_Pnt pnt; - if (!IfcGeom::convert(p, pnt)) return false; + if (!convert(p, pnt)) return false; Poles(i, j) = pnt; } } @@ -847,12 +847,12 @@ bool convert_surf(IfcSchema::IfcBSplineSurfaceWithKnots* l, Handle_Geom_Surface& bool convert_surf(IfcSchema::IfcPlane* l, Handle_Geom_Surface& surf) { gp_Pln pln; - IfcGeom::convert(l, pln); + convert(l, pln); surf = new Geom_Plane(pln); return true; } -bool IfcGeom::convert(const IfcSchema::IfcAdvancedFace* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcAdvancedFace* l, TopoDS_Shape& face) { IfcSchema::IfcSurface* s = l->FaceSurface(); Handle_Geom_Surface surf(0); if (s->is(IfcSchema::Type::IfcBSplineSurfaceWithKnots)) { @@ -868,7 +868,7 @@ bool IfcGeom::convert(const IfcSchema::IfcAdvancedFace* l, TopoDS_Shape& face) { for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { IfcSchema::IfcLoop* loop = (*it)->Bound(); TopoDS_Wire outer_wire; - if (!IfcGeom::convert_wire(loop, outer_wire)) return false; + if (!convert_wire(loop, outer_wire)) return false; TopoDS_Face temp = BRepBuilderAPI_MakeFace(surf, outer_wire); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 42efc4cfff..2d440df0cf 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -102,11 +102,11 @@ #include "../ifcgeom/IfcGeom.h" -bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) { BRepOffsetAPI_Sewing builder; - builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); - builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); - builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetMaxTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetMinTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); TopExp_Explorer exp(compound,TopAbs_FACE); if ( ! exp.More() ) return false; for ( ; exp.More(); exp.Next() ) { @@ -117,13 +117,13 @@ bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Sh shape = builder.SewedShape(); try { ShapeFix_Solid sf_solid; - sf_solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); + sf_solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); shape = sf_solid.SolidFromShell(TopoDS::Shell(shape)); } catch(...) {} return true; } -bool IfcGeom::is_compound(const TopoDS_Shape& shape) { +bool IfcGeom::Kernel::is_compound(const TopoDS_Shape& shape) { bool has_solids = TopExp_Explorer(shape,TopAbs_SOLID).More() != 0; bool has_shells = TopExp_Explorer(shape,TopAbs_SHELL).More() != 0; bool has_compounds = TopExp_Explorer(shape,TopAbs_COMPOUND).More() != 0; @@ -131,21 +131,21 @@ bool IfcGeom::is_compound(const TopoDS_Shape& shape) { return has_compounds && has_faces && !has_solids && !has_shells; } -const TopoDS_Shape& IfcGeom::ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid) { - const bool is_comp = IfcGeom::is_compound(shape); +const TopoDS_Shape& IfcGeom::Kernel::ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid) { + const bool is_comp = is_compound(shape); if ( ! is_comp ) return shape; - IfcGeom::create_solid_from_compound(shape, solid); + create_solid_from_compound(shape, solid); // If the SEW_SHELLS option had been set this precision had been applied - // at the end of the generic IfcGeom::convert_shape() call. - const double precision = IfcGeom::GetValue(GV_PRECISION); - IfcGeom::apply_tolerance(solid, precision); + // at the end of the generic convert_shape() call. + const double precision = getValue(GV_PRECISION); + apply_tolerance(solid, precision); return solid; } -bool IfcGeom::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, - const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes) { +bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, + const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) { // Iterate over IfcOpeningElements IfcGeom::IfcRepresentationShapeItems opening_shapes; unsigned int last_size = 0; @@ -156,7 +156,7 @@ bool IfcGeom::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSch // Convert the IfcRepresentation of the IfcOpeningElement gp_Trsf opening_trsf; - IfcGeom::convert(fes->ObjectPlacement(),opening_trsf); + IfcGeom::Kernel::convert(fes->ObjectPlacement(),opening_trsf); // Move the opening into the coordinate system of the IfcProduct opening_trsf.PreMultiply(entity_trsf.Inverted()); @@ -165,7 +165,7 @@ bool IfcGeom::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSch IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations(); for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) { - IfcGeom::convert_shapes(*it2,opening_shapes); + convert_shapes(*it2,opening_shapes); } const unsigned int current_size = (const unsigned int) opening_shapes.size(); @@ -179,7 +179,7 @@ bool IfcGeom::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSch // Iterate over the shapes of the IfcProduct for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { TopoDS_Shape entity_shape_solid; - const TopoDS_Shape& entity_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid); + const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid); const gp_GTrsf& entity_shape_gtrsf = it3->Placement(); TopoDS_Shape entity_shape; if ( entity_shape_gtrsf.Form() == gp_Other ) { @@ -192,7 +192,7 @@ bool IfcGeom::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSch // Iterate over the shapes of the IfcOpeningElements for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) { TopoDS_Shape opening_shape_solid; - const TopoDS_Shape& opening_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(it4->Shape(),opening_shape_solid); + const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(it4->Shape(),opening_shape_solid); const gp_GTrsf& opening_shape_gtrsf = it4->Placement(); if ( opening_shape_gtrsf.Form() == gp_Other ) { Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to opening of:",entity->entity); @@ -276,8 +276,8 @@ bool IfcGeom::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSch return true; } -bool IfcGeom::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, - const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes) { +bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, + const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) { // Create a compound of all opening shapes in order to speed up the boolean operations TopoDS_Compound opening_compound; @@ -291,7 +291,7 @@ bool IfcGeom::convert_openings_fast(const IfcSchema::IfcProduct* entity, const I // Convert the IfcRepresentation of the IfcOpeningElement gp_Trsf opening_trsf; - IfcGeom::convert(fes->ObjectPlacement(),opening_trsf); + IfcGeom::Kernel::convert(fes->ObjectPlacement(),opening_trsf); // Move the opening into the coordinate system of the IfcProduct opening_trsf.PreMultiply(entity_trsf.Inverted()); @@ -302,7 +302,7 @@ bool IfcGeom::convert_openings_fast(const IfcSchema::IfcProduct* entity, const I IfcGeom::IfcRepresentationShapeItems opening_shapes; for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) { - IfcGeom::convert_shapes(*it2,opening_shapes); + convert_shapes(*it2,opening_shapes); } for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) { @@ -320,7 +320,7 @@ bool IfcGeom::convert_openings_fast(const IfcSchema::IfcProduct* entity, const I // Iterate over the shapes of the IfcProduct for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { TopoDS_Shape entity_shape_solid; - const TopoDS_Shape& entity_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid); + const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid); const gp_GTrsf& entity_shape_gtrsf = it3->Placement(); TopoDS_Shape entity_shape; if ( entity_shape_gtrsf.Form() == gp_Other ) { @@ -353,7 +353,7 @@ bool IfcGeom::convert_openings_fast(const IfcSchema::IfcProduct* entity, const I return true; } -bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) { +bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) { BRepBuilderAPI_MakeFace mf(wire, false); BRepBuilderAPI_FaceError er = mf.Error(); if ( er == BRepBuilderAPI_NotPlanar ) { @@ -368,12 +368,12 @@ bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) { return true; } -bool IfcGeom::convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire) { +bool IfcGeom::Kernel::convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire) { wire = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(curve)); return true; } -bool IfcGeom::profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Shape& face_shape) { +bool IfcGeom::Kernel::profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Shape& face_shape) { TopoDS_Vertex* vertices = new TopoDS_Vertex[numVerts]; for ( int i = 0; i < numVerts; i ++ ) { @@ -387,7 +387,7 @@ bool IfcGeom::profile_helper(int numVerts, double* verts, int numFillets, int* f w.Add(BRepBuilderAPI_MakeEdge(vertices[i],vertices[(i+1)%numVerts])); TopoDS_Face face; - IfcGeom::convert_wire_to_face(w.Wire(),face); + convert_wire_to_face(w.Wire(),face); if ( numFillets && *std::max_element(filletRadii, filletRadii + numFillets) > ALMOST_ZERO ) { BRepFilletAPI_MakeFillet2d fillet (face); @@ -409,17 +409,17 @@ bool IfcGeom::profile_helper(int numVerts, double* verts, int numFillets, int* f delete[] vertices; return true; } -double IfcGeom::shape_volume(const TopoDS_Shape& s) { +double IfcGeom::Kernel::shape_volume(const TopoDS_Shape& s) { GProp_GProps prop; BRepGProp::VolumeProperties(s, prop); return prop.Mass(); } -double IfcGeom::face_area(const TopoDS_Face& f) { +double IfcGeom::Kernel::face_area(const TopoDS_Face& f) { GProp_GProps prop; BRepGProp::SurfaceProperties(f,prop); return prop.Mass(); } -bool IfcGeom::is_convex(const TopoDS_Wire& wire) { +bool IfcGeom::Kernel::is_convex(const TopoDS_Wire& wire) { for ( TopExp_Explorer exp1(wire,TopAbs_VERTEX); exp1.More(); exp1.Next() ) { TopoDS_Vertex V1 = TopoDS::Vertex(exp1.Current()); gp_Pnt P1 = BRep_Tool::Pnt(V1); @@ -434,8 +434,8 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) { edge_points.push_back(P2); } if ( edge_points.size() != 2 ) continue; - if ( edge_points[0].IsEqual(P1,GetValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[1]); - else if ( edge_points[1].IsEqual(P1, GetValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[0]); + if ( edge_points[0].IsEqual(P1,getValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[1]); + else if ( edge_points[1].IsEqual(P1, getValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[0]); } // There should be two of these if ( neighbors.size() != 2 ) return false; @@ -444,10 +444,10 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) { for ( TopExp_Explorer exp2(wire,TopAbs_VERTEX); exp2.More(); exp2.Next() ) { TopoDS_Vertex V2 = TopoDS::Vertex(exp2.Current()); gp_Pnt P2 = BRep_Tool::Pnt(V2); - if ( P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) continue; + if ( P1.IsEqual(P2,getValue(GV_POINT_EQUALITY_TOLERANCE)) ) continue; bool found = false; for( std::vector::const_iterator it = neighbors.begin(); it != neighbors.end(); ++ it ) { - if ( (*it).IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) { found = true; break; } + if ( (*it).IsEqual(P2,getValue(GV_POINT_EQUALITY_TOLERANCE)) ) { found = true; break; } } if ( ! found ) non_neighbors.push_back(P2); } @@ -465,11 +465,11 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) { } return true; } -TopoDS_Shape IfcGeom::halfspace_from_plane(const gp_Pln& pln,const gp_Pnt& cent) { +TopoDS_Shape IfcGeom::Kernel::halfspace_from_plane(const gp_Pln& pln,const gp_Pnt& cent) { TopoDS_Face face = BRepBuilderAPI_MakeFace(pln).Face(); return BRepPrimAPI_MakeHalfSpace(face,cent).Solid(); } -gp_Pln IfcGeom::plane_from_face(const TopoDS_Face& face) { +gp_Pln IfcGeom::Kernel::plane_from_face(const TopoDS_Face& face) { BRepGProp_Face prop(face); Standard_Real u1,u2,v1,v2; prop.Bounds(u1,u2,v1,v2); @@ -480,7 +480,7 @@ gp_Pln IfcGeom::plane_from_face(const TopoDS_Face& face) { prop.Normal(u,v,p,n); return gp_Pln(p,n); } -gp_Pnt IfcGeom::point_above_plane(const gp_Pln& pln, bool agree) { +gp_Pnt IfcGeom::Kernel::point_above_plane(const gp_Pln& pln, bool agree) { if ( agree ) { return pln.Location().Translated(pln.Axis().Direction()); } else { @@ -488,7 +488,7 @@ gp_Pnt IfcGeom::point_above_plane(const gp_Pln& pln, bool agree) { } } -void IfcGeom::apply_tolerance(TopoDS_Shape& s, double t) { +void IfcGeom::Kernel::apply_tolerance(TopoDS_Shape& s, double t) { ShapeFix_ShapeTolerance tol; tol.SetTolerance(s, t); } @@ -503,7 +503,7 @@ static double ifc_planeangle_unit = -1.0; static double force_ccw_face_orientation = -1.0; static double modelling_precision = 0.00001; -void IfcGeom::SetValue(GeomValue var, double value) { +void IfcGeom::Kernel::setValue(GeomValue var, double value) { switch (var) { case GV_DEFLECTION_TOLERANCE: deflection_tolerance = value; @@ -537,7 +537,7 @@ void IfcGeom::SetValue(GeomValue var, double value) { } } -double IfcGeom::GetValue(GeomValue var) { +double IfcGeom::Kernel::getValue(GeomValue var) { switch (var) { case GV_DEFLECTION_TOLERANCE: return deflection_tolerance; @@ -566,7 +566,7 @@ double IfcGeom::GetValue(GeomValue var) { return 0; } -IfcSchema::IfcProductDefinitionShape* IfcGeom::tesselate(TopoDS_Shape& shape, double deflection, IfcEntityList::ptr es) { +IfcSchema::IfcProductDefinitionShape* IfcGeom::Kernel::tesselate(TopoDS_Shape& shape, double deflection, IfcEntityList::ptr es) { BRepMesh::Mesh(shape, deflection); IfcSchema::IfcFace::list::ptr faces (new IfcSchema::IfcFace::list); @@ -655,7 +655,7 @@ TopoDS_Edge find_next(const TopTools_IndexedMapOfShape& edge_set, const TopTools return TopoDS_Edge(); } -bool IfcGeom::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) { +bool IfcGeom::Kernel::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) { BRepOffsetAPI_Sewing sew; sew.Add(shape); @@ -730,14 +730,14 @@ bool IfcGeom::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) { try { ShapeFix_Solid solid; - solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); + solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); shape = solid.SolidFromShell(TopoDS::Shell(shape)); } catch(...) {} return true; } -bool IfcGeom::flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse) { +bool IfcGeom::Kernel::flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse) { TopoDS_Compound compound; BRep_Builder builder; builder.MakeCompound(compound); @@ -748,7 +748,7 @@ bool IfcGeom::flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& sha TopoDS_Shape merged; const TopoDS_Shape& s = it->Shape(); if (fuse) { - IfcGeom::ensure_fit_for_subtraction(s, merged); + ensure_fit_for_subtraction(s, merged); } else { merged = s; } @@ -793,8 +793,8 @@ bool IfcGeom::flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& sha return !result.IsNull(); } -void IfcGeom::remove_redundant_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol) { - if (tol <= 0.) tol = GetValue(GV_POINT_EQUALITY_TOLERANCE); +void IfcGeom::Kernel::remove_redundant_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol) { + if (tol <= 0.) tol = getValue(GV_POINT_EQUALITY_TOLERANCE); tol *= tol; while (true) { diff --git a/src/ifcgeom/IfcGeomHelpers.cpp b/src/ifcgeom/IfcGeomHelpers.cpp index 4c1c37fe3f..1253854e11 100644 --- a/src/ifcgeom/IfcGeomHelpers.cpp +++ b/src/ifcgeom/IfcGeomHelpers.cpp @@ -77,29 +77,19 @@ #include "../ifcgeom/IfcGeom.h" - -namespace IfcGeom { - namespace Cache { -#include "IfcRegisterCreateCache.h" - } -} -#define IN_CACHE(T,E,t,e) std::map::const_iterator it = Cache::T.find(E->entity->id());\ - if ( it != Cache::T.end() ) { e = it->second; return true; } -#define CACHE(T,E,e) Cache::T[E->entity->id()] = e; - -bool IfcGeom::convert(const IfcSchema::IfcCartesianPoint* l, gp_Pnt& point) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianPoint* l, gp_Pnt& point) { IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point) std::vector xyz = l->Coordinates(); point = gp_Pnt( - xyz.size() ? (xyz[0]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f, - xyz.size() > 1 ? (xyz[1]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f, - xyz.size() > 2 ? (xyz[2]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f + xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f ); CACHE(IfcCartesianPoint,l,point) return true; } -bool IfcGeom::convert(const IfcSchema::IfcDirection* l, gp_Dir& dir) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcDirection* l, gp_Dir& dir) { IN_CACHE(IfcDirection,l,gp_Dir,dir) std::vector xyz = l->DirectionRatios(); dir = gp_Dir( @@ -111,22 +101,22 @@ bool IfcGeom::convert(const IfcSchema::IfcDirection* l, gp_Dir& dir) { return true; } -bool IfcGeom::convert(const IfcSchema::IfcVector* l, gp_Vec& v) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcVector* l, gp_Vec& v) { IN_CACHE(IfcVector,l,gp_Vec,v) gp_Dir d; - IfcGeom::convert(l->Orientation(),d); - v = l->Magnitude() * IfcGeom::GetValue(GV_LENGTH_UNIT) * d; + IfcGeom::Kernel::convert(l->Orientation(),d); + v = l->Magnitude() * getValue(GV_LENGTH_UNIT) * d; CACHE(IfcVector,l,v) return true; } -bool IfcGeom::convert(const IfcSchema::IfcAxis2Placement3D* l, gp_Trsf& trsf) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement3D* l, gp_Trsf& trsf) { IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);gp_Dir refDirection; - IfcGeom::convert(l->Location(),o); + IfcGeom::Kernel::convert(l->Location(),o); bool hasRef = l->hasRefDirection(); - if ( l->hasAxis() ) IfcGeom::convert(l->Axis(),axis); - if ( hasRef ) IfcGeom::convert(l->RefDirection(),refDirection); + if ( l->hasAxis() ) IfcGeom::Kernel::convert(l->Axis(),axis); + if ( hasRef ) IfcGeom::Kernel::convert(l->RefDirection(),refDirection); gp_Ax3 ax3; if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection); else ax3 = gp_Ax3(o,axis); @@ -135,26 +125,26 @@ bool IfcGeom::convert(const IfcSchema::IfcAxis2Placement3D* l, gp_Trsf& trsf) { return true; } -bool IfcGeom::convert(const IfcSchema::IfcAxis1Placement* l, gp_Ax1& ax) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis1Placement* l, gp_Ax1& ax) { IN_CACHE(IfcAxis1Placement,l,gp_Ax1,ax) gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1); - IfcGeom::convert(l->Location(),o); - if ( l->hasAxis() ) IfcGeom::convert(l->Axis(), axis); + IfcGeom::Kernel::convert(l->Location(),o); + if ( l->hasAxis() ) IfcGeom::Kernel::convert(l->Axis(), axis); ax = gp_Ax1(o, axis); CACHE(IfcAxis1Placement,l,ax) return true; } -bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, gp_Trsf& trsf) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, gp_Trsf& trsf) { IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf) gp_Pnt origin; - IfcGeom::convert(l->LocalOrigin(),origin); + IfcGeom::Kernel::convert(l->LocalOrigin(),origin); gp_Dir axis1 (1.,0.,0.); gp_Dir axis2 (0.,1.,0.); gp_Dir axis3 (0.,0.,1.); - if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::convert(l->Axis2(),axis2); - if ( l->hasAxis3() ) IfcGeom::convert(l->Axis3(),axis3); + if ( l->hasAxis1() ) IfcGeom::Kernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::Kernel::convert(l->Axis2(),axis2); + if ( l->hasAxis3() ) IfcGeom::Kernel::convert(l->Axis3(),axis3); gp_Ax3 ax3 (origin,axis3,axis1); if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse(); trsf.SetTransformation(ax3); @@ -164,16 +154,16 @@ bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, return true; } -bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator2D* l, gp_Trsf2d& trsf) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator2D* l, gp_Trsf2d& trsf) { IN_CACHE(IfcCartesianTransformationOperator2D,l,gp_Trsf2d,trsf) gp_Pnt origin; gp_Dir axis1 (1.,0.,0.); gp_Dir axis2 (0.,1.,0.); - IfcGeom::convert(l->LocalOrigin(),origin); - if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::convert(l->Axis2(),axis2); + IfcGeom::Kernel::convert(l->LocalOrigin(),origin); + if ( l->hasAxis1() ) IfcGeom::Kernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::Kernel::convert(l->Axis2(),axis2); const gp_Pnt2d origin2d(origin.X(), origin.Y()); const gp_Dir2d axis12d(axis1.X(), axis1.Y()); @@ -198,17 +188,17 @@ bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator2D* l, return true; } -bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* l, gp_GTrsf& gtrsf) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* l, gp_GTrsf& gtrsf) { IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf) gp_Trsf trsf; gp_Pnt origin; - IfcGeom::convert(l->LocalOrigin(),origin); + IfcGeom::Kernel::convert(l->LocalOrigin(),origin); gp_Dir axis1 (1.,0.,0.); gp_Dir axis2 (0.,1.,0.); gp_Dir axis3 (0.,0.,1.); - if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::convert(l->Axis2(),axis2); - if ( l->hasAxis3() ) IfcGeom::convert(l->Axis3(),axis3); + if ( l->hasAxis1() ) IfcGeom::Kernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::Kernel::convert(l->Axis2(),axis2); + if ( l->hasAxis3() ) IfcGeom::Kernel::convert(l->Axis3(),axis3); gp_Ax3 ax3 (origin,axis3,axis1); if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse(); trsf.SetTransformation(ax3); @@ -225,7 +215,7 @@ bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUn return true; } -bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, gp_GTrsf2d& gtrsf) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, gp_GTrsf2d& gtrsf) { IN_CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gp_GTrsf2d,gtrsf) gp_Trsf2d trsf; @@ -233,9 +223,9 @@ bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUn gp_Dir axis1 (1.,0.,0.); gp_Dir axis2 (0.,1.,0.); - IfcGeom::convert(l->LocalOrigin(),origin); - if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::convert(l->Axis2(),axis2); + IfcGeom::Kernel::convert(l->LocalOrigin(),origin); + if ( l->hasAxis1() ) IfcGeom::Kernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::Kernel::convert(l->Axis2(),axis2); const gp_Pnt2d origin2d(origin.X(), origin.Y()); const gp_Dir2d axis12d(axis1.X(), axis1.Y()); @@ -261,14 +251,14 @@ bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUn return true; } -bool IfcGeom::convert(const IfcSchema::IfcPlane* pln, gp_Pln& plane) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcPlane* pln, gp_Pln& plane) { IN_CACHE(IfcPlane,pln,gp_Pln,plane) IfcSchema::IfcAxis2Placement3D* l = pln->Position(); gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);gp_Dir refDirection; - IfcGeom::convert(l->Location(),o); + IfcGeom::Kernel::convert(l->Location(),o); bool hasRef = l->hasRefDirection(); - if ( l->hasAxis() ) IfcGeom::convert(l->Axis(),axis); - if ( hasRef ) IfcGeom::convert(l->RefDirection(),refDirection); + if ( l->hasAxis() ) IfcGeom::Kernel::convert(l->Axis(),axis); + if ( hasRef ) IfcGeom::Kernel::convert(l->RefDirection(),refDirection); gp_Ax3 ax3; if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection); else ax3 = gp_Ax3(o,axis); @@ -277,12 +267,12 @@ bool IfcGeom::convert(const IfcSchema::IfcPlane* pln, gp_Pln& plane) { return true; } -bool IfcGeom::convert(const IfcSchema::IfcAxis2Placement2D* l, gp_Trsf2d& trsf) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement2D* l, gp_Trsf2d& trsf) { IN_CACHE(IfcAxis2Placement2D,l,gp_Trsf2d,trsf) gp_Pnt P; gp_Dir V (1,0,0); - IfcGeom::convert(l->Location(),P); + IfcGeom::Kernel::convert(l->Location(),P); if ( l->hasRefDirection() ) - IfcGeom::convert(l->RefDirection(),V); + IfcGeom::Kernel::convert(l->RefDirection(),V); gp_Ax2d axis(gp_Pnt2d(P.X(),P.Y()),gp_Dir2d(V.X(),V.Y())); trsf.SetTransformation(axis,gp_Ax2d()); @@ -290,7 +280,7 @@ bool IfcGeom::convert(const IfcSchema::IfcAxis2Placement2D* l, gp_Trsf2d& trsf) return true; } -bool IfcGeom::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) { IN_CACHE(IfcObjectPlacement,l,gp_Trsf,trsf) if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) { Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l->entity); @@ -301,7 +291,7 @@ bool IfcGeom::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) { gp_Trsf trsf2; IfcSchema::IfcAxis2Placement relplacement = current->RelativePlacement(); if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) { - IfcGeom::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); + IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); trsf.PreMultiply(trsf2); } if ( current->hasPlacementRelTo() ) { @@ -313,9 +303,4 @@ bool IfcGeom::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) { } CACHE(IfcObjectPlacement,l,trsf) return true; -} - -void IfcGeom::Cache::Purge() { -#include "IfcRegisterPurgeCache.h" - IfcGeom::Cache::PurgeShapeCache(); } \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h new file mode 100644 index 0000000000..1bd47a1695 --- /dev/null +++ b/src/ifcgeom/IfcGeomIterator.h @@ -0,0 +1,635 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +/******************************************************************************** + * * + * Geometrical data in an IFC file consists of shapes (IfcShapeRepresentation) * + * and instances (SUBTYPE OF IfcBuildingElement e.g. IfcWindow). * + * * + * IfcGeom::Representation::Triangulation is a class that represents a * + * triangulated IfcShapeRepresentation. * + * Triangulation.verts is a 1 dimensional vector of float defining the * + * cartesian coordinates of the vertices of the triangulated shape in the * + * format of [x1,y1,z1,..,xn,yn,zn] * + * Triangulation.faces is a 1 dimensional vector of int containing the * + * indices of the triangles referencing positions in Triangulation.verts * + * Triangulation.edges is a 1 dimensional vector of int in {0,1} that dictates* + * the visibility of the edges that span the faces in Triangulation.faces * + * * + * IfcGeom::Element represents the actual IfcBuildingElements. * + * IfcGeomObject.name is the GUID of the element * + * IfcGeomObject.type is the datatype of the element e.g. IfcWindow * + * IfcGeomObject.mesh is a pointer to an IfcMesh * + * IfcGeomObject.transformation.matrix is a 4x3 matrix that defines the * + * orientation and translation of the mesh in relation to the world origin * + * * + * IfcGeom::Iterator::findContext() * + * finds the most suitable representation contexts. Returns true iff * + * at least a single representation will process successfully * + * * + * IfcGeom::Iterator::get() * + * returns a pointer to the current IfcGeom::Element * + * * + * IfcGeom::Iterator::next() * + * returns true iff a following entity is available for a successive call to * + * IfcGeom::Iterator::get() * + * * + * IfcGeom::Iterator::progress() * + * returns an int in [0..100] that indicates the overall progress * + * * + ********************************************************************************/ + +#ifndef IFCGEOMITERATOR_H +#define IFCGEOMITERATOR_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../ifcparse/IfcParse.h" + +#include "../ifcgeom/IfcGeom.h" +#include "../ifcgeom/IfcGeomUtils.h" +#include "../ifcgeom/IfcGeomElement.h" +#include "../ifcgeom/IfcGeomMaterial.h" +#include "../ifcgeom/IfcGeomIteratorSettings.h" +#include "../ifcgeom/IfcRepresentationShapeItem.h" + +namespace IfcGeom { + + template + class Iterator { + private: + Kernel kernel; + IteratorSettings settings; + + IfcParse::IfcFile* ifc_file; + + // A container and iterator for IfcShapeRepresentations + IfcSchema::IfcRepresentation::list::ptr representations; + IfcSchema::IfcRepresentation::list::it shaperep_iterator; + + // The object is fetched beforehand to be sure that get() returns a valid element + TriangulationElement

* current_triangulation; + ShapeModelElement

* current_shape_model; + SerializedElement

* current_serialization; + + // A container and iterator for IfcBuildingElements for the current IfcRepresentation referenced by *shaperep_iterator + IfcSchema::IfcProduct::list::ptr entities; + IfcSchema::IfcProduct::list::it ifcproduct_iterator; + + int done; + int total; + + std::string unit_name; + // double? + P unit_magnitude; + + // Store references to all returned non-geometric elements to be freed when the destructor is called + std::vector*> returned_elements; + + void initUnits() { + // Set default units, set length to meters, angles to undefined + kernel.setValue(IfcGeom::Kernel::GV_LENGTH_UNIT, 1.0); + kernel.setValue(IfcGeom::Kernel::GV_PLANEANGLE_UNIT, -1.0); + + IfcSchema::IfcUnitAssignment::list::ptr unit_assignments = ifc_file->EntitiesByType(); + IfcUtil::IfcAbstractSelect::list::ptr units; + try { + if ( unit_assignments->Size() ) { + IfcSchema::IfcUnitAssignment* unit_assignment = *unit_assignments->begin(); + units = unit_assignment->Units(); + } + } catch (const IfcParse::IfcException&) {} + + if (!units || !units->Size()) { + // No units eh... Since tolerances and deflection are specified internally in meters + // we will try to find another indication of the model size. + IfcSchema::IfcExtrudedAreaSolid::list::ptr extrusions = ifc_file->EntitiesByType(); + if ( ! extrusions->Size() ) return; + double max_height = -1.0f; + for ( IfcSchema::IfcExtrudedAreaSolid::list::it it = extrusions->begin(); it != extrusions->end(); ++ it ) { + try { + const double depth = (*it)->Depth(); + if ( depth > max_height ) max_height = depth; + } catch (const IfcParse::IfcException&) {} + } + if ( max_height > 100.0f ) { + kernel.setValue(IfcGeom::Kernel::GV_LENGTH_UNIT, 0.001); + Logger::Message(Logger::LOG_NOTICE, "Guessed length unit to be in millimeters based on extrusion depth"); + } + return; + } + + try { + for ( IfcUtil::IfcAbstractSelect::list::it it = units->begin(); it != units->end(); ++ it ) { + std::string current_unit_name = ""; + IfcUtil::IfcAbstractSelect* base = *it; + IfcSchema::IfcSIUnit* unit = 0; + double value = 1.f; + if ( base->is(IfcSchema::Type::IfcConversionBasedUnit) ) { + IfcSchema::IfcConversionBasedUnit* u = (IfcSchema::IfcConversionBasedUnit*)base; + current_unit_name = u->Name(); + IfcSchema::IfcMeasureWithUnit* u2 = u->ConversionFactor(); + IfcSchema::IfcUnit u3 = u2->UnitComponent(); + if ( u3->is(IfcSchema::Type::IfcSIUnit) ) { + unit = (IfcSchema::IfcSIUnit*) u3; + } + IfcSchema::IfcValue v = u2->ValueComponent(); + IfcUtil::IfcArgumentSelect* v2 = (IfcUtil::IfcArgumentSelect*) v; + const double f = *v2->wrappedValue(); + value *= f; + } else if ( base->is(IfcSchema::Type::IfcSIUnit) ) { + unit = (IfcSchema::IfcSIUnit*)base; + } + if ( unit ) { + if ( unit->hasPrefix() ) { + value *= IfcGeom::Utils::UnitPrefixToValue(unit->Prefix()); + } + IfcSchema::IfcUnitEnum::IfcUnitEnum type = unit->UnitType(); + if ( type == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT ) { + kernel.setValue(IfcGeom::Kernel::GV_LENGTH_UNIT,value); + if (current_unit_name.empty()) { + if (unit->hasPrefix()) { + current_unit_name = IfcSchema::IfcSIPrefix::ToString(unit->Prefix()); + } + current_unit_name += IfcSchema::IfcSIUnitName::ToString(unit->Name()); + } + unit_magnitude = static_cast

(value); + unit_name = current_unit_name; + } else if ( type == IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) { + kernel.setValue(IfcGeom::Kernel::GV_PLANEANGLE_UNIT, value); + } + } + } + } catch (const IfcParse::IfcException& ex) { + std::stringstream ss; + ss << "Failed to determine unit information '" << ex.what() << "'"; + Logger::Message(Logger::LOG_ERROR, ss.str()); + } + } + + public: + bool findContext() { + + try { + initUnits(); + } catch (...) {} + + // Really this should only be 'Model', as per + // the standard 'Design' is deprecated. So, + // just for backwards compatibility: + std::set context_types; + context_types.insert("model"); + context_types.insert("design"); + // DDS likes to output 'model view' + context_types.insert("model view"); + + double lowest_precision_encountered = std::numeric_limits::infinity(); + bool any_precision_encountered = false; + + representations = IfcSchema::IfcRepresentation::list::ptr(new IfcSchema::IfcRepresentation::list); + + IfcSchema::IfcGeometricRepresentationContext::list::it it; + IfcSchema::IfcGeometricRepresentationSubContext::list::it jt; + IfcSchema::IfcGeometricRepresentationContext::list::ptr contexts = + ifc_file->EntitiesByType(); + + IfcSchema::IfcGeometricRepresentationContext::list::ptr filtered_contexts (new IfcSchema::IfcGeometricRepresentationContext::list); + + for (it = contexts->begin(); it != contexts->end(); ++it) { + IfcSchema::IfcGeometricRepresentationContext* context = *it; + if (context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) { + // Continue, as the list of subcontexts will be considered + // by the parent's context inverse attributes. + continue; + } + 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); + } + if (context->hasContextType() && context_types.find(context_type_lc) != context_types.end()) { + filtered_contexts->push(context); + } + } + + if (filtered_contexts->Size() == 0) { + filtered_contexts = contexts; + } + + for (it = filtered_contexts->begin(); it != filtered_contexts->end(); ++it) { + IfcSchema::IfcGeometricRepresentationContext* context = *it; + + representations->push(context->RepresentationsInContext()); + if (context->hasPrecision() && context->Precision() < lowest_precision_encountered) { + lowest_precision_encountered = context->Precision(); + any_precision_encountered = true; + } + IfcSchema::IfcGeometricRepresentationSubContext::list::ptr sub_contexts = context->HasSubContexts(); + for (jt = sub_contexts->begin(); jt != sub_contexts->end(); ++jt) { + representations->push((*jt)->RepresentationsInContext()); + } + // There is no need for full recursion as the following is governed by the schema: + // WR31: The parent context shall not be another geometric representation sub context. + } + + if (any_precision_encountered) { + kernel.setValue(IfcGeom::Kernel::GV_PRECISION, lowest_precision_encountered); + } else { + kernel.setValue(IfcGeom::Kernel::GV_PRECISION, 1.e-5); + } + + if (representations->Size() == 0) return false; + + shaperep_iterator = representations->begin(); + entities.reset(); + + if (!create()) { + return false; + } + + done = 0; + total = representations->Size(); + + return true; + } + + int progress() { + return 100 * done / total; + } + + const std::string& getUnitName() { + return unit_name; + } + + const P getUnitMagnitude() { + return unit_magnitude; + } + + const std::string getLog() { + return Logger::GetLog(); + } + + IfcParse::IfcFile* getFile() { + return ifc_file; + } + + private: + // Move the the next IfcRepresentation + void _nextShape() { + entities.reset(); + ++ shaperep_iterator; + ++ done; + } + + int _getParentId(IfcSchema::IfcProduct* ifc_product) { + int parent_id = -1; + // In case of an opening element, parent to the RelatingBuildingElement + if ( ifc_product->is(IfcSchema::Type::IfcOpeningElement ) ) { + IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)ifc_product; + IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements(); + if ( voids->Size() ) { + IfcSchema::IfcRelVoidsElement* ifc_void = *voids->begin(); + parent_id = ifc_void->RelatingBuildingElement()->entity->id(); + } + } else if ( ifc_product->is(IfcSchema::Type::IfcElement ) ) { + IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)ifc_product; + IfcSchema::IfcRelFillsElement::list::ptr fills = element->FillsVoids(); + // Incase of a RelatedBuildingElement parent to the opening element + if ( fills->Size() ) { + for ( IfcSchema::IfcRelFillsElement::list::it it = fills->begin(); it != fills->end(); ++ it ) { + IfcSchema::IfcRelFillsElement* fill = *it; + IfcSchema::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement(); + if ( ifc_product == ifc_objectdef ) continue; + parent_id = ifc_objectdef->entity->id(); + } + } + // Else simply parent to the containing structure + if ( parent_id == -1 ) { + IfcSchema::IfcRelContainedInSpatialStructure::list::ptr parents = element->ContainedInStructure(); + if ( parents->Size() ) { + IfcSchema::IfcRelContainedInSpatialStructure* parent = *parents->begin(); + parent_id = parent->RelatingStructure()->entity->id(); + } + } + } + // Parent decompositions to the RelatingObject + if ( parent_id == -1 ) { + IfcEntityList::ptr parents = ifc_product->entity->getInverse(IfcSchema::Type::IfcRelAggregates); + parents->push(ifc_product->entity->getInverse(IfcSchema::Type::IfcRelNests)); + for ( IfcEntityList::it it = parents->begin(); it != parents->end(); ++ it ) { + IfcSchema::IfcRelDecomposes* decompose = (IfcSchema::IfcRelDecomposes*)*it; + IfcSchema::IfcObjectDefinition* ifc_objectdef; + #ifdef USE_IFC4 + if (decompose->is(IfcSchema::Type::IfcRelAggregates)) { + ifc_objectdef = ((IfcSchema::IfcRelAggregates*)decompose)->RelatingObject(); + } else { + continue; + } + #else + ifc_objectdef = decompose->RelatingObject(); + #endif + if ( ifc_product == ifc_objectdef ) continue; + parent_id = ifc_objectdef->entity->id(); + } + } + return parent_id; + } + + ShapeModelElement

* create_shape_model_for_next_entity() { + while ( true ) { + IfcSchema::IfcRepresentation* shaperep; + + // Have we reached the end of our list of representations? + if ( shaperep_iterator == representations->end() ) { + representations.reset(); + return 0; + } + shaperep = *shaperep_iterator; + + // Has the list of IfcProducts for this representation been initialized? + if ( ! entities ) { + + IfcSchema::IfcProductRepresentation::list::ptr prodreps = shaperep->OfProductRepresentation(); + entities = IfcSchema::IfcProduct::list::ptr(new IfcSchema::IfcProduct::list); + for ( IfcSchema::IfcProductRepresentation::list::it it = prodreps->begin(); it != prodreps->end(); ++it ) { + if ( (*it)->is(IfcSchema::Type::IfcProductDefinitionShape) ) { + IfcSchema::IfcProductDefinitionShape* pds = (IfcSchema::IfcProductDefinitionShape*)*it; + entities->push(pds->ShapeOfProduct()); + } else { + // http://buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcrepresentationresource/lexical/ifcproductrepresentation.htm + // IFC2x Edition 3 NOTE Users should not instantiate the entity IfcProductRepresentation from IFC2x Edition 3 onwards. + // It will be changed into an ABSTRACT supertype in future releases of IFC. + + // IfcProductRepresentation also lacks the INVERSE relation to IfcProduct + // Let's find the IfcProducts that reference the IfcProductRepresentation anyway + IfcEntityList::ptr products = (*it)->entity->getInverse(IfcSchema::Type::IfcProduct); + for ( IfcEntityList::it it = products->begin(); it != products->end(); ++ it ) { + entities->push((IfcSchema::IfcProduct*)*it); + } + } + } + // Does this representation have any IfcProducts? + if ( ! entities->Size() ) { + _nextShape(); + continue; + } + ifcproduct_iterator = entities->begin(); + } + // Have we reached the end of our list of IfcProducts? + if ( ifcproduct_iterator == entities->end() ) { + _nextShape(); + continue; + } + + IfcGeom::Representation::BRep* shape; + IfcGeom::IfcRepresentationShapeItems shapes; + + if ( !kernel.convert_shapes(shaperep,shapes) ) { + _nextShape(); + continue; + } + + IfcSchema::IfcProduct* ifc_product = *ifcproduct_iterator; + + int parent_id = -1; + try { + parent_id = _getParentId(ifc_product); + } catch (...) {} + + const std::string name = ifc_product->hasName() ? ifc_product->Name() : ""; + const std::string guid = ifc_product->GlobalId(); + + gp_Trsf trsf; + try { + kernel.convert(ifc_product->ObjectPlacement(),trsf); + } catch (...) {} + + // Does the IfcElement have any IfcOpenings? + // Note that openings for IfcOpeningElements are not processed + IfcSchema::IfcRelVoidsElement::list::ptr openings; + if ( ifc_product->is(IfcSchema::Type::IfcElement) && !ifc_product->is(IfcSchema::Type::IfcOpeningElement) ) { + IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)ifc_product; + openings = element->HasOpenings(); + } + // Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements? + if ( ifc_product->is(IfcSchema::Type::IfcBuildingElementPart ) ) { + IfcSchema::IfcBuildingElementPart* part = (IfcSchema::IfcBuildingElementPart*)ifc_product; + #ifdef USE_IFC4 + IfcSchema::IfcRelAggregates::list::ptr decomposes = part->Decomposes(); + for ( IfcSchema::IfcRelAggregates::list::it it = decomposes->begin(); it != decomposes->end(); ++ it ) { + #else + IfcSchema::IfcRelDecomposes::list::ptr decomposes = part->Decomposes(); + for ( IfcSchema::IfcRelDecomposes::list::it it = decomposes->begin(); it != decomposes->end(); ++ it ) { + #endif + IfcSchema::IfcObjectDefinition* obdef = (*it)->RelatingObject(); + if ( obdef->is(IfcSchema::Type::IfcElement) ) { + IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)obdef; + openings->push(element->HasOpenings()); + } + } + } + + const std::string product_type = IfcSchema::Type::ToString(ifc_product->type()); + ElementSettings element_settings(settings, unit_magnitude, product_type); + + if ( !settings.disable_opening_subtractions() && openings && openings->Size() ) { + IfcGeom::IfcRepresentationShapeItems opened_shapes; + try { + if ( settings.faster_booleans() ) { + bool succes = kernel.convert_openings_fast(ifc_product,openings,shapes,trsf,opened_shapes); + if ( ! succes ) { + opened_shapes.clear(); + kernel.convert_openings(ifc_product,openings,shapes,trsf,opened_shapes); + } + } else { + kernel.convert_openings(ifc_product,openings,shapes,trsf,opened_shapes); + } + } catch(...) { + Logger::Message(Logger::LOG_ERROR,"Error processing openings for:",ifc_product->entity); + } + if ( settings.use_world_coords() ) { + for ( IfcGeom::IfcRepresentationShapeItems::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) { + it->prepend(trsf); + } + trsf = gp_Trsf(); + } + shape = new IfcGeom::Representation::BRep(element_settings, shaperep->entity->id(), opened_shapes); + } else if ( settings.use_world_coords() ) { + for ( IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++ it ) { + it->prepend(trsf); + } + trsf = gp_Trsf(); + shape = new IfcGeom::Representation::BRep(element_settings, shaperep->entity->id(), shapes); + } else { + shape = new IfcGeom::Representation::BRep(element_settings, shaperep->entity->id(), shapes); + } + + return new ShapeModelElement

( + ifc_product->entity->id(), + parent_id, + name, + product_type, + guid, + trsf, + shape + ); + } + } + + public: + + bool next() { + // Free all possible representations of the current geometrical entity + delete current_triangulation; + current_triangulation = 0; + + // Increment the iterator over the list of products using the current + // shape representation + if (entities) { + ++ifcproduct_iterator; + } + + return create(); + } + + Element

* get() { + // TODO: Test settings and throw + if (current_triangulation) return current_triangulation; + else if (current_serialization) return current_serialization; + else if (current_shape_model) return current_shape_model; + else return 0; + } + + const Element

* getObject(int id) { + + gp_Trsf trsf; + int parent_id = -1; + std::string instance_type, product_name, product_guid; + + try { + const IfcUtil::IfcBaseClass* ifc_entity = ifc_file->EntityById(id); + instance_type = IfcSchema::Type::ToString(ifc_entity->type()); + if ( ifc_entity->is(IfcSchema::Type::IfcProduct) ) { + IfcSchema::IfcProduct* ifc_product = (IfcSchema::IfcProduct*)ifc_entity; + + product_guid = ifc_product->GlobalId(); + product_name = ifc_product->hasName() ? ifc_product->Name() : ""; + + try { + parent_id = _getParentId(ifc_product); + } catch (...) {} + + try { + kernel.convert(ifc_product->ObjectPlacement(), trsf); + } catch (...) {} + } + } catch(...) {} + + ElementSettings element_settings(settings, unit_magnitude, instance_type); + Element

* ifc_object = new Element

(element_settings, id, parent_id, product_name, instance_type, product_guid, trsf); + + returned_elements.push_back(ifc_object); + return ifc_object; + } + + bool create() { + try { + current_shape_model = create_shape_model_for_next_entity(); + } catch (...) {} + if (!current_shape_model) return false; + if (settings.use_brep_data()) { + try { + current_serialization = new SerializedElement

(*current_shape_model); + } catch (...) {} + return !!current_serialization; + } else if (!settings.disable_triangulation()) { + try { + current_triangulation = new TriangulationElement

(*current_shape_model); + } catch (...) {} + return !!current_triangulation; + } else { + return false; + } + } + private: + void initialize() { + current_triangulation = 0; + current_shape_model = 0; + current_serialization = 0; + + unit_name = "METER"; + unit_magnitude = 1.f; + + kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1); + kernel.setValue(IfcGeom::Kernel::GV_FORCE_CCW_FACE_ORIENTATION, settings.force_ccw_face_orientation() ? 1 : -1); + } + public: + Iterator(const IteratorSettings& settings, IfcParse::IfcFile* file) + : settings(settings) + , ifc_file(file) + { + initialize(); + } + Iterator(const IteratorSettings& settings, const std::string& filename) + : settings(settings) + , ifc_file(new IfcParse::IfcFile) + { + ifc_file->Init(filename); + initialize(); + } + Iterator(const IteratorSettings& settings, void* data, int length) + : settings(settings) + , ifc_file(new IfcParse::IfcFile) + { + ifc_file->Init(data, length); + initialize(); + } + Iterator(const IteratorSettings& settings, std::istream& filestream, int length) + : settings(settings) + , ifc_file(new IfcParse::IfcFile) + { + ifc_file->Init(filestream, length); + initialize(); + } + + ~Iterator() { + // TODO: Correctly implement destructor for IfcFile + delete ifc_file; + + std::vector*>::const_iterator it; + for (it = returned_elements.begin(); it != returned_elements.end(); ++ it ) { + delete *it; + } + + returned_elements.clear(); + } + }; +} + + +#endif diff --git a/src/ifcgeom/IfcGeomIteratorSettings.h b/src/ifcgeom/IfcGeomIteratorSettings.h new file mode 100644 index 0000000000..2db69fe0f4 --- /dev/null +++ b/src/ifcgeom/IfcGeomIteratorSettings.h @@ -0,0 +1,171 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +#ifndef IFCGEOMITERATORSETTINGS_H +#define IFCGEOMITERATORSETTINGS_H + +#include + +#include "../ifcparse/IfcException.h" + +namespace IfcGeom { + + class IteratorSettings { + public: + // Enumeration of setting identifiers. These settings define the + // behaviour of various aspects of IfcOpenShell. + + // Specifies whether vertices are welded, meaning that the coordinates + // vector will only contain unique xyz-triplets. This results in a + // manifold mesh which is useful for modelling applications, but might + // result in unwanted shading artifacts in rendering applications. + static const int WELD_VERTICES = 1; + // Specifies whether to apply the local placements of building elements + // directly to the coordinates of the representation mesh rather than + // to represent the local placement in the 4x3 matrix, which will in that + // case be the identity matrix. + static const int USE_WORLD_COORDS = 2; + // Internally IfcOpenShell measures everything in meters. This settings + // specifies whether to convert IfcGeomObjects back to the units in which + // the geometry in the IFC file is specified. + static const int CONVERT_BACK_UNITS = 3; + // Specifies whether to use the Open Cascade BREP format for representation + // items rather than to create triangle meshes. This is useful is IfcOpenShell + // is used as a library in an application that is also built on Open Cascade. + static const int USE_BREP_DATA = 4; + // Specifies whether to sew IfcConnectedFaceSets (open and closed shells) to + // TopoDS_Shells or whether to keep them as a loose collection of faces. + static const int SEW_SHELLS = 5; + // Specifies whether to compose IfcOpeningElements into a single compound + // in order to speed up the processing of opening subtractions. + static const int FASTER_BOOLEANS = 6; + // By default singular faces have no explicitly defined orientation, to + // force faces to be defined CounterClockWise set this to true. + static const int FORCE_CCW_FACE_ORIENTATION = 7; + // Disables the subtraction of IfcOpeningElement representations from + // the related building element representations. + static const int DISABLE_OPENING_SUBTRACTIONS = 8; + // Disables the triangulation of the topological representations. Useful if + // the client application understands Open Cascade's native format. + static const int DISABLE_TRIANGULATION = 9; + // Applies default materials to entity instances without a surface style. + static const int APPLY_DEFAULT_MATERIALS = 10; + + // End of settings enumeration. + + private: + bool _weld_vertices, _use_world_coords, _convert_back_units, _use_brep_data, _sew_shells, _faster_booleans, _force_ccw_face_orientation, _disable_opening_subtractions, _disable_triangulation, _apply_default_materials; + double _deflection_tolerance; + public: + IteratorSettings() + : _weld_vertices(true) + , _use_world_coords(false) + , _convert_back_units(false) + , _use_brep_data(false) + , _sew_shells(false) + , _faster_booleans(false) + , _force_ccw_face_orientation(false) + , _disable_triangulation(false) + , _apply_default_materials(false) + // TODO: Make deflection tolerance into a command line argument + // For now, stick to one millimeter. Note that this is independent of the IFC length unit. + , _deflection_tolerance(1.e-3) + {} + + const bool& weld_vertices() const { return _weld_vertices; } + bool& weld_vertices() { return _weld_vertices; } + const bool& use_world_coords() const { return _use_world_coords; } + bool& use_world_coords() { return _use_world_coords; } + const bool& convert_back_units() const { return _convert_back_units; } + bool& convert_back_units() { return _convert_back_units; } + const bool& use_brep_data() const { return _use_brep_data; } + bool& use_brep_data() { return _use_brep_data; } + const bool& sew_shells() const { return _sew_shells; } + bool& sew_shells() { return _sew_shells; } + const bool& faster_booleans() const { return _faster_booleans; } + bool& faster_booleans() { return _faster_booleans; } + const bool& force_ccw_face_orientation() const { return _force_ccw_face_orientation; } + bool& force_ccw_face_orientation() { return _force_ccw_face_orientation; } + const bool& disable_opening_subtractions() const { return _disable_opening_subtractions; } + bool& disable_opening_subtractions() { return _disable_opening_subtractions; } + const bool& disable_triangulation() const { return _disable_triangulation; } + bool& disable_triangulation() { return _disable_triangulation; } + const bool& apply_default_materials() const { return _apply_default_materials; } + bool& apply_default_materials() { return _apply_default_materials; } + + const double& deflection_tolerance() const { return _deflection_tolerance; } + double& deflection_tolerance() { return _deflection_tolerance; } + + void set(int setting, bool value) { + switch (setting) { + case USE_WORLD_COORDS: + _use_world_coords = value; + break; + case WELD_VERTICES: + _weld_vertices = value; + break; + case CONVERT_BACK_UNITS: + _convert_back_units = value; + break; + case USE_BREP_DATA: + _use_brep_data = value; + break; + case FASTER_BOOLEANS: + _faster_booleans = value; + break; + case SEW_SHELLS: + _sew_shells = value; + break; + case FORCE_CCW_FACE_ORIENTATION: + _force_ccw_face_orientation = value; + break; + case DISABLE_OPENING_SUBTRACTIONS: + _disable_opening_subtractions = value; + break; + case DISABLE_TRIANGULATION: + _disable_triangulation = value; + break; + case APPLY_DEFAULT_MATERIALS: + _apply_default_materials = value; + break; + default: throw IfcParse::IfcException("Invalid IteratorSetting"); + } + } + }; + + class ElementSettings : public IteratorSettings { + private: + double _unit_magnitude; + std::string _element_type; + public: + ElementSettings(const IteratorSettings& settings, + double unit_magnitude, + const std::string& element_type) + : IteratorSettings(settings) + , _unit_magnitude(unit_magnitude) + , _element_type(element_type) + {} + + const double& unit_magnitude() const { return _unit_magnitude; } + const std::string& element_type() const { return _element_type; } + }; + +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomMaterial.cpp b/src/ifcgeom/IfcGeomMaterial.cpp new file mode 100644 index 0000000000..04d8b44c7c --- /dev/null +++ b/src/ifcgeom/IfcGeomMaterial.cpp @@ -0,0 +1,34 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +#include "IfcGeomMaterial.h" + +static double black[3] = {0.,0.,0.}; + +IfcGeom::Material::Material(const IfcGeom::SurfaceStyle* style) : style(style) {} +bool IfcGeom::Material::hasDiffuse() const { return style->Diffuse(); } +bool IfcGeom::Material::hasSpecular() const { return style->Specular(); } +bool IfcGeom::Material::hasTransparency() const { return style->Transparency(); } +bool IfcGeom::Material::hasSpecularity() const { return style->Specularity(); } +const double* IfcGeom::Material::diffuse() const { if (hasDiffuse()) return &((*style->Diffuse()).R()); else return black; } +const double* IfcGeom::Material::specular() const { if (hasSpecular()) return &((*style->Specular()).R()); else return black; } +double IfcGeom::Material::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; } +double IfcGeom::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); else return 0; } +const std::string IfcGeom::Material::name() const { return style->Name(); } +bool IfcGeom::Material::operator==(const IfcGeom::Material& other) const { return style == other.style; } diff --git a/src/ifcgeom/IfcGeomMaterial.h b/src/ifcgeom/IfcGeomMaterial.h new file mode 100644 index 0000000000..b82811c407 --- /dev/null +++ b/src/ifcgeom/IfcGeomMaterial.h @@ -0,0 +1,50 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +#ifndef IFCGEOMMATERIAL_H +#define IFCGEOMMATERIAL_H + +#include + +#include "../ifcgeom/IfcGeom.h" + +namespace IfcGeom { + + class Material { + private: + const IfcGeom::SurfaceStyle* style; + public: + explicit Material(const IfcGeom::SurfaceStyle* style = 0); // TODO default constructor for vector? + // Material(const Material& other); + // Material& operator=(const Material& other); + bool hasDiffuse() const; + bool hasSpecular() const; + bool hasTransparency() const; + bool hasSpecularity() const; + const double* diffuse() const; + const double* specular() const; + double transparency() const; + double specularity() const; + const std::string name() const; + bool operator==(const Material& other) const; + }; + +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomObjects.cpp b/src/ifcgeom/IfcGeomObjects.cpp deleted file mode 100644 index f1b3a55498..0000000000 --- a/src/ifcgeom/IfcGeomObjects.cpp +++ /dev/null @@ -1,858 +0,0 @@ -/******************************************************************************** - * * - * This file is part of IfcOpenShell. * - * * - * IfcOpenShell is free software: you can redistribute it and/or modify * - * it under the terms of the Lesser GNU General Public License as published by * - * the Free Software Foundation, either version 3.0 of the License, or * - * (at your option) any later version. * - * * - * IfcOpenShell is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * Lesser GNU General Public License for more details. * - * * - * You should have received a copy of the Lesser GNU General Public License * - * along with this program. If not, see . * - * * - ********************************************************************************/ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../ifcparse/IfcException.h" -#include "../ifcgeom/IfcGeomObjects.h" -#include "../ifcgeom/IfcGeom.h" - -// Welds vertices that belong to different faces -static bool weld_vertices = true; - -static bool convert_back_units = false; -static bool use_faster_booleans = false; -static bool disable_subtractions = false; -static bool disable_triangulation = false; - -int IfcGeomObjects::IfcRepresentationTriangulation::addvert(int material_index, const gp_XYZ& p) { - const float X = convert_back_units ? (float) (p.X() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.X(); - const float Y = convert_back_units ? (float) (p.Y() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.Y(); - const float Z = convert_back_units ? (float) (p.Z() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.Z(); - int i = (int) _verts.size() / 3; - if ( weld_vertices ) { - const VertKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z))); - VertKeyMap::const_iterator it = welds.find(key); - if ( it != welds.end() ) return it->second; - i = (int) welds.size(); - welds[key] = i; - } - _verts.push_back(X); - _verts.push_back(Y); - _verts.push_back(Z); - return i; -} - -static bool use_world_coords = false; -static bool use_brep_data = false; - -static IfcParse::IfcFile* ifc_file = 0; - -IfcGeomObjects::IfcRepresentationBrepData::IfcRepresentationBrepData(const IfcRepresentationShapeModel& shapes) - : _id(shapes.getId()) -{ - try { - TopoDS_Compound compound; - BRep_Builder builder; - builder.MakeCompound(compound); - for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) { - const TopoDS_Shape& s = it->Shape(); - gp_GTrsf trsf = it->Placement(); - if (convert_back_units) { - gp_Trsf scale; - scale.SetScaleFactor(1.0 / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)); - trsf.PreMultiply(scale); - } - bool trsf_valid = false; - gp_Trsf _trsf; - try { - _trsf = trsf.Trsf(); - trsf_valid = true; - } catch (...) {} - const TopoDS_Shape moved_shape = trsf_valid ? s.Moved(_trsf) : - BRepBuilderAPI_GTransform(s,trsf,true).Shape(); - builder.Add(compound,moved_shape); - } - std::stringstream sstream; - BRepTools::Write(compound,sstream); - _brep_data = sstream.str(); - } catch(...) { - Logger::Message(Logger::LOG_ERROR,"Failed to serialize shape:",ifc_file->EntityById(_id)->entity); - } -} - -IfcGeomObjects::IfcRepresentationTriangulation::IfcRepresentationTriangulation(const IfcRepresentationShapeModel& shapes) - : _id(shapes.getId()) -{ - for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) { - - int surface_style_id = -1; - if (it->hasStyle()) { - Material adapter(&it->Style()); - std::vector::const_iterator jt = std::find(_materials.begin(), _materials.end(), adapter); - if (jt == _materials.end()) { - surface_style_id = _materials.size(); - _materials.push_back(adapter); - } else { - surface_style_id = jt - _materials.begin(); - } - } - - const TopoDS_Shape& s = it->Shape(); - const gp_GTrsf& trsf = it->Placement(); - - // Triangulate the shape - try { - // BRepTools::Clean(s); - BRepMesh::Mesh(s, IfcGeom::GetValue(IfcGeom::GV_DEFLECTION_TOLERANCE)); - } catch(...) { - Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape:",ifc_file->EntityById(_id)->entity); - continue; - } - TopExp_Explorer exp; - - // Iterates over the faces of the shape - for ( exp.Init(s,TopAbs_FACE); exp.More(); exp.Next() ) { - TopoDS_Face face = TopoDS::Face(exp.Current()); - TopLoc_Location loc; - Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face,loc); - - if ( ! tri.IsNull() ) { - - // A 3x3 matrix to rotate the vertex normals - const gp_Mat rotation_matrix = trsf.VectorialPart(); - - // Keep track of the number of times an edge is used - // Manifold edges (i.e. edges used twice) are deemed invisible - std::map,int> edgecount; - std::vector > edges_temp; - - const TColgp_Array1OfPnt& nodes = tri->Nodes(); - const TColgp_Array1OfPnt2d& uvs = tri->UVNodes(); - std::vector coords; - BRepGProp_Face prop(face); - std::map dict; - - // Vertex normals are only calculated if vertices are not welded - const bool calculate_normals = ! weld_vertices; - - for( int i = 1; i <= nodes.Length(); ++ i ) { - coords.push_back(nodes(i).Transformed(loc).XYZ()); - trsf.Transforms(*coords.rbegin()); - dict[i] = addvert(surface_style_id, *coords.rbegin()); - - if ( calculate_normals ) { - const gp_Pnt2d& uv = uvs(i); - gp_Pnt p; - 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) { - normal = gp_Dir(normal_direction.XYZ() * rotation_matrix); - } - _normals.push_back((float)normal.X()); - _normals.push_back((float)normal.Y()); - _normals.push_back((float)normal.Z()); - } - } - - const Poly_Array1OfTriangle& triangles = tri->Triangles(); - for( int i = 1; i <= triangles.Length(); ++ i ) { - int n1,n2,n3; - if ( face.Orientation() == TopAbs_REVERSED ) - triangles(i).Get(n3,n2,n1); - else triangles(i).Get(n1,n2,n3); - - /* An alternative would be to calculate normals based - * on the coordinates of the mesh vertices */ - /* - const gp_XYZ pt1 = coords[n1-1]; - const gp_XYZ pt2 = coords[n2-1]; - const gp_XYZ pt3 = coords[n3-1]; - const gp_XYZ v1 = pt2-pt1; - const gp_XYZ v2 = pt3-pt2; - gp_Dir normal = gp_Dir(v1^v2); - _normals.push_back((float)normal.X()); - _normals.push_back((float)normal.Y()); - _normals.push_back((float)normal.Z()); - */ - - _faces.push_back(dict[n1]); - _faces.push_back(dict[n2]); - _faces.push_back(dict[n3]); - - _material_ids.push_back(surface_style_id); - - addedge(n1,n2,edgecount,edges_temp); - addedge(n2,n3,edgecount,edges_temp); - addedge(n3,n1,edgecount,edges_temp); - } - for ( std::vector >::const_iterator it = edges_temp.begin(); it != edges_temp.end(); ++it ) { - _edges.push_back(edgecount[*it]==1); - } - } - } - } -} - -IfcGeomObjects::IfcObject::IfcObject( - int id, - int parent_id, - const std::string& name, - const std::string& type, - const std::string& guid, - const gp_Trsf& trsf) - : _id(id) - , _parent_id(parent_id) - , _name(name) - , _type(type) - , _guid(guid) -{ - // Convert the gp_Trsf into a 4x3 Matrix - // Note that in case the CONVERT_BACK_UNITS setting is enabled - // the translation component of the matrix needs to be divided - // by the magnitude of the IFC model length unit because - // internally in IfcOpenShell everything is measured in meters. - for(int i = 1; i < 5; ++i) { - for (int j = 1; j < 4; ++j) { - const double trsf_value = trsf.Value(j,i); - const double matrix_value = i == 4 && convert_back_units - ? trsf_value / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT) - : trsf_value; - _matrix.push_back(static_cast(matrix_value)); - } - } -} - -IfcGeomObjects::IfcGeomShapeModelObject::IfcGeomShapeModelObject( - int id, - int parent_id, - const std::string& name, - const std::string& type, - const std::string& guid, - const gp_Trsf& trsf, - IfcRepresentationShapeModel* shapes) - : IfcObject(id,parent_id,name,type,guid,trsf) - , _mesh(shapes) -{} - -IfcGeomObjects::IfcGeomBrepDataObject::IfcGeomBrepDataObject( - const IfcGeomShapeModelObject& shape_model) - : IfcObject(shape_model) - , _mesh(new IfcRepresentationBrepData(shape_model.mesh())) -{} - -IfcGeomObjects::IfcGeomObject::IfcGeomObject( - const IfcGeomShapeModelObject& shape_model) - : IfcObject(shape_model) - , _mesh(new IfcRepresentationTriangulation(shape_model.mesh())) -{} - -// A container and iterator for IfcShapeRepresentations -static IfcSchema::IfcShapeRepresentation::list::ptr shapereps; -static IfcSchema::IfcShapeRepresentation::list::it shaperep_iterator; - -// The object is fetched beforehand to be positive an entity actually exists -static IfcGeomObjects::IfcGeomObject* current_geom_obj = 0; -static IfcGeomObjects::IfcGeomShapeModelObject* current_shape_model_obj = 0; -static IfcGeomObjects::IfcGeomBrepDataObject* current_brep_data_obj = 0; - -// A container and iterator for IfcBuildingElements for the current IfcShapeRepresentation referenced by *shaperep_iterator -static IfcSchema::IfcProduct::list::ptr entities; -static IfcSchema::IfcProduct::list::it ifcproduct_iterator; - -static int done; -static int total; - -// Move the the next IfcShapeRepresentation -void _nextShape() { - entities.reset(); - ++ shaperep_iterator; - ++ done; -} - -int _getParentId(IfcSchema::IfcProduct* ifc_product) { - int parent_id = -1; - // In case of an opening element, parent to the RelatingBuildingElement - if ( ifc_product->is(IfcSchema::Type::IfcOpeningElement ) ) { - IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)ifc_product; - IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements(); - if ( voids->Size() ) { - IfcSchema::IfcRelVoidsElement* ifc_void = *voids->begin(); - parent_id = ifc_void->RelatingBuildingElement()->entity->id(); - } - } else if ( ifc_product->is(IfcSchema::Type::IfcElement ) ) { - IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)ifc_product; - IfcSchema::IfcRelFillsElement::list::ptr fills = element->FillsVoids(); - // Incase of a RelatedBuildingElement parent to the opening element - if ( fills->Size() ) { - for ( IfcSchema::IfcRelFillsElement::list::it it = fills->begin(); it != fills->end(); ++ it ) { - IfcSchema::IfcRelFillsElement* fill = *it; - IfcSchema::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement(); - if ( ifc_product == ifc_objectdef ) continue; - parent_id = ifc_objectdef->entity->id(); - } - } - // Else simply parent to the containing structure - if ( parent_id == -1 ) { - IfcSchema::IfcRelContainedInSpatialStructure::list::ptr parents = element->ContainedInStructure(); - if ( parents->Size() ) { - IfcSchema::IfcRelContainedInSpatialStructure* parent = *parents->begin(); - parent_id = parent->RelatingStructure()->entity->id(); - } - } - } - // Parent decompositions to the RelatingObject - if ( parent_id == -1 ) { - IfcEntityList::ptr parents = ifc_product->entity->getInverse(IfcSchema::Type::IfcRelAggregates); - parents->push(ifc_product->entity->getInverse(IfcSchema::Type::IfcRelNests)); - for ( IfcEntityList::it it = parents->begin(); it != parents->end(); ++ it ) { - IfcSchema::IfcRelDecomposes* decompose = (IfcSchema::IfcRelDecomposes*)*it; - IfcSchema::IfcObjectDefinition* ifc_objectdef; -#ifdef USE_IFC4 - if (decompose->is(IfcSchema::Type::IfcRelAggregates)) { - ifc_objectdef = ((IfcSchema::IfcRelAggregates*)decompose)->RelatingObject(); - } else { - continue; - } -#else - ifc_objectdef = decompose->RelatingObject(); -#endif - if ( ifc_product == ifc_objectdef ) continue; - parent_id = ifc_objectdef->entity->id(); - } - } - return parent_id; -} - -IfcGeomObjects::IfcGeomShapeModelObject* create_shape_model_for_next_entity() { - while ( true ) { - IfcSchema::IfcShapeRepresentation* shaperep; - - // Have we reached the end of our list of representations? - if ( shaperep_iterator == shapereps->end() ) { - shapereps.reset(); - return 0; - } - shaperep = *shaperep_iterator; - - // Has the list of IfcProducts for this representation been initialized? - if ( ! entities ) { - if ( shaperep->hasRepresentationIdentifier() ) { - const std::string representation_identifier = shaperep->RepresentationIdentifier(); - if ( shaperep->hasRepresentationType() && representation_identifier == "IAI" && shaperep->RepresentationType() != "BoundingBox" ) { - // Allow for Ifc 2x compatibility - } else if ( representation_identifier != "Body" && - representation_identifier != "Facetation" ) { - _nextShape(); - continue; - } - } - IfcSchema::IfcProductRepresentation::list::ptr prodreps = shaperep->OfProductRepresentation(); - entities = IfcSchema::IfcProduct::list::ptr(new IfcSchema::IfcProduct::list); - for ( IfcSchema::IfcProductRepresentation::list::it it = prodreps->begin(); it != prodreps->end(); ++it ) { - if ( (*it)->is(IfcSchema::Type::IfcProductDefinitionShape) ) { - IfcSchema::IfcProductDefinitionShape* pds = (IfcSchema::IfcProductDefinitionShape*)*it; - entities->push(pds->ShapeOfProduct()); - } else { - // http://buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcrepresentationresource/lexical/ifcproductrepresentation.htm - // IFC2x Edition 3 NOTE Users should not instantiate the entity IfcProductRepresentation from IFC2x Edition 3 onwards. - // It will be changed into an ABSTRACT supertype in future releases of IFC. - - // IfcProductRepresentation also lacks the INVERSE relation to IfcProduct - // Let's find the IfcProducts that reference the IfcProductRepresentation anyway - IfcEntityList::ptr products = (*it)->entity->getInverse(IfcSchema::Type::IfcProduct); - for ( IfcEntityList::it it = products->begin(); it != products->end(); ++ it ) { - entities->push((IfcSchema::IfcProduct*)*it); - } - } - } - // Does this representation have any IfcProducts? - if ( ! entities->Size() ) { - _nextShape(); - continue; - } - ifcproduct_iterator = entities->begin(); - } - // Have we reached the end of our list of IfcProducts? - if ( ifcproduct_iterator == entities->end() ) { - _nextShape(); - continue; - } - - IfcGeomObjects::IfcRepresentationShapeModel* shape; - IfcGeom::IfcRepresentationShapeItems shapes; - - if ( !IfcGeom::convert_shapes(shaperep,shapes) ) { - _nextShape(); - continue; - } - - IfcSchema::IfcProduct* ifc_product = *ifcproduct_iterator; - - int parent_id = -1; - try { - parent_id = _getParentId(ifc_product); - } catch (...) {} - - const std::string name = ifc_product->hasName() ? ifc_product->Name() : ""; - const std::string guid = ifc_product->GlobalId(); - - gp_Trsf trsf; - try { - IfcGeom::convert(ifc_product->ObjectPlacement(),trsf); - } catch (...) {} - - // Does the IfcElement have any IfcOpenings? - // Note that openings for IfcOpeningElements are not processed - IfcSchema::IfcRelVoidsElement::list::ptr openings; - if ( ifc_product->is(IfcSchema::Type::IfcElement) && !ifc_product->is(IfcSchema::Type::IfcOpeningElement) ) { - IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)ifc_product; - openings = element->HasOpenings(); - } - // Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements? - if ( ifc_product->is(IfcSchema::Type::IfcBuildingElementPart ) ) { - IfcSchema::IfcBuildingElementPart* part = (IfcSchema::IfcBuildingElementPart*)ifc_product; -#ifdef USE_IFC4 - IfcSchema::IfcRelAggregates::list::ptr decomposes = part->Decomposes(); - for ( IfcSchema::IfcRelAggregates::list::it it = decomposes->begin(); it != decomposes->end(); ++ it ) { -#else - IfcSchema::IfcRelDecomposes::list::ptr decomposes = part->Decomposes(); - for ( IfcSchema::IfcRelDecomposes::list::it it = decomposes->begin(); it != decomposes->end(); ++ it ) { -#endif - IfcSchema::IfcObjectDefinition* obdef = (*it)->RelatingObject(); - if ( obdef->is(IfcSchema::Type::IfcElement) ) { - IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)obdef; - openings->push(element->HasOpenings()); - } - } - } - - if ( !disable_subtractions && openings && openings->Size() ) { - IfcGeom::IfcRepresentationShapeItems opened_shapes; - try { - if ( use_faster_booleans ) { - bool succes = IfcGeom::convert_openings_fast(ifc_product,openings,shapes,trsf,opened_shapes); - if ( ! succes ) { - opened_shapes.clear(); - IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes); - } - } else { - IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes); - } - } catch(...) { - Logger::Message(Logger::LOG_ERROR,"Error processing openings for:",ifc_product->entity); - } - if ( use_world_coords ) { - for ( IfcGeom::IfcRepresentationShapeItems::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) { - it->prepend(trsf); - } - trsf = gp_Trsf(); - } - shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),opened_shapes); - } else if ( use_world_coords ) { - for ( IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++ it ) { - it->prepend(trsf); - } - trsf = gp_Trsf(); - shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),shapes); - } else { - shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),shapes); - } - - return new IfcGeomObjects::IfcGeomShapeModelObject(ifc_product->entity->id(), parent_id, name, - IfcSchema::Type::ToString(ifc_product->type()), guid, trsf, shape); - } -} - -bool try_and_create_representations_for_current_entity() { - current_shape_model_obj = create_shape_model_for_next_entity(); - if (current_shape_model_obj == 0) { - return false; - } - - if (use_brep_data) { - current_brep_data_obj = new IfcGeomObjects::IfcGeomBrepDataObject(*current_shape_model_obj); - if (current_brep_data_obj == 0) { - return false; - } - } - - if (!disable_triangulation) { - current_geom_obj = new IfcGeomObjects::IfcGeomObject(*current_shape_model_obj); - if (current_geom_obj == 0) { - return false; - } - } - - return true; -} - -bool IfcGeomObjects::Next() { - // Free all possible representations of the current geometrical entity - delete current_geom_obj; - delete current_brep_data_obj; - delete current_shape_model_obj; - current_geom_obj = 0; - current_brep_data_obj = 0; - current_shape_model_obj = 0; - - // Increment the iterator over the list of products using the current - // shape representation - if (entities) { - ++ifcproduct_iterator; - } - - return try_and_create_representations_for_current_entity(); -} - -static std::vector returned_objects; -bool IfcGeomObjects::CleanUp() { - // TODO: Correctly implement destructor for IfcFile - delete ifc_file; - IfcGeom::Cache::Purge(); - std::vector::const_iterator it; - for (it = returned_objects.begin(); it != returned_objects.end(); ++ it ) { - delete *it; - } - returned_objects.clear(); - return true; -} -const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) { - IfcObject* ifc_object = 0; - try { - const IfcUtil::IfcBaseClass* ifc_entity = ifc_file->EntityById(id); - if ( ifc_entity->is(IfcSchema::Type::IfcProduct) ) { - IfcSchema::IfcProduct* ifc_product = (IfcSchema::IfcProduct*)ifc_entity; - int parent_id = -1; - try { - parent_id = _getParentId(ifc_product); - } catch (...) {} - const std::string name = ifc_product->hasName() ? ifc_product->Name() : ""; - gp_Trsf trsf; - try { - IfcGeom::convert(ifc_product->ObjectPlacement(),trsf); - } catch (...) {} - ifc_object = new IfcObject(ifc_product->entity->id(),parent_id,name, - IfcSchema::Type::ToString(ifc_product->type()),ifc_product->GlobalId(),trsf); - } - } catch(...) {} - if ( !ifc_object ) ifc_object = new IfcObject(-1,-1,"","","",gp_Trsf()); - returned_objects.push_back(ifc_object); - return ifc_object; -} -const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() { - if (disable_triangulation) { - throw std::runtime_error("No triangulation available"); - } - return current_geom_obj; -} -const IfcGeomObjects::IfcGeomShapeModelObject* IfcGeomObjects::GetShapeModel() { - return current_shape_model_obj; -} -const IfcGeomObjects::IfcGeomBrepDataObject* IfcGeomObjects::GetBrepData() { - if (!use_brep_data) { - throw std::runtime_error("No BRep data available"); - } - return current_brep_data_obj; -} -double UnitPrefixToValue( IfcSchema::IfcSIPrefix::IfcSIPrefix v ) { - if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_EXA ) return (double) 1e18; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PETA ) return (double) 1e15; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_TERA ) return (double) 1e12; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_GIGA ) return (double) 1e9; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MEGA ) return (double) 1e6; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_KILO ) return (double) 1e3; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_HECTO ) return (double) 1e2; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_DECA ) return (double) 1; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_DECI ) return (double) 1e-1; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_CENTI ) return (double) 1e-2; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MILLI ) return (double) 1e-3; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MICRO ) return (double) 1e-6; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_NANO ) return (double) 1e-9; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PICO ) return (double) 1e-12; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_FEMTO ) return (double) 1e-15; - else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_ATTO ) return (double) 1e-18; - else return 1.0f; -} - -static std::string unit_name = "METER"; -static float unit_magnitude = 1.0f; - -void IfcGeomObjects::InitPrecision() { - IfcGeom::SetValue(IfcGeom::GV_PRECISION, 0.00001); - - try { - IfcSchema::IfcGeometricRepresentationContext::list::ptr rep_contexts = ifc_file->EntitiesByType(); - // Currently, IfcGeometricRepresentationContext aren't used as much as they should be - // in the evaluation of shape representations, hence, we try to find the one with the - // lowest precision. Typically, a value of 1e-5 is encountered. This value is applied - // to all TopoDS_Shapes generated by one of the IfcGeom::convert() functions. - // TODO: Many of the empirically found tolerances should probably be substituted by - // one that is defined in the model file. - double lowest_precision_encountered = std::numeric_limits::infinity(); - bool any_precision_encountered = false; - for (IfcSchema::IfcGeometricRepresentationContext::list::it it = rep_contexts->begin(); it != rep_contexts->end(); ++it) { - IfcSchema::IfcGeometricRepresentationContext* rep_context = *it; - if (rep_context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) continue; - if (rep_context->hasPrecision()) { - const double precision = rep_context->Precision(); - if (precision < lowest_precision_encountered) { - any_precision_encountered = true; - lowest_precision_encountered = precision; - } - } - } - if (any_precision_encountered) { - lowest_precision_encountered *= unit_magnitude; - if (lowest_precision_encountered < 1.e-8) { - Logger::Message(Logger::LOG_WARNING, "Precision lower than 0.00000001 meter not enforced"); - IfcGeom::SetValue(IfcGeom::GV_PRECISION, 1.e-8); - } else { - IfcGeom::SetValue(IfcGeom::GV_PRECISION, lowest_precision_encountered); - } - } - } catch (const IfcParse::IfcException& ex) { - std::stringstream ss; - ss << "Failed to determine precision value '" << ex.what() << "'"; - Logger::Message(Logger::LOG_ERROR, ss.str()); - } -} - -void IfcGeomObjects::InitUnits() { - // Set default units, set length to meters, angles to undefined - IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,1.0); - IfcGeom::SetValue(IfcGeom::GV_PLANEANGLE_UNIT,-1.0); - - IfcSchema::IfcUnitAssignment::list::ptr unit_assignments = ifc_file->EntitiesByType(); - IfcUtil::IfcAbstractSelect::list::ptr units; - try { - if ( unit_assignments->Size() ) { - IfcSchema::IfcUnitAssignment* unit_assignment = *unit_assignments->begin(); - units = unit_assignment->Units(); - } - } catch (const IfcParse::IfcException&) {} - - if (!units || !units->Size()) { - // No units eh... Since tolerances and deflection are specified internally in meters - // we will try to find another indication of the model size. - IfcSchema::IfcExtrudedAreaSolid::list::ptr extrusions = ifc_file->EntitiesByType(); - if ( ! extrusions->Size() ) return; - double max_height = -1.0f; - for ( IfcSchema::IfcExtrudedAreaSolid::list::it it = extrusions->begin(); it != extrusions->end(); ++ it ) { - try { - const double depth = (*it)->Depth(); - if ( depth > max_height ) max_height = depth; - } catch (const IfcParse::IfcException&) {} - } - if ( max_height > 100.0f ) { - IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,0.001); - Logger::Message(Logger::LOG_NOTICE, "Guessed length unit to be in millimeters based on extrusion depth"); - } - return; - } - - try { - for ( IfcUtil::IfcAbstractSelect::list::it it = units->begin(); it != units->end(); ++ it ) { - std::string current_unit_name = ""; - IfcUtil::IfcAbstractSelect* base = *it; - IfcSchema::IfcSIUnit* unit = 0; - double value = 1.0f; - if ( base->is(IfcSchema::Type::IfcConversionBasedUnit) ) { - IfcSchema::IfcConversionBasedUnit* u = (IfcSchema::IfcConversionBasedUnit*)base; - current_unit_name = u->Name(); - IfcSchema::IfcMeasureWithUnit* u2 = u->ConversionFactor(); - IfcSchema::IfcUnit u3 = u2->UnitComponent(); - if ( u3->is(IfcSchema::Type::IfcSIUnit) ) { - unit = (IfcSchema::IfcSIUnit*) u3; - } - IfcSchema::IfcValue v = u2->ValueComponent(); - IfcUtil::IfcArgumentSelect* v2 = (IfcUtil::IfcArgumentSelect*) v; - const double f = *v2->wrappedValue(); - value *= f; - } else if ( base->is(IfcSchema::Type::IfcSIUnit) ) { - unit = (IfcSchema::IfcSIUnit*)base; - } - if ( unit ) { - if ( unit->hasPrefix() ) { - value *= UnitPrefixToValue(unit->Prefix()); - } - IfcSchema::IfcUnitEnum::IfcUnitEnum type = unit->UnitType(); - if ( type == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT ) { - IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,value); - if (current_unit_name.empty()) { - if (unit->hasPrefix()) { - current_unit_name = IfcSchema::IfcSIPrefix::ToString(unit->Prefix()); - } - current_unit_name += IfcSchema::IfcSIUnitName::ToString(unit->Name()); - } - unit_magnitude = value; - unit_name = current_unit_name; - } else if ( type == IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) { - IfcGeom::SetValue(IfcGeom::GV_PLANEANGLE_UNIT,value); - } - } - } - } catch (const IfcParse::IfcException& ex) { - std::stringstream ss; - ss << "Failed to determine unit information '" << ex.what() << "'"; - Logger::Message(Logger::LOG_ERROR, ss.str()); - } -} - -bool IfcGeomObjects::Init(const std::string fn) { - return IfcGeomObjects::Init(fn, 0, 0); -} -bool _Init() { - IfcGeomObjects::InitUnits(); - IfcGeomObjects::InitPrecision(); - - shapereps = ifc_file->EntitiesByType(); - if ( ! shapereps ) return false; - - shaperep_iterator = shapereps->begin(); - entities.reset(); - - if (!try_and_create_representations_for_current_entity()) { - return false; - } - - done = 0; - total = shapereps->Size(); - return true; -} -bool IfcGeomObjects::Init(const std::string fn, std::ostream* log1, std::ostream* log2) { - Logger::SetOutput(log1,log2); - ifc_file = new IfcParse::IfcFile(); - if ( !ifc_file->Init(fn) ) return false; - return _Init(); -} -bool IfcGeomObjects::Init(std::istream& f, int len, std::ostream* log1, std::ostream* log2) { - Logger::SetOutput(log1,log2); - ifc_file = new IfcParse::IfcFile(); - if ( !ifc_file->Init(f, len) ) return false; - return _Init(); -} -bool IfcGeomObjects::Init(void* data, int len) { - Logger::SetOutput(0,0); - ifc_file = new IfcParse::IfcFile(); - if ( !ifc_file->Init(data, len) ) return false; - return _Init(); -} -void IfcGeomObjects::Settings(int setting, bool value) { - switch ( setting ) { - case USE_WORLD_COORDS: - use_world_coords = value; - break; - case WELD_VERTICES: - weld_vertices = value; - break; - case CONVERT_BACK_UNITS: - convert_back_units = value; - break; - case USE_BREP_DATA: - use_brep_data = value; - break; - case FASTER_BOOLEANS: - use_faster_booleans = value; - break; - case SEW_SHELLS: - IfcGeom::SetValue(IfcGeom::GV_MAX_FACES_TO_SEW,value ? 1000 : -1); - break; - case FORCE_CCW_FACE_ORIENTATION: - IfcGeom::SetValue(IfcGeom::GV_FORCE_CCW_FACE_ORIENTATION,value ? 1 : -1); - break; - case DISABLE_OPENING_SUBTRACTIONS: - disable_subtractions = value; - break; - case DISABLE_TRIANGULATION: - disable_triangulation = value; - break; - } -} -int IfcGeomObjects::Progress() { - return 100 * done / total; -} - -const std::string& IfcGeomObjects::GetUnitName() { - return unit_name; -} - -const float IfcGeomObjects::GetUnitMagnitude() { - return unit_magnitude; -} - -const std::string IfcGeomObjects::GetLog() { - return Logger::GetLog(); -} - -IfcParse::IfcFile* IfcGeomObjects::GetFile() { - return ifc_file; -} - -static double black[3] = {0,0,0}; - -IfcGeomObjects::Material::Material(const IfcGeom::SurfaceStyle* style) : style(style) {} -bool IfcGeomObjects::Material::hasDiffuse() const { return style->Diffuse(); } -bool IfcGeomObjects::Material::hasSpecular() const { return style->Specular(); } -bool IfcGeomObjects::Material::hasTransparency() const { return style->Transparency(); } -bool IfcGeomObjects::Material::hasSpecularity() const { return style->Specularity(); } -const double* IfcGeomObjects::Material::diffuse() const { if (hasDiffuse()) return &((*style->Diffuse()).R()); else return black; } -const double* IfcGeomObjects::Material::specular() const { if (hasSpecular()) return &((*style->Specular()).R()); else return black; } -double IfcGeomObjects::Material::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; } -double IfcGeomObjects::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); else return 0; } -const std::string IfcGeomObjects::Material::name() const { return style->Name(); } -bool IfcGeomObjects::Material::operator==(const IfcGeomObjects::Material& other) const { return style == other.style; } - -int IfcGeomObjects::IfcRepresentationBrepData::id() const { return _id; } -const std::string& IfcGeomObjects::IfcRepresentationBrepData::brep_data() const { return _brep_data; } - -int IfcGeomObjects::IfcRepresentationTriangulation::id() const { return _id; } -const std::vector& IfcGeomObjects::IfcRepresentationTriangulation::verts() const { return _verts; } -const std::vector& IfcGeomObjects::IfcRepresentationTriangulation::faces() const { return _faces; } -const std::vector& IfcGeomObjects::IfcRepresentationTriangulation::edges() const { return _edges; } -const std::vector& IfcGeomObjects::IfcRepresentationTriangulation::normals() const { return _normals; } -const std::vector& IfcGeomObjects::IfcRepresentationTriangulation::material_ids() const { return _material_ids; } -const std::vector& IfcGeomObjects::IfcRepresentationTriangulation::materials() const { return _materials; } - -int IfcGeomObjects::IfcObject::id() const { return _id; } -int IfcGeomObjects::IfcObject::parent_id() const { return _parent_id; } -const std::string& IfcGeomObjects::IfcObject::name() const { return _name; } -const std::string& IfcGeomObjects::IfcObject::type() const { return _type; } -const std::string& IfcGeomObjects::IfcObject::guid() const { return _guid; } -const std::vector& IfcGeomObjects::IfcObject::matrix() const { return _matrix; } - -const IfcGeomObjects::IfcRepresentationShapeModel& IfcGeomObjects::IfcGeomShapeModelObject::mesh() const { return *_mesh; } -const IfcGeomObjects::IfcRepresentationTriangulation& IfcGeomObjects::IfcGeomObject::mesh() const { return *_mesh; } -const IfcGeomObjects::IfcRepresentationBrepData& IfcGeomObjects::IfcGeomBrepDataObject::mesh() const { return *_mesh; } - diff --git a/src/ifcgeom/IfcGeomObjects.h b/src/ifcgeom/IfcGeomObjects.h deleted file mode 100644 index 95f8ea023c..0000000000 --- a/src/ifcgeom/IfcGeomObjects.h +++ /dev/null @@ -1,286 +0,0 @@ -/******************************************************************************** - * * - * This file is part of IfcOpenShell. * - * * - * IfcOpenShell is free software: you can redistribute it and/or modify * - * it under the terms of the Lesser GNU General Public License as published by * - * the Free Software Foundation, either version 3.0 of the License, or * - * (at your option) any later version. * - * * - * IfcOpenShell is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * Lesser GNU General Public License for more details. * - * * - * You should have received a copy of the Lesser GNU General Public License * - * along with this program. If not, see . * - * * - ********************************************************************************/ - -/******************************************************************************** - * * - * Geometrical data in an IFC file consists of shapes (IfcShapeRepresentation) * - * and instances (SUBTYPE OF IfcBuildingElement e.g. IfcWindow). * - * * - * IfcMesh is a class that represents a triangulated IfcShapeRepresentation. * - * IfcMesh.verts is a 1 dimensional vector of float defining the cartesian * - * coordinates of the vertices of the triangulated shape in the format of * - * [x1,y1,z1,..,xn,yn,zn] * - * IfcMesh.faces is a 1 dimensional vector of int containing the indices of * - * the triangles referencing positions in IfcMesh.verts * - * IfcMesh.edges is a 1 dimensional vector of int in {0,1} that dictates * - * the visibility of the edges that span the faces in IfcMesh.faces * - * * - * IfcGeomObject represents the actual IfcBuildingElements. * - * IfcGeomObject.name is the GUID of the element * - * IfcGeomObject.type is the datatype of the element e.g. IfcWindow * - * IfcGeomObject.mesh is a pointer to an IfcMesh * - * IfcGeomObject.matrix is a 4x3 matrix that defines the orientation and * - * translation of the mesh in relation to the world origin * - * * - * Init(char* fn) parses the IFC file in fn, returns true on succes. * - * * - * Get() returns a pointer to the current IfcGeomObject * - * * - * Next() returns true if there is an entity yet available * - * * - * Progress() returns an int in [0..100] that indicates the overall progress * - * * - ********************************************************************************/ - -#ifndef IFCOBJECTS_H -#define IFCOBJECTS_H - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "../ifcparse/IfcParse.h" -#include "../ifcgeom/IfcRepresentationShapeItem.h" - -namespace IfcGeomObjects { - - // Enumeration of setting identifiers. These settings define the - // behaviour of various aspects of IfcOpenShell. - - // Specifies whether vertices are welded, meaning that the coordinates - // vector will only contain unique xyz-triplets. This results in a - // manifold mesh which is useful for modelling applications, but might - // result in unwanted shading artifacts in rendering applications. - const int WELD_VERTICES = 1; - // Specifies whether to apply the local placements of building elements - // directly to the coordinates of the representation mesh rather than - // to represent the local placement in the 4x3 matrix, which will in that - // case be the identity matrix. - const int USE_WORLD_COORDS = 2; - // Internally IfcOpenShell measures everything in meters. This settings - // specifies whether to convert IfcGeomObjects back to the units in which - // the geometry in the IFC file is specified. - const int CONVERT_BACK_UNITS = 3; - // Specifies whether to use the Open Cascade BREP format for representation - // items rather than to create triangle meshes. This is useful is IfcOpenShell - // is used as a library in an application that is also built on Open Cascade. - const int USE_BREP_DATA = 4; - // Specifies whether to sew IfcConnectedFaceSets (open and closed shells) to - // TopoDS_Shells or whether to keep them as a loose collection of faces. - const int SEW_SHELLS = 5; - // Specifies whether to compose IfcOpeningElements into a single compound - // in order to speed up the processing of opening subtractions. - const int FASTER_BOOLEANS = 6; - // By default singular faces have no explicitly defined orientation, to - // force faces to be defined CounterClockWise set this to true. - const int FORCE_CCW_FACE_ORIENTATION = 7; - // Disables the subtraction of IfcOpeningElement representations from - // the related building element representations. - const int DISABLE_OPENING_SUBTRACTIONS = 8; - // Disables the triangulation of the topological representations. Useful if - // the client application understands Open Cascade's native format. - const int DISABLE_TRIANGULATION = 9; - - // End of settings enumeration. - - // A nested pair of floats and a material index to be able to store an XYZ coordinate in a map. - // TODO: Make this a std::tuple when compilers add support for that. - typedef std::pair > > VertKey; - typedef std::map VertKeyMap; - typedef std::pair Edge; - - class Material { - private: - const IfcGeom::SurfaceStyle* style; - public: - explicit Material(const IfcGeom::SurfaceStyle* style); - // Material(const Material& other); - // Material& operator=(const Material& other); - bool hasDiffuse() const; - bool hasSpecular() const; - bool hasTransparency() const; - bool hasSpecularity() const; - const double* diffuse() const; - const double* specular() const; - double transparency() const; - double specularity() const; - const std::string name() const; - bool operator==(const Material& other) const; - }; - - class IfcRepresentationShapeModel { - private: - unsigned int id; - const IfcGeom::IfcRepresentationShapeItems shapes; - IfcRepresentationShapeModel(const IfcRepresentationShapeModel& other); - IfcRepresentationShapeModel& operator=(const IfcRepresentationShapeModel& other); - public: - IfcRepresentationShapeModel(unsigned int id, const IfcGeom::IfcRepresentationShapeItems& shapes) - : id(id) - , shapes(shapes) - {} - virtual ~IfcRepresentationShapeModel() {} - IfcGeom::IfcRepresentationShapeItems::const_iterator begin() const { return shapes.begin(); } - IfcGeom::IfcRepresentationShapeItems::const_iterator end() const { return shapes.end(); } - const unsigned int& getId() const { return id; } - }; - - class IfcRepresentationBrepData { - private: - int _id; - std::string _brep_data; - public: - int id() const; - const std::string& brep_data() const; - IfcRepresentationBrepData(const IfcRepresentationShapeModel& s); - virtual ~IfcRepresentationBrepData() {} - private: - IfcRepresentationBrepData(); - IfcRepresentationBrepData(const IfcRepresentationBrepData&); - IfcRepresentationBrepData& operator=(const IfcRepresentationBrepData&); - }; - - class IfcRepresentationTriangulation { - private: - int _id; - std::vector _verts; - std::vector _faces; - std::vector _edges; - std::vector _normals; - std::vector _material_ids; - std::vector _materials; - VertKeyMap welds; - public: - int id() const; - const std::vector& verts() const; - const std::vector& faces() const; - const std::vector& edges() const; - const std::vector& normals() const; - const std::vector& material_ids() const; - const std::vector& materials() const; - IfcRepresentationTriangulation(const IfcRepresentationShapeModel& s); - virtual ~IfcRepresentationTriangulation() {} - private: - int addvert(int material_index, const gp_XYZ& p); - inline void addedge(int n1, int n2, std::map,int>& edgecount, std::vector >& edges_temp) { - const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) ); - if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1; - else edgecount[e] ++; - edges_temp.push_back(e); - } - IfcRepresentationTriangulation(); - IfcRepresentationTriangulation(const IfcRepresentationTriangulation&); - IfcRepresentationTriangulation& operator=(const IfcRepresentationTriangulation&); - }; - - class IfcObject { - private: - int _id; - int _parent_id; - std::string _name; - std::string _type; - std::string _guid; - std::vector _matrix; - public: - int id() const; - int parent_id() const; - const std::string& name() const; - const std::string& type() const; - const std::string& guid() const; - const std::vector& matrix() const; - IfcObject(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf); - virtual ~IfcObject() {} - }; - - class IfcGeomShapeModelObject : public IfcObject { - private: - IfcRepresentationShapeModel* _mesh; - public: - const IfcRepresentationShapeModel& mesh() const; - IfcGeomShapeModelObject(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf, IfcRepresentationShapeModel* mesh); - virtual ~IfcGeomShapeModelObject() { - delete _mesh; - } - private: - IfcGeomShapeModelObject(const IfcGeomShapeModelObject& other); - IfcGeomShapeModelObject& operator=(const IfcGeomShapeModelObject& other); - }; - - class IfcGeomObject : public IfcObject { - private: - IfcRepresentationTriangulation* _mesh; - public: - const IfcRepresentationTriangulation& mesh() const; - IfcGeomObject(const IfcGeomShapeModelObject& shape_model); - virtual ~IfcGeomObject() { - delete _mesh; - } - private: - IfcGeomObject(const IfcGeomObject& other); - IfcGeomObject& operator=(const IfcGeomObject& other); - }; - - class IfcGeomBrepDataObject : public IfcObject { - private: - IfcRepresentationBrepData* _mesh; - public: - const IfcRepresentationBrepData& mesh() const; - IfcGeomBrepDataObject(const IfcGeomShapeModelObject& shape_model); - virtual ~IfcGeomBrepDataObject() { - delete _mesh; - } - private: - IfcGeomBrepDataObject(const IfcGeomBrepDataObject& other); - IfcGeomBrepDataObject& operator=(const IfcGeomBrepDataObject& other); - }; - - bool Init(const std::string fn); - bool Init(void* data, int len); - bool Init(const std::string fn, std::ostream* log1= 0, std::ostream* log2= 0); - bool Init(std::istream& f, int len, std::ostream* log1= 0, std::ostream* log2= 0); - - void Settings(int setting, bool value); - void InitUnits(); - void InitPrecision(); - - const IfcGeomObject* Get(); - const IfcObject* GetObject(int id); - const IfcGeomBrepDataObject* GetBrepData(); - const IfcGeomShapeModelObject* GetShapeModel(); - - bool Next(); - int Progress(); - - const std::string& GetUnitName(); - const float GetUnitMagnitude(); - - const std::string GetLog(); - IfcParse::IfcFile* GetFile(); - - bool CleanUp(); -} - -#endif diff --git a/src/ifcgeom/IfcGeomRenderStyles.cpp b/src/ifcgeom/IfcGeomRenderStyles.cpp index 0c3000e519..30157c4169 100644 --- a/src/ifcgeom/IfcGeomRenderStyles.cpp +++ b/src/ifcgeom/IfcGeomRenderStyles.cpp @@ -19,16 +19,7 @@ #include -#include "IfcGeomRenderStyles.h" - -namespace IfcGeom { - namespace Cache { - std::map Style; - void PurgeStyleCache() { - Style.clear(); - } - } -} +#include "IfcGeom.h" bool process_colour(IfcSchema::IfcColourRgb* colour, std::tr1::array& rgb) { if (colour != 0) { @@ -59,14 +50,14 @@ bool process_colour(IfcSchema::IfcColourOrFactor colour_or_factor, std::tr1::arr } } -const IfcGeom::SurfaceStyle* IfcGeom::get_style(const IfcSchema::IfcRepresentationItem* item) { +const IfcGeom::SurfaceStyle* IfcGeom::Kernel::get_style(const IfcSchema::IfcRepresentationItem* item) { std::pair shading_styles = get_surface_style(item); if (shading_styles.second == 0) { return 0; } int surface_style_id = shading_styles.first->entity->id(); - std::map::const_iterator it = Cache::Style.find(surface_style_id); - if (it != Cache::Style.end()) { + std::map::const_iterator it = cache.Style.find(surface_style_id); + if (it != cache.Style.end()) { return &(it->second); } SurfaceStyle surface_style; @@ -113,7 +104,7 @@ const IfcGeom::SurfaceStyle* IfcGeom::get_style(const IfcSchema::IfcRepresentati surface_style.Transparency().reset(d); } } - return &(Cache::Style[surface_style_id] = surface_style); + return &(cache.Style[surface_style_id] = surface_style); } static std::map default_materials; @@ -161,9 +152,11 @@ void InitDefaultMaterials() { const IfcGeom::SurfaceStyle* IfcGeom::get_default_style(const std::string& s) { if (!default_materials_initialized) InitDefaultMaterials(); std::map::const_iterator it = default_materials.find(s); - if (it == default_materials.end()) return &default_material; - else { - const IfcGeom::SurfaceStyle& surface_style = it->second; - return &surface_style; + if (it == default_materials.end()) { + default_materials.insert(std::make_pair(s, IfcGeom::SurfaceStyle(s))); + default_materials[s].Diffuse().reset(*default_material.Diffuse()); + it = default_materials.find(s); } + const IfcGeom::SurfaceStyle& surface_style = it->second; + return &surface_style; } diff --git a/src/ifcgeom/IfcGeomRenderStyles.h b/src/ifcgeom/IfcGeomRenderStyles.h index 2838cee1f6..08d27bb98e 100644 --- a/src/ifcgeom/IfcGeomRenderStyles.h +++ b/src/ifcgeom/IfcGeomRenderStyles.h @@ -56,10 +56,20 @@ namespace IfcGeom { boost::optional transparency; boost::optional specularity; public: - SurfaceStyle() {} - SurfaceStyle(int id) : id(id) {} + SurfaceStyle() { + this->name = "IfcSurfaceStyleShading"; + } + SurfaceStyle(int id) : id(id) { + std::stringstream sstr; + sstr << "IfcSurfaceStyleShading_" << id; + this->name = sstr.str(); + } SurfaceStyle(const std::string& name) : name(name) {} - SurfaceStyle(int id, const std::string& name) : id(id), name(name) {} + SurfaceStyle(int id, const std::string& name) : id(id) { + std::stringstream sstr; + sstr << id << "_" << name; + this->name = sstr.str(); + } // Not used at this point. In fact, equality testing in the current // architecture can just as easily be accomplished by comparing the @@ -75,21 +85,7 @@ namespace IfcGeom { } } - const std::string Name() const { - if (name && id) { - std::stringstream sstr; - sstr << (*id) << "_" << (*name); - return sstr.str(); - } else if (name) { - return *name; - } else if (id) { - std::stringstream sstr; - sstr << "IfcSurfaceStyleShading_" << (*id); - return sstr.str(); - } else { - return "IfcSurfaceStyleShading"; - } - } + const std::string& Name() const { return *name; } const boost::optional& Diffuse() const { return diffuse; } const boost::optional& Specular() const { return specular; } @@ -101,73 +97,7 @@ namespace IfcGeom { boost::optional& Specularity() { return specularity; } }; - template std::pair get_surface_style(const IfcSchema::IfcRepresentationItem* representation_item) { - IfcSchema::IfcStyledItem::list::ptr styled_items = representation_item->StyledByItem(); - - // Preferably this item-specific logic should not be here, but it easier than somehow associating this information - // with a bare TopoDS_Shape. Perhaps the real solution is to 'upgrade' IfcBooleanResult from a SHAPE to SHAPES in - // IfcRegister.h so that surface style information can be tied to actual implementation of the conversion function. - if (styled_items->Size() == 0 && representation_item->is(IfcSchema::Type::IfcBooleanResult)) { - IfcSchema::IfcBooleanResult* boolean_result = (IfcSchema::IfcBooleanResult*) representation_item; - while (true) { - IfcSchema::IfcRepresentationItem* boolean_op = (IfcSchema::IfcRepresentationItem*) boolean_result->FirstOperand(); - IfcSchema::IfcStyledItem::list::ptr op_styled_items = boolean_op->StyledByItem(); - if (op_styled_items->Size() > 0) { - styled_items = op_styled_items; - break; - } - if (boolean_op->is(IfcSchema::Type::IfcBooleanResult)) { - boolean_result = (IfcSchema::IfcBooleanResult*) boolean_op; - } else { - break; - } - } - } - - for (IfcSchema::IfcStyledItem::list::it jt = styled_items->begin(); jt != styled_items->end(); ++jt) { -#ifdef USE_IFC4 - IfcUtil::IfcAbstractSelect::list::ptr style_assignments = (*jt)->Styles(); - for (IfcUtil::IfcAbstractSelect::list::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) { - if (!(*kt)->is(IfcSchema::Type::IfcPresentationStyleAssignment)) { - continue; - } - IfcSchema::IfcPresentationStyleAssignment* style_assignment = (IfcSchema::IfcPresentationStyleAssignment*) *kt; -#else - IfcSchema::IfcPresentationStyleAssignment::list::ptr style_assignments = (*jt)->Styles(); - for (IfcSchema::IfcPresentationStyleAssignment::list::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) { - IfcSchema::IfcPresentationStyleAssignment* style_assignment = *kt; -#endif - IfcUtil::IfcAbstractSelect::list::ptr styles = style_assignment->Styles(); - for (IfcUtil::IfcAbstractSelect::list::it lt = styles->begin(); lt != styles->end(); ++lt) { - IfcUtil::IfcAbstractSelect* style = *lt; - if (style->is(IfcSchema::Type::IfcSurfaceStyle)) { - IfcSchema::IfcSurfaceStyle* surface_style = (IfcSchema::IfcSurfaceStyle*) style; - if (surface_style->Side() != IfcSchema::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE) { - IfcUtil::IfcAbstractSelect::list::ptr styles_elements = surface_style->Styles(); - for (IfcUtil::IfcAbstractSelect::list::it mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) { - if ((*mt)->is(T::Class())) { - return std::make_pair(surface_style, (T*) *mt); - } - } - } - } - } - } - - // StyledByItem is a SET [0:1] OF IfcStyledItem, so we - // break after encountering the first IfcStyledItem - break; - } - - return std::make_pair(0,0); - } - - const SurfaceStyle* get_style(const IfcSchema::IfcRepresentationItem* representation_item); const SurfaceStyle* get_default_style(const std::string& ifc_type); - - namespace Cache { - void PurgeStyleCache(); - } } #endif \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomRepresentation.cpp b/src/ifcgeom/IfcGeomRepresentation.cpp new file mode 100644 index 0000000000..ad699643c4 --- /dev/null +++ b/src/ifcgeom/IfcGeomRepresentation.cpp @@ -0,0 +1,59 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +#include +#include +#include + +#include +#include + +#include "../ifcgeom/IfcGeom.h" + +#include "IfcGeomRepresentation.h" + +IfcGeom::Representation::Serialization::Serialization(const BRep& brep) + : Representation(brep.settings()) + , _id(brep.getId()) +{ + TopoDS_Compound compound; + BRep_Builder builder; + builder.MakeCompound(compound); + for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++ it ) { + const TopoDS_Shape& s = it->Shape(); + gp_GTrsf trsf = it->Placement(); + if (convert_back_units) { + gp_Trsf scale; + scale.SetScaleFactor(1.0 / settings().unit_magnitude()); + trsf.PreMultiply(scale); + } + bool trsf_valid = false; + gp_Trsf _trsf; + try { + _trsf = trsf.Trsf(); + trsf_valid = true; + } catch (...) {} + const TopoDS_Shape moved_shape = trsf_valid ? s.Moved(_trsf) : + BRepBuilderAPI_GTransform(s,trsf,true).Shape(); + builder.Add(compound,moved_shape); + } + std::stringstream sstream; + BRepTools::Write(compound,sstream); + _brep_data = sstream.str(); +} \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomRepresentation.h b/src/ifcgeom/IfcGeomRepresentation.h new file mode 100644 index 0000000000..1f42ec1968 --- /dev/null +++ b/src/ifcgeom/IfcGeomRepresentation.h @@ -0,0 +1,270 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +#ifndef IFCGEOMREPRESENTATION_H +#define IFCGEOMREPRESENTATION_H + +#include +#include + +#include +#include +#include + +#include + +#include "../ifcgeom/IfcGeomIteratorSettings.h" +#include "../ifcgeom/IfcGeomMaterial.h" + +namespace IfcGeom { + + namespace Representation { + + class Representation { + protected: + const ElementSettings _settings; + public: + explicit Representation(const ElementSettings& settings) : _settings(settings) {} + const ElementSettings& settings() const { return _settings; } + }; + + class BRep : public Representation { + private: + unsigned int id; + const IfcGeom::IfcRepresentationShapeItems shapes; + BRep(const BRep& other); + BRep& operator=(const BRep& other); + public: + BRep(const ElementSettings& settings, unsigned int id, const IfcGeom::IfcRepresentationShapeItems& shapes) + : Representation(settings) + , id(id) + , shapes(shapes) + {} + virtual ~BRep() {} + IfcGeom::IfcRepresentationShapeItems::const_iterator begin() const { return shapes.begin(); } + IfcGeom::IfcRepresentationShapeItems::const_iterator end() const { return shapes.end(); } + const unsigned int& getId() const { return id; } + }; + + class Serialization : public Representation { + private: + int _id; + bool convert_back_units; + std::string _brep_data; + public: + int id() const { return _id; } + const std::string& brep_data() const { return _brep_data; } + Serialization(const BRep& brep); + virtual ~Serialization() {} + private: + Serialization(); + Serialization(const Serialization&); + Serialization& operator=(const Serialization&); + }; + + template + class Triangulation : public Representation { + private: + // A nested pair of floats and a material index to be able to store an XYZ coordinate in a map. + // TODO: Make this a std::tuple when compilers add support for that. + typedef typename std::pair > Coordinate; + typedef typename std::pair VertexKey; + typedef std::map VertexKeyMap; + typedef std::pair Edge; + + int _id; + std::vector

_verts; + std::vector _faces; + std::vector _edges; + std::vector

_normals; + std::vector _material_ids; + std::vector _materials; + VertexKeyMap welds; + + public: + int id() const { return _id; } + const std::vector

& verts() const { return _verts; } + const std::vector& faces() const { return _faces; } + const std::vector& edges() const { return _edges; } + const std::vector

& normals() const { return _normals; } + const std::vector& material_ids() const { return _material_ids; } + const std::vector& materials() const { return _materials; } + Triangulation(const BRep& shape_model) + : Representation(shape_model.settings()) + , _id(shape_model.getId()) + { + for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shape_model.begin(); it != shape_model.end(); ++ it ) { + + int surface_style_id = -1; + if (it->hasStyle()) { + Material adapter(&it->Style()); + std::vector::const_iterator jt = std::find(_materials.begin(), _materials.end(), adapter); + if (jt == _materials.end()) { + surface_style_id = _materials.size(); + _materials.push_back(adapter); + } else { + surface_style_id = jt - _materials.begin(); + } + } + + if (settings().apply_default_materials() && surface_style_id == -1) { + Material material(IfcGeom::get_default_style(settings().element_type())); + std::vector::const_iterator it = std::find(_materials.begin(), _materials.end(), material); + if (it == _materials.end()) { + surface_style_id = _materials.size(); + _materials.push_back(material); + } else { + surface_style_id = it - _materials.begin(); + } + } + + const TopoDS_Shape& s = it->Shape(); + const gp_GTrsf& trsf = it->Placement(); + + // Triangulate the shape + try { + // BRepTools::Clean(s); + BRepMesh::Mesh(s, settings().deflection_tolerance()); + } catch(...) { + + // TODO: Catch outside + // Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape:",ifc_file->EntityById(_id)->entity); + Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape"); + continue; + } + TopExp_Explorer exp; + + // Iterates over the faces of the shape + for ( exp.Init(s,TopAbs_FACE); exp.More(); exp.Next() ) { + TopoDS_Face face = TopoDS::Face(exp.Current()); + TopLoc_Location loc; + Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face,loc); + + if ( ! tri.IsNull() ) { + + // A 3x3 matrix to rotate the vertex normals + const gp_Mat rotation_matrix = trsf.VectorialPart(); + + // Keep track of the number of times an edge is used + // Manifold edges (i.e. edges used twice) are deemed invisible + std::map,int> edgecount; + std::vector > edges_temp; + + const TColgp_Array1OfPnt& nodes = tri->Nodes(); + const TColgp_Array1OfPnt2d& uvs = tri->UVNodes(); + std::vector coords; + BRepGProp_Face prop(face); + std::map dict; + + // Vertex normals are only calculated if vertices are not welded + const bool calculate_normals = !settings().weld_vertices(); + + for( int i = 1; i <= nodes.Length(); ++ i ) { + coords.push_back(nodes(i).Transformed(loc).XYZ()); + trsf.Transforms(*coords.rbegin()); + dict[i] = addVertex(surface_style_id, *coords.rbegin()); + + if ( calculate_normals ) { + const gp_Pnt2d& uv = uvs(i); + gp_Pnt p; + 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) { + normal = gp_Dir(normal_direction.XYZ() * rotation_matrix); + } + _normals.push_back((float)normal.X()); + _normals.push_back((float)normal.Y()); + _normals.push_back((float)normal.Z()); + } + } + + const Poly_Array1OfTriangle& triangles = tri->Triangles(); + for( int i = 1; i <= triangles.Length(); ++ i ) { + int n1,n2,n3; + if ( face.Orientation() == TopAbs_REVERSED ) + triangles(i).Get(n3,n2,n1); + else triangles(i).Get(n1,n2,n3); + + /* An alternative would be to calculate normals based + * on the coordinates of the mesh vertices */ + /* + const gp_XYZ pt1 = coords[n1-1]; + const gp_XYZ pt2 = coords[n2-1]; + const gp_XYZ pt3 = coords[n3-1]; + const gp_XYZ v1 = pt2-pt1; + const gp_XYZ v2 = pt3-pt2; + gp_Dir normal = gp_Dir(v1^v2); + _normals.push_back((float)normal.X()); + _normals.push_back((float)normal.Y()); + _normals.push_back((float)normal.Z()); + */ + + _faces.push_back(dict[n1]); + _faces.push_back(dict[n2]); + _faces.push_back(dict[n3]); + + _material_ids.push_back(surface_style_id); + + addEdge(n1,n2,edgecount,edges_temp); + addEdge(n2,n3,edgecount,edges_temp); + addEdge(n3,n1,edgecount,edges_temp); + } + for ( std::vector >::const_iterator it = edges_temp.begin(); it != edges_temp.end(); ++it ) { + _edges.push_back(edgecount[*it]==1); + } + } + } + } + } + virtual ~Triangulation() {} + private: + // Welds vertices that belong to different faces + int addVertex(int material_index, const gp_XYZ& p) { + const P X = static_cast

(settings().convert_back_units() ? (p.X() / settings().unit_magnitude()) : p.X()); + const P Y = static_cast

(settings().convert_back_units() ? (p.Y() / settings().unit_magnitude()) : p.Y()); + const P Z = static_cast

(settings().convert_back_units() ? (p.Z() / settings().unit_magnitude()) : p.Z()); + int i = (int) _verts.size() / 3; + if (settings().weld_vertices()) { + const VertexKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z))); + VertexKeyMap::const_iterator it = welds.find(key); + if ( it != welds.end() ) return it->second; + i = (int) welds.size(); + welds[key] = i; + } + _verts.push_back(X); + _verts.push_back(Y); + _verts.push_back(Z); + return i; + } + inline void addEdge(int n1, int n2, std::map,int>& edgecount, std::vector >& edges_temp) { + const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) ); + if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1; + else edgecount[e] ++; + edges_temp.push_back(e); + } + Triangulation(); + Triangulation(const Triangulation&); + Triangulation& operator=(const Triangulation&); + }; + + } +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index 4e3ab6a9f9..ad2826f45e 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -95,13 +95,13 @@ #include "../ifcgeom/IfcGeom.h" -bool IfcGeom::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& shape) { TopoDS_Shape face; - if ( ! IfcGeom::convert_face(l->SweptArea(),face) ) return false; + if ( !convert_face(l->SweptArea(),face) ) return false; - const double height = l->Depth() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double height = l->Depth() * getValue(GV_LENGTH_UNIT); gp_Trsf trsf; - IfcGeom::convert(l->Position(),trsf); + IfcGeom::Kernel::convert(l->Position(),trsf); gp_Dir dir; convert(l->ExtrudedDirection(),dir); @@ -138,17 +138,17 @@ bool IfcGeom::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& sh return ! shape.IsNull(); } -bool IfcGeom::convert(const IfcSchema::IfcSurfaceOfLinearExtrusion* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfLinearExtrusion* l, TopoDS_Shape& shape) { TopoDS_Wire wire; - if ( !IfcGeom::convert_wire(l->SweptCurve(), wire) ) { + if ( !convert_wire(l->SweptCurve(), wire) ) { TopoDS_Face face; - if ( !IfcGeom::convert_face(l->SweptCurve(),face) ) return false; + if ( !convert_face(l->SweptCurve(),face) ) return false; TopExp_Explorer exp(face, TopAbs_WIRE); wire = TopoDS::Wire(exp.Current()); } - const double height = l->Depth() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double height = l->Depth() * getValue(GV_LENGTH_UNIT); gp_Trsf trsf; - IfcGeom::convert(l->Position(),trsf); + IfcGeom::Kernel::convert(l->Position(),trsf); gp_Dir dir; convert(l->ExtrudedDirection(),dir); @@ -158,20 +158,20 @@ bool IfcGeom::convert(const IfcSchema::IfcSurfaceOfLinearExtrusion* l, TopoDS_Sh return !shape.IsNull(); } -bool IfcGeom::convert(const IfcSchema::IfcSurfaceOfRevolution* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfRevolution* l, TopoDS_Shape& shape) { TopoDS_Wire wire; - if ( !IfcGeom::convert_wire(l->SweptCurve(), wire) ) { + if ( !convert_wire(l->SweptCurve(), wire) ) { TopoDS_Face face; - if ( !IfcGeom::convert_face(l->SweptCurve(),face) ) return false; + if ( !convert_face(l->SweptCurve(),face) ) return false; TopExp_Explorer exp(face, TopAbs_WIRE); wire = TopoDS::Wire(exp.Current()); } gp_Ax1 ax1; - IfcGeom::convert(l->AxisPosition(), ax1); + IfcGeom::Kernel::convert(l->AxisPosition(), ax1); gp_Trsf trsf; - IfcGeom::convert(l->Position(),trsf); + IfcGeom::Kernel::convert(l->Position(),trsf); shape = BRepPrimAPI_MakeRevol(wire, ax1); @@ -179,17 +179,17 @@ bool IfcGeom::convert(const IfcSchema::IfcSurfaceOfRevolution* l, TopoDS_Shape& return !shape.IsNull(); } -bool IfcGeom::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_Shape& shape) { - const double ang = l->Angle() * IfcGeom::GetValue(GV_PLANEANGLE_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_Shape& shape) { + const double ang = l->Angle() * getValue(GV_PLANEANGLE_UNIT); TopoDS_Face face; - if ( ! IfcGeom::convert_face(l->SweptArea(),face) ) return false; + if ( ! convert_face(l->SweptArea(),face) ) return false; gp_Ax1 ax1; - IfcGeom::convert(l->Axis(), ax1); + IfcGeom::Kernel::convert(l->Axis(), ax1); gp_Trsf trsf; - IfcGeom::convert(l->Position(),trsf); + IfcGeom::Kernel::convert(l->Position(),trsf); if (ang >= M_PI * 2. - ALMOST_ZERO) { shape = BRepPrimAPI_MakeRevol(face, ax1); @@ -201,10 +201,10 @@ bool IfcGeom::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_Shape& sh return !shape.IsNull(); } -bool IfcGeom::convert(const IfcSchema::IfcFacetedBrep* l, IfcRepresentationShapeItems& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcFacetedBrep* l, IfcRepresentationShapeItems& shape) { TopoDS_Shape s; const SurfaceStyle* collective_style = get_style(l); - if (IfcGeom::convert_shape(l->Outer(),s) ) { + if (convert_shape(l->Outer(),s) ) { const SurfaceStyle* indiv_style = get_style(l->Outer()); shape.push_back(IfcRepresentationShapeItem(s, indiv_style ? indiv_style : collective_style)); return true; @@ -212,37 +212,37 @@ bool IfcGeom::convert(const IfcSchema::IfcFacetedBrep* l, IfcRepresentationShape return false; } -bool IfcGeom::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) { IfcSchema::IfcConnectedFaceSet::list::ptr facesets = l->FbsmFaces(); const SurfaceStyle* collective_style = get_style(l); for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) { TopoDS_Shape s; const SurfaceStyle* shell_style = get_style(*it); - if (IfcGeom::convert_shape(*it,s)) { + if (convert_shape(*it,s)) { shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style)); } } return true; } -bool IfcGeom::convert(const IfcSchema::IfcHalfSpaceSolid* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, TopoDS_Shape& shape) { IfcSchema::IfcSurface* surface = l->BaseSurface(); if ( ! surface->is(IfcSchema::Type::IfcPlane) ) { Logger::Message(Logger::LOG_ERROR, "Unsupported BaseSurface:", surface->entity); return false; } gp_Pln pln; - IfcGeom::convert((IfcSchema::IfcPlane*)surface,pln); + IfcGeom::Kernel::convert((IfcSchema::IfcPlane*)surface,pln); const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction()); shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid(); return true; } -bool IfcGeom::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, TopoDS_Shape& shape) { TopoDS_Shape halfspace; - if ( ! IfcGeom::convert((IfcSchema::IfcHalfSpaceSolid*)l,halfspace) ) return false; + if ( ! IfcGeom::Kernel::convert((IfcSchema::IfcHalfSpaceSolid*)l,halfspace) ) return false; TopoDS_Wire wire; - if ( ! IfcGeom::convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false; + if ( ! convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false; gp_Trsf trsf; convert(l->Position(),trsf); TopoDS_Shape prism = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,200)); @@ -252,7 +252,7 @@ bool IfcGeom::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, TopoDS_S return true; } -bool IfcGeom::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) { IfcUtil::IfcAbstractSelect::list::ptr shells = l->SbsmBoundary(); const SurfaceStyle* collective_style = get_style(l); for( IfcUtil::IfcAbstractSelect::list::it it = shells->begin(); it != shells->end(); ++ it ) { @@ -261,14 +261,14 @@ bool IfcGeom::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresen if ((*it)->is(IfcSchema::Type::IfcRepresentationItem)) { shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it); } - if (IfcGeom::convert_shape(*it,s)) { + if (convert_shape(*it,s)) { shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style)); } } return true; } -bool IfcGeom::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) { TopoDS_Shape s1, s2; IfcRepresentationShapeItems items1, items2; TopoDS_Wire boundary_wire; @@ -281,7 +281,7 @@ bool IfcGeom::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) return false; } } else { - if ( ! IfcGeom::convert_shape(operand1,s1) ) { + if ( ! convert_shape(operand1,s1) ) { return false; } } @@ -294,7 +294,7 @@ bool IfcGeom::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) if ( is_shape_collection(operand2) ) { shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true); } else { - shape2_processed = IfcGeom::convert_shape(operand2,s2); + shape2_processed = convert_shape(operand2,s2); } if (!shape2_processed) { @@ -381,23 +381,23 @@ bool IfcGeom::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) } } -bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& shape) { IfcSchema::IfcFace::list::ptr faces = l->CfsFaces(); bool facesAdded = false; const unsigned int num_faces = faces->Size(); bool valid_shell = false; - if ( num_faces < GetValue(GV_MAX_FACES_TO_SEW) ) { + if ( num_faces < getValue(GV_MAX_FACES_TO_SEW) ) { BRepOffsetAPI_Sewing builder; - builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); - builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); - builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetMaxTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetMinTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) { TopoDS_Face face; bool converted_face = false; try { - converted_face = IfcGeom::convert_face(*it,face); + converted_face = convert_face(*it,face); } catch (...) {} - if ( converted_face && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) { + if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) { builder.Add(face); facesAdded = true; } else { @@ -413,7 +413,7 @@ bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& sha if (valid_shell) { try { ShapeFix_Solid solid; - solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); + solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE)); TopoDS_Solid solid_shape = solid.SolidFromShell(TopoDS::Shell(shape)); if (!solid_shape.IsNull()) { try { @@ -434,9 +434,9 @@ bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& sha TopoDS_Face face; bool converted_face = false; try { - converted_face = IfcGeom::convert_face(*it,face); + converted_face = convert_face(*it,face); } catch (...) {} - if ( converted_face && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) { + if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) { builder.Add(compound,face); facesAdded = true; } else { @@ -449,53 +449,53 @@ bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& sha return true; } -bool IfcGeom::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentationShapeItems& shapes) { gp_GTrsf gtrsf; IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget(); if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) { - IfcGeom::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); + IfcGeom::Kernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) { Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); return false; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) { gp_Trsf trsf; - IfcGeom::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); + IfcGeom::Kernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); gtrsf = trsf; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { gp_Trsf2d trsf_2d; - IfcGeom::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,trsf_2d); + IfcGeom::Kernel::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,trsf_2d); gtrsf = (gp_Trsf) trsf_2d; } IfcSchema::IfcRepresentationMap* map = l->MappingSource(); IfcSchema::IfcAxis2Placement placement = map->MappingOrigin(); gp_Trsf trsf; if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { - IfcGeom::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); + IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); } else { gp_Trsf2d trsf_2d; - IfcGeom::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d); + IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d); trsf = trsf_2d; } gtrsf.Multiply(trsf); const unsigned int previous_size = (const unsigned int) shapes.size(); - bool b = IfcGeom::convert_shapes(map->MappedRepresentation(),shapes); + bool b = convert_shapes(map->MappedRepresentation(),shapes); for ( unsigned int i = previous_size; i < shapes.size(); ++ i ) { shapes[i].append(gtrsf); } return b; } -bool IfcGeom::convert(const IfcSchema::IfcShapeRepresentation* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcShapeRepresentation* l, IfcRepresentationShapeItems& shapes) { IfcSchema::IfcRepresentationItem::list::ptr items = l->Items(); bool part_succes = false; if ( items->Size() ) { for ( IfcSchema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++ it ) { IfcSchema::IfcRepresentationItem* representation_item = *it; - if ( IfcGeom::is_shape_collection(representation_item) ) { - part_succes |= IfcGeom::convert_shapes(*it, shapes); + if ( is_shape_collection(representation_item) ) { + part_succes |= convert_shapes(*it, shapes); } else { TopoDS_Shape s; - if (IfcGeom::convert_shape(representation_item,s)) { + if (convert_shape(representation_item,s)) { shapes.push_back(IfcRepresentationShapeItem(s, get_style(representation_item))); part_succes |= true; } @@ -505,40 +505,42 @@ bool IfcGeom::convert(const IfcSchema::IfcShapeRepresentation* l, IfcRepresentat return part_succes; } -bool IfcGeom::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresentationShapeItems& shapes) { IfcUtil::IfcAbstractSelect::list::ptr elements = l->Elements(); if ( !elements->Size() ) return false; + bool part_succes = false; const IfcGeom::SurfaceStyle* parent_style = get_style(l); for ( IfcUtil::IfcAbstractSelect::list::it it = elements->begin(); it != elements->end(); ++ it ) { IfcSchema::IfcGeometricSetSelect element = *it; if (element->is(IfcSchema::Type::IfcSurface)) { IfcSchema::IfcSurface* surface = (IfcSchema::IfcSurface*) element; TopoDS_Shape s; - if (IfcGeom::convert_shape(surface, s)) { + if (convert_shape(surface, s)) { + part_succes = true; const IfcGeom::SurfaceStyle* style = get_style(surface); shapes.push_back(IfcRepresentationShapeItem(s, style ? style : parent_style)); } } } - return true; + return part_succes; } -bool IfcGeom::convert(const IfcSchema::IfcBlock* l, TopoDS_Shape& shape) { - const double dx = l->XLength() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double dy = l->YLength() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double dz = l->ZLength() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcBlock* l, TopoDS_Shape& shape) { + const double dx = l->XLength() * getValue(GV_LENGTH_UNIT); + const double dy = l->YLength() * getValue(GV_LENGTH_UNIT); + const double dz = l->ZLength() * getValue(GV_LENGTH_UNIT); BRepPrimAPI_MakeBox builder(dx, dy, dz); gp_Trsf trsf; - IfcGeom::convert(l->Position(),trsf); + IfcGeom::Kernel::convert(l->Position(),trsf); shape = builder.Solid().Moved(trsf); return true; } -bool IfcGeom::convert(const IfcSchema::IfcRectangularPyramid* l, TopoDS_Shape& shape) { - const double dx = l->XLength() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double dy = l->YLength() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double dz = l->Height() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularPyramid* l, TopoDS_Shape& shape) { + const double dx = l->XLength() * getValue(GV_LENGTH_UNIT); + const double dy = l->YLength() * getValue(GV_LENGTH_UNIT); + const double dz = l->Height() * getValue(GV_LENGTH_UNIT); BRepPrimAPI_MakeWedge builder(dx, dz, dy, dx / 2., dy / 2., dx / 2., dy / 2.); @@ -547,56 +549,56 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangularPyramid* l, TopoDS_Shape& s 0, 0, 1, 0, 0, 1, 0, 0, Precision::Confusion(), Precision::Confusion()); - IfcGeom::convert(l->Position(), trsf1); + IfcGeom::Kernel::convert(l->Position(), trsf1); shape = BRepBuilderAPI_Transform(builder.Solid(), trsf1 * trsf2); return true; } -bool IfcGeom::convert(const IfcSchema::IfcRightCircularCylinder* l, TopoDS_Shape& shape) { - const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double h = l->Height() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcRightCircularCylinder* l, TopoDS_Shape& shape) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); + const double h = l->Height() * getValue(GV_LENGTH_UNIT); BRepPrimAPI_MakeCylinder builder(r, h); gp_Trsf trsf; - IfcGeom::convert(l->Position(),trsf); + IfcGeom::Kernel::convert(l->Position(),trsf); shape = builder.Solid().Moved(trsf); return true; } -bool IfcGeom::convert(const IfcSchema::IfcRightCircularCone* l, TopoDS_Shape& shape) { - const double r = l->BottomRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); - const double h = l->Height() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcRightCircularCone* l, TopoDS_Shape& shape) { + const double r = l->BottomRadius() * getValue(GV_LENGTH_UNIT); + const double h = l->Height() * getValue(GV_LENGTH_UNIT); BRepPrimAPI_MakeCone builder(r, 0., h); gp_Trsf trsf; - IfcGeom::convert(l->Position(),trsf); + IfcGeom::Kernel::convert(l->Position(),trsf); shape = builder.Solid().Moved(trsf); return true; } -bool IfcGeom::convert(const IfcSchema::IfcSphere* l, TopoDS_Shape& shape) { - const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcSphere* l, TopoDS_Shape& shape) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); BRepPrimAPI_MakeSphere builder(r); gp_Trsf trsf; - IfcGeom::convert(l->Position(),trsf); + IfcGeom::Kernel::convert(l->Position(),trsf); shape = builder.Solid().Moved(trsf); return true; } -bool IfcGeom::convert(const IfcSchema::IfcCsgSolid* l, TopoDS_Shape& shape) { - return IfcGeom::convert_shape(l->TreeRootExpression(), shape); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCsgSolid* l, TopoDS_Shape& shape) { + return convert_shape(l->TreeRootExpression(), shape); } -bool IfcGeom::convert(const IfcSchema::IfcCurveBoundedPlane* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCurveBoundedPlane* l, TopoDS_Shape& face) { gp_Pln pln; - IfcGeom::convert(l->BasisSurface(), pln); + IfcGeom::Kernel::convert(l->BasisSurface(), pln); gp_Trsf trsf; trsf.SetTransformation(pln.Position()); TopoDS_Wire outer; - IfcGeom::convert_wire(l->OuterBoundary(), outer); + convert_wire(l->OuterBoundary(), outer); BRepBuilderAPI_MakeFace mf (outer); mf.Add(outer); @@ -605,7 +607,7 @@ bool IfcGeom::convert(const IfcSchema::IfcCurveBoundedPlane* l, TopoDS_Shape& fa for (IfcSchema::IfcCurve::list::it it = inner->begin(); it != inner->end(); ++it) { TopoDS_Wire inner; - IfcGeom::convert_wire(*it, inner); + convert_wire(*it, inner); mf.Add(inner); } @@ -617,13 +619,13 @@ bool IfcGeom::convert(const IfcSchema::IfcCurveBoundedPlane* l, TopoDS_Shape& fa return true; } -bool IfcGeom::convert(const IfcSchema::IfcRectangularTrimmedSurface* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularTrimmedSurface* l, TopoDS_Shape& face) { if (!l->BasisSurface()->is(IfcSchema::Type::IfcPlane)) { Logger::Message(Logger::LOG_ERROR, "Unsupported BasisSurface:", l->BasisSurface()->entity); return false; } gp_Pln pln; - IfcGeom::convert((IfcSchema::IfcPlane*) l->BasisSurface(), pln); + IfcGeom::Kernel::convert((IfcSchema::IfcPlane*) l->BasisSurface(), pln); BRepBuilderAPI_MakeFace mf(pln, l->U1(), l->U2(), l->V1(), l->V2()); @@ -632,7 +634,7 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangularTrimmedSurface* l, TopoDS_S return true; } -bool IfcGeom::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_Shape& shape) { gp_Trsf directrix, position; TopoDS_Shape face; TopoDS_Wire wire, section; @@ -642,9 +644,9 @@ bool IfcGeom::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_ return false; } - if (!IfcGeom::convert(l->Position(), position) || - !IfcGeom::convert_face(l->SweptArea(), face) || - !IfcGeom::convert_wire(l->Directrix(), wire) ) { + if (!IfcGeom::Kernel::convert(l->Position(), position) || + !convert_face(l->SweptArea(), face) || + !convert_wire(l->Directrix(), wire) ) { return false; } @@ -652,7 +654,7 @@ bool IfcGeom::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_ gp_Pnt directrix_origin; gp_Vec directrix_tangent; bool directrix_on_plane = true; - IfcGeom::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln); + IfcGeom::Kernel::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln); // As per Informal propositions 2: The Directrix shall lie on the ReferenceSurface. // This is not always the case with the test files in the repository. I am not sure @@ -705,12 +707,12 @@ bool IfcGeom::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_ return true; } -bool IfcGeom::convert(const IfcSchema::IfcSweptDiskSolid* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcSweptDiskSolid* l, TopoDS_Shape& shape) { TopoDS_Wire wire, section1, section2; const bool hasInnerRadius = l->hasInnerRadius(); - if (!IfcGeom::convert_wire(l->Directrix(), wire)) { + if (!convert_wire(l->Directrix(), wire)) { return false; } @@ -726,12 +728,12 @@ bool IfcGeom::convert(const IfcSchema::IfcSweptDiskSolid* l, TopoDS_Shape& shape directrix = gp_Ax2(directrix_origin, directrix_tangent); } - const double r1 = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double r1 = l->Radius() * getValue(GV_LENGTH_UNIT); Handle(Geom_Circle) circle = new Geom_Circle(directrix, r1); section1 = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(circle)); if (hasInnerRadius) { - const double r2 = l->InnerRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT); + const double r2 = l->InnerRadius() * getValue(GV_LENGTH_UNIT); Handle(Geom_Circle) circle = new Geom_Circle(directrix, r2); section2 = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(circle)); } @@ -782,15 +784,15 @@ bool IfcGeom::convert(const IfcSchema::IfcSweptDiskSolid* l, TopoDS_Shape& shape #ifdef USE_IFC4 -bool IfcGeom::convert(const IfcSchema::IfcCylindricalSurface* l, TopoDS_Shape& face) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCylindricalSurface* l, TopoDS_Shape& face) { gp_Trsf trsf; - IfcGeom::convert(l->Position(),trsf); + IfcGeom::Kernel::convert(l->Position(),trsf); - face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius()), GetValue(GV_PRECISION)).Face().Moved(trsf); + face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius()), getValue(GV_PRECISION)).Face().Moved(trsf); return true; } -bool IfcGeom::convert(const IfcSchema::IfcAdvancedBrep* l, TopoDS_Shape& shape) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcAdvancedBrep* l, TopoDS_Shape& shape) { return convert(l->Outer(), shape); } diff --git a/src/ifcgeom/IfcGeomUtils.cpp b/src/ifcgeom/IfcGeomUtils.cpp new file mode 100644 index 0000000000..871ba93a15 --- /dev/null +++ b/src/ifcgeom/IfcGeomUtils.cpp @@ -0,0 +1,42 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +#include "../ifcparse/IfcParse.h" + +#include "IfcGeomUtils.h" + +double IfcGeom::Utils::UnitPrefixToValue( IfcSchema::IfcSIPrefix::IfcSIPrefix v ) { + if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_EXA ) return 1.e18; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PETA ) return 1.e15; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_TERA ) return 1.e12; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_GIGA ) return 1.e9; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MEGA ) return 1.e6; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_KILO ) return 1.e3; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_HECTO ) return 1.e2; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_DECA ) return 1.; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_DECI ) return 1.e-1; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_CENTI ) return 1.e-2; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MILLI ) return 1.e-3; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MICRO ) return 1.e-6; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_NANO ) return 1.e-9; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PICO ) return 1.e-12; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_FEMTO ) return 1.e-15; + else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_ATTO ) return 1.e-18; + else return 1.f; +} \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomUtils.h b/src/ifcgeom/IfcGeomUtils.h new file mode 100644 index 0000000000..93726fd3de --- /dev/null +++ b/src/ifcgeom/IfcGeomUtils.h @@ -0,0 +1,30 @@ +/******************************************************************************** + * * + * This file is part of IfcOpenShell. * + * * + * IfcOpenShell is free software: you can redistribute it and/or modify * + * it under the terms of the Lesser GNU General Public License as published by * + * the Free Software Foundation, either version 3.0 of the License, or * + * (at your option) any later version. * + * * + * IfcOpenShell is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * Lesser GNU General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see . * + * * + ********************************************************************************/ + +#ifndef IFCGEOMUTILS_H +#define IFCGEOMUTILS_H + +namespace IfcGeom { + + namespace Utils { + double UnitPrefixToValue(IfcSchema::IfcSIPrefix::IfcSIPrefix v); + } +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index 0e3ca1a3e0..db9c1428b9 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -83,12 +83,12 @@ #include "../ifcgeom/IfcGeom.h" -bool IfcGeom::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) { - if ( IfcGeom::GetValue(GV_PLANEANGLE_UNIT)<0 ) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) { + if ( getValue(GV_PLANEANGLE_UNIT)<0 ) { Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity); // Temporarily pretend we do have unit information - IfcGeom::SetValue(GV_PLANEANGLE_UNIT,1.0); + setValue(GV_PLANEANGLE_UNIT,1.0); bool succes_radians = false; bool succes_degrees = false; @@ -98,17 +98,17 @@ bool IfcGeom::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) // First try radians TopoDS_Wire wire_radians, wire_degrees; try { - succes_radians = IfcGeom::convert(l,wire_radians); + succes_radians = IfcGeom::Kernel::convert(l,wire_radians); } catch (...) {} // Now try degrees - IfcGeom::SetValue(GV_PLANEANGLE_UNIT,0.0174532925199433); + setValue(GV_PLANEANGLE_UNIT,0.0174532925199433); try { - succes_degrees = IfcGeom::convert(l,wire_degrees); + succes_degrees = IfcGeom::Kernel::convert(l,wire_degrees); } catch (...) {} // Restore to unknown unit state - IfcGeom::SetValue(GV_PLANEANGLE_UNIT,-1.0); + setValue(GV_PLANEANGLE_UNIT,-1.0); if ( succes_degrees && ! succes_radians ) { use_degrees = true; @@ -145,13 +145,13 @@ bool IfcGeom::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) for( IfcSchema::IfcCompositeCurveSegment::list::it it = segments->begin(); it != segments->end(); ++ it ) { IfcSchema::IfcCurve* curve = (*it)->ParentCurve(); TopoDS_Wire wire2; - if ( ! IfcGeom::convert_wire(curve,wire2) ) { + if ( !convert_wire(curve,wire2) ) { Logger::Message(Logger::LOG_ERROR,"Failed to convert curve:",curve->entity); continue; } if ( ! (*it)->SameSense() ) wire2.Reverse(); ShapeFix_ShapeTolerance FTol; - FTol.SetTolerance(wire2, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_WIRE); + FTol.SetTolerance(wire2, getValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_WIRE); /*if ( it != segments->begin() ) { TopExp_Explorer exp (wire2,TopAbs_VERTEX); const TopoDS_Vertex& first_vertex = TopoDS::Vertex(exp.Current()); @@ -173,12 +173,12 @@ bool IfcGeom::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) return true; } -bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) { IfcSchema::IfcCurve* basis_curve = l->BasisCurve(); bool isConic = basis_curve->is(IfcSchema::Type::IfcConic); - double parameterFactor = isConic ? IfcGeom::GetValue(GV_PLANEANGLE_UNIT) : IfcGeom::GetValue(GV_LENGTH_UNIT); + double parameterFactor = isConic ? getValue(GV_PLANEANGLE_UNIT) : getValue(GV_LENGTH_UNIT); Handle(Geom_Curve) curve; - if ( ! IfcGeom::convert_curve(basis_curve,curve) ) return false; + if ( !convert_curve(basis_curve,curve) ) return false; bool trim_cartesian = l->MasterRepresentation() == IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN; IfcUtil::IfcAbstractSelect::list::ptr trims1 = l->Trim1(); IfcUtil::IfcAbstractSelect::list::ptr trims2 = l->Trim2(); @@ -193,7 +193,7 @@ bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) { for ( IfcUtil::IfcAbstractSelect::list::it it = trims1->begin(); it != trims1->end(); it ++ ) { IfcUtil::IfcAbstractSelect* i = *it; if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) { - IfcGeom::convert((IfcSchema::IfcCartesianPoint*)i, pnts[sense_agreement] ); + IfcGeom::Kernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[sense_agreement] ); has_pnts[sense_agreement] = true; } else if ( i->is(IfcSchema::Type::IfcParameterValue) ) { const double value = *((IfcUtil::IfcArgumentSelect*)i)->wrappedValue(); @@ -204,7 +204,7 @@ bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) { for ( IfcUtil::IfcAbstractSelect::list::it it = trims2->begin(); it != trims2->end(); it ++ ) { IfcUtil::IfcAbstractSelect* i = *it; if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) { - IfcGeom::convert((IfcSchema::IfcCartesianPoint*)i, pnts[1-sense_agreement] ); + IfcGeom::Kernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[1-sense_agreement] ); has_pnts[1-sense_agreement] = true; } else if ( i->is(IfcSchema::Type::IfcParameterValue) ) { const double value = *((IfcUtil::IfcArgumentSelect*)i)->wrappedValue(); @@ -215,15 +215,15 @@ bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) { trim_cartesian &= has_pnts[0] && has_pnts[1]; bool trim_cartesian_failed = !trim_cartesian; if ( trim_cartesian ) { - if ( pnts[0].Distance(pnts[1]) < GetValue(GV_WIRE_CREATION_TOLERANCE) ) { + if ( pnts[0].Distance(pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE) ) { Logger::Message(Logger::LOG_WARNING,"Skipping segment with length below tolerance level:",l->entity); return false; } ShapeFix_ShapeTolerance FTol; TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(pnts[0]); TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(pnts[1]); - FTol.SetTolerance(v1, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX); - FTol.SetTolerance(v2, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX); + FTol.SetTolerance(v1, getValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX); + FTol.SetTolerance(v2, getValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX); BRepBuilderAPI_MakeEdge e (curve,v1,v2); if ( ! e.IsDone() ) { BRepBuilderAPI_EdgeError err = e.Error(); @@ -247,8 +247,8 @@ bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) { } if ( basis_curve->is(IfcSchema::Type::IfcEllipse) ) { IfcSchema::IfcEllipse* ellipse = static_cast(basis_curve); - double x = ellipse->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT); - double y = ellipse->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT); + double x = ellipse->SemiAxis1() * getValue(GV_LENGTH_UNIT); + double y = ellipse->SemiAxis2() * getValue(GV_LENGTH_UNIT); const bool rotated = y > x; if (rotated) { flts[0] -= M_PI / 2.; @@ -272,14 +272,14 @@ bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) { } } -bool IfcGeom::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& result) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& result) { IfcSchema::IfcCartesianPoint::list::ptr points = l->Points(); // Parse and store the points in a sequence TColgp_SequenceOfPnt polygon; for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) { gp_Pnt pnt; - IfcGeom::convert(*it, pnt); + IfcGeom::Kernel::convert(*it, pnt); polygon.Append(pnt); } @@ -295,14 +295,14 @@ bool IfcGeom::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& result) { return true; } -bool IfcGeom::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& result) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& result) { IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon(); // Parse and store the points in a sequence TColgp_SequenceOfPnt polygon; for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) { gp_Pnt pnt; - IfcGeom::convert(*it, pnt); + IfcGeom::Kernel::convert(*it, pnt); polygon.Append(pnt); } @@ -337,11 +337,11 @@ bool IfcGeom::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& result) { return true; } -bool IfcGeom::convert(const IfcSchema::IfcArbitraryOpenProfileDef* l, TopoDS_Wire& result) { - return IfcGeom::convert_wire(l->Curve(), result); +bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryOpenProfileDef* l, TopoDS_Wire& result) { + return convert_wire(l->Curve(), result); } -bool IfcGeom::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& result) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& result) { IfcSchema::IfcPoint* pnt1 = ((IfcSchema::IfcVertexPoint*) l->EdgeStart())->VertexGeometry(); IfcSchema::IfcPoint* pnt2 = ((IfcSchema::IfcVertexPoint*) l->EdgeEnd())->VertexGeometry(); if (!pnt1->is(IfcSchema::Type::IfcCartesianPoint) || !pnt2->is(IfcSchema::Type::IfcCartesianPoint)) { @@ -350,8 +350,8 @@ bool IfcGeom::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& result) { } gp_Pnt p1, p2; - if (!IfcGeom::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) || - !IfcGeom::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2)) + if (!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) || + !IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2)) { return false; } @@ -366,11 +366,11 @@ bool IfcGeom::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& result) { // of the IfcEdgeCurve. const bool is_bounded = l->EdgeGeometry()->is(IfcSchema::Type::IfcBoundedCurve); - if (!is_bounded && IfcGeom::convert_curve(l->EdgeGeometry(), crv)) { + if (!is_bounded && convert_curve(l->EdgeGeometry(), crv)) { mw.Add(BRepBuilderAPI_MakeEdge(crv, p1, p2)); result = mw; return true; - } else if (is_bounded && IfcGeom::convert_wire(l->EdgeGeometry(), result)) { + } else if (is_bounded && convert_wire(l->EdgeGeometry(), result)) { if (!l->SameSense()) std::swap(pnt1, pnt2); TopExp_Explorer exp(result, TopAbs_EDGE); bool first = true; @@ -402,7 +402,7 @@ bool IfcGeom::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& result) { } } -bool IfcGeom::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& result) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& result) { IfcSchema::IfcOrientedEdge::list::ptr li = l->EdgeList(); BRepBuilderAPI_MakeWire mw; for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) { @@ -416,8 +416,8 @@ bool IfcGeom::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& result) { } gp_Pnt p1, p2; - if (!IfcGeom::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) || - !IfcGeom::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2)) + if (!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) || + !IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2)) { return false; } diff --git a/src/ifcgeom/IfcRegister.cpp b/src/ifcgeom/IfcRegister.cpp index 8452568227..9b58176120 100644 --- a/src/ifcgeom/IfcRegister.cpp +++ b/src/ifcgeom/IfcRegister.cpp @@ -19,58 +19,54 @@ #include "IfcGeom.h" -namespace IfcGeom { - namespace Cache { - std::map Shape; - void PurgeShapeCache() { - Shape.clear(); - } - } -} - using namespace IfcSchema; using namespace IfcUtil; -bool IfcGeom::convert_shapes(const IfcBaseClass* l, IfcRepresentationShapeItems& r) { +bool IfcGeom::Kernel::convert_shapes(const IfcBaseClass* l, IfcRepresentationShapeItems& r) { #include "IfcRegisterConvertShapes.h" Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); return false; } -bool IfcGeom::is_shape_collection(const IfcBaseClass* l) { + +bool IfcGeom::Kernel::is_shape_collection(const IfcBaseClass* l) { #include "IfcRegisterIsShapeCollection.h" return false; } -bool IfcGeom::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) { + +bool IfcGeom::Kernel::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) { const unsigned int id = l->entity->id(); bool success = false; bool processed = false; - std::map::const_iterator it = Cache::Shape.find(id); - if ( it != Cache::Shape.end() ) { r = it->second; return true; } + std::map::const_iterator it = cache.Shape.find(id); + if ( it != cache.Shape.end() ) { r = it->second; return true; } #include "IfcRegisterConvertShape.h" if ( processed ) { - const double precision = IfcGeom::GetValue(GV_PRECISION); - IfcGeom::apply_tolerance(r, precision); - Cache::Shape[id] = r; + const double precision = getValue(GV_PRECISION); + apply_tolerance(r, precision); + cache.Shape[id] = r; } else { Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); } return success; } -bool IfcGeom::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) { + +bool IfcGeom::Kernel::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) { #include "IfcRegisterConvertWire.h" Handle(Geom_Curve) curve; - if (IfcGeom::convert_curve(l, curve)) { - return IfcGeom::convert_curve_to_wire(curve, r); + if (IfcGeom::Kernel::convert_curve(l, curve)) { + return IfcGeom::Kernel::convert_curve_to_wire(curve, r); } Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); return false; } -bool IfcGeom::convert_face(const IfcBaseClass* l, TopoDS_Shape& r) { + +bool IfcGeom::Kernel::convert_face(const IfcBaseClass* l, TopoDS_Shape& r) { #include "IfcRegisterConvertFace.h" Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); return false; } -bool IfcGeom::convert_curve(const IfcBaseClass* l, Handle(Geom_Curve)& r) { + +bool IfcGeom::Kernel::convert_curve(const IfcBaseClass* l, Handle(Geom_Curve)& r) { #include "IfcRegisterConvertCurve.h" Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); return false; diff --git a/src/ifcgeom/IfcRegister.h b/src/ifcgeom/IfcRegister.h index 76eb966269..15f8fe0d23 100644 --- a/src/ifcgeom/IfcRegister.h +++ b/src/ifcgeom/IfcRegister.h @@ -41,8 +41,6 @@ #include "../ifcparse/IfcUtil.h" #include "../ifcparse/IfcParse.h" -using namespace IfcSchema; - SHAPES(IfcShellBasedSurfaceModel); SHAPES(IfcFaceBasedSurfaceModel); SHAPES(IfcShapeRepresentation); diff --git a/src/ifcgeom/IfcRegisterConvertShapes.h b/src/ifcgeom/IfcRegisterConvertShapes.h index 962cccb203..9da7ff1263 100644 --- a/src/ifcgeom/IfcRegisterConvertShapes.h +++ b/src/ifcgeom/IfcRegisterConvertShapes.h @@ -2,7 +2,7 @@ #define SHAPES(T) \ if ( l->is(T::Class()) ) { \ try { \ - return IfcGeom::convert((T*)l,r); \ + return convert((T*)l,r); \ } catch (...) { } \ Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \ return false; \ diff --git a/src/ifcgeom/IfcRegisterGeomHeader.h b/src/ifcgeom/IfcRegisterGeomHeader.h index 6d469a6b73..9969d5e2db 100644 --- a/src/ifcgeom/IfcRegisterGeomHeader.h +++ b/src/ifcgeom/IfcRegisterGeomHeader.h @@ -1,5 +1,5 @@ #include "IfcRegisterUndef.h" -#define CLASS(T,V) bool convert(const T* L, V& r); +#define CLASS(T,V) bool convert(const IfcSchema::T* L, V& r); #define SHAPES(T) CLASS(T,IfcRepresentationShapeItems) #define SHAPE(T) CLASS(T,TopoDS_Shape) #define WIRE(T) CLASS(T,TopoDS_Wire) diff --git a/src/ifcgeomserver/IfcGeomServer.cpp b/src/ifcgeomserver/IfcGeomServer.cpp index 125b2e9c66..fcd0e279cd 100644 --- a/src/ifcgeomserver/IfcGeomServer.cpp +++ b/src/ifcgeomserver/IfcGeomServer.cpp @@ -35,7 +35,7 @@ #include #endif -#include "../ifcgeom/IfcGeomObjects.h" +#include "../ifcgeom/IfcGeomIterator.h" using namespace boost; @@ -186,7 +186,7 @@ public: class Entity : public Command { private: - const IfcGeomObjects::IfcGeomObject* geom; + const IfcGeom::TriangulationElement* geom; protected: void read_content(std::istream& s) {} void write_content(std::ostream& s) { @@ -195,7 +195,7 @@ protected: swrite(s, geom->name()); swrite(s, geom->type()); swrite(s, geom->parent_id()); - const std::vector& m = geom->matrix(); + const std::vector& m = geom->transformation().matrix().data(); const float matrix_array[16] = { m[0], m[3], m[6], m[ 9], m[1], m[4], m[7], m[10], @@ -203,17 +203,17 @@ protected: 0, 0, 0, 1 }; swrite(s, std::string((char*)matrix_array, 16 * sizeof(float))); - swrite(s, geom->mesh().id()); - swrite(s, std::string((char*)geom->mesh().verts().data(), geom->mesh().verts().size() * sizeof(float))); - swrite(s, std::string((char*)geom->mesh().normals().data(), geom->mesh().normals().size() * sizeof(float))); + swrite(s, geom->geometry().id()); + swrite(s, std::string((char*)geom->geometry().verts().data(), geom->geometry().verts().size() * sizeof(float))); + swrite(s, std::string((char*)geom->geometry().normals().data(), geom->geometry().normals().size() * sizeof(float))); { std::vector indices; - for (std::vector::const_iterator it = geom->mesh().faces().begin(); it != geom->mesh().faces().end(); ++it) { + for (std::vector::const_iterator it = geom->geometry().faces().begin(); it != geom->geometry().faces().end(); ++it) { indices.push_back(*it); } swrite(s, std::string((char*) indices.data(), indices.size() * sizeof(int32_t))); } { std::vector diffuse_color_array; - for (std::vector::const_iterator it = geom->mesh().materials().begin(); it != geom->mesh().materials().end(); ++it) { - const IfcGeomObjects::Material& m = *it; + for (std::vector::const_iterator it = geom->geometry().materials().begin(); it != geom->geometry().materials().end(); ++it) { + const IfcGeom::Material& m = *it; if (m.hasDiffuse()) { const double* color = m.diffuse(); diffuse_color_array.push_back(static_cast(color[0])); @@ -232,13 +232,13 @@ protected: } swrite(s, std::string((char*) diffuse_color_array.data(), diffuse_color_array.size() * sizeof(float))); } { std::vector material_indices; - for (std::vector::const_iterator it = geom->mesh().material_ids().begin(); it != geom->mesh().material_ids().end(); ++it) { + for (std::vector::const_iterator it = geom->geometry().material_ids().begin(); it != geom->geometry().material_ids().end(); ++it) { material_indices.push_back(*it); } swrite(s, std::string((char*) material_indices.data(), material_indices.size() * sizeof(int32_t))); } } public: - Entity(const IfcGeomObjects::IfcGeomObject* geom) : Command(ENTITY), geom(geom) {}; + Entity(const IfcGeom::TriangulationElement* geom) : Command(ENTITY), geom(geom) {}; }; class Next : public Command { @@ -278,6 +278,8 @@ int main (int argc, char** argv) { bool has_more = false; + IfcGeom::Iterator* iterator = 0; + Hello().write(std::cout); int exit_code = 0; @@ -290,12 +292,15 @@ int main (int argc, char** argv) { char* data = new char[len]; memcpy(data, m.string().c_str(), len); - IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS, false); - IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES, false); - IfcGeomObjects::Settings(IfcGeomObjects::CONVERT_BACK_UNITS, true); - IfcGeomObjects::Settings(IfcGeomObjects::FORCE_CCW_FACE_ORIENTATION, true); + IfcGeom::IteratorSettings settings; + settings.use_world_coords() = false; + settings.weld_vertices() = false; + settings.convert_back_units() = true; + settings.force_ccw_face_orientation() = true; + + iterator = new IfcGeom::Iterator(settings, data, len); + has_more = iterator->findContext(); - has_more = IfcGeomObjects::Init(data, len); More(has_more).write(std::cout); continue; } @@ -305,22 +310,23 @@ int main (int argc, char** argv) { exit_code = 1; break; } - const IfcGeomObjects::IfcGeomObject* geom = IfcGeomObjects::Get(); + const IfcGeom::TriangulationElement* geom = static_cast*>(iterator->get()); Entity(geom).write(std::cout); continue; } case NEXT: { Next n; n.read(std::cin); - has_more = IfcGeomObjects::Next(); + has_more = iterator->next(); if (!has_more) { - IfcGeomObjects::CleanUp(); + delete iterator; + iterator = 0; } More(has_more).write(std::cout); continue; } case GET_LOG: { GetLog gl; gl.read(std::cin); - WriteLog(IfcGeomObjects::GetLog()).write(std::cout); + WriteLog(iterator->getLog()).write(std::cout); continue; } case BYE: { diff --git a/src/ifcmax/IfcMax.cpp b/src/ifcmax/IfcMax.cpp index 49b3c61bab..5a2eeb62fe 100644 --- a/src/ifcmax/IfcMax.cpp +++ b/src/ifcmax/IfcMax.cpp @@ -22,7 +22,7 @@ #include #include "../ifcmax/IfcMax.h" -#include "../ifcgeom/IfcGeomObjects.h" +#include "../ifcgeom/IfcGeomIterator.h" static const int NUM_MATERIAL_SLOTS = 24; @@ -119,7 +119,7 @@ Mtl* FindMaterialByName(MtlBaseLib* library, const std::string& material_name) { return m; } -Mtl* FindOrCreateMaterial(MtlBaseLib* library, Interface* max_interface, int& slot, const IfcGeomObjects::Material& material) { +Mtl* FindOrCreateMaterial(MtlBaseLib* library, Interface* max_interface, int& slot, const IfcGeom::Material& material) { Mtl* m = FindMaterialByName(library, material.name()); if (m == 0) { StdMat2* stdm = NewDefaultStdMat(); @@ -148,7 +148,7 @@ Mtl* FindOrCreateMaterial(MtlBaseLib* library, Interface* max_interface, int& sl return m; } -Mtl* ComposeMultiMaterial(std::map, Mtl*>& multi_mats, MtlBaseLib* library, Interface* max_interface, int& slot, const std::vector& materials, const std::string& object_type, const std::vector& material_ids) { +Mtl* ComposeMultiMaterial(std::map, Mtl*>& multi_mats, MtlBaseLib* library, Interface* max_interface, int& slot, const std::vector& materials, const std::string& object_type, const std::vector& material_ids) { std::vector material_names; bool needs_default = std::find(material_ids.begin(), material_ids.end(), -1) != material_ids.end(); if (needs_default) { @@ -200,9 +200,10 @@ Mtl* ComposeMultiMaterial(std::map, Mtl*>& multi_mats, int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, BOOL suppressPrompts) { - IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,false); - IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,true); - IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS,true); + IfcGeom::IteratorSettings settings; + settings.use_world_coords() = false; + settings.weld_vertices() = true; + settings.sew_shells() = true; #ifdef _UNICODE int fn_buffer_size = WideCharToMultiByte(CP_UTF8, 0, name, -1, 0, 0, 0, 0); @@ -212,7 +213,9 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, const char* fn_mb = name; #endif - if ( ! IfcGeomObjects::Init(fn_mb,0,0) ) return false; + IfcGeom::Iterator iterator(settings, fn_mb); + + if (!iterator.findContext()) return false; itfc->ProgressStart(_T("Importing file..."), TRUE, fn, NULL); @@ -222,30 +225,29 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, std::map, Mtl*> material_cache; do{ - - const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get(); + const IfcGeom::TriangulationElement* o = static_cast*>(iterator.get()); TSTR o_type = S(o->type()); TSTR o_guid = S(o->guid()); - Mtl *m = ComposeMultiMaterial(material_cache, mats, itfc, slot, o->mesh().materials(), o->type(), o->mesh().material_ids()); + Mtl *m = ComposeMultiMaterial(material_cache, mats, itfc, slot, o->geometry().materials(), o->type(), o->geometry().material_ids()); TriObject* tri = CreateNewTriObject(); - const int numVerts = o->mesh().verts().size()/3; + const int numVerts = o->geometry().verts().size()/3; tri->mesh.setNumVerts(numVerts); for( int i = 0; i < numVerts; i ++ ) { - tri->mesh.setVert(i,o->mesh().verts()[3*i+0],o->mesh().verts()[3*i+1],o->mesh().verts()[3*i+2]); + tri->mesh.setVert(i,o->geometry().verts()[3*i+0],o->geometry().verts()[3*i+1],o->geometry().verts()[3*i+2]); } - const int numFaces = o->mesh().faces().size()/3; + const int numFaces = o->geometry().faces().size()/3; tri->mesh.setNumFaces(numFaces); - bool needs_default = std::find(o->mesh().material_ids().begin(), o->mesh().material_ids().end(), -1) != o->mesh().material_ids().end(); + bool needs_default = std::find(o->geometry().material_ids().begin(), o->geometry().material_ids().end(), -1) != o->geometry().material_ids().end(); for( int i = 0; i < numFaces; i ++ ) { - tri->mesh.faces[i].setVerts(o->mesh().faces()[3*i+0],o->mesh().faces()[3*i+1],o->mesh().faces()[3*i+2]); - tri->mesh.faces[i].setEdgeVisFlags(o->mesh().edges()[3*i+0],o->mesh().edges()[3*i+1],o->mesh().edges()[3*i+2]); - MtlID mtlid = o->mesh().material_ids()[i]; + tri->mesh.faces[i].setVerts(o->geometry().faces()[3*i+0],o->geometry().faces()[3*i+1],o->geometry().faces()[3*i+2]); + tri->mesh.faces[i].setEdgeVisFlags(o->geometry().edges()[3*i+0],o->geometry().edges()[3*i+1],o->geometry().edges()[3*i+2]); + MtlID mtlid = o->geometry().material_ids()[i]; if (needs_default) mtlid ++; tri->mesh.faces[i].setMatID(mtlid); } @@ -267,15 +269,14 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, if (m) { node->GetINode()->SetMtl(m); } - node->SetTransform(0,Matrix3 ( Point3(o->matrix()[0],o->matrix()[1],o->matrix()[2]),Point3(o->matrix()[3],o->matrix()[4],o->matrix()[5]), - Point3(o->matrix()[6],o->matrix()[7],o->matrix()[8]),Point3(o->matrix()[9],o->matrix()[10],o->matrix()[11]) )); + const std::vector& matrix_data = o->transformation().matrix().data(); + node->SetTransform(0,Matrix3 ( Point3(matrix_data[0],matrix_data[1],matrix_data[2]),Point3(matrix_data[3],matrix_data[4],matrix_data[5]), + Point3(matrix_data[6],matrix_data[7],matrix_data[8]),Point3(matrix_data[9],matrix_data[10],matrix_data[11]) )); impitfc->AddNodeToScene(node); - itfc->ProgressUpdate(IfcGeomObjects::Progress(),true,_T("")); + itfc->ProgressUpdate(iterator.progress(), true, _T("")); - } while ( IfcGeomObjects::Next() ); - - IfcGeomObjects::CleanUp(); + } while (iterator.next()); itfc->ProgressEnd(); diff --git a/src/ifcparse/IfcParse.h b/src/ifcparse/IfcParse.h index 3ccf11dda0..2cbaa31bb8 100644 --- a/src/ifcparse/IfcParse.h +++ b/src/ifcparse/IfcParse.h @@ -308,8 +308,6 @@ public: std::string authorOrganisation() const; }; -double UnitPrefixToValue( IfcSchema::IfcSIPrefix::IfcSIPrefix v ); - } std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f); diff --git a/src/ifcwrap/IfcPython.i b/src/ifcwrap/IfcPython.i index a5f1b13938..77b3874712 100644 --- a/src/ifcwrap/IfcPython.i +++ b/src/ifcwrap/IfcPython.i @@ -21,14 +21,45 @@ %include "std_string.i" %include "exception.i" +// This is only used for RGB colours, hence the size of 3 %typemap(out) const double* { - // This is only used for RGB colours, hence the size of 3 $result = PyTuple_New(3); for (int i = 0; i < 3; ++i) { PyTuple_SetItem($result, i, PyFloat_FromDouble($1[i])); } } +// Using RTTI return a more specialized type of Element +%typemap(out) IfcGeom::Element* { + IfcGeom::SerializedElement* serialized_elem = dynamic_cast*>($1); + IfcGeom::TriangulationElement* triangulation_elem = dynamic_cast*>($1); + if (triangulation_elem) { + $result = SWIG_NewPointerObj(SWIG_as_voidptr(triangulation_elem), SWIGTYPE_p_IfcGeom__TriangulationElementT_float_t, 0); + } else if (serialized_elem) { + $result = SWIG_NewPointerObj(SWIG_as_voidptr(serialized_elem), SWIGTYPE_p_IfcGeom__SerializedElementT_float_t, 0); + } +} + +// Using RTTI return a more specialized type of Element +%typemap(out) IfcGeom::Element* { + IfcGeom::SerializedElement* serialized_elem = dynamic_cast*>($1); + IfcGeom::TriangulationElement* triangulation_elem = dynamic_cast*>($1); + if (triangulation_elem) { + $result = SWIG_NewPointerObj(SWIG_as_voidptr(triangulation_elem), SWIGTYPE_p_IfcGeom__TriangulationElementT_double_t, 0); + } else if (serialized_elem) { + $result = SWIG_NewPointerObj(SWIG_as_voidptr(serialized_elem), SWIGTYPE_p_IfcGeom__SerializedElementT_double_t, 0); + } +} + +// SWIG does not support bool references in a meaningful way, so the +// IfcGeom::IteratorSettings functions degrade to return a read only value +%typemap(out) double& { + $result = SWIG_From_double(*$1); +} +%typemap(out) bool& { + $result = PyBool_FromLong(static_cast(*$1)); +} + %exception { try { $action @@ -39,14 +70,51 @@ } } -%include "Interface.h" +%include "../ifcgeom/IfcGeomIteratorSettings.h" +%include "../ifcgeom/IfcGeomMaterial.h" +%include "../ifcgeom/IfcGeomRepresentation.h" +%include "../ifcgeom/IfcGeomElement.h" +%include "../ifcgeom/IfcGeomIterator.h" -%module IfcImport %{ - #include "Interface.h" - using namespace IfcGeomObjects; +// This does not seem to work: +%ignore IfcGeom::Iterator::Iterator(const IfcGeom::IteratorSettings&, IfcParse::IfcFile*); +%ignore IfcGeom::Iterator::Iterator(const IfcGeom::IteratorSettings&, void*, int); +%ignore IfcGeom::Iterator::Iterator(const IfcGeom::IteratorSettings&, std::istream&, int); +%ignore IfcGeom::Iterator::Iterator(const IfcGeom::IteratorSettings&, IfcParse::IfcFile*); +%ignore IfcGeom::Iterator::Iterator(const IfcGeom::IteratorSettings&, void*, int); +%ignore IfcGeom::Iterator::Iterator(const IfcGeom::IteratorSettings&, std::istream&, int); + +%extend IfcGeom::IteratorSettings { + %pythoncode %{ + attrs = ("convert_back_units", "deflection_tolerance", "disable_opening_subtractions", "disable_triangulation", "faster_booleans", "force_ccw_face_orientation", "sew_shells", "use_brep_data", "use_world_coords", "weld_vertices") + def __repr__(self): + return "IteratorSettings(%s)"%(",".join(tuple("%s=%r"%(a, getattr(self, a)()) for a in self.attrs))) + %} +} + +%module ifcopenshell %{ + #include "../ifcgeom/IfcGeomIteratorSettings.h" + #include "../ifcgeom/IfcGeomMaterial.h" + #include "../ifcgeom/IfcGeomRepresentation.h" + #include "../ifcgeom/IfcGeomElement.h" + #include "../ifcgeom/IfcGeomIterator.h" + + using namespace IfcGeom; %} -%extend IfcGeomObjects::IfcRepresentationTriangulation { +%extend IfcGeom::Iterator { + static int mantissa_size() { + return std::numeric_limits::digits; + } +}; + +%extend IfcGeom::Iterator { + static int mantissa_size() { + return std::numeric_limits::digits; + } +}; + +%extend IfcGeom::Representation::Triangulation { %pythoncode %{ if _newclass: # Hide the getters with read-only property implementations @@ -57,21 +125,19 @@ normals = property(normals) material_ids = property(material_ids) materials = property(materials) - def __repr__(self): return "RepresentationTriangulation #%d"%self.id %} }; -%extend IfcGeomObjects::IfcRepresentationBrepData { +%extend IfcGeom::Representation::Serialization { %pythoncode %{ if _newclass: # Hide the getters with read-only property implementations id = property(id) brep_data = property(brep_data) - def __repr__(self): return "RepresentationBrepData #%d"%self.id %} }; -%extend IfcGeomObjects::IfcObject { +%extend IfcGeom::Element { %pythoncode %{ if _newclass: # Hide the getters with read-only property implementations @@ -80,30 +146,27 @@ name = property(name) type = property(type) guid = property(guid) - matrix = property(matrix) - def __repr__(self): return "Object #%d"%self.id + transformation = property(transformation) %} }; -%extend IfcGeomObjects::IfcGeomObject { +%extend IfcGeom::TriangulationElement { %pythoncode %{ if _newclass: # Hide the getters with read-only property implementations - mesh = property(mesh) - def __repr__(self): return "GeomObject #%d"%self.id + geometry = property(geometry) %} }; -%extend IfcGeomObjects::IfcGeomBrepDataObject { +%extend IfcGeom::SerializedElement { %pythoncode %{ if _newclass: # Hide the getters with read-only property implementations - mesh = property(mesh) - def __repr__(self): return "GeomBrepDataObject #%d"%self.id + geometry = property(geometry) %} }; -%extend IfcGeomObjects::Material { +%extend IfcGeom::Material { %pythoncode %{ if _newclass: # Hide the getters with read-only property implementations @@ -116,12 +179,61 @@ transparency = property(transparency) specularity = property(specularity) name = property(name) - def __repr__(self): return "Material" + %} +}; + +%extend IfcGeom::Transformation { + %pythoncode %{ + if _newclass: + # Hide the getters with read-only property implementations + matrix = property(matrix) + %} +}; + +%extend IfcGeom::Matrix { + %pythoncode %{ + if _newclass: + # Hide the getters with read-only property implementations + data = property(data) %} }; namespace std { %template(IntVector) vector; %template(FloatVector) vector; - %template(MaterialVector) vector; -}; \ No newline at end of file + %template(DoubleVector) vector; + %template(MaterialVector) vector; +}; + +namespace IfcGeom { + %template(IteratorSinglePrecision) Iterator; + %template(IteratorDoublePrecision) Iterator; + + %template(ElementSinglePrecision) Element; + %template(ElementDoublePrecision) Element; + + %template(TriangulationElementSinglePrecision) TriangulationElement; + %template(TriangulationElementDoublePrecision) TriangulationElement; + + %template(SerializedElementSinglePrecision) SerializedElement; + %template(SerializedElementDoublePrecision) SerializedElement; + + %template(TransformationSinglePrecision) Transformation; + %template(TransformationDoublePrecision) Transformation; + + %template(MatrixSinglePrecision) Matrix; + %template(MatrixDoublePrecision) Matrix; + + namespace Representation { + %template(TriangulationSinglePrecision) Triangulation; + %template(TriangulationDoublePrecision) Triangulation; + }; +}; + +// Hide templating precision to the user by choosing based on Python's +// internal float type. This is probably always going to be a double. +%pythoncode %{ + import sys + for ty in (IteratorSinglePrecision, IteratorDoublePrecision): + if ty.mantissa_size() == sys.float_info.mant_dig: Iterator = ty +%} \ No newline at end of file diff --git a/win/IfcGeom.vcproj b/win/IfcGeom.vcproj index e0a97425e5..44069b05af 100644 --- a/win/IfcGeom.vcproj +++ b/win/IfcGeom.vcproj @@ -167,17 +167,25 @@ > + + + + @@ -197,13 +205,33 @@ > + + + + + + + + + + @@ -220,6 +248,10 @@ RelativePath="..\src\ifcgeom\IfcRegisterConvertShape.h" > + + @@ -236,6 +268,10 @@ RelativePath="..\src\ifcgeom\IfcRegisterGeomHeader.h" > + + @@ -244,7 +280,7 @@ RelativePath="..\src\ifcgeom\IfcRegisterUndef.h" > - diff --git a/win/IfcWrap.vcproj b/win/IfcWrap.vcproj index a2b313c883..7dcdd71b59 100644 --- a/win/IfcWrap.vcproj +++ b/win/IfcWrap.vcproj @@ -62,7 +62,7 @@ @@ -133,7 +133,7 @@