From 89d31ff0caa851b3a11177aa77fbabdcb7302d0f Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 14 Sep 2017 14:22:30 +0300 Subject: [PATCH] Improved stability of Test2248 sketch faces order. --- src/FeaturesPlugin/Test/Test2248.py | 2 +- src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp | 93 ++++++++++++++++++- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/FeaturesPlugin/Test/Test2248.py b/src/FeaturesPlugin/Test/Test2248.py index 85ef22df9..89f15dd57 100644 --- a/src/FeaturesPlugin/Test/Test2248.py +++ b/src/FeaturesPlugin/Test/Test2248.py @@ -48,7 +48,7 @@ SketchConstraintTangent_2 = Sketch_1.setTangent(SketchLine_3.result(), SketchArc SketchCircle_1 = Sketch_1.addCircle(-13.45056286489504, 169.4770920976776, 150.6703210346195) model.do() Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 10, 0) -Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/From_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/Generated_Face_6"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/Generated_Face_6"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/Generated_Face_5"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/Generated_Face_10"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/Generated_Face_6"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/Generated_Face_10"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_9"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/Generated_Face_5"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/Generated_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/Generated_Face_8"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/Generated_Face_10"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/Generated_Face_9"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/Generated_Face_8")]) +Group_1 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/To_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_2"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/To_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/From_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_10"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/Generated_Face_10"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/To_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/From_Face_3"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_9"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_5"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/Generated_Face_6"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_4"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/Generated_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/Generated_Face_5"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_11&Extrusion_1_1/Generated_Face_10"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/Generated_Face_5"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_6&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/Generated_Face_6"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_7&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_10&Extrusion_1_1/Generated_Face_9"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_9&Extrusion_1_1/Generated_Face_8"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_8&Extrusion_1_1/Generated_Face_7")]) model.end() # check that resulting group selection is valid diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp index eca84e8a2..c4bf9d6f3 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp @@ -32,10 +32,12 @@ #include #include #include +#include +#include #include #include - +#include static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape) { @@ -100,6 +102,92 @@ static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape, return findStartVertex(theShape); } +// returns true if the first shape must be located earlier than the second +bool isFirst(const TopoDS_Shape& theFirst, const TopoDS_Shape& theSecond, + NCollection_DataMap >& theAreaToIndex, + const NCollection_DataMap& theCurveToIndex) +{ + // fill theAreaToIndex for both shapes if needed + for(int aShapeNum = 1; aShapeNum <= 2; aShapeNum++) { + TopoDS_Shape aShape = aShapeNum == 1 ? theFirst : theSecond; + if (!theAreaToIndex.IsBound(aShape)) { // fill the list of curve indices + NCollection_List aNewList; + TopExp_Explorer anEdgesExp(aShape, TopAbs_EDGE); + for(; anEdgesExp.More(); anEdgesExp.Next()) { + double aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve( + TopoDS::Edge(anEdgesExp.Current()), aFirst, aLast); + if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) + aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve(); + if (theCurveToIndex.IsBound(aCurve)) { + aNewList.Append(theCurveToIndex.Find(aCurve)); + } + } + NCollection_Array1 aNewArray(1, aNewList.Extent()); + NCollection_List::Iterator aListIter(aNewList); + for(int anIndex = 1; aListIter.More(); aListIter.Next(), anIndex++) { + aNewArray.SetValue(anIndex, aListIter.Value()); + } + std::sort(aNewArray.begin(), aNewArray.end()); + theAreaToIndex.Bind(aShape, aNewArray); + } + } + // compare lists of indices one by one to find chich list indices are lower + NCollection_Array1::Iterator aFirstList(theAreaToIndex.ChangeFind(theFirst)); + NCollection_Array1::Iterator aSecondList(theAreaToIndex.ChangeFind(theSecond)); + for(; aFirstList.More() && aSecondList.More(); aFirstList.Next(), aSecondList.Next()) { + if (aFirstList.Value() < aSecondList.Value()) return true; + if (aFirstList.Value() > aSecondList.Value()) return false; + } + // if faces are identical by curves names (circle splitted by line in seam-point), use parameters + if (!aFirstList.More() && !aSecondList.More()) { + GProp_GProps aGProps; + BRepGProp::SurfaceProperties(theFirst, aGProps); + gp_Pnt aCentre1 = aGProps.CentreOfMass(); + BRepGProp::SurfaceProperties(theSecond, aGProps); + gp_Pnt aCentre2 = aGProps.CentreOfMass(); + return aCentre1.X() + aCentre1.Y() + aCentre1.Z() < aCentre2.X() + aCentre2.Y() + aCentre2.Z(); + } + // if in first list there is no elements left, it is the first + return !aFirstList.More(); +} + +// sorts faces (in theAreas list) to make persistent order: by initial shapes edges +static void sortFaces(TopTools_ListOfShape& theAreas, + const std::list >& theInitialShapes) +{ + // collect indices of all edges to operate them quickly + NCollection_DataMap aCurveToIndex; // curve -> index in initial shapes + std::list >::const_iterator aFeatIt = theInitialShapes.begin(); + for (int anIndex = 0; aFeatIt != theInitialShapes.end(); aFeatIt++) { + std::shared_ptr aShape(*aFeatIt); + const TopoDS_Edge& anEdge = aShape->impl(); + if (anEdge.ShapeType() != TopAbs_EDGE) + continue; + + double aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) + aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve(); + if (!aCurveToIndex.IsBound(aCurve)) + aCurveToIndex.Bind(aCurve, anIndex++); + } + // map from area to the most first indices of curves (to compare) in it + NCollection_DataMap > anAreaToIndex; + // sort areas + TopTools_ListOfShape::Iterator anArea1(theAreas); + for(; anArea1.More(); anArea1.Next()) { + TopTools_ListOfShape::Iterator anArea2 = anArea1; + for(anArea2.Next(); anArea2.More(); anArea2.Next()) { + if (!isFirst(anArea1.Value(), anArea2.Value(), anAreaToIndex, aCurveToIndex)) { // exchange + TopoDS_Shape aTmp = anArea1.Value(); + anArea1.ChangeValue() = anArea2.Value(); + anArea2.ChangeValue() = aTmp; + } + } + } +} + void GeomAlgoAPI_SketchBuilder::createFaces( const std::shared_ptr& theOrigin, const std::shared_ptr& theDirX, @@ -134,7 +222,8 @@ void GeomAlgoAPI_SketchBuilder::createFaces( return; // Collect faces - const TopTools_ListOfShape& anAreas = aBB.Modified(aPlnFace); + TopTools_ListOfShape anAreas = aBB.Modified(aPlnFace); + sortFaces(anAreas, theFeatures); // sort faces by the edges in them TopTools_ListIteratorOfListOfShape anIt(anAreas); for (; anIt.More(); anIt.Next()) { TopoDS_Face aFace = TopoDS::Face(anIt.Value()); -- 2.39.2