diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 8b465db32a..69003d9aa1 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -5,21 +5,13 @@ 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) { - if (tol <= 0.) tol = getValue(GV_PRECISION); - tol *= tol; - +void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon) { + 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]); } } @@ -51,8 +43,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