From 86d0975b2c1780d80195acff07454a6ec332cda0 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Wed, 1 Feb 2023 16:56:02 -0500 Subject: [PATCH] [TD]fix handling of perforated section faces --- src/Mod/TechDraw/App/DrawViewSection.cpp | 135 ++++++++++++++++++----- src/Mod/TechDraw/App/DrawViewSection.h | 7 +- 2 files changed, 112 insertions(+), 30 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawViewSection.cpp b/src/Mod/TechDraw/App/DrawViewSection.cpp index 5333defa53..9176af384c 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.cpp +++ b/src/Mod/TechDraw/App/DrawViewSection.cpp @@ -56,7 +56,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -73,6 +74,8 @@ #include #endif +#include + #include #include #include @@ -400,18 +403,26 @@ void DrawViewSection::makeSectionCut(TopoDS_Shape& baseShape) } // perform cut - BRep_Builder builder; - TopoDS_Compound cutPieces; - builder.MakeCompound(cutPieces); - TopExp_Explorer expl(myShape, TopAbs_SOLID); - for (; expl.More(); expl.Next()) { - const TopoDS_Solid& s = TopoDS::Solid(expl.Current()); - BRepAlgoAPI_Cut mkCut(s, m_cuttingTool); - if (!mkCut.IsDone()) { - Base::Console().Warning("DVS: Section cut has failed in %s\n", getNameInDocument()); - continue; - } - builder.Add(cutPieces, mkCut.Shape()); + // BRep_Builder builder; + // TopoDS_Compound cutPieces; + // builder.MakeCompound(cutPieces); + // TopExp_Explorer expl(myShape, TopAbs_SOLID); + // for (; expl.More(); expl.Next()) { + // const TopoDS_Solid& s = TopoDS::Solid(expl.Current()); + // BRepAlgoAPI_Cut mkCut(s, m_cuttingTool); + // if (!mkCut.IsDone()) { + // Base::Console().Warning("DVS: Section cut has failed in %s\n", getNameInDocument()); + // continue; + // } + // builder.Add(cutPieces, mkCut.Shape()); + // } + + TopoDS_Shape cutPieces = TopoDS_Shape(); + BRepAlgoAPI_Cut mkCut(myShape, m_cuttingTool); + if (!mkCut.IsDone()) { + Base::Console().Warning("DVS: Section cut has failed in %s\n", getNameInDocument()); + } else { + cutPieces = mkCut.Shape(); } // cutPieces contains result of cutting each subshape in baseShape with tool @@ -543,6 +554,9 @@ void DrawViewSection::postHlrTasks(void) requestPaint(); return; } + if (debugSection()) { + BRepTools::Write(faceIntersections, "DVSFaceIntersections.brep");//debug + } TopoDS_Shape centeredFaces = TechDraw::moveShape(faceIntersections, m_saveCentroid * -1.0); @@ -601,10 +615,10 @@ gp_Pln DrawViewSection::getSectionPlane() const //! case is a compound of individual cuts) with the "effective" (flattened) section plane. TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shape& shape) { - // Base::Console().Message("DVS::findSectionPlaneIntersections() - %s\n", getNameInDocument()); +// Base::Console().Message("DVS::findSectionPlaneIntersections() - %s\n", getNameInDocument()); if (shape.IsNull()) { // this shouldn't happen - // Base::Console().Warning("DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n", getNameInDocument()); + Base::Console().Warning("DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n", getNameInDocument()); return TopoDS_Compound(); } @@ -637,7 +651,9 @@ TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shap //move section faces to line up with cut shape TopoDS_Compound DrawViewSection::alignSectionFaces(TopoDS_Shape faceIntersections) { - // Base::Console().Message("DVS::alignSectionFaces()\n"); +// Base::Console().Message("DVS::alignSectionFaces() - %s - faceIntersection.isnull: %d\n", +// getNameInDocument(), +// faceIntersections.IsNull()); TopoDS_Compound sectionFaces; TopoDS_Shape centeredShape = TechDraw::moveShape(faceIntersections, getOriginalCentroid() * -1.0); @@ -657,7 +673,11 @@ TopoDS_Compound DrawViewSection::mapToPage(TopoDS_Shape& shapeToAlign) // needs to be aligned to paper plane (origin, stdZ); //project the faces in the shapeToAlign, build new faces from the resulting wires and //combine everything into a compound of faces - // Base::Console().Message("DVS::mapToPage() - shapeToAlign.null: %d\n", shapeToAlign.IsNull()); +// Base::Console().Message("DVS::mapToPage() - shapeToAlign.null: %d\n", shapeToAlign.IsNull()); + if (debugSection()) { + BRepTools::Write(shapeToAlign, "DVSShapeToAlign.brep"); //debug + } + BRep_Builder builder; TopoDS_Compound result; builder.MakeCompound(result); @@ -682,24 +702,89 @@ TopoDS_Compound DrawViewSection::mapToPage(TopoDS_Shape& shapeToAlign) faceWires.push_back(cleanWire); } - //first wire should be the outer boundary of the face - BRepBuilderAPI_MakeFace mkFace(faceWires.front()); - int wireCount = faceWires.size(); - for (int iWire = 1; iWire < wireCount; iWire++) { - //make holes in the face with the rest of the wires - mkFace.Add(faceWires.at(iWire)); + //validate section face wires + std::vector goodWires; + constexpr double minWireArea = 0.000001; //arbitrary very small face size + for (auto &wire : faceWires) { + if (wire.IsNull()) { + continue; + } + if (!BRep_Tool::IsClosed(wire)) { + continue; //can not make a face from open wire + } + double area = ShapeAnalysis::ContourArea(wire); + if (area <= minWireArea) { + continue; //can not make a face from wire with no area + } + goodWires.push_back(wire); } - builder.Add(result, mkFace.Face()); + + if (goodWires.empty()) { + Base::Console().Warning("DVS::mapToPage - %s - section face has no valid wires.\n", + getNameInDocument()); + continue; + } + + TopoDS_Shape holeyShape = makeFaceFromWires(goodWires); + if (holeyShape.IsNull()) { + continue; + } + + builder.Add(result, TopoDS::Face(holeyShape)); if (debugSection()) { std::stringstream ss; ss << "DVSFaceFromWires" << iFace << ".brep"; - BRepTools::Write(mkFace.Face(), ss.str().c_str());//debug + BRepTools::Write(holeyShape, ss.str().c_str()); //debug } } return result; } +//makes a [perforated] face from an outer wire and wires describing the holes. Open wires +//and wires with zero area are assumed to already have been removed. +TopoDS_Shape DrawViewSection::makeFaceFromWires(std::vector &inWires) +{ + //make sure the largest wire is the first + EdgeWalker eWalker; + std::vector goodWires = eWalker.sortWiresBySize(inWires); + + // make a face from the good wires + //first good wire should be the outer boundary of the face + TopoDS_Face faceToFix; + TopoDS_Shape orientedShape = goodWires.at(0).Oriented(TopAbs_FORWARD); + TopoDS_Wire orientedWire = TopoDS::Wire(orientedShape); + orientedWire.Orientation(TopAbs_FORWARD); + TopoDS_Face blankFace = BRepBuilderAPI_MakeFace(orientedWire); + int wireCount = goodWires.size(); + if (wireCount < 2) { + faceToFix = blankFace; + } else { + //add the holes + BRepBuilderAPI_MakeFace mkFace(blankFace); + for (int iWire = 1; iWire < wireCount; iWire++) { + //make holes in the face with the rest of the wires + orientedShape = goodWires.at(iWire).Oriented(TopAbs_REVERSED); + orientedWire = TopoDS::Wire(orientedShape); + mkFace.Add(orientedWire); + } + + if (!mkFace.IsDone()) { + Base::Console().Warning("DVS::makeFaceFromWires - %s - failed to make section face.\n", + getNameInDocument()); + return TopoDS_Shape(); + } + faceToFix = mkFace.Face(); + } + + //setting the wire orientation above should generate a valid face, but sometimes + //does not, so we fix the shape to resolve any issues + Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; + sfs->Init(faceToFix); + sfs->Perform(); + return sfs->Shape(); +} + //turn OCC section faces into TD geometry std::vector DrawViewSection::makeTDSectionFaces(TopoDS_Compound topoDSFaces) { diff --git a/src/Mod/TechDraw/App/DrawViewSection.h b/src/Mod/TechDraw/App/DrawViewSection.h index 3ee9d4cbc6..f37313108f 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.h +++ b/src/Mod/TechDraw/App/DrawViewSection.h @@ -37,7 +37,6 @@ #include "DrawViewPart.h" - class Bnd_Box; class gp_Pln; class gp_Pnt; @@ -48,10 +47,6 @@ class gp_Ax2; namespace TechDraw { class Face; -} - -namespace TechDraw -{ class DrawProjGroupItem; class DrawGeomHatch; class PATLineSpec; @@ -171,6 +166,8 @@ public: bool showSectionEdges(void); + TopoDS_Shape makeFaceFromWires(std::vector &inWires); + public Q_SLOTS: virtual void onSectionCutFinished(void);