From d17f714dc5355134ba084ac711aac1e7c145cc05 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 13 Jan 2017 17:59:05 +0100 Subject: [PATCH] Isolate geometry processing code into separate opencascade kernel --- cmake/CMakeLists.txt | 22 +- src/examples/IfcAdvancedHouse.cpp | 1 + src/examples/IfcOpenHouse.cpp | 2 + src/ifcconvert/ColladaSerializer.h | 2 +- src/ifcconvert/GeometrySerializer.h | 2 +- src/ifcconvert/IfcConvert.cpp | 7 +- src/ifcconvert/IgesSerializer.h | 6 +- src/ifcconvert/OpenCascadeBasedSerializer.cpp | 20 +- src/ifcconvert/OpenCascadeBasedSerializer.h | 4 +- src/ifcconvert/StepSerializer.h | 5 +- src/ifcconvert/SvgSerializer.cpp | 17 +- src/ifcconvert/SvgSerializer.h | 2 +- src/ifcconvert/WavefrontObjSerializer.h | 2 +- src/ifcconvert/XmlSerializer.cpp | 4 +- src/ifcgeom/ConversionResult.h | 87 +++ src/ifcgeom/IfcGeom.h | 147 +---- src/ifcgeom/IfcGeomAbstractKernel.cpp | 248 +++++++++ src/ifcgeom/IfcGeomElement.h | 32 +- src/ifcgeom/IfcGeomIterator.h | 81 +-- src/ifcgeom/IfcGeomRenderStyles.cpp | 6 +- src/ifcgeom/IfcGeomRepresentation.h | 247 ++------- src/ifcgeom/IfcRegisterConvertCurve.h | 6 - src/ifcgeom/IfcRegisterConvertFace.h | 6 - src/ifcgeom/IfcRegisterConvertWire.h | 6 - src/ifcgeom/IfcRegisterCreateCache.h | 6 - src/ifcgeom/IfcRegisterPurgeCache.h | 6 - src/ifcgeom/IfcRepresentationShapeItem.h | 53 -- .../opencascade/EntityMapping.cpp} | 39 +- .../opencascade/EntityMapping.h} | 4 +- .../opencascade/EntityMappingCreateCache.h | 6 + .../kernels/opencascade/EntityMappingCurve.h | 6 + .../opencascade/EntityMappingDeclaration.h} | 8 +- .../opencascade/EntityMappingDefine.h} | 0 .../kernels/opencascade/EntityMappingFace.h | 6 + .../opencascade/EntityMappingPurgeCache.h | 6 + .../opencascade/EntityMappingShape.h} | 6 +- .../opencascade/EntityMappingShapeType.h} | 6 +- .../opencascade/EntityMappingShapes.h} | 6 +- .../opencascade/EntityMappingUndefine.h} | 0 .../kernels/opencascade/EntityMappingWire.h | 6 + .../opencascade}/IfcGeomCurves.cpp | 17 +- .../opencascade}/IfcGeomFaces.cpp | 75 +-- .../opencascade}/IfcGeomFunctions.cpp | 505 +++++------------- .../opencascade}/IfcGeomHelpers.cpp | 81 +-- .../IfcGeomOpenCascadeSerialization.cpp} | 18 +- .../opencascade}/IfcGeomSerialisation.cpp | 10 +- .../opencascade}/IfcGeomShapes.cpp | 126 ++--- .../opencascade}/IfcGeomWires.cpp | 41 +- .../opencascade/OpenCascadeConversionResult.h | 86 +++ .../kernels/opencascade/OpenCascadeKernel.h | 155 ++++++ .../opencascade/OpenCascadeSerialization.h | 34 ++ .../kernels/opencascade/OpenCascadeShape.cpp | 194 +++++++ 52 files changed, 1369 insertions(+), 1099 deletions(-) create mode 100644 src/ifcgeom/ConversionResult.h create mode 100644 src/ifcgeom/IfcGeomAbstractKernel.cpp delete mode 100644 src/ifcgeom/IfcRegisterConvertCurve.h delete mode 100644 src/ifcgeom/IfcRegisterConvertFace.h delete mode 100644 src/ifcgeom/IfcRegisterConvertWire.h delete mode 100644 src/ifcgeom/IfcRegisterCreateCache.h delete mode 100644 src/ifcgeom/IfcRegisterPurgeCache.h delete mode 100644 src/ifcgeom/IfcRepresentationShapeItem.h rename src/ifcgeom/{IfcRegister.cpp => kernels/opencascade/EntityMapping.cpp} (76%) rename src/ifcgeom/{IfcRegister.h => kernels/opencascade/EntityMapping.h} (98%) create mode 100644 src/ifcgeom/kernels/opencascade/EntityMappingCreateCache.h create mode 100644 src/ifcgeom/kernels/opencascade/EntityMappingCurve.h rename src/ifcgeom/{IfcRegisterGeomHeader.h => kernels/opencascade/EntityMappingDeclaration.h} (60%) rename src/ifcgeom/{IfcRegisterDef.h => kernels/opencascade/EntityMappingDefine.h} (100%) create mode 100644 src/ifcgeom/kernels/opencascade/EntityMappingFace.h create mode 100644 src/ifcgeom/kernels/opencascade/EntityMappingPurgeCache.h rename src/ifcgeom/{IfcRegisterConvertShape.h => kernels/opencascade/EntityMappingShape.h} (88%) rename src/ifcgeom/{IfcRegisterShapeType.h => kernels/opencascade/EntityMappingShapeType.h} (76%) rename src/ifcgeom/{IfcRegisterConvertShapes.h => kernels/opencascade/EntityMappingShapes.h} (84%) rename src/ifcgeom/{IfcRegisterUndef.h => kernels/opencascade/EntityMappingUndefine.h} (100%) create mode 100644 src/ifcgeom/kernels/opencascade/EntityMappingWire.h rename src/ifcgeom/{ => kernels/opencascade}/IfcGeomCurves.cpp (90%) rename src/ifcgeom/{ => kernels/opencascade}/IfcGeomFaces.cpp (90%) rename src/ifcgeom/{ => kernels/opencascade}/IfcGeomFunctions.cpp (75%) rename src/ifcgeom/{ => kernels/opencascade}/IfcGeomHelpers.cpp (78%) rename src/ifcgeom/{IfcGeomRepresentation.cpp => kernels/opencascade/IfcGeomOpenCascadeSerialization.cpp} (81%) rename src/ifcgeom/{ => kernels/opencascade}/IfcGeomSerialisation.cpp (98%) rename src/ifcgeom/{ => kernels/opencascade}/IfcGeomShapes.cpp (85%) rename src/ifcgeom/{ => kernels/opencascade}/IfcGeomWires.cpp (90%) create mode 100644 src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h create mode 100644 src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h create mode 100644 src/ifcgeom/kernels/opencascade/OpenCascadeSerialization.h create mode 100644 src/ifcgeom/kernels/opencascade/OpenCascadeShape.cpp diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 187a0916e5..4084d02f24 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -541,8 +541,8 @@ IF(UNICODE_SUPPORT) ENDIF() # IfcGeom -file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/*.h) -file(GLOB IFCGEOM_CPP_FILES ../src/ifcgeom/*.cpp) +file(GLOB_RECURSE IFCGEOM_H_FILES ../src/ifcgeom/*.h) +file(GLOB_RECURSE IFCGEOM_CPP_FILES ../src/ifcgeom/*.cpp) set(IFCGEOM_FILES ${IFCGEOM_CPP_FILES} ${IFCGEOM_H_FILES}) add_library(IfcGeom ${IFCGEOM_FILES}) @@ -568,14 +568,14 @@ if ((NOT WIN32) AND BUILD_SHARED_LIBS) endif() # IfcGeomServer -file(GLOB CPP_FILES ../src/ifcgeomserver/*.cpp) -file(GLOB H_FILES ../src/ifcgeomserver/*.h) -set(SOURCE_FILES ${CPP_FILES} ${H_FILES}) -ADD_EXECUTABLE(IfcGeomServer ${SOURCE_FILES}) -TARGET_LINK_LIBRARIES(IfcGeomServer ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${ICU_LIBRARIES}) -if ((NOT WIN32) AND BUILD_SHARED_LIBS) - SET_INSTALL_RPATHS(IfcGeomServer "${IFCOPENSHELL_LIBARY_DIR};${OCC_LIBRARY_DIR};${Boost_LIBRARY_DIRS};${ICU_LIBRARY_DIR}") -endif() +# file(GLOB CPP_FILES ../src/ifcgeomserver/*.cpp) +# file(GLOB H_FILES ../src/ifcgeomserver/*.h) +# set(SOURCE_FILES ${CPP_FILES} ${H_FILES}) +# ADD_EXECUTABLE(IfcGeomServer ${SOURCE_FILES}) +# TARGET_LINK_LIBRARIES(IfcGeomServer ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${ICU_LIBRARIES}) +# if ((NOT WIN32) AND BUILD_SHARED_LIBS) +# SET_INSTALL_RPATHS(IfcGeomServer "${IFCOPENSHELL_LIBARY_DIR};${OCC_LIBRARY_DIR};${Boost_LIBRARY_DIRS};${ICU_LIBRARY_DIR}") +# endif() IF(BUILD_IFCPYTHON) ADD_SUBDIRECTORY(../src/ifcwrap ifcwrap) @@ -598,7 +598,7 @@ INSTALL(FILES ${IFCGEOM_H_FILES} DESTINATION ${INCLUDEDIR}/ifcgeom ) -INSTALL(TARGETS IfcParse IfcGeom IfcConvert IfcGeomServer +INSTALL(TARGETS IfcParse IfcGeom IfcConvert # IfcGeomServer ARCHIVE DESTINATION ${LIBDIR} LIBRARY DESTINATION ${LIBDIR} RUNTIME DESTINATION ${BINDIR} diff --git a/src/examples/IfcAdvancedHouse.cpp b/src/examples/IfcAdvancedHouse.cpp index 76cda1d4d6..197a74f09a 100644 --- a/src/examples/IfcAdvancedHouse.cpp +++ b/src/examples/IfcAdvancedHouse.cpp @@ -47,6 +47,7 @@ #include "../ifcparse/IfcUtil.h" #include "../ifcparse/IfcHierarchyHelper.h" #include "../ifcgeom/IfcGeom.h" +#include "../ifcgeom/kernels/opencascade/OpenCascadeSerialization.h" #if USE_VLD #include diff --git a/src/examples/IfcOpenHouse.cpp b/src/examples/IfcOpenHouse.cpp index 88adc574b6..18b329ba5c 100644 --- a/src/examples/IfcOpenHouse.cpp +++ b/src/examples/IfcOpenHouse.cpp @@ -30,6 +30,7 @@ #include #include +#include #ifdef USE_IFC4 #include "../ifcparse/Ifc4.h" @@ -40,6 +41,7 @@ #include "../ifcparse/IfcUtil.h" #include "../ifcparse/IfcHierarchyHelper.h" #include "../ifcgeom/IfcGeom.h" +#include "../ifcgeom/kernels/opencascade/OpenCascadeSerialization.h" #if USE_VLD #include diff --git a/src/ifcconvert/ColladaSerializer.h b/src/ifcconvert/ColladaSerializer.h index b9be98e15a..8dfeb6a7ef 100644 --- a/src/ifcconvert/ColladaSerializer.h +++ b/src/ifcconvert/ColladaSerializer.h @@ -188,7 +188,7 @@ public: bool ready(); void writeHeader(); void write(const IfcGeom::TriangulationElement* o); - void write(const IfcGeom::BRepElement* /*o*/) {} + void write(const IfcGeom::NativeElement* /*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 c2ee0f6416..95d12362a9 100644 --- a/src/ifcconvert/GeometrySerializer.h +++ b/src/ifcconvert/GeometrySerializer.h @@ -36,7 +36,7 @@ public: virtual bool isTesselated() const = 0; virtual void write(const IfcGeom::TriangulationElement* o) = 0; - virtual void write(const IfcGeom::BRepElement* o) = 0; + virtual void write(const IfcGeom::NativeElement* o) = 0; virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) = 0; const IfcGeom::IteratorSettings& settings() const { return settings_; } diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index af0baf5cd6..7015190a78 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -483,6 +483,8 @@ int main(int argc, char** argv) { int old_progress = -1; if (center_model) { + throw std::runtime_error("Not implemented"); + /* double* offset = serializer->settings().offset; gp_XYZ center = (context_iterator.bounds_min() + context_iterator.bounds_max()) * 0.5; offset[0] = -center.X(); @@ -491,6 +493,7 @@ int main(int argc, char** argv) { std::stringstream msg; msg << "Using model offset (" << offset[0] << "," << offset[1] << "," << offset[2] << ")"; Logger::Message(Logger::LOG_NOTICE, msg.str()); + */ } Logger::Status("Creating geometry..."); @@ -498,7 +501,7 @@ int main(int argc, char** argv) { // The functions IfcGeom::Iterator::get() and IfcGeom::Iterator::next() // wrap an iterator of all geometrical products in the Ifc file. // IfcGeom::Iterator::get() returns an IfcGeom::TriangulationElement or - // -BRepElement pointer, based on current settings. (see IfcGeomIterator.h + // -NativeElement pointer, based on current settings. (see IfcGeomIterator.h // for definition) IfcGeom::Iterator::next() is used to poll whether more // geometrical entities are available. None of these functions throw // exceptions, neither for parsing errors or geometrical errors. Upon @@ -512,7 +515,7 @@ int main(int argc, char** argv) { if (is_tesselated) { serializer->write(static_cast*>(geom_object)); } else { - serializer->write(static_cast*>(geom_object)); + serializer->write(static_cast*>(geom_object)); } const int progress = context_iterator.progress() / 2; if (old_progress != progress) Logger::ProgressBar(progress); diff --git a/src/ifcconvert/IgesSerializer.h b/src/ifcconvert/IgesSerializer.h index fb8045c2de..c166b75306 100644 --- a/src/ifcconvert/IgesSerializer.h +++ b/src/ifcconvert/IgesSerializer.h @@ -25,6 +25,8 @@ #include #include +#include "../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h" + class IgesSerializer : public OpenCascadeBasedSerializer { private: @@ -36,8 +38,8 @@ public: : OpenCascadeBasedSerializer(out_filename, settings) {} virtual ~IgesSerializer() {} - void writeShape(const TopoDS_Shape& shape) { - writer.AddShape(shape); + void writeShape(const IfcGeom::ConversionResultShape* shape) { + writer.AddShape(*(IfcGeom::OpenCascadeShape*)shape); } void finalize() { writer.Write(out_filename.c_str()); diff --git a/src/ifcconvert/OpenCascadeBasedSerializer.cpp b/src/ifcconvert/OpenCascadeBasedSerializer.cpp index cf5ae2df62..5ad6777217 100644 --- a/src/ifcconvert/OpenCascadeBasedSerializer.cpp +++ b/src/ifcconvert/OpenCascadeBasedSerializer.cpp @@ -22,8 +22,11 @@ #include #include +#include #include "OpenCascadeBasedSerializer.h" +#include "../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h" +#include "../ifcgeom/kernels/opencascade/OpenCascadeKernel.h" bool OpenCascadeBasedSerializer::ready() { std::ofstream test_file(out_filename.c_str(), std::ios_base::binary); @@ -33,11 +36,11 @@ bool OpenCascadeBasedSerializer::ready() { return succeeded; } -void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement* o) { - for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) { - gp_GTrsf gtrsf = it->Placement(); +void OpenCascadeBasedSerializer::write(const IfcGeom::NativeElement* o) { + for (IfcGeom::ConversionResults::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) { + gp_GTrsf gtrsf = *(IfcGeom::OpenCascadePlacement*) it->Placement(); - const gp_Trsf& o_trsf = o->transformation().data(); + const gp_GTrsf& o_trsf = *(IfcGeom::OpenCascadePlacement*) o->transformation().data(); gtrsf.PreMultiply(o_trsf); if (o->geometry().settings().get(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS)) { @@ -46,10 +49,11 @@ void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement* o) { gtrsf.PreMultiply(scale); } - const TopoDS_Shape& s = it->Shape(); - const TopoDS_Shape moved_shape = IfcGeom::Kernel::apply_transformation(s, gtrsf); - - writeShape(moved_shape); + const TopoDS_Shape& s = *(IfcGeom::OpenCascadeShape*) it->Shape(); + const TopoDS_Shape moved_shape = IfcGeom::OpenCascadeKernel::apply_transformation(s, gtrsf); + + IfcGeom::OpenCascadeShape shp(moved_shape); + writeShape(&shp); } } diff --git a/src/ifcconvert/OpenCascadeBasedSerializer.h b/src/ifcconvert/OpenCascadeBasedSerializer.h index f36a844609..5989fc68ed 100644 --- a/src/ifcconvert/OpenCascadeBasedSerializer.h +++ b/src/ifcconvert/OpenCascadeBasedSerializer.h @@ -38,9 +38,9 @@ public: virtual ~OpenCascadeBasedSerializer() {} void writeHeader() {} bool ready(); - virtual void writeShape(const TopoDS_Shape& shape) = 0; + virtual void writeShape(const IfcGeom::ConversionResultShape* shape) = 0; void write(const IfcGeom::TriangulationElement* /*o*/) {} - void write(const IfcGeom::BRepElement* o); + void write(const IfcGeom::NativeElement* o); bool isTesselated() const { return false; } void setFile(IfcParse::IfcFile*) {} }; diff --git a/src/ifcconvert/StepSerializer.h b/src/ifcconvert/StepSerializer.h index 99fff685b8..9c1c70cdf8 100644 --- a/src/ifcconvert/StepSerializer.h +++ b/src/ifcconvert/StepSerializer.h @@ -26,6 +26,7 @@ #include "../ifcgeom/IfcGeomIterator.h" #include "../ifcconvert/OpenCascadeBasedSerializer.h" +#include "../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h" class StepSerializer : public OpenCascadeBasedSerializer { @@ -36,10 +37,10 @@ public: : OpenCascadeBasedSerializer(out_filename, settings) {} virtual ~StepSerializer() {} - void writeShape(const TopoDS_Shape& shape) { + void writeShape(const IfcGeom::ConversionResultShape* shape) { std::stringstream ss; std::streambuf *sb = std::cout.rdbuf(ss.rdbuf()); - writer.Transfer(shape, STEPControl_AsIs); + writer.Transfer(*(IfcGeom::OpenCascadeShape*)shape, STEPControl_AsIs); std::cout.rdbuf(sb); } void finalize() { diff --git a/src/ifcconvert/SvgSerializer.cpp b/src/ifcconvert/SvgSerializer.cpp index bf64e82db4..e8ab86b889 100644 --- a/src/ifcconvert/SvgSerializer.cpp +++ b/src/ifcconvert/SvgSerializer.cpp @@ -26,8 +26,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -46,6 +48,9 @@ #include "SvgSerializer.h" +#include "../ifcgeom/kernels/opencascade/OpenCascadeKernel.h" +#include "../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h" + const double PI2 = M_PI * 2.; bool SvgSerializer::ready() { @@ -166,7 +171,7 @@ SvgSerializer::path_object& SvgSerializer::start_path(IfcSchema::IfcBuildingStor return p; } -void SvgSerializer::write(const IfcGeom::BRepElement* o) +void SvgSerializer::write(const IfcGeom::NativeElement* o) { IfcSchema::IfcBuildingStorey* storey = 0; IfcSchema::IfcObjectDefinition* obdef = static_cast(file->entityById(o->id())); @@ -213,14 +218,14 @@ void SvgSerializer::write(const IfcGeom::BRepElement* o) path_object& p = start_path(storey, nameElement(o)); - for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) { - gp_GTrsf gtrsf = it->Placement(); + for (IfcGeom::ConversionResults::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) { + gp_GTrsf gtrsf = *(IfcGeom::OpenCascadePlacement*) it->Placement(); - const gp_Trsf& o_trsf = o->transformation().data(); + const gp_GTrsf& o_trsf = *(IfcGeom::OpenCascadePlacement*) o->transformation().data(); gtrsf.PreMultiply(o_trsf); - const TopoDS_Shape& s = it->Shape(); - const TopoDS_Shape moved_shape = IfcGeom::Kernel::apply_transformation(s, gtrsf); + const TopoDS_Shape& s = *(IfcGeom::OpenCascadeShape*) it->Shape(); + const TopoDS_Shape moved_shape = IfcGeom::OpenCascadeKernel::apply_transformation(s, gtrsf); const double inf = std::numeric_limits::infinity(); double zmin = inf; diff --git a/src/ifcconvert/SvgSerializer.h b/src/ifcconvert/SvgSerializer.h index 96099ba1e5..169dae579c 100644 --- a/src/ifcconvert/SvgSerializer.h +++ b/src/ifcconvert/SvgSerializer.h @@ -60,7 +60,7 @@ public: void writeHeader(); bool ready(); void write(const IfcGeom::TriangulationElement* /*o*/) {} - void write(const IfcGeom::BRepElement* o); + void write(const IfcGeom::NativeElement* o); void write(path_object& p, const TopoDS_Wire& wire); path_object& start_path(IfcSchema::IfcBuildingStorey* storey, const std::string& id); bool isTesselated() const { return false; } diff --git a/src/ifcconvert/WavefrontObjSerializer.h b/src/ifcconvert/WavefrontObjSerializer.h index bdbc642ad0..cfb3cd2c62 100644 --- a/src/ifcconvert/WavefrontObjSerializer.h +++ b/src/ifcconvert/WavefrontObjSerializer.h @@ -47,7 +47,7 @@ public: void writeHeader(); void writeMaterial(const IfcGeom::Material& style); void write(const IfcGeom::TriangulationElement* o); - void write(const IfcGeom::BRepElement* /*o*/) {} + void write(const IfcGeom::NativeElement* /*o*/) {} void finalize() {} bool isTesselated() const { return true; } void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {} diff --git a/src/ifcconvert/XmlSerializer.cpp b/src/ifcconvert/XmlSerializer.cpp index a3dbaafc87..dcb574e0cd 100644 --- a/src/ifcconvert/XmlSerializer.cpp +++ b/src/ifcconvert/XmlSerializer.cpp @@ -30,6 +30,8 @@ #include "../ifcparse/IfcSIPrefix.h" #include "../ifcgeom/IfcGeom.h" +#include "../ifcgeom/kernels/opencascade/OpenCascadeKernel.h" + using boost::property_tree::ptree; using namespace IfcSchema; @@ -109,7 +111,7 @@ boost::optional format_attribute(const Argument* argument, IfcUtil: } else if (e->is(IfcSchema::Type::IfcLocalPlacement)) { IfcSchema::IfcLocalPlacement* placement = e->as(); gp_Trsf trsf; - IfcGeom::Kernel kernel; + IfcGeom::OpenCascadeKernel kernel; if (kernel.convert(placement, trsf)) { std::stringstream stream; for (int i = 1; i < 5; ++i) { diff --git a/src/ifcgeom/ConversionResult.h b/src/ifcgeom/ConversionResult.h new file mode 100644 index 0000000000..1c1051f8c4 --- /dev/null +++ b/src/ifcgeom/ConversionResult.h @@ -0,0 +1,87 @@ +/******************************************************************************** + * * + * 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 IFCSHAPELIST_H +#define IFCSHAPELIST_H + +#include "../ifcgeom/IfcGeomRenderStyles.h" +#include "../ifcgeom/IfcGeomIteratorSettings.h" + +namespace IfcGeom { + + namespace Representation { + template + class IFC_GEOM_API Triangulation; + } + + class IFC_GEOM_API ConversionResultPlacement { + public: + virtual void Multiply(const ConversionResultPlacement*) = 0; + virtual void PreMultiply(const ConversionResultPlacement*) = 0; + virtual double Value(int i, int j) const = 0; + virtual ConversionResultPlacement* clone() const = 0; + virtual ~ConversionResultPlacement() {} + }; + + class IFC_GEOM_API ConversionResultShape { + public: + virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement* place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const = 0; + virtual void Serialize(std::string&) const = 0; + virtual ConversionResultShape* clone() const = 0; + virtual ~ConversionResultShape() {} + }; + + class IFC_GEOM_API ConversionResult { + private: + ConversionResultPlacement* placement; + ConversionResultShape* shape; + const SurfaceStyle* style; + public: + ConversionResult(const ConversionResultPlacement* placement, const ConversionResultShape* shape, const SurfaceStyle* style) + : placement(placement->clone()), shape(shape->clone()), style(style) {} + ConversionResult(const ConversionResultPlacement* placement, const ConversionResultShape* shape) + : placement(placement->clone()), shape(shape->clone()), style(0) {} + ConversionResult(const ConversionResultShape* shape, const SurfaceStyle* style) + : placement(0), shape(shape->clone()), style(style) {} + ConversionResult(const ConversionResultShape* shape) + : placement(0), shape(shape->clone()), style(0) {} + void append(const ConversionResultPlacement* trsf) { + if (placement == 0) { + placement = trsf->clone(); + } else { + placement->Multiply(trsf); + } + } + void prepend(const ConversionResultPlacement* trsf) { + if (placement == 0) { + placement = trsf->clone(); + } else { + placement->PreMultiply(trsf); + } + } + const ConversionResultShape* Shape() const { return shape; } + const ConversionResultPlacement* Placement() const { return placement; } + bool hasStyle() const { return style != 0; } + const SurfaceStyle& Style() const { return *style; } + void setStyle(const SurfaceStyle* style) { this->style = style; } + }; + + typedef std::vector ConversionResults; +} +#endif diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index c485d6e347..bb3a8dc371 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -29,57 +29,18 @@ inline static bool ALMOST_THE_SAME(const T& a, const T& b, double tolerance=ALMO return fabs(a-b) < tolerance; } -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "../ifcparse/IfcParse.h" #include "../ifcparse/IfcUtil.h" +#include "../ifcgeom/ConversionResult.h" #include "../ifcgeom/IfcGeomElement.h" #include "../ifcgeom/IfcGeomRepresentation.h" -#include "../ifcgeom/IfcRepresentationShapeItem.h" #include "../ifcgeom/IfcGeomShapeType.h" #include "ifc_geom_api.h" -// Define this in case you want to conserve memory usage at all cost. This has been -// benchmarked extensively: https://github.com/IfcOpenShell/IfcOpenShell/pull/47 -// #define NO_CACHE - -#ifdef NO_CACHE - -#define IN_CACHE(T,E,t,e) -#define CACHE(T,E,e) - -#else - -#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; - -#endif - namespace IfcGeom { -class IFC_GEOM_API Cache { -public: -#include "IfcRegisterCreateCache.h" - std::map Shape; -}; - -class IFC_GEOM_API Kernel { +class IFC_GEOM_API AbstractKernel { private: double deflection_tolerance; @@ -91,15 +52,11 @@ private: double modelling_precision; double dimensionality; -#ifndef NO_CACHE - Cache cache; -#endif - std::map style_cache; const SurfaceStyle* internalize_surface_style(const std::pair& shading_style); public: - Kernel() + AbstractKernel() : deflection_tolerance(0.001) , wire_creation_tolerance(0.0001) , point_equality_tolerance(0.00001) @@ -110,11 +67,11 @@ public: , dimensionality(1.) {} - Kernel(const Kernel& other) { + AbstractKernel(const AbstractKernel& other) { *this = other; } - Kernel& operator=(const Kernel& other) { + AbstractKernel& operator=(const AbstractKernel& other) { setValue(GV_DEFLECTION_TOLERANCE, other.getValue(GV_DEFLECTION_TOLERANCE)); setValue(GV_WIRE_CREATION_TOLERANCE, other.getValue(GV_WIRE_CREATION_TOLERANCE)); setValue(GV_POINT_EQUALITY_TOLERANCE, other.getValue(GV_POINT_EQUALITY_TOLERANCE)); @@ -161,87 +118,29 @@ public: GV_DIMENSIONALITY }; - bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face); - bool convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire); - bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result); - IfcGeom::ShapeType shape_type(const IfcUtil::IfcBaseClass* L); - bool convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result); - bool flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse); - bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result); - bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& result); - bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result); - bool 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 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 convert_layerset(const IfcSchema::IfcProduct*, std::vector&, std::vector&, std::vector&); - bool apply_layerset(const IfcRepresentationShapeItems&, const std::vector&, const std::vector&, IfcRepresentationShapeItems&); - bool apply_folded_layerset(const IfcRepresentationShapeItems&, const std::vector< std::vector >&, const std::vector&, IfcRepresentationShapeItems&); - bool fold_layers(const IfcSchema::IfcWall*, const IfcRepresentationShapeItems&, const std::vector&, const std::vector&, std::vector< std::vector >&); - - bool split_solid_by_surface(const TopoDS_Shape&, const Handle_Geom_Surface&, TopoDS_Shape&, TopoDS_Shape&); - bool split_solid_by_shell(const TopoDS_Shape&, const TopoDS_Shape& s, TopoDS_Shape&, TopoDS_Shape&); - - const Handle_Geom_Curve intersect(const Handle_Geom_Surface&, const Handle_Geom_Surface&); - const Handle_Geom_Curve intersect(const Handle_Geom_Surface&, const TopoDS_Face&); - const Handle_Geom_Curve intersect(const TopoDS_Face&, const Handle_Geom_Surface&); - bool intersect(const Handle_Geom_Curve&, const Handle_Geom_Surface&, gp_Pnt&); - bool intersect(const Handle_Geom_Curve&, const TopoDS_Face&, gp_Pnt&); - bool intersect(const Handle_Geom_Curve&, const TopoDS_Shape&, std::vector&); - bool intersect(const Handle_Geom_Surface&, const TopoDS_Shape&, std::vector< std::pair >&); - bool closest(const gp_Pnt&, const std::vector&, gp_Pnt&); - bool project(const Handle_Geom_Curve&, const gp_Pnt&, gp_Pnt& p, double& u, double& d); - bool project(const Handle_Geom_Surface&, const TopoDS_Shape&, double& u1, double& v1, double& u2, double& v2, double widen=0.1); - int count(const TopoDS_Shape&, TopAbs_ShapeEnum); - - bool find_wall_end_points(const IfcSchema::IfcWall*, gp_Pnt& start, gp_Pnt& end); - IfcSchema::IfcSurfaceStyleShading* get_surface_style(IfcSchema::IfcRepresentationItem* item); const IfcSchema::IfcRepresentationItem* find_item_carrying_style(const IfcSchema::IfcRepresentationItem* item); - bool create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& solid); - bool create_solid_from_faces(const TopTools_ListOfShape& face_list, TopoDS_Shape& solid); - bool is_compound(const TopoDS_Shape& shape); - bool is_convex(const TopoDS_Wire& wire); - TopoDS_Shape halfspace_from_plane(const gp_Pln& pln,const gp_Pnt& cent); - gp_Pln plane_from_face(const TopoDS_Face& face); - gp_Pnt point_above_plane(const gp_Pln& pln, bool agree=true); - const TopoDS_Shape& ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid); - bool profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Shape& face); - 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) const; - bool fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape); - void remove_duplicate_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.); - void remove_collinear_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.); - bool wire_to_sequence_of_point(const TopoDS_Wire&, TColgp_SequenceOfPnt&); - void sequence_of_point_to_wire(const TColgp_SequenceOfPnt&, TopoDS_Wire&, bool closed); - bool approximate_plane_through_wire(const TopoDS_Wire&, gp_Pln&); - bool flatten_wire(TopoDS_Wire&); - - static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_Trsf&); - static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&); - bool is_identity_transform(IfcUtil::IfcBaseClass*); - + void setValue(GeomValue var, double value); + double getValue(GeomValue var) const; + IfcSchema::IfcRelVoidsElement::list::ptr find_openings(IfcSchema::IfcProduct* product); - IfcSchema::IfcRepresentation* find_representation(const IfcSchema::IfcProduct*, const std::string&); - std::pair initializeUnits(IfcSchema::IfcUnitAssignment*); - IfcSchema::IfcObjectDefinition* get_decomposing_entity(IfcSchema::IfcProduct*); - template - IfcGeom::BRepElement

* create_brep_for_representation_and_product( - const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*); + virtual bool is_identity_transform(IfcUtil::IfcBaseClass*) = 0; - template - IfcGeom::BRepElement

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

*); + virtual IfcGeom::NativeElement* create_brep_for_representation_and_product( + const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*) = 0; + + virtual IfcGeom::NativeElement* create_brep_for_processed_representation( + const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement*) = 0; const SurfaceStyle* get_style(const IfcSchema::IfcRepresentationItem*); const SurfaceStyle* get_style(const IfcSchema::IfcMaterial*); + + static AbstractKernel* kernel_by_name(const std::string&); template std::pair _get_surface_style(const IfcSchema::IfcStyledItem* si) { #ifdef USE_IFC4 @@ -292,21 +191,7 @@ public: return std::make_pair(0,0); } - void purge_cache() { - // Rather hack-ish, but a stopgap solution to keep memory under control - // for large files. SurfaceStyles need to be kept at all costs, as they - // are read later on when serializing Collada files. -#ifndef NO_CACHE - cache = Cache(); -#endif - } - -#include "IfcRegisterGeomHeader.h" - }; -IFC_GEOM_API IfcSchema::IfcProductDefinitionShape* tesselate(const TopoDS_Shape& shape, double deflection); -IFC_GEOM_API IfcSchema::IfcProductDefinitionShape* serialise(const TopoDS_Shape& shape, bool advanced); - } #endif diff --git a/src/ifcgeom/IfcGeomAbstractKernel.cpp b/src/ifcgeom/IfcGeomAbstractKernel.cpp new file mode 100644 index 0000000000..a5669d44f6 --- /dev/null +++ b/src/ifcgeom/IfcGeomAbstractKernel.cpp @@ -0,0 +1,248 @@ +#include "../ifcparse/IfcSIPrefix.h" + +#include "IfcGeom.h" +#include "kernels/opencascade/OpenCascadeKernel.h" + +void IfcGeom::AbstractKernel::setValue(GeomValue var, double value) { + switch (var) { + case GV_DEFLECTION_TOLERANCE: + deflection_tolerance = value; + break; + case GV_WIRE_CREATION_TOLERANCE: + wire_creation_tolerance = value; + break; + case GV_POINT_EQUALITY_TOLERANCE: + point_equality_tolerance = value; + break; + case GV_MAX_FACES_TO_SEW: + max_faces_to_sew = value; + break; + case GV_LENGTH_UNIT: + ifc_length_unit = value; + break; + case GV_PLANEANGLE_UNIT: + ifc_planeangle_unit = value; + break; + case GV_PRECISION: + modelling_precision = value; + break; + case GV_DIMENSIONALITY: + dimensionality = value; + break; + default: + assert(!"never reach here"); + } +} + +double IfcGeom::AbstractKernel::getValue(GeomValue var) const { + switch (var) { + case GV_DEFLECTION_TOLERANCE: + return deflection_tolerance; + case GV_WIRE_CREATION_TOLERANCE: + return wire_creation_tolerance; + case GV_MINIMAL_FACE_AREA: + // Considering a right-angled triangle, this about the smallest + // area you can obtain without the vertices being confused. + return modelling_precision * modelling_precision / 2.; + case GV_POINT_EQUALITY_TOLERANCE: + return point_equality_tolerance; + case GV_MAX_FACES_TO_SEW: + return max_faces_to_sew; + case GV_LENGTH_UNIT: + return ifc_length_unit; + break; + case GV_PLANEANGLE_UNIT: + return ifc_planeangle_unit; + break; + case GV_PRECISION: + return modelling_precision; + break; + case GV_DIMENSIONALITY: + return dimensionality; + break; + } + assert(!"never reach here"); + return 0; +} + +IfcSchema::IfcRelVoidsElement::list::ptr IfcGeom::AbstractKernel::find_openings(IfcSchema::IfcProduct* product) { + + IfcSchema::IfcRelVoidsElement::list::ptr openings(new IfcSchema::IfcRelVoidsElement::list); + if (product->is(IfcSchema::Type::IfcElement) && !product->is(IfcSchema::Type::IfcOpeningElement)) { + IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product; + openings = element->HasOpenings(); + } + + // Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements? + IfcSchema::IfcObjectDefinition* obdef = product->as(); + for (;;) { +#ifdef USE_IFC4 + IfcSchema::IfcRelAggregates::list::ptr decomposes = obdef->Decomposes(); +#else + IfcSchema::IfcRelDecomposes::list::ptr decomposes = obdef->Decomposes(); +#endif + if (decomposes->size() != 1) break; + IfcSchema::IfcObjectDefinition* rel_obdef = (*decomposes->begin())->RelatingObject(); + if (rel_obdef->is(IfcSchema::Type::IfcElement) && !rel_obdef->is(IfcSchema::Type::IfcOpeningElement)) { + IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)rel_obdef; + openings->push(element->HasOpenings()); + } + + obdef = rel_obdef; + } + + return openings; +} + +IfcSchema::IfcObjectDefinition* IfcGeom::AbstractKernel::get_decomposing_entity(IfcSchema::IfcProduct* product) { + IfcSchema::IfcObjectDefinition* parent = 0; + + // In case of an opening element, parent to the RelatingBuildingElement + if (product->is(IfcSchema::Type::IfcOpeningElement)) { + IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)product; + IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements(); + if (voids->size()) { + IfcSchema::IfcRelVoidsElement* ifc_void = *voids->begin(); + parent = ifc_void->RelatingBuildingElement(); + } + } else if (product->is(IfcSchema::Type::IfcElement)) { + IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)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 (product == ifc_objectdef) continue; + parent = ifc_objectdef; + } + } + // Else simply parent to the containing structure + if (!parent) { + IfcSchema::IfcRelContainedInSpatialStructure::list::ptr parents = element->ContainedInStructure(); + if (parents->size()) { + IfcSchema::IfcRelContainedInSpatialStructure* container = *parents->begin(); + parent = container->RelatingStructure(); + } + } + } + // Parent decompositions to the RelatingObject + if (!parent) { + IfcEntityList::ptr parents = product->entity->getInverse(IfcSchema::Type::IfcRelAggregates, -1); + parents->push(product->entity->getInverse(IfcSchema::Type::IfcRelNests, -1)); + 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 (product == ifc_objectdef) continue; + parent = ifc_objectdef; + } + } + return parent; +} + +std::pair IfcGeom::AbstractKernel::initializeUnits(IfcSchema::IfcUnitAssignment* unit_assignment) { + // Set default units, set length to meters, angles to undefined + setValue(IfcGeom::AbstractKernel::GV_LENGTH_UNIT, 1.0); + setValue(IfcGeom::AbstractKernel::GV_PLANEANGLE_UNIT, -1.0); + + std::string unit_name = "METER"; + double unit_magnitude = 1.; + + try { + IfcEntityList::ptr units = unit_assignment->Units(); + if (!units || !units->size()) { + Logger::Message(Logger::LOG_ERROR, "No unit information found"); + } else { + for (IfcEntityList::it it = units->begin(); it != units->end(); ++it) { + IfcUtil::IfcBaseClass* base = *it; + if (base->is(IfcSchema::Type::IfcNamedUnit)) { + IfcSchema::IfcNamedUnit* named_unit = base->as(); + if (named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT || + named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT) + { + std::string current_unit_name; + const double current_unit_magnitude = IfcParse::get_SI_equivalent(named_unit); + if (current_unit_magnitude != 0.) { + if (named_unit->is(IfcSchema::Type::IfcConversionBasedUnit)) { + IfcSchema::IfcConversionBasedUnit* u = (IfcSchema::IfcConversionBasedUnit*)base; + current_unit_name = u->Name(); + } else if (named_unit->is(IfcSchema::Type::IfcSIUnit)) { + IfcSchema::IfcSIUnit* si_unit = named_unit->as(); + if (si_unit->hasPrefix()) { + current_unit_name = IfcSchema::IfcSIPrefix::ToString(si_unit->Prefix()) + unit_name; + } + current_unit_name += IfcSchema::IfcSIUnitName::ToString(si_unit->Name()); + } + if (named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT) { + unit_name = current_unit_name; + unit_magnitude = current_unit_magnitude; + setValue(IfcGeom::AbstractKernel::GV_LENGTH_UNIT, current_unit_magnitude); + } else { + setValue(IfcGeom::AbstractKernel::GV_PLANEANGLE_UNIT, current_unit_magnitude); + } + } + } + } + } + } + } catch (const IfcParse::IfcException& ex) { + std::stringstream ss; + ss << "Failed to determine unit information '" << ex.what() << "'"; + Logger::Message(Logger::LOG_ERROR, ss.str()); + } + + return std::pair(unit_name, unit_magnitude); +} + +IfcSchema::IfcRepresentation* IfcGeom::AbstractKernel::find_representation(const IfcSchema::IfcProduct* product, const std::string& identifier) { + if (!product->hasRepresentation()) return 0; + IfcSchema::IfcProductRepresentation* prod_rep = product->Representation(); + IfcSchema::IfcRepresentation::list::ptr reps = prod_rep->Representations(); + for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { + if ((**it).hasRepresentationIdentifier() && (**it).RepresentationIdentifier() == identifier) { + return *it; + } + } + return 0; +} + +const IfcSchema::IfcRepresentationItem* IfcGeom::AbstractKernel::find_item_carrying_style(const IfcSchema::IfcRepresentationItem* item) { + if (item->StyledByItem()->size()) { + return item; + } + + while (item->is(IfcSchema::Type::IfcBooleanClippingResult)) { + // All instantiations of IfcBooleanOperand (type of FirstOperand) are subtypes of + // IfcGeometricRepresentationItem + item = (IfcSchema::IfcGeometricRepresentationItem*) ((IfcSchema::IfcBooleanClippingResult*) item)->FirstOperand(); + if (item->StyledByItem()->size()) { + return item; + } + } + + // TODO: Ideally this would be done for other entities (such as IfcCsgSolid) as well. + // But neither are these very prevalent, nor does the current IfcOpenShell style + // mechanism enable to conveniently style subshapes, which would be necessary for + // distinctly styled union operands. + + return item; +} + +IfcGeom::AbstractKernel* IfcGeom::AbstractKernel::kernel_by_name(const std::string& name) { + if (name == "opencascade") { + return new OpenCascadeKernel(); + } else if (name == "cgal") { + throw std::runtime_error("Not implemented"); + } else { + throw std::runtime_error("No kernel named " + name); + } +} \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomElement.h b/src/ifcgeom/IfcGeomElement.h index 7d1410c938..adab841ee0 100644 --- a/src/ifcgeom/IfcGeomElement.h +++ b/src/ifcgeom/IfcGeomElement.h @@ -36,7 +36,7 @@ namespace IfcGeom { private: std::vector

_data; public: - Matrix(const ElementSettings& settings, const gp_Trsf& trsf) { + Matrix(const ElementSettings& settings, const ConversionResultPlacement* 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 @@ -44,7 +44,7 @@ namespace IfcGeom { // 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 trsf_value = trsf->Value(j,i); const double matrix_value = i == 4 && settings.get(IteratorSettings::CONVERT_BACK_UNITS) ? trsf_value / settings.unit_magnitude() : trsf_value; @@ -58,14 +58,14 @@ namespace IfcGeom { template class Transformation { private: - gp_Trsf trsf; + ConversionResultPlacement* trsf; Matrix

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

& matrix() const { return _matrix; } }; @@ -89,7 +89,7 @@ namespace IfcGeom { const std::string& context() const { return _context; } const std::string& unique_id() const { return _unique_id; } 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 std::string& context, const gp_Trsf& trsf) + Element(const ElementSettings& settings, int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const std::string& context, const ConversionResultPlacement* trsf) : _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _context(context), _transformation(settings, trsf) { std::ostringstream oss; @@ -106,19 +106,19 @@ namespace IfcGeom { }; template - class BRepElement : public Element

{ + class NativeElement : public Element

{ private: - boost::shared_ptr _geometry; + boost::shared_ptr _geometry; public: - const boost::shared_ptr& geometry_pointer() const { return _geometry; } - const Representation::BRep& geometry() const { return *_geometry; } - BRepElement(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const std::string& context, const gp_Trsf& trsf, const boost::shared_ptr& geometry) + const boost::shared_ptr& geometry_pointer() const { return _geometry; } + const Representation::Native& geometry() const { return *_geometry; } + NativeElement(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const std::string& context, const ConversionResultPlacement* trsf, const boost::shared_ptr& geometry) : Element

(geometry->settings(),id,parent_id,name,type,guid,context,trsf) , _geometry(geometry) {} private: - BRepElement(const BRepElement& other); - BRepElement& operator=(const BRepElement& other); + NativeElement(const NativeElement& other); + NativeElement& operator=(const NativeElement& other); }; template @@ -128,7 +128,7 @@ namespace IfcGeom { public: const Representation::Triangulation

& geometry() const { return *_geometry; } const boost::shared_ptr< Representation::Triangulation

>& geometry_pointer() const { return _geometry; } - TriangulationElement(const BRepElement

& shape_model) + TriangulationElement(const NativeElement

& shape_model) : Element

(shape_model) , _geometry(boost::shared_ptr >(new Representation::Triangulation

(shape_model.geometry()))) {} @@ -147,7 +147,7 @@ namespace IfcGeom { Representation::Serialization* _geometry; public: const Representation::Serialization& geometry() const { return *_geometry; } - SerializedElement(const BRepElement

& shape_model) + SerializedElement(const NativeElement

& shape_model) : Element

(shape_model) , _geometry(new Representation::Serialization(shape_model.geometry())) {} diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index b9c50730f1..150c6899f7 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -67,20 +67,13 @@ #include #include -#include -#include -#include -#include -#include -#include - #include "../ifcparse/IfcFile.h" #include "../ifcgeom/IfcGeom.h" #include "../ifcgeom/IfcGeomElement.h" #include "../ifcgeom/IfcGeomMaterial.h" #include "../ifcgeom/IfcGeomIteratorSettings.h" -#include "../ifcgeom/IfcRepresentationShapeItem.h" +#include "../ifcgeom/ConversionResult.h" // The infamous min & max Win32 #defines can leak here from OCE depending on the build configuration #ifdef min @@ -98,7 +91,7 @@ namespace IfcGeom { Iterator(const Iterator&); // N/I Iterator& operator=(const Iterator&); // N/I - Kernel kernel; + AbstractKernel* kernel; IteratorSettings settings; IfcParse::IfcFile* ifc_file; @@ -109,7 +102,7 @@ namespace IfcGeom { // The object is fetched beforehand to be sure that get() returns a valid element TriangulationElement

* current_triangulation; - BRepElement

* current_shape_model; + NativeElement

* current_shape_model; SerializedElement

* current_serialization; // A container and iterator for IfcBuildingElements for the current IfcRepresentation referenced by *representation_iterator @@ -122,14 +115,14 @@ namespace IfcGeom { std::string unit_name; // double? P unit_magnitude; - gp_XYZ bounds_min_; - gp_XYZ bounds_max_; + /* gp_XYZ bounds_min_; + gp_XYZ bounds_max_; */ void initUnits() { IfcSchema::IfcProject::list::ptr projects = ifc_file->entitiesByType(); if (projects->size() == 1) { IfcSchema::IfcProject* project = *projects->begin(); - std::pair length_unit = kernel.initializeUnits(project->UnitsInContext()); + std::pair length_unit = kernel->initializeUnits(project->UnitsInContext()); unit_name = length_unit.first; unit_magnitude = static_cast

(length_unit.second); } @@ -253,12 +246,12 @@ namespace IfcGeom { lowest_precision_encountered *= unit_magnitude; if (lowest_precision_encountered < 1.e-7) { Logger::Message(Logger::LOG_WARNING, "Precision lower than 0.0000001 meter not enforced"); - kernel.setValue(IfcGeom::Kernel::GV_PRECISION, 1.e-7); + kernel->setValue(IfcGeom::AbstractKernel::GV_PRECISION, 1.e-7); } else { - kernel.setValue(IfcGeom::Kernel::GV_PRECISION, lowest_precision_encountered); + kernel->setValue(IfcGeom::AbstractKernel::GV_PRECISION, lowest_precision_encountered); } } else { - kernel.setValue(IfcGeom::Kernel::GV_PRECISION, 1.e-5); + kernel->setValue(IfcGeom::AbstractKernel::GV_PRECISION, 1.e-5); } if (representations->size() == 0) { @@ -276,7 +269,8 @@ namespace IfcGeom { done = 0; total = representations->size(); - for (int i = 1; i < 4; ++i) { + /* + for (int i = 1; i < 4; ++i) { bounds_min_.SetCoord(i, std::numeric_limits::infinity()); bounds_max_.SetCoord(i, -std::numeric_limits::infinity()); } @@ -289,7 +283,7 @@ namespace IfcGeom { gp_Trsf trsf; bool success = false; try { - success = kernel.convert(product->ObjectPlacement(), trsf); + success = kernel->convert(product->ObjectPlacement(), trsf); } catch (...) {} if (!success) { continue; @@ -304,6 +298,7 @@ namespace IfcGeom { bounds_max_.SetZ(std::max(bounds_max_.Z(), pos.Z())); } } + */ return true; } @@ -362,8 +357,10 @@ namespace IfcGeom { return boost::regex(str); } + /* const gp_XYZ& bounds_min() const { return bounds_min_; } const gp_XYZ& bounds_max() const { return bounds_max_; } + */ private: // Move to the next IfcRepresentation @@ -371,10 +368,14 @@ namespace IfcGeom { // In order to conserve memory and reduce cache insertion times, the cache is // cleared after an arbitary number of processed representations. This has been // benchmarked extensively: https://github.com/IfcOpenShell/IfcOpenShell/pull/47 + + /* static const int clear_interval = 64; if (done % clear_interval == clear_interval - 1) { - kernel.purge_cache(); + kernel->purge_cache(); } + */ + ifcproducts.reset(); ++ representation_iterator; ++ done; @@ -382,7 +383,7 @@ namespace IfcGeom { std::set mapped_representations_processed; - BRepElement

* create_shape_model_for_next_entity() { + NativeElement

* create_shape_model_for_next_entity() { for (;;) { IfcSchema::IfcRepresentation* representation; @@ -423,7 +424,7 @@ namespace IfcGeom { bool has_layers = false; for (IfcSchema::IfcProduct::list::it it = unfiltered_products->begin(); it != unfiltered_products->end(); ++it) { - if (kernel.find_openings(*it)->size()) { + if (kernel->find_openings(*it)->size()) { has_openings = true; } IfcSchema::IfcRelAssociates::list::ptr associations = (*it)->HasAssociations(); @@ -438,7 +439,7 @@ namespace IfcGeom { } // With world coords enabled, object transformations are directly applied to - // the BRep. There is no way to re-use the geometry for multiple products. + // the Native. There is no way to re-use the geometry for multiple products. const bool process_maps_for_current_representation = !settings.get(IteratorSettings::USE_WORLD_COORDS) && (!has_openings || settings.get(IteratorSettings::DISABLE_OPENING_SUBTRACTIONS)) && (!has_layers || !settings.get(IteratorSettings::APPLY_LAYERSETS)); @@ -453,9 +454,9 @@ namespace IfcGeom { if (item->is(IfcSchema::Type::IfcMappedItem)) { if (item->StyledByItem()->size() == 0) { IfcSchema::IfcMappedItem* mapped_item = item->as(); - if (kernel.is_identity_transform(mapped_item->MappingTarget())) { + if (kernel->is_identity_transform(mapped_item->MappingTarget())) { IfcSchema::IfcRepresentationMap* map = mapped_item->MappingSource(); - if (kernel.is_identity_transform(map->MappingOrigin())) { + if (kernel->is_identity_transform(map->MappingOrigin())) { representation_mapped_to = map->MappedRepresentation(); IfcSchema::IfcProductRepresentation::list::ptr prodreps = representation_mapped_to->OfProductRepresentation(); @@ -466,7 +467,7 @@ namespace IfcGeom { IfcSchema::IfcProduct::list::ptr products_of_prodrep = (*it)->entity->getInverse(IfcSchema::Type::IfcProduct, -1)->as(); products->push(products_of_prodrep); for (IfcSchema::IfcProduct::list::it jt = products_of_prodrep->begin(); jt != products_of_prodrep->end(); ++jt) { - if (kernel.find_openings(*jt)->size() > 0 && !settings.get(IteratorSettings::DISABLE_OPENING_SUBTRACTIONS)) { + if (kernel->find_openings(*jt)->size() > 0 && !settings.get(IteratorSettings::DISABLE_OPENING_SUBTRACTIONS)) { all_product_without_openings = false; break; } @@ -501,13 +502,13 @@ namespace IfcGeom { if (process_maps_for_current_representation && maps->size() == 1) { IfcSchema::IfcRepresentationMap* map = *maps->begin(); - if (kernel.is_identity_transform(map->MappingOrigin())) { + if (kernel->is_identity_transform(map->MappingOrigin())) { IfcSchema::IfcMappedItem::list::ptr items = map->MapUsage(); for (IfcSchema::IfcMappedItem::list::it it = items->begin(); it != items->end(); ++it) { IfcSchema::IfcMappedItem* item = *it; if (item->StyledByItem()->size() != 0) continue; - if (!kernel.is_identity_transform(item->MappingTarget())) { + if (!kernel->is_identity_transform(item->MappingTarget())) { continue; } @@ -519,7 +520,7 @@ namespace IfcGeom { for (IfcSchema::IfcProductRepresentation::list::it kt = prodreps->begin(); kt != prodreps->end(); ++kt) { IfcSchema::IfcProduct::list::ptr prods = (*kt)->entity->getInverse(IfcSchema::Type::IfcProduct, -1)->as(); for (IfcSchema::IfcProduct::list::it lt = prods->begin(); lt != prods->end(); ++lt) { - if (kernel.find_openings(*lt)->size() == 0 || settings.get(IteratorSettings::DISABLE_OPENING_SUBTRACTIONS)) { + if (kernel->find_openings(*lt)->size() == 0 || settings.get(IteratorSettings::DISABLE_OPENING_SUBTRACTIONS)) { if (!unfiltered_products->contains(*lt)) { unfiltered_products->push(*lt); } @@ -549,7 +550,7 @@ namespace IfcGeom { if (!type_found && traverse) { foreach(IfcSchema::Type::Enum type, entities_to_include_or_exclude) { IfcSchema::IfcProduct* parent, * current = prod; - while ((parent = static_cast(kernel.get_decomposing_entity(current))) != 0) { + while ((parent = static_cast(kernel->get_decomposing_entity(current))) != 0) { if (parent->is(type)) { type_found = true; break; @@ -573,7 +574,7 @@ namespace IfcGeom { if (!name_found && traverse) { foreach(const boost::regex& r, names_to_include_or_exclude) { IfcSchema::IfcProduct* parent, *current = prod; - while ((parent = static_cast(kernel.get_decomposing_entity(current))) != 0) { + while ((parent = static_cast(kernel->get_decomposing_entity(current))) != 0) { if (parent->hasName() && boost::regex_match(parent->Name(), r)) { name_found = true; break; @@ -604,11 +605,11 @@ namespace IfcGeom { Logger::SetProduct(product); - BRepElement

* element; + NativeElement

* element; if (ifcproduct_iterator == ifcproducts->begin() || !settings.get(IteratorSettings::USE_WORLD_COORDS)) { - element = kernel.create_brep_for_representation_and_product

(settings, representation, product); + element = kernel->create_brep_for_representation_and_product(settings, representation, product); } else { - element = kernel.create_brep_for_processed_representation(settings, representation, product, current_shape_model); + element = kernel->create_brep_for_processed_representation(settings, representation, product, current_shape_model); } Logger::SetProduct(boost::none); @@ -655,6 +656,7 @@ namespace IfcGeom { return ret; } + /* const Element

* getObject(int id) { gp_Trsf trsf; @@ -672,14 +674,14 @@ namespace IfcGeom { parent_id = -1; try { - IfcSchema::IfcObjectDefinition* parent_object = kernel.get_decomposing_entity(ifc_product); + IfcSchema::IfcObjectDefinition* parent_object = kernel->get_decomposing_entity(ifc_product); if (parent_object) { parent_id = parent_object->entity->id(); } } catch (...) {} try { - kernel.convert(ifc_product->ObjectPlacement(), trsf); + kernel->convert(ifc_product->ObjectPlacement(), trsf); } catch (...) {} } } catch(...) {} @@ -689,11 +691,12 @@ namespace IfcGeom { return ifc_object; } + */ bool create() { bool success = true; - IfcGeom::BRepElement

* next_shape_model = 0; + IfcGeom::NativeElement

* next_shape_model = 0; IfcGeom::SerializedElement

* next_serialization = 0; IfcGeom::TriangulationElement

* next_triangulation = 0; @@ -747,8 +750,10 @@ namespace IfcGeom { unit_name = "METER"; unit_magnitude = 1.f; - kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.get(IteratorSettings::SEW_SHELLS) ? 1000 : -1); - kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IteratorSettings::INCLUDE_CURVES) + kernel = IfcGeom::AbstractKernel::kernel_by_name("opencascade"); + + kernel->setValue(IfcGeom::AbstractKernel::GV_MAX_FACES_TO_SEW, settings.get(IteratorSettings::SEW_SHELLS) ? 1000 : -1); + kernel->setValue(IfcGeom::AbstractKernel::GV_DIMENSIONALITY, (settings.get(IteratorSettings::INCLUDE_CURVES) ? (settings.get(IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.)); } diff --git a/src/ifcgeom/IfcGeomRenderStyles.cpp b/src/ifcgeom/IfcGeomRenderStyles.cpp index 39c0d4ef37..398c13679b 100644 --- a/src/ifcgeom/IfcGeomRenderStyles.cpp +++ b/src/ifcgeom/IfcGeomRenderStyles.cpp @@ -50,7 +50,7 @@ bool process_colour(IfcSchema::IfcColourOrFactor* colour_or_factor, double* rgb) } } -const IfcGeom::SurfaceStyle* IfcGeom::Kernel::internalize_surface_style(const std::pair& shading_styles) { +const IfcGeom::SurfaceStyle* IfcGeom::AbstractKernel::internalize_surface_style(const std::pair& shading_styles) { if (shading_styles.second == 0) { return 0; } @@ -106,11 +106,11 @@ const IfcGeom::SurfaceStyle* IfcGeom::Kernel::internalize_surface_style(const st return &(style_cache[surface_style_id] = surface_style); } -const IfcGeom::SurfaceStyle* IfcGeom::Kernel::get_style(const IfcSchema::IfcRepresentationItem* item) { +const IfcGeom::SurfaceStyle* IfcGeom::AbstractKernel::get_style(const IfcSchema::IfcRepresentationItem* item) { return internalize_surface_style(get_surface_style(item)); } -const IfcGeom::SurfaceStyle* IfcGeom::Kernel::get_style(const IfcSchema::IfcMaterial* material) { +const IfcGeom::SurfaceStyle* IfcGeom::AbstractKernel::get_style(const IfcSchema::IfcMaterial* material) { IfcSchema::IfcMaterialDefinitionRepresentation::list::ptr defs = material->HasRepresentation(); for (IfcSchema::IfcMaterialDefinitionRepresentation::list::it jt = defs->begin(); jt != defs->end(); ++jt) { IfcSchema::IfcRepresentation::list::ptr reps = (*jt)->Representations(); diff --git a/src/ifcgeom/IfcGeomRepresentation.h b/src/ifcgeom/IfcGeomRepresentation.h index 7a18dc4bab..52f3ddceed 100644 --- a/src/ifcgeom/IfcGeomRepresentation.h +++ b/src/ifcgeom/IfcGeomRepresentation.h @@ -20,22 +20,9 @@ #ifndef IFCGEOMREPRESENTATION_H #define IFCGEOMREPRESENTATION_H -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - #include "../ifcgeom/IfcGeomIteratorSettings.h" #include "../ifcgeom/IfcGeomMaterial.h" -#include "../ifcgeom/IfcRepresentationShapeItem.h" +#include "../ifcgeom/ConversionResult.h" namespace IfcGeom { @@ -54,22 +41,22 @@ namespace IfcGeom { virtual ~Representation() {} }; - class IFC_GEOM_API BRep : public Representation { + class IFC_GEOM_API Native : public Representation { private: unsigned int id; - const IfcGeom::IfcRepresentationShapeItems _shapes; - BRep(const BRep& other); - BRep& operator=(const BRep& other); + const IfcGeom::ConversionResults _shapes; + Native(const Native& other); + Native& operator=(const Native& other); public: - BRep(const ElementSettings& settings, unsigned int id, const IfcGeom::IfcRepresentationShapeItems& shapes) + Native(const ElementSettings& settings, unsigned int id, const IfcGeom::ConversionResults& 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 IfcGeom::IfcRepresentationShapeItems& shapes() const { return _shapes; } + virtual ~Native() {} + IfcGeom::ConversionResults::const_iterator begin() const { return _shapes.begin(); } + IfcGeom::ConversionResults::const_iterator end() const { return _shapes.end(); } + const IfcGeom::ConversionResults& shapes() const { return _shapes; } const unsigned int& getId() const { return id; } }; @@ -82,7 +69,7 @@ namespace IfcGeom { int id() const { return _id; } const std::string& brep_data() const { return _brep_data; } const std::vector& surface_styles() const { return _surface_styles; } - Serialization(const BRep& brep); + Serialization(const Native& brep); virtual ~Serialization() {} private: Serialization(); @@ -91,8 +78,8 @@ namespace IfcGeom { }; template - class Triangulation : public Representation { - private: + class IFC_GEOM_API Triangulation : public Representation { + protected: // 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; @@ -112,6 +99,7 @@ namespace IfcGeom { 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; } @@ -119,12 +107,20 @@ namespace IfcGeom { const std::vector

& uvs() const { return uvs_; } const std::vector& material_ids() const { return _material_ids; } const std::vector& materials() const { return _materials; } - - Triangulation(const BRep& shape_model) + + std::vector

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

& normals() { return _normals; } + std::vector

& uvs() { return uvs_; } + std::vector& material_ids() { return _material_ids; } + std::vector& materials() { return _materials; } + + Triangulation(const Native& shape_model) : Representation(shape_model.settings()) , _id(shape_model.getId()) { - for ( IfcGeom::IfcRepresentationShapeItems::const_iterator iit = shape_model.begin(); iit != shape_model.end(); ++ iit ) { + for (IfcGeom::ConversionResults::const_iterator iit = shape_model.begin(); iit != shape_model.end(); ++iit) { int surface_style_id = -1; if (iit->hasStyle()) { @@ -149,185 +145,10 @@ namespace IfcGeom { } } - const TopoDS_Shape& s = iit->Shape(); - const gp_GTrsf& trsf = iit->Placement(); - - // Triangulate the shape - try { - BRepMesh_IncrementalMesh(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; - } - - // Iterates over the faces of the shape - int num_faces = 0; - TopExp_Explorer exp; - for ( exp.Init(s,TopAbs_FACE); exp.More(); exp.Next(), ++num_faces ) { - 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 and calculation is not disable explicitly. - const bool calculate_normals = !settings().get(IteratorSettings::WELD_VERTICES) && - !settings().get(IteratorSettings::NO_NORMALS); - - 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(static_cast

(normal.X())); - _normals.push_back(static_cast

(normal.Y())); - _normals.push_back(static_cast

(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(dict[n1], dict[n2], edgecount, edges_temp); - addEdge(dict[n2], dict[n3], edgecount, edges_temp); - addEdge(dict[n3], dict[n1], edgecount, edges_temp); - } - for ( std::vector >::const_iterator jt = edges_temp.begin(); jt != edges_temp.end(); ++jt ) { - if (edgecount[*jt] == 1) { - // non manifold edge, face boundary - _edges.push_back(jt->first); - _edges.push_back(jt->second); - } - } - } - } - - if (!_normals.empty() && settings().get(IfcGeom::IteratorSettings::GENERATE_UVS)) { - uvs_ = box_project_uvs(_verts, _normals); - } - - if (num_faces == 0) { - // Edges are only emitted if there are no faces. A mixed representation of faces - // and loose edges is discouraged by the standard. An alternative would be to use - // TopExp_Explorer texp(s, TopAbs_EDGE, TopAbs_FACE) to find edges that do not - // belong to any face. - for (TopExp_Explorer texp(s, TopAbs_EDGE); texp.More(); texp.Next()) { - BRepAdaptor_Curve crv(TopoDS::Edge(texp.Current())); - GCPnts_QuasiUniformDeflection tessellater(crv, settings().deflection_tolerance()); - int n = tessellater.NbPoints(); - int start = (int)_verts.size() / 3; - for (int i = 1; i <= n; ++i) { - gp_XYZ p = tessellater.Value(i).XYZ(); - - /* - // In case you want direction arrows on your edges - double u = tessellater.Parameter(i); - gp_XYZ p2, p3; - gp_Pnt tmp; - gp_Vec tmp2; - crv.D1(u, tmp, tmp2); - gp_Dir d1, d2, d3, d4; - d1 = tmp2; - if (texp.Current().Orientation() == TopAbs_REVERSED) { - d1 = -d1; - } - if (fabs(d1.Z()) < 0.5) { - d2 = d1.Crossed(gp::DZ()); - } else { - d2 = d1.Crossed(gp::DY()); - } - d3 = d1.XYZ() + d2.XYZ(); - d4 = d1.XYZ() - d2.XYZ(); - p2 = p - d3.XYZ() / 10.; - p3 = p - d4.XYZ() / 10.; - trsf.Transforms(p2); - trsf.Transforms(p3); - _material_ids.push_back(surface_style_id); - _material_ids.push_back(surface_style_id); - _verts.push_back(static_cast

(p2.X())); - _verts.push_back(static_cast

(p2.Y())); - _verts.push_back(static_cast

(p2.Z())); - _verts.push_back(static_cast

(p3.X())); - _verts.push_back(static_cast

(p3.Y())); - _verts.push_back(static_cast

(p3.Z())); - */ - - trsf.Transforms(p); - - _material_ids.push_back(surface_style_id); - - _verts.push_back(static_cast

(p.X())); - _verts.push_back(static_cast

(p.Y())); - _verts.push_back(static_cast

(p.Z())); - - if (i > 1) { - _edges.push_back(start + i - 2); - _edges.push_back(start + i - 1); - // _edges.push_back(start + 3 * (i - 2) + 2); - // _edges.push_back(start + 3 * (i - 1) + 2); - } - - // _edges.push_back(start + 3 * (i - 1) + 0); - // _edges.push_back(start + 3 * (i - 1) + 2); - // _edges.push_back(start + 3 * (i - 1) + 1); - // _edges.push_back(start + 3 * (i - 1) + 2); - } - } - } - - BRepTools::Clean(s); + iit->Shape()->Triangulate(settings(), iit->Placement(), this, surface_style_id); } - } + } + virtual ~Triangulation() {} /// Generates UVs for a single mesh using box projection. @@ -360,13 +181,13 @@ namespace IfcGeom { return uvs; } - private: + public: // Welds vertices that belong to different faces - int addVertex(int material_index, const gp_XYZ& p) { + int addVertex(int material_index, P X, P Y, P Z) { const bool convert = settings().get(IteratorSettings::CONVERT_BACK_UNITS); - const P X = static_cast

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

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

(convert ? (p.Z() / settings().unit_magnitude()) : p.Z()); + X = static_cast

(convert ? (X / settings().unit_magnitude()) : X); + Y = static_cast

(convert ? (Y / settings().unit_magnitude()) : Y); + Z = static_cast

(convert ? (Z / settings().unit_magnitude()) : Z); int i = (int) _verts.size() / 3; if (settings().get(IteratorSettings::WELD_VERTICES)) { const VertexKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z))); @@ -386,6 +207,8 @@ namespace IfcGeom { else edgecount[e] ++; edges_temp.push_back(e); } + + private: Triangulation(); Triangulation(const Triangulation&); Triangulation& operator=(const Triangulation&); diff --git a/src/ifcgeom/IfcRegisterConvertCurve.h b/src/ifcgeom/IfcRegisterConvertCurve.h deleted file mode 100644 index e67aa45807..0000000000 --- a/src/ifcgeom/IfcRegisterConvertCurve.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "IfcRegisterUndef.h" -#define CURVE(T) \ - if ( l->is(T::Class()) ) return convert((T*)l,r); -#include "IfcRegisterDef.h" - -#include "IfcRegister.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterConvertFace.h b/src/ifcgeom/IfcRegisterConvertFace.h deleted file mode 100644 index 04d524d315..0000000000 --- a/src/ifcgeom/IfcRegisterConvertFace.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "IfcRegisterUndef.h" -#define FACE(T) \ - if ( l->is(T::Class()) ) return convert((T*)l,r); -#include "IfcRegisterDef.h" - -#include "IfcRegister.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterConvertWire.h b/src/ifcgeom/IfcRegisterConvertWire.h deleted file mode 100644 index cd914b5c81..0000000000 --- a/src/ifcgeom/IfcRegisterConvertWire.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "IfcRegisterUndef.h" -#define WIRE(T) \ - if ( l->is(T::Class()) ) return convert((T*)l,r); -#include "IfcRegisterDef.h" - -#include "IfcRegister.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterCreateCache.h b/src/ifcgeom/IfcRegisterCreateCache.h deleted file mode 100644 index c1425d071f..0000000000 --- a/src/ifcgeom/IfcRegisterCreateCache.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "IfcRegisterUndef.h" -#define CLASS(T,V) \ - std::map T; -#include "IfcRegisterDef.h" - -#include "IfcRegister.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterPurgeCache.h b/src/ifcgeom/IfcRegisterPurgeCache.h deleted file mode 100644 index 1afa070943..0000000000 --- a/src/ifcgeom/IfcRegisterPurgeCache.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "IfcRegisterUndef.h" -#define CLASS(T,V) \ - T.clear(); -#include "IfcRegisterDef.h" - -#include "IfcRegister.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRepresentationShapeItem.h b/src/ifcgeom/IfcRepresentationShapeItem.h deleted file mode 100644 index 29d5ca264b..0000000000 --- a/src/ifcgeom/IfcRepresentationShapeItem.h +++ /dev/null @@ -1,53 +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 . * - * * - ********************************************************************************/ - -#ifndef IFCSHAPELIST_H -#define IFCSHAPELIST_H - -#include -#include - -#include "../ifcgeom/IfcGeomRenderStyles.h" - -namespace IfcGeom { - class IFC_GEOM_API IfcRepresentationShapeItem { - private: - gp_GTrsf placement; - TopoDS_Shape shape; - const SurfaceStyle* style; - public: - IfcRepresentationShapeItem(const gp_GTrsf& placement, const TopoDS_Shape& shape, const SurfaceStyle* style) - : placement(placement), shape(shape), style(style) {} - IfcRepresentationShapeItem(const gp_GTrsf& placement, const TopoDS_Shape& shape) - : placement(placement), shape(shape), style(0) {} - IfcRepresentationShapeItem(const TopoDS_Shape& shape, const SurfaceStyle* style) - : shape(shape), style(style) {} - IfcRepresentationShapeItem(const TopoDS_Shape& shape) - : shape(shape), style(0) {} - void append(const gp_GTrsf& trsf) { placement.Multiply(trsf); } - void prepend(const gp_GTrsf& trsf) { placement.PreMultiply(trsf); } - const TopoDS_Shape& Shape() const { return shape; } - const gp_GTrsf& Placement() const { return placement; } - bool hasStyle() const { return style != 0; } - const SurfaceStyle& Style() const { return *style; } - void setStyle(const SurfaceStyle* style) { this->style = style; } - }; - typedef std::vector IfcRepresentationShapeItems; -} -#endif diff --git a/src/ifcgeom/IfcRegister.cpp b/src/ifcgeom/kernels/opencascade/EntityMapping.cpp similarity index 76% rename from src/ifcgeom/IfcRegister.cpp rename to src/ifcgeom/kernels/opencascade/EntityMapping.cpp index ba119c12bc..a04bc28e5d 100644 --- a/src/ifcgeom/IfcRegister.cpp +++ b/src/ifcgeom/kernels/opencascade/EntityMapping.cpp @@ -17,33 +17,36 @@ * * ********************************************************************************/ -#include "IfcGeom.h" -#include "IfcGeomShapeType.h" +#include "../../../ifcgeom/IfcGeomShapeType.h" +#include "../../../ifcgeom/IfcGeom.h" + +#include "OpenCascadeKernel.h" +#include "OpenCascadeConversionResult.h" using namespace IfcSchema; using namespace IfcUtil; -bool IfcGeom::Kernel::convert_shapes(const IfcBaseClass* l, IfcRepresentationShapeItems& r) { +bool IfcGeom::OpenCascadeKernel::convert_shapes(const IfcBaseClass* l, ConversionResults& r) { if (shape_type(l) != ST_SHAPELIST) { TopoDS_Shape shp; if (convert_shape(l, shp)) { - r.push_back(IfcGeom::IfcRepresentationShapeItem(shp, get_style(l->as()))); + r.push_back(IfcGeom::ConversionResult(new OpenCascadeShape(shp), get_style(l->as()))); return true; } return false; } -#include "IfcRegisterConvertShapes.h" +#include "EntityMappingShapes.h" Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); return false; } -IfcGeom::ShapeType IfcGeom::Kernel::shape_type(const IfcBaseClass* l) { -#include "IfcRegisterShapeType.h" +IfcGeom::ShapeType IfcGeom::OpenCascadeKernel::shape_type(const IfcBaseClass* l) { +#include "EntityMappingShapeType.h" return ST_OTHER; } -bool IfcGeom::Kernel::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) { +bool IfcGeom::OpenCascadeKernel::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) { const unsigned int id = l->entity->id(); bool success = false; bool processed = false; @@ -60,10 +63,10 @@ bool IfcGeom::Kernel::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) { ignored = (!include_solids_and_surfaces && (st == ST_SHAPE || st == ST_FACE)) || (!include_curves && (st == ST_WIRE || st == ST_CURVE)); if (st == ST_SHAPELIST) { processed = true; - IfcRepresentationShapeItems items; + ConversionResults items; success = convert_shapes(l, items) && flatten_shape_list(items, r, false); } else if (st == ST_SHAPE && include_solids_and_surfaces) { -#include "IfcRegisterConvertShape.h" +#include "EntityMappingShape.h" } else if (st == ST_FACE && include_solids_and_surfaces) { processed = true; success = convert_face(l, r); @@ -99,24 +102,24 @@ bool IfcGeom::Kernel::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) { return success; } -bool IfcGeom::Kernel::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) { -#include "IfcRegisterConvertWire.h" +bool IfcGeom::OpenCascadeKernel::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) { +#include "EntityMappingWire.h" Handle(Geom_Curve) curve; - if (IfcGeom::Kernel::convert_curve(l, curve)) { - return IfcGeom::Kernel::convert_curve_to_wire(curve, r); + if (convert_curve(l, curve)) { + return convert_curve_to_wire(curve, r); } Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); return false; } -bool IfcGeom::Kernel::convert_face(const IfcBaseClass* l, TopoDS_Shape& r) { -#include "IfcRegisterConvertFace.h" +bool IfcGeom::OpenCascadeKernel::convert_face(const IfcBaseClass* l, TopoDS_Shape& r) { +#include "EntityMappingFace.h" Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); return false; } -bool IfcGeom::Kernel::convert_curve(const IfcBaseClass* l, Handle(Geom_Curve)& r) { -#include "IfcRegisterConvertCurve.h" +bool IfcGeom::OpenCascadeKernel::convert_curve(const IfcBaseClass* l, Handle(Geom_Curve)& r) { +#include "EntityMappingCurve.h" Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); return false; } \ No newline at end of file diff --git a/src/ifcgeom/IfcRegister.h b/src/ifcgeom/kernels/opencascade/EntityMapping.h similarity index 98% rename from src/ifcgeom/IfcRegister.h rename to src/ifcgeom/kernels/opencascade/EntityMapping.h index 2e6f20297d..a892f4eadd 100644 --- a/src/ifcgeom/IfcRegister.h +++ b/src/ifcgeom/kernels/opencascade/EntityMapping.h @@ -38,8 +38,8 @@ #include #include -#include "../ifcparse/IfcUtil.h" -#include "../ifcparse/IfcParse.h" +#include "../../../ifcparse/IfcUtil.h" +#include "../../../ifcparse/IfcParse.h" SHAPES(IfcShellBasedSurfaceModel); SHAPES(IfcFaceBasedSurfaceModel); diff --git a/src/ifcgeom/kernels/opencascade/EntityMappingCreateCache.h b/src/ifcgeom/kernels/opencascade/EntityMappingCreateCache.h new file mode 100644 index 0000000000..274ecf5833 --- /dev/null +++ b/src/ifcgeom/kernels/opencascade/EntityMappingCreateCache.h @@ -0,0 +1,6 @@ +#include "EntityMappingUndefine.h" +#define CLASS(T,V) \ + std::map T; +#include "EntityMappingDefine.h" + +#include "EntityMapping.h" diff --git a/src/ifcgeom/kernels/opencascade/EntityMappingCurve.h b/src/ifcgeom/kernels/opencascade/EntityMappingCurve.h new file mode 100644 index 0000000000..3b2b139edb --- /dev/null +++ b/src/ifcgeom/kernels/opencascade/EntityMappingCurve.h @@ -0,0 +1,6 @@ +#include "EntityMappingUndefine.h" +#define CURVE(T) \ + if ( l->is(T::Class()) ) return convert((T*)l,r); +#include "EntityMappingDefine.h" + +#include "EntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterGeomHeader.h b/src/ifcgeom/kernels/opencascade/EntityMappingDeclaration.h similarity index 60% rename from src/ifcgeom/IfcRegisterGeomHeader.h rename to src/ifcgeom/kernels/opencascade/EntityMappingDeclaration.h index 9969d5e2db..abbf45b59c 100644 --- a/src/ifcgeom/IfcRegisterGeomHeader.h +++ b/src/ifcgeom/kernels/opencascade/EntityMappingDeclaration.h @@ -1,10 +1,10 @@ -#include "IfcRegisterUndef.h" +#include "EntityMappingUndefine.h" #define CLASS(T,V) bool convert(const IfcSchema::T* L, V& r); -#define SHAPES(T) CLASS(T,IfcRepresentationShapeItems) +#define SHAPES(T) CLASS(T,ConversionResults) #define SHAPE(T) CLASS(T,TopoDS_Shape) #define WIRE(T) CLASS(T,TopoDS_Wire) #define FACE(T) CLASS(T,TopoDS_Shape) #define CURVE(T) CLASS(T,Handle(Geom_Curve)) -#include "IfcRegisterDef.h" +#include "EntityMappingDefine.h" -#include "IfcRegister.h" \ No newline at end of file +#include "EntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterDef.h b/src/ifcgeom/kernels/opencascade/EntityMappingDefine.h similarity index 100% rename from src/ifcgeom/IfcRegisterDef.h rename to src/ifcgeom/kernels/opencascade/EntityMappingDefine.h diff --git a/src/ifcgeom/kernels/opencascade/EntityMappingFace.h b/src/ifcgeom/kernels/opencascade/EntityMappingFace.h new file mode 100644 index 0000000000..68917d90de --- /dev/null +++ b/src/ifcgeom/kernels/opencascade/EntityMappingFace.h @@ -0,0 +1,6 @@ +#include "EntityMappingUndefine.h" +#define FACE(T) \ + if ( l->is(T::Class()) ) return convert((T*)l,r); +#include "EntityMappingDefine.h" + +#include "EntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/kernels/opencascade/EntityMappingPurgeCache.h b/src/ifcgeom/kernels/opencascade/EntityMappingPurgeCache.h new file mode 100644 index 0000000000..19164b2847 --- /dev/null +++ b/src/ifcgeom/kernels/opencascade/EntityMappingPurgeCache.h @@ -0,0 +1,6 @@ +#include "EntityMappingUndefine.h" +#define CLASS(T,V) \ + T.clear(); +#include "EntityMappingDefine.h" + +#include "EntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterConvertShape.h b/src/ifcgeom/kernels/opencascade/EntityMappingShape.h similarity index 88% rename from src/ifcgeom/IfcRegisterConvertShape.h rename to src/ifcgeom/kernels/opencascade/EntityMappingShape.h index 81a2703ee0..76d742dca2 100644 --- a/src/ifcgeom/IfcRegisterConvertShape.h +++ b/src/ifcgeom/kernels/opencascade/EntityMappingShape.h @@ -1,4 +1,4 @@ -#include "IfcRegisterUndef.h" +#include "EntityMappingUndefine.h" #define SHAPE(T) \ if ( !processed && l->is(T::Class()) ) { \ processed = true; \ @@ -21,6 +21,6 @@ return false; \ } \ } -#include "IfcRegisterDef.h" +#include "EntityMappingDefine.h" -#include "IfcRegister.h" \ No newline at end of file +#include "EntityMapping.h" \ No newline at end of file diff --git a/src/ifcgeom/IfcRegisterShapeType.h b/src/ifcgeom/kernels/opencascade/EntityMappingShapeType.h similarity index 76% rename from src/ifcgeom/IfcRegisterShapeType.h rename to src/ifcgeom/kernels/opencascade/EntityMappingShapeType.h index d11d64c9b0..92b553559e 100644 --- a/src/ifcgeom/IfcRegisterShapeType.h +++ b/src/ifcgeom/kernels/opencascade/EntityMappingShapeType.h @@ -1,4 +1,4 @@ -#include "IfcRegisterUndef.h" +#include "EntityMappingUndefine.h" #define SHAPES(T) \ if ( l->is(T::Class()) ) return ST_SHAPELIST; #define SHAPE(T) \ @@ -9,6 +9,6 @@ if ( l->is(T::Class()) ) return ST_FACE; #define CURVE(T) \ if ( l->is(T::Class()) ) return ST_CURVE; -#include "IfcRegisterDef.h" +#include "EntityMappingDefine.h" -#include "IfcRegister.h" \ No newline at end of file +#include "EntityMapping.h" diff --git a/src/ifcgeom/IfcRegisterConvertShapes.h b/src/ifcgeom/kernels/opencascade/EntityMappingShapes.h similarity index 84% rename from src/ifcgeom/IfcRegisterConvertShapes.h rename to src/ifcgeom/kernels/opencascade/EntityMappingShapes.h index 9f61849ba6..be302d5475 100644 --- a/src/ifcgeom/IfcRegisterConvertShapes.h +++ b/src/ifcgeom/kernels/opencascade/EntityMappingShapes.h @@ -1,4 +1,4 @@ -#include "IfcRegisterUndef.h" +#include "EntityMappingUndefine.h" #define SHAPES(T) \ if ( l->is(T::Class()) ) { \ try { \ @@ -13,6 +13,6 @@ } \ return false; \ } -#include "IfcRegisterDef.h" +#include "EntityMappingDefine.h" -#include "IfcRegister.h" \ No newline at end of file +#include "EntityMapping.h" diff --git a/src/ifcgeom/IfcRegisterUndef.h b/src/ifcgeom/kernels/opencascade/EntityMappingUndefine.h similarity index 100% rename from src/ifcgeom/IfcRegisterUndef.h rename to src/ifcgeom/kernels/opencascade/EntityMappingUndefine.h diff --git a/src/ifcgeom/kernels/opencascade/EntityMappingWire.h b/src/ifcgeom/kernels/opencascade/EntityMappingWire.h new file mode 100644 index 0000000000..77ffc2394e --- /dev/null +++ b/src/ifcgeom/kernels/opencascade/EntityMappingWire.h @@ -0,0 +1,6 @@ +#include "EntityMappingUndefine.h" +#define WIRE(T) \ + if ( l->is(T::Class()) ) return convert((T*)l,r); +#include "EntityMappingDefine.h" + +#include "EntityMapping.h" diff --git a/src/ifcgeom/IfcGeomCurves.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomCurves.cpp similarity index 90% rename from src/ifcgeom/IfcGeomCurves.cpp rename to src/ifcgeom/kernels/opencascade/IfcGeomCurves.cpp index 76f36f6e15..b4aaf97612 100644 --- a/src/ifcgeom/IfcGeomCurves.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomCurves.cpp @@ -19,7 +19,7 @@ /******************************************************************************** * * - * Implementations of the various conversion functions defined in IfcRegister.h * + * Implementations of the various conversion functions defined in EntityMapping.h * * * ********************************************************************************/ @@ -81,9 +81,10 @@ #include #endif -#include "../ifcgeom/IfcGeom.h" +#include "../../../ifcgeom/IfcGeom.h" +#include "OpenCascadeKernel.h" -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircle* l, Handle(Geom_Curve)& curve) { +bool IfcGeom::OpenCascadeKernel::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); @@ -92,17 +93,17 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircle* l, Handle(Geom_Curve)& gp_Trsf trsf; IfcSchema::IfcAxis2Placement* placement = l->Position(); if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { - IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); + IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); } else { gp_Trsf2d trsf2d; - IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d); + IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d); trsf = trsf2d; } gp_Ax2 ax = gp_Ax2().Transformed(trsf); curve = new Geom_Circle(ax, r); return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcEllipse* l, Handle(Geom_Curve)& curve) { +bool IfcGeom::OpenCascadeKernel::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) { @@ -132,7 +133,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEllipse* l, Handle(Geom_Curve) curve = new Geom_Ellipse(ax, x, y); return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcLine* l, Handle(Geom_Curve)& curve) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcLine* l, Handle(Geom_Curve)& curve) { gp_Pnt pnt;gp_Vec vec; convert(l->Pnt(),pnt); convert(l->Dir(),vec); @@ -142,7 +143,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcLine* l, Handle(Geom_Curve)& c } #ifdef USE_IFC4 -bool IfcGeom::Kernel::convert(const IfcSchema::IfcBSplineCurveWithKnots* l, Handle(Geom_Curve)& curve) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcBSplineCurveWithKnots* l, Handle(Geom_Curve)& curve) { const bool is_rational = l->is(IfcSchema::Type::IfcRationalBSplineCurveWithKnots); diff --git a/src/ifcgeom/IfcGeomFaces.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomFaces.cpp similarity index 90% rename from src/ifcgeom/IfcGeomFaces.cpp rename to src/ifcgeom/kernels/opencascade/IfcGeomFaces.cpp index d937848433..22e59c2fff 100644 --- a/src/ifcgeom/IfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomFaces.cpp @@ -19,7 +19,7 @@ /******************************************************************************** * * - * Implementations of the various conversion functions defined in IfcRegister.h * + * Implementations of the various conversion functions defined in EntityMapping.h * * * ********************************************************************************/ @@ -101,9 +101,10 @@ #include #endif -#include "../ifcgeom/IfcGeom.h" +#include "../../../ifcgeom/IfcGeom.h" +#include "OpenCascadeKernel.h" -bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds(); Handle(Geom_Surface) face_surface; @@ -347,7 +348,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { return success; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, TopoDS_Shape& face) { TopoDS_Wire wire; if ( ! convert_wire(l->OuterCurve(),wire) ) return false; @@ -357,7 +358,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, return success; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids* l, TopoDS_Shape& face) { TopoDS_Wire profile; if ( ! convert_wire(l->OuterCurve(),profile) ) return false; BRepBuilderAPI_MakeFace mf(profile); @@ -374,7 +375,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids* return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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); @@ -389,14 +390,14 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleProfileDef* l, TopoDS has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf2d); } double coords[8] = {-x,-y,x,-y,x,y,-x,y}; return profile_helper(4,coords,0,0,0,trsf2d,face); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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); @@ -412,7 +413,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf2d); } double coords[8] = {-x,-y, x,-y, x,y, -x,y}; @@ -421,7 +422,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, return profile_helper(4,coords,4,fillets,radii,trsf2d,face); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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); @@ -446,7 +447,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf2d); } double coords1[8] = {-x ,-y, x ,-y, x, y, -x, y }; @@ -475,7 +476,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrapeziumProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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); @@ -492,14 +493,14 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrapeziumProfileDef* l, TopoDS has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf2d); } double coords[8] = {-x1,-y, x1,-y, dx+w-x1,y, dx-x1,y}; return profile_helper(4,coords,0,0,0,trsf2d,face); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcIShapeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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); @@ -537,7 +538,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcIShapeProfileDef* l, TopoDS_Sh has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::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}; @@ -546,7 +547,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcIShapeProfileDef* l, TopoDS_Sh return profile_helper(12,coords,(doFillet1||doFillet2) ? 4 : 0,fillets,radii,trsf2d,face); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcZShapeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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); @@ -576,7 +577,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcZShapeProfileDef* l, TopoDS_Sh has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::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}; @@ -585,7 +586,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcZShapeProfileDef* l, TopoDS_Sh return profile_helper(8,coords,(doFillet || doEdgeFillet) ? 4 : 0,fillets,radii,trsf2d,face); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCShapeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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); @@ -609,7 +610,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCShapeProfileDef* l, TopoDS_Sh has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::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}; @@ -618,7 +619,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCShapeProfileDef* l, TopoDS_Sh return profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcLShapeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcLShapeProfileDef* l, TopoDS_Shape& face) { const bool hasSlope = l->hasLegSlope(); const bool doEdgeFillet = l->hasEdgeRadius(); const bool doFillet = l->hasFilletRadius(); @@ -684,7 +685,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcLShapeProfileDef* l, TopoDS_Sh has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf2d); } double coords[12] = {-x,-y, x,-y, x,-y+d-dy1, xx, xy, -x+d-dx1,y, -x,y}; @@ -693,7 +694,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcLShapeProfileDef* l, TopoDS_Sh return profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcUShapeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcUShapeProfileDef* l, TopoDS_Shape& face) { const bool doEdgeFillet = l->hasEdgeRadius(); const bool doFillet = l->hasFilletRadius(); const bool hasSlope = l->hasFlangeSlope(); @@ -732,7 +733,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcUShapeProfileDef* l, TopoDS_Sh has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::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}; @@ -741,7 +742,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcUShapeProfileDef* l, TopoDS_Sh return profile_helper(8, coords, (doFillet || doEdgeFillet) ? 4 : 0, fillets, radii, trsf2d, face); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcTShapeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcTShapeProfileDef* l, TopoDS_Shape& face) { const bool doFlangeEdgeFillet = l->hasFlangeEdgeRadius(); const bool doWebEdgeFillet = l->hasWebEdgeRadius(); const bool doFillet = l->hasFilletRadius(); @@ -821,7 +822,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcTShapeProfileDef* l, TopoDS_Sh has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::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}; @@ -830,7 +831,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcTShapeProfileDef* l, TopoDS_Sh return profile_helper(8, coords, (doFillet || doWebEdgeFillet || doFlangeEdgeFillet) ? 6 : 0, fillets, radii, trsf2d, face); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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); @@ -843,7 +844,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleProfileDef* l, TopoDS_Sh has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf2d); } gp_Ax2 ax = gp_Ax2().Transformed(trsf2d); @@ -860,7 +861,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleProfileDef* l, TopoDS_Sh return success; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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); @@ -875,7 +876,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, Top has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf2d); } gp_Ax2 ax = gp_Ax2().Transformed(trsf2d); @@ -896,7 +897,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, Top return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcEllipseProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcEllipseProfileDef* l, TopoDS_Shape& face) { double rx = l->SemiAxis1() * getValue(GV_LENGTH_UNIT); double ry = l->SemiAxis2() * getValue(GV_LENGTH_UNIT); @@ -913,7 +914,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEllipseProfileDef* l, TopoDS_S has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf2d); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf2d); } gp_Ax2 ax = gp_Ax2(); @@ -934,7 +935,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEllipseProfileDef* l, TopoDS_S return success; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCenterLineProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcCenterLineProfileDef* l, TopoDS_Shape& face) { const double d = l->Thickness() * getValue(GV_LENGTH_UNIT) / 2.; TopoDS_Wire wire; @@ -983,7 +984,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCenterLineProfileDef* l, TopoD return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcCompositeProfileDef* l, TopoDS_Shape& face) { // BRepBuilderAPI_MakeFace mf; TopoDS_Compound compound; @@ -1013,10 +1014,10 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeProfileDef* l, TopoDS return !face.IsNull(); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcDerivedProfileDef* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcDerivedProfileDef* l, TopoDS_Shape& face) { TopoDS_Face f; gp_Trsf2d trsf2d; - if (convert_face(l->ParentProfile(), f) && IfcGeom::Kernel::convert(l->Operator(), trsf2d)) { + if (convert_face(l->ParentProfile(), f) && IfcGeom::OpenCascadeKernel::convert(l->Operator(), trsf2d)) { gp_Trsf trsf = trsf2d; face = TopoDS::Face(BRepBuilderAPI_Transform(f, trsf)); return true; @@ -1025,7 +1026,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcDerivedProfileDef* l, TopoDS_S } } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcPlane* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcPlane* l, TopoDS_Shape& face) { gp_Pln pln; convert(l, pln); Handle_Geom_Surface surf = new Geom_Plane(pln); @@ -1039,7 +1040,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPlane* l, TopoDS_Shape& face) #ifdef USE_IFC4 -bool IfcGeom::Kernel::convert(const IfcSchema::IfcBSplineSurfaceWithKnots* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcBSplineSurfaceWithKnots* l, TopoDS_Shape& face) { boost::shared_ptr< IfcTemplatedEntityListList > cps = l->ControlPointsList(); std::vector uknots = l->UKnots(); std::vector vknots = l->VKnots(); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomFunctions.cpp similarity index 75% rename from src/ifcgeom/IfcGeomFunctions.cpp rename to src/ifcgeom/kernels/opencascade/IfcGeomFunctions.cpp index 2e6e501771..fc13aa24c4 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomFunctions.cpp @@ -130,9 +130,13 @@ #include -#include "../ifcparse/IfcSIPrefix.h" -#include "../ifcparse/IfcFile.h" -#include "../ifcgeom/IfcGeom.h" +#include "../../../ifcparse/IfcSIPrefix.h" +#include "../../../ifcparse/IfcFile.h" +#include "../../../ifcgeom/IfcGeom.h" + +#include "../opencascade/OpenCascadeConversionResult.h" + +#include "OpenCascadeKernel.h" #if OCC_VERSION_HEX < 0x60900 #ifdef _MSC_VER @@ -142,7 +146,7 @@ #endif #endif -bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) { TopTools_ListOfShape face_list; TopExp_Explorer exp(compound, TopAbs_FACE); for (; exp.More(); exp.Next()) { @@ -157,7 +161,7 @@ bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, T return create_solid_from_faces(face_list, shape); } -bool IfcGeom::Kernel::create_solid_from_faces(const TopTools_ListOfShape& face_list, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::create_solid_from_faces(const TopTools_ListOfShape& face_list, TopoDS_Shape& shape) { bool valid_shell = false; TopTools_ListIteratorOfListOfShape face_iterator; @@ -220,7 +224,7 @@ bool IfcGeom::Kernel::create_solid_from_faces(const TopTools_ListOfShape& face_l return valid_shell; } -bool IfcGeom::Kernel::is_compound(const TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::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; @@ -228,7 +232,7 @@ bool IfcGeom::Kernel::is_compound(const TopoDS_Shape& shape) { return has_compounds && has_faces && !has_solids && !has_shells; } -const TopoDS_Shape& IfcGeom::Kernel::ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid) { +const TopoDS_Shape& IfcGeom::OpenCascadeKernel::ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid) { const bool is_comp = is_compound(shape); if (!is_comp) { return solid = shape; @@ -246,14 +250,14 @@ const TopoDS_Shape& IfcGeom::Kernel::ensure_fit_for_subtraction(const TopoDS_Sha return solid; } -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) { +bool IfcGeom::OpenCascadeKernel::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, + const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) { // TODO: Refactor convert_openings() convert_openings_fast() and convert(IfcBooleanResult) to use // the same code base and conform to the same checks and logging messages. // Iterate over IfcOpeningElements - IfcGeom::IfcRepresentationShapeItems opening_shapes; + IfcGeom::ConversionResults opening_shapes; unsigned int last_size = 0; for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) { IfcSchema::IfcRelVoidsElement* v = *it; @@ -281,27 +285,34 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons const unsigned int current_size = (const unsigned int) opening_shapes.size(); for ( unsigned int i = last_size; i < current_size; ++ i ) { - opening_shapes[i].prepend(opening_trsf); + OpenCascadePlacement p((gp_GTrsf)opening_trsf); + opening_shapes[i].prepend(&p); } last_size = current_size; } } // Iterate over the shapes of the IfcProduct - for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { + for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { TopoDS_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(); - if ( entity_shape_gtrsf.Form() == gp_Other ) { - Logger::Message(Logger::LOG_WARNING, "Applying non uniform transformation to:", entity->entity); + const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*)it3->Shape(),entity_shape_solid); + const OpenCascadePlacement* entity_shape_gtrsf = (OpenCascadePlacement*) it3->Placement(); + + TopoDS_Shape entity_shape; + if (entity_shape_gtrsf != 0) { + if (entity_shape_gtrsf->trsf().Form() == gp_Other) { + Logger::Message(Logger::LOG_WARNING, "Applying non uniform transformation to:", entity->entity); + } + entity_shape = apply_transformation(entity_shape_unlocated, entity_shape_gtrsf->trsf()); + } else { + entity_shape = entity_shape_unlocated; } - TopoDS_Shape entity_shape = apply_transformation(entity_shape_unlocated, entity_shape_gtrsf); // Iterate over the shapes of the IfcOpeningElements - for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) { + for ( IfcGeom::ConversionResults::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) { TopoDS_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(); + const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*)it4->Shape(),opening_shape_solid); + const gp_GTrsf& opening_shape_gtrsf = *(OpenCascadePlacement*)it4->Placement(); if ( opening_shape_gtrsf.Form() == gp_Other ) { Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to opening of:",entity->entity); } @@ -409,15 +420,15 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons } } - cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(entity_shape, &it3->Style())); + cut_shapes.push_back(IfcGeom::ConversionResult(new OpenCascadeShape(entity_shape), &it3->Style())); } return true; } #if OCC_VERSION_HEX < 0x60900 -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) { +bool IfcGeom::OpenCascadeKernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, + const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) { // Create a compound of all opening shapes in order to speed up the boolean operations TopoDS_Compound opening_compound; @@ -444,16 +455,16 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, IfcSchema::IfcProductRepresentation* prodrep = fes->Representation(); IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations(); - IfcGeom::IfcRepresentationShapeItems opening_shapes; + IfcGeom::ConversionResults opening_shapes; for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) { convert_shapes(*it2,opening_shapes); } for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) { - gp_GTrsf gtrsf = opening_shapes[i].Placement(); + gp_GTrsf gtrsf = *(OpenCascadePlacement*) opening_shapes[i].Placement(); gtrsf.PreMultiply(opening_trsf); - TopoDS_Shape opening_shape = apply_transformation(opening_shapes[i].Shape(), gtrsf); + TopoDS_Shape opening_shape = apply_transformation(*(OpenCascadeShape*)opening_shapes[i].Shape(), gtrsf); builder.Add(opening_compound, opening_shape); } @@ -461,10 +472,10 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, } // Iterate over the shapes of the IfcProduct - for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { + for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { TopoDS_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(); + const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*)it3->Shape(),entity_shape_solid); + const gp_GTrsf& entity_shape_gtrsf = *(OpenCascadePlacement*)it3->Placement(); if (entity_shape_gtrsf.Form() == gp_Other) { Logger::Message(Logger::LOG_WARNING, "Applying non uniform transformation to:", entity->entity); } @@ -479,7 +490,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, BRepCheck_Analyzer analyser(brep_cut_result); is_valid = analyser.IsValid() != 0; if ( is_valid ) { - cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(brep_cut_result, &it3->Style())); + cut_shapes.push_back(IfcGeom::ConversionResult(new OpenCascadeShape(brep_cut_result), &it3->Style())); } } if ( !is_valid ) { @@ -494,8 +505,8 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, return true; } #else -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) { +bool IfcGeom::OpenCascadeKernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, + const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) { TopTools_ListOfShape opening_shapelist; @@ -519,16 +530,16 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, IfcSchema::IfcProductRepresentation* prodrep = fes->Representation(); IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations(); - IfcGeom::IfcRepresentationShapeItems opening_shapes; + IfcGeom::ConversionResults opening_shapes; for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) { convert_shapes(*it2,opening_shapes); } for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) { - gp_GTrsf gtrsf = opening_shapes[i].Placement(); + gp_GTrsf gtrsf = *(OpenCascadePlacement*)opening_shapes[i].Placement(); gtrsf.PreMultiply(opening_trsf); - TopoDS_Shape opening_shape = apply_transformation(opening_shapes[i].Shape(), gtrsf); + TopoDS_Shape opening_shape = apply_transformation(*(OpenCascadeShape*)opening_shapes[i].Shape(), gtrsf); opening_shapelist.Append(opening_shape); } @@ -536,10 +547,10 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, } // Iterate over the shapes of the IfcProduct - for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { + for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { TopoDS_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(); + const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*)it3->Shape(),entity_shape_solid); + const gp_GTrsf& entity_shape_gtrsf = *(OpenCascadePlacement*)it3->Placement(); if (entity_shape_gtrsf.Form() == gp_Other) { Logger::Message(Logger::LOG_WARNING, "Applying non uniform transformation to:", entity->entity); } @@ -560,7 +571,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, BRepCheck_Analyzer analyser(brep_cut_result); is_valid = analyser.IsValid() != 0; if ( is_valid ) { - cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(brep_cut_result, &it3->Style())); + cut_shapes.push_back(IfcGeom::ConversionResult(new OpenCascadeShape(brep_cut_result), &it3->Style())); } } if ( !is_valid ) { @@ -576,7 +587,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, } #endif -bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) { +bool IfcGeom::OpenCascadeKernel::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 ) { @@ -591,14 +602,14 @@ bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& return true; } -bool IfcGeom::Kernel::convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire) { +bool IfcGeom::OpenCascadeKernel::convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire) { try { wire = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(curve)); } catch(...) { return false; } return true; } -bool IfcGeom::Kernel::profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Shape& face_shape) { +bool IfcGeom::OpenCascadeKernel::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 ++ ) { @@ -634,17 +645,17 @@ bool IfcGeom::Kernel::profile_helper(int numVerts, double* verts, int numFillets delete[] vertices; return true; } -double IfcGeom::Kernel::shape_volume(const TopoDS_Shape& s) { +double IfcGeom::OpenCascadeKernel::shape_volume(const TopoDS_Shape& s) { GProp_GProps prop; BRepGProp::VolumeProperties(s, prop); return prop.Mass(); } -double IfcGeom::Kernel::face_area(const TopoDS_Face& f) { +double IfcGeom::OpenCascadeKernel::face_area(const TopoDS_Face& f) { GProp_GProps prop; BRepGProp::SurfaceProperties(f,prop); return prop.Mass(); } -bool IfcGeom::Kernel::is_convex(const TopoDS_Wire& wire) { +bool IfcGeom::OpenCascadeKernel::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); @@ -690,11 +701,11 @@ bool IfcGeom::Kernel::is_convex(const TopoDS_Wire& wire) { } return true; } -TopoDS_Shape IfcGeom::Kernel::halfspace_from_plane(const gp_Pln& pln,const gp_Pnt& cent) { +TopoDS_Shape IfcGeom::OpenCascadeKernel::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::Kernel::plane_from_face(const TopoDS_Face& face) { +gp_Pln IfcGeom::OpenCascadeKernel::plane_from_face(const TopoDS_Face& face) { BRepGProp_Face prop(face); Standard_Real u1,u2,v1,v2; prop.Bounds(u1,u2,v1,v2); @@ -705,7 +716,7 @@ gp_Pln IfcGeom::Kernel::plane_from_face(const TopoDS_Face& face) { prop.Normal(u,v,p,n); return gp_Pln(p,n); } -gp_Pnt IfcGeom::Kernel::point_above_plane(const gp_Pln& pln, bool agree) { +gp_Pnt IfcGeom::OpenCascadeKernel::point_above_plane(const gp_Pln& pln, bool agree) { if ( agree ) { return pln.Location().Translated(pln.Axis().Direction()); } else { @@ -713,73 +724,11 @@ gp_Pnt IfcGeom::Kernel::point_above_plane(const gp_Pln& pln, bool agree) { } } -void IfcGeom::Kernel::apply_tolerance(TopoDS_Shape& s, double t) { +void IfcGeom::OpenCascadeKernel::apply_tolerance(TopoDS_Shape& s, double t) { ShapeFix_ShapeTolerance tol; tol.SetTolerance(s, t); } -void IfcGeom::Kernel::setValue(GeomValue var, double value) { - switch (var) { - case GV_DEFLECTION_TOLERANCE: - deflection_tolerance = value; - break; - case GV_WIRE_CREATION_TOLERANCE: - wire_creation_tolerance = value; - break; - case GV_POINT_EQUALITY_TOLERANCE: - point_equality_tolerance = value; - break; - case GV_MAX_FACES_TO_SEW: - max_faces_to_sew = value; - break; - case GV_LENGTH_UNIT: - ifc_length_unit = value; - break; - case GV_PLANEANGLE_UNIT: - ifc_planeangle_unit = value; - break; - case GV_PRECISION: - modelling_precision = value; - break; - case GV_DIMENSIONALITY: - dimensionality = value; - break; - default: - assert(!"never reach here"); - } -} - -double IfcGeom::Kernel::getValue(GeomValue var) const { - switch (var) { - case GV_DEFLECTION_TOLERANCE: - return deflection_tolerance; - case GV_WIRE_CREATION_TOLERANCE: - return wire_creation_tolerance; - case GV_MINIMAL_FACE_AREA: - // Considering a right-angled triangle, this about the smallest - // area you can obtain without the vertices being confused. - return modelling_precision * modelling_precision / 2.; - case GV_POINT_EQUALITY_TOLERANCE: - return point_equality_tolerance; - case GV_MAX_FACES_TO_SEW: - return max_faces_to_sew; - case GV_LENGTH_UNIT: - return ifc_length_unit; - break; - case GV_PLANEANGLE_UNIT: - return ifc_planeangle_unit; - break; - case GV_PRECISION: - return modelling_precision; - break; - case GV_DIMENSIONALITY: - return dimensionality; - break; - } - assert(!"never reach here"); - return 0; -} - // Returns the vertex part of an TopoDS_Edge edge that is not TopoDS_Vertex vertex TopoDS_Vertex find_other(const TopoDS_Edge& edge, const TopoDS_Vertex& vertex) { TopExp_Explorer exp(edge, TopAbs_VERTEX); @@ -805,7 +754,7 @@ TopoDS_Edge find_next(const TopTools_IndexedMapOfShape& edge_set, const TopTools return TopoDS_Edge(); } -bool IfcGeom::Kernel::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) { BRepOffsetAPI_Sewing sew; sew.Add(shape); @@ -886,22 +835,22 @@ bool IfcGeom::Kernel::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& sha return true; } -bool IfcGeom::Kernel::flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& shapes, TopoDS_Shape& result, bool fuse) { +bool IfcGeom::OpenCascadeKernel::flatten_shape_list(const IfcGeom::ConversionResults& shapes, TopoDS_Shape& result, bool fuse) { TopoDS_Compound compound; BRep_Builder builder; builder.MakeCompound(compound); result = TopoDS_Shape(); - for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) { + for ( IfcGeom::ConversionResults::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) { TopoDS_Shape merged; - const TopoDS_Shape& s = it->Shape(); + const TopoDS_Shape& s = *(OpenCascadeShape*)it->Shape(); if (fuse) { ensure_fit_for_subtraction(s, merged); } else { merged = s; } - const gp_GTrsf& trsf = it->Placement(); + const gp_GTrsf& trsf = *(OpenCascadePlacement*)it->Placement(); const TopoDS_Shape moved_shape = apply_transformation(merged, trsf); if (shapes.size() == 1) { @@ -947,7 +896,7 @@ bool IfcGeom::Kernel::flatten_shape_list(const IfcGeom::IfcRepresentationShapeIt return success; } -void IfcGeom::Kernel::remove_duplicate_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol) { +void IfcGeom::OpenCascadeKernel::remove_duplicate_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol) { if (tol <= 0.) tol = getValue(GV_PRECISION); tol *= tol; @@ -971,7 +920,7 @@ void IfcGeom::Kernel::remove_duplicate_points_from_loop(TColgp_SequenceOfPnt& po } } -void IfcGeom::Kernel::remove_collinear_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol) { +void IfcGeom::OpenCascadeKernel::remove_collinear_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol) { if (tol <= 0.) tol = getValue(GV_PRECISION); const int start = closed ? 1 : 2; const int end = polygon.Length() - (closed ? 0 : 1); @@ -996,7 +945,7 @@ void IfcGeom::Kernel::remove_collinear_points_from_loop(TColgp_SequenceOfPnt& po } } -bool IfcGeom::Kernel::wire_to_sequence_of_point(const TopoDS_Wire& w, TColgp_SequenceOfPnt& p) { +bool IfcGeom::OpenCascadeKernel::wire_to_sequence_of_point(const TopoDS_Wire& w, TColgp_SequenceOfPnt& p) { TopExp_Explorer exp(w, TopAbs_EDGE); for (; exp.More(); exp.Next()) { double a, b; @@ -1023,7 +972,7 @@ bool IfcGeom::Kernel::wire_to_sequence_of_point(const TopoDS_Wire& w, TColgp_Seq return true; } -void IfcGeom::Kernel::sequence_of_point_to_wire(const TColgp_SequenceOfPnt& p, TopoDS_Wire& w, bool close) { +void IfcGeom::OpenCascadeKernel::sequence_of_point_to_wire(const TColgp_SequenceOfPnt& p, TopoDS_Wire& w, bool close) { BRepBuilderAPI_MakePolygon builder; for (int i = 1; i <= p.Length(); ++i) { builder.Add(p.Value(i)); @@ -1034,41 +983,11 @@ void IfcGeom::Kernel::sequence_of_point_to_wire(const TColgp_SequenceOfPnt& p, T w = builder.Wire(); } -IfcSchema::IfcRelVoidsElement::list::ptr IfcGeom::Kernel::find_openings(IfcSchema::IfcProduct* product) { - - IfcSchema::IfcRelVoidsElement::list::ptr openings(new IfcSchema::IfcRelVoidsElement::list); - if ( product->is(IfcSchema::Type::IfcElement) && !product->is(IfcSchema::Type::IfcOpeningElement) ) { - IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product; - openings = element->HasOpenings(); - } - - // Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements? - IfcSchema::IfcObjectDefinition* obdef = product->as(); - for (;;) { -#ifdef USE_IFC4 - IfcSchema::IfcRelAggregates::list::ptr decomposes = obdef->Decomposes(); -#else - IfcSchema::IfcRelDecomposes::list::ptr decomposes = obdef->Decomposes(); -#endif - if (decomposes->size() != 1) break; - IfcSchema::IfcObjectDefinition* rel_obdef = (*decomposes->begin())->RelatingObject(); - if ( rel_obdef->is(IfcSchema::Type::IfcElement) && !rel_obdef->is(IfcSchema::Type::IfcOpeningElement) ) { - IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)rel_obdef; - openings->push(element->HasOpenings()); - } - - obdef = rel_obdef; - } - - return openings; -} - -template -IfcGeom::BRepElement

* IfcGeom::Kernel::create_brep_for_representation_and_product( +IfcGeom::NativeElement* IfcGeom::OpenCascadeKernel::create_brep_for_representation_and_product( const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product) { - IfcGeom::Representation::BRep* shape; - IfcGeom::IfcRepresentationShapeItems shapes, shapes2; + IfcGeom::Representation::Native* shape; + IfcGeom::ConversionResults shapes, shapes2; if ( !convert_shapes(representation, shapes) ) { return 0; @@ -1121,7 +1040,7 @@ IfcGeom::BRepElement

* IfcGeom::Kernel::create_brep_for_representation_and_pro ElementSettings element_settings(settings, getValue(GV_LENGTH_UNIT), product_type); if (!settings.get(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && openings && openings->size()) { - IfcGeom::IfcRepresentationShapeItems opened_shapes; + IfcGeom::ConversionResults opened_shapes; try { #if OCC_VERSION_HEX < 0x60900 const bool faster_booleans = settings.get(IteratorSettings::FASTER_BOOLEANS); @@ -1141,20 +1060,20 @@ IfcGeom::BRepElement

* IfcGeom::Kernel::create_brep_for_representation_and_pro Logger::Message(Logger::LOG_ERROR,"Error processing openings for:",product->entity); } if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { - for ( IfcGeom::IfcRepresentationShapeItems::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) { - it->prepend(trsf); + for ( IfcGeom::ConversionResults::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) { + it->prepend(new OpenCascadePlacement(trsf)); } trsf = gp_Trsf(); } - shape = new IfcGeom::Representation::BRep(element_settings, representation->entity->id(), opened_shapes); + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), opened_shapes); } else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { - for ( IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++ it ) { - it->prepend(trsf); + for ( IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++ it ) { + it->prepend(new OpenCascadePlacement(trsf)); } trsf = gp_Trsf(); - shape = new IfcGeom::Representation::BRep(element_settings, representation->entity->id(), shapes); + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); } else { - shape = new IfcGeom::Representation::BRep(element_settings, representation->entity->id(), shapes); + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); } std::string context_string = ""; @@ -1164,22 +1083,21 @@ IfcGeom::BRepElement

* IfcGeom::Kernel::create_brep_for_representation_and_pro context_string = representation->ContextOfItems()->ContextType(); } - return new BRepElement

( + return new NativeElement( product->entity->id(), parent_id, name, product_type, guid, context_string, - trsf, - boost::shared_ptr(shape) + new OpenCascadePlacement(trsf), + boost::shared_ptr(shape) ); } -template -IfcGeom::BRepElement

* IfcGeom::Kernel::create_brep_for_processed_representation( +IfcGeom::NativeElement* IfcGeom::OpenCascadeKernel::create_brep_for_processed_representation( const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, - IfcGeom::BRepElement

* brep) + IfcGeom::NativeElement* brep) { int parent_id = -1; try { @@ -1206,138 +1124,19 @@ IfcGeom::BRepElement

* IfcGeom::Kernel::create_brep_for_processed_representati const std::string product_type = IfcSchema::Type::ToString(product->type()); - return new BRepElement

( + return new NativeElement( product->entity->id(), parent_id, name, product_type, guid, context_string, - trsf, + new OpenCascadePlacement(trsf), brep->geometry_pointer() ); } -IfcSchema::IfcObjectDefinition* IfcGeom::Kernel::get_decomposing_entity(IfcSchema::IfcProduct* product) { - IfcSchema::IfcObjectDefinition* parent = 0; - - // In case of an opening element, parent to the RelatingBuildingElement - if ( product->is(IfcSchema::Type::IfcOpeningElement ) ) { - IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)product; - IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements(); - if ( voids->size() ) { - IfcSchema::IfcRelVoidsElement* ifc_void = *voids->begin(); - parent = ifc_void->RelatingBuildingElement(); - } - } else if ( product->is(IfcSchema::Type::IfcElement ) ) { - IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)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 ( product == ifc_objectdef ) continue; - parent = ifc_objectdef; - } - } - // Else simply parent to the containing structure - if (!parent) { - IfcSchema::IfcRelContainedInSpatialStructure::list::ptr parents = element->ContainedInStructure(); - if ( parents->size() ) { - IfcSchema::IfcRelContainedInSpatialStructure* container = *parents->begin(); - parent = container->RelatingStructure(); - } - } - } - // Parent decompositions to the RelatingObject - if (!parent) { - IfcEntityList::ptr parents = product->entity->getInverse(IfcSchema::Type::IfcRelAggregates, -1); - parents->push(product->entity->getInverse(IfcSchema::Type::IfcRelNests, -1)); - 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 ( product == ifc_objectdef ) continue; - parent = ifc_objectdef; - } - } - return parent; -} - -template IFC_GEOM_API IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and_product( - const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product); -template IFC_GEOM_API IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and_product( - const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product); - -template IFC_GEOM_API IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_processed_representation( - const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::BRepElement* brep); -template IFC_GEOM_API IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_processed_representation( - const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::BRepElement* brep); - -std::pair IfcGeom::Kernel::initializeUnits(IfcSchema::IfcUnitAssignment* unit_assignment) { - // Set default units, set length to meters, angles to undefined - setValue(IfcGeom::Kernel::GV_LENGTH_UNIT, 1.0); - setValue(IfcGeom::Kernel::GV_PLANEANGLE_UNIT, -1.0); - - std::string unit_name = "METER"; - double unit_magnitude = 1.; - - try { - IfcEntityList::ptr units = unit_assignment->Units(); - if (!units || !units->size()) { - Logger::Message(Logger::LOG_ERROR, "No unit information found"); - } else { - for (IfcEntityList::it it = units->begin(); it != units->end(); ++it) { - IfcUtil::IfcBaseClass* base = *it; - if (base->is(IfcSchema::Type::IfcNamedUnit)) { - IfcSchema::IfcNamedUnit* named_unit = base->as(); - if (named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT || - named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT) - { - std::string current_unit_name; - const double current_unit_magnitude = IfcParse::get_SI_equivalent(named_unit); - if (current_unit_magnitude != 0.) { - if (named_unit->is(IfcSchema::Type::IfcConversionBasedUnit)) { - IfcSchema::IfcConversionBasedUnit* u = (IfcSchema::IfcConversionBasedUnit*)base; - current_unit_name = u->Name(); - } else if (named_unit->is(IfcSchema::Type::IfcSIUnit)) { - IfcSchema::IfcSIUnit* si_unit = named_unit->as(); - if (si_unit->hasPrefix()) { - current_unit_name = IfcSchema::IfcSIPrefix::ToString(si_unit->Prefix()) + unit_name; - } - current_unit_name += IfcSchema::IfcSIUnitName::ToString(si_unit->Name()); - } - if (named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT) { - unit_name = current_unit_name; - unit_magnitude = current_unit_magnitude; - setValue(IfcGeom::Kernel::GV_LENGTH_UNIT, current_unit_magnitude); - } else { - setValue(IfcGeom::Kernel::GV_PLANEANGLE_UNIT, current_unit_magnitude); - } - } - } - } - } - } - } catch (const IfcParse::IfcException& ex) { - std::stringstream ss; - ss << "Failed to determine unit information '" << ex.what() << "'"; - Logger::Message(Logger::LOG_ERROR, ss.str()); - } - - return std::pair(unit_name, unit_magnitude); -} - -bool IfcGeom::Kernel::convert_layerset(const IfcSchema::IfcProduct* product, std::vector& surfaces, std::vector& styles, std::vector& thicknesses) { +bool IfcGeom::OpenCascadeKernel::convert_layerset(const IfcSchema::IfcProduct* product, std::vector& surfaces, std::vector& styles, std::vector& thicknesses) { IfcSchema::IfcMaterialLayerSetUsage* usage = 0; Handle_Geom_Surface reference_surface; @@ -1363,9 +1162,9 @@ bool IfcGeom::Kernel::convert_layerset(const IfcSchema::IfcProduct* product, std return false; } - IfcRepresentationShapeItems axis_items; + ConversionResults axis_items; { - Kernel temp = *this; + OpenCascadeKernel temp = *this; temp.setValue(GV_DIMENSIONALITY, -1.); temp.convert_shapes(axis_representation, axis_items); } @@ -1465,7 +1264,7 @@ bool IfcGeom::Kernel::convert_layerset(const IfcSchema::IfcProduct* product, std return true; } -const Handle_Geom_Curve IfcGeom::Kernel::intersect(const Handle_Geom_Surface& a, const Handle_Geom_Surface& b) { +const Handle_Geom_Curve IfcGeom::OpenCascadeKernel::intersect(const Handle_Geom_Surface& a, const Handle_Geom_Surface& b) { GeomAPI_IntSS x(a, b, 1.e-7); if (x.IsDone() && x.NbLines() == 1) { return x.Line(1); @@ -1474,15 +1273,15 @@ const Handle_Geom_Curve IfcGeom::Kernel::intersect(const Handle_Geom_Surface& a, } } -const Handle_Geom_Curve IfcGeom::Kernel::intersect(const Handle_Geom_Surface& a, const TopoDS_Face& b) { +const Handle_Geom_Curve IfcGeom::OpenCascadeKernel::intersect(const Handle_Geom_Surface& a, const TopoDS_Face& b) { return intersect(a, BRep_Tool::Surface(b)); } -const Handle_Geom_Curve IfcGeom::Kernel::intersect(const TopoDS_Face& a, const Handle_Geom_Surface& b) { +const Handle_Geom_Curve IfcGeom::OpenCascadeKernel::intersect(const TopoDS_Face& a, const Handle_Geom_Surface& b) { return intersect(BRep_Tool::Surface(a), b); } -bool IfcGeom::Kernel::intersect(const Handle_Geom_Curve& a, const Handle_Geom_Surface& b, gp_Pnt& p) { +bool IfcGeom::OpenCascadeKernel::intersect(const Handle_Geom_Curve& a, const Handle_Geom_Surface& b, gp_Pnt& p) { GeomAPI_IntCS x(a, b); if (x.IsDone() && x.NbPoints() == 1) { p = x.Point(1); @@ -1492,11 +1291,11 @@ bool IfcGeom::Kernel::intersect(const Handle_Geom_Curve& a, const Handle_Geom_Su } } -bool IfcGeom::Kernel::intersect(const Handle_Geom_Curve& a, const TopoDS_Face& b, gp_Pnt &c) { +bool IfcGeom::OpenCascadeKernel::intersect(const Handle_Geom_Curve& a, const TopoDS_Face& b, gp_Pnt &c) { return intersect(a, BRep_Tool::Surface(b), c); } -bool IfcGeom::Kernel::intersect(const Handle_Geom_Curve& a, const TopoDS_Shape& b, std::vector& out) { +bool IfcGeom::OpenCascadeKernel::intersect(const Handle_Geom_Curve& a, const TopoDS_Shape& b, std::vector& out) { TopExp_Explorer exp(b, TopAbs_FACE); gp_Pnt p; for (; exp.More(); exp.Next()) { @@ -1507,7 +1306,7 @@ bool IfcGeom::Kernel::intersect(const Handle_Geom_Curve& a, const TopoDS_Shape& return !out.empty(); } -bool IfcGeom::Kernel::intersect(const Handle_Geom_Surface& a, const TopoDS_Shape& b, std::vector< std::pair >& out) { +bool IfcGeom::OpenCascadeKernel::intersect(const Handle_Geom_Surface& a, const TopoDS_Shape& b, std::vector< std::pair >& out) { TopExp_Explorer exp(b, TopAbs_FACE); for (; exp.More(); exp.Next()) { const TopoDS_Face& f = TopoDS::Face(exp.Current()); @@ -1520,7 +1319,7 @@ bool IfcGeom::Kernel::intersect(const Handle_Geom_Surface& a, const TopoDS_Shape return !out.empty(); } -bool IfcGeom::Kernel::closest(const gp_Pnt& a, const std::vector& b, gp_Pnt& c) { +bool IfcGeom::OpenCascadeKernel::closest(const gp_Pnt& a, const std::vector& b, gp_Pnt& c) { double minimal_distance = std::numeric_limits::infinity(); for (std::vector::const_iterator it = b.begin(); it != b.end(); ++it) { const double d = a.Distance(*it); @@ -1532,14 +1331,14 @@ bool IfcGeom::Kernel::closest(const gp_Pnt& a, const std::vector& b, gp_ return minimal_distance != std::numeric_limits::infinity(); } -bool IfcGeom::Kernel::project(const Handle_Geom_Curve& crv, const gp_Pnt& pt, gp_Pnt& p, double& u, double& d) { +bool IfcGeom::OpenCascadeKernel::project(const Handle_Geom_Curve& crv, const gp_Pnt& pt, gp_Pnt& p, double& u, double& d) { ShapeAnalysis_Curve sac; sac.Project(crv, pt, 1e-3, p, u, false); d = pt.Distance(p); return true; } -int IfcGeom::Kernel::count(const TopoDS_Shape& s, TopAbs_ShapeEnum t) { +int IfcGeom::OpenCascadeKernel::count(const TopoDS_Shape& s, TopAbs_ShapeEnum t) { int i = 0; TopExp_Explorer exp(s, t); for (; exp.More(); exp.Next()) { @@ -1548,22 +1347,22 @@ int IfcGeom::Kernel::count(const TopoDS_Shape& s, TopAbs_ShapeEnum t) { return i; } -bool IfcGeom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pnt& start, gp_Pnt& end) { +bool IfcGeom::OpenCascadeKernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pnt& start, gp_Pnt& end) { IfcSchema::IfcRepresentation* axis_representation = find_representation(wall, "Axis"); if (!axis_representation) { return false; } - IfcRepresentationShapeItems items; + ConversionResults items; { - Kernel temp = *this; + OpenCascadeKernel temp = *this; temp.setValue(GV_DIMENSIONALITY, -1.); temp.convert_shapes(axis_representation, items); } TopoDS_Vertex a, b; - for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) { - TopExp_Explorer exp(it->Shape(), TopAbs_VERTEX); + for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { + TopExp_Explorer exp(*(OpenCascadeShape*)it->Shape(), TopAbs_VERTEX); for (; exp.More(); exp.Next()) { b = TopoDS::Vertex(exp.Current()); if (a.IsNull()) { @@ -1582,7 +1381,7 @@ bool IfcGeom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pn return true; } -bool IfcGeom::Kernel::fold_layers(const IfcSchema::IfcWall* wall, const IfcRepresentationShapeItems& items, const std::vector& surfaces, const std::vector& thicknesses, std::vector< std::vector >& result) { +bool IfcGeom::OpenCascadeKernel::fold_layers(const IfcSchema::IfcWall* wall, const ConversionResults& items, const std::vector& surfaces, const std::vector& thicknesses, std::vector< std::vector >& result) { bool folds_made = false; IfcSchema::IfcRelConnectsPathElements::list::ptr connections(new IfcSchema::IfcRelConnectsPathElements::list); @@ -1725,9 +1524,9 @@ bool IfcGeom::Kernel::fold_layers(const IfcSchema::IfcWall* wall, const IfcRepre IfcSchema::IfcRepresentation* axis_representation = find_representation(other_wall, "Axis"); - IfcRepresentationShapeItems axis_items; + ConversionResults axis_items; { - Kernel temp = *this; + OpenCascadeKernel temp = *this; temp.setValue(GV_DIMENSIONALITY, -1.); temp.convert_shapes(axis_representation, axis_items); } @@ -1888,7 +1687,7 @@ bool IfcGeom::Kernel::fold_layers(const IfcSchema::IfcWall* wall, const IfcRepre return folds_made; } -bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& items, const std::vector< std::vector >& surfaces, const std::vector& styles, IfcRepresentationShapeItems& result) { +bool IfcGeom::OpenCascadeKernel::apply_folded_layerset(const ConversionResults& items, const std::vector< std::vector >& surfaces, const std::vector& styles, ConversionResults& result) { Bnd_Box bb; TopoDS_Shape input; flatten_shape_list(items, input, false); @@ -1968,11 +1767,11 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i } else if (shells.size() == 1) { - for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) { + for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { TopoDS_Shape a,b; - if (split_solid_by_shell(it->Shape(), shells[0], a, b)) { - result.push_back(IfcRepresentationShapeItem(it->Placement(), b, styles[0] ? styles[0] : &it->Style())); - result.push_back(IfcRepresentationShapeItem(it->Placement(), a, styles[1] ? styles[1] : &it->Style())); + if (split_solid_by_shell(*(OpenCascadeShape*)it->Shape(), shells[0], a, b)) { + result.push_back(ConversionResult(it->Placement(), new OpenCascadeShape(b), styles[0] ? styles[0] : &it->Style())); + result.push_back(ConversionResult(it->Placement(), new OpenCascadeShape(a), styles[1] ? styles[1] : &it->Style())); } else { continue; } @@ -1985,8 +1784,8 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i typedef std::vector< std::vector > temp_t; temp_t temp; - for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) { - const TopoDS_Shape& s = it->Shape(); + for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { + const TopoDS_Shape& s = *(OpenCascadeShape*)it->Shape(); TopoDS_Solid sld; ensure_fit_for_subtraction(s, sld); std::vector temp2; @@ -2008,13 +1807,13 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i } } - IfcRepresentationShapeItems::const_iterator it1 = items.begin(); + ConversionResults::const_iterator it1 = items.begin(); temp_t::const_iterator it2 = temp.begin(); for(; it1 != items.end(); ++it1, ++it2) { std::vector::const_iterator it4 = styles.begin(); for (temp_t::value_type::const_iterator it3 = it2->begin(); it3 != it2->end(); ++it3, ++it4) { - result.push_back(IfcRepresentationShapeItem(it1->Placement(), *it3, (*it4) ? (*it4) : &it1->Style())); + result.push_back(ConversionResult(it1->Placement(), new OpenCascadeShape(*it3), (*it4) ? (*it4) : &it1->Style())); } } @@ -2024,18 +1823,18 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i } -bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, const std::vector& surfaces, const std::vector& styles, IfcRepresentationShapeItems& result) { +bool IfcGeom::OpenCascadeKernel::apply_layerset(const ConversionResults& items, const std::vector& surfaces, const std::vector& styles, ConversionResults& result) { if (surfaces.size() < 3) { return false; } else if (surfaces.size() == 3) { - for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) { + for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { TopoDS_Shape a,b; - if (split_solid_by_surface(it->Shape(), surfaces[1], a, b)) { - result.push_back(IfcRepresentationShapeItem(it->Placement(), b, styles[0] ? styles[0] : &it->Style())); - result.push_back(IfcRepresentationShapeItem(it->Placement(), a, styles[1] ? styles[1] : &it->Style())); + if (split_solid_by_surface(*(OpenCascadeShape*)it->Shape(), surfaces[1], a, b)) { + result.push_back(ConversionResult(it->Placement(), new OpenCascadeShape(b), styles[0] ? styles[0] : &it->Style())); + result.push_back(ConversionResult(it->Placement(), new OpenCascadeShape(a), styles[1] ? styles[1] : &it->Style())); } else { continue; } @@ -2049,7 +1848,7 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c // Determine whether sequence of surfaces is consistent with surface normal, so that // layer operations are applied in the correct order. This seems to be always the case. Bnd_Box bb; - for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) { + for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { BRepBndLib::Add(it->Shape(), bb); } @@ -2077,9 +1876,9 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c typedef std::vector< std::vector > temp_t; temp_t temp; - for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) { + for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { // No transformation on purpose in order not interfere with layerset alignment - const TopoDS_Shape& s = it->Shape(); + const TopoDS_Shape& s = *(OpenCascadeShape*)it->Shape(); TopoDS_Solid sld; ensure_fit_for_subtraction(s, sld); std::vector temp2; @@ -2101,13 +1900,13 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c } } - IfcRepresentationShapeItems::const_iterator it1 = items.begin(); + ConversionResults::const_iterator it1 = items.begin(); temp_t::const_iterator it2 = temp.begin(); for(; it1 != items.end(); ++it1, ++it2) { std::vector::const_iterator it4 = styles.begin(); for (temp_t::value_type::const_iterator it3 = it2->begin(); it3 != it2->end(); ++it3, ++it4) { - result.push_back(IfcRepresentationShapeItem(it1->Placement(), *it3, (*it4) ? (*it4) : &it1->Style())); + result.push_back(ConversionResult(it1->Placement(), new OpenCascadeShape(*it3), (*it4) ? (*it4) : &it1->Style())); } } @@ -2115,19 +1914,7 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c } } -IfcSchema::IfcRepresentation* IfcGeom::Kernel::find_representation(const IfcSchema::IfcProduct* product, const std::string& identifier) { - if (!product->hasRepresentation()) return 0; - IfcSchema::IfcProductRepresentation* prod_rep = product->Representation(); - IfcSchema::IfcRepresentation::list::ptr reps = prod_rep->Representations(); - for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { - if ((**it).hasRepresentationIdentifier() && (**it).RepresentationIdentifier() == identifier) { - return *it; - } - } - return 0; -} - -bool IfcGeom::Kernel::split_solid_by_surface(const TopoDS_Shape& input, const Handle_Geom_Surface& surface, TopoDS_Shape& front, TopoDS_Shape& back) { +bool IfcGeom::OpenCascadeKernel::split_solid_by_surface(const TopoDS_Shape& input, const Handle_Geom_Surface& surface, TopoDS_Shape& front, TopoDS_Shape& back) { // Use an unbounded surface, that isolate part of the input shape, // to split this shape into two parts. Make sure that the addition // of the two result volumes matches that of the input. @@ -2148,7 +1935,7 @@ bool IfcGeom::Kernel::split_solid_by_surface(const TopoDS_Shape& input, const Ha return b; } -bool IfcGeom::Kernel::split_solid_by_shell(const TopoDS_Shape& input, const TopoDS_Shape& shell, TopoDS_Shape& front, TopoDS_Shape& back) { +bool IfcGeom::OpenCascadeKernel::split_solid_by_shell(const TopoDS_Shape& input, const TopoDS_Shape& shell, TopoDS_Shape& front, TopoDS_Shape& back) { // Use a shell, typically one or more connected faces, that isolate part // of the input shape, to split this shape into two parts. Make sure that // the addition of the two result volumes matches that of the input. @@ -2207,7 +1994,7 @@ bool IfcGeom::Kernel::split_solid_by_shell(const TopoDS_Shape& input, const Topo return ALMOST_THE_SAME(ab, a+b, 1.e-3); } -bool IfcGeom::Kernel::project(const Handle_Geom_Surface& srf, const TopoDS_Shape& shp, double& u1, double& v1, double& u2, double& v2, double widen) { +bool IfcGeom::OpenCascadeKernel::project(const Handle_Geom_Surface& srf, const TopoDS_Shape& shp, double& u1, double& v1, double& u2, double& v2, double widen) { ShapeAnalysis_Surface sas(srf); u1 = v1 = +std::numeric_limits::infinity(); @@ -2259,29 +2046,7 @@ bool IfcGeom::Kernel::project(const Handle_Geom_Surface& srf, const TopoDS_Shape return true; } -const IfcSchema::IfcRepresentationItem* IfcGeom::Kernel::find_item_carrying_style(const IfcSchema::IfcRepresentationItem* item) { - if (item->StyledByItem()->size()) { - return item; - } - - while (item->is(IfcSchema::Type::IfcBooleanClippingResult)) { - // All instantiations of IfcBooleanOperand (type of FirstOperand) are subtypes of - // IfcGeometricRepresentationItem - item = (IfcSchema::IfcGeometricRepresentationItem*) ((IfcSchema::IfcBooleanClippingResult*) item)->FirstOperand(); - if (item->StyledByItem()->size()) { - return item; - } - } - - // TODO: Ideally this would be done for other entities (such as IfcCsgSolid) as well. - // But neither are these very prevalent, nor does the current IfcOpenShell style - // mechanism enable to conveniently style subshapes, which would be necessary for - // distinctly styled union operands. - - return item; -} - -bool IfcGeom::Kernel::is_identity_transform(IfcUtil::IfcBaseClass* l) { +bool IfcGeom::OpenCascadeKernel::is_identity_transform(IfcUtil::IfcBaseClass* l) { IfcSchema::IfcAxis2Placement2D* ax2d; IfcSchema::IfcAxis2Placement3D* ax3d; @@ -2319,7 +2084,7 @@ bool IfcGeom::Kernel::is_identity_transform(IfcUtil::IfcBaseClass* l) { } } -bool IfcGeom::Kernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp_Pln& plane) { +bool IfcGeom::OpenCascadeKernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp_Pln& plane) { // Newell's Method is used for the normal calculation // as a simple edge cross product can give opposite results // for a concave face boundary. @@ -2369,7 +2134,7 @@ bool IfcGeom::Kernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp return true; } -bool IfcGeom::Kernel::flatten_wire(TopoDS_Wire& wire) { +bool IfcGeom::OpenCascadeKernel::flatten_wire(TopoDS_Wire& wire) { gp_Pln pln; if (!approximate_plane_through_wire(wire, pln)) { return false; @@ -2391,7 +2156,7 @@ bool IfcGeom::Kernel::flatten_wire(TopoDS_Wire& wire) { } -TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const gp_Trsf& t) { +TopoDS_Shape IfcGeom::OpenCascadeKernel::apply_transformation(const TopoDS_Shape& s, const gp_Trsf& t) { if (t.Form() == gp_Identity) { return s; } else { @@ -2404,7 +2169,7 @@ TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const } } -TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const gp_GTrsf& t) { +TopoDS_Shape IfcGeom::OpenCascadeKernel::apply_transformation(const TopoDS_Shape& s, const gp_GTrsf& t) { if (t.Form() == gp_Other) { return BRepBuilderAPI_GTransform(s, t, true); } else { diff --git a/src/ifcgeom/IfcGeomHelpers.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomHelpers.cpp similarity index 78% rename from src/ifcgeom/IfcGeomHelpers.cpp rename to src/ifcgeom/kernels/opencascade/IfcGeomHelpers.cpp index 29851a2627..9f22441f96 100644 --- a/src/ifcgeom/IfcGeomHelpers.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomHelpers.cpp @@ -19,7 +19,7 @@ /******************************************************************************** * * - * Implementations of the various conversion functions defined in IfcRegister.h * + * Implementations of the various conversion functions defined in EntityMapping.h * * * ********************************************************************************/ @@ -75,7 +75,8 @@ #include -#include "../ifcgeom/IfcGeom.h" +#include "../../../ifcgeom/IfcGeom.h" +#include "OpenCascadeKernel.h" // Helper functions (re)set gp_(G)Trsf(2d) forms explicitly to 'Identity' // so that it can be easily identified in the IfcMappedItem processing @@ -124,7 +125,7 @@ bool is_identity(const T& t, double tolerance) { return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianPoint* l, gp_Pnt& point) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcCartesianPoint* l, gp_Pnt& point) { IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point) std::vector xyz = l->Coordinates(); point = gp_Pnt( @@ -136,7 +137,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianPoint* l, gp_Pnt& poi return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcDirection* l, gp_Dir& dir) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcDirection* l, gp_Dir& dir) { IN_CACHE(IfcDirection,l,gp_Dir,dir) std::vector xyz = l->DirectionRatios(); dir = gp_Dir( @@ -148,22 +149,22 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcDirection* l, gp_Dir& dir) { return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcVector* l, gp_Vec& v) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcVector* l, gp_Vec& v) { IN_CACHE(IfcVector,l,gp_Vec,v) gp_Dir d; - IfcGeom::Kernel::convert(l->Orientation(),d); + IfcGeom::OpenCascadeKernel::convert(l->Orientation(),d); v = l->Magnitude() * getValue(GV_LENGTH_UNIT) * d; CACHE(IfcVector,l,v) return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement3D* l, gp_Trsf& trsf) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Location(),o); + IfcGeom::OpenCascadeKernel::convert(l->Location(),o); bool hasRef = l->hasRefDirection(); - if ( l->hasAxis() ) IfcGeom::Kernel::convert(l->Axis(),axis); - if ( hasRef ) IfcGeom::Kernel::convert(l->RefDirection(),refDirection); + if ( l->hasAxis() ) IfcGeom::OpenCascadeKernel::convert(l->Axis(),axis); + if ( hasRef ) IfcGeom::OpenCascadeKernel::convert(l->RefDirection(),refDirection); gp_Ax3 ax3; if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection); else ax3 = gp_Ax3(o,axis); @@ -176,26 +177,26 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement3D* l, gp_Trsf& return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis1Placement* l, gp_Ax1& ax) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Location(),o); - if ( l->hasAxis() ) IfcGeom::Kernel::convert(l->Axis(), axis); + IfcGeom::OpenCascadeKernel::convert(l->Location(),o); + if ( l->hasAxis() ) IfcGeom::OpenCascadeKernel::convert(l->Axis(), axis); ax = gp_Ax1(o, axis); CACHE(IfcAxis1Placement,l,ax) return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, gp_Trsf& trsf) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, gp_Trsf& trsf) { IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf) gp_Pnt origin; - IfcGeom::Kernel::convert(l->LocalOrigin(),origin); + IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::Kernel::convert(l->Axis2(),axis2); - if ( l->hasAxis3() ) IfcGeom::Kernel::convert(l->Axis3(),axis3); + if ( l->hasAxis1() ) IfcGeom::OpenCascadeKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::OpenCascadeKernel::convert(l->Axis2(),axis2); + if ( l->hasAxis3() ) IfcGeom::OpenCascadeKernel::convert(l->Axis3(),axis3); gp_Ax3 ax3 (origin,axis3,axis1); if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse(); @@ -212,16 +213,16 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperato return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator2D* l, gp_Trsf2d& trsf) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->LocalOrigin(),origin); - if ( l->hasAxis1() ) IfcGeom::Kernel::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::Kernel::convert(l->Axis2(),axis2); + IfcGeom::OpenCascadeKernel::convert(l->LocalOrigin(),origin); + if ( l->hasAxis1() ) IfcGeom::OpenCascadeKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::OpenCascadeKernel::convert(l->Axis2(),axis2); const gp_Pnt2d origin2d(origin.X(), origin.Y()); const gp_Dir2d axis12d(axis1.X(), axis1.Y()); @@ -251,17 +252,17 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperato return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* l, gp_GTrsf& gtrsf) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* l, gp_GTrsf& gtrsf) { IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf) gp_Trsf trsf; gp_Pnt origin; - IfcGeom::Kernel::convert(l->LocalOrigin(),origin); + IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::Kernel::convert(l->Axis2(),axis2); - if ( l->hasAxis3() ) IfcGeom::Kernel::convert(l->Axis3(),axis3); + if ( l->hasAxis1() ) IfcGeom::OpenCascadeKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::OpenCascadeKernel::convert(l->Axis2(),axis2); + if ( l->hasAxis3() ) IfcGeom::OpenCascadeKernel::convert(l->Axis3(),axis3); gp_Ax3 ax3 (origin,axis3,axis1); if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse(); trsf.SetTransformation(ax3); @@ -283,7 +284,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperato return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, gp_GTrsf2d& gtrsf) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, gp_GTrsf2d& gtrsf) { IN_CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gp_GTrsf2d,gtrsf) gp_Trsf2d trsf; @@ -291,9 +292,9 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperato gp_Dir axis1 (1.,0.,0.); gp_Dir axis2 (0.,1.,0.); - IfcGeom::Kernel::convert(l->LocalOrigin(),origin); - if ( l->hasAxis1() ) IfcGeom::Kernel::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::Kernel::convert(l->Axis2(),axis2); + IfcGeom::OpenCascadeKernel::convert(l->LocalOrigin(),origin); + if ( l->hasAxis1() ) IfcGeom::OpenCascadeKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::OpenCascadeKernel::convert(l->Axis2(),axis2); const gp_Pnt2d origin2d(origin.X(), origin.Y()); const gp_Dir2d axis12d(axis1.X(), axis1.Y()); @@ -324,14 +325,14 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCartesianTransformationOperato return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcPlane* pln, gp_Pln& plane) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Location(),o); + IfcGeom::OpenCascadeKernel::convert(l->Location(),o); bool hasRef = l->hasRefDirection(); - if ( l->hasAxis() ) IfcGeom::Kernel::convert(l->Axis(),axis); - if ( hasRef ) IfcGeom::Kernel::convert(l->RefDirection(),refDirection); + if ( l->hasAxis() ) IfcGeom::OpenCascadeKernel::convert(l->Axis(),axis); + if ( hasRef ) IfcGeom::OpenCascadeKernel::convert(l->RefDirection(),refDirection); gp_Ax3 ax3; if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection); else ax3 = gp_Ax3(o,axis); @@ -340,12 +341,12 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPlane* pln, gp_Pln& plane) { return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement2D* l, gp_Trsf2d& trsf) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Location(),P); + IfcGeom::OpenCascadeKernel::convert(l->Location(),P); if ( l->hasRefDirection() ) - IfcGeom::Kernel::convert(l->RefDirection(),V); + IfcGeom::OpenCascadeKernel::convert(l->RefDirection(),V); gp_Ax2d axis(gp_Pnt2d(P.X(),P.Y()), gp_Dir2d(V.X(),V.Y())); @@ -357,7 +358,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement2D* l, gp_Trsf2d return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) { +bool IfcGeom::OpenCascadeKernel::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); @@ -368,7 +369,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& t gp_Trsf trsf2; IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement(); if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) { - IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); + IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); trsf.PreMultiply(trsf2); } if ( current->hasPlacementRelTo() ) { diff --git a/src/ifcgeom/IfcGeomRepresentation.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomOpenCascadeSerialization.cpp similarity index 81% rename from src/ifcgeom/IfcGeomRepresentation.cpp rename to src/ifcgeom/kernels/opencascade/IfcGeomOpenCascadeSerialization.cpp index c5ecc7623c..82802cc1c4 100644 --- a/src/ifcgeom/IfcGeomRepresentation.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomOpenCascadeSerialization.cpp @@ -23,20 +23,22 @@ #include -#include "../ifcgeom/IfcGeom.h" +#include "../../../ifcgeom/IfcGeom.h" +#include "../../../ifcgeom/IfcGeomRepresentation.h" -#include "IfcGeomRepresentation.h" +#include "../opencascade/OpenCascadeKernel.h" +#include "../opencascade/OpenCascadeConversionResult.h" -IfcGeom::Representation::Serialization::Serialization(const BRep& brep) +IfcGeom::Representation::Serialization::Serialization(const Native& 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(); + for (IfcGeom::ConversionResults::const_iterator it = brep.begin(); it != brep.end(); ++ it) { + const TopoDS_Shape& s = ((OpenCascadeShape*) it->Shape())->shape(); + gp_GTrsf trsf = ((OpenCascadePlacement*)it->Placement())->trsf(); if (it->hasStyle() && it->Style().Diffuse()) { const IfcGeom::SurfaceStyle::ColorComponent& clr = *it->Style().Diffuse(); @@ -60,11 +62,11 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep) trsf.PreMultiply(scale); } - const TopoDS_Shape moved_shape = IfcGeom::Kernel::apply_transformation(s, trsf); + const TopoDS_Shape moved_shape = IfcGeom::OpenCascadeKernel::apply_transformation(s, trsf); 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/IfcGeomSerialisation.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomSerialisation.cpp similarity index 98% rename from src/ifcgeom/IfcGeomSerialisation.cpp rename to src/ifcgeom/kernels/opencascade/IfcGeomSerialisation.cpp index 1cbdcd097c..7e228a3d13 100644 --- a/src/ifcgeom/IfcGeomSerialisation.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomSerialisation.cpp @@ -1,3 +1,8 @@ +#include +#include +#include +#include + #include #include #include @@ -14,7 +19,10 @@ #include #include -#include "IfcGeom.h" +#include "../../../ifcgeom/IfcGeom.h" + +#include "OpenCascadeKernel.h" +#include "OpenCascadeSerialization.h" template int convert_to_ifc(const T& t, U*& u, bool /*advanced*/) { diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp similarity index 85% rename from src/ifcgeom/IfcGeomShapes.cpp rename to src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp index 32ac0bd88a..7ee9edb92b 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp @@ -19,7 +19,7 @@ /******************************************************************************** * * - * Implementations of the various conversion functions defined in IfcRegister.h * + * Implementations of the various conversion functions defined in EntityMapping.h * * * ********************************************************************************/ @@ -101,9 +101,12 @@ #include -#include "../ifcgeom/IfcGeom.h" +#include "../../../ifcgeom/IfcGeom.h" -bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& shape) { +#include "OpenCascadeKernel.h" +#include "OpenCascadeConversionResult.h" + +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_Shape& shape) { const double height = l->Depth() * getValue(GV_LENGTH_UNIT); if (height < getValue(GV_PRECISION)) { Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l->entity); @@ -119,7 +122,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_S has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf); } gp_Dir dir; @@ -163,7 +166,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolid* l, TopoDS_S } #ifdef USE_IFC4 -bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* l, TopoDS_Shape& shape) { const double height = l->Depth() * getValue(GV_LENGTH_UNIT); if (height < getValue(GV_PRECISION)) { Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l->entity); @@ -180,7 +183,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* l, T has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf); } gp_Dir dir; @@ -264,7 +267,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* l, T } #endif -bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfLinearExtrusion* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcSurfaceOfLinearExtrusion* l, TopoDS_Shape& shape) { TopoDS_Wire wire; if ( !convert_wire(l->SweptCurve(), wire) ) { TopoDS_Face face; @@ -280,7 +283,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfLinearExtrusion* l, T has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf); } gp_Dir dir; @@ -297,7 +300,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfLinearExtrusion* l, T return !shape.IsNull(); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfRevolution* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcSurfaceOfRevolution* l, TopoDS_Shape& shape) { TopoDS_Wire wire; if ( !convert_wire(l->SweptCurve(), wire) ) { TopoDS_Face face; @@ -307,7 +310,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfRevolution* l, TopoDS } gp_Ax1 ax1; - IfcGeom::Kernel::convert(l->AxisPosition(), ax1); + IfcGeom::OpenCascadeKernel::convert(l->AxisPosition(), ax1); gp_Trsf trsf; bool has_position = true; @@ -315,7 +318,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfRevolution* l, TopoDS has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf); } shape = BRepPrimAPI_MakeRevol(wire, ax1); @@ -329,14 +332,14 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceOfRevolution* l, TopoDS return !shape.IsNull(); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_Shape& shape) { const double ang = l->Angle() * getValue(GV_PLANEANGLE_UNIT); TopoDS_Face face; if ( ! convert_face(l->SweptArea(),face) ) return false; gp_Ax1 ax1; - IfcGeom::Kernel::convert(l->Axis(), ax1); + IfcGeom::OpenCascadeKernel::convert(l->Axis(), ax1); gp_Trsf trsf; bool has_position = true; @@ -344,7 +347,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_S has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf); } if (ang >= M_PI * 2. - ALMOST_ZERO) { @@ -362,7 +365,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRevolvedAreaSolid* l, TopoDS_S return !shape.IsNull(); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, IfcRepresentationShapeItems& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) { TopoDS_Shape s; const SurfaceStyle* collective_style = get_style(l); if (convert_shape(l->Outer(),s) ) { @@ -387,13 +390,13 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, IfcRepre } } - shape.push_back(IfcRepresentationShapeItem(s, indiv_style ? indiv_style : collective_style)); + shape.push_back(ConversionResult(new OpenCascadeShape(s), indiv_style ? indiv_style : collective_style)); return true; } return false; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, ConversionResults& shapes) { bool part_success = false; IfcSchema::IfcConnectedFaceSet::list::ptr facesets = l->FbsmFaces(); const SurfaceStyle* collective_style = get_style(l); @@ -401,29 +404,29 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcR TopoDS_Shape s; const SurfaceStyle* shell_style = get_style(*it); if (convert_shape(*it,s)) { - shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style)); + shapes.push_back(ConversionResult(new OpenCascadeShape(s), shell_style ? shell_style : collective_style)); part_success |= true; } } return part_success; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert((IfcSchema::IfcPlane*)surface,pln); + IfcGeom::OpenCascadeKernel::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::Kernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, TopoDS_Shape& shape) { TopoDS_Shape halfspace; - if ( ! IfcGeom::Kernel::convert((IfcSchema::IfcHalfSpaceSolid*)l,halfspace) ) return false; + if ( ! IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcHalfSpaceSolid*)l,halfspace) ) return false; TopoDS_Wire wire; if ( ! convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false; @@ -455,7 +458,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, ConversionResults& shapes) { IfcEntityList::ptr shells = l->SbsmBoundary(); const SurfaceStyle* collective_style = get_style(l); for( IfcEntityList::it it = shells->begin(); it != shells->end(); ++ it ) { @@ -465,16 +468,16 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, Ifc shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it); } if (convert_shape(*it,s)) { - shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style)); + shapes.push_back(ConversionResult(new OpenCascadeShape(s), shell_style ? shell_style : collective_style)); } } return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) { TopoDS_Shape s1, s2; - IfcRepresentationShapeItems items1, items2; + ConversionResults items1, items2; TopoDS_Wire boundary_wire; IfcSchema::IfcBooleanOperand* operand1 = l->FirstOperand(); IfcSchema::IfcBooleanOperand* operand2 = l->SecondOperand(); @@ -623,7 +626,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape return false; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& shape) { IfcSchema::IfcFace::list::ptr faces = l->CfsFaces(); TopTools_ListOfShape face_list; @@ -666,31 +669,31 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Sh return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionResults& shapes) { gp_GTrsf gtrsf; IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget(); if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) { - IfcGeom::Kernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); + IfcGeom::OpenCascadeKernel::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::Kernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); + IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); gtrsf = trsf; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { gp_Trsf2d trsf_2d; - IfcGeom::Kernel::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,trsf_2d); + IfcGeom::OpenCascadeKernel::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::Kernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); + IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); } else { gp_Trsf2d trsf_2d; - IfcGeom::Kernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d); + IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d); trsf = trsf_2d; } gtrsf.Multiply(trsf); @@ -701,7 +704,8 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentati bool b = convert_shapes(map->MappedRepresentation(), shapes); for (size_t i = previous_size; i < shapes.size(); ++ i ) { - shapes[i].prepend(gtrsf); + IfcGeom::OpenCascadePlacement place(gtrsf); + shapes[i].prepend(&place); // Apply styles assigned to the mapped item only if on // a more granular level no styles have been applied @@ -713,7 +717,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentati return b; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcRepresentation* l, ConversionResults& shapes) { IfcSchema::IfcRepresentationItem::list::ptr items = l->Items(); bool part_succes = false; if ( items->size() ) { @@ -724,7 +728,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresen } else { TopoDS_Shape s; if (convert_shape(representation_item,s)) { - shapes.push_back(IfcRepresentationShapeItem(s, get_style(representation_item))); + shapes.push_back(ConversionResult(new OpenCascadeShape(s), get_style(representation_item))); part_succes |= true; } } @@ -733,7 +737,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresen return part_succes; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcGeometricSet* l, ConversionResults& shapes) { IfcEntityList::ptr elements = l->Elements(); if ( !elements->size() ) return false; bool part_succes = false; @@ -751,20 +755,20 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresenta } else if (element->is(IfcSchema::Type::IfcSurface)) { style = get_style((IfcSchema::IfcSurface*) element); } - shapes.push_back(IfcRepresentationShapeItem(s, style ? style : parent_style)); + shapes.push_back(ConversionResult(new OpenCascadeShape(s), style ? style : parent_style)); } } return part_succes; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcBlock* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Position(),trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(),trsf); // IfcCsgPrimitive3D.Position has unit scale factor shape = builder.Solid().Moved(trsf); @@ -772,7 +776,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBlock* l, TopoDS_Shape& shape) return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularPyramid* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::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); @@ -789,18 +793,18 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularPyramid* l, TopoDS_ #endif ); - IfcGeom::Kernel::convert(l->Position(), trsf1); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf1); shape = BRepBuilderAPI_Transform(builder.Solid(), trsf1 * trsf2); return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRightCircularCylinder* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Position(),trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(),trsf); // IfcCsgPrimitive3D.Position has unit scale factor shape = builder.Solid().Moved(trsf); @@ -808,13 +812,13 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRightCircularCylinder* l, Topo return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRightCircularCone* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Position(),trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(),trsf); // IfcCsgPrimitive3D.Position has unit scale factor shape = builder.Solid().Moved(trsf); @@ -822,12 +826,12 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRightCircularCone* l, TopoDS_S return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcSphere* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(l->Position(),trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(),trsf); // IfcCsgPrimitive3D.Position has unit scale factor shape = builder.Solid().Moved(trsf); @@ -835,13 +839,13 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSphere* l, TopoDS_Shape& shape return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCsgSolid* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcCsgSolid* l, TopoDS_Shape& shape) { return convert_shape(l->TreeRootExpression(), shape); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCurveBoundedPlane* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcCurveBoundedPlane* l, TopoDS_Shape& face) { gp_Pln pln; - IfcGeom::Kernel::convert(l->BasisSurface(), pln); + IfcGeom::OpenCascadeKernel::convert(l->BasisSurface(), pln); gp_Trsf trsf; trsf.SetTransformation(pln.Position(), gp::XOY()); @@ -870,13 +874,13 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCurveBoundedPlane* l, TopoDS_S return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularTrimmedSurface* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert((IfcSchema::IfcPlane*) l->BasisSurface(), pln); + IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcPlane*) l->BasisSurface(), pln); BRepBuilderAPI_MakeFace mf(pln, l->U1(), l->U2(), l->V1(), l->V2()); @@ -885,7 +889,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularTrimmedSurface* l, return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_Shape& shape) { gp_Trsf directrix, position; TopoDS_Shape face; TopoDS_Wire wire, section; @@ -901,7 +905,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, has_position = l->hasPosition(); #endif if (has_position) { - IfcGeom::Kernel::convert(l->Position(), trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(), trsf); } if (!convert_face(l->SweptArea(), face) || @@ -913,7 +917,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, gp_Pnt directrix_origin; gp_Vec directrix_tangent; bool directrix_on_plane = true; - IfcGeom::Kernel::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln); + IfcGeom::OpenCascadeKernel::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 @@ -971,7 +975,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcSweptDiskSolid* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcSweptDiskSolid* l, TopoDS_Shape& shape) { TopoDS_Wire wire, section1, section2; bool hasInnerRadius = l->hasInnerRadius(); @@ -1053,9 +1057,9 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSweptDiskSolid* l, TopoDS_Shap #ifdef USE_IFC4 -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCylindricalSurface* l, TopoDS_Shape& face) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcCylindricalSurface* l, TopoDS_Shape& face) { gp_Trsf trsf; - IfcGeom::Kernel::convert(l->Position(),trsf); + IfcGeom::OpenCascadeKernel::convert(l->Position(),trsf); // IfcElementarySurface.Position has unit scale factor #if OCC_VERSION_HEX < 0x60502 @@ -1066,11 +1070,11 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCylindricalSurface* l, TopoDS_ return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcAdvancedBrep* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcAdvancedBrep* l, TopoDS_Shape& shape) { return convert(l->Outer(), shape); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, TopoDS_Shape& shape) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, TopoDS_Shape& shape) { IfcSchema::IfcCartesianPointList3D* point_list = l->Coordinates(); const std::vector< std::vector > coordinates = point_list->CoordList(); std::vector points; diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomWires.cpp similarity index 90% rename from src/ifcgeom/IfcGeomWires.cpp rename to src/ifcgeom/kernels/opencascade/IfcGeomWires.cpp index 714244ae96..fb102dd6fc 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomWires.cpp @@ -19,7 +19,7 @@ /******************************************************************************** * * - * Implementations of the various conversion functions defined in IfcRegister.h * + * Implementations of the various conversion functions defined in EntityMapping.h * * * ********************************************************************************/ @@ -86,9 +86,10 @@ #include #include -#include "../ifcgeom/IfcGeom.h" +#include "../../../ifcgeom/IfcGeom.h" +#include "OpenCascadeKernel.h" -bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) { +bool IfcGeom::OpenCascadeKernel::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); @@ -103,13 +104,13 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire // First try radians TopoDS_Wire wire_radians, wire_degrees; try { - succes_radians = IfcGeom::Kernel::convert(l,wire_radians); + succes_radians = IfcGeom::OpenCascadeKernel::convert(l,wire_radians); } catch (...) {} // Now try degrees setValue(GV_PLANEANGLE_UNIT,0.0174532925199433); try { - succes_degrees = IfcGeom::Kernel::convert(l,wire_degrees); + succes_degrees = IfcGeom::OpenCascadeKernel::convert(l,wire_degrees); } catch (...) {} // Restore to unknown unit state @@ -197,7 +198,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) { +bool IfcGeom::OpenCascadeKernel::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 ? getValue(GV_PLANEANGLE_UNIT) : getValue(GV_LENGTH_UNIT); @@ -215,7 +216,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& for ( IfcEntityList::it it = trims1->begin(); it != trims1->end(); it ++ ) { IfcUtil::IfcBaseClass* i = *it; if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) { - IfcGeom::Kernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[sense_agreement] ); + IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[sense_agreement] ); has_pnts[sense_agreement] = true; } else if ( i->is(IfcSchema::Type::IfcParameterValue) ) { const double value = *((IfcSchema::IfcParameterValue*)i); @@ -226,7 +227,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& for ( IfcEntityList::it it = trims2->begin(); it != trims2->end(); it ++ ) { IfcUtil::IfcBaseClass* i = *it; if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) { - IfcGeom::Kernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[1-sense_agreement] ); + IfcGeom::OpenCascadeKernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[1-sense_agreement] ); has_pnts[1-sense_agreement] = true; } else if ( i->is(IfcSchema::Type::IfcParameterValue) ) { const double value = *((IfcSchema::IfcParameterValue*)i); @@ -294,14 +295,14 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& } } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& result) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(*it, pnt); + IfcGeom::OpenCascadeKernel::convert(*it, pnt); polygon.Append(pnt); } @@ -317,14 +318,14 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& resu return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& result) { +bool IfcGeom::OpenCascadeKernel::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::Kernel::convert(*it, pnt); + IfcGeom::OpenCascadeKernel::convert(*it, pnt); polygon.Append(pnt); } @@ -359,11 +360,11 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& resu return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryOpenProfileDef* l, TopoDS_Wire& result) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcArbitraryOpenProfileDef* l, TopoDS_Wire& result) { return convert_wire(l->Curve(), result); } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& result) { +bool IfcGeom::OpenCascadeKernel::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)) { @@ -372,8 +373,8 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& res } gp_Pnt p1, p2; - if (!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) || - !IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2)) + if (!IfcGeom::OpenCascadeKernel::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) || + !IfcGeom::OpenCascadeKernel::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2)) { return false; } @@ -441,7 +442,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeCurve* l, TopoDS_Wire& res } } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& result) { +bool IfcGeom::OpenCascadeKernel::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) { @@ -454,7 +455,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& resu return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdge* l, TopoDS_Wire& result) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcEdge* l, TopoDS_Wire& result) { if (!l->EdgeStart()->is(IfcSchema::Type::IfcVertexPoint) || !l->EdgeEnd()->is(IfcSchema::Type::IfcVertexPoint)) { Logger::Message(Logger::LOG_ERROR, "Only IfcVertexPoints are supported for EdgeStart and -End", l->entity); return false; @@ -481,7 +482,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdge* l, TopoDS_Wire& result) return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcOrientedEdge* l, TopoDS_Wire& result) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcOrientedEdge* l, TopoDS_Wire& result) { if (convert_wire(l->EdgeElement(), result)) { if (!l->Orientation()) { result.Reverse(); @@ -492,7 +493,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcOrientedEdge* l, TopoDS_Wire& } } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcSubedge* l, TopoDS_Wire& result) { +bool IfcGeom::OpenCascadeKernel::convert(const IfcSchema::IfcSubedge* l, TopoDS_Wire& result) { TopoDS_Wire temp; if (convert_wire(l->ParentEdge(), result) && convert((IfcSchema::IfcEdge*) l, temp)) { TopExp_Explorer exp(result, TopAbs_EDGE); diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h new file mode 100644 index 0000000000..297c72f6fb --- /dev/null +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h @@ -0,0 +1,86 @@ +/******************************************************************************** +* * +* 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 IFCGEOMOPENCASCADEREPRESENTATION_H +#define IFCGEOMOPENCASCADEREPRESENTATION_H + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace IfcGeom { + + class OpenCascadePlacement : public ConversionResultPlacement { + public: + OpenCascadePlacement(const gp_GTrsf& trsf) + : trsf_(trsf) + {} + + const gp_GTrsf& trsf() const { return trsf_; } + operator const gp_GTrsf& () { return trsf_; } + + virtual double Value(int i, int j) const { + return trsf_.Value(i, j); + } + virtual void Multiply(const ConversionResultPlacement* other) { + trsf_.Multiply(((OpenCascadePlacement*)other)->trsf_); + } + virtual void PreMultiply(const ConversionResultPlacement* other) { + trsf_.PreMultiply(((OpenCascadePlacement*)other)->trsf_); + } + virtual ConversionResultPlacement* clone() const { + return new OpenCascadePlacement(trsf_); + } + private: + gp_GTrsf trsf_; + }; + + class OpenCascadeShape : public ConversionResultShape { + public: + OpenCascadeShape(const TopoDS_Shape& shape) + : shape_(shape) + {} + + const TopoDS_Shape& shape() const { return shape_; } + operator const TopoDS_Shape& () { return shape_; } + + virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const; + virtual void Serialize(std::string&) const { + throw std::runtime_error("Not implemented"); + } + virtual ConversionResultShape* clone() const { + return new OpenCascadeShape(shape_); + } + private: + TopoDS_Shape shape_; + }; + +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h new file mode 100644 index 0000000000..2ed4ae65ee --- /dev/null +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h @@ -0,0 +1,155 @@ +/******************************************************************************** +* * +* 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 OPENCASADE_KERNEL_H +#define OPENCASADE_KERNEL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Define this in case you want to conserve memory usage at all cost. This has been +// benchmarked extensively: https://github.com/IfcOpenShell/IfcOpenShell/pull/47 +// #define NO_CACHE + +#ifdef NO_CACHE + +#define IN_CACHE(T,E,t,e) +#define CACHE(T,E,e) + +#else + +#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; + +#endif + +namespace IfcGeom { + + class IFC_GEOM_API Cache { + public: +#include "EntityMappingCreateCache.h" + std::map Shape; + }; + + class IFC_GEOM_API OpenCascadeKernel : public AbstractKernel { + public: + +#ifndef NO_CACHE + Cache cache; +#endif + + IfcGeom::ShapeType shape_type(const IfcUtil::IfcBaseClass* L); + + bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face); + bool convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire); + bool convert_shapes(const IfcUtil::IfcBaseClass* L, ConversionResults& result); + bool convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result); + bool flatten_shape_list(const IfcGeom::ConversionResults& shapes, TopoDS_Shape& result, bool fuse); + bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result); + bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& result); + bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result); + + + bool convert_layerset(const IfcSchema::IfcProduct*, std::vector&, std::vector&, std::vector&); + bool apply_layerset(const ConversionResults&, const std::vector&, const std::vector&, ConversionResults&); + bool apply_folded_layerset(const ConversionResults&, const std::vector< std::vector >&, const std::vector&, ConversionResults&); + bool fold_layers(const IfcSchema::IfcWall*, const ConversionResults&, const std::vector&, const std::vector&, std::vector< std::vector >&); + + bool split_solid_by_surface(const TopoDS_Shape&, const Handle_Geom_Surface&, TopoDS_Shape&, TopoDS_Shape&); + bool split_solid_by_shell(const TopoDS_Shape&, const TopoDS_Shape& s, TopoDS_Shape&, TopoDS_Shape&); + + const Handle_Geom_Curve intersect(const Handle_Geom_Surface&, const Handle_Geom_Surface&); + const Handle_Geom_Curve intersect(const Handle_Geom_Surface&, const TopoDS_Face&); + const Handle_Geom_Curve intersect(const TopoDS_Face&, const Handle_Geom_Surface&); + bool intersect(const Handle_Geom_Curve&, const Handle_Geom_Surface&, gp_Pnt&); + bool intersect(const Handle_Geom_Curve&, const TopoDS_Face&, gp_Pnt&); + bool intersect(const Handle_Geom_Curve&, const TopoDS_Shape&, std::vector&); + bool intersect(const Handle_Geom_Surface&, const TopoDS_Shape&, std::vector< std::pair >&); + bool closest(const gp_Pnt&, const std::vector&, gp_Pnt&); + bool project(const Handle_Geom_Curve&, const gp_Pnt&, gp_Pnt& p, double& u, double& d); + bool project(const Handle_Geom_Surface&, const TopoDS_Shape&, double& u1, double& v1, double& u2, double& v2, double widen = 0.1); + int count(const TopoDS_Shape&, TopAbs_ShapeEnum); + + + bool find_wall_end_points(const IfcSchema::IfcWall*, gp_Pnt& start, gp_Pnt& end); + + bool create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& solid); + bool create_solid_from_faces(const TopTools_ListOfShape& face_list, TopoDS_Shape& solid); + bool is_compound(const TopoDS_Shape& shape); + bool is_convex(const TopoDS_Wire& wire); + TopoDS_Shape halfspace_from_plane(const gp_Pln& pln, const gp_Pnt& cent); + gp_Pln plane_from_face(const TopoDS_Face& face); + gp_Pnt point_above_plane(const gp_Pln& pln, bool agree = true); + const TopoDS_Shape& ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid); + bool profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Shape& face); + double shape_volume(const TopoDS_Shape& s); + double face_area(const TopoDS_Face& f); + void apply_tolerance(TopoDS_Shape& s, double t); + + bool fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape); + void remove_duplicate_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol = -1.); + void remove_collinear_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol = -1.); + bool wire_to_sequence_of_point(const TopoDS_Wire&, TColgp_SequenceOfPnt&); + void sequence_of_point_to_wire(const TColgp_SequenceOfPnt&, TopoDS_Wire&, bool closed); + bool approximate_plane_through_wire(const TopoDS_Wire&, gp_Pln&); + bool flatten_wire(TopoDS_Wire&); + + static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_Trsf&); + static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&); + + bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes); + bool convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes); + + void purge_cache() { + // Rather hack-ish, but a stopgap solution to keep memory under control + // for large files. SurfaceStyles need to be kept at all costs, as they + // are read later on when serializing Collada files. +#ifndef NO_CACHE + cache = Cache(); +#endif + } + + virtual bool is_identity_transform(IfcUtil::IfcBaseClass*); + virtual IfcGeom::NativeElement* create_brep_for_representation_and_product( + const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*); + virtual IfcGeom::NativeElement* create_brep_for_processed_representation( + const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement*); + +#include "EntityMappingDeclaration.h" + + }; + +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeSerialization.h b/src/ifcgeom/kernels/opencascade/OpenCascadeSerialization.h new file mode 100644 index 0000000000..c2937df7f6 --- /dev/null +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeSerialization.h @@ -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 . * +* * +********************************************************************************/ + +#ifndef OPENCASCADESERIALIZATION_H +#define OPENCASCADESERIALIZATION_H + +#include "../../../ifcparse/IfcParse.h" + +#include + +namespace IfcGeom { + + IfcSchema::IfcProductDefinitionShape* tesselate(const TopoDS_Shape& shape, double deflection); + IfcSchema::IfcProductDefinitionShape* serialise(const TopoDS_Shape& shape, bool advanced); + +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeShape.cpp b/src/ifcgeom/kernels/opencascade/OpenCascadeShape.cpp new file mode 100644 index 0000000000..fcc94b52e3 --- /dev/null +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeShape.cpp @@ -0,0 +1,194 @@ + + +#include "../../../ifcgeom/IfcGeom.h" +#include "../../../ifcgeom/IfcGeomIteratorSettings.h" +#include "../../../ifcgeom/ConversionResult.h" + +#include "OpenCascadeConversionResult.h" + +#include + +void IfcGeom::OpenCascadeShape::Triangulate(const IfcGeom::IteratorSettings& settings, const IfcGeom::ConversionResultPlacement* place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { + + const TopoDS_Shape& s = shape_; + const gp_GTrsf& trsf = dynamic_cast(place)->trsf(); + + // Triangulate the shape + try { + BRepMesh_IncrementalMesh(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"); + return; + } + + // Iterates over the faces of the shape + int num_faces = 0; + TopExp_Explorer exp; + for (exp.Init(s, TopAbs_FACE); exp.More(); exp.Next(), ++num_faces) { + 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 and calculation is not disable explicitly. + const bool calculate_normals = !settings.get(IteratorSettings::WELD_VERTICES) && + !settings.get(IteratorSettings::NO_NORMALS); + + for (int i = 1; i <= nodes.Length(); ++i) { + coords.push_back(nodes(i).Transformed(loc).XYZ()); + trsf.Transforms(*coords.rbegin()); + const gp_XYZ& last = *coords.rbegin(); + dict[i] = t->addVertex(surface_style_id, last.X(), last.Y(), last.Z()); + + 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); + } + t->normals().push_back(static_cast(normal.X())); + t->normals().push_back(static_cast(normal.Y())); + t->normals().push_back(static_cast(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()); + */ + + t->faces().push_back(dict[n1]); + t->faces().push_back(dict[n2]); + t->faces().push_back(dict[n3]); + + t->material_ids().push_back(surface_style_id); + + t->addEdge(dict[n1], dict[n2], edgecount, edges_temp); + t->addEdge(dict[n2], dict[n3], edgecount, edges_temp); + t->addEdge(dict[n3], dict[n1], edgecount, edges_temp); + } + for (std::vector >::const_iterator jt = edges_temp.begin(); jt != edges_temp.end(); ++jt) { + if (edgecount[*jt] == 1) { + // non manifold edge, face boundary + t->edges().push_back(jt->first); + t->edges().push_back(jt->second); + } + } + } + } + + /* + TODO: Unimplemented + if (!t.normals().empty() && settings().get(IfcGeom::IteratorSettings::GENERATE_UVS)) { + t.uvs() = box_project_uvs(t.verts(), t.normals()); + } + */ + + if (num_faces == 0) { + // Edges are only emitted if there are no faces. A mixed representation of faces + // and loose edges is discouraged by the standard. An alternative would be to use + // TopExp_Explorer texp(s, TopAbs_EDGE, TopAbs_FACE) to find edges that do not + // belong to any face. + for (TopExp_Explorer texp(s, TopAbs_EDGE); texp.More(); texp.Next()) { + BRepAdaptor_Curve crv(TopoDS::Edge(texp.Current())); + GCPnts_QuasiUniformDeflection tessellater(crv, settings.deflection_tolerance()); + int n = tessellater.NbPoints(); + int start = (int)t->verts().size() / 3; + for (int i = 1; i <= n; ++i) { + gp_XYZ p = tessellater.Value(i).XYZ(); + + /* + // In case you want direction arrows on your edges + double u = tessellater.Parameter(i); + gp_XYZ p2, p3; + gp_Pnt tmp; + gp_Vec tmp2; + crv.D1(u, tmp, tmp2); + gp_Dir d1, d2, d3, d4; + d1 = tmp2; + if (texp.Current().Orientation() == TopAbs_REVERSED) { + d1 = -d1; + } + if (fabs(d1.Z()) < 0.5) { + d2 = d1.Crossed(gp::DZ()); + } else { + d2 = d1.Crossed(gp::DY()); + } + d3 = d1.XYZ() + d2.XYZ(); + d4 = d1.XYZ() - d2.XYZ(); + p2 = p - d3.XYZ() / 10.; + p3 = p - d4.XYZ() / 10.; + trsf.Transforms(p2); + trsf.Transforms(p3); + _material_ids.push_back(surface_style_id); + _material_ids.push_back(surface_style_id); + _verts.push_back(static_cast

(p2.X())); + _verts.push_back(static_cast

(p2.Y())); + _verts.push_back(static_cast

(p2.Z())); + _verts.push_back(static_cast

(p3.X())); + _verts.push_back(static_cast

(p3.Y())); + _verts.push_back(static_cast

(p3.Z())); + */ + + trsf.Transforms(p); + + t->material_ids().push_back(surface_style_id); + + t->verts().push_back(static_cast(p.X())); + t->verts().push_back(static_cast(p.Y())); + t->verts().push_back(static_cast(p.Z())); + + if (i > 1) { + t->edges().push_back(start + i - 2); + t->edges().push_back(start + i - 1); + // _edges.push_back(start + 3 * (i - 2) + 2); + // _edges.push_back(start + 3 * (i - 1) + 2); + } + + // _edges.push_back(start + 3 * (i - 1) + 0); + // _edges.push_back(start + 3 * (i - 1) + 2); + // _edges.push_back(start + 3 * (i - 1) + 1); + // _edges.push_back(start + 3 * (i - 1) + 2); + } + } + } + + BRepTools::Clean(s); +}