diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index a1464e56e7..10c7b93912 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -536,7 +536,7 @@ if(NOT Boost_VERSION LESS 105800) add_definitions(-DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE) endif() -set(IFCOPENSHELL_LIBRARIES IfcParse IfcGeom IfcGeom IfcGeom_CGAL Serializers Serializers) +set(IFCOPENSHELL_LIBRARIES IfcParse IfcGeom Serializers) # IfcParse file(GLOB IFCPARSE_H_FILES ../src/ifcparse/*.h) @@ -561,11 +561,6 @@ file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/*.h) file(GLOB IFCGEOM_CPP_FILES ../src/ifcgeom/*.cpp) set(IFCGEOM_FILES ${IFCGEOM_CPP_FILES} ${IFCGEOM_H_FILES}) -# IfcGeom, schema agnostic, OCCT -file(GLOB SCHEMA_AGNOSTIC_H_FILES ../src/ifcgeom_schema_agnostic/*.h) -file(GLOB SCHEMA_AGNOSTIC_CPP_FILES ../src/ifcgeom_schema_agnostic/*.cpp) -set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES}) - foreach(schema 2x3 4) add_library(IfcGeom_ifc${schema} ${IFCGEOM_FILES}) set_target_properties(IfcGeom_ifc${schema} PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc${schema} -DUSE_IFC${schema}") @@ -573,32 +568,28 @@ TARGET_LINK_LIBRARIES(IfcGeom_ifc${schema} IfcParse ${OPENCASCADE_LIBRARIES}) list(APPEND IfcGeom_libraries IfcGeom_ifc${schema}) endforeach() -add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES}) -set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS) -TARGET_LINK_LIBRARIES(IfcGeom ${IfcGeom_libraries}) - ### CGAL -# IfcGeom, schema dependent, OCCT +# IfcGeom, schema dependent, CGAL file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/kernels/cgal/*.h) file(GLOB IFCGEOM_CPP_FILES ../src/ifcgeom/kernels/cgal/*.cpp) set(IFCGEOM_FILES ${IFCGEOM_CPP_FILES} ${IFCGEOM_H_FILES}) -# IfcGeom, schema agnostic, OCCT -file(GLOB SCHEMA_AGNOSTIC_H_FILES ../src/ifcgeom_schema_agnostic_cgal/*.h) -file(GLOB SCHEMA_AGNOSTIC_CPP_FILES ../src/ifcgeom_schema_agnostic_cgal/*.cpp) -set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES}) - foreach(schema 2x3 4) -add_library(IfcGeom_ifc${schema} ${IFCGEOM_FILES}) +add_library(IfcGeom_CGAL_ifc${schema} ${IFCGEOM_FILES}) set_target_properties(IfcGeom_CGAL_ifc${schema} PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc${schema} -DUSE_IFC${schema}") TARGET_LINK_LIBRARIES(IfcGeom_CGAL_ifc${schema} IfcParse ${OPENCASCADE_LIBRARIES}) list(APPEND IfcGeom_CGAL_libraries IfcGeom_CGAL_ifc${schema}) endforeach() -add_library(IfcGeom_CGAL ${SCHEMA_AGNOSTIC_FILES}) -set_target_properties(IfcGeom_CGAL PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS) -TARGET_LINK_LIBRARIES(IfcGeom_CGAL ${IfcGeom_CGAL_libraries}) +# IfcGeom, schema and kernel agnostic +file(GLOB SCHEMA_AGNOSTIC_H_FILES ../src/ifcgeom_schema_agnostic/*.h) +file(GLOB SCHEMA_AGNOSTIC_CPP_FILES ../src/ifcgeom_schema_agnostic/*.cpp) +set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES}) + +add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES}) +set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS) +TARGET_LINK_LIBRARIES(IfcGeom ${IfcGeom_libraries}) endif(BUILD_IFCGEOM) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 910d17ad18..2e7ac79e7a 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -711,7 +711,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 @@ -729,7 +729,7 @@ int main(int argc, char** argv) } else { - serializer->write(static_cast*>(geom_object)); + serializer->write(static_cast*>(geom_object)); } if (!no_progress) { @@ -1152,7 +1152,7 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std if (num_created) { has_more = context_iterator.next(); } - IfcGeom::BRepElement* geom_object = nullptr; + IfcGeom::NativeElement* geom_object = nullptr; if (has_more) { geom_object = context_iterator.get_native(); } @@ -1205,7 +1205,7 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std auto quantity_count = latebound_access::create(f, "IfcQuantityCount"); latebound_access::set(quantity_count, "Name", std::string("Surface Genus")); latebound_access::set(quantity_count, "Description", '#' + boost::lexical_cast(part.ItemId())); - latebound_access::set(quantity_count, "CountValue", IfcGeom::Kernel::surface_genus(part.Shape())); + latebound_access::set(quantity_count, "CountValue", part.Shape()->surface_genus()); quantities_2->push(quantity_count); } diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index c6e3c7692d..f4466798bd 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -52,14 +52,15 @@ inline static bool ALMOST_THE_SAME(const T& a, const T& b, double tolerance=ALMO #include "../ifcparse/IfcParse.h" #include "../ifcparse/IfcBaseClass.h" -#include "../ifcgeom/IfcGeomElement.h" -#include "../ifcgeom/IfcGeomRepresentation.h" -#include "../ifcgeom/IfcRepresentationShapeItem.h" +#include "../ifcgeom_schema_agnostic/IfcGeomElement.h" +#include "../ifcgeom_schema_agnostic/IfcGeomRepresentation.h" +#include "../ifcgeom_schema_agnostic/ConversionResult.h" #include "../ifcgeom/IfcGeomShapeType.h" #include "../ifcgeom_schema_agnostic/Kernel.h" +#include "OpenCascadeConversionResult.h" -#include "ifc_geom_api.h" +#include "../ifcgeom_schema_agnostic/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 @@ -258,21 +259,21 @@ public: 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); + bool convert_shapes(const IfcUtil::IfcBaseClass* L, ConversionResults& 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 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_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_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 assert_closed_wire(TopoDS_Wire& wire); 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 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&); @@ -326,6 +327,7 @@ public: static double shape_volume(const TopoDS_Shape& s); static double face_area(const TopoDS_Face& f); + static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const OpenCascadePlacement*); static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_Trsf&); static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&); @@ -338,12 +340,12 @@ public: std::pair initializeUnits(IfcSchema::IfcUnitAssignment*); template - IfcGeom::BRepElement* create_brep_for_representation_and_product( + IfcGeom::NativeElement* create_brep_for_representation_and_product( const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*); template - IfcGeom::BRepElement* create_brep_for_processed_representation( - const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::BRepElement*); + IfcGeom::NativeElement* create_brep_for_processed_representation( + const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement*); const IfcSchema::IfcMaterial* get_single_material_association(const IfcSchema::IfcProduct*); IfcSchema::IfcRepresentation* representation_mapped_to(const IfcSchema::IfcRepresentation* representation); @@ -416,15 +418,15 @@ public: virtual void setValue(GeomValue var, double value); virtual double getValue(GeomValue var) const; - virtual IfcGeom::BRepElement* convert( + virtual IfcGeom::NativeElement* convert( const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation, IfcUtil::IfcBaseClass* product) { return create_brep_for_representation_and_product(settings, (IfcSchema::IfcRepresentation*) representation, (IfcSchema::IfcProduct*) product); } - virtual IfcRepresentationShapeItems convert(IfcUtil::IfcBaseClass* item) { - IfcRepresentationShapeItems items; + virtual ConversionResults convert(IfcUtil::IfcBaseClass* item) { + ConversionResults items; bool success = convert_shapes(item, items); if (!success) { throw IfcParse::IfcException("Failed to process representation item"); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index fff22622f9..2dd9f4129b 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -507,13 +507,13 @@ const TopoDS_Shape& IfcGeom::Kernel::ensure_fit_for_subtraction(const TopoDS_Sha } 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) { + 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; @@ -545,30 +545,26 @@ 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); - } + 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 = 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(); - if ( opening_shape_gtrsf.Form() == gp_Other ) { - Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to opening of:",entity); - } + const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*) it4->Shape(),opening_shape_solid); + const OpenCascadePlacement* opening_shape_gtrsf = (OpenCascadePlacement*)it4->Placement(); TopoDS_Shape opening_shape = apply_transformation(opening_shape_unlocated, opening_shape_gtrsf); double opening_volume; @@ -673,7 +669,7 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons } } - cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), it3->Placement(), entity_shape, &it3->Style())); + cut_shapes.push_back(IfcGeom::ConversionResult(it3->ItemId(), it3->Placement()->clone(), new OpenCascadeShape(entity_shape), &it3->Style())); } return true; @@ -681,7 +677,7 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons #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) { + 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; @@ -712,7 +708,7 @@ 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); @@ -729,7 +725,7 @@ 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(); @@ -747,7 +743,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(it3->ItemId(), brep_cut_result, &it3->Style())); + cut_shapes.push_back(IfcGeom::ConversionResult(it3->ItemId(), brep_cut_result, &it3->Style())); } } if ( !is_valid ) { @@ -772,7 +768,7 @@ namespace { } 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) { + const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) { std::vector< std::pair > opening_vector; @@ -800,7 +796,7 @@ 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); @@ -808,9 +804,12 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, for (unsigned int i = 0; i < opening_shapes.size(); ++i) { TopoDS_Shape opening_shape_solid; - const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(opening_shapes[i].Shape(), opening_shape_solid); + const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*)opening_shapes[i].Shape(), opening_shape_solid); - gp_GTrsf gtrsf = opening_shapes[i].Placement(); + gp_GTrsf gtrsf; + if (opening_shapes[i].Placement()) { + gtrsf = ((OpenCascadePlacement*)opening_shapes[i].Placement())->trsf(); + } gtrsf.PreMultiply(opening_trsf); TopoDS_Shape opening_shape = apply_transformation(opening_shape_unlocated, gtrsf); opening_vector.push_back(std::make_pair(min_edge_length(opening_shape), opening_shape)); @@ -822,13 +821,10 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, std::sort(opening_vector.begin(), opening_vector.end(), opening_sorter()); // 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); - } + 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 = apply_transformation(entity_shape_unlocated, entity_shape_gtrsf); TopoDS_Shape result = entity_shape; @@ -859,7 +855,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, } } - cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(it3->ItemId(), result, &it3->Style())); + cut_shapes.push_back(IfcGeom::ConversionResult(it3->ItemId(), new OpenCascadeShape(result), &it3->Style())); } return true; } @@ -1263,22 +1259,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::Kernel::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 OpenCascadePlacement* trsf = (const OpenCascadePlacement*) it->Placement(); const TopoDS_Shape moved_shape = apply_transformation(merged, trsf); if (shapes.size() == 1) { @@ -1463,7 +1459,7 @@ const IfcSchema::IfcMaterial* IfcGeom::Kernel::get_single_material_association(c } template -IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and_product( +IfcGeom::NativeElement* IfcGeom::Kernel::create_brep_for_representation_and_product( const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product) { std::stringstream representation_id_builder; @@ -1471,7 +1467,7 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and representation_id_builder << representation->data().id(); IfcGeom::Representation::BRep* shape; - IfcGeom::IfcRepresentationShapeItems shapes, shapes2; + IfcGeom::ConversionResults shapes, shapes2; if ( !convert_shapes(representation, shapes) ) { return 0; @@ -1526,7 +1522,7 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and const IfcSchema::IfcMaterial* single_material = get_single_material_association(product); if (single_material) { const IfcGeom::SurfaceStyle* s = get_style(single_material); - for (IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++it) { + for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) { if (!it->hasStyle() && s) { it->setStyle(s); material_style_applied = true; @@ -1534,7 +1530,7 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and } } else { bool some_items_without_style = false; - for (IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++it) { + for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) { if (!it->hasStyle()) { some_items_without_style = true; break; @@ -1584,7 +1580,7 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and representation_id_builder << "-" << (*it)->data().id(); } - IfcGeom::IfcRepresentationShapeItems opened_shapes; + IfcGeom::ConversionResults opened_shapes; bool caught_error = false; try { #if OCC_VERSION_HEX < 0x60900 @@ -1617,16 +1613,18 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and } 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 ) { + OpenCascadePlacement p(trsf); + it->prepend(&p); } trsf = gp_Trsf(); representation_id_builder << "-world-coords"; } shape = new IfcGeom::Representation::BRep(element_settings, representation_id_builder.str(), 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 ) { + OpenCascadePlacement p(trsf); + it->prepend(&p); } trsf = gp_Trsf(); representation_id_builder << "-world-coords"; @@ -1642,14 +1640,14 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and context_string = representation->ContextOfItems()->ContextType(); } - auto elem = new BRepElement( + auto elem = new NativeElement( product->data().id(), parent_id, name, product_type, guid, context_string, - trsf, + new OpenCascadePlacement(trsf), boost::shared_ptr(shape), product ); @@ -1703,7 +1701,7 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and int genus = q2->as()->CountValue(); for (auto& part : elem->geometry()) { if (part.ItemId() == item_id) { - if (surface_genus(part.Shape()) != genus) { + if (surface_genus(*(OpenCascadeShape*)part.Shape()) != genus) { all_succeeded = false; } } @@ -1792,9 +1790,9 @@ IfcSchema::IfcProduct::list::ptr IfcGeom::Kernel::products_represented_by(const } template -IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_processed_representation( +IfcGeom::NativeElement* IfcGeom::Kernel::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 { @@ -1827,32 +1825,32 @@ IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_processed_represen const std::string product_type = product->declaration().name(); - return new BRepElement( + return new NativeElement( product->data().id(), parent_id, name, product_type, guid, context_string, - trsf, + new OpenCascadePlacement(trsf), brep->geometry_pointer(), product ); } -template IFC_GEOM_API IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and_product( +template IFC_GEOM_API IfcGeom::NativeElement* 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( +template IFC_GEOM_API IfcGeom::NativeElement* 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( +template IFC_GEOM_API IfcGeom::NativeElement* 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); -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::NativeElement* IfcGeom::Kernel::create_brep_for_processed_representation( + const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement* brep); +template IFC_GEOM_API IfcGeom::NativeElement* IfcGeom::Kernel::create_brep_for_processed_representation( + const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement* brep); +template IFC_GEOM_API IfcGeom::NativeElement* IfcGeom::Kernel::create_brep_for_processed_representation( + const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement* brep); std::pair IfcGeom::Kernel::initializeUnits(IfcSchema::IfcUnitAssignment* unit_assignment) { // Set default units, set length to meters, angles to undefined @@ -1952,7 +1950,7 @@ bool IfcGeom::Kernel::convert_layerset(const IfcSchema::IfcProduct* product, std return false; } - IfcRepresentationShapeItems axis_items; + ConversionResults axis_items; { Kernel temp = *this; temp.setValue(GV_DIMENSIONALITY, -1.); @@ -2144,7 +2142,7 @@ bool IfcGeom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pn return false; } - IfcRepresentationShapeItems items; + ConversionResults items; { Kernel temp = *this; temp.setValue(GV_DIMENSIONALITY, -1.); @@ -2152,8 +2150,8 @@ bool IfcGeom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pn } 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()) { @@ -2172,7 +2170,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::Kernel::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); @@ -2321,7 +2319,7 @@ bool IfcGeom::Kernel::fold_layers(const IfcSchema::IfcWall* wall, const IfcRepre continue; } - IfcRepresentationShapeItems axis_items; + ConversionResults axis_items; { Kernel temp = *this; temp.setValue(GV_DIMENSIONALITY, -1.); @@ -2605,7 +2603,7 @@ namespace { #endif } -bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& items, const std::vector< std::vector >& surfaces, const std::vector& styles, IfcRepresentationShapeItems& result) { +bool IfcGeom::Kernel::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); @@ -2681,11 +2679,11 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i } else if (shells.Extent() == 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.First(), a, b)) { - result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), b, styles[0] ? styles[0] : &it->Style())); - result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), a, styles[1] ? styles[1] : &it->Style())); + if (split_solid_by_shell(*(OpenCascadeShape*)it->Shape(), shells.First(), a, b)) { + result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(b), styles[0] ? styles[0] : &it->Style())); + result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(a), styles[1] ? styles[1] : &it->Style())); } else { continue; } @@ -2695,16 +2693,16 @@ bool IfcGeom::Kernel::apply_folded_layerset(const IfcRepresentationShapeItems& i } else { - for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) { + for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { - const TopoDS_Shape& s = it->Shape(); + const TopoDS_Shape& s = *(OpenCascadeShape*)it->Shape(); TopoDS_Solid sld; ensure_fit_for_subtraction(s, sld); std::vector slices; - if (split(*this, it->Shape(), shells, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) { + if (split(*this, *(OpenCascadeShape*)it->Shape(), shells, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) { for (size_t i = 0; i < slices.size(); ++i) { - result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), slices[i], styles[i] ? styles[i] : &it->Style())); + result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(slices[i]), styles[i] ? styles[i] : &it->Style())); } } else { return false; @@ -2717,18 +2715,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::Kernel::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->ItemId(), it->Placement(), b, styles[0] ? styles[0] : &it->Style())); - result.push_back(IfcRepresentationShapeItem(it->ItemId(), 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->ItemId(), it->Placement()->clone(), new OpenCascadeShape(b), styles[0] ? styles[0] : &it->Style())); + result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(a), styles[1] ? styles[1] : &it->Style())); } else { continue; } @@ -2742,7 +2740,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); } @@ -2767,9 +2765,9 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c mass.ChangeCoord() += n1.XYZ(); */ - for (IfcRepresentationShapeItems::const_iterator it = items.begin(); it != items.end(); ++it) { + for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { - const TopoDS_Shape& s = it->Shape(); + const TopoDS_Shape& s = *(OpenCascadeShape*)it->Shape(); TopoDS_Solid sld; ensure_fit_for_subtraction(s, sld); @@ -2786,9 +2784,9 @@ bool IfcGeom::Kernel::apply_layerset(const IfcRepresentationShapeItems& items, c } std::vector slices; - if (split(*this, it->Shape(), operands, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) { + if (split(*this, *(OpenCascadeShape*)it->Shape(), operands, getValue(GV_PRECISION), slices) && slices.size() == styles.size()) { for (size_t i = 0; i < slices.size(); ++i) { - result.push_back(IfcRepresentationShapeItem(it->ItemId(), it->Placement(), slices[i], styles[i] ? styles[i] : &it->Style())); + result.push_back(ConversionResult(it->ItemId(), it->Placement()->clone(), new OpenCascadeShape(slices[i]), styles[i] ? styles[i] : &it->Style())); } } else { return false; @@ -3201,28 +3199,32 @@ bool IfcGeom::Kernel::triangulate_wire(const TopoDS_Wire& wire, TopTools_ListOfS return true; } -TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const gp_Trsf& t) { - if (t.Form() == gp_Identity) { +TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const OpenCascadePlacement* t) { + if (t == nullptr) { return s; } else { - /// @todo set to 1. and exactly 1. or use epsilon? - if (t.ScaleFactor() != 1.) { - return BRepBuilderAPI_Transform(s, t, true); - } else { - return s.Moved(t); - } + return apply_transformation(s, t->trsf()); } } TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const gp_GTrsf& t) { if (t.Form() == gp_Other) { + Logger::Message(Logger::LOG_WARNING, "Applying non uniform transformation"); return BRepBuilderAPI_GTransform(s, t, true); } else { - return apply_transformation(s, t.Trsf()); } } +TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const gp_Trsf& t) { + /// @todo set to 1. and exactly 1. or use epsilon? + if (t.ScaleFactor() != 1.) { + return BRepBuilderAPI_Transform(s, t, true); + } else { + return s.Moved(t); + } +} + namespace { /* diff --git a/src/ifcgeom/IfcGeomIteratorImplementation.h b/src/ifcgeom/IfcGeomIteratorImplementation.h index b32668a5e8..b430a79edd 100644 --- a/src/ifcgeom/IfcGeomIteratorImplementation.h +++ b/src/ifcgeom/IfcGeomIteratorImplementation.h @@ -76,10 +76,10 @@ #include "../ifcparse/IfcFile.h" #include "../ifcgeom/IfcGeom.h" -#include "../ifcgeom/IfcGeomElement.h" +#include "../ifcgeom_schema_agnostic/IfcGeomElement.h" #include "../ifcgeom_schema_agnostic/IfcGeomMaterial.h" -#include "../ifcgeom/IfcGeomIteratorSettings.h" -#include "../ifcgeom/IfcRepresentationShapeItem.h" +#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h" +#include "../ifcgeom_schema_agnostic/ConversionResult.h" #include "../ifcgeom_schema_agnostic/IfcGeomFilter.h" #include "../ifcgeom_schema_agnostic/IteratorImplementation.h" @@ -112,7 +112,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 @@ -403,7 +403,7 @@ namespace IfcGeom { return associated_single_materials.size() == 1; } - BRepElement* create_shape_model_for_next_entity() { + NativeElement* create_shape_model_for_next_entity() { for (;;) { IfcSchema::IfcRepresentation* representation; @@ -474,7 +474,7 @@ namespace IfcGeom { IfcSchema::IfcProduct* product = *ifcproduct_iterator; Logger::SetProduct(product); - BRepElement* element; + NativeElement* element; if (ifcproduct_iterator == ifcproducts->begin() || !geometry_reuse_ok_for_current_representation_) { element = kernel.create_brep_for_representation_and_product(settings, representation, product); } else { @@ -588,7 +588,7 @@ namespace IfcGeom { } /// Gets the native (Open Cascade) representation of the current geometrical entity. - BRepElement* get_native() + NativeElement* get_native() { // TODO: Test settings and throw return current_shape_model; @@ -646,12 +646,12 @@ namespace IfcGeom { ElementSettings element_settings(settings, unit_magnitude, instance_type); - Element* ifc_object = new Element(element_settings, id, parent_id, product_name, instance_type, product_guid, "", trsf, ifc_product); + Element* ifc_object = new Element(element_settings, id, parent_id, product_name, instance_type, product_guid, "", new OpenCascadePlacement(trsf), ifc_product); return ifc_object; } IfcUtil::IfcBaseClass* create() { - IfcGeom::BRepElement* next_shape_model = 0; + IfcGeom::NativeElement* next_shape_model = 0; IfcGeom::SerializedElement* next_serialization = 0; IfcGeom::TriangulationElement* next_triangulation = 0; diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index e72af56d93..1ace031e56 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -366,7 +366,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::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) { TopoDS_Shape s; const SurfaceStyle* collective_style = get_style(l); if (convert_shape(l->Outer(),s) ) { @@ -391,13 +391,13 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, IfcRepre } } - shape.push_back(IfcRepresentationShapeItem(l->data().id(), s, indiv_style ? indiv_style : collective_style)); + shape.push_back(ConversionResult(l->data().id(), 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::Kernel::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); @@ -405,7 +405,7 @@ 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(l->data().id(), s, shell_style ? shell_style : collective_style)); + shapes.push_back(ConversionResult(l->data().id(), new OpenCascadeShape(s), shell_style ? shell_style : collective_style)); part_success |= true; } } @@ -459,7 +459,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::Kernel::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 ) { @@ -469,7 +469,7 @@ 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(l->data().id(), s, shell_style ? shell_style : collective_style)); + shapes.push_back(ConversionResult(l->data().id(), new OpenCascadeShape(s), shell_style ? shell_style : collective_style)); } } return true; @@ -478,7 +478,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, Ifc bool IfcGeom::Kernel::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(); @@ -664,7 +664,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Sh return true; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, ConversionResults& shapes) { gp_GTrsf gtrsf; IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget(); if ( transform->declaration().is(IfcSchema::IfcCartesianTransformationOperator3DnonUniform::Class()) ) { @@ -699,7 +699,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); + OpenCascadePlacement p(gtrsf); + shapes[i].prepend(&p); // Apply styles assigned to the mapped item only if on // a more granular level no styles have been applied @@ -711,7 +712,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcMappedItem* l, IfcRepresentati return b; } -bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresentationShapeItems& shapes) { +bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, ConversionResults& shapes) { IfcSchema::IfcRepresentationItem::list::ptr items = l->Items(); bool part_succes = false; if ( items->size() ) { @@ -722,7 +723,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresen } else { TopoDS_Shape s; if (convert_shape(representation_item,s)) { - shapes.push_back(IfcRepresentationShapeItem(representation_item->data().id(), s, get_style(representation_item))); + shapes.push_back(ConversionResult(representation_item->data().id(), new OpenCascadeShape(s), get_style(representation_item))); part_succes |= true; } } @@ -731,7 +732,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::Kernel::convert(const IfcSchema::IfcGeometricSet* l, ConversionResults& shapes) { IfcEntityList::ptr elements = l->Elements(); if ( !elements->size() ) return false; bool part_succes = false; @@ -749,7 +750,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresenta } else if (element->declaration().is(IfcSchema::IfcSurface::Class())) { style = get_style((IfcSchema::IfcSurface*) element); } - shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, style ? style : parent_style)); + shapes.push_back(ConversionResult(l->data().id(), new OpenCascadeShape(s), style ? style : parent_style)); } } return part_succes; diff --git a/src/ifcgeom/IfcGeomTree.h b/src/ifcgeom/IfcGeomTree.h index d2acf71c33..e369acc5d3 100644 --- a/src/ifcgeom/IfcGeomTree.h +++ b/src/ifcgeom/IfcGeomTree.h @@ -21,7 +21,7 @@ #define IFCGEOMTREE_H #include "../ifcparse/IfcFile.h" -#include "../ifcgeom/IfcGeomElement.h" +#include "../ifcgeom_schema_agnostic/IfcGeomElement.h" #include "../ifcgeom_schema_agnostic/IfcGeomIterator.h" #include "../ifcgeom_schema_agnostic/Kernel.h" @@ -267,7 +267,7 @@ namespace IfcGeom { if (it.initialize()) { do { - IfcGeom::BRepElement* elem = (IfcGeom::BRepElement*)it.get(); + IfcGeom::NativeElement* elem = (IfcGeom::NativeElement*)it.get(); add((IfcUtil::IfcBaseEntity*)f.instance_by_id(elem->id()), elem->geometry().as_compound()); } while (it.next()); } diff --git a/src/ifcgeom/IfcRegister.cpp b/src/ifcgeom/IfcRegister.cpp index 08773b09e6..b0574c2008 100644 --- a/src/ifcgeom/IfcRegister.cpp +++ b/src/ifcgeom/IfcRegister.cpp @@ -24,11 +24,11 @@ using namespace IfcUtil; -bool IfcGeom::Kernel::convert_shapes(const IfcBaseClass* l, IfcRepresentationShapeItems& r) { +bool IfcGeom::Kernel::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(l->data().id(), shp, get_style(l->as()))); + r.push_back(IfcGeom::ConversionResult(l->data().id(), new OpenCascadeShape(shp), get_style(l->as()))); return true; } return false; @@ -61,7 +61,7 @@ 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" diff --git a/src/ifcgeom/IfcRegisterGeomHeader.h b/src/ifcgeom/IfcRegisterGeomHeader.h index 9969d5e2db..51286f3693 100644 --- a/src/ifcgeom/IfcRegisterGeomHeader.h +++ b/src/ifcgeom/IfcRegisterGeomHeader.h @@ -1,6 +1,6 @@ #include "IfcRegisterUndef.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) diff --git a/src/ifcgeom/IfcRepresentationShapeItem.h b/src/ifcgeom/IfcRepresentationShapeItem.h deleted file mode 100644 index 58a77c4c5b..0000000000 --- a/src/ifcgeom/IfcRepresentationShapeItem.h +++ /dev/null @@ -1,55 +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_schema_agnostic/IfcGeomRenderStyles.h" - -namespace IfcGeom { - class IFC_GEOM_API IfcRepresentationShapeItem { - private: - int id; - gp_GTrsf placement; - TopoDS_Shape shape; - const SurfaceStyle* style; - public: - IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape, const SurfaceStyle* style) - : id(id), placement(placement), shape(shape), style(style) {} - IfcRepresentationShapeItem(int id, const gp_GTrsf& placement, const TopoDS_Shape& shape) - : id(id), placement(placement), shape(shape), style(0) {} - IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape, const SurfaceStyle* style) - : id(id), shape(shape), style(style) {} - IfcRepresentationShapeItem(int id, const TopoDS_Shape& shape) - : id(id), 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; } - int ItemId() const { return id; } - }; - typedef std::vector IfcRepresentationShapeItems; -} -#endif diff --git a/src/ifcgeom/OpenCascadeConversionResult.h b/src/ifcgeom/OpenCascadeConversionResult.h new file mode 100644 index 0000000000..8254510245 --- /dev/null +++ b/src/ifcgeom/OpenCascadeConversionResult.h @@ -0,0 +1,104 @@ +/******************************************************************************** +* * +* 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 + +#include "../ifcgeom_schema_agnostic/ConversionResult.h" + +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_); + } + + virtual ConversionResultPlacement* inverted() const { + return new OpenCascadePlacement(trsf_.Inverted()); + } + + virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement* other) const { + return new OpenCascadePlacement(trsf_.Multiplied(((OpenCascadePlacement*)other)->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 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_); + } + + virtual int surface_genus() const; + private: + TopoDS_Shape shape_; + }; + +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/OpenCascadeShape.cpp b/src/ifcgeom/OpenCascadeShape.cpp new file mode 100644 index 0000000000..bf9e705674 --- /dev/null +++ b/src/ifcgeom/OpenCascadeShape.cpp @@ -0,0 +1,202 @@ +#include "OpenCascadeConversionResult.h" + +#include "../ifcparse/IfcLogger.h" +#include "../ifcgeom_schema_agnostic/IfcGeomRepresentation.h" + +#include "IfcGeom.h" + +#include + +#include + +template +void triangulate_helper(const TopoDS_Shape& s, const IfcGeom::IteratorSettings& settings, const IfcGeom::ConversionResultPlacement* place, IfcGeom::Representation::Triangulation* t, int surface_style_id) { + + gp_GTrsf trsf; + if (place) { + 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(IfcGeom::IteratorSettings::WELD_VERTICES) && + !settings.get(IfcGeom::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() > 1.e-9) { + normal = gp_Dir(normal_direction.XYZ() * rotation_matrix); + } + t->addNormal(normal.X(), normal.Y(), 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->addFace(surface_style_id, dict[n1], dict[n2], dict[n3]); + + 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->registerEdge(jt->first, 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); +} + +void IfcGeom::OpenCascadeShape::Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { + triangulate_helper(shape_, settings, place, t, surface_style_id); +} + +void IfcGeom::OpenCascadeShape::Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { + triangulate_helper(shape_, settings, place, t, surface_style_id); +} + +int IfcGeom::OpenCascadeShape::surface_genus() const { + return IfcGeom::Kernel::surface_genus(shape_); +} \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/todo.cpp b/src/ifcgeom/kernels/cgal/todo.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ifcgeom/kernels/cgal/todo.h b/src/ifcgeom/kernels/cgal/todo.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ifcgeom_schema_agnostic/ConversionResult.h b/src/ifcgeom_schema_agnostic/ConversionResult.h new file mode 100644 index 0000000000..2f2b9d9796 --- /dev/null +++ b/src/ifcgeom_schema_agnostic/ConversionResult.h @@ -0,0 +1,93 @@ +/******************************************************************************** + * * + * 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_schema_agnostic/IfcGeomRenderStyles.h" +#include "../ifcgeom_schema_agnostic/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 ConversionResultPlacement* inverted() const = 0; + virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement*) const = 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 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 int surface_genus() const = 0; + virtual ~ConversionResultShape() {} + }; + + class IFC_GEOM_API ConversionResult { + private: + int id; + ConversionResultPlacement* placement; + ConversionResultShape* shape; + const SurfaceStyle* style; + public: + ConversionResult(int id, const ConversionResultPlacement* placement, const ConversionResultShape* shape, const SurfaceStyle* style) + : id(id), placement(placement->clone()), shape(shape->clone()), style(style) {} + ConversionResult(int id, const ConversionResultPlacement* placement, const ConversionResultShape* shape) + : id(id), placement(placement->clone()), shape(shape->clone()), style(0) {} + ConversionResult(int id, const ConversionResultShape* shape, const SurfaceStyle* style) + : id(id), placement(0), shape(shape->clone()), style(style) {} + ConversionResult(int id, const ConversionResultShape* shape) + : id(id), 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; } + int ItemId() const { return id; } + }; + + typedef std::vector ConversionResults; +} +#endif diff --git a/src/ifcgeom/IfcGeomElement.h b/src/ifcgeom_schema_agnostic/IfcGeomElement.h similarity index 85% rename from src/ifcgeom/IfcGeomElement.h rename to src/ifcgeom_schema_agnostic/IfcGeomElement.h index 26ecd7341b..fa6e00a107 100644 --- a/src/ifcgeom/IfcGeomElement.h +++ b/src/ifcgeom_schema_agnostic/IfcGeomElement.h @@ -25,8 +25,8 @@ #include "../ifcparse/IfcGlobalId.h" -#include "../ifcgeom/IfcGeomRepresentation.h" -#include "../ifcgeom/IfcGeomIteratorSettings.h" +#include "../ifcgeom_schema_agnostic/IfcGeomRepresentation.h" +#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h" #include "ifc_geom_api.h" namespace IfcGeom { @@ -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; @@ -59,23 +59,23 @@ namespace IfcGeom { class Transformation { private: ElementSettings settings_; - gp_Trsf trsf_; + ConversionResultPlacement* trsf_; Matrix

matrix_; public: - Transformation(const ElementSettings& settings, const gp_Trsf& trsf) + Transformation(const ElementSettings& settings, const ConversionResultPlacement* trsf) : settings_(settings) - , trsf_(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_; } Transformation inverted() const { - return Transformation(settings_, trsf_.Inverted()); + return Transformation(settings_, trsf_->inverted()); } Transformation multiplied(const Transformation& other) const { - return Transformation(settings_, trsf_.Multiplied(other.data())); + return Transformation(settings_, trsf_->multiplied(other.data())); } }; @@ -129,7 +129,7 @@ namespace IfcGeom { void SetParents(std::vector*> newparents) { _parents = newparents; } 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, IfcUtil::IfcBaseEntity* product) + const std::string& guid, const std::string& context, const ConversionResultPlacement* trsf, IfcUtil::IfcBaseEntity* product) : _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _context(context), _transformation(settings, trsf) , product_(product) { @@ -159,28 +159,25 @@ namespace IfcGeom { }; template - class BRepElement : public Element { + class NativeElement : public Element { private: 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, + 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, IfcUtil::IfcBaseEntity* product) : Element(geometry->settings() ,id, parent_id, name, type, guid, context, trsf, product) , _geometry(geometry) {} bool calculate_projected_surface_area(double& along_x, double& along_y, double& along_z) const { - const auto& trsf = this->transformation().data(); - const gp_Mat& mat = trsf.HVectorialPart(); - gp_Ax3 ax(trsf.TranslationPart(), mat.Column(3), mat.Column(1)); - return geometry().calculate_projected_surface_area(ax, along_x, along_y, along_z); + return geometry().calculate_projected_surface_area(this->transformation().data(), along_x, along_y, along_z); } private: - BRepElement(const BRepElement& other); - BRepElement& operator=(const BRepElement& other); + NativeElement(const NativeElement& other); + NativeElement& operator=(const NativeElement& other); }; template @@ -190,7 +187,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()))) {} @@ -209,7 +206,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_schema_agnostic/IfcGeomIterator.h b/src/ifcgeom_schema_agnostic/IfcGeomIterator.h index 4658d37780..babff4709f 100644 --- a/src/ifcgeom_schema_agnostic/IfcGeomIterator.h +++ b/src/ifcgeom_schema_agnostic/IfcGeomIterator.h @@ -119,7 +119,7 @@ namespace IfcGeom { Element* get() { return implementation_->get(); } - BRepElement* get_native() { return implementation_->get_native(); } + NativeElement* get_native() { return implementation_->get_native(); } const Element* get_object(int id) { return implementation_->get_object(id); } diff --git a/src/ifcgeom/IfcGeomIteratorSettings.h b/src/ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h similarity index 99% rename from src/ifcgeom/IfcGeomIteratorSettings.h rename to src/ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h index 7928d296ec..662d475e1e 100644 --- a/src/ifcgeom/IfcGeomIteratorSettings.h +++ b/src/ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h @@ -23,6 +23,7 @@ #include "ifc_geom_api.h" #include "../ifcparse/IfcException.h" #include "../ifcparse/IfcBaseClass.h" +#include "../ifcparse/IfcLogger.h" namespace IfcGeom { diff --git a/src/ifcgeom_schema_agnostic/IfcGeomRenderStyles.h b/src/ifcgeom_schema_agnostic/IfcGeomRenderStyles.h index 804e1caa12..ec0b5ed265 100644 --- a/src/ifcgeom_schema_agnostic/IfcGeomRenderStyles.h +++ b/src/ifcgeom_schema_agnostic/IfcGeomRenderStyles.h @@ -20,7 +20,7 @@ #ifndef IFCGEOMRENDERSTYLES_H #define IFCGEOMRENDERSTYLES_H -#include "../ifcgeom/ifc_geom_api.h" +#include "../ifcgeom_schema_agnostic/ifc_geom_api.h" #include #include diff --git a/src/ifcgeom/IfcGeomRepresentation.cpp b/src/ifcgeom_schema_agnostic/IfcGeomRepresentation.cpp similarity index 84% rename from src/ifcgeom/IfcGeomRepresentation.cpp rename to src/ifcgeom_schema_agnostic/IfcGeomRepresentation.cpp index 4a6158601a..011fd96a4d 100644 --- a/src/ifcgeom/IfcGeomRepresentation.cpp +++ b/src/ifcgeom_schema_agnostic/IfcGeomRepresentation.cpp @@ -26,16 +26,16 @@ #include #include -#include "../ifcgeom/IfcGeom.h" - #include "IfcGeomRepresentation.h" +#include "../ifcgeom/OpenCascadeConversionResult.h" +#include "../ifcgeom_schema_agnostic/Kernel.h" IfcGeom::Representation::Serialization::Serialization(const BRep& brep) : Representation(brep.settings()) , id_(brep.id()) { TopoDS_Compound compound = brep.as_compound(); - for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++ it) { + for (IfcGeom::ConversionResults::const_iterator it = brep.begin(); it != brep.end(); ++ it) { if (it->hasStyle() && it->Style().Diffuse()) { const IfcGeom::SurfaceStyle::ColorComponent& clr = *it->Style().Diffuse(); surface_styles_.push_back(clr.R()); @@ -57,7 +57,7 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep) brep_data_ = sstream.str(); } -// todo copied from kernel +// @todo copied from kernel #include #include @@ -86,9 +86,13 @@ TopoDS_Compound IfcGeom::Representation::BRep::as_compound() const { TopoDS_Compound compound; BRep_Builder builder; builder.MakeCompound(compound); - for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = begin(); it != end(); ++it) { - const TopoDS_Shape& s = it->Shape(); - gp_GTrsf trsf = it->Placement(); + + for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) { + const TopoDS_Shape& s = *(OpenCascadeShape*) it->Shape(); + gp_GTrsf trsf; + if (it->Placement()) { + trsf = ((OpenCascadePlacement*)it->Placement())->trsf(); + } if (settings().get(IteratorSettings::CONVERT_BACK_UNITS)) { gp_Trsf scale; @@ -166,7 +170,7 @@ namespace { const gp_Vec v2 = pt3 - pt2; const gp_Vec v3 = pt1 - pt3; const gp_Vec normal_vector = v1 ^ v2; - if (normal_vector.Magnitude() > ALMOST_ZERO) { + if (normal_vector.Magnitude() > 1.e-9) { gp_Dir normal = gp_Dir(); double edge_lengths[3] = { v1.Magnitude(), v2.Magnitude(), v3.Magnitude() }; @@ -190,9 +194,9 @@ bool IfcGeom::Representation::BRep::calculate_surface_area(double& area) const { try { area = 0.; - for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = begin(); it != end(); ++it) { + for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) { GProp_GProps prop; - BRepGProp::SurfaceProperties(it->Shape(), prop); + BRepGProp::SurfaceProperties(*(OpenCascadeShape*)it->Shape(), prop); area += prop.Mass(); } @@ -207,10 +211,10 @@ bool IfcGeom::Representation::BRep::calculate_volume(double& volume) const { try { volume = 0.; - for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = begin(); it != end(); ++it) { - if (Kernel::is_manifold(it->Shape())) { + for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) { + if (Kernel::is_manifold(*(OpenCascadeShape*)it->Shape())) { GProp_GProps prop; - BRepGProp::VolumeProperties(it->Shape(), prop); + BRepGProp::VolumeProperties(*(OpenCascadeShape*)it->Shape(), prop); volume += prop.Mass(); } else { return false; @@ -224,15 +228,19 @@ bool IfcGeom::Representation::BRep::calculate_volume(double& volume) const { } } -bool IfcGeom::Representation::BRep::calculate_projected_surface_area(const gp_Ax3 & ax, double & along_x, double & along_y, double & along_z) const { +bool IfcGeom::Representation::BRep::calculate_projected_surface_area(const ConversionResultPlacement* place, double & along_x, double & along_y, double & along_z) const { try { + gp_Trsf trsf = ((OpenCascadePlacement*)place)->trsf().Trsf(); + gp_Mat mat = trsf.HVectorialPart(); + gp_Ax3 ax(trsf.TranslationPart(), mat.Column(3), mat.Column(1)); + along_x = along_y = along_z = 0.; - for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = begin(); it != end(); ++it) { + for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) { double x, y, z; - surface_area_along_direction(settings().deflection_tolerance(), it->Shape(), ax, x, y, z); + surface_area_along_direction(settings().deflection_tolerance(), *(OpenCascadeShape*)it->Shape(), ax, x, y, z); - if (Kernel::is_manifold(it->Shape())) { + if (Kernel::is_manifold(*(OpenCascadeShape*)it->Shape())) { x /= 2.; y /= 2.; z /= 2.; diff --git a/src/ifcgeom/IfcGeomRepresentation.h b/src/ifcgeom_schema_agnostic/IfcGeomRepresentation.h similarity index 50% rename from src/ifcgeom/IfcGeomRepresentation.h rename to src/ifcgeom_schema_agnostic/IfcGeomRepresentation.h index 7f1eb8f9e5..f67b130b43 100644 --- a/src/ifcgeom/IfcGeomRepresentation.h +++ b/src/ifcgeom_schema_agnostic/IfcGeomRepresentation.h @@ -35,12 +35,14 @@ #include #include -#include "../ifcgeom/IfcGeomIteratorSettings.h" +#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h" #include "../ifcgeom_schema_agnostic/IfcGeomMaterial.h" -#include "../ifcgeom/IfcRepresentationShapeItem.h" +#include "../ifcgeom_schema_agnostic/ConversionResult.h" #include +#include + namespace IfcGeom { namespace Representation { @@ -61,25 +63,25 @@ namespace IfcGeom { class IFC_GEOM_API BRep : public Representation { private: std::string id_; - const IfcGeom::IfcRepresentationShapeItems shapes_; + const IfcGeom::ConversionResults shapes_; BRep(const BRep& other); BRep& operator=(const BRep& other); public: - BRep(const ElementSettings& settings, const std::string& id, const IfcGeom::IfcRepresentationShapeItems& shapes) + BRep(const ElementSettings& settings, const std::string& 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_; } + 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 std::string& id() const { return id_; } TopoDS_Compound as_compound() const; bool calculate_volume(double&) const; bool calculate_surface_area(double&) const; - bool calculate_projected_surface_area(const gp_Ax3& ax, double& along_x, double& along_y, double& along_z) const; + bool calculate_projected_surface_area(const ConversionResultPlacement* ax, double& along_x, double& along_y, double& along_z) const; }; class IFC_GEOM_API Serialization : public Representation { @@ -133,7 +135,7 @@ namespace IfcGeom { : Representation(shape_model.settings()) , id_(shape_model.id()) { - 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()) { @@ -158,192 +160,7 @@ 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(...) { - 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() > 1.e-9) { - normal = gp_Dir(normal_direction.XYZ() * rotation_matrix); - } else { - Handle_Geom_Surface surf = BRep_Tool::Surface(face); - // Special case the normal at the poles of a spherical surface - if (surf->DynamicType() == STANDARD_TYPE(Geom_SphericalSurface)) { - if (fabs(fabs(uv.Y()) - M_PI / 2.) < 1.e-9) { - const bool is_top = uv.Y() > 0; - const bool is_forward = face.Orientation() == TopAbs_FORWARD; - const double z = (is_top == is_forward) ? 1. : -1.; - normal = gp_Dir(gp_XYZ(0, 0, z) * rotation_matrix); - } - } - // TODO: Do the same for conical surfaces, but they are rare in IFC. - } - _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() {} @@ -378,13 +195,14 @@ 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))); @@ -398,12 +216,34 @@ namespace IfcGeom { _verts.push_back(Z); return i; } + inline void addEdge(int n1, int n2, std::map,int>& edgecount, std::vector >& edges_temp) { const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) ); if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1; else edgecount[e] ++; edges_temp.push_back(e); } + + inline void addNormal(P X, P Y, P Z) { + _normals.push_back(X); + _normals.push_back(Y); + _normals.push_back(Z); + } + + inline void addFace(int style, int i0, int i1, int i2) { + _faces.push_back(i0); + _faces.push_back(i1); + _faces.push_back(i2); + + _material_ids.push_back(style); + } + + inline void registerEdge(int i0, int i1) { + _edges.push_back(i0); + _edges.push_back(i1); + } + + private: Triangulation(); Triangulation(const Triangulation&); Triangulation& operator=(const Triangulation&); diff --git a/src/ifcgeom_schema_agnostic/IteratorImplementation.h b/src/ifcgeom_schema_agnostic/IteratorImplementation.h index 69ddbb618f..5417584c20 100644 --- a/src/ifcgeom_schema_agnostic/IteratorImplementation.h +++ b/src/ifcgeom_schema_agnostic/IteratorImplementation.h @@ -3,7 +3,7 @@ #include "../ifcgeom_schema_agnostic/IfcGeomFilter.h" #include "../ifcparse/IfcFile.h" -#include "../ifcgeom/IfcGeomIteratorSettings.h" +#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h" #include @@ -20,7 +20,7 @@ namespace IfcGeom { class Element; template - class BRepElement; + class NativeElement; } typedef boost::function3*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector&> iterator_float_float_fn; @@ -71,7 +71,7 @@ namespace IfcGeom { virtual IfcParse::IfcFile* file() const = 0; virtual IfcUtil::IfcBaseClass* next() = 0; virtual Element* get() = 0; - virtual BRepElement* get_native() = 0; + virtual NativeElement* get_native() = 0; virtual const Element* get_object(int id) = 0; virtual IfcUtil::IfcBaseClass* create() = 0; }; diff --git a/src/ifcgeom_schema_agnostic/Kernel.h b/src/ifcgeom_schema_agnostic/Kernel.h index c924f8af6a..5f1fdac66c 100644 --- a/src/ifcgeom_schema_agnostic/Kernel.h +++ b/src/ifcgeom_schema_agnostic/Kernel.h @@ -2,8 +2,8 @@ #define ITERATOR_KERNEL_H #include "../ifcparse/IfcFile.h" -#include "../ifcgeom/IfcGeomIteratorSettings.h" -#include "../ifcgeom/IfcRepresentationShapeItem.h" +#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h" +#include "../ifcgeom_schema_agnostic/ConversionResult.h" #include "../ifcparse/Ifc2x3.h" #include "../ifcparse/Ifc4.h" @@ -15,7 +15,7 @@ namespace IfcGeom { template - class BRepElement; + class NativeElement; class Kernel { private: @@ -64,14 +64,14 @@ namespace IfcGeom { return implementation_->getValue(var); } - virtual BRepElement* convert( + virtual NativeElement* convert( const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation, IfcUtil::IfcBaseClass* product) { return implementation_->convert(settings, representation, product); } - virtual IfcRepresentationShapeItems convert(IfcUtil::IfcBaseClass* item) { + virtual ConversionResults convert(IfcUtil::IfcBaseClass* item) { return implementation_->convert(item); } diff --git a/src/ifcgeom_schema_agnostic/Serialization.h b/src/ifcgeom_schema_agnostic/Serialization.h index be3d79bd3f..e7adf5f057 100644 --- a/src/ifcgeom_schema_agnostic/Serialization.h +++ b/src/ifcgeom_schema_agnostic/Serialization.h @@ -1,4 +1,4 @@ -#include "../ifcgeom/ifc_geom_api.h" +#include "../ifcgeom_schema_agnostic/ifc_geom_api.h" #include "../ifcparse/IfcBaseClass.h" #include diff --git a/src/ifcgeom/ifc_geom_api.h b/src/ifcgeom_schema_agnostic/ifc_geom_api.h similarity index 100% rename from src/ifcgeom/ifc_geom_api.h rename to src/ifcgeom_schema_agnostic/ifc_geom_api.h diff --git a/src/ifcgeom_schema_agnostic_cgal/todo.cpp b/src/ifcgeom_schema_agnostic_cgal/todo.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ifcgeom_schema_agnostic_cgal/todo.h b/src/ifcgeom_schema_agnostic_cgal/todo.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ifcgeomserver/IfcGeomServer.cpp b/src/ifcgeomserver/IfcGeomServer.cpp index ed340a7a48..7a2cc9ee90 100644 --- a/src/ifcgeomserver/IfcGeomServer.cpp +++ b/src/ifcgeomserver/IfcGeomServer.cpp @@ -39,7 +39,7 @@ #endif #include "../ifcgeom_schema_agnostic/IfcGeomIterator.h" -#include "../ifcgeom/IfcGeomElement.h" +#include "../ifcgeom_schema_agnostic/IfcGeomElement.h" #include "../ifcparse/IfcFile.h" #include "../ifcparse/IfcLogger.h" @@ -404,9 +404,9 @@ static const std::string WALKABLE_SURFACE_AREA = "WALKABLE_SURFACE_AREA"; class QuantityWriter_v0 : public EntityExtension { private: - const IfcGeom::BRepElement* elem_; + const IfcGeom::NativeElement* elem_; public: - QuantityWriter_v0(const IfcGeom::BRepElement* elem) : + QuantityWriter_v0(const IfcGeom::NativeElement* elem) : elem_(elem) { put_json(TOTAL_SURFACE_AREA, 0.); @@ -419,9 +419,9 @@ public: class QuantityWriter_v1 : public EntityExtension { private: - const IfcGeom::BRepElement* elem_; + const IfcGeom::NativeElement* elem_; public: - QuantityWriter_v1(const IfcGeom::BRepElement* elem) : + QuantityWriter_v1(const IfcGeom::NativeElement* elem) : elem_(elem) { double a, b, c; diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index ce359b1708..80a67a6745 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -369,7 +369,7 @@ struct ShapeRTTI : public boost::static_visitor } } - IfcGeom::BRepElement* brep = kernel.convert(settings, ifc_representation, product); + IfcGeom::NativeElement* brep = kernel.convert(settings, ifc_representation, product); if (!brep) { throw IfcParse::IfcException("Failed to process shape"); } @@ -387,7 +387,7 @@ struct ShapeRTTI : public boost::static_visitor } else { if (!representation) { if (instance->declaration().is(Schema::IfcRepresentationItem::Class()) || instance->declaration().is(Schema::IfcRepresentation::Class())) { - IfcGeom::IfcRepresentationShapeItems shapes = kernel.convert(instance); + IfcGeom::ConversionResults shapes = kernel.convert(instance); IfcGeom::ElementSettings element_settings(settings, kernel.getValue(IfcGeom::Kernel::GV_LENGTH_UNIT), instance->declaration().name()); IfcGeom::Representation::BRep brep(element_settings, boost::lexical_cast(instance->data().id()), shapes); diff --git a/src/serializers/ColladaSerializer.h b/src/serializers/ColladaSerializer.h index 84cd4b7c69..d85dc989a0 100644 --- a/src/serializers/ColladaSerializer.h +++ b/src/serializers/ColladaSerializer.h @@ -230,7 +230,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/serializers/GeometrySerializer.h b/src/serializers/GeometrySerializer.h index 0673a1cc65..45b14d8660 100644 --- a/src/serializers/GeometrySerializer.h +++ b/src/serializers/GeometrySerializer.h @@ -28,7 +28,7 @@ typedef float real_t; #include "../serializers/Serializer.h" #include "../ifcgeom_schema_agnostic/IfcGeomIterator.h" -#include "../ifcgeom/IfcGeomElement.h" +#include "../ifcgeom_schema_agnostic/IfcGeomElement.h" class SerializerSettings : public IfcGeom::IteratorSettings { @@ -77,7 +77,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 SerializerSettings& settings() const { return settings_; } diff --git a/src/serializers/IgesSerializer.h b/src/serializers/IgesSerializer.h index 93fca9b514..77845d0116 100644 --- a/src/serializers/IgesSerializer.h +++ b/src/serializers/IgesSerializer.h @@ -42,8 +42,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/serializers/OpenCascadeBasedSerializer.cpp b/src/serializers/OpenCascadeBasedSerializer.cpp index d19c80566d..257fa83e4e 100644 --- a/src/serializers/OpenCascadeBasedSerializer.cpp +++ b/src/serializers/OpenCascadeBasedSerializer.cpp @@ -34,7 +34,7 @@ bool OpenCascadeBasedSerializer::ready() { return succeeded; } -void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement* o) { +void OpenCascadeBasedSerializer::write(const IfcGeom::NativeElement* o) { TopoDS_Shape compound = o->geometry().as_compound(); if (o->geometry().settings().get(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS)) { @@ -44,7 +44,8 @@ void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement* o) { compound = BRepBuilderAPI_Transform(compound, scale, true).Shape(); } - writeShape(compound); + IfcGeom::OpenCascadeShape s(compound); + writeShape(&s); } #define RATHER_SMALL (1e-3) diff --git a/src/serializers/OpenCascadeBasedSerializer.h b/src/serializers/OpenCascadeBasedSerializer.h index 048c1228a4..e1f78e1401 100644 --- a/src/serializers/OpenCascadeBasedSerializer.h +++ b/src/serializers/OpenCascadeBasedSerializer.h @@ -21,7 +21,7 @@ #define OPENCASCADEBASEDSERIALIZER_H #include "../ifcgeom_schema_agnostic/IfcGeomIterator.h" - +#include "../ifcgeom/OpenCascadeConversionResult.h" #include "../serializers/GeometrySerializer.h" class OpenCascadeBasedSerializer : public GeometrySerializer { @@ -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/serializers/StepSerializer.h b/src/serializers/StepSerializer.h index db9ea54d77..5b31bace6e 100644 --- a/src/serializers/StepSerializer.h +++ b/src/serializers/StepSerializer.h @@ -36,10 +36,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)->shape(), STEPControl_AsIs); std::cout.rdbuf(sb); } void finalize() { diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index 9710b5338c..720448294a 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -283,14 +283,14 @@ SvgSerializer::path_object& SvgSerializer::start_path(IfcUtil::IfcBaseEntity* st return p; } -void SvgSerializer::write(const IfcGeom::BRepElement* o) +void SvgSerializer::write(const IfcGeom::NativeElement* o) { IfcUtil::IfcBaseEntity* storey = storey_; boost::optional storey_elevation = boost::none; /* - TODO: based on BRepElement::parent() + TODO: based on NativeElement::parent() IfcSchema::IfcObjectDefinition* obdef = static_cast(file->entityById(o->id())); diff --git a/src/serializers/SvgSerializer.h b/src/serializers/SvgSerializer.h index f1ec93cb76..81f661bd4c 100644 --- a/src/serializers/SvgSerializer.h +++ b/src/serializers/SvgSerializer.h @@ -62,7 +62,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(IfcUtil::IfcBaseEntity* storey, const std::string& id); bool isTesselated() const { return false; } diff --git a/src/serializers/WavefrontObjSerializer.h b/src/serializers/WavefrontObjSerializer.h index 299dc065b6..80866eb122 100644 --- a/src/serializers/WavefrontObjSerializer.h +++ b/src/serializers/WavefrontObjSerializer.h @@ -51,7 +51,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*/) {}