From 6297ff74f169bac61fc462720bf003552bbff0cb Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Thu, 2 Mar 2017 18:11:11 -0600 Subject: [PATCH] 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;