From 6a6f348c27889cb42a528fc9967fec61135bf1af Mon Sep 17 00:00:00 2001 From: azv Date: Tue, 12 Aug 2014 10:59:48 +0400 Subject: [PATCH] Issue #95 fix: Crash on circle creation is eliminated --- src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp | 55 ++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp index 4cd345b86..334f0da24 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp @@ -31,6 +31,8 @@ #include +#include + #ifndef DBL_MAX #define DBL_MAX 1.7976931348623158e+308 #endif @@ -40,7 +42,7 @@ const double tolerance = Precision::Confusion(); // This value helps to find direction on the boundaries of curve. // It is not significant for lines, but is used for circles to avoid // wrong directions of movement (when two edges are tangent on the certain vertex) -const double shift = acos(1.0 - 2.0 * tolerance); +const double shift = acos(1.0 - 3.0 * tolerance); /// \brief Search first vertex - the vertex with lowest x coordinate, which is used in 2 edges at least static const TopoDS_Shape& findStartVertex( @@ -104,14 +106,25 @@ void GeomAlgoAPI_SketchBuilder::createFaces( BOPAlgo_PaveFiller aPF; TopoDS_Shape aFeaturesCompound; - if (theFeatures.size() == 1) + // Obtain only edges from the features list + std::list< boost::shared_ptr > anEdges; + std::list< boost::shared_ptr >::const_iterator aFeatIt = theFeatures.begin(); + for ( ; aFeatIt != theFeatures.end(); aFeatIt++) + { + boost::shared_ptr aShape(*aFeatIt); + const TopoDS_Edge& anEdge = aShape->impl(); + if (anEdge.ShapeType() == TopAbs_EDGE) + anEdges.push_back(aShape); + } + + if (anEdges.size() == 1) { // If there is only one feature, BOPAlgo_Builder will decline to work. Need to process it anyway - aFeaturesCompound = theFeatures.front()->impl(); + aFeaturesCompound = anEdges.front()->impl(); } else { - std::list< boost::shared_ptr >::const_iterator anIt = theFeatures.begin(); - for (; anIt != theFeatures.end(); anIt++) + std::list< boost::shared_ptr >::const_iterator anIt = anEdges.begin(); + for (; anIt != anEdges.end(); anIt++) { boost::shared_ptr aPreview(*anIt); aBuilder.AddArgument(aPreview->impl()); @@ -346,8 +359,7 @@ void GeomAlgoAPI_SketchBuilder::fixIntersections( for (++anIter2; anIter2 != theFaces.end(); anIter2++) { const TopoDS_Face& aF1 = (*anIter1)->impl(); - if (aF1.ShapeType() != TopAbs_FACE) // TODO: MPV - this workaround must be fixed later by AZV, now it just removes crash - continue; + assert(aF1.ShapeType() == TopAbs_FACE); // all items in result list should be faces TopExp_Explorer aVert2((*anIter2)->impl(), TopAbs_VERTEX); for ( ; aVert2.More(); aVert2.Next()) { @@ -359,8 +371,7 @@ void GeomAlgoAPI_SketchBuilder::fixIntersections( if (aVert2.More()) { // second shape is not inside first, change the shapes order and repeat comparision const TopoDS_Face& aF2 = (*anIter2)->impl(); - if (aF2.ShapeType() != TopAbs_FACE) // TODO: MPV - this workaround must be fixed later by AZV, now it just removes crash - continue; + assert(aF2.ShapeType() == TopAbs_FACE); // all items in result list should be faces TopExp_Explorer aVert1((*anIter1)->impl(), TopAbs_VERTEX); for ( ; aVert1.More(); aVert1.Next()) { @@ -373,14 +384,30 @@ void GeomAlgoAPI_SketchBuilder::fixIntersections( { // first shape should be cut from the second BRepAlgoAPI_Cut aCut((*anIter2)->impl(), (*anIter1)->impl()); - (*anIter2)->setImpl(new TopoDS_Shape(aCut.Shape())); + aCut.Build(); + TopExp_Explorer anExp(aCut.Shape(), TopAbs_FACE); + (*anIter2)->setImpl(new TopoDS_Shape(anExp.Current())); + for (anExp.Next(); anExp.More(); anExp.Next()) + { + boost::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(anExp.Current())); + theFaces.push_back(aShape); + } } } else { // second shape should be cut from the first BRepAlgoAPI_Cut aCut((*anIter1)->impl(), (*anIter2)->impl()); - (*anIter1)->setImpl(new TopoDS_Shape(aCut.Shape())); + aCut.Build(); + TopExp_Explorer anExp(aCut.Shape(), TopAbs_FACE); + (*anIter1)->setImpl(new TopoDS_Shape(anExp.Current())); + for (anExp.Next(); anExp.More(); anExp.Next()) + { + boost::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(anExp.Current())); + theFaces.push_back(aShape); + } } } } @@ -588,12 +615,14 @@ gp_Dir getOuterEdgeDirection(const TopoDS_Shape& theEdge, gp_Pnt aPnt; gp_Vec aTang; - aCurve->D1(aFirst + shift, aPnt, aTang); + // A direction is determined not in the boundary points but in the points with small shift. + // It was done to avoid tangency between circle and other edge in the shared vertex. + aCurve->D1(aFirst + shift > aLast ? aFirst : aFirst + shift, aPnt, aTang); aCurve->D0(aFirst, aPnt); if (aVertexPnt.IsEqual(aPnt, tolerance)) return gp_Dir(aTang.Reversed()); - aCurve->D1(aLast - shift, aPnt, aTang); + aCurve->D1(aLast - shift < aFirst ? aLast : aLast - shift, aPnt, aTang); return gp_Dir(aTang); } -- 2.39.2