X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_SelectionNaming.cpp;h=1b1c51e9ec70901a076e22a19d15503fb263dae5;hb=b73fb7468bea81901dbeed8e229d742f788ec282;hp=6de12da8d0ad49553c9819a2ae402c9ae9bc86fa;hpb=75e77d680594278a2da06c25fb6dbbad178e9fcd;p=modules%2Fshaper.git diff --git a/src/Model/Model_SelectionNaming.cpp b/src/Model/Model_SelectionNaming.cpp index 6de12da8d..1b1c51e9e 100644 --- a/src/Model/Model_SelectionNaming.cpp +++ b/src/Model/Model_SelectionNaming.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,41 @@ Model_SelectionNaming::Model_SelectionNaming(TDF_Label theSelectionLab) myLab = theSelectionLab; } +// searches named shape by the shape in the given document (identified by the label) +// tries to find s shape nearest to the context-label +static Handle(TNaming_NamedShape) shapeToNS(const TDF_Label theLabAccess, + const TopoDS_Shape& theShape, const TDF_Label& theContextLab) +{ + Handle(TNaming_NamedShape) aResult; + if (!TNaming_Tool::HasLabel(theLabAccess, theShape)) // no shape in the document + return aResult; + int aContextLabDepth = theContextLab.IsNull() ? 100 : theContextLab.Depth(); + TNaming_SameShapeIterator aNSIter(theShape, theLabAccess); + for(; aNSIter.More(); aNSIter.Next()) { + TDF_Label aLabel = aNSIter.Label(); + Handle(TNaming_NamedShape) aNS; + if (aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + if (aNS->Evolution() != TNaming_SELECTED && aNS->Evolution() != TNaming_DELETE) { + // check this is new shape in this named shape + bool aIsNew = false; + for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) + if (!aNSIter.NewShape().IsNull() && aNSIter.NewShape().IsSame(theShape)) + aIsNew = true; + if (!aIsNew) + continue; + // check this is the context-shape + while(aLabel.Depth() > aContextLabDepth) + aLabel = aLabel.Father(); + if (aLabel.IsEqual(theContextLab)) + return aNS; + if (aResult.IsNull()) // take the first, otherwise it will get shapes from results, etc + aResult = aNS; // keep some result anyway - if there are no context labels return any + } + } + } + return aResult; +} + std::string Model_SelectionNaming::getShapeName( std::shared_ptr theDoc, const TopoDS_Shape& theShape, ResultPtr& theContext, const bool theAnotherDoc, const bool theWholeContext) @@ -70,13 +106,14 @@ std::string Model_SelectionNaming::getShapeName( // (it was in BodyBuilder, but did not work on Result rename) bool isNeedContextName = theContext->shape().get() != NULL; // check if the subShape is already in DF - Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(theShape, myLab); + std::shared_ptr aData = + std::dynamic_pointer_cast(theContext->data()); + TDF_Label aContextDataLab(aData.get() && aData->isValid() ? aData->label() : TDF_Label()); + Handle(TNaming_NamedShape) aNS = shapeToNS(myLab, theShape, aContextDataLab); Handle(TDataStd_Name) anAttr; if(!aNS.IsNull() && !aNS->IsEmpty()) { // in the document if(aNS->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) { - std::shared_ptr aData = - std::dynamic_pointer_cast(theContext->data()); - if (isNeedContextName && aData && aData->label().IsEqual(aNS->Label())) { + if (isNeedContextName && aData && aContextDataLab.IsEqual(aNS->Label())) { // do nothing because this context name will be added later in this method } else { aName = TCollection_AsciiString(anAttr->Get()).ToCString(); @@ -104,10 +141,10 @@ std::string Model_SelectionNaming::getShapeName( !aNS->Label().IsDescendant(aContextData->label())) { isNeedContextName = false; TDF_Label aNSDataLab = aNS->Label(); - while(aNSDataLab.Depth() != 7 && aNSDataLab.Depth() > 5) + if (aNSDataLab.Depth() % 2 == 0) aNSDataLab = aNSDataLab.Father(); ObjectPtr aNewContext = theDoc->objects()->object(aNSDataLab); - if (!aNewContext.get() && aNSDataLab.Depth() == 7) { + while(!aNewContext.get() && aNSDataLab.Depth() > 5) { aNSDataLab = aNSDataLab.Father().Father(); aNewContext = theDoc->objects()->object(aNSDataLab); } @@ -219,6 +256,78 @@ const TopoDS_Shape findCommonShape( return aSharedShape; } +// searches theType shape that contains theConnectionType sub-shapes in each shape from the List, +// so, implements the neighbours searching +/* +const TopoDS_Shape findCommonShapeByNB(const TopAbs_ShapeEnum theType, + const TopAbs_ShapeEnum theConnectionType, const TopTools_ListOfShape& theList) +{ +TopTools_MapOfShape aCheckedShapes; // already checked shapes of type theType + TopoDS_Shape aResult; // theType result shape + for(TopTools_ListIteratorOfListOfShape anIt(theList); anIt.More(); anIt.Next()) { // iterate all + for(TopExp_Explorer anExp(anIt.ChangeValue(), theType); anExp.More(); anExp.Next()) { + if (aCheckedShapes.Contains(anExp.Current())) + continue; // already checked + aCheckedShapes.Add(anExp.Current()); + TopTools_MapOfShape aConnectors; // all connectors of the checked theType shape + for(TopExp_Explorer aCExp(anExp.Current(), theConnectionType); aCExp.More(); aCExp.Next()) { + aConnectors.Add(aCExp.Current()); + } + // check that all shapes from the List contain the connector sub-shapes + bool aFound = true; + for(TopTools_ListIteratorOfListOfShape anIt2(theList); anIt2.More() && aFound; anIt2.Next()) { + if (anIt2.Value().IsSame(anIt.Value())) + continue; + aFound = false; + for(TopExp_Explorer anE(anIt2.ChangeValue(), theConnectionType); anE.More(); anE.Next()) { + if (aConnectors.Contains(anE.Current())) { + aFound = true; + break; + } + } + } + if (aFound) { + if (!aResult.IsNull()) // more than one result + return TopoDS_Shape(); + aResult = anExp.Current(); + } + } + } + return aResult; +}*/ + +std::string Model_SelectionNaming::vertexNameByEdges(TopoDS_Shape theContext, TopoDS_Shape theSub, + std::shared_ptr theDoc, ResultPtr& theContextRes, const bool theAnotherDoc) +{ + std::string aResult; + TopTools_IndexedDataMapOfShapeListOfShape aMap; + TopExp::MapShapesAndAncestors(theContext, TopAbs_VERTEX, TopAbs_EDGE, aMap); + const TopTools_ListOfShape& aList22 = aMap.FindFromKey(theSub); + if(aList22.Extent() >= 2) { // regular solution + TopTools_MapOfShape aFMap; + TopTools_ListOfShape aListE; + TopTools_ListIteratorOfListOfShape itl2(aList22); + for (int i = 1;itl2.More();itl2.Next(),i++) { + if(aFMap.Add(itl2.Value())) + aListE.Append(itl2.Value()); + } + TopTools_ListIteratorOfListOfShape itl(aListE); + for (int i = 1;itl.More();itl.Next(),i++) { + const TopoDS_Shape& anEdge = itl.Value(); + std::string anEdgeName = getShapeName(theDoc, anEdge, theContextRes, theAnotherDoc, false); + if (anEdgeName.empty()) { // edge is not in DS + aResult.clear(); + return aResult; + } + if(i == 1) + aResult = anEdgeName; + else + aResult += "&" + anEdgeName; + } + } + return aResult; +} + std::string Model_SelectionNaming::namingName(ResultPtr& theContext, std::shared_ptr theSubSh, const std::string& theDefaultName, const bool theAnotherDoc) @@ -288,7 +397,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, } } else break; - TopTools_ListOfShape aListOfNbs; + TopTools_MapOfShape aNbs; if(!isTrivialCase) { // find Neighbors TNaming_Localizer aLocalizer; TopTools_MapOfShape aMap3; @@ -302,25 +411,25 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, TopTools_ListIteratorOfListOfShape it2(aList); for(;it2.More();it2.Next()) { if(aSMap.Contains(it2.Value())) continue; // skip this Face - aListOfNbs.Append(it2.Value()); + aNbs.Add(it2.Value()); } } } // else a trivial case // build name of the sub-shape Edge - for(int i=1; i <= aSMap.Extent(); i++) { - const TopoDS_Shape& aFace = aSMap.FindKey(i); + // iterate faces of the context to get stable order, not map-order + TopTools_MapOfShape aStoredFaces; // to avoid duplicates + for(TopExp_Explorer aContExp(aContext, TopAbs_FACE); aContExp.More(); aContExp.Next()) { + const TopoDS_Shape& aFace = aContExp.Current(); + if (aStoredFaces.Contains(aFace) || !(aSMap.Contains(aFace) || aNbs.Contains(aFace))) + continue; + aStoredFaces.Add(aFace); std::string aFaceName = getShapeName(aDoc, aFace, theContext, theAnotherDoc, false); - if(i == 1) + if(aName.empty()) aName = aFaceName; else aName += "&" + aFaceName; } - TopTools_ListIteratorOfListOfShape itl(aListOfNbs); - for (;itl.More();itl.Next()) { - std::string aFaceName = getShapeName(aDoc, itl.Value(), theContext, theAnotherDoc, false); - aName += "&" + aFaceName; - } } break; @@ -355,40 +464,28 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, break; int n = aList.Extent(); bool isByFaces = n >= 3; + if (isByFaces) { // check that by faces vertex is identified uniquly (2317) + TopoDS_Shape aVertex = findCommonShape(TopAbs_VERTEX, aList); + isByFaces = !aVertex.IsNull() && aVertex.ShapeType() == TopAbs_VERTEX; + } + if(!isByFaces) { // open topology case or Compound case => via edges - TopTools_IndexedDataMapOfShapeListOfShape aMap; - TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap); - const TopTools_ListOfShape& aList22 = aMap.FindFromKey(aSubShape); - if(aList22.Extent() >= 2) { // regular solution - - // bug! duplication; fix is below - aFMap.Clear(); - TopTools_ListOfShape aListE; - TopTools_ListIteratorOfListOfShape itl2(aList22); - for (int i = 1;itl2.More();itl2.Next(),i++) { - if(aFMap.Add(itl2.Value())) - aListE.Append(itl2.Value()); - } - n = aListE.Extent(); - TopTools_ListIteratorOfListOfShape itl(aListE); - for (int i = 1;itl.More();itl.Next(),i++) { - const TopoDS_Shape& anEdge = itl.Value(); - std::string anEdgeName = getShapeName(aDoc, anEdge, theContext, theAnotherDoc, false); - if (anEdgeName.empty()) { // edge is not in DS, trying by faces anyway - isByFaces = true; - aName.clear(); - break; + aName = vertexNameByEdges(aContext, aSubShape, aDoc, theContext, theAnotherDoc); + isByFaces = aName.empty(); + if (isByFaces) { // try to find a vertex in sketch faces + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(theContext); + if (aConstr.get() && aConstr->facesNum()) { + for(int aFace = aConstr->facesNum() - 1; isByFaces && aFace >= 0; aFace--) { + std::shared_ptr aGFace = aConstr->face(aFace); + aName = vertexNameByEdges(aGFace->impl(), aSubShape, + aDoc, theContext, theAnotherDoc); + isByFaces = aName.empty(); } - if(i == 1) - aName = anEdgeName; - else - aName += "&" + anEdgeName; } - }//reg - else { // dangle vertex: if(aList22.Extent() == 1) - //it should be already in DF } } + if (isByFaces) { TopTools_ListIteratorOfListOfShape itl(aList); for (int i = 1;itl.More();itl.Next(),i++) { @@ -404,7 +501,6 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, break; } } - return aName; } @@ -844,16 +940,28 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, aFaceContext = aDoc->findByName(aContName, *it, anUniqueContext); } } - const TopoDS_Shape aFace = findFaceByName(*it, aDoc, aFaceContext, anUniqueContext); + TopoDS_Shape aFace = findFaceByName(*it, aDoc, aFaceContext, anUniqueContext); + if (aFace.IsNull() && aFaceContext.get() && + aFaceContext->groupName() == ModelAPI_ResultConstruction::group() ) { + // search the construction sub-elements for the intersection if they are in the tree + size_t aSlash = it->find("/"); + if (aSlash != std::string::npos) { + std::string aSubShapeName = it->substr(aSlash + 1); + aFace = findFaceByName(aSubShapeName, aDoc, aFaceContext, true); + } + } if(!aFace.IsNull()) aList.Append(aFace); } aSelection = findCommonShape(aType, aList); + //if (aSelection.IsNull() && aType == TopAbs_EDGE) { // try to find selection by neighbours + // aSelection = findCommonShapeByNB(aType, TopAbs_VERTEX, aList); + //} } } // in case of construction, there is no registered names for all sub-elements, // even for the main element; so, trying to find them by name (without "&" intersections) - if (aN < 2) { + if (aSelection.IsNull() && aN < 2) { size_t aConstrNamePos = aSubShapeName.find("/"); bool isFullName = aConstrNamePos == std::string::npos; std::string anEmpty, aContrName = aContName; @@ -1008,6 +1116,21 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, } } } + } else if (aSelection.IsNull() && aN >= 2 && aType == TopAbs_VERTEX) { + // support of shape name as intersection separated by "&" + static std::string anEdgeType = "edge"; // for now it works only with su-edges + std::list::iterator aSubNames = aListofNames.begin(); + TopTools_ListOfShape aSubsList; + for(; aSubNames != aListofNames.end(); aSubNames++) { + std::string aSubName = *aSubNames; + std::shared_ptr aSubShapeFound; + std::shared_ptr aContextFound; + if (selectSubShape(anEdgeType, aSubName, theDoc, aSubShapeFound, aContextFound)) { + if (aSubShapeFound.get()) + aSubsList.Append(aSubShapeFound->impl()); + } + } + aSelection = findCommonShape(TopAbs_VERTEX, aSubsList); } if (!aSelection.IsNull()) { // Select it (must be after N=0 checking,