diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 6d69e9c384..8b465db32a 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -23,10 +23,10 @@ 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(); + CGAL::Polyhedron_3 polyhedron; PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -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/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index e438b3ace1..3dc4b9c95e 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..e1a4383dc4 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); @@ -956,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; + } +} diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp index 2a878e40fe..d4cda51f6c 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomPrimitives.cpp @@ -126,8 +126,23 @@ 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) { - // 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..4ad278c939 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -50,7 +50,13 @@ 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); + 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 // TODO: Would be faster to triangulate top/bottom face template rather than use Nef polyhedra for subtraction @@ -84,10 +90,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 +123,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 +183,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 +239,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 +253,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 +291,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 +307,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 +324,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 +341,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 +518,13 @@ 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() = Kernel::Point_3(r*vertex->point().x(), + r*vertex->point().y(), + r*vertex->point().z()); + vertex->point() = vertex->point().transform(trsf); + } return true; } @@ -555,8 +566,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 +608,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 +642,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 +693,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 +712,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::Nef_polyhedron_3(pln); + // 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(); 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/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); 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() {