diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 063b4d8abf..38f9e0d457 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -23,71 +23,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, Convers return part_succes; } -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal_shape_t &shape) { - const double height = l->Depth() * getValue(GV_LENGTH_UNIT); - if (height < getValue(GV_PRECISION)) { - Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l->entity); - return false; - } - - cgal_face_t face; - if ( !convert_face(l->SweptArea(),face) ) return false; - - cgal_placement_t trsf; - bool has_position = true; -#ifdef USE_IFC4 - has_position = l->hasPosition(); -#endif - if (has_position) { - IfcGeom::CgalKernel::convert(l->Position(), trsf); - } - - cgal_direction_t dir; - convert(l->ExtrudedDirection(),dir); -// std::cout << "Direction: " << dir << std::endl; - - std::list face_list; - face_list.push_back(face); - - for (std::vector::const_iterator current_vertex = face.outer.begin(); - current_vertex != face.outer.end(); - ++current_vertex) { - std::vector::const_iterator next_vertex = current_vertex; - ++next_vertex; - if (next_vertex == face.outer.end()) { - next_vertex = face.outer.begin(); - } cgal_face_t side_face; - side_face.outer.push_back(*next_vertex); - side_face.outer.push_back(*current_vertex); - side_face.outer.push_back(*current_vertex+height*dir); - side_face.outer.push_back(*next_vertex+height*dir); - face_list.push_back(side_face); - } - - cgal_face_t top_face; - for (std::vector::const_reverse_iterator vertex = face.outer.rbegin(); - vertex != face.outer.rend(); - ++vertex) { - top_face.outer.push_back(*vertex+height*dir); - } face_list.push_back(top_face); - - // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); - PolyhedronBuilder builder(&face_list); - polyhedron.delegate(builder); - - // Stitch edges -// std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); - if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { - CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } -// std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - - shape = polyhedron; - return true; -} - bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { std::vector xyz = l->Coordinates(); if (xyz.size() == 3) { @@ -209,30 +144,3 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_p // CACHE(IfcObjectPlacement,l,trsf) return true; } - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cgal_face_t& face) { - const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); - const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); - - if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) { - Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); - return false; - } - - cgal_placement_t trsf2d; - bool has_position = true; -#ifdef USE_IFC4 - has_position = l->hasPosition(); -#endif - if (has_position) { - IfcGeom::CgalKernel::convert(l->Position(), trsf2d); - } - - face = cgal_face_t(); - face.outer.push_back(Kernel::Point_3(-x, -y, 0.0)); - face.outer.push_back(Kernel::Point_3( x, -y, 0.0)); - face.outer.push_back(Kernel::Point_3( x, y, 0.0)); - face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); - - return true; -} diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index d7c576a4e7..26d5f819c1 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -81,79 +81,6 @@ bool IfcGeom::CgalKernel::convert_shape(const IfcBaseClass* l, cgal_shape_t& r) return success; } -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) { - cgal_shape_t s; - const SurfaceStyle* collective_style = get_style(l); - if (convert_shape(l->Outer(),s) ) { - const SurfaceStyle* indiv_style = get_style(l->Outer()); - - IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list); - if (l->is(IfcSchema::Type::IfcFacetedBrepWithVoids)) { - voids = l->as()->Voids(); - } -#ifdef USE_IFC4 - if (l->is(IfcSchema::Type::IfcAdvancedBrepWithVoids)) { - voids = l->as()->Voids(); - } -#endif - - for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) { -// TopoDS_Shape s2; -// /// @todo No extensive shapefixing since shells should be disjoint. -// /// @todo Awaiting generalized boolean ops module with appropriate checking -// if (convert_shape(l->Outer(), s2)) { -// s = BRepAlgoAPI_Cut(s, s2).Shape(); -// } - } - - shape.push_back(ConversionResult(new CgalShape(s), indiv_style ? indiv_style : collective_style)); - return true; - } - return false; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_shape_t& shape) { - IfcSchema::IfcFace::list::ptr faces = l->CfsFaces(); - - std::list face_list; - for (IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++it) { - bool success = false; - cgal_face_t face; - - try { - success = convert_face(*it, face); - } catch (...) {} - - if (!success) { - Logger::Message(Logger::LOG_WARNING, "Failed to convert face:", (*it)->entity); - continue; - } - -// std::cout << "Face in ConnectedFaceSet: " << std::endl; -// for (auto &point: face.outer) { -// std::cout << "\tPoint(" << point << ")" << std::endl; -// } - - face_list.push_back(face); - } - - // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); - PolyhedronBuilder builder(&face_list); - polyhedron.delegate(builder); - - // Stitch edges -// std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); - if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { - CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } -// std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - - shape = polyhedron; - return true; -} - bool IfcGeom::CgalKernel::convert_wire(const IfcBaseClass* l, cgal_wire_t& r) { #include "CgalEntityMappingWire.h" Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); @@ -166,94 +93,6 @@ bool IfcGeom::CgalKernel::convert_face(const IfcBaseClass* l, cgal_face_t& r) { return false; } -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face) { - IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds(); - - int num_outer_bounds = 0; - - for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { - IfcSchema::IfcFaceBound* bound = *it; - if (bound->is(IfcSchema::Type::IfcFaceOuterBound)) num_outer_bounds ++; - } - - if (num_outer_bounds != 1) { - Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity); - return false; - } - - cgal_face_t mf; - - for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { - IfcSchema::IfcFaceBound* bound = *it; - IfcSchema::IfcLoop* loop = bound->Bound(); - - const bool is_interior = !bound->is(IfcSchema::Type::IfcFaceOuterBound); - - cgal_wire_t wire; - if (!convert_wire(loop, wire)) { - Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity); - return false; - } - - if (!is_interior) { - mf.outer = wire; - } else { - mf.inner.push_back(wire); - } - } - - face = mf; - -// std::cout << "Face: " << std::endl; -// for (auto &point: face.outer) { -// std::cout << "\tPoint(" << point << ")" << std::endl; -// } - - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& result) { - IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon(); - - // Parse and store the points in a sequence - cgal_wire_t polygon = std::vector(); - for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) { - cgal_point_t pnt; - IfcGeom::CgalKernel::convert(*it, pnt); - polygon.push_back(pnt); - } - - // A loop should consist of at least three vertices - std::size_t original_count = polygon.size(); - if (original_count < 3) { - Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); - return false; - } - - // TODO: Remove repeated points (and points that are too close to one another?) -// remove_duplicate_points_from_loop(polygon, true); - - std::size_t count = polygon.size(); - if (original_count - count != 0) { - std::stringstream ss; ss << (original_count - count) << " edges removed for:"; - Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity); - } - - if (count < 3) { - Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); - return false; - } - - result = polygon; - -// std::cout << "PolyLoop: " << std::endl; -// for (auto &point: polygon) { -// std::cout << "\tPoint(" << point << ")" << std::endl; -// } - - return true; -} - bool IfcGeom::CgalKernel::convert_curve(const IfcBaseClass* l, cgal_curve_t& r) { #include "CgalEntityMappingCurve.h" Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp new file mode 100644 index 0000000000..6cd88a434b --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -0,0 +1,74 @@ +#include "CgalKernel.h" + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cgal_face_t& face) { + const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + } + + face = cgal_face_t(); + face.outer.push_back(Kernel::Point_3(-x, -y, 0.0)); + face.outer.push_back(Kernel::Point_3( x, -y, 0.0)); + face.outer.push_back(Kernel::Point_3( x, y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); + + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face) { + IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds(); + + int num_outer_bounds = 0; + + for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { + IfcSchema::IfcFaceBound* bound = *it; + if (bound->is(IfcSchema::Type::IfcFaceOuterBound)) num_outer_bounds ++; + } + + if (num_outer_bounds != 1) { + Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity); + return false; + } + + cgal_face_t mf; + + for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { + IfcSchema::IfcFaceBound* bound = *it; + IfcSchema::IfcLoop* loop = bound->Bound(); + + const bool is_interior = !bound->is(IfcSchema::Type::IfcFaceOuterBound); + + cgal_wire_t wire; + if (!convert_wire(loop, wire)) { + Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity); + return false; + } + + if (!is_interior) { + mf.outer = wire; + } else { + mf.inner.push_back(wire); + } + } + + face = mf; + + // std::cout << "Face: " << std::endl; + // for (auto &point: face.outer) { + // std::cout << "\tPoint(" << point << ")" << std::endl; + // } + + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp new file mode 100644 index 0000000000..b8efaf7f18 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -0,0 +1,140 @@ +#include "CgalKernel.h" +#include "CgalConversionResult.h" + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) { + cgal_shape_t s; + const SurfaceStyle* collective_style = get_style(l); + if (convert_shape(l->Outer(),s) ) { + const SurfaceStyle* indiv_style = get_style(l->Outer()); + + IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list); + if (l->is(IfcSchema::Type::IfcFacetedBrepWithVoids)) { + voids = l->as()->Voids(); + } +#ifdef USE_IFC4 + if (l->is(IfcSchema::Type::IfcAdvancedBrepWithVoids)) { + voids = l->as()->Voids(); + } +#endif + + for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) { + // TopoDS_Shape s2; + // /// @todo No extensive shapefixing since shells should be disjoint. + // /// @todo Awaiting generalized boolean ops module with appropriate checking + // if (convert_shape(l->Outer(), s2)) { + // s = BRepAlgoAPI_Cut(s, s2).Shape(); + // } + } + + shape.push_back(ConversionResult(new CgalShape(s), indiv_style ? indiv_style : collective_style)); + return true; + } + return false; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal_shape_t &shape) { + const double height = l->Depth() * getValue(GV_LENGTH_UNIT); + if (height < getValue(GV_PRECISION)) { + Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", l->entity); + return false; + } + + cgal_face_t face; + if ( !convert_face(l->SweptArea(),face) ) return false; + + cgal_placement_t trsf; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf); + } + + cgal_direction_t dir; + convert(l->ExtrudedDirection(),dir); + // std::cout << "Direction: " << dir << std::endl; + + std::list face_list; + face_list.push_back(face); + + for (std::vector::const_iterator current_vertex = face.outer.begin(); + current_vertex != face.outer.end(); + ++current_vertex) { + std::vector::const_iterator next_vertex = current_vertex; + ++next_vertex; + if (next_vertex == face.outer.end()) { + next_vertex = face.outer.begin(); + } cgal_face_t side_face; + side_face.outer.push_back(*next_vertex); + side_face.outer.push_back(*current_vertex); + side_face.outer.push_back(*current_vertex+height*dir); + side_face.outer.push_back(*next_vertex+height*dir); + face_list.push_back(side_face); + } + + cgal_face_t top_face; + for (std::vector::const_reverse_iterator vertex = face.outer.rbegin(); + vertex != face.outer.rend(); + ++vertex) { + top_face.outer.push_back(*vertex+height*dir); + } face_list.push_back(top_face); + + // Naive creation + cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + PolyhedronBuilder builder(&face_list); + polyhedron.delegate(builder); + + // Stitch edges + // std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); + if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { + CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); + } + // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + + shape = polyhedron; + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_shape_t& shape) { + IfcSchema::IfcFace::list::ptr faces = l->CfsFaces(); + + std::list face_list; + for (IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++it) { + bool success = false; + cgal_face_t face; + + try { + success = convert_face(*it, face); + } catch (...) {} + + if (!success) { + Logger::Message(Logger::LOG_WARNING, "Failed to convert face:", (*it)->entity); + continue; + } + + // std::cout << "Face in ConnectedFaceSet: " << std::endl; + // for (auto &point: face.outer) { + // std::cout << "\tPoint(" << point << ")" << std::endl; + // } + + face_list.push_back(face); + } + + // Naive creation + cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + PolyhedronBuilder builder(&face_list); + polyhedron.delegate(builder); + + // Stitch edges + // std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); + if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { + CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); + } + // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + + shape = polyhedron; + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp new file mode 100644 index 0000000000..56e43432c3 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -0,0 +1,43 @@ +#include "CgalKernel.h" + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& result) { + IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon(); + + // Parse and store the points in a sequence + cgal_wire_t polygon = std::vector(); + for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) { + cgal_point_t pnt; + IfcGeom::CgalKernel::convert(*it, pnt); + polygon.push_back(pnt); + } + + // A loop should consist of at least three vertices + std::size_t original_count = polygon.size(); + if (original_count < 3) { + Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); + return false; + } + + // TODO: Remove repeated points (and points that are too close to one another?) + // remove_duplicate_points_from_loop(polygon, true); + + std::size_t count = polygon.size(); + if (original_count - count != 0) { + std::stringstream ss; ss << (original_count - count) << " edges removed for:"; + Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity); + } + + if (count < 3) { + Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity); + return false; + } + + result = polygon; + + // std::cout << "PolyLoop: " << std::endl; + // for (auto &point: polygon) { + // std::cout << "\tPoint(" << point << ")" << std::endl; + // } + + return true; +}