From c2eeb5a3742732e7f18977f95ea83d91f50d096c Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 28 Sep 2017 13:27:25 +0300 Subject: [PATCH] Improved the speed of naming structure filling for the issue #2256 --- src/Model/Model_AttributeSelection.cpp | 28 +++++---- src/Model/Model_BodyBuilder.cpp | 79 +++++++++++++++----------- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index f26270a9f..665f2eba5 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -137,6 +137,12 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, std::shared_ptr aSubShape; if (theSubShape.get() && !theContext->shape()->isEqual(theSubShape)) aSubShape = theSubShape; // the whole context + if (aConstruction->isInfinite()) { + // For correct naming selection, put the shape into the naming structure. + // It seems sub-shapes are not needed: only this shape is (and can be ) selected. + TNaming_Builder aBuilder(aSelLab); + aBuilder.Generated(theContext->shape()->impl()); + } int anIndex = aConstruction->select(theSubShape, owner()->document()); TDataStd_Integer::Set(aSelLab, anIndex); } else if (theContext->groupName() == ModelAPI_ResultPart::group()) { @@ -204,21 +210,23 @@ std::shared_ptr Model_AttributeSelection::value() } } + std::shared_ptr aConstr = + std::dynamic_pointer_cast(context()); + if (aConstr) { + if (aConstr->isInfinite()) + return aResult; // empty result + } Handle(TNaming_NamedShape) aSelection; if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { TopoDS_Shape aSelShape = aSelection->Get(); aResult = std::shared_ptr(new GeomAPI_Shape); aResult->setImpl(new TopoDS_Shape(aSelShape)); - } else { // for simple construction element: just shape of this construction element - std::shared_ptr aConstr = - std::dynamic_pointer_cast(context()); - if (aConstr) { - Handle(TDataStd_Integer) anIndex; - if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { - if (anIndex->Get() == 0) // it is just reference to construction, nothing is in value - return aResult; - return aConstr->shape(anIndex->Get(), owner()->document()); - } + } else if (aConstr) { // for simple construction element: just shape of this construction element + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + if (anIndex->Get() == 0) // it is just reference to construction, nothing is in value + return aResult; + return aConstr->shape(anIndex->Get(), owner()->document()); } } } diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 39fbea9b6..49fad4397 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -616,42 +616,57 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, int findAmbiguities(const TopoDS_Shape& theShapeIn, TopTools_ListOfShape& theList) { - int aNumEdges(0); theList.Clear(); - TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors; - TopAbs_ShapeEnum aTS(TopAbs_EDGE); - TopAbs_ShapeEnum aTA(TopAbs_FACE); - TopTools_MapOfShape aMap1, aMap2; // map1 - for edge ancestors; map2 - for keys => edges - TopTools_ListOfShape aKeyList; - TopExp::MapShapesAndAncestors(theShapeIn, aTS, aTA, subShapeAndAncestors); - for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) { - const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i); - const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i); - aMap1.Clear(); - TopTools_ListIteratorOfListOfShape it(ancestors1); - for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1 - for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) { - if (i == j) continue; - const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j); - const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j); - if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) { - int aNum (ancestors2.Extent()); - TopTools_ListIteratorOfListOfShape it(ancestors2); - for(;it.More();it.Next()) - if(aMap1.Contains(it.Value())) aNum--; - if(aNum == 0) { - if(aMap2.Add(aKeyEdge1)) - aKeyList.Append(aKeyEdge1); - if(aMap2.Add(aKeyEdge2)) - aKeyList.Append(aKeyEdge2); + // edges -> ancestor faces list + TopTools_IndexedDataMapOfShapeListOfShape aSubShapeAndAncestors; + TopExp::MapShapesAndAncestors(theShapeIn, TopAbs_EDGE, TopAbs_FACE, aSubShapeAndAncestors); + // keeps the shapes which are already in the resulting list + TopTools_MapOfShape alreadyThere; + // map from faces identifier (combination of hash-codes) to list of edges produced such ID + NCollection_DataMap > aFacesIDs; + + TopTools_IndexedDataMapOfShapeListOfShape::Iterator anAncestorsIter(aSubShapeAndAncestors); + for (; anAncestorsIter.More(); anAncestorsIter.Next()) { + const TopTools_ListOfShape& ancestors = anAncestorsIter.Value(); + if (ancestors.Extent() < 2) + continue; + Standard_Integer anID = 0; + for(TopTools_ListIteratorOfListOfShape aFaceIt(ancestors); aFaceIt.More(); aFaceIt.Next()) { + anID ^= HashCode(aFaceIt.ChangeValue(), 1990657); // Pierpont prime + } + if (aFacesIDs.IsBound(anID)) { // there found same edge, check they really have same faces + const NCollection_List& aSameFaces1 = + aSubShapeAndAncestors.FindFromKey(anAncestorsIter.Key()); + NCollection_List::Iterator aSameEdge(aFacesIDs.ChangeFind(anID)); + for(; aSameEdge.More(); aSameEdge.Next()) { + const NCollection_List& aSameFaces2 = + aSubShapeAndAncestors.FindFromKey(aSameEdge.Value()); + if (aSameFaces2.Extent() != aSameFaces1.Extent()) // the number of faces is different + break; + + NCollection_List::Iterator aFaceIter1(aSameFaces1); + for(; aFaceIter1.More(); aFaceIter1.Next()) { + NCollection_List::Iterator aFaceIter2(aSameFaces2); + for(; aFaceIter2.More(); aFaceIter2.Next()) { + if (aFaceIter1.Value().IsSame(aFaceIter2.Value())) + break; + } + if (!aFaceIter2.More()) // aFaceIter1 contains a face, which is not in aFaceIter2 + break; + } + if (!aFaceIter1.More()) { // all the faces are same => put to the result + if (alreadyThere.Add(aSameEdge.Value())) + theList.Append(aSameEdge.Value()); + if (alreadyThere.Add(anAncestorsIter.Key())) + theList.Append(anAncestorsIter.Key()); } } - } // at the end ==> List of edges to be named in addition + } else { // ID is unique, just add this edge + aFacesIDs.Bind(anID, NCollection_List()); + } + aFacesIDs.ChangeFind(anID).Append(anAncestorsIter.Key()); // add to the list anyway } - aNumEdges = aKeyList.Extent(); - if(aNumEdges) - theList.Assign(aKeyList); - return aNumEdges; + return theList.Extent(); } //======================================================================= -- 2.39.2