From 38cbdbc0f422bfbb9934b2efa3032a6ad7c86e09 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 13 Mar 2017 20:22:19 -0600 Subject: [PATCH 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 6/7] 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 7/7] 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; }