From 57fae25de8287d2f89178c57633696cb2609f3cb Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 1 Mar 2017 17:48:19 -0600 Subject: [PATCH 01/86] Putting functions into files per geometric type --- .../kernels/cgal/CgalConversionFunctions.cpp | 92 ---------- .../kernels/cgal/CgalEntityMapping.cpp | 161 ------------------ src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 74 ++++++++ .../kernels/cgal/CgalIfcGeomShapes.cpp | 140 +++++++++++++++ src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 43 +++++ 5 files changed, 257 insertions(+), 253 deletions(-) create mode 100644 src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp create mode 100644 src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp create mode 100644 src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp 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; +} From 2cb53a860dfc91f4fdc68d7b0fda5f34125a14a5 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 2 Mar 2017 15:09:05 -0600 Subject: [PATCH 02/86] Entities for basic CSG --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 78 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index b163696066..520c21dfd4 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -37,6 +37,8 @@ SHAPES(IfcManifoldSolidBrep); SHAPE(IfcExtrudedAreaSolid); SHAPE(IfcConnectedFaceSet); +SHAPE(IfcCsgSolid); +SHAPE(IfcBlock); FACE(IfcFace); FACE(IfcRectangleProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index b8efaf7f18..78b9b33c80 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -138,3 +138,81 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ shape = polyhedron; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCsgSolid* l, cgal_shape_t& shape) { + return convert_shape(l->TreeRootExpression(), shape); +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& shape) { + const double dx = l->XLength() * getValue(GV_LENGTH_UNIT); + const double dy = l->YLength() * getValue(GV_LENGTH_UNIT); + const double dz = l->ZLength() * getValue(GV_LENGTH_UNIT); + + std::list face_list; + + // x = 0 + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0, dy, dz)); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, dz)); + + // x = dx + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(dx, 0, dz)); + face_list.back().outer.push_back(Kernel::Point_3(dx, dy, dz)); + face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0)); + + // y = 0 + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, dz)); + face_list.back().outer.push_back(Kernel::Point_3(dx, 0, dz)); + face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0)); + + // y = dy + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0)); + face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0)); + face_list.back().outer.push_back(Kernel::Point_3(dx, dy, dz)); + face_list.back().outer.push_back(Kernel::Point_3(0, dy, dz)); + + // z = 0 + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0)); + + // z = dz + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, dz)); + face_list.back().outer.push_back(Kernel::Point_3(0, dy, dz)); + face_list.back().outer.push_back(Kernel::Point_3(dx, dy, dz)); + face_list.back().outer.push_back(Kernel::Point_3(dx, 0, dz)); + + // 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; + + cgal_placement_t trsf; + IfcGeom::CgalKernel::convert(l->Position(),trsf); + + // IfcCsgPrimitive3D.Position has unit scale factor + for (auto &vertex: vertices(polyhedron)) { + vertex->point() = vertex->point().transform(trsf); + } + + shape = polyhedron; + return true; +} From c9633273a6f89206364a7d76ffbea65e10ca56ae Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 2 Mar 2017 17:11:58 -0600 Subject: [PATCH 03/86] Several more classes, needs testing --- .../kernels/cgal/CgalConversionFunctions.cpp | 5 ++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 3 ++ src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 10 ++++ .../kernels/cgal/CgalIfcGeomShapes.cpp | 52 +++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 20 ++++++- src/ifcgeom/kernels/cgal/CgalKernel.h | 2 + 6 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 38f9e0d457..b096b3408e 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -144,3 +144,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_p // CACHE(IfcObjectPlacement,l,trsf) return true; } + +bool IfcGeom::CgalKernel::convert_wire_to_face(const cgal_wire_t& wire, cgal_face_t& face) { + face.outer = wire; + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 520c21dfd4..54efeb04ba 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -34,16 +34,19 @@ SHAPES(IfcRepresentation); // IfcFacetedBrepWithVoids included // IfcAdvancedBrepWithVoids included SHAPES(IfcManifoldSolidBrep); +SHAPES(IfcMappedItem); SHAPE(IfcExtrudedAreaSolid); SHAPE(IfcConnectedFaceSet); SHAPE(IfcCsgSolid); SHAPE(IfcBlock); +FACE(IfcArbitraryClosedProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); WIRE(IfcPolyLoop); +WIRE(IfcPolyline); CLASS(IfcCartesianPoint,cgal_point_t); CLASS(IfcDirection,cgal_direction_t); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 6cd88a434b..7c4e64337f 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -1,5 +1,15 @@ #include "CgalKernel.h" +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l, cgal_face_t& face) { + cgal_wire_t wire; + if ( ! convert_wire(l->OuterCurve(),wire) ) return false; + + cgal_face_t f; + bool success = convert_wire_to_face(wire, f); + if (success) face = f; + return success; +} + 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); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 78b9b33c80..37c344e483 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -32,6 +32,58 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, Conv return false; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionResults& shapes) { + cgal_placement_t gtrsf; + IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget(); + if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) { + Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); +// IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); + } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) { + Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); + return false; + } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) { + cgal_placement_t trsf; + Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); +// IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); + gtrsf = trsf; + } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { + cgal_placement_t trsf_2d; + Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); +// IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,trsf_2d); + gtrsf = (cgal_placement_t) trsf_2d; + } + IfcSchema::IfcRepresentationMap* map = l->MappingSource(); + IfcSchema::IfcAxis2Placement* placement = map->MappingOrigin(); + cgal_placement_t trsf; + if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); + } else { + cgal_placement_t trsf_2d; + IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d); + trsf = trsf_2d; + } + // TODO: Check + gtrsf = trsf * gtrsf; + + const IfcGeom::SurfaceStyle* mapped_item_style = get_style(l); + + const size_t previous_size = shapes.size(); + bool b = convert_shapes(map->MappedRepresentation(), shapes); + + for (size_t i = previous_size; i < shapes.size(); ++ i ) { + IfcGeom::CgalPlacement place(gtrsf); + shapes[i].prepend(&place); + + // Apply styles assigned to the mapped item only if on + // a more granular level no styles have been applied + if (!shapes[i].hasStyle()) { + shapes[i].setStyle(mapped_item_style); + } + } + + return b; +} + 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)) { diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index 56e43432c3..c6d8820c65 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -18,7 +18,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& return false; } - // TODO: Remove repeated points (and points that are too close to one another?) + // 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(); @@ -41,3 +41,21 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyline* l, cgal_wire_t& result) { + IfcSchema::IfcCartesianPoint::list::ptr points = l->Points(); + + // 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); + } + + // TODO: Remove points that are too close to one another + // remove_duplicate_points_from_loop(polygon, false); + + result = polygon; + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 4e82272375..94021ae750 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -130,6 +130,8 @@ namespace IfcGeom { bool convert_wire(const IfcUtil::IfcBaseClass* L, cgal_wire_t& result); bool convert_curve(const IfcUtil::IfcBaseClass* L, cgal_curve_t& result); bool convert_face(const IfcUtil::IfcBaseClass* L, cgal_face_t& result); + + bool convert_wire_to_face(const cgal_wire_t& wire, cgal_face_t& face); // 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); From 6297ff74f169bac61fc462720bf003552bbff0cb Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 2 Mar 2017 18:11:11 -0600 Subject: [PATCH 04/86] Boolean ops using Nef polyhedra (untested) --- .../kernels/cgal/CgalConversionFunctions.cpp | 7 +- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 238 ++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalKernel.h | 1 + 4 files changed, 246 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index b096b3408e..9573fdaa7a 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -25,14 +25,17 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, Convers bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { std::vector xyz = l->Coordinates(); - if (xyz.size() == 3) { + if (xyz.size() < 4) { point = Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f); // std::cout << "Converted Point(" << point << ")" << std::endl; return true; } else { - throw std::runtime_error("Point without 3 coordinates"); + std::cout << "Point("; + for (auto &coordinate: xyz) std::cout << coordinate << " "; + std::cout << ")"; + throw std::runtime_error("Could not parse point"); } } diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 54efeb04ba..12c8224e20 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -40,6 +40,8 @@ SHAPE(IfcExtrudedAreaSolid); SHAPE(IfcConnectedFaceSet); SHAPE(IfcCsgSolid); SHAPE(IfcBlock); +SHAPE(IfcBooleanResult); +SHAPE(IfcSphere); FACE(IfcArbitraryClosedProfileDef); FACE(IfcFace); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 37c344e483..d16264bc0f 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -268,3 +268,241 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh shape = polyhedron; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_shape_t& shape) { + + cgal_shape_t s1, s2; + ConversionResults items1, items2; + cgal_wire_t boundary_wire; + IfcSchema::IfcBooleanOperand* operand1 = l->FirstOperand(); + IfcSchema::IfcBooleanOperand* operand2 = l->SecondOperand(); + bool is_halfspace = operand2->is(IfcSchema::Type::IfcHalfSpaceSolid); + + if ( shape_type(operand1) == ST_SHAPELIST ) { + std::cout << "ST_SHAPELIST" << std::endl; +// if (!(convert_shapes(operand1, items1) && flatten_shape_list(items1, s1, true))) { + return false; +// } + } else if ( shape_type(operand1) == ST_SHAPE ) { + if ( ! convert_shape(operand1, s1) ) { + return false; + } +// TopoDS_Solid temp_solid; +// s1 = ensure_fit_for_subtraction(s1, temp_solid); + } else { + Logger::Message(Logger::LOG_ERROR, "s1: Invalid representation item for boolean operation", operand1->entity); + return false; + } + +// const double first_operand_volume = shape_volume(s1); +// if ( first_operand_volume <= ALMOST_ZERO ) +// Logger::Message(Logger::LOG_WARNING,"Empty solid for:",l->FirstOperand()->entity); + + bool shape2_processed = false; + if ( shape_type(operand2) == ST_SHAPELIST ) { + std::cout << "ST_SHAPELIST" << std::endl; +// shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true); + } else if ( shape_type(operand2) == ST_SHAPE ) { + shape2_processed = convert_shape(operand2,s2); + if (shape2_processed && !is_halfspace) { +// TopoDS_Solid temp_solid; +// s2 = ensure_fit_for_subtraction(s2, temp_solid); + } + } else { + Logger::Message(Logger::LOG_ERROR, "s2: Invalid representation item for boolean operation", operand2->entity); + } + + if (!shape2_processed) { +// shape = s1; + Logger::Message(Logger::LOG_ERROR,"Failed to convert SecondOperand of:",l->entity); +// return true; + } + +// if (!is_halfspace) { +// const double second_operand_volume = shape_volume(s2); +// if ( second_operand_volume <= ALMOST_ZERO ) +// Logger::Message(Logger::LOG_WARNING,"Empty solid for:",operand2->entity); +// } + + const IfcSchema::IfcBooleanOperator::IfcBooleanOperator op = l->Operator(); + + CGAL::Nef_polyhedron_3 nef1(s1); + CGAL::Nef_polyhedron_3 nef2(s2); + + if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { + + CGAL::Nef_polyhedron_3 nef_result = nef1-nef2; + cgal_shape_t result; + nef_result.convert_to_polyhedron(result); + shape = result; + return true; + + } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) { + + CGAL::Nef_polyhedron_3 nef_result = nef1+nef2; + cgal_shape_t result; + nef_result.convert_to_polyhedron(result); + shape = result; + return true; + + } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) { + + CGAL::Nef_polyhedron_3 nef_result = nef1*nef2; + cgal_shape_t result; + nef_result.convert_to_polyhedron(result); + shape = result; + return true; + + } + + return false; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& shape) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); + + // Make icosahedron + float golden_ratio = (1.0+sqrtf(5.0))/2.0; + float normalising_factor = sqrtf(golden_ratio*golden_ratio+1.0); + std::vector icosahedron_vertices; + icosahedron_vertices.push_back(Kernel::Point_3(-1.0/normalising_factor, golden_ratio/normalising_factor, 0.0)); + icosahedron_vertices.push_back(Kernel::Point_3( 1.0/normalising_factor, golden_ratio/normalising_factor, 0.0)); + icosahedron_vertices.push_back(Kernel::Point_3(-1.0/normalising_factor, -golden_ratio/normalising_factor, 0.0)); + icosahedron_vertices.push_back(Kernel::Point_3( 1.0/normalising_factor, -golden_ratio/normalising_factor, 0.0)); + icosahedron_vertices.push_back(Kernel::Point_3(0.0, -1.0/normalising_factor, golden_ratio/normalising_factor)); + icosahedron_vertices.push_back(Kernel::Point_3(0.0, 1.0/normalising_factor, golden_ratio/normalising_factor)); + icosahedron_vertices.push_back(Kernel::Point_3(0.0, -1.0/normalising_factor, -golden_ratio/normalising_factor)); + icosahedron_vertices.push_back(Kernel::Point_3(0.0, 1.0/normalising_factor, -golden_ratio/normalising_factor)); + icosahedron_vertices.push_back(Kernel::Point_3( golden_ratio/normalising_factor, 0.0, -1.0/normalising_factor)); + icosahedron_vertices.push_back(Kernel::Point_3( golden_ratio/normalising_factor, 0.0, 1.0/normalising_factor)); + icosahedron_vertices.push_back(Kernel::Point_3(-golden_ratio/normalising_factor, 0.0, -1.0/normalising_factor)); + icosahedron_vertices.push_back(Kernel::Point_3(-golden_ratio/normalising_factor, 0.0, 1.0/normalising_factor)); + + std::list face_list; + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[0]); + face_list.back().outer.push_back(icosahedron_vertices[11]); + face_list.back().outer.push_back(icosahedron_vertices[5]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[0]); + face_list.back().outer.push_back(icosahedron_vertices[5]); + face_list.back().outer.push_back(icosahedron_vertices[1]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[0]); + face_list.back().outer.push_back(icosahedron_vertices[1]); + face_list.back().outer.push_back(icosahedron_vertices[7]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[0]); + face_list.back().outer.push_back(icosahedron_vertices[7]); + face_list.back().outer.push_back(icosahedron_vertices[10]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[0]); + face_list.back().outer.push_back(icosahedron_vertices[10]); + face_list.back().outer.push_back(icosahedron_vertices[11]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[1]); + face_list.back().outer.push_back(icosahedron_vertices[5]); + face_list.back().outer.push_back(icosahedron_vertices[9]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[5]); + face_list.back().outer.push_back(icosahedron_vertices[11]); + face_list.back().outer.push_back(icosahedron_vertices[4]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[11]); + face_list.back().outer.push_back(icosahedron_vertices[10]); + face_list.back().outer.push_back(icosahedron_vertices[2]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[10]); + face_list.back().outer.push_back(icosahedron_vertices[7]); + face_list.back().outer.push_back(icosahedron_vertices[6]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[7]); + face_list.back().outer.push_back(icosahedron_vertices[1]); + face_list.back().outer.push_back(icosahedron_vertices[8]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[3]); + face_list.back().outer.push_back(icosahedron_vertices[9]); + face_list.back().outer.push_back(icosahedron_vertices[4]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[3]); + face_list.back().outer.push_back(icosahedron_vertices[4]); + face_list.back().outer.push_back(icosahedron_vertices[2]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[3]); + face_list.back().outer.push_back(icosahedron_vertices[2]); + face_list.back().outer.push_back(icosahedron_vertices[6]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[3]); + face_list.back().outer.push_back(icosahedron_vertices[6]); + face_list.back().outer.push_back(icosahedron_vertices[8]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[3]); + face_list.back().outer.push_back(icosahedron_vertices[8]); + face_list.back().outer.push_back(icosahedron_vertices[9]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[4]); + face_list.back().outer.push_back(icosahedron_vertices[9]); + face_list.back().outer.push_back(icosahedron_vertices[5]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[2]); + face_list.back().outer.push_back(icosahedron_vertices[4]); + face_list.back().outer.push_back(icosahedron_vertices[11]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[6]); + face_list.back().outer.push_back(icosahedron_vertices[2]); + face_list.back().outer.push_back(icosahedron_vertices[10]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[8]); + face_list.back().outer.push_back(icosahedron_vertices[6]); + face_list.back().outer.push_back(icosahedron_vertices[7]); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(icosahedron_vertices[9]); + face_list.back().outer.push_back(icosahedron_vertices[8]); + face_list.back().outer.push_back(icosahedron_vertices[1]); + + // TODO: Refine icosahedron to create icosphere + + // 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; + + cgal_placement_t trsf; + IfcGeom::CgalKernel::convert(l->Position(),trsf); + + for (auto &vertex: vertices(polyhedron)) { + vertex->point() = Kernel::Point_3(vertex->point().x()*r, + vertex->point().y()*r, + vertex->point().z()*r).transform(trsf); + } + + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 94021ae750..748fd4fbb3 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -47,6 +47,7 @@ if ( it != cache.T.end() ) { e = it->second; return true; } #include #include #include +#include typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; From 82cd4056b7a825891a4239c07d05e9d59eefd2be Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 2 Mar 2017 18:22:34 -0600 Subject: [PATCH 05/86] IfcRectangularPyramid --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 60 ++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 12c8224e20..20d363e13b 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -42,6 +42,7 @@ SHAPE(IfcCsgSolid); SHAPE(IfcBlock); SHAPE(IfcBooleanResult); SHAPE(IfcSphere); +SHAPE(IfcRectangularPyramid); FACE(IfcArbitraryClosedProfileDef); FACE(IfcFace); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index d16264bc0f..ae969a8e13 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -260,7 +260,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - // IfcCsgPrimitive3D.Position has unit scale factor for (auto &vertex: vertices(polyhedron)) { vertex->point() = vertex->point().transform(trsf); } @@ -506,3 +505,62 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cgal_shape_t& shape) { + const double dx = l->XLength() * getValue(GV_LENGTH_UNIT); + const double dy = l->YLength() * getValue(GV_LENGTH_UNIT); + const double dz = l->Height() * getValue(GV_LENGTH_UNIT); + + std::list face_list; + + // Base + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0)); + + // Lateral faces + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz)); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(0, dy, 0)); + face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz)); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(dx, dy, 0)); + face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz)); + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(dx, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0)); + face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz)); + + // 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; + + cgal_placement_t trsf; + IfcGeom::CgalKernel::convert(l->Position(),trsf); + + for (auto &vertex: vertices(polyhedron)) { + vertex->point() = vertex->point().transform(trsf); + } + + shape = polyhedron; + return true; +} From bece7053a001af99686db6bc249dd78915e8d545 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 2 Mar 2017 18:39:18 -0600 Subject: [PATCH 06/86] IfcRightCircularCylinder --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 20d363e13b..0f66367e23 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -43,6 +43,7 @@ SHAPE(IfcBlock); SHAPE(IfcBooleanResult); SHAPE(IfcSphere); SHAPE(IfcRectangularPyramid); +SHAPE(IfcRightCircularCylinder); FACE(IfcArbitraryClosedProfileDef); FACE(IfcFace); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index ae969a8e13..8b28f4abbb 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -564,3 +564,61 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cga shape = polyhedron; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, cgal_shape_t& shape) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); + const double h = l->Height() * getValue(GV_LENGTH_UNIT); + + std::list face_list; + + const int segments = 10; + + // Base + face_list.push_back(cgal_face_t()); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*3.141592653589793/((double)segments); + face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + } + + // Side faces + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*3.141592653589793/((double)segments); + int next_segment = (current_segment+1)%segments; + double next_angle = next_segment*3.141592653589793/((double)segments); + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(r*cos(next_angle), r*sin(next_angle), 0)); + face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), h)); + face_list.back().outer.push_back(Kernel::Point_3(r*cos(next_angle), r*sin(next_angle), h)); + } + + // Top + face_list.push_back(cgal_face_t()); + for (int current_segment = segments-1; current_segment >= 0; --current_segment) { + double current_angle = current_segment*3.141592653589793/((double)segments); + face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), h)); + } + + // 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; + + cgal_placement_t trsf; + IfcGeom::CgalKernel::convert(l->Position(),trsf); + + for (auto &vertex: vertices(polyhedron)) { + vertex->point() = vertex->point().transform(trsf); + } + + shape = polyhedron; + return true; +} From 302e7b2db86dacdf5fa7b74580f15cd5bdfd59e0 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 2 Mar 2017 18:42:10 -0600 Subject: [PATCH 07/86] IfcRightCircularCone --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 0f66367e23..afbb9db9f5 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -44,6 +44,7 @@ SHAPE(IfcBooleanResult); SHAPE(IfcSphere); SHAPE(IfcRectangularPyramid); SHAPE(IfcRightCircularCylinder); +SHAPE(IfcRightCircularCone); FACE(IfcArbitraryClosedProfileDef); FACE(IfcFace); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 8b28f4abbb..71dd71432b 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -622,3 +622,53 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, shape = polyhedron; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal_shape_t& shape) { + const double r = l->BottomRadius() * getValue(GV_LENGTH_UNIT); + const double h = l->Height() * getValue(GV_LENGTH_UNIT); + + std::list face_list; + + const int segments = 10; + + // Base + face_list.push_back(cgal_face_t()); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*3.141592653589793/((double)segments); + face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + } + + // Side faces + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*3.141592653589793/((double)segments); + int next_segment = (current_segment+1)%segments; + double next_angle = next_segment*3.141592653589793/((double)segments); + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(Kernel::Point_3(r*cos(next_angle), r*sin(next_angle), 0)); + face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + face_list.back().outer.push_back(Kernel::Point_3(0, 0, h)); + } + + // 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; + + cgal_placement_t trsf; + IfcGeom::CgalKernel::convert(l->Position(),trsf); + + for (auto &vertex: vertices(polyhedron)) { + vertex->point() = vertex->point().transform(trsf); + } + + shape = polyhedron; + return true; +} From 596c4f8b7750b4bb37822fcc3da9869a9473525f Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 3 Mar 2017 09:58:17 -0600 Subject: [PATCH 08/86] Adding some validation code --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 71dd71432b..b0e710c084 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -142,7 +142,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } + } CGAL_postcondition(polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; shape = polyhedron; @@ -254,7 +254,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } + } CGAL_postcondition(polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; @@ -278,7 +278,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha bool is_halfspace = operand2->is(IfcSchema::Type::IfcHalfSpaceSolid); if ( shape_type(operand1) == ST_SHAPELIST ) { - std::cout << "ST_SHAPELIST" << std::endl; + Logger::Message(Logger::LOG_ERROR, "s1: ST_SHAPELIST Unsupported", operand1->entity); // if (!(convert_shapes(operand1, items1) && flatten_shape_list(items1, s1, true))) { return false; // } @@ -299,7 +299,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha bool shape2_processed = false; if ( shape_type(operand2) == ST_SHAPELIST ) { - std::cout << "ST_SHAPELIST" << std::endl; + Logger::Message(Logger::LOG_ERROR, "s2: ST_SHAPELIST Unsupported", operand1->entity); // shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true); } else if ( shape_type(operand2) == ST_SHAPE ) { shape2_processed = convert_shape(operand2,s2); @@ -325,8 +325,19 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha const IfcSchema::IfcBooleanOperator::IfcBooleanOperator op = l->Operator(); + CGAL_precondition(s1.is_valid() && s1.is_closed()); CGAL::Nef_polyhedron_3 nef1(s1); + if (!nef1.is_simple()) { + Logger::Message(Logger::LOG_ERROR, "s1: Not simple Nef?", operand1->entity); + return false; + } + + CGAL_precondition(s2.is_valid() && s2.is_closed()); CGAL::Nef_polyhedron_3 nef2(s2); + if (!nef2.is_simple()) { + Logger::Message(Logger::LOG_ERROR, "s2: Not simple Nef?", operand2->entity); + return false; + } if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { @@ -491,7 +502,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } + } CGAL_postcondition(polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; @@ -551,7 +562,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cga CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } + } CGAL_postcondition(polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; @@ -609,7 +620,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } + } CGAL_postcondition(polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; @@ -659,7 +670,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } + } CGAL_postcondition(polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; From 7145b1ae85d7f56a45f74a3c9cfdade0007a0d3c Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 3 Mar 2017 12:58:52 -0600 Subject: [PATCH 09/86] Some debugging code, checking transformations --- .../kernels/cgal/CgalConversionFunctions.cpp | 6 +-- .../kernels/cgal/CgalIfcGeomShapes.cpp | 52 ++++++++++++++++--- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 9573fdaa7a..d0d6be43bc 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -53,7 +53,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_ // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) cgal_point_t o; cgal_direction_t axis = Kernel::Vector_3(0,0,1); - cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); // TODO: Put identity for now. Check? + cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); IfcGeom::CgalKernel::convert(l->Location(),o); bool hasRef = l->hasRefDirection(); if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); @@ -62,7 +62,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_ Kernel::Vector_3 y = CGAL::cross_product(Kernel::Vector_3(0.0, 0.0, 1.0), refDirection); trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), 0.0, o.cartesian(0), refDirection.cartesian(1), y.cartesian(1), 0.0, o.cartesian(1), - 0.0, y.cartesian(2), 1.0, 0.0); + 0.0, 0.0, 1.0, 0.0); // CACHE(IfcAxis2Placement3D,l,trsf) return true; @@ -72,7 +72,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_ // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) cgal_point_t o; cgal_direction_t axis = Kernel::Vector_3(0,0,1); - cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); // TODO: Put identity for now. Check? + cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); IfcGeom::CgalKernel::convert(l->Location(),o); bool hasRef = l->hasRefDirection(); if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index b0e710c084..87acdd4394 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -142,7 +142,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } CGAL_postcondition(polyhedron.is_closed()); + } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; shape = polyhedron; @@ -254,7 +254,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } CGAL_postcondition(polyhedron.is_closed()); + } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; @@ -339,27 +339,63 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha return false; } + std::ofstream f1; + f1.open("/Users/ken/Desktop/s1.off"); + f1 << s1 << std::endl; + f1.close(); + std::ofstream f2; + f2.open("/Users/ken/Desktop/s2.off"); + f2 << s2 << std::endl; + f2.close(); + if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { + std::cout << "Difference" << std::endl; CGAL::Nef_polyhedron_3 nef_result = nef1-nef2; + if (!nef_result.is_simple()) { + std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; + return false; + } cgal_shape_t result; nef_result.convert_to_polyhedron(result); + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/result.off"); + fresult << result << std::endl; + fresult.close(); shape = result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) { + std::cout << "Union" << std::endl; CGAL::Nef_polyhedron_3 nef_result = nef1+nef2; + if (!nef_result.is_simple()) { + std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; + return false; + } cgal_shape_t result; nef_result.convert_to_polyhedron(result); + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/result.off"); + fresult << result << std::endl; + fresult.close(); shape = result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) { + std::cout << "Intersection" << std::endl; CGAL::Nef_polyhedron_3 nef_result = nef1*nef2; + if (!nef_result.is_simple()) { + std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; + return false; + } cgal_shape_t result; nef_result.convert_to_polyhedron(result); + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/result.off"); + fresult << result << std::endl; + fresult.close(); shape = result; return true; @@ -502,7 +538,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } CGAL_postcondition(polyhedron.is_closed()); + } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; @@ -562,7 +598,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cga CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } CGAL_postcondition(polyhedron.is_closed()); + } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; @@ -582,7 +618,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, std::list face_list; - const int segments = 10; + const int segments = 25; // Base face_list.push_back(cgal_face_t()); @@ -620,7 +656,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } CGAL_postcondition(polyhedron.is_closed()); + } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; @@ -640,7 +676,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal std::list face_list; - const int segments = 10; + const int segments = 25; // Base face_list.push_back(cgal_face_t()); @@ -670,7 +706,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } CGAL_postcondition(polyhedron.is_closed()); + } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; cgal_placement_t trsf; From c59ae03cb3beee36d6ef3d2a288349384234dbd7 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 3 Mar 2017 13:12:05 -0600 Subject: [PATCH 10/86] Fixed bug in cylinders/cones --- src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 87acdd4394..7b0b5d173a 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -623,15 +623,15 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, // Base face_list.push_back(cgal_face_t()); for (int current_segment = 0; current_segment < segments; ++current_segment) { - double current_angle = current_segment*3.141592653589793/((double)segments); + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); } // Side faces for (int current_segment = 0; current_segment < segments; ++current_segment) { - double current_angle = current_segment*3.141592653589793/((double)segments); + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); int next_segment = (current_segment+1)%segments; - double next_angle = next_segment*3.141592653589793/((double)segments); + double next_angle = next_segment*2.0*3.141592653589793/((double)segments); face_list.push_back(cgal_face_t()); face_list.back().outer.push_back(Kernel::Point_3(r*cos(next_angle), r*sin(next_angle), 0)); face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); @@ -642,7 +642,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, // Top face_list.push_back(cgal_face_t()); for (int current_segment = segments-1; current_segment >= 0; --current_segment) { - double current_angle = current_segment*3.141592653589793/((double)segments); + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), h)); } @@ -681,15 +681,15 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal // Base face_list.push_back(cgal_face_t()); for (int current_segment = 0; current_segment < segments; ++current_segment) { - double current_angle = current_segment*3.141592653589793/((double)segments); + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); } // Side faces for (int current_segment = 0; current_segment < segments; ++current_segment) { - double current_angle = current_segment*3.141592653589793/((double)segments); + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); int next_segment = (current_segment+1)%segments; - double next_angle = next_segment*3.141592653589793/((double)segments); + double next_angle = next_segment*2.0*3.141592653589793/((double)segments); face_list.push_back(cgal_face_t()); face_list.back().outer.push_back(Kernel::Point_3(r*cos(next_angle), r*sin(next_angle), 0)); face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); From efb8bce25aa6a95e07a3e3bb00aa33123056c34f Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 3 Mar 2017 13:20:47 -0600 Subject: [PATCH 11/86] =?UTF-8?q?Didn=E2=80=99t=20save=20sphere=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 7b0b5d173a..ec1c1d4170 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -550,6 +550,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s vertex->point().z()*r).transform(trsf); } +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/sphere.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); + + shape = polyhedron; return true; } From bbe0b74f83a760db650f01d5064bc54f24f18fbe Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 3 Mar 2017 13:56:08 -0600 Subject: [PATCH 12/86] Boolean ops working? --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 97 ++++++++++++++----- 1 file changed, 74 insertions(+), 23 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index ec1c1d4170..95fe301e15 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -339,18 +339,18 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha return false; } - std::ofstream f1; - f1.open("/Users/ken/Desktop/s1.off"); - f1 << s1 << std::endl; - f1.close(); - std::ofstream f2; - f2.open("/Users/ken/Desktop/s2.off"); - f2 << s2 << std::endl; - f2.close(); +// std::ofstream f1; +// f1.open("/Users/ken/Desktop/s1.off"); +// f1 << s1 << std::endl; +// f1.close(); +// std::ofstream f2; +// f2.open("/Users/ken/Desktop/s2.off"); +// f2 << s2 << std::endl; +// f2.close(); if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { - std::cout << "Difference" << std::endl; +// std::cout << "Difference" << std::endl; CGAL::Nef_polyhedron_3 nef_result = nef1-nef2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; @@ -358,16 +358,16 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha } cgal_shape_t result; nef_result.convert_to_polyhedron(result); - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/result.off"); - fresult << result << std::endl; - fresult.close(); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/result.off"); +// fresult << result << std::endl; +// fresult.close(); shape = result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) { - std::cout << "Union" << std::endl; +// std::cout << "Union" << std::endl; CGAL::Nef_polyhedron_3 nef_result = nef1+nef2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; @@ -375,16 +375,16 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha } cgal_shape_t result; nef_result.convert_to_polyhedron(result); - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/result.off"); - fresult << result << std::endl; - fresult.close(); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/result.off"); +// fresult << result << std::endl; +// fresult.close(); shape = result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) { - std::cout << "Intersection" << std::endl; +// std::cout << "Intersection" << std::endl; CGAL::Nef_polyhedron_3 nef_result = nef1*nef2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; @@ -392,10 +392,10 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha } cgal_shape_t result; nef_result.convert_to_polyhedron(result); - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/result.off"); - fresult << result << std::endl; - fresult.close(); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/result.off"); +// fresult << result << std::endl; +// fresult.close(); shape = result; return true; @@ -527,12 +527,63 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s face_list.back().outer.push_back(icosahedron_vertices[1]); // TODO: Refine icosahedron to create icosphere + const unsigned int refinements = 3; + for (unsigned int current_refinement = 0; current_refinement < refinements; ++current_refinement) { + std::list refined_face_list; + for (auto &face: face_list) { + Kernel::Point_3 vertex0 = face.outer[0]; + Kernel::Point_3 vertex1 = face.outer[1]; + Kernel::Point_3 vertex2 = face.outer[2]; + + Kernel::Point_3 midpoint01 = CGAL::midpoint(vertex0, vertex1); + Kernel::Point_3 midpoint12 = CGAL::midpoint(vertex1, vertex2); + Kernel::Point_3 midpoint20 = CGAL::midpoint(vertex2, vertex0); + + double midpoint01_distance_to_origin = sqrt(CGAL::to_double(CGAL::squared_distance(midpoint01, Kernel::Point_3(0, 0, 0)))); + midpoint01 = Kernel::Point_3(midpoint01.x()/midpoint01_distance_to_origin, + midpoint01.y()/midpoint01_distance_to_origin, + midpoint01.z()/midpoint01_distance_to_origin); + double midpoint12_distance_to_origin = sqrt(CGAL::to_double(CGAL::squared_distance(midpoint12, Kernel::Point_3(0, 0, 0)))); + midpoint12 = Kernel::Point_3(midpoint12.x()/midpoint12_distance_to_origin, + midpoint12.y()/midpoint12_distance_to_origin, + midpoint12.z()/midpoint12_distance_to_origin); + double midpoint20_distance_to_origin = sqrt(CGAL::to_double(CGAL::squared_distance(midpoint20, Kernel::Point_3(0, 0, 0)))); + midpoint20 = Kernel::Point_3(midpoint20.x()/midpoint20_distance_to_origin, + midpoint20.y()/midpoint20_distance_to_origin, + midpoint20.z()/midpoint20_distance_to_origin); + + refined_face_list.push_back(cgal_face_t()); + refined_face_list.back().outer.push_back(vertex0); + refined_face_list.back().outer.push_back(midpoint01); + refined_face_list.back().outer.push_back(midpoint20); + + refined_face_list.push_back(cgal_face_t()); + refined_face_list.back().outer.push_back(vertex1); + refined_face_list.back().outer.push_back(midpoint12); + refined_face_list.back().outer.push_back(midpoint01); + + refined_face_list.push_back(cgal_face_t()); + refined_face_list.back().outer.push_back(vertex2); + refined_face_list.back().outer.push_back(midpoint20); + refined_face_list.back().outer.push_back(midpoint12); + + refined_face_list.push_back(cgal_face_t()); + refined_face_list.back().outer.push_back(midpoint01); + refined_face_list.back().outer.push_back(midpoint12); + refined_face_list.back().outer.push_back(midpoint20); + } face_list = refined_face_list; + } // Naive creation cgal_shape_t polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/sphere.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); + // 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); From b9828b029c917019bce4524d697c08edf5690db0 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 3 Mar 2017 15:25:45 -0600 Subject: [PATCH 13/86] Right way to output more than one object --- .../kernels/cgal/CgalConversionResult.cpp | 42 +++++++++++++------ .../kernels/cgal/CgalIfcGeomShapes.cpp | 7 ++-- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 59225e53f0..cb25f900ef 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -12,6 +12,11 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, vertex->point() = vertex->point().transform(trsf); } +// std::ofstream fbefore; +// fbefore.open("/Users/ken/Desktop/before.off"); +// fbefore << s << std::endl; +// fbefore.close(); + // Triangulate the shape and compute the normals std::map vertex_normals; boost::associative_property_map> vertex_normals_map(vertex_normals); @@ -23,26 +28,37 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape"); return; } + +// std::ofstream fafter; +// fafter.open("/Users/ken/Desktop/after.off"); +// fafter << s << std::endl; +// fafter.close(); CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); - - // Iterates over the faces of the shape - int num_faces = 0, num_vertices = 0; + std::map::Vertex_const_handle, int> vertices_map; + std::size_t initial_size = t->verts().size()/3; + for (auto &vertex: vertices(s)) { + if (vertices_map.count(vertex) == 0) { + vertices_map[vertex] = (int)(vertices_map.size()+initial_size); + t->addVertex(surface_style_id, + CGAL::to_double(vertex->point().cartesian(0)), + CGAL::to_double(vertex->point().cartesian(1)), + CGAL::to_double(vertex->point().cartesian(2))); +// std::cout << "Size: " << t->verts().size() << std::endl; + for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(vertex_normals_map[vertex].cartesian(i))); + } + } + for (auto &face: faces(s)) { + if (!face->is_triangle()) { + std::cout << "Warning: non-triangular face!" << std::endl; + continue; + } CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin(); do { - t->addVertex(surface_style_id, - CGAL::to_double(current_halfedge->vertex()->point().cartesian(0)), - CGAL::to_double(current_halfedge->vertex()->point().cartesian(1)), - CGAL::to_double(current_halfedge->vertex()->point().cartesian(2))); - for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(face_normals_map[face].cartesian(i))); - t->faces().push_back(num_vertices); - ++num_vertices; + t->faces().push_back(vertices_map[current_halfedge->vertex()]); ++current_halfedge; } while (current_halfedge != face->facet_begin()); t->material_ids().push_back(surface_style_id); - ++num_faces; } - -// std::cout << num_faces << " faces" << std::endl; } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 95fe301e15..e163bea2b8 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -526,8 +526,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s face_list.back().outer.push_back(icosahedron_vertices[8]); face_list.back().outer.push_back(icosahedron_vertices[1]); - // TODO: Refine icosahedron to create icosphere - const unsigned int refinements = 3; + const unsigned int refinements = 2; for (unsigned int current_refinement = 0; current_refinement < refinements; ++current_refinement) { std::list refined_face_list; for (auto &face: face_list) { @@ -675,7 +674,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, std::list face_list; - const int segments = 25; + const int segments = 12; // Base face_list.push_back(cgal_face_t()); @@ -733,7 +732,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal std::list face_list; - const int segments = 25; + const int segments = 12; // Base face_list.push_back(cgal_face_t()); From 64bc8e9d4fcf9554e4111a7ffa1512e8659ddaa6 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 10:52:57 -0600 Subject: [PATCH 14/86] Circular profiles, added missing transformation for rectangles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 41 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index afbb9db9f5..e35dad0f01 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -47,6 +47,7 @@ SHAPE(IfcRightCircularCylinder); SHAPE(IfcRightCircularCone); FACE(IfcArbitraryClosedProfileDef); +FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 7c4e64337f..05de331234 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -24,9 +24,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg #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)); @@ -34,6 +31,44 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg face.outer.push_back(Kernel::Point_3( x, y, 0.0)); face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_face_t& face) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); + if ( r == 0.0f ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 12; + + face = cgal_face_t(); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + return true; } From 1bcc369c7a66425b17f7e340e3bdfdc8228f4711 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:12:06 -0600 Subject: [PATCH 15/86] Rounded rectangles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index e35dad0f01..d2b1deeb90 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -50,6 +50,7 @@ FACE(IfcArbitraryClosedProfileDef); FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); +FACE(IfcRoundedRectangleProfileDef); WIRE(IfcPolyLoop); WIRE(IfcPolyline); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 05de331234..fad3b6affa 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -41,6 +41,57 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg return true; } +// TODO: Untested +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* 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); + const double r = l->RoundingRadius() * getValue(GV_LENGTH_UNIT); + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || r < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 3; + + face = cgal_face_t(); + + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + } + + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (0.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + } + + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (1.0*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + } + + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (1.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_face_t& face) { const double r = l->Radius() * getValue(GV_LENGTH_UNIT); if ( r == 0.0f ) { From 584b2e5584eaecf6144b0e5031ad279c0dabec4c Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:18:51 -0600 Subject: [PATCH 16/86] IfcTrapeziumProfileDef --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index d2b1deeb90..2528bb3622 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -51,6 +51,7 @@ FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); FACE(IfcRoundedRectangleProfileDef); +FACE(IfcTrapeziumProfileDef) WIRE(IfcPolyLoop); WIRE(IfcPolyline); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index fad3b6affa..4b8c369820 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -92,6 +92,39 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrapeziumProfileDef* l, cgal_face_t& face) { + const double x1 = l->BottomXDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double w = l->TopXDim() * getValue(GV_LENGTH_UNIT); + const double dx = l->TopXOffset() * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); + + if ( x1 < ALMOST_ZERO || w < ALMOST_ZERO || y < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + face = cgal_face_t(); + face.outer.push_back(Kernel::Point_3(-x1, -y, 0.0)); + face.outer.push_back(Kernel::Point_3(x1, -y, 0.0)); + face.outer.push_back(Kernel::Point_3(dx+w-x1, y, 0.0)); + face.outer.push_back(Kernel::Point_3(dx-x1, y, 0.0)); + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_face_t& face) { const double r = l->Radius() * getValue(GV_LENGTH_UNIT); if ( r == 0.0f ) { From 1d3732aa62bf67ee9d1845b178b136fd215a09f1 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:23:37 -0600 Subject: [PATCH 17/86] IfcEllipseProfileDef --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 3 +- src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 2528bb3622..65cdb41309 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -51,7 +51,8 @@ FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); FACE(IfcRoundedRectangleProfileDef); -FACE(IfcTrapeziumProfileDef) +FACE(IfcTrapeziumProfileDef); +FACE(IfcEllipseProfileDef); WIRE(IfcPolyLoop); WIRE(IfcPolyline); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 4b8c369820..294b9d8105 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -156,6 +156,39 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_ return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEllipseProfileDef* l, cgal_face_t& face) { + double rx = l->SemiAxis1() * getValue(GV_LENGTH_UNIT); + double ry = l->SemiAxis2() * getValue(GV_LENGTH_UNIT); + + if ( rx < ALMOST_ZERO || ry < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 12; + + face = cgal_face_t(); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(rx*cos(current_angle), ry*sin(current_angle), 0)); + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face) { IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds(); From 033a2e748262fc011e90e18ea34f2368f41b06a0 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:28:57 -0600 Subject: [PATCH 18/86] IfcFaceBasedSurfaceModel --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 65cdb41309..635da2cfd1 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -35,6 +35,7 @@ SHAPES(IfcRepresentation); // IfcAdvancedBrepWithVoids included SHAPES(IfcManifoldSolidBrep); SHAPES(IfcMappedItem); +SHAPES(IfcFaceBasedSurfaceModel); SHAPE(IfcExtrudedAreaSolid); SHAPE(IfcConnectedFaceSet); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index e163bea2b8..66578c5763 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -84,6 +84,21 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR return b; } +bool IfcGeom::CgalKernel::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); + for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) { + cgal_shape_t s; + const SurfaceStyle* shell_style = get_style(*it); + if (convert_shape(*it,s)) { + shapes.push_back(ConversionResult(new CgalShape(s), shell_style ? shell_style : collective_style)); + part_success |= true; + } + } + return part_success; +} + 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)) { From 484cea968e40a441480dfb8f533231fa3180e3ad Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:41:58 -0600 Subject: [PATCH 19/86] IfcTriangulatedFaceSet --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 635da2cfd1..072594ce65 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -46,6 +46,7 @@ SHAPE(IfcSphere); SHAPE(IfcRectangularPyramid); SHAPE(IfcRightCircularCylinder); SHAPE(IfcRightCircularCone); +SHAPE(IfcTriangulatedFaceSet); FACE(IfcArbitraryClosedProfileDef); FACE(IfcCircleProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 66578c5763..10f7bde015 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -790,3 +790,65 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal shape = polyhedron; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cgal_shape_t& shape) { + IfcSchema::IfcCartesianPointList3D* point_list = l->Coordinates(); + const std::vector< std::vector > coordinates = point_list->CoordList(); + std::vector points; + points.reserve(coordinates.size()); + for (std::vector< std::vector >::const_iterator it = coordinates.begin(); it != coordinates.end(); ++it) { + const std::vector& coords = *it; + if (coords.size() != 3) { + Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on Coordinates", l->entity); + return false; + } + points.push_back(Kernel::Point_3(coords[0] * getValue(GV_LENGTH_UNIT), + coords[1] * getValue(GV_LENGTH_UNIT), + coords[2] * getValue(GV_LENGTH_UNIT))); + } + + std::vector< std::vector > indices = l->CoordIndex(); + + std::list face_list; + + for(std::vector< std::vector >::const_iterator it = indices.begin(); it != indices.end(); ++ it) { + const std::vector& tri = *it; + if (tri.size() != 3) { + Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on CoordIndex", l->entity); + return false; + } + + const int min_index = *std::min_element(tri.begin(), tri.end()); + const int max_index = *std::max_element(tri.begin(), tri.end()); + + if (min_index < 1 || max_index > (int) points.size()) { + Logger::Message(Logger::LOG_ERROR, "Contents of CoordIndex out of bounds", l->entity); + return false; + } + + const Kernel::Point_3& a = points[tri[0] - 1]; // account for zero- vs + const Kernel::Point_3& b = points[tri[1] - 1]; // one-based indices in + const Kernel::Point_3& c = points[tri[2] - 1]; // c++ and express + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(a); + face_list.back().outer.push_back(b); + face_list.back().outer.push_back(c); + } + + // 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); + } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); + // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + + shape = polyhedron; + return true; +} From ca19d447cce742c648fbe082dddb637b803d9756 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 15:03:57 -0600 Subject: [PATCH 20/86] Zero-radius rounded rectangles --- src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 294b9d8105..4d208bd4cc 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -60,26 +60,29 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef const int segments = 3; - face = cgal_face_t(); - - for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = current_segment*0.5*3.141592653589793/((double)segments); - face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + if (r == 0.0) { + 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)); } - for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (0.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); - face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); - } - - for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (1.0*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); - face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); - } - - for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (1.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); - face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + else { + face = cgal_face_t(); + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + } for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (0.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + } for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (1.0*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + } for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (1.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + } } if (has_position) { From 4f5ecee81e59d6eb567c521d453905c0f78e7462 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 16:03:29 -0600 Subject: [PATCH 21/86] Removing duplicate points, IfcCartesianTransformationOperator3D with problems --- .../kernels/cgal/CgalConversionFunctions.cpp | 41 +++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 23 ++++++++++- src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 8 ++-- src/ifcgeom/kernels/cgal/CgalKernel.h | 2 + 5 files changed, 69 insertions(+), 6 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index d0d6be43bc..6866dea9e9 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -152,3 +152,44 @@ bool IfcGeom::CgalKernel::convert_wire_to_face(const cgal_wire_t& wire, cgal_fac face.outer = wire; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, cgal_placement_t& trsf) { +// IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf) + cgal_point_t origin; + IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); + cgal_direction_t axis1 (1.,0.,0.); + cgal_direction_t axis2 (0.,1.,0.); + cgal_direction_t axis3 (0.,0.,1.); + if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); + if ( l->hasAxis3() ) IfcGeom::CgalKernel::convert(l->Axis3(),axis3); + double scale = 1.0; + if (l->hasScale()) { + scale = l->Scale(); + } + + trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0), + axis1.cartesian(1), scale*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), + axis1.cartesian(2), axis2.cartesian(2), scale*axis3.cartesian(2), origin.cartesian(2)); + +// CACHE(IfcCartesianTransformationOperator3D,l,trsf) + return true; +} + +void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol) { + if (tol <= 0.) tol = getValue(GV_PRECISION); + tol *= tol; + + for (int i = 0; i < polygon.size(); ++i) { + for (int j = i+1; j < polygon.size(); ++j) { + if (CGAL::squared_distance(polygon[i], polygon[j]) < tol) { + polygon.erase(polygon.begin()+j); + --j; + } + } if (closed) { + if (CGAL::squared_distance(polygon.front(), polygon.back()) < tol) { + polygon.erase(polygon.begin()+polygon.size()-1); + } + } + } +} diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 072594ce65..78ab93c02e 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -64,3 +64,4 @@ CLASS(IfcDirection,cgal_direction_t); CLASS(IfcAxis2Placement2D,cgal_placement_t); CLASS(IfcAxis2Placement3D,cgal_placement_t); CLASS(IfcObjectPlacement,cgal_placement_t); +CLASS(IfcCartesianTransformationOperator3D,cgal_placement_t); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 10f7bde015..0bdd75128f 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -43,8 +43,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR return false; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) { cgal_placement_t trsf; - Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); -// IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); gtrsf = trsf; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { cgal_placement_t trsf_2d; @@ -108,6 +107,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal cgal_face_t face; if ( !convert_face(l->SweptArea(),face) ) return false; +// std::cout << "Face vertices: " << face.outer.size() << std::endl; cgal_placement_t trsf; bool has_position = true; @@ -125,6 +125,17 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal std::list face_list; face_list.push_back(face); +// if (true) { +// cgal_shape_t polyhedron = CGAL::Polyhedron_3(); +// PolyhedronBuilder builder(&face_list); +// polyhedron.delegate(builder); +// +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/profile.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); +// } + for (std::vector::const_iterator current_vertex = face.outer.begin(); current_vertex != face.outer.end(); ++current_vertex) { @@ -155,6 +166,14 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // 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 (!polyhedron.is_valid()) { + std::cout << "Invalid polyhedron!" << std::endl; + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/invalid.off"); + fresult << polyhedron << std::endl; + fresult.close(); + } + if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index c6d8820c65..b605eac93a 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -18,8 +18,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& return false; } - // TODO: Remove repeated points and points that are too close to one another - // remove_duplicate_points_from_loop(polygon, true); + // Remove 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) { @@ -53,8 +53,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyline* l, cgal_wire_t& polygon.push_back(pnt); } - // TODO: Remove points that are too close to one another - // remove_duplicate_points_from_loop(polygon, false); + // Remove points that are too close to one another + remove_duplicate_points_from_loop(polygon, false); result = polygon; return true; diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 748fd4fbb3..30d0a33792 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -133,6 +133,8 @@ namespace IfcGeom { bool convert_face(const IfcUtil::IfcBaseClass* L, cgal_face_t& result); bool convert_wire_to_face(const cgal_wire_t& wire, cgal_face_t& face); + + void remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol = -1.); // 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); From 27b5fd0fc50cf45bff5f60a07abf2530ad013aea Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 17:29:20 -0600 Subject: [PATCH 22/86] Debug code --- src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 6866dea9e9..040b09bd59 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -167,11 +167,18 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOpe if (l->hasScale()) { scale = l->Scale(); } - + + // TODO: Untested trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0), axis1.cartesian(1), scale*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), axis1.cartesian(2), axis2.cartesian(2), scale*axis3.cartesian(2), origin.cartesian(2)); +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + // CACHE(IfcCartesianTransformationOperator3D,l,trsf) return true; } From 64e385c3614e293303ca4eb5c7679e23ec043b37 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 17:45:55 -0600 Subject: [PATCH 23/86] Skeleton for IfcEdgeLoop and IfcOrientedEdge --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 ++ src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 78ab93c02e..1d50cdff5c 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -56,6 +56,8 @@ FACE(IfcRoundedRectangleProfileDef); FACE(IfcTrapeziumProfileDef); FACE(IfcEllipseProfileDef); +WIRE(IfcEdgeLoop); +WIRE(IfcOrientedEdge); WIRE(IfcPolyLoop); WIRE(IfcPolyline); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index b605eac93a..07adccfe8c 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -59,3 +59,29 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyline* l, cgal_wire_t& result = polygon; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEdgeLoop* l, cgal_wire_t& result) { + IfcSchema::IfcOrientedEdge::list::ptr li = l->EdgeList(); + cgal_wire_t mw; + for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) { + cgal_wire_t w; + if (convert_wire(*it, w)) { + // TODO: What to do here? +// mw.Add(TopoDS::Edge(TopoDS_Iterator(w).Value())); + return false; + } + } + result = mw; + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcOrientedEdge* l, cgal_wire_t& result) { + if (convert_wire(l->EdgeElement(), result)) { + if (!l->Orientation()) { + std::reverse(result.begin(),result.end()); + } + return true; + } else { + return false; + } +} From b299c2747387c6e48f67174cf8c704f65c905586 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 19:28:12 -0600 Subject: [PATCH 24/86] Switched to Nef_polyhedron_3. Some problems... --- .../kernels/cgal/CgalConversionResult.cpp | 13 ++-- .../kernels/cgal/CgalIfcGeomShapes.cpp | 64 +++++++++---------- src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 2 +- src/ifcgeom/kernels/cgal/CgalKernel.h | 2 +- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index cb25f900ef..beffd368cb 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -7,8 +7,11 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, // std::cout << "Model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; // std::cout << "Valid: " << s.is_valid() << std::endl; + CGAL::Polyhedron_3 polyhedron; + s.convert_to_polyhedron(polyhedron); + // Apply transformation - if (place != NULL) for (auto &vertex: vertices(s)) { + if (place != NULL) for (auto &vertex: vertices(polyhedron)) { vertex->point() = vertex->point().transform(trsf); } @@ -22,7 +25,7 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, boost::associative_property_map> vertex_normals_map(vertex_normals); std::map face_normals; boost::associative_property_map> face_normals_map(face_normals); - if (CGAL::Polygon_mesh_processing::triangulate_faces(s)) { + if (CGAL::Polygon_mesh_processing::triangulate_faces(polyhedron)) { // std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; } else { Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape"); @@ -34,10 +37,10 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, // fafter << s << std::endl; // fafter.close(); - CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); + CGAL::Polygon_mesh_processing::compute_normals(polyhedron, vertex_normals_map, face_normals_map); std::map::Vertex_const_handle, int> vertices_map; std::size_t initial_size = t->verts().size()/3; - for (auto &vertex: vertices(s)) { + for (auto &vertex: vertices(polyhedron)) { if (vertices_map.count(vertex) == 0) { vertices_map[vertex] = (int)(vertices_map.size()+initial_size); t->addVertex(surface_style_id, @@ -49,7 +52,7 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, } } - for (auto &face: faces(s)) { + for (auto &face: faces(polyhedron)) { if (!face->is_triangle()) { std::cout << "Warning: non-triangular face!" << std::endl; continue; diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 0bdd75128f..6a5d2bf88a 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -159,7 +159,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal } face_list.push_back(top_face); // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -179,7 +179,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -209,7 +209,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -221,7 +221,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ } // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -279,7 +279,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh face_list.back().outer.push_back(Kernel::Point_3(dx, 0, dz)); // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -298,7 +298,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh vertex->point() = vertex->point().transform(trsf); } - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -359,16 +359,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha const IfcSchema::IfcBooleanOperator::IfcBooleanOperator op = l->Operator(); - CGAL_precondition(s1.is_valid() && s1.is_closed()); - CGAL::Nef_polyhedron_3 nef1(s1); - if (!nef1.is_simple()) { + if (!s1.is_simple()) { Logger::Message(Logger::LOG_ERROR, "s1: Not simple Nef?", operand1->entity); return false; } - CGAL_precondition(s2.is_valid() && s2.is_closed()); - CGAL::Nef_polyhedron_3 nef2(s2); - if (!nef2.is_simple()) { + if (!s2.is_simple()) { Logger::Message(Logger::LOG_ERROR, "s2: Not simple Nef?", operand2->entity); return false; } @@ -385,52 +381,52 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { // std::cout << "Difference" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = nef1-nef2; + CGAL::Nef_polyhedron_3 nef_result = s1-s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; } - cgal_shape_t result; - nef_result.convert_to_polyhedron(result); +// cgal_shape_t result; +// nef_result.convert_to_polyhedron(result); // std::ofstream fresult; // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - shape = result; + shape = nef_result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) { // std::cout << "Union" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = nef1+nef2; + CGAL::Nef_polyhedron_3 nef_result = s1+s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; } - cgal_shape_t result; - nef_result.convert_to_polyhedron(result); +// cgal_shape_t result; +// nef_result.convert_to_polyhedron(result); // std::ofstream fresult; // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - shape = result; + shape = nef_result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) { // std::cout << "Intersection" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = nef1*nef2; + CGAL::Nef_polyhedron_3 nef_result = s1*s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; } - cgal_shape_t result; - nef_result.convert_to_polyhedron(result); +// cgal_shape_t result; +// nef_result.convert_to_polyhedron(result); // std::ofstream fresult; // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - shape = result; + shape = nef_result; return true; } @@ -608,7 +604,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -639,7 +635,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s // fresult << polyhedron << std::endl; // fresult.close(); - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -679,7 +675,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cga face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz)); // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -698,7 +694,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cga vertex->point() = vertex->point().transform(trsf); } - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -737,7 +733,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -756,7 +752,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, vertex->point() = vertex->point().transform(trsf); } - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -787,7 +783,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -806,7 +802,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal vertex->point() = vertex->point().transform(trsf); } - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -856,7 +852,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cg } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -868,6 +864,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cg } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index 07adccfe8c..220b854930 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -66,7 +66,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEdgeLoop* l, cgal_wire_t& for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) { cgal_wire_t w; if (convert_wire(*it, w)) { - // TODO: What to do here? + // TODO: What to do here? Add some points only? // mw.Add(TopoDS::Edge(TopoDS_Iterator(w).Value())); return false; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 30d0a33792..ada2fdd91c 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -62,7 +62,7 @@ struct cgal_face_t { std::vector inner; }; -typedef CGAL::Polyhedron_3 cgal_shape_t; +typedef CGAL::Nef_polyhedron_3 cgal_shape_t; typedef boost::graph_traits>::vertex_descriptor cgal_vertex_descriptor_t; typedef boost::graph_traits>::face_descriptor cgal_face_descriptor_t; From 1fb76a9749acfb4eb28381c0c016cdfc988e4bfd Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 12:50:06 -0600 Subject: [PATCH 25/86] Switched to normals per vertex per face --- .../kernels/cgal/CgalConversionResult.cpp | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index beffd368cb..171b7ee2e8 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -38,19 +38,6 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, // fafter.close(); CGAL::Polygon_mesh_processing::compute_normals(polyhedron, vertex_normals_map, face_normals_map); - std::map::Vertex_const_handle, int> vertices_map; - std::size_t initial_size = t->verts().size()/3; - for (auto &vertex: vertices(polyhedron)) { - if (vertices_map.count(vertex) == 0) { - vertices_map[vertex] = (int)(vertices_map.size()+initial_size); - t->addVertex(surface_style_id, - CGAL::to_double(vertex->point().cartesian(0)), - CGAL::to_double(vertex->point().cartesian(1)), - CGAL::to_double(vertex->point().cartesian(2))); -// std::cout << "Size: " << t->verts().size() << std::endl; - for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(vertex_normals_map[vertex].cartesian(i))); - } - } for (auto &face: faces(polyhedron)) { if (!face->is_triangle()) { @@ -59,7 +46,12 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, } CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin(); do { - t->faces().push_back(vertices_map[current_halfedge->vertex()]); + t->faces().push_back((int)t->verts().size()/3); + t->addVertex(surface_style_id, + CGAL::to_double(current_halfedge->vertex()->point().cartesian(0)), + CGAL::to_double(current_halfedge->vertex()->point().cartesian(1)), + CGAL::to_double(current_halfedge->vertex()->point().cartesian(2))); + for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(face_normals_map[face].cartesian(i))); ++current_halfedge; } while (current_halfedge != face->facet_begin()); t->material_ids().push_back(surface_style_id); From 29021d8b0638fb1d517a11caed04906f9efc68cb Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 13:04:22 -0600 Subject: [PATCH 26/86] Hollow circles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 1d50cdff5c..f9f1b43252 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -49,6 +49,7 @@ SHAPE(IfcRightCircularCone); SHAPE(IfcTriangulatedFaceSet); FACE(IfcArbitraryClosedProfileDef); +FACE(IfcCircleHollowProfileDef); FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 4d208bd4cc..f49fcc8cf2 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -159,6 +159,45 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_ return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, cgal_face_t& face) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); + const double t = l->WallThickness() * getValue(GV_LENGTH_UNIT); + + if ( r == 0.0f || t == 0.0f ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 12; + + face = cgal_face_t(); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + } + + face.inner.push_back(cgal_wire_t()); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3((r-t)*cos(current_angle), (r-t)*sin(current_angle), 0)); + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEllipseProfileDef* l, cgal_face_t& face) { double rx = l->SemiAxis1() * getValue(GV_LENGTH_UNIT); double ry = l->SemiAxis2() * getValue(GV_LENGTH_UNIT); From 31d4de228abc4136409845a3b0f63482e79771a4 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 13:18:49 -0600 Subject: [PATCH 27/86] Extrusions with holes (Nef) --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 76 ++++++++++++++++--- 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 6a5d2bf88a..f028fec103 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -105,8 +105,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal return false; } - cgal_face_t face; - if ( !convert_face(l->SweptArea(),face) ) return false; + // Outer + cgal_face_t bottom_face; + if ( !convert_face(l->SweptArea(),bottom_face) ) return false; // std::cout << "Face vertices: " << face.outer.size() << std::endl; cgal_placement_t trsf; @@ -123,7 +124,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // std::cout << "Direction: " << dir << std::endl; std::list face_list; - face_list.push_back(face); + face_list.push_back(bottom_face); // if (true) { // cgal_shape_t polyhedron = CGAL::Polyhedron_3(); @@ -136,13 +137,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // fresult.close(); // } - for (std::vector::const_iterator current_vertex = face.outer.begin(); - current_vertex != face.outer.end(); + for (std::vector::const_iterator current_vertex = bottom_face.outer.begin(); + current_vertex != bottom_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(); + if (next_vertex == bottom_face.outer.end()) { + next_vertex = bottom_face.outer.begin(); } cgal_face_t side_face; side_face.outer.push_back(*next_vertex); side_face.outer.push_back(*current_vertex); @@ -152,8 +153,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal } cgal_face_t top_face; - for (std::vector::const_reverse_iterator vertex = face.outer.rbegin(); - vertex != face.outer.rend(); + for (std::vector::const_reverse_iterator vertex = bottom_face.outer.rbegin(); + vertex != bottom_face.outer.rend(); ++vertex) { top_face.outer.push_back(*vertex+height*dir); } face_list.push_back(top_face); @@ -180,6 +181,63 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; shape = CGAL::Nef_polyhedron_3(polyhedron); + + // Inner + // TODO: Would be faster to triangulate top/bottom face template rather than use Nef polyhedra for subtraction + for (auto &inner: bottom_face.inner) { +// std::cout << "Inner wire" << std::endl; + face_list.clear(); + + cgal_face_t hole_bottom_face; + hole_bottom_face.outer = inner; + face_list.push_back(hole_bottom_face); + + for (std::vector::const_iterator current_vertex = inner.begin(); + current_vertex != inner.end(); + ++current_vertex) { + std::vector::const_iterator next_vertex = current_vertex; + ++next_vertex; + if (next_vertex == inner.end()) { + next_vertex = inner.begin(); + } cgal_face_t hole_side_face; + hole_side_face.outer.push_back(*next_vertex); + hole_side_face.outer.push_back(*current_vertex); + hole_side_face.outer.push_back(*current_vertex+height*dir); + hole_side_face.outer.push_back(*next_vertex+height*dir); + face_list.push_back(hole_side_face); + } + + cgal_face_t hole_top_face; + for (std::vector::const_reverse_iterator vertex = inner.rbegin(); + vertex != inner.rend(); + ++vertex) { + hole_top_face.outer.push_back(*vertex+height*dir); + } face_list.push_back(hole_top_face); + + // Naive creation + CGAL::Polyhedron_3 hole_polyhedron = CGAL::Polyhedron_3(); + PolyhedronBuilder builder(&face_list); + hole_polyhedron.delegate(builder); + + // Stitch edges + // std::cout << "Before: " << hole_polyhedron.size_of_vertices() << " vertices and " << hole_polyhedron.size_of_facets() << " facets" << std::endl; + CGAL::Polygon_mesh_processing::stitch_borders(hole_polyhedron); + if (!hole_polyhedron.is_valid()) { + std::cout << "Invalid hole polyhedron!" << std::endl; + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/invalid.off"); + fresult << hole_polyhedron << std::endl; + fresult.close(); + } + + if (!CGAL::Polygon_mesh_processing::is_outward_oriented(hole_polyhedron)) { + CGAL::Polygon_mesh_processing::reverse_face_orientations(hole_polyhedron); + } CGAL_postcondition(hole_polyhedron.is_valid() && hole_polyhedron.is_closed()); + // std::cout << "After: " << hole_polyhedron.size_of_vertices() << " vertices and " << hole_polyhedron.size_of_facets() << " facets" << std::endl; + + shape -= CGAL::Nef_polyhedron_3(hole_polyhedron); + } + return true; } From 66048610e239232237983ede202bbc92bbbb4001 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 13:41:04 -0600 Subject: [PATCH 28/86] Rounded rectangles work now, def must be before rectangles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 +- src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index f9f1b43252..52ca33352d 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -52,8 +52,8 @@ FACE(IfcArbitraryClosedProfileDef); FACE(IfcCircleHollowProfileDef); FACE(IfcCircleProfileDef); FACE(IfcFace); -FACE(IfcRectangleProfileDef); FACE(IfcRoundedRectangleProfileDef); +FACE(IfcRectangleProfileDef); FACE(IfcTrapeziumProfileDef); FACE(IfcEllipseProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index f49fcc8cf2..c5e861b587 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -43,6 +43,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg // TODO: Untested bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, cgal_face_t& face) { + std::cout << "IfcRoundedRectangleProfileDef" << std::endl; + const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double r = l->RoundingRadius() * getValue(GV_LENGTH_UNIT); @@ -73,14 +75,17 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef for (int current_segment = 0; current_segment <= segments; ++current_segment) { double current_angle = current_segment*0.5*3.141592653589793/((double)segments); face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); - } for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (0.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); - } for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (1.0*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); - } for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (1.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); } } From 27d8e860245f9b3a725ca7bbad464337e35361f8 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 13:52:29 -0600 Subject: [PATCH 29/86] Hollow rectangle profiles, all tested now --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 101 +++++++++++++++++- 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 52ca33352d..b85f741966 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -53,6 +53,7 @@ FACE(IfcCircleHollowProfileDef); FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRoundedRectangleProfileDef); +FACE(IfcRectangleHollowProfileDef); FACE(IfcRectangleProfileDef); FACE(IfcTrapeziumProfileDef); FACE(IfcEllipseProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index c5e861b587..9e8fe9fecf 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -41,10 +41,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg return true; } -// TODO: Untested bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, cgal_face_t& face) { - std::cout << "IfcRoundedRectangleProfileDef" << std::endl; - const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double r = l->RoundingRadius() * getValue(GV_LENGTH_UNIT); @@ -100,6 +97,100 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleHollowProfileDef* 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); + const double d = l->WallThickness() * getValue(GV_LENGTH_UNIT); + + const bool fr1 = l->hasOuterFilletRadius(); + const bool fr2 = l->hasInnerFilletRadius(); + + const double r1 = fr1 ? l->OuterFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.; + const double r2 = fr2 ? l->InnerFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.; + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 3; + + if (!fr1 || r1 == 0.0) { + 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)); + } + + else { + face = cgal_face_t(); + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r1+r1*cos(current_angle), y-r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r1+r1*cos(current_angle), y-r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r1+r1*cos(current_angle), -y+r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r1+r1*cos(current_angle), -y+r1+r1*sin(current_angle), 0)); + } + } + + if (!fr2 || r2 == 0.0) { + face.inner.push_back(cgal_wire_t()); + face.inner.back().push_back(Kernel::Point_3(-x+d, -y+d, 0.0)); + face.inner.back().push_back(Kernel::Point_3( x-d, -y+d, 0.0)); + face.inner.back().push_back(Kernel::Point_3( x-d, y-d, 0.0)); + face.inner.back().push_back(Kernel::Point_3(-x+d, y-d, 0.0)); + } + + else { + face.inner.push_back(cgal_wire_t()); + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3(x-d-r1+r1*cos(current_angle), y-d-r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3(-x+d+r1+r1*cos(current_angle), y-d-r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3(-x+d+r1+r1*cos(current_angle), -y+d+r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3(x-d-r1+r1*cos(current_angle), -y+d+r1+r1*sin(current_angle), 0)); + } + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } for (auto &inner: face.inner) { + for (auto &vertex: inner) { + vertex = vertex.transform(trsf2d); + } + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrapeziumProfileDef* l, cgal_face_t& face) { const double x1 = l->BottomXDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double w = l->TopXDim() * getValue(GV_LENGTH_UNIT); @@ -197,6 +288,10 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, IfcGeom::CgalKernel::convert(l->Position(), trsf2d); for (auto &vertex: face.outer) { vertex = vertex.transform(trsf2d); + } for (auto &inner: face.inner) { + for (auto &vertex: inner) { + vertex = vertex.transform(trsf2d); + } } } From 3f94d4af37da312cd1972459655dd31bd59663d6 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 14:30:48 -0600 Subject: [PATCH 30/86] Skeleton for planes+halfspaces. Might be wrong. --- .../kernels/cgal/CgalConversionFunctions.cpp | 12 ++++++++++++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 ++ src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp | 18 ++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalKernel.h | 1 + 4 files changed, 33 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 040b09bd59..50c0cb892d 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -49,6 +49,18 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_directi return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPlane* pln, cgal_plane_t& plane) { +// IN_CACHE(IfcPlane,pln,gp_Pln,plane) + IfcSchema::IfcAxis2Placement3D* l = pln->Position(); + cgal_point_t o; + cgal_direction_t axis = Kernel::Vector_3(0,0,1); + IfcGeom::CgalKernel::convert(l->Location(),o); + if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); + plane = Kernel::Plane_3(o, axis); +// CACHE(IfcPlane,pln,plane) + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_placement_t& trsf) { // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) cgal_point_t o; diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index b85f741966..77c654e604 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -47,6 +47,7 @@ SHAPE(IfcRectangularPyramid); SHAPE(IfcRightCircularCylinder); SHAPE(IfcRightCircularCone); SHAPE(IfcTriangulatedFaceSet); +SHAPE(IfcHalfSpaceSolid); FACE(IfcArbitraryClosedProfileDef); FACE(IfcCircleHollowProfileDef); @@ -65,6 +66,7 @@ WIRE(IfcPolyline); CLASS(IfcCartesianPoint,cgal_point_t); CLASS(IfcDirection,cgal_direction_t); +CLASS(IfcPlane,cgal_plane_t); CLASS(IfcAxis2Placement2D,cgal_placement_t); CLASS(IfcAxis2Placement3D,cgal_placement_t); CLASS(IfcObjectPlacement,cgal_placement_t); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index f028fec103..8882d9e961 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -925,3 +925,21 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cg shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, cgal_shape_t& shape) { + IfcSchema::IfcSurface* surface = l->BaseSurface(); + if ( ! surface->is(IfcSchema::Type::IfcPlane) ) { + Logger::Message(Logger::LOG_ERROR, "Unsupported BaseSurface:", surface->entity); + return false; + } + cgal_plane_t pln; + IfcGeom::CgalKernel::convert((IfcSchema::IfcPlane*)surface,pln); + + // TODO: This might be the other way around? + if (!l->AgreementFlag()) pln = pln.opposite(); +// const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction()); +// shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid(); + + shape = CGAL::Nef_polyhedron_3(pln); + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index ada2fdd91c..7a27ae854e 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -54,6 +54,7 @@ typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; typedef Kernel::Aff_transformation_3 cgal_placement_t; typedef Kernel::Point_3 cgal_point_t; typedef Kernel::Vector_3 cgal_direction_t; +typedef Kernel::Plane_3 cgal_plane_t; typedef std::vector cgal_curve_t; typedef std::vector cgal_wire_t; From a3df0556aa7083dc70415054dd59fd8ded21d2e0 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 19:39:59 -0600 Subject: [PATCH 31/86] Composite curves --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 5 +- src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 90 +++++++++++++++++++ 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 77c654e604..a6e8430528 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -63,6 +63,7 @@ WIRE(IfcEdgeLoop); WIRE(IfcOrientedEdge); WIRE(IfcPolyLoop); WIRE(IfcPolyline); +WIRE(IfcCompositeCurve); CLASS(IfcCartesianPoint,cgal_point_t); CLASS(IfcDirection,cgal_direction_t); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 8882d9e961..07df06545f 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -127,7 +127,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal face_list.push_back(bottom_face); // if (true) { -// cgal_shape_t polyhedron = CGAL::Polyhedron_3(); +// CGAL::Polyhedron_3 polyhedron; // PolyhedronBuilder builder(&face_list); // polyhedron.delegate(builder); // @@ -166,12 +166,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // Stitch edges // std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + CGAL::Polyhedron_3 old_polyhedron(polyhedron); CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!polyhedron.is_valid()) { std::cout << "Invalid polyhedron!" << std::endl; std::ofstream fresult; fresult.open("/Users/ken/Desktop/invalid.off"); - fresult << polyhedron << std::endl; + fresult << old_polyhedron << std::endl; fresult.close(); } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index 220b854930..72ac78fa2d 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -85,3 +85,93 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcOrientedEdge* l, cgal_wire return false; } } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCompositeCurve* l, cgal_wire_t& wire) { + if ( getValue(GV_PLANEANGLE_UNIT)<0 ) { + Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity); + + // Temporarily pretend we do have unit information + setValue(GV_PLANEANGLE_UNIT,1.0); + + bool succes_radians = false; + bool succes_degrees = false; + bool use_radians = false; + bool use_degrees = false; + + // First try radians + cgal_wire_t wire_radians, wire_degrees; + try { + succes_radians = IfcGeom::CgalKernel::convert(l,wire_radians); + } catch (...) {} + + // Now try degrees + setValue(GV_PLANEANGLE_UNIT,0.0174532925199433); + try { + succes_degrees = IfcGeom::CgalKernel::convert(l,wire_degrees); + } catch (...) {} + + // Restore to unknown unit state + setValue(GV_PLANEANGLE_UNIT,-1.0); + + if ( succes_degrees && ! succes_radians ) { + use_degrees = true; + } else if ( succes_radians && ! succes_degrees ) { + use_radians = true; + } else if ( succes_radians && succes_degrees ) { + if ( wire_degrees.back() == wire_degrees.front() && wire_radians.back() != wire_radians.front() ) { + use_degrees = true; + } else if ( wire_radians.back() == wire_radians.front() && wire_degrees.back() != wire_degrees.front() ) { + use_radians = true; + } else { + // No heuristic left to prefer the one over the other, + // apparently both variants are equally succesful. + // The curve might be composed of only straight segments. + // Let's go with the wire created using radians as that + // at least is a SI unit. + use_radians = true; + } + } + + if ( use_radians ) { + Logger::Message(Logger::LOG_NOTICE,"Used radians to create composite curve"); + wire = wire_radians; + } else if ( use_degrees ) { + Logger::Message(Logger::LOG_NOTICE,"Used degrees to create composite curve"); + wire = wire_degrees; + } + + return use_radians || use_degrees; + } + IfcSchema::IfcCompositeCurveSegment::list::ptr segments = l->Segments(); + cgal_wire_t w; + //TopoDS_Vertex last_vertex; + for( IfcSchema::IfcCompositeCurveSegment::list::it it = segments->begin(); it != segments->end(); ++ it ) { + IfcSchema::IfcCurve* curve = (*it)->ParentCurve(); + cgal_wire_t wire2; + if ( !convert_wire(curve,wire2) ) { + Logger::Message(Logger::LOG_ERROR,"Failed to convert curve:",curve->entity); + continue; + } + if ( ! (*it)->SameSense() ) std::reverse(wire2.begin(),wire2.end()); + + if (wire2.empty()) { + continue; + } else if (w.empty()) { + w = wire2; + } else if (w.back() == w.front()) { + std::vector::const_iterator vertex = wire2.begin(); + ++vertex; + while (vertex != wire2.end()) { + w.push_back(*vertex); + ++vertex; + } + } else { + for (auto &vertex: wire2) w.push_back(vertex); + } + } + + remove_duplicate_points_from_loop(w, false); + + wire = w; + return true; +} From cb7ed51fc6c3f6c3460778b785d5db769a8de0ea Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 20:00:32 -0600 Subject: [PATCH 32/86] IfcCartesianTransformationOperator3DnonUniform (untested) --- .../kernels/cgal/CgalConversionFunctions.cpp | 30 +++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 13 +++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 50c0cb892d..c931af40bf 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -185,6 +185,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOpe axis1.cartesian(1), scale*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), axis1.cartesian(2), axis2.cartesian(2), scale*axis3.cartesian(2), origin.cartesian(2)); +// std::cout << std::endl; // for (int i = 0; i < 3; ++i) { // for (int j = 0; j < 4; ++j) { // std::cout << trsf.cartesian(i, j) << " "; @@ -195,6 +196,35 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOpe return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* l, cgal_placement_t& gtrsf) { +// IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf) + cgal_point_t origin; + IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); + cgal_direction_t axis1 (1.,0.,0.); + cgal_direction_t axis2 (0.,1.,0.); + cgal_direction_t axis3 (0.,0.,1.); + if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); + if ( l->hasAxis3() ) IfcGeom::CgalKernel::convert(l->Axis3(),axis3); + const double scale1 = l->hasScale() ? l->Scale() : 1.0f; + const double scale2 = l->hasScale2() ? l->Scale2() : scale1; + const double scale3 = l->hasScale3() ? l->Scale3() : scale1; + + // TODO: Untested + gtrsf = Kernel::Aff_transformation_3(scale1*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0), + axis1.cartesian(1), scale2*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), + axis1.cartesian(2), axis2.cartesian(2), scale3*axis3.cartesian(2), origin.cartesian(2)); + +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + +// CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gtrsf) + return true; +} + void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol) { if (tol <= 0.) tol = getValue(GV_PRECISION); tol *= tol; diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index a6e8430528..a98d162c87 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -72,3 +72,4 @@ CLASS(IfcAxis2Placement2D,cgal_placement_t); CLASS(IfcAxis2Placement3D,cgal_placement_t); CLASS(IfcObjectPlacement,cgal_placement_t); CLASS(IfcCartesianTransformationOperator3D,cgal_placement_t); +CLASS(IfcCartesianTransformationOperator3DnonUniform,cgal_placement_t); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 07df06545f..e419996de2 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -36,8 +36,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR cgal_placement_t gtrsf; IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget(); if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); -// IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); + return false; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) { Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); return false; @@ -45,6 +46,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR cgal_placement_t trsf; IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); gtrsf = trsf; +// Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); +// return false; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { cgal_placement_t trsf_2d; Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); @@ -61,9 +64,17 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d); trsf = trsf_2d; } + // TODO: Check gtrsf = trsf * gtrsf; +// std::cout << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << gtrsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + const IfcGeom::SurfaceStyle* mapped_item_style = get_style(l); const size_t previous_size = shapes.size(); From 0d36693780e4dd531f09f507dff672ad8560441e Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 8 Mar 2017 19:38:25 -0600 Subject: [PATCH 33/86] C profiles --- .../kernels/cgal/CgalConversionFunctions.cpp | 2 +- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 92 +++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index c931af40bf..eb6561c890 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -217,7 +217,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOpe // for (int i = 0; i < 3; ++i) { // for (int j = 0; j < 4; ++j) { -// std::cout << trsf.cartesian(i, j) << " "; +// std::cout << gtrsf.cartesian(i, j) << " "; // } std::cout << std::endl; // } diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index a98d162c87..a4102d7d11 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -58,6 +58,7 @@ FACE(IfcRectangleHollowProfileDef); FACE(IfcRectangleProfileDef); FACE(IfcTrapeziumProfileDef); FACE(IfcEllipseProfileDef); +FACE(IfcCShapeProfileDef); WIRE(IfcEdgeLoop); WIRE(IfcOrientedEdge); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 9e8fe9fecf..6463169512 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -376,3 +376,95 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCShapeProfileDef* l, cgal_face_t& face) { + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double x = l->Width() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d1 = l->WallThickness() * getValue(GV_LENGTH_UNIT); + const double d2 = l->Girth() * getValue(GV_LENGTH_UNIT); + bool doFillet = l->hasInternalFilletRadius(); + double f1 = 0; + double f2 = 0; + if ( doFillet ) { + f1 = l->InternalFilletRadius() * getValue(GV_LENGTH_UNIT); + f2 = f1 + d1; + } + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < 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 + + const int segments = 3; + + if (!doFillet || f1 == 0.0) { + 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+d2, 0.0)); + face.outer.push_back(Kernel::Point_3(x-d1, -y+d2, 0.0)); + face.outer.push_back(Kernel::Point_3(x-d1, -y+d1, 0.0)); + face.outer.push_back(Kernel::Point_3(-x+d1, -y+d1, 0.0)); + face.outer.push_back(Kernel::Point_3(-x+d1, y-d1, 0.0)); + face.outer.push_back(Kernel::Point_3(x-d1, y-d1, 0.0)); + face.outer.push_back(Kernel::Point_3(x-d1, y-d2, 0.0)); + face.outer.push_back(Kernel::Point_3(x, y-d2, 0.0)); + face.outer.push_back(Kernel::Point_3(x, y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); + } + + else { + face = cgal_face_t(); + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+f2+f2*cos(current_angle), -y+f2+f2*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), -y+f2+f2*sin(current_angle), 0)); + } + face.outer.push_back(Kernel::Point_3(x, -y+d2, 0.0)); + face.outer.push_back(Kernel::Point_3(x-d1, -y+d2, 0.0)); + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-f2+f1*cos(current_angle), -y+f2+f1*sin(current_angle), 0)); + } + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+f2+f1*cos(current_angle), -y+f2+f1*sin(current_angle), 0)); + } + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+f2+f1*cos(current_angle), y-f2+f1*sin(current_angle), 0)); + } + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-f2+f1*cos(current_angle), y-f2+f1*sin(current_angle), 0)); + } + face.outer.push_back(Kernel::Point_3(x-d1, y-d2, 0.0)); + face.outer.push_back(Kernel::Point_3(x, y-d2, 0.0)); + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), y-f2+f2*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+f2+f2*cos(current_angle), y-f2+f2*sin(current_angle), 0)); + } + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} From e922212357af518503880f92cfec7c9b36b1bea5 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 8 Mar 2017 19:55:17 -0600 Subject: [PATCH 34/86] L profiles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 109 ++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index a4102d7d11..fb54c938c5 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -59,6 +59,7 @@ FACE(IfcRectangleProfileDef); FACE(IfcTrapeziumProfileDef); FACE(IfcEllipseProfileDef); FACE(IfcCShapeProfileDef); +FACE(IfcLShapeProfileDef); WIRE(IfcEdgeLoop); WIRE(IfcOrientedEdge); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 6463169512..68a27bef3b 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -468,3 +468,112 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCShapeProfileDef* l, cgal_ return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcLShapeProfileDef* l, cgal_face_t& face) { + const bool hasSlope = l->hasLegSlope(); + const bool doEdgeFillet = l->hasEdgeRadius(); + const bool doFillet = l->hasFilletRadius(); + + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double x = (l->hasWidth() ? l->Width() : l->Depth()) / 2.0f * getValue(GV_LENGTH_UNIT); + const double d = l->Thickness() * getValue(GV_LENGTH_UNIT); + const double slope = hasSlope ? (l->LegSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.; + + double f1 = 0.0f; + double f2 = 0.0f; + if (doFillet) { + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); + } + if ( doEdgeFillet) { + f2 = l->EdgeRadius() * getValue(GV_LENGTH_UNIT); + } + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + double xx = -x+d; + double xy = -y+d; + double dy1 = 0.; + double dy2 = 0.; + double dx1 = 0.; + double dx2 = 0.; + if (hasSlope) { + dy1 = tan(slope) * x; + dy2 = tan(slope) * (x - d); + dx1 = tan(slope) * y; + dx2 = tan(slope) * (y - d); + + const double x1s = x; const double y1s = -y + d - dy1; + const double x1e = -x + d; const double y1e = -y + d + dy2; + const double x2s = -x + d - dx1; const double y2s = y; + const double x2e = -x + d + dx2; const double y2e = -y + d; + + const double a1 = y1e - y1s; + const double b1 = x1s - x1e; + const double c1 = a1*x1s + b1*y1s; + + const double a2 = y2e - y2s; + const double b2 = x2s - x2e; + const double c2 = a2*x2s + b2*y2s; + + const double det = a1*b2 - a2*b1; + + if (ALMOST_THE_SAME(det, 0.)) { + Logger::Message(Logger::LOG_NOTICE, "Legs do not intersect for:",l->entity); + return false; + } + + xx = (b2*c1 - b1*c2) / det; + xy = (a1*c2 - a2*c1) / det; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 3; + + 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)); + if (f2 == 0.0) { + face.outer.push_back(Kernel::Point_3(x, -y+d-dy1, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), -y+d-dy1-f2+f2*sin(current_angle), 0)); + } + } if (f1 == 0.0) { + face.outer.push_back(Kernel::Point_3(xx, xy, 0.0)); + } else { + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(xx+f1+f1*cos(current_angle), xy+f1+f1*sin(current_angle), 0)); + } + } if (f2 == 0.0) { + face.outer.push_back(Kernel::Point_3(-x+d-dx1, y, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+d-dx1-f2+f2*cos(current_angle), y-f2+f2*sin(current_angle), 0)); + } + } face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; + +// double coords[12] = {-x,-y, x,-y, x,-y+d-dy1, xx, xy, -x+d-dx1,y, -x,y}; +// int fillets[3] = {2,3,4}; +// double radii[3] = {f2,f1,f2}; +// return profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face); +} From 15e4e1952ffa522b0676fa0d0aa5da22d15149a4 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Wed, 8 Mar 2017 20:11:45 -0600 Subject: [PATCH 35/86] I profiles (untested) --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 88 +++++++++++++++++-- 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index fb54c938c5..379d855231 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -59,6 +59,7 @@ FACE(IfcRectangleProfileDef); FACE(IfcTrapeziumProfileDef); FACE(IfcEllipseProfileDef); FACE(IfcCShapeProfileDef); +FACE(IfcIShapeProfileDef); FACE(IfcLShapeProfileDef); WIRE(IfcEdgeLoop); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 68a27bef3b..69e50cde35 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -571,9 +571,87 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcLShapeProfileDef* l, cgal_ } return true; - -// double coords[12] = {-x,-y, x,-y, x,-y+d-dy1, xx, xy, -x+d-dx1,y, -x,y}; -// int fillets[3] = {2,3,4}; -// double radii[3] = {f2,f1,f2}; -// return profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face); +} + +// TODO: Untested +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcIShapeProfileDef* l, cgal_face_t& face) { + const double x1 = l->OverallWidth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double y = l->OverallDepth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d1 = l->WebThickness() / 2.0f * getValue(GV_LENGTH_UNIT); + const double dy1 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT); + + bool doFillet1 = l->hasFilletRadius(); + double f1 = 0.; + if ( doFillet1 ) { + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); + } + + bool doFillet2 = doFillet1; + double x2 = x1, dy2 = dy1, f2 = f1; + + if (l->is(IfcSchema::Type::IfcAsymmetricIShapeProfileDef)) { + IfcSchema::IfcAsymmetricIShapeProfileDef* assym = (IfcSchema::IfcAsymmetricIShapeProfileDef*) l; + x2 = assym->TopFlangeWidth() / 2. * getValue(GV_LENGTH_UNIT); + doFillet2 = assym->hasTopFlangeFilletRadius(); + if (doFillet2) { + f2 = assym->TopFlangeFilletRadius() * getValue(GV_LENGTH_UNIT); + } + if (assym->hasTopFlangeThickness()) { + dy2 = assym->TopFlangeThickness() * getValue(GV_LENGTH_UNIT); + } + } + + if ( x1 < ALMOST_ZERO || x2 < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || dy1 < ALMOST_ZERO || dy2 < 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 + + const int segments = 3; + + face = cgal_face_t(); + face.outer.push_back(Kernel::Point_3(-x1, -y, 0.0)); + face.outer.push_back(Kernel::Point_3(x1, -y, 0.0)); + face.outer.push_back(Kernel::Point_3(x1, -y+dy1, 0.0)); + if (f1 == 0.0) { + face.outer.push_back(Kernel::Point_3(d1, -y+dy1, 0.0)); + face.outer.push_back(Kernel::Point_3(d1, y-dy2, 0.0)); + } else { + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(d1+f1+f1*cos(current_angle), -y+dy1+f1+f1*sin(current_angle), 0)); + } for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(d1+f1+f1*cos(current_angle), y-dy2-f1+f1*sin(current_angle), 0)); + } + } face.outer.push_back(Kernel::Point_3(x2, y-dy2, 0.0)); + face.outer.push_back(Kernel::Point_3(x2, y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x2, y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x2, y-dy2, 0.0)); + if (f2 == 0.0) { + face.outer.push_back(Kernel::Point_3(-d1, y-dy2, 0.0)); + face.outer.push_back(Kernel::Point_3(-d1, -y+dy1, 0.0)); + } else { + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-d1-f2+f2*cos(current_angle), y-dy2-f2+f2*sin(current_angle), 0)); + } for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-d1-f2+f2*cos(current_angle), -y+dy1+f2+f2*sin(current_angle), 0)); + } + } face.outer.push_back(Kernel::Point_3(-x1, -y+dy1, 0.0)); + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; } From 619b4fbed53bdfe09b974f2df871379c043afe96 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 9 Mar 2017 12:14:00 +0100 Subject: [PATCH 36/86] Fix CGAL library linking on windows, conditional IfcTriangulatedFaceSet based on schema --- cmake/CMakeLists.txt | 22 +++++++++++++------ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 ++ .../kernels/cgal/CgalIfcGeomShapes.cpp | 2 ++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 63c8712908..604bb3781b 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -220,15 +220,23 @@ ENDIF() FIND_LIBRARY(libCGAL NAMES CGAL PATHS ${CGAL_LIBRARY_DIR} NO_DEFAULT_PATH) IF(libCGAL) MESSAGE(STATUS "CGAL library files found") + foreach(lib ${CGAL_LIBRARY_NAMES}) + string(REPLACE libCGAL "${lib}" lib_path "${libCGAL}") + list(APPEND CGAL_LIBRARIES "${lib_path}") + endforeach() ELSE() - MESSAGE(FATAL_ERROR "Unable to find CGAL library files, aborting") + FILE(GLOB CGAL_LIBRARIES ${CGAL_LIBRARY_DIR}/CGAL*.lib) + LIST(LENGTH CGAL_LIBRARY_NAMES num_cgal_library_names) + LIST(LENGTH CGAL_LIBRARIES num_cgal_libraries) + LINK_DIRECTORIES("${CGAL_LIBRARY_DIR}") + if(NOT "${num_cgal_library_names}" STREQUAL "${num_cgal_library_names}") + MESSAGE(FATAL_ERROR "Unable to find CGAL library files, aborting") + endif() + MESSAGE(STATUS "CGAL library files found") ENDIF() -foreach(lib ${CGAL_LIBRARY_NAMES}) - string(REPLACE libCGAL "${lib}" lib_path "${libCGAL}") - list(APPEND CGAL_LIBRARIES "${lib_path}") -endforeach() -FIND_LIBRARY(libGMP NAMES gmp PATHS ${GMP_LIBRARY_DIR} NO_DEFAULT_PATH) -FIND_LIBRARY(libMPFR NAMES mpfr PATHS ${MPFR_LIBRARY_DIR} NO_DEFAULT_PATH) +# TODO: Remove hardcoded version numbers for windows +FIND_LIBRARY(libGMP NAMES gmp "libgmp-10" PATHS ${GMP_LIBRARY_DIR} NO_DEFAULT_PATH) +FIND_LIBRARY(libMPFR NAMES mpfr "libmpfr-4" PATHS ${MPFR_LIBRARY_DIR} NO_DEFAULT_PATH) IF(NOT libGMP) MESSAGE(FATAL_ERROR "Unable to find GMP library files, aborting") ENDIF() diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 379d855231..371a2b7769 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -46,7 +46,9 @@ SHAPE(IfcSphere); SHAPE(IfcRectangularPyramid); SHAPE(IfcRightCircularCylinder); SHAPE(IfcRightCircularCone); +#ifdef USE_IFC4 SHAPE(IfcTriangulatedFaceSet); +#endif SHAPE(IfcHalfSpaceSolid); FACE(IfcArbitraryClosedProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index e419996de2..ce8f1fa17f 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -876,6 +876,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal return true; } +#ifdef USE_IFC4 bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cgal_shape_t& shape) { IfcSchema::IfcCartesianPointList3D* point_list = l->Coordinates(); const std::vector< std::vector > coordinates = point_list->CoordList(); @@ -937,6 +938,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cg shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } +#endif bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, cgal_shape_t& shape) { IfcSchema::IfcSurface* surface = l->BaseSurface(); From 0596827b9d0c9271f1a56a6fe2c6f987089107ff Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 9 Mar 2017 15:04:54 +0100 Subject: [PATCH 37/86] Fix null pointer access in tesselation of opencascade shape --- src/ifcgeom/kernels/opencascade/OpenCascadeShape.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeShape.cpp b/src/ifcgeom/kernels/opencascade/OpenCascadeShape.cpp index fcc94b52e3..da31ee08b9 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeShape.cpp +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeShape.cpp @@ -11,7 +11,10 @@ void IfcGeom::OpenCascadeShape::Triangulate(const IfcGeom::IteratorSettings& settings, const IfcGeom::ConversionResultPlacement* place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { const TopoDS_Shape& s = shape_; - const gp_GTrsf& trsf = dynamic_cast(place)->trsf(); + gp_GTrsf trsf; + if (place) { + trsf = dynamic_cast(place)->trsf(); + } // Triangulate the shape try { From 7bcd0d0a8dd6dc161358ff175b828614eab908eb Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 9 Mar 2017 15:35:29 +0100 Subject: [PATCH 38/86] Apply transformation to IfcExtrudedAreaSolid --- src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index ce8f1fa17f..3eba31aa9c 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -191,6 +191,10 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + + for (auto &vertex : vertices(polyhedron)) { + vertex->point() = vertex->point().transform(trsf); + } shape = CGAL::Nef_polyhedron_3(polyhedron); @@ -241,6 +245,10 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal fresult << hole_polyhedron << std::endl; fresult.close(); } + + for (auto &vertex : vertices(hole_polyhedron)) { + vertex->point() = vertex->point().transform(trsf); + } if (!CGAL::Polygon_mesh_processing::is_outward_oriented(hole_polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(hole_polyhedron); From 0fbadc2985f2409762131d79fc41ef251a0cdadc Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 9 Mar 2017 16:29:14 -0600 Subject: [PATCH 39/86] T profiles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 139 ++++++++++++++++++ 2 files changed, 140 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 371a2b7769..99387cec0d 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -63,6 +63,7 @@ FACE(IfcEllipseProfileDef); FACE(IfcCShapeProfileDef); FACE(IfcIShapeProfileDef); FACE(IfcLShapeProfileDef); +FACE(IfcTShapeProfileDef); WIRE(IfcEdgeLoop); WIRE(IfcOrientedEdge); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 69e50cde35..5d50e810da 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -655,3 +655,142 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcIShapeProfileDef* l, cgal_ return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTShapeProfileDef* l, cgal_face_t& face) { + const bool doFlangeEdgeFillet = l->hasFlangeEdgeRadius(); + const bool doWebEdgeFillet = l->hasWebEdgeRadius(); + const bool doFillet = l->hasFilletRadius(); + const bool hasFlangeSlope = l->hasFlangeSlope(); + const bool hasWebSlope = l->hasWebSlope(); + + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double x = l->FlangeWidth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d1 = l->WebThickness() * getValue(GV_LENGTH_UNIT); + const double d2 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT); + const double flangeSlope = hasFlangeSlope ? (l->FlangeSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.; + const double webSlope = hasWebSlope ? (l->WebSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.; + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + double dy1 = 0.0f; + double dy2 = 0.0f; + double dx1 = 0.0f; + double dx2 = 0.0f; + double f1 = 0.0f; + double f2 = 0.0f; + double f3 = 0.0f; + + if (doFillet) { + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); + } + if (doWebEdgeFillet) { + f2 = l->WebEdgeRadius() * getValue(GV_LENGTH_UNIT); + } + if (doFlangeEdgeFillet) { + f3 = l->FlangeEdgeRadius() * getValue(GV_LENGTH_UNIT); + } + + double xx, xy; + if (hasFlangeSlope) { + dy1 = (x / 2. - d1) * tan(flangeSlope); + dy2 = x / 2. * tan(flangeSlope); + } + if (hasWebSlope) { + dx1 = (y - d2) * tan(webSlope); + dx2 = y * tan(webSlope); + } + if (hasWebSlope || hasFlangeSlope) { + const double x1s = d1/2. - dx2; const double y1s = -y; + const double x1e = d1/2. + dx1; const double y1e = y - d2; + const double x2s = x; const double y2s = y - d2 + dy2; + const double x2e = d1/2.; const double y2e = y - d2 - dy1; + + const double a1 = y1e - y1s; + const double b1 = x1s - x1e; + const double c1 = a1*x1s + b1*y1s; + + const double a2 = y2e - y2s; + const double b2 = x2s - x2e; + const double c2 = a2*x2s + b2*y2s; + + const double det = a1*b2 - a2*b1; + + if (ALMOST_THE_SAME(det, 0.)) { + Logger::Message(Logger::LOG_NOTICE, "Web and flange do not intersect for:",l->entity); + return false; + } + + xx = (b2*c1 - b1*c2) / det; + xy = (a1*c2 - a2*c1) / det; + } else { + xx = d1 / 2; + xy = y - d2; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 3; + + face = cgal_face_t(); + if (f2 == 0.0) { + face.outer.push_back(Kernel::Point_3(d1/2.-dx2, -y, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(d1/2.-dx2-f2+f2*cos(current_angle), -y+f2+f2*sin(current_angle), 0)); + } + } if (f1 == 0.0) { + face.outer.push_back(Kernel::Point_3(xx, xy, 0.0)); + } else { + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(xx+f1+f1*cos(current_angle), xy-f1+f1*sin(current_angle), 0)); + } + } if (f3 == 0.0) { + face.outer.push_back(Kernel::Point_3(x, y-d2+dy2, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-f3+f3*cos(current_angle), y-d2+dy2+f3+f3*sin(current_angle), 0)); + } + } face.outer.push_back(Kernel::Point_3(x, y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); + if (f3 == 0.0) { + face.outer.push_back(Kernel::Point_3(-x, y-d2+dy2, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+f3+f3*cos(current_angle), y-d2+dy2+f3+f3*sin(current_angle), 0)); + } + } if (f1 == 0.0) { + face.outer.push_back(Kernel::Point_3(-xx, xy, 0.0)); + } else { + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-xx-f1+f1*cos(current_angle), xy-f1+f1*sin(current_angle), 0)); + } + } if (f2 == 0.0) { + face.outer.push_back(Kernel::Point_3(-d1/2.+dx2, -y, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-d1/2.+dx2+f2+f2*cos(current_angle), -y+f2+f2*sin(current_angle), 0)); + } + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} From 3e918180d235b5fcee981453841866c15844d64e Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 9 Mar 2017 16:46:09 -0600 Subject: [PATCH 40/86] U profiles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 85 +++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 99387cec0d..eca2679c2c 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -64,6 +64,7 @@ FACE(IfcCShapeProfileDef); FACE(IfcIShapeProfileDef); FACE(IfcLShapeProfileDef); FACE(IfcTShapeProfileDef); +FACE(IfcUShapeProfileDef); WIRE(IfcEdgeLoop); WIRE(IfcOrientedEdge); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 5d50e810da..169f8fd8f6 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -794,3 +794,88 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTShapeProfileDef* l, cgal_ return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcUShapeProfileDef* l, cgal_face_t& face) { + const bool doEdgeFillet = l->hasEdgeRadius(); + const bool doFillet = l->hasFilletRadius(); + const bool hasSlope = l->hasFlangeSlope(); + + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double x = l->FlangeWidth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d1 = l->WebThickness() * getValue(GV_LENGTH_UNIT); + const double d2 = l->FlangeThickness() * getValue(GV_LENGTH_UNIT); + const double slope = hasSlope ? (l->FlangeSlope() * getValue(GV_PLANEANGLE_UNIT)) : 0.; + + double dy1 = 0.0f; + double dy2 = 0.0f; + double f1 = 0.0f; + double f2 = 0.0f; + + if (doFillet) { + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); + } + if (doEdgeFillet) { + f2 = l->EdgeRadius() * getValue(GV_LENGTH_UNIT); + } + + if (hasSlope) { + dy1 = (x - d1) * tan(slope); + dy2 = x * tan(slope); + } + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || d1 < ALMOST_ZERO || d2 < 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 + + const int segments = 3; + + 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)); + if (f2 == 0.0) { + face.outer.push_back(Kernel::Point_3(x, -y+d2-dy2, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), -y+d2-dy2-f2+f2*sin(current_angle), 0)); + } + } if (f1 == 0.0) { + face.outer.push_back(Kernel::Point_3(-x+d1, -y+d2+dy1, 0.0)); + } else { + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+d1+f1+f1*cos(current_angle), -y+d2+dy1+f1+f1*sin(current_angle), 0)); + } + } if (f1 == 0.0) { + face.outer.push_back(Kernel::Point_3(-x+d1, y-d2-dy1, 0.0)); + } else { + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+d1+f1+f1*cos(current_angle), y-d2-dy1-f1+f1*sin(current_angle), 0)); + } + } if (f2 == 0.0) { + face.outer.push_back(Kernel::Point_3(x,y-d2+dy2, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), y-d2+dy2+f2+f2*sin(current_angle), 0)); + } + } face.outer.push_back(Kernel::Point_3(x,y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x,y, 0.0)); + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} From 3972727f9d6896c20d0e2a613cd762054e932ffe Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 9 Mar 2017 16:55:33 -0600 Subject: [PATCH 41/86] Z profiles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index eca2679c2c..c2f0825b72 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -65,6 +65,7 @@ FACE(IfcIShapeProfileDef); FACE(IfcLShapeProfileDef); FACE(IfcTShapeProfileDef); FACE(IfcUShapeProfileDef); +FACE(IfcZShapeProfileDef); WIRE(IfcEdgeLoop); WIRE(IfcOrientedEdge); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 169f8fd8f6..0040b65cc3 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -879,3 +879,80 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcUShapeProfileDef* l, cgal_ return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcZShapeProfileDef* l, cgal_face_t& face) { + const double x = l->FlangeWidth() * getValue(GV_LENGTH_UNIT); + const double y = l->Depth() / 2.0f * getValue(GV_LENGTH_UNIT); + const double dx = l->WebThickness() / 2.0f * getValue(GV_LENGTH_UNIT); + const double dy = l->FlangeThickness() * getValue(GV_LENGTH_UNIT); + + bool doFillet = l->hasFilletRadius(); + bool doEdgeFillet = l->hasEdgeRadius(); + + double f1 = 0.; + double f2 = 0.; + + if ( doFillet ) { + f1 = l->FilletRadius() * getValue(GV_LENGTH_UNIT); + } + if ( doEdgeFillet ) { + f2 = l->EdgeRadius() * getValue(GV_LENGTH_UNIT); + } + + if ( x == 0.0f || y == 0.0f || dx == 0.0f || dy == 0.0f ) { + 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 + + const int segments = 3; + + face = cgal_face_t(); + face.outer.push_back(Kernel::Point_3(-dx, -y, 0.0)); + face.outer.push_back(Kernel::Point_3(x, -y, 0.0)); + if (f2 == 0.0) { + face.outer.push_back(Kernel::Point_3(x, -y+dy, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-f2+f2*cos(current_angle), -y+dy-f2+f2*sin(current_angle), 0)); + } + } if (f1 == 0.0) { + face.outer.push_back(Kernel::Point_3(dx, -y+dy, 0.0)); + } else { + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(dx+f1+f1*cos(current_angle), -y+dy+f1+f1*sin(current_angle), 0)); + } + } face.outer.push_back(Kernel::Point_3(dx, y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); + if (f2 == 0.0) { + face.outer.push_back(Kernel::Point_3(-x, y-dy, 0.0)); + } else { + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+f2+f2*cos(current_angle), y-dy+f2+f2*sin(current_angle), 0)); + } + } if (f1 == 0.0) { + face.outer.push_back(Kernel::Point_3(-dx, y-dy, 0.0)); + } else { + for (int current_segment = segments; current_segment >= 0; --current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-dx-f1+f1*cos(current_angle), y-dy-f1+f1*sin(current_angle), 0)); + } + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} From 06c10dc4da93abf24991a181317f7675736db985 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 9 Mar 2017 17:04:37 -0600 Subject: [PATCH 42/86] Correct plane creation? --- src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index eb6561c890..30e441be04 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -54,9 +54,15 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPlane* pln, cgal_plane_t& IfcSchema::IfcAxis2Placement3D* l = pln->Position(); cgal_point_t o; cgal_direction_t axis = Kernel::Vector_3(0,0,1); + cgal_direction_t refDirection; IfcGeom::CgalKernel::convert(l->Location(),o); + bool hasRef = l->hasRefDirection(); if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); - plane = Kernel::Plane_3(o, axis); + if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); + cgal_plane_t ax3; + if ( hasRef ) ax3 = Kernel::Plane_3(o,o+axis,o+refDirection); + else ax3 = Kernel::Plane_3(o,axis); + plane = ax3; // CACHE(IfcPlane,pln,plane) return true; } From 287fb9f0ed115ab515a84b48c9de64f0182d9fbe Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 9 Mar 2017 18:42:54 -0600 Subject: [PATCH 43/86] Convert openings and subtract them --- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 101 ++++++++++++++++++++---- src/ifcgeom/kernels/cgal/CgalKernel.h | 2 +- 2 files changed, 87 insertions(+), 16 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index e67be1c390..f111d9bc93 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -111,25 +111,24 @@ IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_representat const std::string product_type = IfcSchema::Type::ToString(product->type()); ElementSettings element_settings(settings, getValue(GV_LENGTH_UNIT), product_type); - if (!settings.get(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && openings && openings->size()) { - Logger::Message(Logger::LOG_ERROR, "Not implemented opening subtractions"); - } - - if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { - // TODO: OpenCascade code uses opened_shapes. Check why. + if (!settings.get(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && openings && openings->size()) { + IfcGeom::ConversionResults opened_shapes; + convert_openings(product,openings,shapes,trsf,opened_shapes); + if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { + for ( IfcGeom::ConversionResults::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) { + it->prepend(new CgalPlacement(trsf)); + } + trsf = cgal_placement_t(); + } + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), opened_shapes); + } else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { for ( IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++ it ) { it->prepend(new CgalPlacement(trsf)); } - trsf = Kernel::Aff_transformation_3(); - shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); - } else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { - for ( IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++ it ) { - it->prepend(new CgalPlacement(trsf)); - } - trsf = Kernel::Aff_transformation_3(); - shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); + trsf = cgal_placement_t(); + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); } else { - shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); + shape = new IfcGeom::Representation::Native(element_settings, representation->entity->id(), shapes); } std::string context_string = ""; @@ -191,3 +190,75 @@ IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_processed_r brep->geometry_pointer() ); } + +bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, + const IfcGeom::ConversionResults& entity_shapes, const cgal_placement_t& entity_trsf, IfcGeom::ConversionResults& cut_shapes) { + + std::list opening_shapelist; + + for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) { + IfcSchema::IfcRelVoidsElement* v = *it; + IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement(); + if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) { + if (!fes->hasRepresentation()) continue; + + // Convert the IfcRepresentation of the IfcOpeningElement + cgal_placement_t opening_trsf; + if (fes->hasObjectPlacement()) { + try { + convert(fes->ObjectPlacement(),opening_trsf); + } catch (...) {} + } + + // Move the opening into the coordinate system of the IfcProduct + opening_trsf = opening_trsf * entity_trsf.inverse(); + + IfcSchema::IfcProductRepresentation* prodrep = fes->Representation(); + IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations(); + + IfcGeom::ConversionResults opening_shapes; + + for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) { + convert_shapes(*it2,opening_shapes); + } + + for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) { + cgal_shape_t opening_shape(((CgalShape*)opening_shapes[i].Shape())->shape()); + if (opening_shapes[i].Placement()) { + cgal_placement_t gtrsf = *(CgalPlacement*)opening_shapes[i].Placement(); + gtrsf = gtrsf * opening_trsf; + opening_shape.transform(gtrsf); + } opening_shapelist.push_back(opening_shape); + } + + } + } + + // Iterate over the shapes of the IfcProduct + for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) { + const cgal_shape_t& entity_shape_unlocated(((CgalShape*)it3->Shape())->shape()); + cgal_shape_t entity_shape(entity_shape_unlocated); + if (it3->Placement()) { + const cgal_placement_t& entity_shape_gtrsf = *(CgalPlacement*)it3->Placement(); + entity_shape.transform(entity_shape_gtrsf); + } + + cgal_shape_t brep_cut_result(entity_shape); + + for (auto &opening: opening_shapelist) { + brep_cut_result -= opening; + } + + if (brep_cut_result.is_valid()) { + cut_shapes.push_back(IfcGeom::ConversionResult(new CgalShape(brep_cut_result), &it3->Style())); + } else { + // Apparently processing the boolean operation failed or resulted in an invalid result + // in which case the original shape without the subtractions is returned instead + // we try convert the openings in the original way, one by one. + Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed:", entity->entity); + return false; + } + + } + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 7a27ae854e..e6658f547f 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -137,7 +137,7 @@ namespace IfcGeom { void remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol = -1.); - // 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(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const cgal_placement_t& entity_trsf, ConversionResults& cut_shapes); void purge_cache() { // Rather hack-ish, but a stopgap solution to keep memory under control From b5e79b2558be6b5382c670d62c185f2e4abde5b2 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 10 Mar 2017 17:44:19 -0600 Subject: [PATCH 44/86] Debug code --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 4 --- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 25 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 3eba31aa9c..788db838aa 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -37,8 +37,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget(); if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) { IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); - Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); - return false; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) { Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); return false; @@ -46,8 +44,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR cgal_placement_t trsf; IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); gtrsf = trsf; -// Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); -// return false; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { cgal_placement_t trsf_2d; Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index f111d9bc93..16c58bbd5b 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -213,6 +213,13 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, // Move the opening into the coordinate system of the IfcProduct opening_trsf = opening_trsf * entity_trsf.inverse(); +// std::cout << "opening_trsf" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << opening_trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + IfcSchema::IfcProductRepresentation* prodrep = fes->Representation(); IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations(); @@ -246,7 +253,25 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, cgal_shape_t brep_cut_result(entity_shape); for (auto &opening: opening_shapelist) { + + CGAL::Polyhedron_3 polyhedron; + brep_cut_result.convert_to_polyhedron(polyhedron); + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/before.off"); + fresult << polyhedron << std::endl; + fresult.close(); + + opening.convert_to_polyhedron(polyhedron); + fresult.open("/Users/ken/Desktop/opening.off"); + fresult << polyhedron << std::endl; + fresult.close(); + brep_cut_result -= opening; + + brep_cut_result.convert_to_polyhedron(polyhedron); + fresult.open("/Users/ken/Desktop/after.off"); + fresult << polyhedron << std::endl; + fresult.close(); } if (brep_cut_result.is_valid()) { From ac7099ab39803f6e6f53d55dbd844ff0cda86b59 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 10 Mar 2017 18:21:15 -0600 Subject: [PATCH 45/86] Fixed bug with opening placements --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 24 +++++++++++--- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 33 +++++++++++++++---- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 788db838aa..e06163c425 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -235,11 +235,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // std::cout << "Before: " << hole_polyhedron.size_of_vertices() << " vertices and " << hole_polyhedron.size_of_facets() << " facets" << std::endl; CGAL::Polygon_mesh_processing::stitch_borders(hole_polyhedron); if (!hole_polyhedron.is_valid()) { - std::cout << "Invalid hole polyhedron!" << std::endl; - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/invalid.off"); - fresult << hole_polyhedron << std::endl; - fresult.close(); +// std::cout << "Invalid hole polyhedron!" << std::endl; +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/invalid.off"); +// fresult << hole_polyhedron << std::endl; +// fresult.close(); + return false; } for (auto &vertex : vertices(hole_polyhedron)) { @@ -254,6 +255,19 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal shape -= CGAL::Nef_polyhedron_3(hole_polyhedron); } +// std::cout << "trsf" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + +// shape.convert_to_polyhedron(polyhedron); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/extrusion.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); + return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 16c58bbd5b..bc13ea6fb0 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -210,10 +210,24 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, } catch (...) {} } +// std::cout << "entity_trsf" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << entity_trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } +// +// std::cout << "opening_trsf before" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << opening_trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + // Move the opening into the coordinate system of the IfcProduct opening_trsf = opening_trsf * entity_trsf.inverse(); -// std::cout << "opening_trsf" << std::endl; +// std::cout << "opening_trsf after" << std::endl; // for (int i = 0; i < 3; ++i) { // for (int j = 0; j < 4; ++j) { // std::cout << opening_trsf.cartesian(i, j) << " "; @@ -230,12 +244,19 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, } for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) { + cgal_placement_t gtrsf; + if (opening_shapes[i].Placement()) gtrsf = *(CgalPlacement*)opening_shapes[i].Placement(); + gtrsf = gtrsf * opening_trsf; cgal_shape_t opening_shape(((CgalShape*)opening_shapes[i].Shape())->shape()); - if (opening_shapes[i].Placement()) { - cgal_placement_t gtrsf = *(CgalPlacement*)opening_shapes[i].Placement(); - gtrsf = gtrsf * opening_trsf; - opening_shape.transform(gtrsf); - } opening_shapelist.push_back(opening_shape); + opening_shape.transform(gtrsf); + opening_shapelist.push_back(opening_shape); + +// std::cout << "gtrsf" << std::endl; +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << gtrsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } } } From d02918070d601811f730663f400048bc11ffe203 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 10 Mar 2017 18:26:15 -0600 Subject: [PATCH 46/86] Remove debug code --- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 34 +++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index bc13ea6fb0..10e616c318 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -245,7 +245,9 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) { cgal_placement_t gtrsf; - if (opening_shapes[i].Placement()) gtrsf = *(CgalPlacement*)opening_shapes[i].Placement(); + if (opening_shapes[i].Placement()) { + gtrsf = *(CgalPlacement*)opening_shapes[i].Placement(); + } gtrsf = gtrsf * opening_trsf; cgal_shape_t opening_shape(((CgalShape*)opening_shapes[i].Shape())->shape()); opening_shape.transform(gtrsf); @@ -275,24 +277,24 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, for (auto &opening: opening_shapelist) { - CGAL::Polyhedron_3 polyhedron; - brep_cut_result.convert_to_polyhedron(polyhedron); - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/before.off"); - fresult << polyhedron << std::endl; - fresult.close(); - - opening.convert_to_polyhedron(polyhedron); - fresult.open("/Users/ken/Desktop/opening.off"); - fresult << polyhedron << std::endl; - fresult.close(); +// CGAL::Polyhedron_3 polyhedron; +// brep_cut_result.convert_to_polyhedron(polyhedron); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/before.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); +// +// opening.convert_to_polyhedron(polyhedron); +// fresult.open("/Users/ken/Desktop/opening.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); brep_cut_result -= opening; - brep_cut_result.convert_to_polyhedron(polyhedron); - fresult.open("/Users/ken/Desktop/after.off"); - fresult << polyhedron << std::endl; - fresult.close(); +// brep_cut_result.convert_to_polyhedron(polyhedron); +// fresult.open("/Users/ken/Desktop/after.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); } if (brep_cut_result.is_valid()) { From 54331062c3fd560fc92ad76fbb330b0578db90a8 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 13 Mar 2017 19:08:23 -0600 Subject: [PATCH 47/86] Basic curve types --- .../kernels/cgal/CgalConversionFunctions.cpp | 9 +++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 5 ++ .../kernels/cgal/CgalIfcGeomCurves.cpp | 75 +++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalKernel.h | 1 + 4 files changed, 90 insertions(+) create mode 100644 src/ifcgeom/kernels/cgal/CgalIfcGeomCurves.cpp diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 30e441be04..f290b24061 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -49,6 +49,15 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_directi return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcVector* l, cgal_vector_t& v) { +// IN_CACHE(IfcVector,l,cgal_vector_t,v) + cgal_direction_t d; + IfcGeom::CgalKernel::convert(l->Orientation(),d); + v = l->Magnitude() * getValue(GV_LENGTH_UNIT) * d; +// CACHE(IfcVector,l,v) + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPlane* pln, cgal_plane_t& plane) { // IN_CACHE(IfcPlane,pln,gp_Pln,plane) IfcSchema::IfcAxis2Placement3D* l = pln->Position(); diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index c2f0825b72..21dbc8cbb6 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -73,8 +73,13 @@ WIRE(IfcPolyLoop); WIRE(IfcPolyline); WIRE(IfcCompositeCurve); +CURVE(IfcCircle); +CURVE(IfcEllipse); +CURVE(IfcLine); + CLASS(IfcCartesianPoint,cgal_point_t); CLASS(IfcDirection,cgal_direction_t); +CLASS(IfcVector,cgal_vector_t); CLASS(IfcPlane,cgal_plane_t); CLASS(IfcAxis2Placement2D,cgal_placement_t); CLASS(IfcAxis2Placement3D,cgal_placement_t); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomCurves.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomCurves.cpp new file mode 100644 index 0000000000..536bc74b66 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomCurves.cpp @@ -0,0 +1,75 @@ +#include "CgalKernel.h" + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircle* l, cgal_curve_t& curve) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); + if ( r < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", l->entity); + return false; + } + cgal_placement_t trsf; + IfcSchema::IfcAxis2Placement* placement = l->Position(); + if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); + } else { + cgal_placement_t trsf2d; + IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d); + trsf = trsf2d; + } + + const int segments = 12; + + curve = cgal_curve_t(); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + curve.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + } + + for (auto &vertex: curve) { + vertex = vertex.transform(trsf); + } + + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEllipse* l, cgal_curve_t& curve) { + double x = l->SemiAxis1() * getValue(GV_LENGTH_UNIT); + double y = l->SemiAxis2() * getValue(GV_LENGTH_UNIT); + if (x < ALMOST_ZERO || y < ALMOST_ZERO) { + Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", l->entity); + return false; + } + cgal_placement_t trsf; + IfcSchema::IfcAxis2Placement* placement = l->Position(); + if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { + convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); + } else { + cgal_placement_t trsf2d; + convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d); + trsf = trsf2d; + } + + const int segments = 12; + + curve = cgal_curve_t(); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + curve.push_back(Kernel::Point_3(x*cos(current_angle), y*sin(current_angle), 0)); + } + + for (auto &vertex: curve) { + vertex = vertex.transform(trsf); + } + + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcLine* l, cgal_curve_t& curve) { + cgal_point_t pnt; + cgal_direction_t vec; + convert(l->Pnt(),pnt); + convert(l->Dir(),vec); + curve = cgal_curve_t(); + curve.push_back(pnt); + curve.push_back(pnt+vec); + return true; +} diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index e6658f547f..f63404d129 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -54,6 +54,7 @@ typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; typedef Kernel::Aff_transformation_3 cgal_placement_t; typedef Kernel::Point_3 cgal_point_t; typedef Kernel::Vector_3 cgal_direction_t; +typedef Kernel::Vector_3 cgal_vector_t; typedef Kernel::Plane_3 cgal_plane_t; typedef std::vector cgal_curve_t; typedef std::vector cgal_wire_t; From 7d16b725a33d2ffd938a7c2772d930d9ef44ec17 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 13 Mar 2017 19:08:50 -0600 Subject: [PATCH 48/86] IfcTrimmedCurve. Needs projection to closest point in curve? --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 158 ++++++++++++++++++ 2 files changed, 159 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 21dbc8cbb6..80a6cae20a 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -72,6 +72,7 @@ WIRE(IfcOrientedEdge); WIRE(IfcPolyLoop); WIRE(IfcPolyline); WIRE(IfcCompositeCurve); +WIRE(IfcTrimmedCurve); CURVE(IfcCircle); CURVE(IfcEllipse); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index 72ac78fa2d..c6832de476 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -175,3 +175,161 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCompositeCurve* l, cgal_wi wire = w; return true; } + +// TODO: Project points to closest point in curve? +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrimmedCurve* l, cgal_wire_t& wire) { + IfcSchema::IfcCurve* basis_curve = l->BasisCurve(); + bool isConic = basis_curve->is(IfcSchema::Type::IfcConic); + double parameterFactor = isConic ? getValue(GV_PLANEANGLE_UNIT) : getValue(GV_LENGTH_UNIT); + cgal_curve_t curve; + if ( !convert_curve(basis_curve,curve) ) return false; + bool trim_cartesian = l->MasterRepresentation() == IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN; + IfcEntityList::ptr trims1 = l->Trim1(); + IfcEntityList::ptr trims2 = l->Trim2(); + unsigned sense_agreement = l->SenseAgreement() ? 0 : 1; + double flts[2]; + cgal_point_t pnts[2]; + bool has_flts[2] = {false,false}; + bool has_pnts[2] = {false,false}; + cgal_wire_t w; + for ( IfcEntityList::it it = trims1->begin(); it != trims1->end(); it ++ ) { + IfcUtil::IfcBaseClass* i = *it; + if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[sense_agreement] ); + has_pnts[sense_agreement] = true; + } else if ( i->is(IfcSchema::Type::IfcParameterValue) ) { + const double value = *((IfcSchema::IfcParameterValue*)i); + flts[sense_agreement] = value * parameterFactor; + has_flts[sense_agreement] = true; + } + } + for ( IfcEntityList::it it = trims2->begin(); it != trims2->end(); it ++ ) { + IfcUtil::IfcBaseClass* i = *it; + if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianPoint*)i, pnts[1-sense_agreement] ); + has_pnts[1-sense_agreement] = true; + } else if ( i->is(IfcSchema::Type::IfcParameterValue) ) { + const double value = *((IfcSchema::IfcParameterValue*)i); + flts[1-sense_agreement] = value * parameterFactor; + has_flts[1-sense_agreement] = true; + } + } + trim_cartesian &= has_pnts[0] && has_pnts[1]; + bool trim_cartesian_failed = !trim_cartesian; + if ( trim_cartesian ) { + if ( CGAL::squared_distance(pnts[0], pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE) ) { + Logger::Message(Logger::LOG_WARNING,"Skipping segment with length below tolerance level:",l->entity); + return false; + } + if (l->SenseAgreement()) { + bool found = false; + int loops_to_go = 2; + std::vector::const_iterator point = curve.begin(); + do { + if (!found) { + if (CGAL::squared_distance(*point, pnts[0]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { + found = true; + w.push_back(*point); + } + } else { + w.push_back(*point); + if (CGAL::squared_distance(*point, pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { + break; + } + } ++point; + if (point == curve.end()) { + point = curve.begin(); + --loops_to_go; + } + } while (point != curve.begin() && loops_to_go > 0); + } else { + bool found = false; + int loops_to_go = 2; + std::vector::const_reverse_iterator point = curve.rbegin(); + do { + if (!found) { + if (CGAL::squared_distance(*point, pnts[0]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { + found = true; + w.push_back(*point); + } + } else { + w.push_back(*point); + if (CGAL::squared_distance(*point, pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { + break; + } + } ++point; + if (point == curve.rend() && loops_to_go > 0) point = curve.rbegin(); + } while (point != curve.rbegin()); + } + } + if ( (!trim_cartesian || trim_cartesian_failed) && (has_flts[0] && has_flts[1]) ) { + // The Geom_Line is constructed from a gp_Pnt and gp_Dir, whereas the IfcLine + // is defined by an IfcCartesianPoint and an IfcVector with Magnitude. Because + // the vector is normalised when passed to Geom_Line constructor the magnitude + // needs to be factored in with the IfcParameterValue here. + if ( basis_curve->is(IfcSchema::Type::IfcLine) ) { + IfcSchema::IfcLine* line = static_cast(basis_curve); + const double magnitude = line->Dir()->Magnitude(); + flts[0] *= magnitude; flts[1] *= magnitude; + } + if ( basis_curve->is(IfcSchema::Type::IfcEllipse) ) { + IfcSchema::IfcEllipse* ellipse = static_cast(basis_curve); + double x = ellipse->SemiAxis1() * getValue(GV_LENGTH_UNIT); + double y = ellipse->SemiAxis2() * getValue(GV_LENGTH_UNIT); + const bool rotated = y > x; + if (rotated) { + flts[0] -= M_PI / 2.; + flts[1] -= M_PI / 2.; + } + } + if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],M_PI*2.),0.) ) { + for (auto &point: curve) w.push_back(point); + } else { + if (l->SenseAgreement()) { + bool found = false; + int loops_to_go = 2; + std::vector::const_iterator point = curve.begin(); + do { + if (!found) { + if (CGAL::squared_distance(*point, pnts[0]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { + found = true; + w.push_back(*point); + } + } else { + w.push_back(*point); + if (CGAL::squared_distance(*point, pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { + break; + } + } ++point; + if (point == curve.end()) { + point = curve.begin(); + --loops_to_go; + } + } while (point != curve.begin() && loops_to_go > 0); + } else { + bool found = false; + int loops_to_go = 2; + std::vector::const_reverse_iterator point = curve.rbegin(); + do { + if (!found) { + if (CGAL::squared_distance(*point, pnts[0]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { + found = true; + w.push_back(*point); + } + } else { + w.push_back(*point); + if (CGAL::squared_distance(*point, pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { + break; + } + } ++point; + if (point == curve.rend() && loops_to_go > 0) point = curve.rbegin(); + } while (point != curve.rbegin()); + } + } + } else if ( trim_cartesian_failed && (has_pnts[0] && has_pnts[1]) ) { + w.push_back(pnts[0]); + w.push_back(pnts[1]); + } + wire = w; + return true; +} From 81cb7f379ea1ecfea634a10d30acdc98cf9d9e4d Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 13 Mar 2017 19:26:54 -0600 Subject: [PATCH 49/86] Ignore output files in /test/ --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index f7b2047913..69f95db0c8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,9 @@ __pycache__ # Visual Studio Code files .vscode +# Mac metadata .DS_Store +# Conversion results +/test/input/*.obj +/test/input/*.mtl +/test/input/*.tmp \ No newline at end of file From 38cbdbc0f422bfbb9934b2efa3032a6ad7c86e09 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 13 Mar 2017 20:22:19 -0600 Subject: [PATCH 50/86] Correct way to create trimmed parametric curves? --- src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 66 +++++-------------- 1 file changed, 16 insertions(+), 50 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index c6832de476..674ba921d6 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -176,7 +176,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCompositeCurve* l, cgal_wi return true; } -// TODO: Project points to closest point in curve? bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrimmedCurve* l, cgal_wire_t& wire) { IfcSchema::IfcCurve* basis_curve = l->BasisCurve(); bool isConic = basis_curve->is(IfcSchema::Type::IfcConic); @@ -217,6 +216,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrimmedCurve* l, cgal_wire trim_cartesian &= has_pnts[0] && has_pnts[1]; bool trim_cartesian_failed = !trim_cartesian; if ( trim_cartesian ) { + // TODO: Project points to closest point in curve? if ( CGAL::squared_distance(pnts[0], pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE) ) { Logger::Message(Logger::LOG_WARNING,"Skipping segment with length below tolerance level:",l->entity); return false; @@ -272,58 +272,24 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrimmedCurve* l, cgal_wire const double magnitude = line->Dir()->Magnitude(); flts[0] *= magnitude; flts[1] *= magnitude; } - if ( basis_curve->is(IfcSchema::Type::IfcEllipse) ) { - IfcSchema::IfcEllipse* ellipse = static_cast(basis_curve); - double x = ellipse->SemiAxis1() * getValue(GV_LENGTH_UNIT); - double y = ellipse->SemiAxis2() * getValue(GV_LENGTH_UNIT); - const bool rotated = y > x; - if (rotated) { - flts[0] -= M_PI / 2.; - flts[1] -= M_PI / 2.; - } - } if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],M_PI*2.),0.) ) { for (auto &point: curve) w.push_back(point); } else { - if (l->SenseAgreement()) { - bool found = false; - int loops_to_go = 2; - std::vector::const_iterator point = curve.begin(); - do { - if (!found) { - if (CGAL::squared_distance(*point, pnts[0]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { - found = true; - w.push_back(*point); - } - } else { - w.push_back(*point); - if (CGAL::squared_distance(*point, pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { - break; - } - } ++point; - if (point == curve.end()) { - point = curve.begin(); - --loops_to_go; - } - } while (point != curve.begin() && loops_to_go > 0); - } else { - bool found = false; - int loops_to_go = 2; - std::vector::const_reverse_iterator point = curve.rbegin(); - do { - if (!found) { - if (CGAL::squared_distance(*point, pnts[0]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { - found = true; - w.push_back(*point); - } - } else { - w.push_back(*point); - if (CGAL::squared_distance(*point, pnts[1]) < getValue(GV_WIRE_CREATION_TOLERANCE)*getValue(GV_WIRE_CREATION_TOLERANCE)) { - break; - } - } ++point; - if (point == curve.rend() && loops_to_go > 0) point = curve.rbegin(); - } while (point != curve.rbegin()); + const int segments_of_full_curve = 12; + double segment_angle = 2.0*3.141592653589793/segments_of_full_curve; + if ( basis_curve->is(IfcSchema::Type::IfcEllipse) ) { + IfcSchema::IfcEllipse* ellipse = static_cast(basis_curve); + double x = ellipse->SemiAxis1() * getValue(GV_LENGTH_UNIT); + double y = ellipse->SemiAxis2() * getValue(GV_LENGTH_UNIT); + for (double current_angle = flts[0]; current_angle < flts[1]; current_angle += segment_angle) { + w.push_back(Kernel::Point_3(x*cos(current_angle), y*sin(current_angle), 0)); + } w.push_back(Kernel::Point_3(x*cos(flts[1]), y*sin(flts[1]), 0)); + } if ( basis_curve->is(IfcSchema::Type::IfcCircle) ) { + IfcSchema::IfcCircle* circle = static_cast(basis_curve); + double r = circle->Radius() * getValue(GV_LENGTH_UNIT); + for (double current_angle = flts[0]; current_angle < flts[1]; current_angle += segment_angle) { + w.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + } w.push_back(Kernel::Point_3(r*cos(flts[1]), r*sin(flts[1]), 0)); } } } else if ( trim_cartesian_failed && (has_pnts[0] && has_pnts[1]) ) { From d2aef0fcbd1cbd13db725fa1c527435776ec3a0d Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 13 Mar 2017 22:32:12 -0600 Subject: [PATCH 51/86] 2D Cartesian transformations (untested) --- .../kernels/cgal/CgalConversionFunctions.cpp | 48 +++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 4 +- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index f290b24061..61477a3c78 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -180,6 +180,54 @@ bool IfcGeom::CgalKernel::convert_wire_to_face(const cgal_wire_t& wire, cgal_fac return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2D* l, cgal_placement_t& trsf) { +// IN_CACHE(IfcCartesianTransformationOperator2D,l,cgal_placement_t,trsf) + + cgal_point_t origin; + cgal_direction_t axis1 (1.,0.,0.); + cgal_direction_t axis2 (0.,1.,0.); + + IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); + if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); + double scale = 1.0; + if (l->hasScale()) { + scale = l->Scale(); + } + + // TODO: Untested + trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), 0.0, origin.cartesian(0), + axis1.cartesian(1), scale*axis2.cartesian(1), 0.0, origin.cartesian(1), + 0.0, 0.0, 1.0, 0.0); + +// CACHE(IfcCartesianTransformationOperator2D,l,trsf) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, cgal_placement_t& gtrsf) { +// IN_CACHE(IfcCartesianTransformationOperator2DnonUniform,l,cgal_placement_t,gtrsf) + + cgal_placement_t trsf; + cgal_point_t origin; + cgal_direction_t axis1 (1.,0.,0.); + cgal_direction_t axis2 (0.,1.,0.); + + IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); + if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); + + const double scale1 = l->hasScale() ? l->Scale() : 1.0f; + const double scale2 = l->hasScale2() ? l->Scale2() : scale1; + + // TODO: Untested + trsf = Kernel::Aff_transformation_3(scale1*axis1.cartesian(0), axis2.cartesian(0), 0.0, origin.cartesian(0), + axis1.cartesian(1), scale2*axis2.cartesian(1), 0.0, origin.cartesian(1), + 0.0, 0.0, 1.0, 0.0); + +// CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gtrsf) + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, cgal_placement_t& trsf) { // IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf) cgal_point_t origin; diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 80a6cae20a..e0ecad5298 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -85,5 +85,7 @@ CLASS(IfcPlane,cgal_plane_t); CLASS(IfcAxis2Placement2D,cgal_placement_t); CLASS(IfcAxis2Placement3D,cgal_placement_t); CLASS(IfcObjectPlacement,cgal_placement_t); -CLASS(IfcCartesianTransformationOperator3D,cgal_placement_t); +CLASS(IfcCartesianTransformationOperator2DnonUniform,cgal_placement_t); CLASS(IfcCartesianTransformationOperator3DnonUniform,cgal_placement_t); +CLASS(IfcCartesianTransformationOperator2D,cgal_placement_t); +CLASS(IfcCartesianTransformationOperator3D,cgal_placement_t); From 98ce04ed6480283c8fbd9507d97e40b0ecb63ccc Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 16 Mar 2017 18:44:25 -0600 Subject: [PATCH 52/86] Fix logic of transformations --- .../kernels/cgal/CgalConversionFunctions.cpp | 68 +++++++++++++------ .../kernels/cgal/CgalIfcGeomShapes.cpp | 2 +- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 61477a3c78..7e9c48046e 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -25,18 +25,11 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, Convers bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { std::vector xyz = l->Coordinates(); - if (xyz.size() < 4) { - point = Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, - xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, - xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f); -// std::cout << "Converted Point(" << point << ")" << std::endl; - return true; - } else { - std::cout << "Point("; - for (auto &coordinate: xyz) std::cout << coordinate << " "; - std::cout << ")"; - throw std::runtime_error("Could not parse point"); - } + point = Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f); +// std::cout << "Converted Point(" << point << ")" << std::endl; + return true; } bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_direction_t& dir) { @@ -63,15 +56,46 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPlane* pln, cgal_plane_t& IfcSchema::IfcAxis2Placement3D* l = pln->Position(); cgal_point_t o; cgal_direction_t axis = Kernel::Vector_3(0,0,1); - cgal_direction_t refDirection; + cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); IfcGeom::CgalKernel::convert(l->Location(),o); bool hasRef = l->hasRefDirection(); if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); + Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); + Kernel::Vector_3 x = CGAL::cross_product(y, axis); + cgal_plane_t ax3; - if ( hasRef ) ax3 = Kernel::Plane_3(o,o+axis,o+refDirection); + if ( hasRef ) ax3 = Kernel::Plane_3(o,o+x,o+y); else ax3 = Kernel::Plane_3(o,axis); plane = ax3; + +// std::cout << "IfcPlane C = " << o << std::endl; +// std::cout << "IfcPlane z (axis, exact) = " << axis << std::endl; +// std::cout << "IfcPlane x (refDirection, approximate) = " << refDirection << std::endl; +// std::cout << "IfcPlane y (computed, exact) = " << y << std::endl; +// std::cout << "IfcPlane x (computed, exact) = " << x << std::endl; +// +// std::cout << "Plane_3 o = " << o << std::endl; +// std::cout << "Plane_3 o+x = " << o+x << std::endl; +// std::cout << "Plane_3 o+y = " << o+y << std::endl; + + // ax + by + cz + d = 0 +// std::cout << "Plane: a = " << plane.a() << ", b = " << plane.b() << ", c = " << plane.c() << ", d = " << plane.d() << std::endl; + +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/plane.obj"); +// // x = -5, y = -5, z = (5a +5b -d)/c +// fresult << "v -5 -5 " << (5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; +// // x = -5, y = +5, z = (5a -5b -d)/c +// fresult << "v -5 5 " << (5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; +// // x = 5, y = -5, z = (-5a +5b -d)/c +// fresult << "v 5 -5 " << (-5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; +// // x = 5, y = +5, z = (-5a -5b -d)/c +// fresult << "v 5 5 " << (-5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; +// fresult << "f 1 2 3" << std::endl; +// fresult << "f 4 3 2" << std::endl; +// fresult.close(); + // CACHE(IfcPlane,pln,plane) return true; } @@ -79,14 +103,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPlane* pln, cgal_plane_t& bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_placement_t& trsf) { // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) cgal_point_t o; - cgal_direction_t axis = Kernel::Vector_3(0,0,1); cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); IfcGeom::CgalKernel::convert(l->Location(),o); bool hasRef = l->hasRefDirection(); if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); + cgal_direction_t y = Kernel::Vector_3(-refDirection.y(), refDirection.x(), 0.0); - // TODO: From Thomas' email. Should be checked. - Kernel::Vector_3 y = CGAL::cross_product(Kernel::Vector_3(0.0, 0.0, 1.0), refDirection); + // TODO: Should be checked. trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), 0.0, o.cartesian(0), refDirection.cartesian(1), y.cartesian(1), 0.0, o.cartesian(1), 0.0, 0.0, 1.0, 0.0); @@ -104,16 +127,17 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_ bool hasRef = l->hasRefDirection(); if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); + Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); + Kernel::Vector_3 x = CGAL::cross_product(y, axis); // std::cout << "Ref direction: " << refDirection << std::endl; // std::cout << "Axis: " << axis << std::endl; // std::cout << "Origin: " << o << std::endl; - // TODO: From Thomas' email. Should be checked. - Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); - trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), axis.cartesian(0), o.cartesian(0), - refDirection.cartesian(1), y.cartesian(1), axis.cartesian(1), o.cartesian(1), - refDirection.cartesian(2), y.cartesian(2), axis.cartesian(2), o.cartesian(2)); + // TODO: Should be checked. + trsf = Kernel::Aff_transformation_3(x.cartesian(0), y.cartesian(0), axis.cartesian(0), o.cartesian(0), + x.cartesian(1), y.cartesian(1), axis.cartesian(1), o.cartesian(1), + x.cartesian(2), y.cartesian(2), axis.cartesian(2), o.cartesian(2)); // for (int i = 0; i < 3; ++i) { // for (int j = 0; j < 4; ++j) { diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index e06163c425..dfe4782294 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -967,7 +967,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, cgal_sh cgal_plane_t pln; IfcGeom::CgalKernel::convert((IfcSchema::IfcPlane*)surface,pln); - // TODO: This might be the other way around? + // TODO: This might be the other way around if (!l->AgreementFlag()) pln = pln.opposite(); // const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction()); // shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid(); From 30e88210b28bc2343bbb8c8d1f0e2a27d376ed3a Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 16 Mar 2017 19:20:41 -0600 Subject: [PATCH 53/86] Simplified code by moving Nef creation outside --- .../kernels/cgal/CgalConversionFunctions.cpp | 25 ++ .../kernels/cgal/CgalIfcGeomShapes.cpp | 224 ++---------------- src/ifcgeom/kernels/cgal/CgalKernel.h | 4 +- 3 files changed, 44 insertions(+), 209 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 7e9c48046e..b44429d144 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -329,3 +329,28 @@ void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon } } } + +CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(std::list &face_list) { + + // Naive creation + CGAL::Polyhedron_3 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 (!polyhedron.is_valid()) { + std::cout << "Invalid polyhedron!" << std::endl; + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/invalid.off"); + fresult << old_polyhedron << std::endl; + fresult.close(); + } + 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; + + return CGAL::Nef_polyhedron_3(polyhedron); +} diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index dfe4782294..7ac1ec8677 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -133,17 +133,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal std::list face_list; face_list.push_back(bottom_face); -// if (true) { -// CGAL::Polyhedron_3 polyhedron; -// PolyhedronBuilder builder(&face_list); -// polyhedron.delegate(builder); -// -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/profile.off"); -// fresult << polyhedron << std::endl; -// fresult.close(); -// } - for (std::vector::const_iterator current_vertex = bottom_face.outer.begin(); current_vertex != bottom_face.outer.end(); ++current_vertex) { @@ -166,33 +155,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal top_face.outer.push_back(*vertex+height*dir); } face_list.push_back(top_face); - // Naive creation - CGAL::Polyhedron_3 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::Polyhedron_3 old_polyhedron(polyhedron); - CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); - if (!polyhedron.is_valid()) { - std::cout << "Invalid polyhedron!" << std::endl; - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/invalid.off"); - fresult << old_polyhedron << std::endl; - fresult.close(); - } - - if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { - CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); - } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); - // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - - for (auto &vertex : vertices(polyhedron)) { - vertex->point() = vertex->point().transform(trsf); - } - - shape = CGAL::Nef_polyhedron_3(polyhedron); + shape = create_nef_polyhedron(face_list); // Inner // TODO: Would be faster to triangulate top/bottom face template rather than use Nef polyhedra for subtraction @@ -226,48 +189,10 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal hole_top_face.outer.push_back(*vertex+height*dir); } face_list.push_back(hole_top_face); - // Naive creation - CGAL::Polyhedron_3 hole_polyhedron = CGAL::Polyhedron_3(); - PolyhedronBuilder builder(&face_list); - hole_polyhedron.delegate(builder); - - // Stitch edges - // std::cout << "Before: " << hole_polyhedron.size_of_vertices() << " vertices and " << hole_polyhedron.size_of_facets() << " facets" << std::endl; - CGAL::Polygon_mesh_processing::stitch_borders(hole_polyhedron); - if (!hole_polyhedron.is_valid()) { -// std::cout << "Invalid hole polyhedron!" << std::endl; -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/invalid.off"); -// fresult << hole_polyhedron << std::endl; -// fresult.close(); - return false; - } - - for (auto &vertex : vertices(hole_polyhedron)) { - vertex->point() = vertex->point().transform(trsf); - } - - if (!CGAL::Polygon_mesh_processing::is_outward_oriented(hole_polyhedron)) { - CGAL::Polygon_mesh_processing::reverse_face_orientations(hole_polyhedron); - } CGAL_postcondition(hole_polyhedron.is_valid() && hole_polyhedron.is_closed()); - // std::cout << "After: " << hole_polyhedron.size_of_vertices() << " vertices and " << hole_polyhedron.size_of_facets() << " facets" << std::endl; - - shape -= CGAL::Nef_polyhedron_3(hole_polyhedron); + shape -= create_nef_polyhedron(face_list); } -// std::cout << "trsf" << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << trsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - -// shape.convert_to_polyhedron(polyhedron); -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/extrusion.off"); -// fresult << polyhedron << std::endl; -// fresult.close(); - + shape.transform(trsf); return true; } @@ -296,20 +221,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ face_list.push_back(face); } - // Naive creation - CGAL::Polyhedron_3 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 = CGAL::Nef_polyhedron_3(polyhedron); + shape = create_nef_polyhedron(face_list); return true; } @@ -366,27 +278,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh face_list.back().outer.push_back(Kernel::Point_3(dx, dy, dz)); face_list.back().outer.push_back(Kernel::Point_3(dx, 0, dz)); - // Naive creation - CGAL::Polyhedron_3 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); - } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); - // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - for (auto &vertex: vertices(polyhedron)) { - vertex->point() = vertex->point().transform(trsf); - } - - shape = CGAL::Nef_polyhedron_3(polyhedron); + shape = create_nef_polyhedron(face_list); + shape.transform(trsf); + return true; } @@ -691,39 +588,11 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s } face_list = refined_face_list; } - // Naive creation - CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); - PolyhedronBuilder builder(&face_list); - polyhedron.delegate(builder); - -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/sphere.off"); -// fresult << polyhedron << std::endl; -// fresult.close(); - - // 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); - } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); - // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - for (auto &vertex: vertices(polyhedron)) { - vertex->point() = Kernel::Point_3(vertex->point().x()*r, - vertex->point().y()*r, - vertex->point().z()*r).transform(trsf); - } - -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/sphere.off"); -// fresult << polyhedron << std::endl; -// fresult.close(); - - shape = CGAL::Nef_polyhedron_3(polyhedron); + shape = create_nef_polyhedron(face_list); + shape.transform(trsf); return true; } @@ -762,27 +631,11 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cga face_list.back().outer.push_back(Kernel::Point_3(0, 0, 0)); face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz)); - // Naive creation - CGAL::Polyhedron_3 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); - } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); - // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - for (auto &vertex: vertices(polyhedron)) { - vertex->point() = vertex->point().transform(trsf); - } - - shape = CGAL::Nef_polyhedron_3(polyhedron); + shape = create_nef_polyhedron(face_list); + shape.transform(trsf); return true; } @@ -820,27 +673,11 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, face_list.back().outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), h)); } - // Naive creation - CGAL::Polyhedron_3 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); - } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); - // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - for (auto &vertex: vertices(polyhedron)) { - vertex->point() = vertex->point().transform(trsf); - } - - shape = CGAL::Nef_polyhedron_3(polyhedron); + shape = create_nef_polyhedron(face_list); + shape.transform(trsf); return true; } @@ -870,27 +707,11 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal face_list.back().outer.push_back(Kernel::Point_3(0, 0, h)); } - // Naive creation - CGAL::Polyhedron_3 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); - } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); - // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - for (auto &vertex: vertices(polyhedron)) { - vertex->point() = vertex->point().transform(trsf); - } - - shape = CGAL::Nef_polyhedron_3(polyhedron); + shape = create_nef_polyhedron(face_list); + shape.transform(trsf); return true; } @@ -940,20 +761,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cg face_list.back().outer.push_back(c); } - // Naive creation - CGAL::Polyhedron_3 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); - } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); - // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - - shape = CGAL::Nef_polyhedron_3(polyhedron); + shape = create_nef_polyhedron(face_list); return true; } #endif diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index f63404d129..71071f5d92 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -138,7 +138,9 @@ namespace IfcGeom { void remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol = -1.); - bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const cgal_placement_t& entity_trsf, ConversionResults& cut_shapes); + bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const cgal_placement_t& entity_trsf, ConversionResults& cut_shapes); + + CGAL::Nef_polyhedron_3 create_nef_polyhedron(std::list &face_list); void purge_cache() { // Rather hack-ish, but a stopgap solution to keep memory under control From 0ffa633a6da9822387286ebe820d678c27d129d3 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 16 Mar 2017 19:30:39 -0600 Subject: [PATCH 54/86] Better validation --- .../kernels/cgal/CgalConversionFunctions.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index b44429d144..b42d90bcdf 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -341,11 +341,20 @@ CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(std::l // std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!polyhedron.is_valid()) { - std::cout << "Invalid polyhedron!" << std::endl; + std::cout << "Polyhedron not valid!" << std::endl; std::ofstream fresult; fresult.open("/Users/ken/Desktop/invalid.off"); - fresult << old_polyhedron << std::endl; + fresult << polyhedron << std::endl; fresult.close(); + return CGAL::Nef_polyhedron_3(); + } if (!polyhedron.is_closed()) { + std::cout << "Polyhedron not closed" << std::endl; + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/open.off"); + fresult << polyhedron << std::endl; + fresult.close(); + // TODO: Nef constructor doesn't support open meshes + return CGAL::Nef_polyhedron_3(polyhedron); } if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); From 2bbe80fd280f4dc8138f79973dbb10b5df8adefc Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 17 Mar 2017 16:12:24 -0600 Subject: [PATCH 55/86] Problems with extended kernel experiment, but this should be incorporated in any case --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 116 ++++++++++-------- 1 file changed, 67 insertions(+), 49 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 7ac1ec8677..6a6248f8ba 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -302,11 +302,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha return false; // } } else if ( shape_type(operand1) == ST_SHAPE ) { - if ( ! convert_shape(operand1, s1) ) { + if (!convert_shape(operand1, s1) ) { return false; } -// TopoDS_Solid temp_solid; -// s1 = ensure_fit_for_subtraction(s1, temp_solid); } else { Logger::Message(Logger::LOG_ERROR, "s1: Invalid representation item for boolean operation", operand1->entity); return false; @@ -322,18 +320,14 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha // shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true); } else if ( shape_type(operand2) == ST_SHAPE ) { shape2_processed = convert_shape(operand2,s2); - if (shape2_processed && !is_halfspace) { -// TopoDS_Solid temp_solid; -// s2 = ensure_fit_for_subtraction(s2, temp_solid); - } } else { Logger::Message(Logger::LOG_ERROR, "s2: Invalid representation item for boolean operation", operand2->entity); } if (!shape2_processed) { -// shape = s1; + shape = s1; Logger::Message(Logger::LOG_ERROR,"Failed to convert SecondOperand of:",l->entity); -// return true; + return true; } // if (!is_halfspace) { @@ -347,76 +341,100 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha if (!s1.is_simple()) { Logger::Message(Logger::LOG_ERROR, "s1: Not simple Nef?", operand1->entity); return false; + } else { + std::ofstream f1; + CGAL::Polyhedron_3 p1; + s1.convert_to_Polyhedron(p1); + f1.open("/Users/ken/Desktop/s1.off"); + f1 << p1 << std::endl; + f1.close(); } if (!s2.is_simple()) { Logger::Message(Logger::LOG_ERROR, "s2: Not simple Nef?", operand2->entity); return false; + } else if (is_halfspace) { + // std::cout << "s2: halfspace" << std::endl; + IfcSchema::IfcHalfSpaceSolid *hss = static_cast(operand2); + IfcSchema::IfcSurface* surface = hss->BaseSurface(); + if (surface->is(IfcSchema::Type::IfcPlane) ) { + cgal_plane_t plane; + IfcGeom::CgalKernel::convert((IfcSchema::IfcPlane *)surface, plane); + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/s2.off"); + fresult << "OFF" << std::endl << "4 2 4" << std::endl; + // x = -5, y = -5, z = (5a +5b -d)/c + fresult << "-5 -5 " << (5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; + // x = -5, y = +5, z = (5a -5b -d)/c + fresult << "-5 5 " << (5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; + // x = 5, y = -5, z = (-5a +5b -d)/c + fresult << "5 -5 " << (-5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; + // x = 5, y = +5, z = (-5a -5b -d)/c + fresult << "5 5 " << (-5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; + fresult << "3 0 1 2" << std::endl; + fresult << "3 3 2 1" << std::endl; + fresult.close(); + } + } else { + std::ofstream f2; + CGAL::Polyhedron_3 p2; + s2.convert_to_Polyhedron(p2); + f2.open("/Users/ken/Desktop/s2.off"); + f2 << p2 << std::endl; + f2.close(); } -// std::ofstream f1; -// f1.open("/Users/ken/Desktop/s1.off"); -// f1 << s1 << std::endl; -// f1.close(); -// std::ofstream f2; -// f2.open("/Users/ken/Desktop/s2.off"); -// f2 << s2 << std::endl; -// f2.close(); - if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { -// std::cout << "Difference" << std::endl; + std::cout << "Difference" << std::endl; CGAL::Nef_polyhedron_3 nef_result = s1-s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; - } -// cgal_shape_t result; -// nef_result.convert_to_polyhedron(result); -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/result.off"); -// fresult << result << std::endl; -// fresult.close(); - shape = nef_result; + } else { + CGAL::Polyhedron_3 result; + nef_result.convert_to_polyhedron(result); + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/result.off"); + fresult << result << std::endl; + fresult.close(); + } shape = nef_result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) { -// std::cout << "Union" << std::endl; + std::cout << "Union" << std::endl; CGAL::Nef_polyhedron_3 nef_result = s1+s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; - } -// cgal_shape_t result; -// nef_result.convert_to_polyhedron(result); -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/result.off"); -// fresult << result << std::endl; -// fresult.close(); - shape = nef_result; + } else { + CGAL::Polyhedron_3 result; + nef_result.convert_to_polyhedron(result); + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/result.off"); + fresult << result << std::endl; + fresult.close(); + } shape = nef_result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) { -// std::cout << "Intersection" << std::endl; + std::cout << "Intersection" << std::endl; CGAL::Nef_polyhedron_3 nef_result = s1*s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; - } -// cgal_shape_t result; -// nef_result.convert_to_polyhedron(result); -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/result.off"); -// fresult << result << std::endl; -// fresult.close(); - shape = nef_result; + } else { + CGAL::Polyhedron_3 result; + nef_result.convert_to_polyhedron(result); + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/result.off"); + fresult << result << std::endl; + fresult.close(); + } shape = nef_result; return true; - - } - - return false; + } return false; } bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& shape) { From 95e6c14f396ae9310b5b2b88e501a6edc423163d Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 17 Mar 2017 19:24:51 -0600 Subject: [PATCH 56/86] Hack to solve issues with IfcHalfSpaceSolid. Not ideal. --- .../kernels/cgal/CgalConversionFunctions.cpp | 20 +-- .../kernels/cgal/CgalIfcGeomShapes.cpp | 114 ++++++++++-------- 2 files changed, 72 insertions(+), 62 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index b42d90bcdf..3291059fb5 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -341,18 +341,18 @@ CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(std::l // std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!polyhedron.is_valid()) { - std::cout << "Polyhedron not valid!" << std::endl; - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/invalid.off"); - fresult << polyhedron << std::endl; - fresult.close(); + std::cout << "create_nef_polyhedron: Polyhedron not valid!" << std::endl; +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/invalid.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); return CGAL::Nef_polyhedron_3(); } if (!polyhedron.is_closed()) { - std::cout << "Polyhedron not closed" << std::endl; - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/open.off"); - fresult << polyhedron << std::endl; - fresult.close(); + std::cout << "create_nef_polyhedron: Polyhedron not closed" << std::endl; +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/open.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); // TODO: Nef constructor doesn't support open meshes return CGAL::Nef_polyhedron_3(polyhedron); } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 6a6248f8ba..15e5054dc4 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -342,14 +342,16 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha Logger::Message(Logger::LOG_ERROR, "s1: Not simple Nef?", operand1->entity); return false; } else { - std::ofstream f1; - CGAL::Polyhedron_3 p1; - s1.convert_to_Polyhedron(p1); - f1.open("/Users/ken/Desktop/s1.off"); - f1 << p1 << std::endl; - f1.close(); +// std::ofstream f1; +// CGAL::Polyhedron_3 p1; +// s1.convert_to_Polyhedron(p1); +// f1.open("/Users/ken/Desktop/s1.off"); +// f1 << p1 << std::endl; +// f1.close(); } + bool is_plane = false; + cgal_plane_t plane; if (!s2.is_simple()) { Logger::Message(Logger::LOG_ERROR, "s2: Not simple Nef?", operand2->entity); return false; @@ -358,80 +360,86 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha IfcSchema::IfcHalfSpaceSolid *hss = static_cast(operand2); IfcSchema::IfcSurface* surface = hss->BaseSurface(); if (surface->is(IfcSchema::Type::IfcPlane) ) { - cgal_plane_t plane; + is_plane = true; IfcGeom::CgalKernel::convert((IfcSchema::IfcPlane *)surface, plane); - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/s2.off"); - fresult << "OFF" << std::endl << "4 2 4" << std::endl; - // x = -5, y = -5, z = (5a +5b -d)/c - fresult << "-5 -5 " << (5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; - // x = -5, y = +5, z = (5a -5b -d)/c - fresult << "-5 5 " << (5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; - // x = 5, y = -5, z = (-5a +5b -d)/c - fresult << "5 -5 " << (-5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; - // x = 5, y = +5, z = (-5a -5b -d)/c - fresult << "5 5 " << (-5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; - fresult << "3 0 1 2" << std::endl; - fresult << "3 3 2 1" << std::endl; - fresult.close(); + if (hss->AgreementFlag()) plane = plane.opposite(); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/s2.off"); +// fresult << "OFF" << std::endl << "4 2 4" << std::endl; +// // x = -5, y = -5, z = (5a +5b -d)/c +// fresult << "-5 -5 " << (5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; +// // x = -5, y = +5, z = (5a -5b -d)/c +// fresult << "-5 5 " << (5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; +// // x = 5, y = -5, z = (-5a +5b -d)/c +// fresult << "5 -5 " << (-5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; +// // x = 5, y = +5, z = (-5a -5b -d)/c +// fresult << "5 5 " << (-5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; +// fresult << "3 0 1 2" << std::endl; +// fresult << "3 3 2 1" << std::endl; +// fresult.close(); } } else { - std::ofstream f2; - CGAL::Polyhedron_3 p2; - s2.convert_to_Polyhedron(p2); - f2.open("/Users/ken/Desktop/s2.off"); - f2 << p2 << std::endl; - f2.close(); +// std::ofstream f2; +// CGAL::Polyhedron_3 p2; +// s2.convert_to_Polyhedron(p2); +// f2.open("/Users/ken/Desktop/s2.off"); +// f2 << p2 << std::endl; +// f2.close(); } if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { - std::cout << "Difference" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = s1-s2; +// std::cout << "Difference" << std::endl; + CGAL::Nef_polyhedron_3 nef_result = s1; + if (is_halfspace) { + if (is_plane) nef_result = nef_result.intersection(plane, CGAL::Nef_polyhedron_3::Intersection_mode::CLOSED_HALFSPACE); + } else { + nef_result -= s2; + } if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; } else { - CGAL::Polyhedron_3 result; - nef_result.convert_to_polyhedron(result); - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/result.off"); - fresult << result << std::endl; - fresult.close(); +// CGAL::Polyhedron_3 result; +// nef_result.convert_to_polyhedron(result); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/result.off"); +// fresult << result << std::endl; +// fresult.close(); } shape = nef_result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) { - std::cout << "Union" << std::endl; +// std::cout << "Union" << std::endl; CGAL::Nef_polyhedron_3 nef_result = s1+s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; } else { - CGAL::Polyhedron_3 result; - nef_result.convert_to_polyhedron(result); - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/result.off"); - fresult << result << std::endl; - fresult.close(); +// CGAL::Polyhedron_3 result; +// nef_result.convert_to_polyhedron(result); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/result.off"); +// fresult << result << std::endl; +// fresult.close(); } shape = nef_result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) { - std::cout << "Intersection" << std::endl; +// std::cout << "Intersection" << std::endl; CGAL::Nef_polyhedron_3 nef_result = s1*s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; } else { - CGAL::Polyhedron_3 result; - nef_result.convert_to_polyhedron(result); - std::ofstream fresult; - fresult.open("/Users/ken/Desktop/result.off"); - fresult << result << std::endl; - fresult.close(); +// CGAL::Polyhedron_3 result; +// nef_result.convert_to_polyhedron(result); +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/result.off"); +// fresult << result << std::endl; +// fresult.close(); } shape = nef_result; return true; } return false; @@ -793,11 +801,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, cgal_sh cgal_plane_t pln; IfcGeom::CgalKernel::convert((IfcSchema::IfcPlane*)surface,pln); - // TODO: This might be the other way around - if (!l->AgreementFlag()) pln = pln.opposite(); + // TODO: Don't fully understand the logic here. Might be incorrect. + if (l->AgreementFlag()) pln = pln.opposite(); // const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction()); // shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid(); - shape = CGAL::Nef_polyhedron_3(pln); + shape = CGAL::Nef_polyhedron_3(); + // TODO: We return an empty Nef polyhedron for now and handle halfspace differences in IfcBooleanResult. The other option would be to switch to an extended kernel. +// shape = CGAL::Nef_polyhedron_3(pln); return true; } From cf9605f1089098775bfa5eb1b691aecdd95a74c0 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 20 Mar 2017 15:56:31 -0600 Subject: [PATCH 57/86] Missing Shapes, support for voids --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 6 ++- .../kernels/cgal/CgalIfcGeomShapes.cpp | 52 ++++++++++++++++--- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index e0ecad5298..e438b3ace1 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -28,14 +28,16 @@ #include "../../../ifcparse/IfcUtil.h" #include "../../../ifcparse/IfcParse.h" +SHAPES(IfcShellBasedSurfaceModel); +SHAPES(IfcFaceBasedSurfaceModel); SHAPES(IfcRepresentation); +SHAPES(IfcMappedItem); // IfcFacetedBrep included // IfcAdvancedBrep included // IfcFacetedBrepWithVoids included // IfcAdvancedBrepWithVoids included SHAPES(IfcManifoldSolidBrep); -SHAPES(IfcMappedItem); -SHAPES(IfcFaceBasedSurfaceModel); +SHAPES(IfcGeometricSet); SHAPE(IfcExtrudedAreaSolid); SHAPE(IfcConnectedFaceSet); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 15e5054dc4..7e912c8b5b 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -1,6 +1,46 @@ #include "CgalKernel.h" #include "CgalConversionResult.h" +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcGeometricSet* l, ConversionResults& shapes) { + IfcEntityList::ptr elements = l->Elements(); + if ( !elements->size() ) return false; + bool part_succes = false; + const IfcGeom::SurfaceStyle* parent_style = get_style(l); + for ( IfcEntityList::it it = elements->begin(); it != elements->end(); ++ it ) { + IfcSchema::IfcGeometricSetSelect* element = *it; + cgal_shape_t s; + if (convert_shape(element, s)) { + part_succes = true; + const IfcGeom::SurfaceStyle* style = 0; + if (element->is(IfcSchema::Type::IfcPoint)) { + style = get_style((IfcSchema::IfcPoint*) element); + } else if (element->is(IfcSchema::Type::IfcCurve)) { + style = get_style((IfcSchema::IfcCurve*) element); + } else if (element->is(IfcSchema::Type::IfcSurface)) { + style = get_style((IfcSchema::IfcSurface*) element); + } + shapes.push_back(ConversionResult(new CgalShape(s), style ? style : parent_style)); + } + } + return part_succes; +} + +bool IfcGeom::CgalKernel::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 ) { + cgal_shape_t s; + const SurfaceStyle* shell_style = 0; + if ((*it)->is(IfcSchema::Type::IfcRepresentationItem)) { + shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it); + } + if (convert_shape(*it,s)) { + shapes.push_back(ConversionResult(new CgalShape(s), shell_style ? shell_style : collective_style)); + } + } + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) { cgal_shape_t s; const SurfaceStyle* collective_style = get_style(l); @@ -18,12 +58,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, Conv #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(); - // } + cgal_shape_t 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 -= s2; + } } shape.push_back(ConversionResult(new CgalShape(s), indiv_style ? indiv_style : collective_style)); From cf6bd5a6291b3d11b7e81158eed46873e7746cb6 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 20 Mar 2017 16:31:06 -0600 Subject: [PATCH 58/86] Enabled missing Cartesian transformations --- src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 7e912c8b5b..39c505386a 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -78,17 +78,11 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) { IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) { - Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); - return false; + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2DnonUniform*)transform,gtrsf); } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) { - cgal_placement_t trsf; - IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); - gtrsf = trsf; + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,gtrsf); } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { - cgal_placement_t trsf_2d; - Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); -// IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,trsf_2d); - gtrsf = (cgal_placement_t) trsf_2d; + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,gtrsf); } IfcSchema::IfcRepresentationMap* map = l->MappingSource(); IfcSchema::IfcAxis2Placement* placement = map->MappingOrigin(); From 8090bb4c0070650b8d5a30313392b0b448846656 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 20 Mar 2017 16:35:14 -0600 Subject: [PATCH 59/86] Shapes with styles in separate file --- .../kernels/cgal/CgalConversionFunctions.cpp | 21 --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 139 --------------- .../cgal/CgalIfcGeomShapesWithStyles.cpp | 160 ++++++++++++++++++ 3 files changed, 160 insertions(+), 160 deletions(-) create mode 100644 src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 3291059fb5..a7a52b34ad 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -1,27 +1,6 @@ #include "../../../ifcparse/IfcParse.h" #include "CgalKernel.h" -#include "CgalConversionResult.h" - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, ConversionResults& shapes) { - IfcSchema::IfcRepresentationItem::list::ptr items = l->Items(); - bool part_succes = false; - if (items->size()) { - for (IfcSchema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) { - IfcSchema::IfcRepresentationItem* representation_item = *it; - if (shape_type(representation_item) == ST_SHAPELIST) { - part_succes |= convert_shapes(*it, shapes); - } else { - cgal_shape_t s; - if (convert_shape(representation_item, s)) { - shapes.push_back(ConversionResult(new CgalShape(s), get_style(representation_item))); - part_succes |= true; - } - } - } - } - return part_succes; -} bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { std::vector xyz = l->Coordinates(); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 39c505386a..80a5da0066 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -1,143 +1,4 @@ #include "CgalKernel.h" -#include "CgalConversionResult.h" - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcGeometricSet* l, ConversionResults& shapes) { - IfcEntityList::ptr elements = l->Elements(); - if ( !elements->size() ) return false; - bool part_succes = false; - const IfcGeom::SurfaceStyle* parent_style = get_style(l); - for ( IfcEntityList::it it = elements->begin(); it != elements->end(); ++ it ) { - IfcSchema::IfcGeometricSetSelect* element = *it; - cgal_shape_t s; - if (convert_shape(element, s)) { - part_succes = true; - const IfcGeom::SurfaceStyle* style = 0; - if (element->is(IfcSchema::Type::IfcPoint)) { - style = get_style((IfcSchema::IfcPoint*) element); - } else if (element->is(IfcSchema::Type::IfcCurve)) { - style = get_style((IfcSchema::IfcCurve*) element); - } else if (element->is(IfcSchema::Type::IfcSurface)) { - style = get_style((IfcSchema::IfcSurface*) element); - } - shapes.push_back(ConversionResult(new CgalShape(s), style ? style : parent_style)); - } - } - return part_succes; -} - -bool IfcGeom::CgalKernel::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 ) { - cgal_shape_t s; - const SurfaceStyle* shell_style = 0; - if ((*it)->is(IfcSchema::Type::IfcRepresentationItem)) { - shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it); - } - if (convert_shape(*it,s)) { - shapes.push_back(ConversionResult(new CgalShape(s), shell_style ? shell_style : collective_style)); - } - } - return true; -} - -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) { - cgal_shape_t 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 -= s2; - } - } - - shape.push_back(ConversionResult(new CgalShape(s), indiv_style ? indiv_style : collective_style)); - return true; - } - return false; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionResults& shapes) { - cgal_placement_t gtrsf; - IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget(); - if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) { - IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); - } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) { - IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2DnonUniform*)transform,gtrsf); - } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) { - IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,gtrsf); - } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { - IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,gtrsf); - } - IfcSchema::IfcRepresentationMap* map = l->MappingSource(); - IfcSchema::IfcAxis2Placement* placement = map->MappingOrigin(); - cgal_placement_t trsf; - if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { - IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); - } else { - cgal_placement_t trsf_2d; - IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d); - trsf = trsf_2d; - } - - // TODO: Check - gtrsf = trsf * gtrsf; - -// std::cout << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << gtrsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - - const IfcGeom::SurfaceStyle* mapped_item_style = get_style(l); - - const size_t previous_size = shapes.size(); - bool b = convert_shapes(map->MappedRepresentation(), shapes); - - for (size_t i = previous_size; i < shapes.size(); ++ i ) { - IfcGeom::CgalPlacement place(gtrsf); - shapes[i].prepend(&place); - - // Apply styles assigned to the mapped item only if on - // a more granular level no styles have been applied - if (!shapes[i].hasStyle()) { - shapes[i].setStyle(mapped_item_style); - } - } - - return b; -} - -bool IfcGeom::CgalKernel::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); - for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) { - cgal_shape_t s; - const SurfaceStyle* shell_style = get_style(*it); - if (convert_shape(*it,s)) { - shapes.push_back(ConversionResult(new CgalShape(s), shell_style ? shell_style : collective_style)); - part_success |= true; - } - } - return part_success; -} bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal_shape_t &shape) { const double height = l->Depth() * getValue(GV_LENGTH_UNIT); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp new file mode 100644 index 0000000000..4898625956 --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp @@ -0,0 +1,160 @@ +#include "CgalKernel.h" +#include "CgalConversionResult.h" + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRepresentation* l, ConversionResults& shapes) { + IfcSchema::IfcRepresentationItem::list::ptr items = l->Items(); + bool part_succes = false; + if (items->size()) { + for (IfcSchema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) { + IfcSchema::IfcRepresentationItem* representation_item = *it; + if (shape_type(representation_item) == ST_SHAPELIST) { + part_succes |= convert_shapes(*it, shapes); + } else { + cgal_shape_t s; + if (convert_shape(representation_item, s)) { + shapes.push_back(ConversionResult(new CgalShape(s), get_style(representation_item))); + part_succes |= true; + } + } + } + } + return part_succes; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcGeometricSet* l, ConversionResults& shapes) { + IfcEntityList::ptr elements = l->Elements(); + if ( !elements->size() ) return false; + bool part_succes = false; + const IfcGeom::SurfaceStyle* parent_style = get_style(l); + for ( IfcEntityList::it it = elements->begin(); it != elements->end(); ++ it ) { + IfcSchema::IfcGeometricSetSelect* element = *it; + cgal_shape_t s; + if (convert_shape(element, s)) { + part_succes = true; + const IfcGeom::SurfaceStyle* style = 0; + if (element->is(IfcSchema::Type::IfcPoint)) { + style = get_style((IfcSchema::IfcPoint*) element); + } else if (element->is(IfcSchema::Type::IfcCurve)) { + style = get_style((IfcSchema::IfcCurve*) element); + } else if (element->is(IfcSchema::Type::IfcSurface)) { + style = get_style((IfcSchema::IfcSurface*) element); + } + shapes.push_back(ConversionResult(new CgalShape(s), style ? style : parent_style)); + } + } + return part_succes; +} + +bool IfcGeom::CgalKernel::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 ) { + cgal_shape_t s; + const SurfaceStyle* shell_style = 0; + if ((*it)->is(IfcSchema::Type::IfcRepresentationItem)) { + shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it); + } + if (convert_shape(*it,s)) { + shapes.push_back(ConversionResult(new CgalShape(s), shell_style ? shell_style : collective_style)); + } + } + return true; +} + +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) { + cgal_shape_t 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 -= s2; + } + } + + shape.push_back(ConversionResult(new CgalShape(s), indiv_style ? indiv_style : collective_style)); + return true; + } + return false; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionResults& shapes) { + cgal_placement_t gtrsf; + IfcSchema::IfcCartesianTransformationOperator* transform = l->MappingTarget(); + if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3DnonUniform*)transform,gtrsf); + } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2DnonUniform*)transform,gtrsf); + } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,gtrsf); + } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator2D*)transform,gtrsf); + } + IfcSchema::IfcRepresentationMap* map = l->MappingSource(); + IfcSchema::IfcAxis2Placement* placement = map->MappingOrigin(); + cgal_placement_t trsf; + if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf); + } else { + cgal_placement_t trsf_2d; + IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d); + trsf = trsf_2d; + } + + // TODO: Check + gtrsf = trsf * gtrsf; + + // std::cout << std::endl; + // for (int i = 0; i < 3; ++i) { + // for (int j = 0; j < 4; ++j) { + // std::cout << gtrsf.cartesian(i, j) << " "; + // } std::cout << std::endl; + // } + + const IfcGeom::SurfaceStyle* mapped_item_style = get_style(l); + + const size_t previous_size = shapes.size(); + bool b = convert_shapes(map->MappedRepresentation(), shapes); + + for (size_t i = previous_size; i < shapes.size(); ++ i ) { + IfcGeom::CgalPlacement place(gtrsf); + shapes[i].prepend(&place); + + // Apply styles assigned to the mapped item only if on + // a more granular level no styles have been applied + if (!shapes[i].hasStyle()) { + shapes[i].setStyle(mapped_item_style); + } + } + + return b; +} + +bool IfcGeom::CgalKernel::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); + for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) { + cgal_shape_t s; + const SurfaceStyle* shell_style = get_style(*it); + if (convert_shape(*it,s)) { + shapes.push_back(ConversionResult(new CgalShape(s), shell_style ? shell_style : collective_style)); + part_success |= true; + } + } + return part_success; +} From 62ca6f6a7d2e79a03f9033b79b8d04fbc0425caf Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 20 Mar 2017 16:45:27 -0600 Subject: [PATCH 60/86] Checked shapes with styles. Found bug? --- src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp index 4898625956..2bfd8caaac 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp @@ -79,8 +79,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, Conv for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) { cgal_shape_t s2; - /// @todo No extensive shapefixing since shells should be disjoint. - /// @todo Awaiting generalized boolean ops module with appropriate checking + // TODO: This looks weird. Aren't we removing the outer shell again and again? + // Maybe it should be + // if (convert_shape(*it, s2)) { if (convert_shape(l->Outer(), s2)) { s -= s2; } From 71d7bbd6bab33de8a533b39b67fee2a91b757917 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 20 Mar 2017 20:06:48 -0600 Subject: [PATCH 61/86] =?UTF-8?q?Ordering=20things=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kernels/cgal/CgalConversionFunctions.cpp | 286 ------------------ .../kernels/cgal/CgalIfcGeomPrimitives.cpp | 285 +++++++++++++++++ 2 files changed, 285 insertions(+), 286 deletions(-) create mode 100644 src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index a7a52b34ad..818ee56f47 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -1,296 +1,10 @@ -#include "../../../ifcparse/IfcParse.h" - #include "CgalKernel.h" -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { - std::vector xyz = l->Coordinates(); - point = Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, - xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, - xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f); -// std::cout << "Converted Point(" << point << ")" << std::endl; - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_direction_t& dir) { -// IN_CACHE(IfcDirection,l,cgal_direction_t,dir) - std::vector xyz = l->DirectionRatios(); - dir = Kernel::Vector_3(xyz.size() ? xyz[0] : 0.0f, - xyz.size() > 1 ? xyz[1] : 0.0f, - xyz.size() > 2 ? xyz[2] : 0.0f); -// CACHE(IfcDirection,l,dir) - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcVector* l, cgal_vector_t& v) { -// IN_CACHE(IfcVector,l,cgal_vector_t,v) - cgal_direction_t d; - IfcGeom::CgalKernel::convert(l->Orientation(),d); - v = l->Magnitude() * getValue(GV_LENGTH_UNIT) * d; -// CACHE(IfcVector,l,v) - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPlane* pln, cgal_plane_t& plane) { -// IN_CACHE(IfcPlane,pln,gp_Pln,plane) - IfcSchema::IfcAxis2Placement3D* l = pln->Position(); - cgal_point_t o; - cgal_direction_t axis = Kernel::Vector_3(0,0,1); - cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); - IfcGeom::CgalKernel::convert(l->Location(),o); - bool hasRef = l->hasRefDirection(); - if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); - if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); - Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); - Kernel::Vector_3 x = CGAL::cross_product(y, axis); - - cgal_plane_t ax3; - if ( hasRef ) ax3 = Kernel::Plane_3(o,o+x,o+y); - else ax3 = Kernel::Plane_3(o,axis); - plane = ax3; - -// std::cout << "IfcPlane C = " << o << std::endl; -// std::cout << "IfcPlane z (axis, exact) = " << axis << std::endl; -// std::cout << "IfcPlane x (refDirection, approximate) = " << refDirection << std::endl; -// std::cout << "IfcPlane y (computed, exact) = " << y << std::endl; -// std::cout << "IfcPlane x (computed, exact) = " << x << std::endl; -// -// std::cout << "Plane_3 o = " << o << std::endl; -// std::cout << "Plane_3 o+x = " << o+x << std::endl; -// std::cout << "Plane_3 o+y = " << o+y << std::endl; - - // ax + by + cz + d = 0 -// std::cout << "Plane: a = " << plane.a() << ", b = " << plane.b() << ", c = " << plane.c() << ", d = " << plane.d() << std::endl; - -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/plane.obj"); -// // x = -5, y = -5, z = (5a +5b -d)/c -// fresult << "v -5 -5 " << (5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; -// // x = -5, y = +5, z = (5a -5b -d)/c -// fresult << "v -5 5 " << (5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; -// // x = 5, y = -5, z = (-5a +5b -d)/c -// fresult << "v 5 -5 " << (-5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; -// // x = 5, y = +5, z = (-5a -5b -d)/c -// fresult << "v 5 5 " << (-5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; -// fresult << "f 1 2 3" << std::endl; -// fresult << "f 4 3 2" << std::endl; -// fresult.close(); - -// CACHE(IfcPlane,pln,plane) - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_placement_t& trsf) { - // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) - cgal_point_t o; - cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); - IfcGeom::CgalKernel::convert(l->Location(),o); - bool hasRef = l->hasRefDirection(); - if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); - cgal_direction_t y = Kernel::Vector_3(-refDirection.y(), refDirection.x(), 0.0); - - // TODO: Should be checked. - trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), 0.0, o.cartesian(0), - refDirection.cartesian(1), y.cartesian(1), 0.0, o.cartesian(1), - 0.0, 0.0, 1.0, 0.0); - - // CACHE(IfcAxis2Placement3D,l,trsf) - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_placement_t& trsf) { -// IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) - cgal_point_t o; - cgal_direction_t axis = Kernel::Vector_3(0,0,1); - cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); - IfcGeom::CgalKernel::convert(l->Location(),o); - bool hasRef = l->hasRefDirection(); - if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); - if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); - Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); - Kernel::Vector_3 x = CGAL::cross_product(y, axis); - -// std::cout << "Ref direction: " << refDirection << std::endl; -// std::cout << "Axis: " << axis << std::endl; -// std::cout << "Origin: " << o << std::endl; - - // TODO: Should be checked. - trsf = Kernel::Aff_transformation_3(x.cartesian(0), y.cartesian(0), axis.cartesian(0), o.cartesian(0), - x.cartesian(1), y.cartesian(1), axis.cartesian(1), o.cartesian(1), - x.cartesian(2), y.cartesian(2), axis.cartesian(2), o.cartesian(2)); - -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << trsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - -// CACHE(IfcAxis2Placement3D,l,trsf) - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_placement_t& trsf) { - // TODO: These macros don't work for the CGAL types. Need to check why. -// IN_CACHE(IfcObjectPlacement,l,cgal_placement_t,trsf) - if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) { - Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l->entity); - return false; - } - -// std::cout << "initial trsf (identity?)" << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << trsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - - IfcSchema::IfcLocalPlacement* current = (IfcSchema::IfcLocalPlacement*)l; - for (;;) { - cgal_placement_t trsf2; - - IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement(); - if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) { - IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); - -// std::cout << "trsf2" << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << trsf2.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - - trsf = trsf * trsf2; // TODO: I think it's fine, but maybe should it be the other way around? - -// std::cout << "trsf (after multiplication)" << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << trsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - } - if ( current->hasPlacementRelTo() ) { - IfcSchema::IfcObjectPlacement* relto = current->PlacementRelTo(); - if ( relto->is(IfcSchema::Type::IfcLocalPlacement) ) - current = (IfcSchema::IfcLocalPlacement*)current->PlacementRelTo(); - else break; - } else break; - } -// CACHE(IfcObjectPlacement,l,trsf) - return true; -} - bool IfcGeom::CgalKernel::convert_wire_to_face(const cgal_wire_t& wire, cgal_face_t& face) { face.outer = wire; return true; } -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2D* l, cgal_placement_t& trsf) { -// IN_CACHE(IfcCartesianTransformationOperator2D,l,cgal_placement_t,trsf) - - cgal_point_t origin; - cgal_direction_t axis1 (1.,0.,0.); - cgal_direction_t axis2 (0.,1.,0.); - - IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); - if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); - double scale = 1.0; - if (l->hasScale()) { - scale = l->Scale(); - } - - // TODO: Untested - trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), 0.0, origin.cartesian(0), - axis1.cartesian(1), scale*axis2.cartesian(1), 0.0, origin.cartesian(1), - 0.0, 0.0, 1.0, 0.0); - -// CACHE(IfcCartesianTransformationOperator2D,l,trsf) - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, cgal_placement_t& gtrsf) { -// IN_CACHE(IfcCartesianTransformationOperator2DnonUniform,l,cgal_placement_t,gtrsf) - - cgal_placement_t trsf; - cgal_point_t origin; - cgal_direction_t axis1 (1.,0.,0.); - cgal_direction_t axis2 (0.,1.,0.); - - IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); - if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); - - const double scale1 = l->hasScale() ? l->Scale() : 1.0f; - const double scale2 = l->hasScale2() ? l->Scale2() : scale1; - - // TODO: Untested - trsf = Kernel::Aff_transformation_3(scale1*axis1.cartesian(0), axis2.cartesian(0), 0.0, origin.cartesian(0), - axis1.cartesian(1), scale2*axis2.cartesian(1), 0.0, origin.cartesian(1), - 0.0, 0.0, 1.0, 0.0); - -// CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gtrsf) - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, cgal_placement_t& trsf) { -// IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf) - cgal_point_t origin; - IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); - cgal_direction_t axis1 (1.,0.,0.); - cgal_direction_t axis2 (0.,1.,0.); - cgal_direction_t axis3 (0.,0.,1.); - if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); - if ( l->hasAxis3() ) IfcGeom::CgalKernel::convert(l->Axis3(),axis3); - double scale = 1.0; - if (l->hasScale()) { - scale = l->Scale(); - } - - // TODO: Untested - trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0), - axis1.cartesian(1), scale*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), - axis1.cartesian(2), axis2.cartesian(2), scale*axis3.cartesian(2), origin.cartesian(2)); - -// std::cout << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << trsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - -// CACHE(IfcCartesianTransformationOperator3D,l,trsf) - return true; -} - -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* l, cgal_placement_t& gtrsf) { -// IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf) - cgal_point_t origin; - IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); - cgal_direction_t axis1 (1.,0.,0.); - cgal_direction_t axis2 (0.,1.,0.); - cgal_direction_t axis3 (0.,0.,1.); - if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); - if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); - if ( l->hasAxis3() ) IfcGeom::CgalKernel::convert(l->Axis3(),axis3); - const double scale1 = l->hasScale() ? l->Scale() : 1.0f; - const double scale2 = l->hasScale2() ? l->Scale2() : scale1; - const double scale3 = l->hasScale3() ? l->Scale3() : scale1; - - // TODO: Untested - gtrsf = Kernel::Aff_transformation_3(scale1*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0), - axis1.cartesian(1), scale2*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), - axis1.cartesian(2), axis2.cartesian(2), scale3*axis3.cartesian(2), origin.cartesian(2)); - -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << gtrsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - -// CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gtrsf) - return true; -} - void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol) { if (tol <= 0.) tol = getValue(GV_PRECISION); tol *= tol; diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp new file mode 100644 index 0000000000..2a878e40fe --- /dev/null +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp @@ -0,0 +1,285 @@ +#include "CgalKernel.h" + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianPoint* l, cgal_point_t& point) { + std::vector xyz = l->Coordinates(); + point = Kernel::Point_3(xyz.size() ? (xyz[0]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 1 ? (xyz[1]*getValue(GV_LENGTH_UNIT)) : 0.0f, + xyz.size() > 2 ? (xyz[2]*getValue(GV_LENGTH_UNIT)) : 0.0f); + // std::cout << "Converted Point(" << point << ")" << std::endl; + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDirection* l, cgal_direction_t& dir) { + // IN_CACHE(IfcDirection,l,cgal_direction_t,dir) + std::vector xyz = l->DirectionRatios(); + dir = Kernel::Vector_3(xyz.size() ? xyz[0] : 0.0f, + xyz.size() > 1 ? xyz[1] : 0.0f, + xyz.size() > 2 ? xyz[2] : 0.0f); + // CACHE(IfcDirection,l,dir) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcVector* l, cgal_vector_t& v) { + // IN_CACHE(IfcVector,l,cgal_vector_t,v) + cgal_direction_t d; + IfcGeom::CgalKernel::convert(l->Orientation(),d); + v = l->Magnitude() * getValue(GV_LENGTH_UNIT) * d; + // CACHE(IfcVector,l,v) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPlane* pln, cgal_plane_t& plane) { + // IN_CACHE(IfcPlane,pln,gp_Pln,plane) + IfcSchema::IfcAxis2Placement3D* l = pln->Position(); + cgal_point_t o; + cgal_direction_t axis = Kernel::Vector_3(0,0,1); + cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); + IfcGeom::CgalKernel::convert(l->Location(),o); + bool hasRef = l->hasRefDirection(); + if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); + if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); + Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); + Kernel::Vector_3 x = CGAL::cross_product(y, axis); + + cgal_plane_t ax3; + if ( hasRef ) ax3 = Kernel::Plane_3(o,o+x,o+y); + else ax3 = Kernel::Plane_3(o,axis); + plane = ax3; + + // std::cout << "IfcPlane C = " << o << std::endl; + // std::cout << "IfcPlane z (axis, exact) = " << axis << std::endl; + // std::cout << "IfcPlane x (refDirection, approximate) = " << refDirection << std::endl; + // std::cout << "IfcPlane y (computed, exact) = " << y << std::endl; + // std::cout << "IfcPlane x (computed, exact) = " << x << std::endl; + // + // std::cout << "Plane_3 o = " << o << std::endl; + // std::cout << "Plane_3 o+x = " << o+x << std::endl; + // std::cout << "Plane_3 o+y = " << o+y << std::endl; + + // ax + by + cz + d = 0 + // std::cout << "Plane: a = " << plane.a() << ", b = " << plane.b() << ", c = " << plane.c() << ", d = " << plane.d() << std::endl; + + // std::ofstream fresult; + // fresult.open("/Users/ken/Desktop/plane.obj"); + // // x = -5, y = -5, z = (5a +5b -d)/c + // fresult << "v -5 -5 " << (5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; + // // x = -5, y = +5, z = (5a -5b -d)/c + // fresult << "v -5 5 " << (5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; + // // x = 5, y = -5, z = (-5a +5b -d)/c + // fresult << "v 5 -5 " << (-5.0*CGAL::to_double(plane.a())+5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; + // // x = 5, y = +5, z = (-5a -5b -d)/c + // fresult << "v 5 5 " << (-5.0*CGAL::to_double(plane.a())-5.0*CGAL::to_double(plane.b())-CGAL::to_double(plane.d()))/CGAL::to_double(plane.c()) << std::endl; + // fresult << "f 1 2 3" << std::endl; + // fresult << "f 4 3 2" << std::endl; + // fresult.close(); + + // CACHE(IfcPlane,pln,plane) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_placement_t& trsf) { + // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) + cgal_point_t o; + cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); + IfcGeom::CgalKernel::convert(l->Location(),o); + bool hasRef = l->hasRefDirection(); + if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); + cgal_direction_t y = Kernel::Vector_3(-refDirection.y(), refDirection.x(), 0.0); + + // TODO: Should be checked. + trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), 0.0, o.cartesian(0), + refDirection.cartesian(1), y.cartesian(1), 0.0, o.cartesian(1), + 0.0, 0.0, 1.0, 0.0); + + // CACHE(IfcAxis2Placement3D,l,trsf) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_placement_t& trsf) { + // IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf) + cgal_point_t o; + cgal_direction_t axis = Kernel::Vector_3(0,0,1); + cgal_direction_t refDirection = Kernel::Vector_3(1,0,0); + IfcGeom::CgalKernel::convert(l->Location(),o); + bool hasRef = l->hasRefDirection(); + if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(),axis); + if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); + Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); + Kernel::Vector_3 x = CGAL::cross_product(y, axis); + + // std::cout << "Ref direction: " << refDirection << std::endl; + // std::cout << "Axis: " << axis << std::endl; + // std::cout << "Origin: " << o << std::endl; + + // TODO: Should be checked. + trsf = Kernel::Aff_transformation_3(x.cartesian(0), y.cartesian(0), axis.cartesian(0), o.cartesian(0), + x.cartesian(1), y.cartesian(1), axis.cartesian(1), o.cartesian(1), + x.cartesian(2), y.cartesian(2), axis.cartesian(2), o.cartesian(2)); + + // for (int i = 0; i < 3; ++i) { + // for (int j = 0; j < 4; ++j) { + // std::cout << trsf.cartesian(i, j) << " "; + // } std::cout << std::endl; + // } + + // CACHE(IfcAxis2Placement3D,l,trsf) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_placement_t& trsf) { + // TODO: These macros don't work for the CGAL types. Need to check why. + // IN_CACHE(IfcObjectPlacement,l,cgal_placement_t,trsf) + if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) { + Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l->entity); + return false; + } + + // std::cout << "initial trsf (identity?)" << std::endl; + // for (int i = 0; i < 3; ++i) { + // for (int j = 0; j < 4; ++j) { + // std::cout << trsf.cartesian(i, j) << " "; + // } std::cout << std::endl; + // } + + IfcSchema::IfcLocalPlacement* current = (IfcSchema::IfcLocalPlacement*)l; + for (;;) { + cgal_placement_t trsf2; + + IfcSchema::IfcAxis2Placement* relplacement = current->RelativePlacement(); + if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) { + IfcGeom::CgalKernel::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2); + + // std::cout << "trsf2" << std::endl; + // for (int i = 0; i < 3; ++i) { + // for (int j = 0; j < 4; ++j) { + // std::cout << trsf2.cartesian(i, j) << " "; + // } std::cout << std::endl; + // } + + trsf = trsf * trsf2; // TODO: I think it's fine, but maybe should it be the other way around? + + // std::cout << "trsf (after multiplication)" << std::endl; + // for (int i = 0; i < 3; ++i) { + // for (int j = 0; j < 4; ++j) { + // std::cout << trsf.cartesian(i, j) << " "; + // } std::cout << std::endl; + // } + } + if ( current->hasPlacementRelTo() ) { + IfcSchema::IfcObjectPlacement* relto = current->PlacementRelTo(); + if ( relto->is(IfcSchema::Type::IfcLocalPlacement) ) + current = (IfcSchema::IfcLocalPlacement*)current->PlacementRelTo(); + else break; + } else break; + } + // CACHE(IfcObjectPlacement,l,trsf) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2D* l, cgal_placement_t& trsf) { + // IN_CACHE(IfcCartesianTransformationOperator2D,l,cgal_placement_t,trsf) + + cgal_point_t origin; + cgal_direction_t axis1 (1.,0.,0.); + cgal_direction_t axis2 (0.,1.,0.); + + IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); + if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); + double scale = 1.0; + if (l->hasScale()) { + scale = l->Scale(); + } + + // TODO: Untested + trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), 0.0, origin.cartesian(0), + axis1.cartesian(1), scale*axis2.cartesian(1), 0.0, origin.cartesian(1), + 0.0, 0.0, 1.0, 0.0); + + // CACHE(IfcCartesianTransformationOperator2D,l,trsf) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, cgal_placement_t& gtrsf) { + // IN_CACHE(IfcCartesianTransformationOperator2DnonUniform,l,cgal_placement_t,gtrsf) + + cgal_placement_t trsf; + cgal_point_t origin; + cgal_direction_t axis1 (1.,0.,0.); + cgal_direction_t axis2 (0.,1.,0.); + + IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); + if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); + + const double scale1 = l->hasScale() ? l->Scale() : 1.0f; + const double scale2 = l->hasScale2() ? l->Scale2() : scale1; + + // TODO: Untested + trsf = Kernel::Aff_transformation_3(scale1*axis1.cartesian(0), axis2.cartesian(0), 0.0, origin.cartesian(0), + axis1.cartesian(1), scale2*axis2.cartesian(1), 0.0, origin.cartesian(1), + 0.0, 0.0, 1.0, 0.0); + + // CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gtrsf) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, cgal_placement_t& trsf) { + // IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf) + cgal_point_t origin; + IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); + cgal_direction_t axis1 (1.,0.,0.); + cgal_direction_t axis2 (0.,1.,0.); + cgal_direction_t axis3 (0.,0.,1.); + if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); + if ( l->hasAxis3() ) IfcGeom::CgalKernel::convert(l->Axis3(),axis3); + double scale = 1.0; + if (l->hasScale()) { + scale = l->Scale(); + } + + // TODO: Untested + trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0), + axis1.cartesian(1), scale*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), + axis1.cartesian(2), axis2.cartesian(2), scale*axis3.cartesian(2), origin.cartesian(2)); + + // std::cout << std::endl; + // for (int i = 0; i < 3; ++i) { + // for (int j = 0; j < 4; ++j) { + // std::cout << trsf.cartesian(i, j) << " "; + // } std::cout << std::endl; + // } + + // CACHE(IfcCartesianTransformationOperator3D,l,trsf) + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* l, cgal_placement_t& gtrsf) { + // IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf) + cgal_point_t origin; + IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); + cgal_direction_t axis1 (1.,0.,0.); + cgal_direction_t axis2 (0.,1.,0.); + cgal_direction_t axis3 (0.,0.,1.); + if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); + if ( l->hasAxis3() ) IfcGeom::CgalKernel::convert(l->Axis3(),axis3); + const double scale1 = l->hasScale() ? l->Scale() : 1.0f; + const double scale2 = l->hasScale2() ? l->Scale2() : scale1; + const double scale3 = l->hasScale3() ? l->Scale3() : scale1; + + // TODO: Untested + gtrsf = Kernel::Aff_transformation_3(scale1*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0), + axis1.cartesian(1), scale2*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), + axis1.cartesian(2), axis2.cartesian(2), scale3*axis3.cartesian(2), origin.cartesian(2)); + + // for (int i = 0; i < 3; ++i) { + // for (int j = 0; j < 4; ++j) { + // std::cout << gtrsf.cartesian(i, j) << " "; + // } std::cout << std::endl; + // } + + // CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gtrsf) + return true; +} From 4061f93560ab90d93db17d5ec49c339490bb7277 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 20 Mar 2017 20:57:17 -0600 Subject: [PATCH 62/86] Export non-simple Nef too --- .../kernels/cgal/CgalConversionFunctions.cpp | 16 +++++++-- .../kernels/cgal/CgalConversionResult.cpp | 34 +++++++++++++++++-- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 818ee56f47..6d69e9c384 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -41,13 +41,23 @@ CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(std::l // fresult.close(); return CGAL::Nef_polyhedron_3(); } if (!polyhedron.is_closed()) { - std::cout << "create_nef_polyhedron: Polyhedron not closed" << std::endl; // std::ofstream fresult; // fresult.open("/Users/ken/Desktop/open.off"); // fresult << polyhedron << std::endl; // fresult.close(); - // TODO: Nef constructor doesn't support open meshes - return CGAL::Nef_polyhedron_3(polyhedron); + CGAL::Nef_polyhedron_3 mesh; + unsigned int current_face = 0; + for (auto &face: faces(polyhedron)) { + ++current_face; +// if (current_face%10 == 0) std::cout << current_face << "/" << polyhedron.size_of_facets() << std::endl; + std::list points_in_face; + CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin(); + do { + points_in_face.push_back(current_halfedge->vertex()->point()); + ++current_halfedge; + } while (current_halfedge != face->facet_begin()); + mesh += CGAL::Nef_polyhedron_3(points_in_face.begin(), points_in_face.end()); + } return mesh; } if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 171b7ee2e8..93abf453b4 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -4,11 +4,39 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { cgal_shape_t s = shape_; const cgal_placement_t& trsf = dynamic_cast(place)->trsf(); -// std::cout << "Model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; -// std::cout << "Valid: " << s.is_valid() << std::endl; + + std::cout << "Nef Model: " << s.number_of_facets() << " facets and " << s.number_of_vertices() << " vertices" << std::endl; + std::cout << "Simple: " << s.is_simple() << std::endl; CGAL::Polyhedron_3 polyhedron; - s.convert_to_polyhedron(polyhedron); + if (s.is_simple()) s.convert_to_polyhedron(polyhedron); + else { + std::list face_list; + face_list.push_back(cgal_face_t()); + std::set::Halffacet_const_handle> visited_halffacets; + for (CGAL::Nef_polyhedron_3::Halffacet_const_iterator current_halffacet = s.halffacets_begin(); + current_halffacet != s.halffacets_end(); + ++current_halffacet) { + if (visited_halffacets.count(current_halffacet->twin())) continue; + for (CGAL::Nef_polyhedron_3::Halffacet_cycle_const_iterator current_halffacet_cycle = current_halffacet->facet_cycles_begin(); + current_halffacet_cycle != current_halffacet->facet_cycles_end(); + ++current_halffacet_cycle) { + if (current_halffacet_cycle.is_shalfloop()) continue; + CGAL::Nef_polyhedron_3::SHalfedge_const_handle first_shalfedge = current_halffacet_cycle; + CGAL::Nef_polyhedron_3::SHalfedge_const_handle current_shalfedge = first_shalfedge; + if (!face_list.back().outer.empty()) face_list.push_back(cgal_face_t()); + do { + face_list.back().outer.push_back(current_shalfedge->source()->center_vertex()->point()); + current_shalfedge = current_shalfedge->next(); + } while (current_shalfedge != first_shalfedge); + } + } if (face_list.back().outer.empty()) face_list.pop_back(); + PolyhedronBuilder builder(&face_list); + polyhedron.delegate(builder); + } + + std::cout << "Polyhedron Model: " << polyhedron.size_of_facets() << " facets and " << polyhedron.size_of_vertices() << " vertices" << std::endl; + std::cout << "Valid: " << polyhedron.is_valid() << std::endl; // Apply transformation if (place != NULL) for (auto &vertex: vertices(polyhedron)) { From 12967790ba52ca4f0f0591b78c861fd73469d6f6 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 23 Mar 2017 19:49:15 -0600 Subject: [PATCH 63/86] Switched back to Polyhedron_3 for shapes. Should be checked. --- .../kernels/cgal/CgalConversionFunctions.cpp | 46 ++++++--------- .../kernels/cgal/CgalConversionResult.cpp | 41 ++----------- .../kernels/cgal/CgalIfcGeomPrimitives.cpp | 1 - .../kernels/cgal/CgalIfcGeomShapes.cpp | 58 +++++++++---------- .../cgal/CgalIfcGeomShapesWithStyles.cpp | 5 +- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 9 ++- src/ifcgeom/kernels/cgal/CgalKernel.h | 3 +- 7 files changed, 63 insertions(+), 100 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 6d69e9c384..6a7b805150 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -23,7 +23,7 @@ void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon } } -CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(std::list &face_list) { +CGAL::Polyhedron_3 IfcGeom::CgalKernel::create_polyhedron(std::list &face_list) { // Naive creation CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); @@ -34,35 +34,25 @@ CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(std::l // std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); if (!polyhedron.is_valid()) { - std::cout << "create_nef_polyhedron: Polyhedron not valid!" << std::endl; -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/invalid.off"); -// fresult << polyhedron << std::endl; -// fresult.close(); - return CGAL::Nef_polyhedron_3(); - } if (!polyhedron.is_closed()) { -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/open.off"); -// fresult << polyhedron << std::endl; -// fresult.close(); - CGAL::Nef_polyhedron_3 mesh; - unsigned int current_face = 0; - for (auto &face: faces(polyhedron)) { - ++current_face; -// if (current_face%10 == 0) std::cout << current_face << "/" << polyhedron.size_of_facets() << std::endl; - std::list points_in_face; - CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin(); - do { - points_in_face.push_back(current_halfedge->vertex()->point()); - ++current_halfedge; - } while (current_halfedge != face->facet_begin()); - mesh += CGAL::Nef_polyhedron_3(points_in_face.begin(), points_in_face.end()); - } return mesh; - } - if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { - CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); + std::cout << "create_polyhedron: Polyhedron not valid!" << std::endl; + // std::ofstream fresult; + // fresult.open("/Users/ken/Desktop/invalid.off"); + // fresult << polyhedron << std::endl; + // fresult.close(); + return CGAL::Polyhedron_3(); + } if (polyhedron.is_closed()) { + 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; + return polyhedron; +} + + +CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(std::list &face_list) { + CGAL::Polyhedron_3 polyhedron = create_polyhedron(face_list); return CGAL::Nef_polyhedron_3(polyhedron); } diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 93abf453b4..ba6e1fa5b2 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -5,41 +5,8 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, cgal_shape_t s = shape_; const cgal_placement_t& trsf = dynamic_cast(place)->trsf(); - std::cout << "Nef Model: " << s.number_of_facets() << " facets and " << s.number_of_vertices() << " vertices" << std::endl; - std::cout << "Simple: " << s.is_simple() << std::endl; - - CGAL::Polyhedron_3 polyhedron; - if (s.is_simple()) s.convert_to_polyhedron(polyhedron); - else { - std::list face_list; - face_list.push_back(cgal_face_t()); - std::set::Halffacet_const_handle> visited_halffacets; - for (CGAL::Nef_polyhedron_3::Halffacet_const_iterator current_halffacet = s.halffacets_begin(); - current_halffacet != s.halffacets_end(); - ++current_halffacet) { - if (visited_halffacets.count(current_halffacet->twin())) continue; - for (CGAL::Nef_polyhedron_3::Halffacet_cycle_const_iterator current_halffacet_cycle = current_halffacet->facet_cycles_begin(); - current_halffacet_cycle != current_halffacet->facet_cycles_end(); - ++current_halffacet_cycle) { - if (current_halffacet_cycle.is_shalfloop()) continue; - CGAL::Nef_polyhedron_3::SHalfedge_const_handle first_shalfedge = current_halffacet_cycle; - CGAL::Nef_polyhedron_3::SHalfedge_const_handle current_shalfedge = first_shalfedge; - if (!face_list.back().outer.empty()) face_list.push_back(cgal_face_t()); - do { - face_list.back().outer.push_back(current_shalfedge->source()->center_vertex()->point()); - current_shalfedge = current_shalfedge->next(); - } while (current_shalfedge != first_shalfedge); - } - } if (face_list.back().outer.empty()) face_list.pop_back(); - PolyhedronBuilder builder(&face_list); - polyhedron.delegate(builder); - } - - std::cout << "Polyhedron Model: " << polyhedron.size_of_facets() << " facets and " << polyhedron.size_of_vertices() << " vertices" << std::endl; - std::cout << "Valid: " << polyhedron.is_valid() << std::endl; - // Apply transformation - if (place != NULL) for (auto &vertex: vertices(polyhedron)) { + if (place != NULL) for (auto &vertex: vertices(s)) { vertex->point() = vertex->point().transform(trsf); } @@ -53,7 +20,7 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, boost::associative_property_map> vertex_normals_map(vertex_normals); std::map face_normals; boost::associative_property_map> face_normals_map(face_normals); - if (CGAL::Polygon_mesh_processing::triangulate_faces(polyhedron)) { + if (CGAL::Polygon_mesh_processing::triangulate_faces(s)) { // std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; } else { Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape"); @@ -65,9 +32,9 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, // fafter << s << std::endl; // fafter.close(); - CGAL::Polygon_mesh_processing::compute_normals(polyhedron, vertex_normals_map, face_normals_map); + CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); - for (auto &face: faces(polyhedron)) { + for (auto &face: faces(s)) { if (!face->is_triangle()) { std::cout << "Warning: non-triangular face!" << std::endl; continue; diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp index 2a878e40fe..446f877394 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp @@ -127,7 +127,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_ } bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_placement_t& trsf) { - // TODO: These macros don't work for the CGAL types. Need to check why. // IN_CACHE(IfcObjectPlacement,l,cgal_placement_t,trsf) if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) { Logger::Message(Logger::LOG_ERROR, "Unsupported IfcObjectPlacement:", l->entity); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 80a5da0066..a275b071bf 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -50,7 +50,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal top_face.outer.push_back(*vertex+height*dir); } face_list.push_back(top_face); - shape = create_nef_polyhedron(face_list); + CGAL::Nef_polyhedron_3 nef_shape = create_nef_polyhedron(face_list); // Inner // TODO: Would be faster to triangulate top/bottom face template rather than use Nef polyhedra for subtraction @@ -84,10 +84,11 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal hole_top_face.outer.push_back(*vertex+height*dir); } face_list.push_back(hole_top_face); - shape -= create_nef_polyhedron(face_list); + nef_shape -= create_nef_polyhedron(face_list); } - shape.transform(trsf); + nef_shape.transform(trsf); + nef_shape.convert_to_polyhedron(shape); return true; } @@ -116,7 +117,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ face_list.push_back(face); } - shape = create_nef_polyhedron(face_list); + shape = create_polyhedron(face_list); return true; } @@ -176,9 +177,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - shape = create_nef_polyhedron(face_list); - shape.transform(trsf); - + shape = create_polyhedron(face_list); + for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); return true; } @@ -233,8 +233,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha const IfcSchema::IfcBooleanOperator::IfcBooleanOperator op = l->Operator(); - if (!s1.is_simple()) { - Logger::Message(Logger::LOG_ERROR, "s1: Not simple Nef?", operand1->entity); + if (!s1.is_valid()) { + Logger::Message(Logger::LOG_ERROR, "s1: Not valid?", operand1->entity); return false; } else { // std::ofstream f1; @@ -247,8 +247,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha bool is_plane = false; cgal_plane_t plane; - if (!s2.is_simple()) { - Logger::Message(Logger::LOG_ERROR, "s2: Not simple Nef?", operand2->entity); + if (!s2.is_valid()) { + Logger::Message(Logger::LOG_ERROR, "s2: Not valid?", operand2->entity); return false; } else if (is_halfspace) { // std::cout << "s2: halfspace" << std::endl; @@ -285,11 +285,11 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { // std::cout << "Difference" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = s1; + CGAL::Nef_polyhedron_3 nef_result(s1); if (is_halfspace) { if (is_plane) nef_result = nef_result.intersection(plane, CGAL::Nef_polyhedron_3::Intersection_mode::CLOSED_HALFSPACE); } else { - nef_result -= s2; + nef_result -= CGAL::Nef_polyhedron_3(s2); } if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; @@ -301,13 +301,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - } shape = nef_result; + } nef_result.convert_to_polyhedron(shape); return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) { // std::cout << "Union" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = s1+s2; + CGAL::Nef_polyhedron_3 nef_result = CGAL::Nef_polyhedron_3(s1)+CGAL::Nef_polyhedron_3(s2); if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; @@ -318,13 +318,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - } shape = nef_result; + } nef_result.convert_to_polyhedron(shape); return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) { // std::cout << "Intersection" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = s1*s2; + CGAL::Nef_polyhedron_3 nef_result = CGAL::Nef_polyhedron_3(s1)*CGAL::Nef_polyhedron_3(s2); if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; @@ -335,7 +335,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - } shape = nef_result; + } nef_result.convert_to_polyhedron(shape); return true; } return false; } @@ -512,8 +512,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - shape = create_nef_polyhedron(face_list); - shape.transform(trsf); + shape = create_polyhedron(face_list); + for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); return true; } @@ -555,8 +555,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cga cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - shape = create_nef_polyhedron(face_list); - shape.transform(trsf); + shape = create_polyhedron(face_list); + for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); return true; } @@ -597,8 +597,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - shape = create_nef_polyhedron(face_list); - shape.transform(trsf); + shape = create_polyhedron(face_list); + for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); return true; } @@ -631,8 +631,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal cgal_placement_t trsf; IfcGeom::CgalKernel::convert(l->Position(),trsf); - shape = create_nef_polyhedron(face_list); - shape.transform(trsf); + shape = create_polyhedron(face_list); + for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); return true; } @@ -682,7 +682,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cg face_list.back().outer.push_back(c); } - shape = create_nef_polyhedron(face_list); + shape = create_polyhedron(face_list); return true; } #endif @@ -701,8 +701,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, cgal_sh // const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction()); // shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid(); - shape = CGAL::Nef_polyhedron_3(); - // TODO: We return an empty Nef polyhedron for now and handle halfspace differences in IfcBooleanResult. The other option would be to switch to an extended kernel. + shape = CGAL::Polyhedron_3(); + // TODO: We need to do something for now. Find a better solution later (abstract shape class?) // shape = CGAL::Nef_polyhedron_3(pln); return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp index 2bfd8caaac..a2a804f0aa 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp @@ -63,6 +63,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) { cgal_shape_t s; + CGAL::Nef_polyhedron_3 nef_s(s); const SurfaceStyle* collective_style = get_style(l); if (convert_shape(l->Outer(),s) ) { const SurfaceStyle* indiv_style = get_style(l->Outer()); @@ -79,14 +80,16 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, Conv for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) { cgal_shape_t s2; + CGAL::Nef_polyhedron_3 nef_s2(s2); // TODO: This looks weird. Aren't we removing the outer shell again and again? // Maybe it should be // if (convert_shape(*it, s2)) { if (convert_shape(l->Outer(), s2)) { - s -= s2; + nef_s -= nef_s2; } } + nef_s.convert_to_polyhedron(s); shape.push_back(ConversionResult(new CgalShape(s), indiv_style ? indiv_style : collective_style)); return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 10e616c318..2e69487603 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -250,7 +250,7 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, } gtrsf = gtrsf * opening_trsf; cgal_shape_t opening_shape(((CgalShape*)opening_shapes[i].Shape())->shape()); - opening_shape.transform(gtrsf); + for (auto &vertex: vertices(opening_shape)) vertex->point() = vertex->point().transform(gtrsf); opening_shapelist.push_back(opening_shape); // std::cout << "gtrsf" << std::endl; @@ -270,10 +270,11 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, cgal_shape_t entity_shape(entity_shape_unlocated); if (it3->Placement()) { const cgal_placement_t& entity_shape_gtrsf = *(CgalPlacement*)it3->Placement(); - entity_shape.transform(entity_shape_gtrsf); + for (auto &vertex: vertices(entity_shape)) vertex->point() = vertex->point().transform(entity_shape_gtrsf); } cgal_shape_t brep_cut_result(entity_shape); + CGAL::Nef_polyhedron_3 nef_brep_cut_result(brep_cut_result); for (auto &opening: opening_shapelist) { @@ -289,7 +290,8 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, // fresult << polyhedron << std::endl; // fresult.close(); - brep_cut_result -= opening; + CGAL::Nef_polyhedron_3 nef_opening(opening); + nef_brep_cut_result -= nef_opening; // brep_cut_result.convert_to_polyhedron(polyhedron); // fresult.open("/Users/ken/Desktop/after.off"); @@ -298,6 +300,7 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, } if (brep_cut_result.is_valid()) { + nef_brep_cut_result.convert_to_Polyhedron(brep_cut_result); cut_shapes.push_back(IfcGeom::ConversionResult(new CgalShape(brep_cut_result), &it3->Style())); } else { // Apparently processing the boolean operation failed or resulted in an invalid result diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 71071f5d92..baaf48914c 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -64,7 +64,7 @@ struct cgal_face_t { std::vector inner; }; -typedef CGAL::Nef_polyhedron_3 cgal_shape_t; +typedef CGAL::Polyhedron_3 cgal_shape_t; typedef boost::graph_traits>::vertex_descriptor cgal_vertex_descriptor_t; typedef boost::graph_traits>::face_descriptor cgal_face_descriptor_t; @@ -140,6 +140,7 @@ namespace IfcGeom { bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const cgal_placement_t& entity_trsf, ConversionResults& cut_shapes); + CGAL::Polyhedron_3 create_polyhedron(std::list &face_list); CGAL::Nef_polyhedron_3 create_nef_polyhedron(std::list &face_list); void purge_cache() { From dd206a2a52ae2a86a05c2936f849f6b2d4fdea26 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 23 Mar 2017 20:20:43 -0600 Subject: [PATCH 64/86] A few more simple IFC classes to fill in things --- .../kernels/cgal/CgalConversionFunctions.cpp | 2 +- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 63 ++++++++++++++----- src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 15 +++++ .../kernels/cgal/CgalIfcGeomPrimitives.cpp | 16 +++++ .../kernels/cgal/CgalIfcGeomShapes.cpp | 10 ++- src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 28 +++++++++ 6 files changed, 114 insertions(+), 20 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 6a7b805150..8b465db32a 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -26,7 +26,7 @@ void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon CGAL::Polyhedron_3 IfcGeom::CgalKernel::create_polyhedron(std::list &face_list) { // Naive creation - CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron; PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index e438b3ace1..37967d966b 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -39,55 +39,84 @@ SHAPES(IfcMappedItem); SHAPES(IfcManifoldSolidBrep); SHAPES(IfcGeometricSet); +#ifdef USE_IFC4 +//SHAPE(IfcCylindricalSurface); +//SHAPE(IfcAdvancedBrep); +//SHAPE(IfcBSplineSurfaceWithKnots); +SHAPE(IfcTriangulatedFaceSet); +//SHAPE(IfcExtrudedAreaSolidTapered); +#endif +//SHAPE(IfcPlane); SHAPE(IfcExtrudedAreaSolid); +//SHAPE(IfcRevolvedAreaSolid); SHAPE(IfcConnectedFaceSet); -SHAPE(IfcCsgSolid); -SHAPE(IfcBlock); SHAPE(IfcBooleanResult); -SHAPE(IfcSphere); +//SHAPE(IfcPolygonalBoundedHalfSpace); +SHAPE(IfcHalfSpaceSolid); +//SHAPE(IfcSurfaceOfLinearExtrusion); +//SHAPE(IfcSurfaceOfRevolution); +SHAPE(IfcBlock); SHAPE(IfcRectangularPyramid); SHAPE(IfcRightCircularCylinder); SHAPE(IfcRightCircularCone); -#ifdef USE_IFC4 -SHAPE(IfcTriangulatedFaceSet); -#endif -SHAPE(IfcHalfSpaceSolid); +SHAPE(IfcSphere); +SHAPE(IfcCsgSolid); +//SHAPE(IfcCurveBoundedPlane); +//SHAPE(IfcRectangularTrimmedSurface); +//SHAPE(IfcSurfaceCurveSweptAreaSolid); +//SHAPE(IfcSweptDiskSolid); +FACE(IfcArbitraryProfileDefWithVoids); FACE(IfcArbitraryClosedProfileDef); -FACE(IfcCircleHollowProfileDef); -FACE(IfcCircleProfileDef); -FACE(IfcFace); FACE(IfcRoundedRectangleProfileDef); FACE(IfcRectangleHollowProfileDef); FACE(IfcRectangleProfileDef); -FACE(IfcTrapeziumProfileDef); -FACE(IfcEllipseProfileDef); +FACE(IfcTrapeziumProfileDef) FACE(IfcCShapeProfileDef); +// IfcAsymmetricIShapeProfileDef included FACE(IfcIShapeProfileDef); FACE(IfcLShapeProfileDef); FACE(IfcTShapeProfileDef); FACE(IfcUShapeProfileDef); FACE(IfcZShapeProfileDef); +FACE(IfcCircleHollowProfileDef); +FACE(IfcCircleProfileDef); +FACE(IfcEllipseProfileDef); +//FACE(IfcCenterLineProfileDef); +//FACE(IfcCompositeProfileDef); +//FACE(IfcDerivedProfileDef); +// IfcFaceSurface included +// IfcAdvancedFace included in case of IFC4 +FACE(IfcFace); -WIRE(IfcEdgeLoop); +//WIRE(IfcEdgeCurve); +//WIRE(IfcSubedge); WIRE(IfcOrientedEdge); -WIRE(IfcPolyLoop); +WIRE(IfcEdge); +WIRE(IfcEdgeLoop); WIRE(IfcPolyline); +WIRE(IfcPolyLoop); WIRE(IfcCompositeCurve); WIRE(IfcTrimmedCurve); +//WIRE(IfcArbitraryOpenProfileDef); CURVE(IfcCircle); CURVE(IfcEllipse); CURVE(IfcLine); +#ifdef USE_IFC4 +// IfcRationalBSplineCurveWithKnots included +//CURVE(IfcBSplineCurveWithKnots); +#endif CLASS(IfcCartesianPoint,cgal_point_t); CLASS(IfcDirection,cgal_direction_t); -CLASS(IfcVector,cgal_vector_t); -CLASS(IfcPlane,cgal_plane_t); CLASS(IfcAxis2Placement2D,cgal_placement_t); CLASS(IfcAxis2Placement3D,cgal_placement_t); -CLASS(IfcObjectPlacement,cgal_placement_t); +CLASS(IfcAxis1Placement,cgal_placement_t); CLASS(IfcCartesianTransformationOperator2DnonUniform,cgal_placement_t); CLASS(IfcCartesianTransformationOperator3DnonUniform,cgal_placement_t); CLASS(IfcCartesianTransformationOperator2D,cgal_placement_t); CLASS(IfcCartesianTransformationOperator3D,cgal_placement_t); +CLASS(IfcObjectPlacement,cgal_placement_t); +CLASS(IfcVector,cgal_vector_t); +CLASS(IfcPlane,cgal_plane_t); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 0040b65cc3..09729e2467 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -10,6 +10,21 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* return success; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids* l, cgal_face_t& face) { + cgal_wire_t profile; + if ( ! convert_wire(l->OuterCurve(),profile) ) return false; + cgal_face_t mf; + mf.outer = profile; + IfcSchema::IfcCurve::list::ptr voids = l->InnerCurves(); + for( IfcSchema::IfcCurve::list::it it = voids->begin(); it != voids->end(); ++ it ) { + cgal_wire_t hole; + if ( convert_wire(*it,hole) ) { + mf.inner.push_back(hole); + } + } face = mf; + 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); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp index 446f877394..d4cda51f6c 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp @@ -126,6 +126,22 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_ return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis1Placement* l, cgal_placement_t& ax) { +// IN_CACHE(IfcAxis1Placement,l,gp_Ax1,ax) + cgal_point_t o; + cgal_direction_t axis = Kernel::Vector_3(0,0,1); + IfcGeom::CgalKernel::convert(l->Location(),o); + if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(), axis); + + // TODO: Should be checked. + ax = Kernel::Aff_transformation_3(1.0, 0.0, axis.cartesian(0), o.cartesian(0), + 0.0, 1.0, axis.cartesian(1), o.cartesian(1), + 0.0, 0.0, axis.cartesian(2), o.cartesian(2)); + +// CACHE(IfcAxis1Placement,l,ax) + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_placement_t& trsf) { // IN_CACHE(IfcObjectPlacement,l,cgal_placement_t,trsf) if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) { diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index a275b071bf..c29b9ad36f 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -50,6 +50,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal top_face.outer.push_back(*vertex+height*dir); } face_list.push_back(top_face); + if (bottom_face.inner.empty()) { + shape = create_polyhedron(face_list); + for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); + return true; + } + CGAL::Nef_polyhedron_3 nef_shape = create_nef_polyhedron(face_list); // Inner @@ -701,8 +707,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcHalfSpaceSolid* l, cgal_sh // const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction()); // shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid(); + // TODO: For now we do nothing and process halfspaces in IfcBooleanResult, which likely doesn't capture all cases. + // Find a better solution later (with an abstract shape class?) shape = CGAL::Polyhedron_3(); - // TODO: We need to do something for now. Find a better solution later (abstract shape class?) -// shape = CGAL::Nef_polyhedron_3(pln); return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index 674ba921d6..ee874bc140 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -86,6 +86,34 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcOrientedEdge* l, cgal_wire } } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEdge* l, cgal_wire_t& result) { + if (!l->EdgeStart()->is(IfcSchema::Type::IfcVertexPoint) || !l->EdgeEnd()->is(IfcSchema::Type::IfcVertexPoint)) { + Logger::Message(Logger::LOG_ERROR, "Only IfcVertexPoints are supported for EdgeStart and -End", l->entity); + return false; + } + + IfcSchema::IfcPoint* pnt1 = ((IfcSchema::IfcVertexPoint*) l->EdgeStart())->VertexGeometry(); + IfcSchema::IfcPoint* pnt2 = ((IfcSchema::IfcVertexPoint*) l->EdgeEnd())->VertexGeometry(); + if (!pnt1->is(IfcSchema::Type::IfcCartesianPoint) || !pnt2->is(IfcSchema::Type::IfcCartesianPoint)) { + Logger::Message(Logger::LOG_ERROR, "Only IfcCartesianPoints are supported for VertexGeometry", l->entity); + return false; + } + + cgal_point_t p1, p2; + if (!convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) || + !convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2)) + { + return false; + } + + cgal_wire_t mw; + mw.push_back(p1); + mw.push_back(p2); + + result = mw; + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCompositeCurve* l, cgal_wire_t& wire) { if ( getValue(GV_PLANEANGLE_UNIT)<0 ) { Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity); From f8f4db72ec9f8d017635711acae4f22db47f96ba Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 23 Mar 2017 20:25:54 -0600 Subject: [PATCH 65/86] IfcDerivedProfileDef --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 +- src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 37967d966b..3dc4b9c95e 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -84,7 +84,7 @@ FACE(IfcCircleProfileDef); FACE(IfcEllipseProfileDef); //FACE(IfcCenterLineProfileDef); //FACE(IfcCompositeProfileDef); -//FACE(IfcDerivedProfileDef); +FACE(IfcDerivedProfileDef); // IfcFaceSurface included // IfcAdvancedFace included in case of IFC4 FACE(IfcFace); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 09729e2467..e1a4383dc4 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -971,3 +971,18 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcZShapeProfileDef* l, cgal_ return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcDerivedProfileDef* l, cgal_face_t& face) { + cgal_face_t f; + cgal_placement_t trsf2d; + if (convert_face(l->ParentProfile(), f) && IfcGeom::CgalKernel::convert(l->Operator(), trsf2d)) { + cgal_placement_t trsf = trsf2d; + for (auto &vertex: f.outer) vertex = vertex.transform(trsf); + for (auto &ring: f.inner) { + for (auto &vertex: ring) vertex = vertex.transform(trsf); + } face = f; + return true; + } else { + return false; + } +} From 583c3348027788ddd83362ca90c5eb9e02c6fbdd Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 23 Mar 2017 20:31:41 -0600 Subject: [PATCH 66/86] Removed sphere radius at some point --- src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index c29b9ad36f..4ad278c939 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -519,7 +519,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s IfcGeom::CgalKernel::convert(l->Position(),trsf); shape = create_polyhedron(face_list); - for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); + for (auto &vertex: vertices(shape)) { + vertex->point() = Kernel::Point_3(r*vertex->point().x(), + r*vertex->point().y(), + r*vertex->point().z()); + vertex->point() = vertex->point().transform(trsf); + } return true; } From ed9676ed38e3cd008d6c1e503bf556a53ded4e8c Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 30 Mar 2017 19:04:39 -0600 Subject: [PATCH 67/86] Squashed some bugs --- .../kernels/cgal/CgalConversionFunctions.cpp | 20 ++++++++++++++ .../kernels/cgal/CgalIfcGeomPrimitives.cpp | 27 ++++++++++++++++--- .../cgal/CgalIfcGeomShapesWithStyles.cpp | 7 +++-- src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 6 ++--- src/ifcgeom/kernels/cgal/CgalKernel.h | 4 ++- 5 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 8b465db32a..b34ca73bc8 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -51,8 +51,28 @@ CGAL::Polyhedron_3 IfcGeom::CgalKernel::create_polyhedron(std::list IfcGeom::CgalKernel::create_polyhedron(CGAL::Nef_polyhedron_3 &nef_polyhedron) { + if (nef_polyhedron.is_simple()) { + CGAL::Polyhedron_3 polyhedron; + nef_polyhedron.convert_to_polyhedron(polyhedron); + return polyhedron; + } else { + std::cout << "Nef polyhedron not simple: cannot create polyhedron!" << std::endl; + return CGAL::Polyhedron_3(); + } +} CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(std::list &face_list) { CGAL::Polyhedron_3 polyhedron = create_polyhedron(face_list); return CGAL::Nef_polyhedron_3(polyhedron); } + +CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(CGAL::Polyhedron_3 &polyhedron) { + if (polyhedron.is_valid()) { + CGAL::Polygon_mesh_processing::triangulate_faces(polyhedron); + return CGAL::Nef_polyhedron_3(polyhedron); + } else { + std::cout << "Polyhedron not valid: cannot create Nef polyhedron!" << std::endl; + return CGAL::Nef_polyhedron_3(); + } +} diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp index d4cda51f6c..62c155b5ba 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp @@ -86,6 +86,14 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement2D* l, cgal_ if ( hasRef ) IfcGeom::CgalKernel::convert(l->RefDirection(),refDirection); cgal_direction_t y = Kernel::Vector_3(-refDirection.y(), refDirection.x(), 0.0); + const double tolerance = 0.01; + if (refDirection.squared_length() < 1.0-tolerance || refDirection.squared_length() > 1.0+tolerance || + y.squared_length() < 1.0-tolerance || y.squared_length() > 1.0+tolerance) { + std::cout << "Ref direction (x): " << refDirection << " squared length: " << refDirection.squared_length() << std::endl; + std::cout << "y: " << y << " squared length: " << y.squared_length() << std::endl; + std::cout << "Origin: " << o << std::endl; + } + // TODO: Should be checked. trsf = Kernel::Aff_transformation_3(refDirection.cartesian(0), y.cartesian(0), 0.0, o.cartesian(0), refDirection.cartesian(1), y.cartesian(1), 0.0, o.cartesian(1), @@ -107,9 +115,16 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis2Placement3D* l, cgal_ Kernel::Vector_3 y = CGAL::cross_product(axis, refDirection); Kernel::Vector_3 x = CGAL::cross_product(y, axis); - // std::cout << "Ref direction: " << refDirection << std::endl; - // std::cout << "Axis: " << axis << std::endl; - // std::cout << "Origin: " << o << std::endl; + const double tolerance = 0.01; + if (x.squared_length() < 1.0-tolerance || x.squared_length() > 1.0+tolerance || + y.squared_length() < 1.0-tolerance || y.squared_length() > 1.0+tolerance || + axis.squared_length() < 1.0-tolerance || axis.squared_length() > 1.0+tolerance) { + std::cout << "Ref direction: " << refDirection << " squared length: " << refDirection.squared_length() << std::endl; + std::cout << "Axis (z): " << axis << " squared length: " << axis.squared_length() << std::endl; + std::cout << "y: " << y << " squared length: " << y.squared_length() << std::endl; + std::cout << "x: " << x << " squared length: " << x.squared_length() << std::endl; + std::cout << "Origin: " << o << std::endl; + } // TODO: Should be checked. trsf = Kernel::Aff_transformation_3(x.cartesian(0), y.cartesian(0), axis.cartesian(0), o.cartesian(0), @@ -133,6 +148,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcAxis1Placement* l, cgal_pl IfcGeom::CgalKernel::convert(l->Location(),o); if ( l->hasAxis() ) IfcGeom::CgalKernel::convert(l->Axis(), axis); + const double tolerance = 0.01; + if (axis.squared_length() < 1.0-tolerance || axis.squared_length() > 1.0+tolerance) { + std::cout << "Axis (z): " << axis << " squared length: " << axis.squared_length() << std::endl; + std::cout << "Origin: " << o << std::endl; + } + // TODO: Should be checked. ax = Kernel::Aff_transformation_3(1.0, 0.0, axis.cartesian(0), o.cartesian(0), 0.0, 1.0, axis.cartesian(1), o.cartesian(1), diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp index a2a804f0aa..c28d6ee8e2 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapesWithStyles.cpp @@ -63,9 +63,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, ConversionResults& shape) { cgal_shape_t s; - CGAL::Nef_polyhedron_3 nef_s(s); const SurfaceStyle* collective_style = get_style(l); if (convert_shape(l->Outer(),s) ) { + CGAL::Nef_polyhedron_3 nef_s = create_nef_polyhedron(s); const SurfaceStyle* indiv_style = get_style(l->Outer()); IfcSchema::IfcClosedShell::list::ptr voids(new IfcSchema::IfcClosedShell::list); @@ -80,16 +80,15 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcManifoldSolidBrep* l, Conv for (IfcSchema::IfcClosedShell::list::it it = voids->begin(); it != voids->end(); ++it) { cgal_shape_t s2; - CGAL::Nef_polyhedron_3 nef_s2(s2); // TODO: This looks weird. Aren't we removing the outer shell again and again? // Maybe it should be // if (convert_shape(*it, s2)) { if (convert_shape(l->Outer(), s2)) { - nef_s -= nef_s2; + nef_s -= CGAL::Nef_polyhedron_3(s2); } } - nef_s.convert_to_polyhedron(s); + s = create_polyhedron(nef_s); shape.push_back(ConversionResult(new CgalShape(s), indiv_style ? indiv_style : collective_style)); return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index ee874bc140..c845cba55a 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -19,7 +19,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& } // Remove points that are too close to one another - remove_duplicate_points_from_loop(polygon, true); + remove_duplicate_points_from_loop(polygon); std::size_t count = polygon.size(); if (original_count - count != 0) { @@ -54,7 +54,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyline* l, cgal_wire_t& } // Remove points that are too close to one another - remove_duplicate_points_from_loop(polygon, false); + remove_duplicate_points_from_loop(polygon); result = polygon; return true; @@ -198,7 +198,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCompositeCurve* l, cgal_wi } } - remove_duplicate_points_from_loop(w, false); + remove_duplicate_points_from_loop(w); wire = w; return true; diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index baaf48914c..266b7a8294 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -136,12 +136,14 @@ namespace IfcGeom { bool convert_wire_to_face(const cgal_wire_t& wire, cgal_face_t& face); - void remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol = -1.); + void remove_duplicate_points_from_loop(cgal_wire_t& polygon); bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const cgal_placement_t& entity_trsf, ConversionResults& cut_shapes); CGAL::Polyhedron_3 create_polyhedron(std::list &face_list); + CGAL::Polyhedron_3 create_polyhedron(CGAL::Nef_polyhedron_3 &nef_polyhedron); CGAL::Nef_polyhedron_3 create_nef_polyhedron(std::list &face_list); + CGAL::Nef_polyhedron_3 create_nef_polyhedron(CGAL::Polyhedron_3 &polyhedron); void purge_cache() { // Rather hack-ish, but a stopgap solution to keep memory under control From 71ad7dd4bc6feb2db3a550cd7ba17c1302c73d5e Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 30 Mar 2017 19:06:47 -0600 Subject: [PATCH 68/86] Forgot one line --- src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index b34ca73bc8..2b5110f859 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -5,7 +5,7 @@ bool IfcGeom::CgalKernel::convert_wire_to_face(const cgal_wire_t& wire, cgal_fac return true; } -void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol) { +void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon) { if (tol <= 0.) tol = getValue(GV_PRECISION); tol *= tol; From c1887f3f1fbe7c7227e2f2eaa75ff32bedb57f00 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 30 Mar 2017 19:16:11 -0600 Subject: [PATCH 69/86] And the rest --- .../kernels/cgal/CgalConversionFunctions.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 2b5110f859..69003d9aa1 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -6,20 +6,12 @@ bool IfcGeom::CgalKernel::convert_wire_to_face(const cgal_wire_t& wire, cgal_fac } void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon) { - if (tol <= 0.) tol = getValue(GV_PRECISION); - tol *= tol; - + std::set points; for (int i = 0; i < polygon.size(); ++i) { - for (int j = i+1; j < polygon.size(); ++j) { - if (CGAL::squared_distance(polygon[i], polygon[j]) < tol) { - polygon.erase(polygon.begin()+j); - --j; - } - } if (closed) { - if (CGAL::squared_distance(polygon.front(), polygon.back()) < tol) { - polygon.erase(polygon.begin()+polygon.size()-1); - } - } + if (points.count(polygon[i])) { + polygon.erase(polygon.begin()+i); + --i; + } else points.insert(polygon[i]); } } From 4a340027bf475dc7c81aae10b2da5fa6f8ea2aad Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 30 Mar 2017 20:12:23 -0600 Subject: [PATCH 70/86] IfcExtrudedAreaSolidTapered (with problems?) --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 +- .../kernels/cgal/CgalIfcGeomShapes.cpp | 127 +++++++++++++++++- 2 files changed, 126 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 3dc4b9c95e..22f52e6f2d 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -44,7 +44,7 @@ SHAPES(IfcGeometricSet); //SHAPE(IfcAdvancedBrep); //SHAPE(IfcBSplineSurfaceWithKnots); SHAPE(IfcTriangulatedFaceSet); -//SHAPE(IfcExtrudedAreaSolidTapered); +SHAPE(IfcExtrudedAreaSolidTapered); #endif //SHAPE(IfcPlane); SHAPE(IfcExtrudedAreaSolid); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 4ad278c939..227d45825c 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -52,7 +52,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal if (bottom_face.inner.empty()) { shape = create_polyhedron(face_list); - for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); + if (has_position) for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); return true; } @@ -66,6 +66,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal cgal_face_t hole_bottom_face; hole_bottom_face.outer = inner; + remove_duplicate_points_from_loop(hole_bottom_face.outer); face_list.push_back(hole_bottom_face); for (std::vector::const_iterator current_vertex = inner.begin(); @@ -93,11 +94,133 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal nef_shape -= create_nef_polyhedron(face_list); } - nef_shape.transform(trsf); + if (has_position) { + // IfcSweptAreaSolid.Position (trsf) is an IfcAxis2Placement3D + // and therefore has a unit scale factor + nef_shape.transform(trsf); + } + nef_shape.convert_to_polyhedron(shape); return true; } +#ifdef USE_IFC4 +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* 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 face1, face2; + if (!convert_face(l->SweptArea(), face1)) return false; + if (!convert_face(l->EndSweptArea(), face2)) 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); + + for (auto &vertex: face2.outer) vertex = vertex + height*dir; + for (auto &ring: face2.inner) { + for (auto &vertex: ring) vertex = vertex + height*dir; + } + + // Outer + std::list face_list; + face_list.push_back(face1); + face_list.push_back(face2); + + std::vector::const_iterator current_face1_vertex = face1.outer.begin(); + std::vector::const_iterator current_face2_vertex = face2.outer.begin(); + while (current_face1_vertex != face1.outer.end() && + current_face2_vertex != face2.outer.end()) { + std::vector::const_iterator next_face1_vertex = current_face1_vertex; + std::vector::const_iterator next_face2_vertex = current_face2_vertex; + ++next_face1_vertex; + ++next_face2_vertex; + if (next_face1_vertex == face1.outer.end()) next_face1_vertex = face1.outer.begin(); + if (next_face2_vertex == face2.outer.end()) next_face2_vertex = face2.outer.begin(); + cgal_face_t side_face; + side_face.outer.push_back(*next_face1_vertex); + side_face.outer.push_back(*current_face1_vertex); + side_face.outer.push_back(*current_face2_vertex); + side_face.outer.push_back(*next_face2_vertex); + face_list.push_back(side_face); + ++current_face1_vertex; + ++current_face2_vertex; + } + + if (face1.inner.empty() || face2.inner.empty()) { + shape = create_polyhedron(face_list); + if (has_position) for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); + return true; + } + + CGAL::Nef_polyhedron_3 nef_shape = create_nef_polyhedron(face_list); + + // Inner + // TODO: Would be faster to triangulate top/bottom face template rather than use Nef polyhedra for subtraction + std::vector::iterator inner_face1 = face1.inner.begin(); + std::vector::iterator inner_face2 = face2.inner.begin(); + while (inner_face1 != face1.inner.end() && + inner_face2 != face2.inner.end()) { + face_list.clear(); + + cgal_face_t hole_face1; + hole_face1.outer = *inner_face1; + remove_duplicate_points_from_loop(hole_face1.outer); + face_list.push_back(hole_face1); + + cgal_face_t hole_face2; + hole_face2.outer = *inner_face2; + remove_duplicate_points_from_loop(hole_face2.outer); + face_list.push_back(hole_face2); + + current_face1_vertex = hole_face1.outer.begin(); + current_face2_vertex = hole_face2.outer.begin(); + while (current_face1_vertex != hole_face1.outer.end() && + current_face2_vertex != hole_face2.outer.end()) { + std::vector::const_iterator next_face1_vertex = current_face1_vertex; + std::vector::const_iterator next_face2_vertex = current_face2_vertex; + ++next_face1_vertex; + ++next_face2_vertex; + if (next_face1_vertex == hole_face1.outer.end()) next_face1_vertex = hole_face1.outer.begin(); + if (next_face2_vertex == hole_face2.outer.end()) next_face2_vertex = hole_face2.outer.begin(); + cgal_face_t side_face; + side_face.outer.push_back(*next_face1_vertex); + side_face.outer.push_back(*current_face1_vertex); + side_face.outer.push_back(*current_face2_vertex); + side_face.outer.push_back(*next_face2_vertex); + face_list.push_back(side_face); + ++current_face1_vertex; + ++current_face2_vertex; + } + + nef_shape -= create_nef_polyhedron(face_list); + + ++inner_face1; + ++inner_face2; + } + + if (has_position) { + // IfcSweptAreaSolid.Position (trsf) is an IfcAxis2Placement3D + // and therefore has a unit scale factor + nef_shape.transform(trsf); + } + + nef_shape.convert_to_polyhedron(shape); + return true; +} +#endif + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_shape_t& shape) { IfcSchema::IfcFace::list::ptr faces = l->CfsFaces(); From c9267d7ace8584bca4997ad2bb1db8d38413d6cf Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 30 Mar 2017 21:11:05 -0600 Subject: [PATCH 71/86] Fixed orientation bug in tapered extrusions --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 227d45825c..e3264e78ec 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -136,7 +136,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* // Outer std::list face_list; face_list.push_back(face1); - face_list.push_back(face2); std::vector::const_iterator current_face1_vertex = face1.outer.begin(); std::vector::const_iterator current_face2_vertex = face2.outer.begin(); @@ -158,12 +157,27 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* ++current_face2_vertex; } + cgal_face_t top_face; + for (std::vector::const_reverse_iterator vertex = face2.outer.rbegin(); + vertex != face2.outer.rend(); + ++vertex) { + top_face.outer.push_back(*vertex); + } face_list.push_back(top_face); + if (face1.inner.empty() || face2.inner.empty()) { shape = create_polyhedron(face_list); if (has_position) for (auto &vertex: vertices(shape)) vertex->point() = vertex->point().transform(trsf); return true; } +// std::ofstream f1; +// CGAL::Polyhedron_3 outer_polyhedron; +// PolyhedronBuilder builder(&face_list); +// outer_polyhedron.delegate(builder); +// f1.open("/Users/ken/Desktop/outer.off"); +// f1 << outer_polyhedron << std::endl; +// f1.close(); + CGAL::Nef_polyhedron_3 nef_shape = create_nef_polyhedron(face_list); // Inner @@ -182,7 +196,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* cgal_face_t hole_face2; hole_face2.outer = *inner_face2; remove_duplicate_points_from_loop(hole_face2.outer); - face_list.push_back(hole_face2); current_face1_vertex = hole_face1.outer.begin(); current_face2_vertex = hole_face2.outer.begin(); @@ -204,6 +217,21 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* ++current_face2_vertex; } + cgal_face_t top_hole_face; + for (std::vector::const_reverse_iterator vertex = hole_face2.outer.rbegin(); + vertex != hole_face2.outer.rend(); + ++vertex) { + top_hole_face.outer.push_back(*vertex); + } face_list.push_back(top_hole_face); + +// std::ofstream f2; +// CGAL::Polyhedron_3 inner_polyhedron; +// PolyhedronBuilder builder(&face_list); +// inner_polyhedron.delegate(builder); +// f2.open("/Users/ken/Desktop/inner.off"); +// f2 << inner_polyhedron << std::endl; +// f2.close(); + nef_shape -= create_nef_polyhedron(face_list); ++inner_face1; From 009f50abe1b3e6705316bfe5cdc451326773226f Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 5 Apr 2017 15:57:21 +0200 Subject: [PATCH 72/86] Fix compilation on MSVC --- src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index c845cba55a..08a947efd6 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -1,3 +1,7 @@ +// For MSVC to have M_PI +#define _USE_MATH_DEFINES +#include + #include "CgalKernel.h" bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& result) { From 91e5b337d371c2f1bbf31f7ce5907b6b5f4c4b5b Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 5 Apr 2017 16:06:07 +0200 Subject: [PATCH 73/86] Reverse matrix multiplication order --- src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp | 2 +- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp index 62c155b5ba..34f5b6c10c 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp @@ -192,7 +192,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcObjectPlacement* l, cgal_p // } std::cout << std::endl; // } - trsf = trsf * trsf2; // TODO: I think it's fine, but maybe should it be the other way around? + trsf = trsf2 * trsf; // std::cout << "trsf (after multiplication)" << std::endl; // for (int i = 0; i < 3; ++i) { diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 2e69487603..9c9512ceac 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -225,7 +225,7 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, // } // Move the opening into the coordinate system of the IfcProduct - opening_trsf = opening_trsf * entity_trsf.inverse(); + opening_trsf = entity_trsf.inverse() * opening_trsf; // std::cout << "opening_trsf after" << std::endl; // for (int i = 0; i < 3; ++i) { @@ -248,7 +248,7 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, if (opening_shapes[i].Placement()) { gtrsf = *(CgalPlacement*)opening_shapes[i].Placement(); } - gtrsf = gtrsf * opening_trsf; + gtrsf = opening_trsf * gtrsf; cgal_shape_t opening_shape(((CgalShape*)opening_shapes[i].Shape())->shape()); for (auto &vertex: vertices(opening_shape)) vertex->point() = vertex->point().transform(gtrsf); opening_shapelist.push_back(opening_shape); From 7189219aa4692316e921bc5ae707673b167beeac Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 6 Apr 2017 14:44:57 +0200 Subject: [PATCH 74/86] Attempt to fix travis build w/ CGAL --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7fe6cc4b3c..fc3360ddf8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,8 @@ install: - sudo apt-get install -y liboce-ocaf-lite-dev - sudo apt-get install -y libpcre3-dev + + - sudo apt-get install -y libcgal-dev libmpfr-dev libgmp-dev script: - pwd @@ -51,8 +53,8 @@ script: - cd cmake - mkdir build-ifc2x3 build-ifc4 - cd build-ifc2x3 - - cmake -DCOLLADA_SUPPORT=True -DOPENCOLLADA_INCLUDE_DIR=/usr/local/include/opencollada -DOPENCOLLADA_LIBRARY_DIR=/usr/local/lib/opencollada -DPCRE_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu -DUSE_IFC4=False -DBUILD_IFCPYTHON=True -DUNICODE_SUPPORT=True -DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu .. + - cmake -DCOLLADA_SUPPORT=True -DOPENCOLLADA_INCLUDE_DIR=/usr/local/include/opencollada -DOPENCOLLADA_LIBRARY_DIR=/usr/local/lib/opencollada -DPCRE_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu -DUSE_IFC4=False -DBUILD_IFCPYTHON=True -DUNICODE_SUPPORT=True -DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu -DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu/ -DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu/ .. - make -j IfcConvert - cd ../build-ifc4 - - cmake -DCOLLADA_SUPPORT=True -DOPENCOLLADA_INCLUDE_DIR=/usr/local/include/opencollada -DOPENCOLLADA_LIBRARY_DIR=/usr/local/lib/opencollada -DPCRE_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu -DUSE_IFC4=True -DBUILD_IFCPYTHON=True -DUNICODE_SUPPORT=True -DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu .. + - cmake -DCOLLADA_SUPPORT=True -DOPENCOLLADA_INCLUDE_DIR=/usr/local/include/opencollada -DOPENCOLLADA_LIBRARY_DIR=/usr/local/lib/opencollada -DPCRE_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu -DUSE_IFC4=True -DBUILD_IFCPYTHON=True -DUNICODE_SUPPORT=True -DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu -DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu/ -DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu/ .. - make -j IfcConvert From 7b7f9b4852e713bde06ff27d3f8ae96f4650cfe3 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 6 Apr 2017 14:57:10 +0200 Subject: [PATCH 75/86] Attempt to fix travis build w/ CGAL --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index fc3360ddf8..a289378efa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,11 +15,11 @@ install: - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 90 - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90 - - sudo apt-get install -y libboost1.55-dev - - sudo apt-get install -y libboost-regex1.55-dev - - sudo apt-get install -y libboost-system1.55-dev - - sudo apt-get install -y libboost-thread1.55-dev - - sudo apt-get install -y libboost-program-options1.55-dev + - sudo apt-get install -y libboost-dev + - sudo apt-get install -y libboost-regex-dev + - sudo apt-get install -y libboost-system-dev + - sudo apt-get install -y libboost-thread-dev + - sudo apt-get install -y libboost-program-options-dev - sudo apt-get install -y cmake - sudo apt-get install -y libicu-dev - sudo apt-get install -y python-all-dev From 8d9acfa677564f750558c135d711dc4e671d1e28 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 6 Apr 2017 15:23:45 +0200 Subject: [PATCH 76/86] Attempt to fix travis build w/ CGAL --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a289378efa..51aa99a546 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: cpp compiler: gcc os: linux -dist: trusty +dist: xenial sudo: required From 248c73c2ab945b06924bf9fddc7e0c44faa1e82e Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 10 Apr 2017 18:53:28 -0500 Subject: [PATCH 77/86] Catch failures to convert Nef to Polyhedron_3 --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 46 +++++++++++++++---- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 12 ++++- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index e3264e78ec..7b64a21321 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -100,8 +100,14 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal nef_shape.transform(trsf); } - nef_shape.convert_to_polyhedron(shape); - return true; + try { + nef_shape.convert_to_polyhedron(shape); + return true; + } catch (...) { + std::cout << "IfcExtrudedAreaSolid: cannot convert Nef to polyhedron!" << std::endl; + return false; + } + } #ifdef USE_IFC4 @@ -244,8 +250,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* nef_shape.transform(trsf); } - nef_shape.convert_to_polyhedron(shape); - return true; + try { + nef_shape.convert_to_polyhedron(shape); + return true; + } catch (...) { + std::cout << "IfcExtrudedAreaSolidTapered: cannot convert Nef to polyhedron!" << std::endl; + return false; + } } #endif @@ -458,8 +469,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - } nef_result.convert_to_polyhedron(shape); - return true; + } try { + nef_result.convert_to_polyhedron(shape); + return true; + } catch (...) { + std::cout << "IfcBooleanResult: cannot convert Nef to polyhedron!" << std::endl; + return false; + } } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) { @@ -475,8 +491,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - } nef_result.convert_to_polyhedron(shape); - return true; + } try { + nef_result.convert_to_polyhedron(shape); + return true; + } catch (...) { + std::cout << "IfcBooleanResult: cannot convert Nef to polyhedron!" << std::endl; + return false; + } } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) { @@ -492,8 +513,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - } nef_result.convert_to_polyhedron(shape); - return true; + } try { + nef_result.convert_to_polyhedron(shape); + return true; + } catch (...) { + std::cout << "IfcBooleanResult: cannot convert Nef to polyhedron!" << std::endl; + return false; + } } return false; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 9c9512ceac..d13dab80ec 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -300,8 +300,16 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, } if (brep_cut_result.is_valid()) { - nef_brep_cut_result.convert_to_Polyhedron(brep_cut_result); - cut_shapes.push_back(IfcGeom::ConversionResult(new CgalShape(brep_cut_result), &it3->Style())); + try { + nef_brep_cut_result.convert_to_polyhedron(brep_cut_result); + cut_shapes.push_back(IfcGeom::ConversionResult(new CgalShape(brep_cut_result), &it3->Style())); + } catch (...) { + // Apparently processing the boolean operation failed or resulted in an invalid result + // in which case the original shape without the subtractions is returned instead + // we try convert the openings in the original way, one by one. + Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed:", entity->entity); + return false; + } } else { // Apparently processing the boolean operation failed or resulted in an invalid result // in which case the original shape without the subtractions is returned instead From 26bd03e4073b52b570ab77f13c58c96206df287c Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 10 Apr 2017 18:53:52 -0500 Subject: [PATCH 78/86] Ditto --- src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 69003d9aa1..c01c6e8576 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -45,9 +45,14 @@ CGAL::Polyhedron_3 IfcGeom::CgalKernel::create_polyhedron(std::list IfcGeom::CgalKernel::create_polyhedron(CGAL::Nef_polyhedron_3 &nef_polyhedron) { if (nef_polyhedron.is_simple()) { - CGAL::Polyhedron_3 polyhedron; - nef_polyhedron.convert_to_polyhedron(polyhedron); - return polyhedron; + try { + CGAL::Polyhedron_3 polyhedron; + nef_polyhedron.convert_to_polyhedron(polyhedron); + return polyhedron; + } catch (...) { + std::cout << "Conversion from Nef to polyhedron failed!" << std::endl; + return CGAL::Polyhedron_3(); + } } else { std::cout << "Nef polyhedron not simple: cannot create polyhedron!" << std::endl; return CGAL::Polyhedron_3(); From 9f2a617ad740995195711737da5e51826ae82124 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 10 Apr 2017 18:54:30 -0500 Subject: [PATCH 79/86] Catch a few nasty cases in triangulation, more efficient to only compute face normals --- .../kernels/cgal/CgalConversionResult.cpp | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index ba6e1fa5b2..8aa38cbee1 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -10,29 +10,52 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, vertex->point() = vertex->point().transform(trsf); } + if (!s.is_valid() || !s.is_closed()) { + Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (before triangulation)"); + std::ofstream ferror; + ferror.open("/Users/ken/Desktop/error.off"); + ferror << s << std::endl; + ferror.close(); + return; + } + // std::ofstream fbefore; // fbefore.open("/Users/ken/Desktop/before.off"); // fbefore << s << std::endl; // fbefore.close(); // Triangulate the shape and compute the normals - std::map vertex_normals; - boost::associative_property_map> vertex_normals_map(vertex_normals); +// std::map vertex_normals; +// boost::associative_property_map> vertex_normals_map(vertex_normals); std::map face_normals; boost::associative_property_map> face_normals_map(face_normals); - if (CGAL::Polygon_mesh_processing::triangulate_faces(s)) { -// std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; - } else { - Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape"); + cgal_shape_t s_copy(s); + if (!CGAL::Polygon_mesh_processing::triangulate_faces(s) ) { + Logger::Message(Logger::LOG_ERROR, "Triangulation failed"); + std::ofstream ferror; + ferror.open("/Users/ken/Desktop/error.off"); + ferror << s << std::endl; + ferror.close(); return; } + // std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; // std::ofstream fafter; // fafter.open("/Users/ken/Desktop/after.off"); // fafter << s << std::endl; // fafter.close(); - - CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); + + if (!s.is_valid() || !s.is_closed()) { + Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (after triangulation)"); + std::ofstream ferror; + ferror.open("/Users/ken/Desktop/error.off"); + ferror << s_copy << std::endl; + ferror.close(); + return; + } + +// CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); + CGAL::Polygon_mesh_processing::compute_face_normals(s, face_normals_map); for (auto &face: faces(s)) { if (!face->is_triangle()) { From 164e67a50bc3deaee567a30aa2dc1853299fe71b Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 21 Apr 2017 15:43:19 +0200 Subject: [PATCH 80/86] Catching some more CGAL errors, allow non-closed meshes, start of new code to triangulate faces --- .../kernels/cgal/CgalConversionFunctions.cpp | 52 ++++++++++++++++--- .../kernels/cgal/CgalConversionResult.cpp | 16 ++++-- .../kernels/cgal/CgalIfcGeomShapes.cpp | 34 +++++++++--- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 34 ++++++++++-- src/ifcgeom/kernels/cgal/CgalKernel.h | 1 + 5 files changed, 117 insertions(+), 20 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index c01c6e8576..c3645d77b8 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -26,7 +26,7 @@ CGAL::Polyhedron_3 IfcGeom::CgalKernel::create_polyhedron(std::list IfcGeom::CgalKernel::create_polyhedron(CGAL::Nef_poly nef_polyhedron.convert_to_polyhedron(polyhedron); return polyhedron; } catch (...) { - std::cout << "Conversion from Nef to polyhedron failed!" << std::endl; + Logger::Message(Logger::LOG_ERROR, "Conversion from Nef to polyhedron failed!"); return CGAL::Polyhedron_3(); } } else { - std::cout << "Nef polyhedron not simple: cannot create polyhedron!" << std::endl; + Logger::Message(Logger::LOG_ERROR, "Nef polyhedron not simple: cannot create polyhedron!"); return CGAL::Polyhedron_3(); } } CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(std::list &face_list) { CGAL::Polyhedron_3 polyhedron = create_polyhedron(face_list); - return CGAL::Nef_polyhedron_3(polyhedron); + CGAL::Polygon_mesh_processing::triangulate_faces(polyhedron); + CGAL::Nef_polyhedron_3 nef_polyhedron; + try { + nef_polyhedron = CGAL::Nef_polyhedron_3(polyhedron); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Conversion to Nef polyhedron failed!"); + return nef_polyhedron; + } return nef_polyhedron; } CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(CGAL::Polyhedron_3 &polyhedron) { if (polyhedron.is_valid()) { CGAL::Polygon_mesh_processing::triangulate_faces(polyhedron); - return CGAL::Nef_polyhedron_3(polyhedron); + CGAL::Nef_polyhedron_3 nef_polyhedron; + try { + nef_polyhedron = CGAL::Nef_polyhedron_3(polyhedron); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Conversion to Nef polyhedron failed!"); + return nef_polyhedron; + } return nef_polyhedron; } else { - std::cout << "Polyhedron not valid: cannot create Nef polyhedron!" << std::endl; + Logger::Message(Logger::LOG_ERROR, "Polyhedron not valid: cannot create Nef polyhedron!"); return CGAL::Nef_polyhedron_3(); } } + +CGAL::Polyhedron_3 IfcGeom::CgalKernel::triangulate_faces(CGAL::Polyhedron_3 &polyhedron) { + std::list face_list; + + for (CGAL::Polyhedron_3::Facet_const_iterator current_facet = polyhedron.facets_begin(); + current_facet != polyhedron.facets_end(); + ++current_facet) { + + // Triangle + if (current_facet->is_triangle()) { + face_list.push_back(cgal_face_t()); + CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = current_facet->facet_begin(); + do { + face_list.back().outer.push_back(current_halfedge->vertex()->point()); + ++current_halfedge; + } while (current_halfedge != current_facet->facet_begin()); + } + + // Polygon + else { + std::list points_in_polygon; + + } + } + + return create_polyhedron(face_list); +} diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 8aa38cbee1..98a4272fee 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -10,7 +10,7 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, vertex->point() = vertex->point().transform(trsf); } - if (!s.is_valid() || !s.is_closed()) { + if (!s.is_valid()) { Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (before triangulation)"); std::ofstream ferror; ferror.open("/Users/ken/Desktop/error.off"); @@ -30,7 +30,17 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, std::map face_normals; boost::associative_property_map> face_normals_map(face_normals); cgal_shape_t s_copy(s); - if (!CGAL::Polygon_mesh_processing::triangulate_faces(s) ) { + bool success = false; + try { + success = CGAL::Polygon_mesh_processing::triangulate_faces(s); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Triangulation crashed"); + std::ofstream ferror; + ferror.open("/Users/ken/Desktop/error.off"); + ferror << s << std::endl; + ferror.close(); + return; + } if (!success) { Logger::Message(Logger::LOG_ERROR, "Triangulation failed"); std::ofstream ferror; ferror.open("/Users/ken/Desktop/error.off"); @@ -45,7 +55,7 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, // fafter << s << std::endl; // fafter.close(); - if (!s.is_valid() || !s.is_closed()) { + if (!s.is_valid()) { Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (after triangulation)"); std::ofstream ferror; ferror.open("/Users/ken/Desktop/error.off"); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 7b64a21321..f6af7fc884 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -91,7 +91,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal hole_top_face.outer.push_back(*vertex+height*dir); } face_list.push_back(hole_top_face); - nef_shape -= create_nef_polyhedron(face_list); + try { + nef_shape -= create_nef_polyhedron(face_list); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "IfcExtrudedAreaSolid: cannot subtract opening for:", l->entity); + return false; + } } if (has_position) { @@ -104,7 +109,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal nef_shape.convert_to_polyhedron(shape); return true; } catch (...) { - std::cout << "IfcExtrudedAreaSolid: cannot convert Nef to polyhedron!" << std::endl; + Logger::Message(Logger::LOG_ERROR, "IfcExtrudedAreaSolid: cannot convert Nef to polyhedron for:", l->entity); return false; } @@ -238,7 +243,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolidTapered* // f2 << inner_polyhedron << std::endl; // f2.close(); - nef_shape -= create_nef_polyhedron(face_list); + try { + nef_shape -= create_nef_polyhedron(face_list); + } catch (...) { + std::cout << "IfcExtrudedAreaSolidTapered: cannot subtract opening for:" << std::endl; + return false; + } ++inner_face1; ++inner_face2; @@ -453,14 +463,24 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { // std::cout << "Difference" << std::endl; - CGAL::Nef_polyhedron_3 nef_result(s1); - if (is_halfspace) { + CGAL::Nef_polyhedron_3 nef_result; + try { + nef_result = CGAL::Nef_polyhedron_3(s1); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "s1: cannot convert to Nef?", operand1->entity); + return false; + } if (is_halfspace) { if (is_plane) nef_result = nef_result.intersection(plane, CGAL::Nef_polyhedron_3::Intersection_mode::CLOSED_HALFSPACE); } else { - nef_result -= CGAL::Nef_polyhedron_3(s2); + CGAL::Nef_polyhedron_3 nef_s2; + try { + nef_s2 = CGAL::Nef_polyhedron_3(s2); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "s2: cannot convert to Nef?", operand2->entity); + } nef_result -= nef_s2; } if (!nef_result.is_simple()) { - std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; + Logger::Message(Logger::LOG_ERROR, "s2: not simple?", operand2->entity); return false; } else { // CGAL::Polyhedron_3 result; diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index d13dab80ec..280db29647 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -290,8 +290,26 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, // fresult << polyhedron << std::endl; // fresult.close(); - CGAL::Nef_polyhedron_3 nef_opening(opening); - nef_brep_cut_result -= nef_opening; + CGAL::Nef_polyhedron_3 nef_opening; + try { + nef_opening = CGAL::Nef_polyhedron_3(opening); + } catch (...) { + Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed (Nef conversion):", entity->entity); + std::ofstream ferror; + ferror.open("/Users/ken/Desktop/error.off"); + ferror << entity_shape << std::endl; + ferror.close(); + return false; + } try { + nef_brep_cut_result -= nef_opening; + } catch (...) { + Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed (subtraction):", entity->entity); + std::ofstream ferror; + ferror.open("/Users/ken/Desktop/error.off"); + ferror << entity_shape << std::endl; + ferror.close(); + return false; + } // brep_cut_result.convert_to_polyhedron(polyhedron); // fresult.open("/Users/ken/Desktop/after.off"); @@ -307,14 +325,22 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, // Apparently processing the boolean operation failed or resulted in an invalid result // in which case the original shape without the subtractions is returned instead // we try convert the openings in the original way, one by one. - Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed:", entity->entity); + Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed (conversion):", entity->entity); + std::ofstream ferror; + ferror.open("/Users/ken/Desktop/error.off"); + ferror << entity_shape << std::endl; + ferror.close(); return false; } } else { // Apparently processing the boolean operation failed or resulted in an invalid result // in which case the original shape without the subtractions is returned instead // we try convert the openings in the original way, one by one. - Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed:", entity->entity); + Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed (invalid):", entity->entity); + std::ofstream ferror; + ferror.open("/Users/ken/Desktop/error.off"); + ferror << entity_shape << std::endl; + ferror.close(); return false; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 266b7a8294..a445ec275c 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -140,6 +140,7 @@ namespace IfcGeom { bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const cgal_placement_t& entity_trsf, ConversionResults& cut_shapes); + CGAL::Polyhedron_3 triangulate_faces(CGAL::Polyhedron_3 &polyhedron); CGAL::Polyhedron_3 create_polyhedron(std::list &face_list); CGAL::Polyhedron_3 create_polyhedron(CGAL::Nef_polyhedron_3 &nef_polyhedron); CGAL::Nef_polyhedron_3 create_nef_polyhedron(std::list &face_list); From 85a36738d2357fd77429da8fe522736a17958c5e Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 25 Apr 2017 13:42:38 +0200 Subject: [PATCH 81/86] Comment out triangulation code --- .../kernels/cgal/CgalConversionFunctions.cpp | 52 +++++++++---------- src/ifcgeom/kernels/cgal/CgalKernel.h | 2 +- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index c3645d77b8..026b491b88 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -87,29 +87,29 @@ CGAL::Nef_polyhedron_3 IfcGeom::CgalKernel::create_nef_polyhedron(CGAL:: } } -CGAL::Polyhedron_3 IfcGeom::CgalKernel::triangulate_faces(CGAL::Polyhedron_3 &polyhedron) { - std::list face_list; - - for (CGAL::Polyhedron_3::Facet_const_iterator current_facet = polyhedron.facets_begin(); - current_facet != polyhedron.facets_end(); - ++current_facet) { - - // Triangle - if (current_facet->is_triangle()) { - face_list.push_back(cgal_face_t()); - CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = current_facet->facet_begin(); - do { - face_list.back().outer.push_back(current_halfedge->vertex()->point()); - ++current_halfedge; - } while (current_halfedge != current_facet->facet_begin()); - } - - // Polygon - else { - std::list points_in_polygon; - - } - } - - return create_polyhedron(face_list); -} +//CGAL::Polyhedron_3 IfcGeom::CgalKernel::triangulate_faces(CGAL::Polyhedron_3 &polyhedron) { +// std::list face_list; +// +// for (CGAL::Polyhedron_3::Facet_const_iterator current_facet = polyhedron.facets_begin(); +// current_facet != polyhedron.facets_end(); +// ++current_facet) { +// +// // Triangle +// if (current_facet->is_triangle()) { +// face_list.push_back(cgal_face_t()); +// CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = current_facet->facet_begin(); +// do { +// face_list.back().outer.push_back(current_halfedge->vertex()->point()); +// ++current_halfedge; +// } while (current_halfedge != current_facet->facet_begin()); +// } +// +// // Polygon +// else { +// std::list points_in_polygon; +// +// } +// } +// +// return create_polyhedron(face_list); +//} diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index a445ec275c..ed3ba02b69 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -140,7 +140,7 @@ namespace IfcGeom { bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const cgal_placement_t& entity_trsf, ConversionResults& cut_shapes); - CGAL::Polyhedron_3 triangulate_faces(CGAL::Polyhedron_3 &polyhedron); +// CGAL::Polyhedron_3 triangulate_faces(CGAL::Polyhedron_3 &polyhedron); CGAL::Polyhedron_3 create_polyhedron(std::list &face_list); CGAL::Polyhedron_3 create_polyhedron(CGAL::Nef_polyhedron_3 &nef_polyhedron); CGAL::Nef_polyhedron_3 create_nef_polyhedron(std::list &face_list); From 02244400abbc2269cb1ffc0c867aaf8e6490f027 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 25 Apr 2017 13:43:55 +0200 Subject: [PATCH 82/86] Remove old debug code --- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 52 ------------------------- 1 file changed, 52 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 280db29647..a35d21b9ae 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -96,13 +96,6 @@ IfcGeom::NativeElement* IfcGeom::CgalKernel::create_brep_for_representat try { convert(product->ObjectPlacement(), trsf); } catch (...) {} - -// std::cout << "trsf" << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << trsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } // Does the IfcElement have any IfcOpenings? // Note that openings for IfcOpeningElements are not processed @@ -210,30 +203,9 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, } catch (...) {} } -// std::cout << "entity_trsf" << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << entity_trsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } -// -// std::cout << "opening_trsf before" << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << opening_trsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - // Move the opening into the coordinate system of the IfcProduct opening_trsf = entity_trsf.inverse() * opening_trsf; -// std::cout << "opening_trsf after" << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << opening_trsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } - IfcSchema::IfcProductRepresentation* prodrep = fes->Representation(); IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations(); @@ -252,13 +224,6 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, cgal_shape_t opening_shape(((CgalShape*)opening_shapes[i].Shape())->shape()); for (auto &vertex: vertices(opening_shape)) vertex->point() = vertex->point().transform(gtrsf); opening_shapelist.push_back(opening_shape); - -// std::cout << "gtrsf" << std::endl; -// for (int i = 0; i < 3; ++i) { -// for (int j = 0; j < 4; ++j) { -// std::cout << gtrsf.cartesian(i, j) << " "; -// } std::cout << std::endl; -// } } } @@ -278,18 +243,6 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, for (auto &opening: opening_shapelist) { -// CGAL::Polyhedron_3 polyhedron; -// brep_cut_result.convert_to_polyhedron(polyhedron); -// std::ofstream fresult; -// fresult.open("/Users/ken/Desktop/before.off"); -// fresult << polyhedron << std::endl; -// fresult.close(); -// -// opening.convert_to_polyhedron(polyhedron); -// fresult.open("/Users/ken/Desktop/opening.off"); -// fresult << polyhedron << std::endl; -// fresult.close(); - CGAL::Nef_polyhedron_3 nef_opening; try { nef_opening = CGAL::Nef_polyhedron_3(opening); @@ -310,11 +263,6 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, ferror.close(); return false; } - -// brep_cut_result.convert_to_polyhedron(polyhedron); -// fresult.open("/Users/ken/Desktop/after.off"); -// fresult << polyhedron << std::endl; -// fresult.close(); } if (brep_cut_result.is_valid()) { From b732759388dc8c2d01753ec9e9c73080a57d05dd Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 25 Apr 2017 13:44:34 +0200 Subject: [PATCH 83/86] Comprehensive validation code for opening subtractions --- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 203 +++++++++++++++++++----- 1 file changed, 163 insertions(+), 40 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index a35d21b9ae..5a9ebd4f0f 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -238,60 +238,183 @@ bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* entity, for (auto &vertex: vertices(entity_shape)) vertex->point() = vertex->point().transform(entity_shape_gtrsf); } - cgal_shape_t brep_cut_result(entity_shape); - CGAL::Nef_polyhedron_3 nef_brep_cut_result(brep_cut_result); + cgal_shape_t original_entity_shape(entity_shape); + if (!entity_shape.is_valid()) { + Logger::Message(Logger::LOG_ERROR, "Conversion to Nef will fail. Invalid entity:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + return false; + } if (!entity_shape.is_closed()) { + // TODO: There can be substractions to remove parts of non-volumetric objects. Maybe iterate over all faces of an entity and put them in a Nef_polyhedron_3 through Boolean union? Highly inefficient but maybe desirable... + Logger::Message(Logger::LOG_ERROR, "Subtraction of openings not supported for non-closed entity:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + return false; + } bool success = false; + try { + success = CGAL::Polygon_mesh_processing::triangulate_faces(entity_shape); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Triangulation of entity crashed:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + return false; + } if (!success) { + Logger::Message(Logger::LOG_ERROR, "Triangulation of entity failed:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + return false; + } if (CGAL::Polygon_mesh_processing::does_self_intersect(entity_shape)) { + Logger::Message(Logger::LOG_ERROR, "Conversion to Nef will fail. Self-intersecting entity:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + return false; + } CGAL::Nef_polyhedron_3 nef_brep_cut_result; + try { + nef_brep_cut_result = CGAL::Nef_polyhedron_3(entity_shape); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Could not convert entity to Nef:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + return false; + } try { + cgal_shape_t brep_cut_result; + nef_brep_cut_result.convert_to_polyhedron(brep_cut_result); + } catch (...) { + Logger::Message(Logger::LOG_WARNING, "Final conversion will likely fail. Could not convert entity from Nef:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); +// return false; + } for (auto &opening: opening_shapelist) { - CGAL::Nef_polyhedron_3 nef_opening; + cgal_shape_t original_opening_shape(opening); + if (!opening.is_valid()) { + Logger::Message(Logger::LOG_ERROR, "Conversion to Nef will fail. Invalid opening in entity:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + std::ofstream fopening; + fopening.open("/Users/ken/Desktop/opening.off"); + fopening << original_opening_shape << std::endl; + fopening.close(); + return false; + } if (!opening.is_closed()) { + Logger::Message(Logger::LOG_ERROR, "Subtraction of opening makes no sense. Not closed opening in entity:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + std::ofstream fopening; + fopening.open("/Users/ken/Desktop/opening.off"); + fopening << original_opening_shape << std::endl; + fopening.close(); + return false; + } success = false; + try { + success = CGAL::Polygon_mesh_processing::triangulate_faces(opening); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Triangulation of opening of entity crashed:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + std::ofstream fopening; + fopening.open("/Users/ken/Desktop/opening.off"); + fopening << original_opening_shape << std::endl; + fopening.close(); + return false; + } if (!success) { + Logger::Message(Logger::LOG_ERROR, "Triangulation of opening of entity failed:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + std::ofstream fopening; + fopening.open("/Users/ken/Desktop/opening.off"); + fopening << original_opening_shape << std::endl; + fopening.close(); + return false; + } if (CGAL::Polygon_mesh_processing::does_self_intersect(entity_shape)) { + Logger::Message(Logger::LOG_ERROR, "Conversion to Nef will fail. Self-intersecting opening of entity:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + std::ofstream fopening; + fopening.open("/Users/ken/Desktop/opening.off"); + fopening << original_opening_shape << std::endl; + fopening.close(); + return false; + } CGAL::Nef_polyhedron_3 nef_opening; try { nef_opening = CGAL::Nef_polyhedron_3(opening); } catch (...) { - Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed (Nef conversion):", entity->entity); - std::ofstream ferror; - ferror.open("/Users/ken/Desktop/error.off"); - ferror << entity_shape << std::endl; - ferror.close(); + Logger::Message(Logger::LOG_ERROR, "Could not convert opening of entity to Nef:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + std::ofstream fopening; + fopening.open("/Users/ken/Desktop/opening.off"); + fopening << original_opening_shape << std::endl; + fopening.close(); return false; + } try { + cgal_shape_t opening_shape; + nef_opening.convert_to_polyhedron(opening_shape); + } catch (...) { + Logger::Message(Logger::LOG_WARNING, "Final conversion will likely fail. Could not convert opening of entity from Nef:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + std::ofstream fopening; + fopening.open("/Users/ken/Desktop/opening.off"); + fopening << original_opening_shape << std::endl; + fopening.close(); +// return false; } try { nef_brep_cut_result -= nef_opening; } catch (...) { - Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed (subtraction):", entity->entity); - std::ofstream ferror; - ferror.open("/Users/ken/Desktop/error.off"); - ferror << entity_shape << std::endl; - ferror.close(); + Logger::Message(Logger::LOG_ERROR, "Could not subtract Nef opening of entity:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); + std::ofstream fopening; + fopening.open("/Users/ken/Desktop/opening.off"); + fopening << original_opening_shape << std::endl; + fopening.close(); return false; } } - if (brep_cut_result.is_valid()) { - try { - nef_brep_cut_result.convert_to_polyhedron(brep_cut_result); - cut_shapes.push_back(IfcGeom::ConversionResult(new CgalShape(brep_cut_result), &it3->Style())); - } catch (...) { - // Apparently processing the boolean operation failed or resulted in an invalid result - // in which case the original shape without the subtractions is returned instead - // we try convert the openings in the original way, one by one. - Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed (conversion):", entity->entity); - std::ofstream ferror; - ferror.open("/Users/ken/Desktop/error.off"); - ferror << entity_shape << std::endl; - ferror.close(); - return false; - } - } else { - // Apparently processing the boolean operation failed or resulted in an invalid result - // in which case the original shape without the subtractions is returned instead - // we try convert the openings in the original way, one by one. - Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed (invalid):", entity->entity); - std::ofstream ferror; - ferror.open("/Users/ken/Desktop/error.off"); - ferror << entity_shape << std::endl; - ferror.close(); + try { + nef_brep_cut_result.convert_to_polyhedron(entity_shape); + } catch (...) { + Logger::Message(Logger::LOG_ERROR, "Could not convert entity with openings from Nef:", entity->entity); + std::ofstream fentity; + fentity.open("/Users/ken/Desktop/entity.off"); + fentity << original_entity_shape << std::endl; + fentity.close(); return false; - } + } cut_shapes.push_back(IfcGeom::ConversionResult(new CgalShape(entity_shape), &it3->Style())); - } - return true; + } return true; } From 8b539d2b93f5f9713ef2d0b3fbe28b262db3833a Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 25 Apr 2017 13:44:57 +0200 Subject: [PATCH 84/86] Requirement for self-intersection tests --- src/ifcgeom/kernels/cgal/CgalKernel.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index ed3ba02b69..c9c2c46495 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -47,6 +47,7 @@ if ( it != cache.T.end() ) { e = it->second; return true; } #include #include #include +#include #include typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; From 42f23a786f9d988e9c9826582419be4f7a0d6e30 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 25 Apr 2017 13:45:18 +0200 Subject: [PATCH 85/86] Output all errors as separate files --- .../kernels/cgal/CgalConversionResult.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 98a4272fee..f2ecb1a66b 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -10,10 +10,19 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, vertex->point() = vertex->point().transform(trsf); } + std::string error_file_path; + for (unsigned int error_number = 1; error_number < 1000; ++error_number) { + error_file_path = std::string("/Users/ken/Desktop/error/error"); + error_file_path += std::to_string(error_number); + error_file_path += ".off"; + std::ifstream file_path_test(error_file_path); + if (!file_path_test.good()) break; + } + if (!s.is_valid()) { Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (before triangulation)"); std::ofstream ferror; - ferror.open("/Users/ken/Desktop/error.off"); + ferror.open(error_file_path); ferror << s << std::endl; ferror.close(); return; @@ -36,14 +45,14 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, } catch (...) { Logger::Message(Logger::LOG_ERROR, "Triangulation crashed"); std::ofstream ferror; - ferror.open("/Users/ken/Desktop/error.off"); + ferror.open(error_file_path); ferror << s << std::endl; ferror.close(); return; } if (!success) { Logger::Message(Logger::LOG_ERROR, "Triangulation failed"); std::ofstream ferror; - ferror.open("/Users/ken/Desktop/error.off"); + ferror.open(error_file_path); ferror << s << std::endl; ferror.close(); return; @@ -58,7 +67,7 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, if (!s.is_valid()) { Logger::Message(Logger::LOG_ERROR, "Invalid Polyhedron_3 in object (after triangulation)"); std::ofstream ferror; - ferror.open("/Users/ken/Desktop/error.off"); + ferror.open(error_file_path); ferror << s_copy << std::endl; ferror.close(); return; From 9ae55ab303ec366a255be214434282cfe5b5140a Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 6 Jun 2017 17:12:46 +0200 Subject: [PATCH 86/86] Small fixes to transformations --- src/ifcgeom/kernels/cgal/CgalConversionResult.h | 10 +++------- src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp | 3 +-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index b02e6e5c95..5ed715a50f 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -34,17 +34,13 @@ namespace IfcGeom { operator const cgal_placement_t& () { return trsf_; } virtual double Value(int i, int j) const { - // TODO: Check -// std::cout << "Getting CgalPlacement with i = " << i << " and j = " << j << std::endl; - return CGAL::to_double(trsf_.cartesian(i-1, j-1)); + return CGAL::to_double(trsf_.cartesian(i-1, j-1)); } virtual void Multiply(const ConversionResultPlacement* other) { - // TODO: Check - trsf_ = ((CgalPlacement *)other)->trsf_ * trsf_; + trsf_ = trsf_ * ((CgalPlacement *)other)->trsf_; } virtual void PreMultiply(const ConversionResultPlacement* other) { - // TODO: Check - trsf_ = trsf_ * ((CgalPlacement *)other)->trsf_; + trsf_ = ((CgalPlacement *)other)->trsf_ * trsf_; } virtual ConversionResultPlacement* clone() const { return new CgalPlacement(trsf_); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp index 34f5b6c10c..f91617f8f3 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp @@ -236,10 +236,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOpe return true; } -bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, cgal_placement_t& gtrsf) { +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* l, cgal_placement_t& trsf) { // IN_CACHE(IfcCartesianTransformationOperator2DnonUniform,l,cgal_placement_t,gtrsf) - cgal_placement_t trsf; cgal_point_t origin; cgal_direction_t axis1 (1.,0.,0.); cgal_direction_t axis2 (0.,1.,0.);