From afb2aaab5ab1cbe9869bb17810fbb56f0bf37d81 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 13 Aug 2020 12:22:03 +0200 Subject: [PATCH] Fixes for polygonal facesets and skip over errors in SVG --- src/ifcgeom/IfcGeomShapes.cpp | 99 +++++++++++++++---------------- src/serializers/SvgSerializer.cpp | 4 +- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index a1163d1d3b..9f9884d727 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -1624,6 +1624,39 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, TopoDS return true; } +namespace { + bool make_indexed_polygon(IfcGeom::Kernel& k, const std::vector& points, const std::vector& indices, TopoDS_Wire& wire) { + TColgp_SequenceOfPnt polygon; + for (std::vector::size_type j = 0; j != indices.size(); j++) { + const gp_Pnt& point = points[indices[j] - 1]; + polygon.Append(point); + } + k.remove_duplicate_points_from_loop(polygon, true); + + if (polygon.Size() < 3) { + return false; + } + + BRepBuilderAPI_MakePolygon wire_builder; + for (int i = 1; i <= polygon.Length(); ++i) { + wire_builder.Add(polygon.Value(i)); + } + wire_builder.Close(); + + wire = wire_builder.Wire(); + + TopoDS_Iterator it(wire); + for (; it.More(); it.Next()) { + BRepAdaptor_Curve ad(TopoDS::Edge(it.Value())); + } + + ShapeFix_ShapeTolerance FTol; + FTol.SetTolerance(wire, k.getValue(IfcGeom::Kernel::GV_PRECISION), TopAbs_WIRE); + + return true; + } +} + bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalFaceSet* pfs, TopoDS_Shape& shape) { IfcSchema::IfcCartesianPointList3D* point_list = pfs->Coordinates(); const std::vector > coordinates = point_list->CoordList(); @@ -1640,33 +1673,15 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalFaceSet* pfs, TopoDS_ auto polygonal_faces = pfs->Faces(); - std::vector faces; - - TopoDS_Compound all_faces; - BRep_Builder compound_builder; - compound_builder.MakeCompound(all_faces); - - ShapeFix_ShapeTolerance FTol; + TopTools_ListOfShape faces; for (unsigned i = 0; i < polygonal_faces->size(); i++) { IfcSchema::IfcIndexedPolygonalFace* la = (IfcSchema::IfcIndexedPolygonalFace*)*(polygonal_faces->begin() + i); TopoDS_Face face; - // Gives the indexed points defining the face - std::vector test = la->CoordIndex(); - - // The points vector gathers all the indexed - // points, sorted in order (cf BuildingSmart https://urlz.fr/aXN6) - std::vector face_points; - BRepBuilderAPI_MakePolygon wire_builder = BRepBuilderAPI_MakePolygon(); - for (std::vector::size_type j = 0; j != test.size(); j++) { - const gp_Pnt& point = points[test[j] - 1]; - TopoDS_Vertex vertex = BRepBuilderAPI_MakeVertex(point); - wire_builder.Add(vertex); - } - - wire_builder.Close(); - TopoDS_Wire wire = wire_builder.Wire(); - FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE); + TopoDS_Wire wire; + if (!make_indexed_polygon(*this, points, la->CoordIndex(), wire)) { + continue; + } if (la->declaration().is(IfcSchema::IfcIndexedPolygonalFaceWithVoids::Class())) { IfcSchema::IfcIndexedPolygonalFaceWithVoids* converted = (IfcSchema::IfcIndexedPolygonalFaceWithVoids*)la; @@ -1675,22 +1690,11 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalFaceSet* pfs, TopoDS_ BRepBuilderAPI_MakeFace facemaker = BRepBuilderAPI_MakeFace(wire); std::vector vectorofwires{ wire }; for (std::vector >::const_iterator it = innercoordinates.begin(); it != innercoordinates.end(); ++it) { - std::vector mycoords = *it; - BRepBuilderAPI_MakePolygon inner_wire_builder = BRepBuilderAPI_MakePolygon(); - for (std::vector::size_type j = 0; j != mycoords.size(); j++) { - gp_Pnt apoint = points[mycoords[j] - 1]; - TopoDS_Vertex vertex = BRepBuilderAPI_MakeVertex(apoint); - inner_wire_builder.Add(vertex); - } - - inner_wire_builder.Close(); - - TopoDS_Wire mywire = inner_wire_builder.Wire(); - FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE); - - vectorofwires.push_back(mywire); - - facemaker.Add(mywire); + TopoDS_Wire inner_wire; + if (make_indexed_polygon(*this, points, *it, inner_wire)) { + vectorofwires.push_back(inner_wire); + facemaker.Add(inner_wire); + } } facemaker.Build(); @@ -1704,7 +1708,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalFaceSet* pfs, TopoDS_ for (; it.More(); it.Next()) { const TopoDS_Face& tri = TopoDS::Face(it.Value()); if (face_area(tri) > getValue(GV_MINIMAL_FACE_AREA)) { - faces.push_back(tri); + faces.Append(tri); } } continue; @@ -1723,7 +1727,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalFaceSet* pfs, TopoDS_ for (; it.More(); it.Next()) { const TopoDS_Face& tri = TopoDS::Face(it.Value()); if (face_area(tri) > getValue(GV_MINIMAL_FACE_AREA)) { - faces.push_back(tri); + faces.Append(tri); } } continue; @@ -1744,20 +1748,13 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalFaceSet* pfs, TopoDS_ } if (face_area(face) > getValue(GV_MINIMAL_FACE_AREA)) { - faces.push_back(face); + faces.Append(face); } } - if (faces.empty()) return false; + if (faces.Size() == 0) return false; - TopTools_ListOfShape faces_list; - for (std::vector::const_iterator it = faces.begin(); it != faces.end(); ++it) { - faces_list.Append(*it); - } - - create_solid_from_faces(faces_list, shape); - - return true; + return create_solid_from_faces(faces, shape); } #endif diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index 54ea948171..43788ffe84 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -443,7 +443,9 @@ void SvgSerializer::write(const IfcGeom::BRepElement* o) const TopoDS_Shape& subshape = it.Value(); Bnd_Box bb; - BRepBndLib::Add(it.Value(), bb); + try { + BRepBndLib::Add(it.Value(), bb); + } catch (const Standard_Failure&) {} // Empty geometry if (bb.IsVoid()) {