From 921ada74d4c524bd95b18481fec695cc86a54511 Mon Sep 17 00:00:00 2001 From: Wanderer Fan Date: Mon, 31 Jan 2022 13:22:26 -0500 Subject: [PATCH] [TD]Fix 4486 allow detail view of Base with no solids --- src/Mod/TechDraw/App/DrawUtil.cpp | 20 +++- src/Mod/TechDraw/App/DrawUtil.h | 2 + src/Mod/TechDraw/App/DrawViewDetail.cpp | 149 ++++++++++++++++-------- src/Mod/TechDraw/App/DrawViewDetail.h | 1 + 4 files changed, 123 insertions(+), 49 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawUtil.cpp b/src/Mod/TechDraw/App/DrawUtil.cpp index 575fe01f3c..1bcab66030 100644 --- a/src/Mod/TechDraw/App/DrawUtil.cpp +++ b/src/Mod/TechDraw/App/DrawUtil.cpp @@ -596,9 +596,9 @@ Base::Vector3d DrawUtil::Intersect2d(Base::Vector3d p1, Base::Vector3d d1, double C2 = A2*p2.x + B2*p2.y; double det = A1*B2 - A2*B1; - if(det == 0){ + if (fpCompare(det, 0.0, Precision::Confusion())) { Base::Console().Message("Lines are parallel\n"); - }else{ + } else { double x = (B2*C1 - B1*C2)/det; double y = (A1*C2 - A2*C1)/det; result.x = x; @@ -623,7 +623,7 @@ Base::Vector2d DrawUtil::Intersect2d(Base::Vector2d p1, Base::Vector2d d1, double C2 = A2*p2.x + B2*p2.y; double det = A1*B2 - A2*B1; - if(det == 0){ + if (fpCompare(det, 0.0, Precision::Confusion())) { Base::Console().Message("Lines are parallel\n"); }else{ double x = (B2*C1 - B1*C2)/det; @@ -826,6 +826,20 @@ bool DrawUtil::circulation(Base::Vector3d A, Base::Vector3d B, Base::Vector3d C) return false; } +int DrawUtil::countSubShapes(TopoDS_Shape shape, TopAbs_ShapeEnum subShape) +{ + int count = 0; + TopExp_Explorer Ex(shape, subShape); + while (Ex.More()) + { + count++; + Ex.Next(); + } + return count; +} + + + // Supplementary mathematical functions // ==================================== diff --git a/src/Mod/TechDraw/App/DrawUtil.h b/src/Mod/TechDraw/App/DrawUtil.h index 57a714e572..9c53c6d8c9 100644 --- a/src/Mod/TechDraw/App/DrawUtil.h +++ b/src/Mod/TechDraw/App/DrawUtil.h @@ -124,6 +124,8 @@ class TechDrawExport DrawUtil { static bool isCrazy(TopoDS_Edge e); static Base::Vector3d getFaceCenter(TopoDS_Face f); static bool circulation(Base::Vector3d A, Base::Vector3d B, Base::Vector3d C); + static int countSubShapes(TopoDS_Shape shape, TopAbs_ShapeEnum subShape); + // Supplementary mathematical functions static int sgn(double x); diff --git a/src/Mod/TechDraw/App/DrawViewDetail.cpp b/src/Mod/TechDraw/App/DrawViewDetail.cpp index 3ea133b289..10dac9f361 100644 --- a/src/Mod/TechDraw/App/DrawViewDetail.cpp +++ b/src/Mod/TechDraw/App/DrawViewDetail.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -276,6 +277,8 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute(void) return DrawView::execute(); } +//try to create a detail of the solids & shells in shape +//if there are no solids/shells in shape, use the edges in shape void DrawViewDetail::detailExec(TopoDS_Shape shape, DrawViewPart* dvp, DrawViewSection* dvs) @@ -286,6 +289,9 @@ void DrawViewDetail::detailExec(TopoDS_Shape shape, double radius = getFudgeRadius(); double scale = getScale(); + int solidCount = DrawUtil::countSubShapes(shape, TopAbs_SOLID); + int shellCount = DrawUtil::countSubShapes(shape, TopAbs_SHELL); + BRepBuilderAPI_Copy BuilderCopy(shape); TopoDS_Shape myShape = BuilderCopy.Shape(); @@ -318,6 +324,9 @@ void DrawViewDetail::detailExec(TopoDS_Shape shape, Base::Vector3d toolPlaneOrigin = anchorOffset3d + dirDetail * diag * -1.0; //center tool about anchor double extrudeLength = 2.0 * toolPlaneOrigin.Length(); + //make a square face as a basis for cutting prism + //this should be square or circle depending on PreferencesGui::mattingStyle() + //but that would require bridge between App/Gui gp_Pnt gpnt(toolPlaneOrigin.x,toolPlaneOrigin.y,toolPlaneOrigin.z); gp_Dir gdir(dirDetail.x,dirDetail.y,dirDetail.z); gp_Pln gpln(gpnt,gdir); @@ -337,32 +346,56 @@ void DrawViewDetail::detailExec(TopoDS_Shape shape, BRep_Builder builder; TopoDS_Compound pieces; builder.MakeCompound(pieces); - TopExp_Explorer expl(myShape, TopAbs_SOLID); - int indb = 0; - int outdb = 0; - for (; expl.More(); expl.Next()) { - indb++; - const TopoDS_Solid& s = TopoDS::Solid(expl.Current()); + if (solidCount > 0) { + TopExp_Explorer expl(myShape, TopAbs_SOLID); + for (; expl.More(); expl.Next()) { + const TopoDS_Solid& s = TopoDS::Solid(expl.Current()); - BRepAlgoAPI_Common mkCommon(s,tool); - if (!mkCommon.IsDone()) { -// Base::Console().Warning("DVD::execute - %s - detail cut operation failed (1)\n", getNameInDocument()); - continue; + BRepAlgoAPI_Common mkCommon(s,tool); + if (!mkCommon.IsDone()) { + // Base::Console().Warning("DVD::execute - %s - detail cut operation failed (1)\n", getNameInDocument()); + continue; + } + if (mkCommon.Shape().IsNull()) { + // Base::Console().Warning("DVD::execute - %s - detail cut operation failed (2)\n", getNameInDocument()); + continue; + } + //this might be overkill for piecewise algo + //Did we get at least 1 solid? + TopExp_Explorer xp; + xp.Init(mkCommon.Shape(),TopAbs_SOLID); + if (!(xp.More() == Standard_True)) { + // Base::Console().Warning("DVD::execute - mkCommon.Shape is not a solid!\n"); + continue; + } + builder.Add(pieces, mkCommon.Shape()); } - if (mkCommon.Shape().IsNull()) { -// Base::Console().Warning("DVD::execute - %s - detail cut operation failed (2)\n", getNameInDocument()); - continue; + } + + if (shellCount > 0) { + TopExp_Explorer expl(myShape, TopAbs_SHELL); + for (; expl.More(); expl.Next()) { + const TopoDS_Shell& s = TopoDS::Shell(expl.Current()); + + BRepAlgoAPI_Common mkCommon(s,tool); + if (!mkCommon.IsDone()) { + // Base::Console().Warning("DVD::execute - %s - detail cut operation failed (1)\n", getNameInDocument()); + continue; + } + if (mkCommon.Shape().IsNull()) { + // Base::Console().Warning("DVD::execute - %s - detail cut operation failed (2)\n", getNameInDocument()); + continue; + } + //this might be overkill for piecewise algo + //Did we get at least 1 shell? + TopExp_Explorer xp; + xp.Init(mkCommon.Shape(),TopAbs_SHELL); + if (!(xp.More() == Standard_True)) { + // Base::Console().Warning("DVD::execute - mkCommon.Shape is not a shell!\n"); + continue; + } + builder.Add(pieces, mkCommon.Shape()); } - //this might be overkill for piecewise algo - //Did we get at least 1 solid? - TopExp_Explorer xp; - xp.Init(mkCommon.Shape(),TopAbs_SOLID); - if (!(xp.More() == Standard_True)) { -// Base::Console().Warning("DVD::execute - mkCommon.Shape is not a solid!\n"); - continue; - } - builder.Add(pieces, mkCommon.Shape()); - outdb++; } if (debugDetail()) { @@ -371,19 +404,6 @@ void DrawViewDetail::detailExec(TopoDS_Shape shape, BRepTools::Write(pieces, "DVDCommon.brep"); //debug } - Bnd_Box testBox; - testBox.SetGap(0.0); - BRepBndLib::Add(pieces, testBox); - if (testBox.IsVoid()) { - TechDraw::GeometryObject* go = getGeometryObject(); - if (go != nullptr) { - go->clear(); - } - dvp->requestPaint(); - Base::Console().Warning("DVD::execute - %s - detail area contains no geometry\n", getNameInDocument()); - return; - } - //for debugging show compound instead of common // BRep_Builder builder; // TopoDS_Compound Comp; @@ -403,23 +423,37 @@ void DrawViewDetail::detailExec(TopoDS_Shape shape, Base::Vector3d stdOrg(0.0,0.0,0.0); gp_Ax2 viewAxis = dvp->getProjectionCS(stdOrg); //sb same CS as base view. - //center shape on origin -// TopoDS_Shape centeredShape = TechDraw::moveShape(detail, - TopoDS_Shape centeredShape = TechDraw::moveShape(pieces, - centroid * -1.0); + TopoDS_Shape scaledShape; + if ((solidCount > 0) || + (shellCount > 0)) { + //make a detail of the solids/shell in the base view + //center shape on origin + TopoDS_Shape centeredShape = TechDraw::moveShape(pieces, + centroid * -1.0); + scaledShape = TechDraw::scaleShape(centeredShape, + getScale()); + if (debugDetail()) { + BRepTools::Write(tool, "DVDScaled.brep"); //debug + } + } else { + //no solids, no shells, do what you can with edges + TopoDS_Shape projectedEdges = projectEdgesOntoFace(myShape, aProjFace, gdir); + TopoDS_Shape centeredShape = TechDraw::moveShape(projectedEdges, + centroid * -1.0); + if (debugDetail()) { + BRepTools::Write(projectedEdges, "DVDProjectedEdges.brep"); //debug + BRepTools::Write(centeredShape, "DVDCenteredShape.brep"); //debug + } + scaledShape = TechDraw::scaleShape(centeredShape, + getScale()); + } - TopoDS_Shape scaledShape = TechDraw::scaleShape(centeredShape, - getScale()); if (!DrawUtil::fpCompare(Rotation.getValue(),0.0)) { scaledShape = TechDraw::rotateShape(scaledShape, viewAxis, Rotation.getValue()); } - if (debugDetail()) { - BRepTools::Write(tool, "DVDScaled.brep"); //debug - } - geometryObject = buildGeometryObject(scaledShape,viewAxis); geometryObject->pruneVertexGeom(Base::Vector3d(0.0,0.0,0.0), Radius.getValue() * scale); //remove vertices beyond clipradius @@ -450,6 +484,29 @@ void DrawViewDetail::detailExec(TopoDS_Shape shape, } +TopoDS_Shape DrawViewDetail::projectEdgesOntoFace(TopoDS_Shape edgeShape, TopoDS_Face projFace, gp_Dir projDir) +{ + BRep_Builder builder; + TopoDS_Compound edges; + builder.MakeCompound(edges); + TopExp_Explorer Ex(edgeShape, TopAbs_EDGE); + while (Ex.More()) + { + TopoDS_Edge e = TopoDS::Edge(Ex.Current()); + BRepProj_Projection mkProj(e, projFace, projDir); + if (mkProj.IsDone()) { + builder.Add(edges, mkProj.Shape()); + } + Ex.Next(); + } + if (debugDetail()) { + BRepTools::Write(edges, "DVDEdges.brep"); //debug + } + + return edges; +} + + double DrawViewDetail::getFudgeRadius() { return Radius.getValue() * m_fudge; diff --git a/src/Mod/TechDraw/App/DrawViewDetail.h b/src/Mod/TechDraw/App/DrawViewDetail.h index 8bfb536eb7..a1e4261549 100644 --- a/src/Mod/TechDraw/App/DrawViewDetail.h +++ b/src/Mod/TechDraw/App/DrawViewDetail.h @@ -75,6 +75,7 @@ public: DrawViewPart* baseView, DrawViewSection* sectionAlias); double getFudgeRadius(void); + TopoDS_Shape projectEdgesOntoFace(TopoDS_Shape edgeShape, TopoDS_Face projFace, gp_Dir projDir); protected: Base::Vector3d toR3(const gp_Ax2 fromSystem, const Base::Vector3d fromPoint);