X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSelector%2FSelector_Selector.cpp;h=b0cc3a1f5e66309e641b3f5e1a2e2d52f13740de;hb=4e677bdcfd9ebe4b467a1cc4cc274bcfbe5fb8ca;hp=f59226cc92520b3c2279151b4cc996487fb3ff03;hpb=2da91de2a9adef6b5bc5c94f840831f33334e0cb;p=modules%2Fshaper.git diff --git a/src/Selector/Selector_Selector.cpp b/src/Selector/Selector_Selector.cpp index f59226cc9..b0cc3a1f5 100644 --- a/src/Selector/Selector_Selector.cpp +++ b/src/Selector/Selector_Selector.cpp @@ -26,7 +26,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -34,15 +37,17 @@ #include #include #include +#include #include #include #include #include +#include #include -/// type of the selection, integerm keeps the Selector_Type value +/// type of the selection, integer keeps the Selector_Type value static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6"); /// type of the shape, stored in case it is intersection or container static const Standard_GUID kSHAPE_TYPE("864b3267-cb9d-4107-bf58-c3ce1775b171"); @@ -53,6 +58,14 @@ static const Standard_GUID kBASE_ARRAY("7c515b1a-9549-493d-9946-a4933a22f45f"); static const Standard_GUID kLEVELS_ARRAY("ee4c4b45-e859-4e86-aa4f-6eac68e0ca1f"); // weak index (integer) of the sub-shape static const Standard_GUID kWEAK_INDEX("e9373a61-cabc-4ee8-aabf-aea47c62ed87"); +// geometrical naming indicator +static const Standard_GUID kGEOMETRICAL_NAMING("a5322d02-50fb-43ed-9255-75c7b93f6657"); + +// string identifier of the weak name in modification or intersection types of algorithm +static const std::string kWEAK_NAME_IDENTIFIER = "weak_name_"; +// string identifier of the pure weak name algorithm +static const std::string kPUREWEAK_NAME_IDENTIFIER = "_weak_name_"; + Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab) { @@ -64,37 +77,54 @@ TDF_Label Selector_Selector::label() return myLab; } +void Selector_Selector::setBaseDocument(const TDF_Label theAccess) +{ + myBaseDocumentLab = theAccess; +} + // adds to theResult all labels that contain initial shapes for theValue located in theFinal -static void findBases(Handle(TNaming_NamedShape) theFinal, const TopoDS_Shape& theValue, - bool aMustBeAtFinal, TDF_LabelList& theResult) +static void findBases(TDF_Label theAccess, Handle(TNaming_NamedShape) theFinal, + const TopoDS_Shape& theValue, + bool aMustBeAtFinal, const TDF_Label& theAdditionalDocument, TDF_LabelList& theResult) { - TNaming_SameShapeIterator aLabIter(theValue, theFinal->Label()); + bool aFoundAnyShape = false; + TNaming_SameShapeIterator aLabIter(theValue, theAccess); for(; aLabIter.More(); aLabIter.Next()) { Handle(TNaming_NamedShape) aNS; - aLabIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS); - if (aMustBeAtFinal && aNS != theFinal) - continue; // looking for old at the same final label only - TNaming_Evolution anEvolution = aNS->Evolution(); - if (anEvolution == TNaming_PRIMITIVE) { - // check that this is not in the results already - const TDF_Label aResult = aNS->Label(); - TDF_LabelList::Iterator aResIter(theResult); - for(; aResIter.More(); aResIter.Next()) { - if (aResIter.Value().IsEqual(aResult)) - break; + if (aLabIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + if (aMustBeAtFinal && aNS != theFinal) + continue; // looking for old at the same final label only + TNaming_Evolution anEvolution = aNS->Evolution(); + if (anEvolution == TNaming_PRIMITIVE) { + // check that this is not in the results already + const TDF_Label aResult = aNS->Label(); + TDF_LabelList::Iterator aResIter(theResult); + for(; aResIter.More(); aResIter.Next()) { + if (aResIter.Value().IsEqual(aResult)) + break; + } + if (!aResIter.More()) // not found, so add this new + theResult.Append(aResult); + aFoundAnyShape = true; } - if (!aResIter.More()) // not found, so add this new - theResult.Append(aResult); - } - if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) { - for(TNaming_Iterator aThisIter(aNS); aThisIter.More(); aThisIter.Next()) { - if (aThisIter.NewShape().IsSame(theValue)) { - // continue recursively, null NS means that any NS are ok - findBases(theFinal, aThisIter.OldShape(), false, theResult); + if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) { + for(TNaming_Iterator aThisIter(aNS); aThisIter.More(); aThisIter.Next()) { + if (aThisIter.NewShape().IsSame(theValue)) { + // continue recursively, null NS means that any NS are ok + findBases(theAccess, theFinal, aThisIter.OldShape(), + false, theAdditionalDocument, theResult); + aFoundAnyShape = true; + } } } } } + if (!aFoundAnyShape && !theAdditionalDocument.IsNull()) { // try to find in additional document + static TDF_Label anEmpty; + if (TNaming_Tool::HasLabel(theAdditionalDocument, theValue)) + findBases(theAdditionalDocument, Handle(TNaming_NamedShape)(), theValue, + false, anEmpty, theResult); + } } // returns the sub-shapes of theSubType which belong to all theShapes (so, common or intersection) @@ -165,9 +195,33 @@ static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theV } } +/// Returns true if the given shapes are based on the same geometry +static bool sameGeometry(const TopoDS_Shape theShape1, const TopoDS_Shape theShape2) { + if (!theShape1.IsNull() && !theShape2.IsNull() && theShape1.ShapeType() == theShape2.ShapeType()) + { + if (theShape1.ShapeType() == TopAbs_FACE) { // check surfaces + TopLoc_Location aLoc1, aLoc2; + TopoDS_Face aFace1 = TopoDS::Face(theShape1); + Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(aFace1, aLoc1); + TopoDS_Face aFace2 = TopoDS::Face(theShape2); + Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(aFace2, aLoc2); + return aSurf1 == aSurf2 && aLoc1.IsEqual(aLoc2); + } else if (theShape1.ShapeType() == TopAbs_FACE) { // check curves + TopLoc_Location aLoc1, aLoc2; + Standard_Real aFirst, aLast; + TopoDS_Edge anEdge1 = TopoDS::Edge(theShape1); + Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aLoc1, aFirst, aLast); + TopoDS_Edge anEdge2 = TopoDS::Edge(theShape2); + Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(anEdge2, aLoc2, aFirst, aLast); + return aCurve1 == aCurve2 && aLoc1.IsEqual(aLoc2); + } + } + return false; +} + /// Searches the neighbor shape by neighbors defined in theNB in theContext shape static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext, - const std::list >& theNB) + const std::list >& theNB, const bool theGeometrical) { // searching for neighbors with minimum level int aMinLevel = 0; @@ -206,6 +260,7 @@ static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext, return TopoDS_Shape(); // not found any candidate if (aMatches.Extent() == 1) return aMatches.First(); // already found good candidate + TopoDS_Compound aResultCompound; // in case of geometrical name and many candidates // iterate all matches to find by other (higher level) neighbors the best candidate TopoDS_Shape aGoodCandidate; for(TopoDS_ListOfShape::Iterator aCandidate(aMatches); aCandidate.More(); aCandidate.Next()) { @@ -222,8 +277,16 @@ static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext, if (!aFooundHigherLevel && aLevelNBs.IsEmpty()) { // iterated all, so, good candidate if (aGoodCandidate.IsNull()) { aGoodCandidate = aCandidate.Value(); - } else { // too many good candidates - return TopoDS_Shape(); + } else { // another good candidate + if (theGeometrical && sameGeometry(aGoodCandidate, aCandidate.Value())) { + static TopoDS_Builder aBuilder; + if (aResultCompound.IsNull()) { + aBuilder.MakeCompound(aResultCompound); + aBuilder.Add(aResultCompound, aGoodCandidate); + } + aBuilder.Add(aResultCompound, aCandidate.Value()); + } else + return TopoDS_Shape(); } } if (!aLevelNBs.IsEmpty()) { @@ -241,18 +304,21 @@ static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext, break; } } + if (!aResultCompound.IsNull()) + return aResultCompound; return aGoodCandidate; } bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue, - const bool theUseNeighbors) + const bool theGeometricalNaming, const bool theUseNeighbors, const bool theUseIntersections) { if (theValue.IsNull() || theContext.IsNull()) return false; + myGeometricalNaming = theGeometricalNaming; // check the value shape can be named as it is, or it is needed to construct it from the // higher level shapes (like a box vertex by faces that form this vertex) bool aIsFound = TNaming_Tool::HasLabel(myLab, theValue); - if (aIsFound) { // additional check for selection and delete evolution only: also could not be used + if (aIsFound) { // additional check for selection and delete evolution only: also could not use aIsFound = false; for(TNaming_SameShapeIterator aShapes(theValue, myLab); aShapes.More(); aShapes.Next()) { @@ -266,6 +332,23 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape } } } + // searching in the base document + if (!aIsFound && !myBaseDocumentLab.IsNull() && + TNaming_Tool::HasLabel(myBaseDocumentLab, theValue)) + { + TNaming_SameShapeIterator aShapes(theValue, myBaseDocumentLab); + for(; aShapes.More(); aShapes.Next()) + { + Handle(TNaming_NamedShape) aNS; + if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED || + aNS->Evolution() == TNaming_PRIMITIVE) { + aIsFound = true; + break; + } + } + } + } if (!aIsFound) { TopAbs_ShapeEnum aSelectionType = theValue.ShapeType(); myShapeType = aSelectionType; @@ -273,7 +356,8 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape aSelectionType == TopAbs_SHELL || aSelectionType == TopAbs_WIRE) { // iterate all sub-shapes and select them on sublabels for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) { - if (!selectBySubSelector(theContext, aSubIter.Value())) { + if (!selectBySubSelector(theContext, aSubIter.Value(), + theGeometricalNaming, theUseNeighbors, theUseIntersections)) { return false; // if some selector is failed, everything is failed } } @@ -284,8 +368,8 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape // try to find the shape of the higher level type in the context shape bool aFacesTried = false; // for identification of vertices, faces are tried, then edges TopoDS_ListOfShape aLastCommon; // to store the commons not good, but may be used for weak - TopTools_MapOfShape aLastIntersectors; - while(aSelectionType != TopAbs_FACE || !aFacesTried) { + TopoDS_ListOfShape aLastIntersectors; + while(theUseIntersections && (aSelectionType != TopAbs_FACE || !aFacesTried)) { if (aSelectionType == TopAbs_FACE) { if (theValue.ShapeType() != TopAbs_VERTEX) break; @@ -296,6 +380,9 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape TopTools_MapOfShape anIntersectors; // shapes of aSelectionType that contain theValue TopoDS_ListOfShape anIntList; // same as anIntersectors for(TopExp_Explorer aSelExp(theContext, aSelectionType); aSelExp.More(); aSelExp.Next()) { + if (aSelectionType == TopAbs_EDGE && + BRep_Tool::Degenerated(TopoDS::Edge(aSelExp.Current()))) + continue; TopExp_Explorer aSubExp(aSelExp.Current(), theValue.ShapeType()); for(; aSubExp.More(); aSubExp.Next()) { if (aSubExp.Current().IsSame(theValue)) { @@ -311,9 +398,10 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape if (aCommon.Extent() == 1 && aCommon.First().IsSame(theValue)) { // name the intersectors mySubSelList.clear(); - TopTools_MapOfShape::Iterator anInt(anIntersectors); + TopoDS_ListOfShape::Iterator anInt(anIntList); for (; anInt.More(); anInt.Next()) { - if (!selectBySubSelector(theContext, anInt.Value())) { + if (!selectBySubSelector(theContext, anInt.Value(), + theGeometricalNaming, theUseNeighbors, false)) { break; // if some selector is failed, stop and search another solution } } @@ -323,14 +411,14 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape } } else if (aCommon.Extent() > 1 && aLastCommon.IsEmpty()) { aLastCommon = aCommon; - aLastIntersectors = anIntersectors; + aLastIntersectors = anIntList; } } if (!theUseNeighbors) return false; - // searching by neighbours + // searching by neighbors std::list > aNBs; /// neighbor sub-shape -> level of neighborhood for(int aLevel = 1; true; aLevel++) { TopTools_MapOfShape aNewNB; @@ -338,20 +426,26 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration break; } - // check which can be named correctly, without by neighbors type - for(TopTools_MapOfShape::Iterator aNBIter(aNewNB); aNBIter.More(); ) { - Selector_Selector aSelector(myLab.FindChild(1)); - if (aSelector.select(theContext, aNBIter.Value(), false)) { // add to the list of good NBs - aNBs.push_back(std::pair(aNBIter.Value(), aLevel)); + // iterate by the order in theContext to keep same naming names + TopExp_Explorer anOrder(theContext, theValue.ShapeType()); + for (; anOrder.More(); anOrder.Next()) { + if (aNewNB.Contains(anOrder.Current())) { + TopoDS_Shape aNewNBShape = anOrder.Current(); + // check which can be named correctly, without "by neighbors" type + Selector_Selector aSelector(myLab.FindChild(1)); + aSelector.setBaseDocument(myBaseDocumentLab); + if (aSelector.select(theContext, aNewNBShape, theGeometricalNaming, false, false)) { + // add to list of good NBs + aNBs.push_back(std::pair(aNewNBShape, aLevel)); + } } - aNewNB.Remove(aNBIter.Key()); - aNBIter.Initialize(aNewNB); } - TopoDS_Shape aResult = findNeighbor(theContext, aNBs); + TopoDS_Shape aResult = findNeighbor(theContext, aNBs, theGeometricalNaming); if (!aResult.IsNull() && aResult.IsSame(theValue)) { std::list >::iterator aNBIter = aNBs.begin(); for(; aNBIter != aNBs.end(); aNBIter++) { - if (!selectBySubSelector(theContext, aNBIter->first, false)) { + if (!selectBySubSelector(theContext, aNBIter->first, + theGeometricalNaming, false, false)) { return false; // something is wrong because before this selection was ok } myNBLevel.push_back(aNBIter->second); @@ -369,9 +463,10 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape if (myWeakIndex != -1) { // name the intersectors mySubSelList.clear(); - TopTools_MapOfShape::Iterator anInt(aLastIntersectors); + TopoDS_ListOfShape::Iterator anInt(aLastIntersectors); for (; anInt.More(); anInt.Next()) { - if (!selectBySubSelector(theContext, anInt.Value())) { + if (!selectBySubSelector(theContext, anInt.Value(), + theGeometricalNaming, theUseNeighbors, theUseIntersections)) { break; // if some selector is failed, stop and search another solution } } @@ -382,34 +477,36 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape } } - // pure weak naming - myType = SELTYPE_WEAK_NAMING; - Selector_NExplode aNexp(theContext, theValue.ShapeType()); - myWeakIndex = aNexp.index(theValue); - if (myWeakIndex != -1) { - myShapeType = theValue.ShapeType(); - // searching for context shape label to store in myFinal - myFinal.Nullify(); - if (TNaming_Tool::HasLabel(myLab, theContext)) { - for(TNaming_SameShapeIterator aShapes(theContext, myLab); aShapes.More(); aShapes.Next()) - { - Handle(TNaming_NamedShape) aNS; - if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { - TNaming_Evolution anEvolution = aNS->Evolution(); - if (anEvolution == TNaming_PRIMITIVE || anEvolution == TNaming_GENERATED || - anEvolution == TNaming_MODIFY) { - // check this is a new shape - for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) { - if (aNSIter.NewShape().IsSame(theContext)) { - myFinal = aNS->Label(); - break; + // pure weak naming: there is no sense to use pure weak naming for neighbors selection + if (theUseNeighbors) { + myType = SELTYPE_WEAK_NAMING; + Selector_NExplode aNexp(theContext, theValue.ShapeType()); + myWeakIndex = aNexp.index(theValue); + if (myWeakIndex != -1) { + myShapeType = theValue.ShapeType(); + // searching for context shape label to store in myFinal + myFinal.Nullify(); + if (TNaming_Tool::HasLabel(myLab, theContext)) { + for(TNaming_SameShapeIterator aShapes(theContext, myLab); aShapes.More(); aShapes.Next()) + { + Handle(TNaming_NamedShape) aNS; + if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + TNaming_Evolution anEvolution = aNS->Evolution(); + if (anEvolution == TNaming_PRIMITIVE || anEvolution == TNaming_GENERATED || + anEvolution == TNaming_MODIFY) { + // check this is a new shape + for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) { + if (aNSIter.NewShape().IsSame(theContext)) { + myFinal = aNS->Label(); + break; + } } } } } } + return true; // could be final empty (in case it is called recursively) or not } - return true; // could be final empty (in case it is called recursively) or not } return false; @@ -417,22 +514,27 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape // searching for the base shapes of the value Handle(TNaming_NamedShape) aPrimitiveNS; NCollection_List aModifList; - for(TNaming_SameShapeIterator aShapes(theValue, myLab); aShapes.More(); aShapes.Next()) - { - Handle(TNaming_NamedShape) aNS; - if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { - TNaming_Evolution anEvolution = aNS->Evolution(); - if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as PRIMITIVE - aPrimitiveNS = aNS; - break; - } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) { - // check this is a new shape - TNaming_Iterator aNSIter(aNS); - for(; aNSIter.More(); aNSIter.Next()) - if (aNSIter.NewShape().IsSame(theValue)) - break; - if (aNSIter.More()) // new was found - aModifList.Append(aNS); + for(int aUseExternal = 0; aUseExternal < 2; aUseExternal++) { + TDF_Label aLab = aUseExternal == 0 ? myLab : myBaseDocumentLab; + if (aLab.IsNull() || !TNaming_Tool::HasLabel(aLab, theValue)) + continue; + for(TNaming_SameShapeIterator aShapes(theValue, aLab); aShapes.More(); aShapes.Next()) + { + Handle(TNaming_NamedShape) aNS; + if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + TNaming_Evolution anEvolution = aNS->Evolution(); + if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as PRIMITIVE + aPrimitiveNS = aNS; + break; + } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) { + // check this is a new shape + TNaming_Iterator aNSIter(aNS); + for(; aNSIter.More(); aNSIter.Next()) + if (aNSIter.NewShape().IsSame(theValue)) + break; + if (aNSIter.More()) // new was found + aModifList.Append(aNS); + } } } } @@ -466,38 +568,45 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape if (!aModifList.IsEmpty()) { // searching for all the base shapes of this modification - findBases(aModifList.First(), theValue, true, myBases); + findBases(myLab, aModifList.First(), theValue, true, myBaseDocumentLab, myBases); if (!myBases.IsEmpty()) { myFinal = aModifList.First()->Label(); TopoDS_ListOfShape aCommon; findModificationResult(aCommon); - // trying to search by neighbours + // trying to search by neighbors if (aCommon.Extent() > 1) { // more complicated selection if (!theUseNeighbors) return false; - // searching by neighbours - std::list > aNBs; /// neighbor sub-shape -> level of neighborhood + // searching by neighbors + std::list > aNBs;//neighbor sub-shape -> level of neighborhood for(int aLevel = 1; true; aLevel++) { TopTools_MapOfShape aNewNB; findNeighbors(theContext, theValue, aLevel, aNewNB); if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration break; } - // check which can be named correctly, without by neighbors type - for(TopTools_MapOfShape::Iterator aNBIter(aNewNB); aNBIter.More(); ) { - Selector_Selector aSelector(myLab.FindChild(1)); - if (aSelector.select(theContext, aNBIter.Value(), false)) { // add to the list of good NBs - aNBs.push_back(std::pair(aNBIter.Value(), aLevel)); + // iterate by the order in theContext to keep same naming names + TopExp_Explorer anOrder(theContext, theValue.ShapeType()); + for (; anOrder.More(); anOrder.Next()) { + if (aNewNB.Contains(anOrder.Current())) { + TopoDS_Shape aNewNBShape = anOrder.Current(); + // check which can be named correctly, without "by neighbors" type + Selector_Selector aSelector(myLab.FindChild(1)); + if (!myBaseDocumentLab.IsNull()) + aSelector.setBaseDocument(myBaseDocumentLab); + if (aSelector.select(theContext, aNewNBShape, theGeometricalNaming, false)) { + // add to list of good NBs + aNBs.push_back(std::pair(aNewNBShape, aLevel)); + } } - aNewNB.Remove(aNBIter.Key()); - aNBIter.Initialize(aNewNB); } - TopoDS_Shape aResult = findNeighbor(theContext, aNBs); + TopoDS_Shape aResult = findNeighbor(theContext, aNBs, theGeometricalNaming); if (!aResult.IsNull() && aResult.IsSame(theValue)) { std::list >::iterator aNBIter = aNBs.begin(); for(; aNBIter != aNBs.end(); aNBIter++) { - if (!selectBySubSelector(theContext, aNBIter->first)) { + if (!selectBySubSelector(theContext, aNBIter->first, + theGeometricalNaming, theUseNeighbors, theUseIntersections)) { return false; // something is wrong because before this selection was ok } myNBLevel.push_back(aNBIter->second); @@ -507,7 +616,7 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape return true; } } - // filter by neighbours did not help + // filter by neighbors did not help if (aCommon.Extent() > 1) { // weak naming between the common results Selector_NExplode aNexp(aCommon); myWeakIndex = aNexp.index(theValue); @@ -521,11 +630,12 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape TopoDS_ListOfShape aCommon; myFinal = aModifList.First()->Label(); Handle(TNaming_NamedShape) aNS; - myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS); - for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) { - const TopoDS_Shape& aNewShape = aFinalIter.NewShape(); - if (!aNewShape.IsNull()) - aCommon.Append(aNewShape); + if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) { + const TopoDS_Shape& aNewShape = aFinalIter.NewShape(); + if (!aNewShape.IsNull()) + aCommon.Append(aNewShape); + } } Selector_NExplode aNexp(aCommon); myWeakIndex = aNexp.index(theValue); @@ -543,6 +653,8 @@ void Selector_Selector::store() { myLab.ForgetAllAttributes(true); // remove old naming data TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType); + if (myGeometricalNaming) + TDataStd_UAttribute::Set(myLab, kGEOMETRICAL_NAMING); switch(myType) { case SELTYPE_CONTAINER: case SELTYPE_INTERSECT: { @@ -614,6 +726,7 @@ bool Selector_Selector::restore() Handle(TDataStd_Integer) aTypeAttr; if (!myLab.FindAttribute(kSEL_TYPE, aTypeAttr)) return false; + myGeometricalNaming = myLab.IsAttribute(kGEOMETRICAL_NAMING); myType = Selector_Type(aTypeAttr->Get()); switch(myType) { case SELTYPE_CONTAINER: @@ -627,6 +740,7 @@ bool Selector_Selector::restore() mySubSelList.clear(); for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) { mySubSelList.push_back(Selector_Selector(aSub.Value()->Label())); + mySubSelList.back().setBaseDocument(myBaseDocumentLab); if (!mySubSelList.back().restore()) aSubResult = false; } @@ -670,6 +784,7 @@ bool Selector_Selector::restore() mySubSelList.clear(); for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) { mySubSelList.push_back(Selector_Selector(aSub.Value()->Label())); + mySubSelList.back().setBaseDocument(myBaseDocumentLab); if (!mySubSelList.back().restore()) aSubResult = false; } @@ -704,26 +819,39 @@ bool Selector_Selector::restore() } /// Returns in theResults all shapes with history started in theBase and ended in theFinal -static void findFinals(const TopoDS_Shape& theBase, const TDF_Label& theFinal, - TopTools_MapOfShape& theResults) +static void findFinals(const TDF_Label& anAccess, const TopoDS_Shape& theBase, + const TDF_Label& theFinal, + const TDF_Label& theAdditionalDoc, TopTools_MapOfShape& theResults) { - for(TNaming_NewShapeIterator aBaseIter(theBase, theFinal); aBaseIter.More(); aBaseIter.Next()) { - TNaming_Evolution anEvolution = aBaseIter.NamedShape()->Evolution(); - if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) { - if (aBaseIter.NamedShape()->Label().IsEqual(theFinal)) { - theResults.Add(aBaseIter.Shape()); - } else { - findFinals(aBaseIter.Shape(), theFinal, theResults); + if (TNaming_Tool::HasLabel(anAccess, theBase)) { + for(TNaming_NewShapeIterator aBaseIter(theBase, anAccess); aBaseIter.More(); aBaseIter.Next()) + { + TNaming_Evolution anEvolution = aBaseIter.NamedShape()->Evolution(); + if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) { + if (aBaseIter.NamedShape()->Label().IsEqual(theFinal)) { + theResults.Add(aBaseIter.Shape()); + } else { + findFinals(anAccess, aBaseIter.Shape(), theFinal, theAdditionalDoc, theResults); + } } } } + if (!theAdditionalDoc.IsNull()) { // search additionally by the additional access label + static TDF_Label anEmpty; + findFinals(theAdditionalDoc, theBase, theFinal, anEmpty, theResults); + } } void Selector_Selector::findModificationResult(TopoDS_ListOfShape& theCommon) { for(TDF_LabelList::Iterator aBase(myBases); aBase.More(); aBase.Next()) { + TDF_Label anAdditionalDoc; // this document if base is started in extra document + if (aBase.Value().Root() != myLab.Root()) { + anAdditionalDoc = myLab; + } TopTools_MapOfShape aFinals; - for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next()) - findFinals(aBaseShape.NewShape(), myFinal, aFinals); + for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next()) { + findFinals(aBase.Value(), aBaseShape.NewShape(), myFinal, anAdditionalDoc, aFinals); + } if (!aFinals.IsEmpty()) { if (theCommon.IsEmpty()) { // just copy all to common for(TopTools_MapOfShape::Iterator aFinal(aFinals); aFinal.More(); aFinal.Next()) { @@ -814,25 +942,43 @@ bool Selector_Selector::solve(const TopoDS_Shape& theContext) break; } case SELTYPE_MODIFICATION: { - if (myBases.IsEmpty() && myWeakIndex) { // weak name by the final shapes index + if (myBases.IsEmpty() && myWeakIndex > 0) { // weak name by the final shapes index TopoDS_ListOfShape aCommon; Handle(TNaming_NamedShape) aNS; - myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS); - for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) { - const TopoDS_Shape& aNewShape = aFinalIter.NewShape(); - if (!aNewShape.IsNull()) - aCommon.Append(aNewShape); + if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) { + const TopoDS_Shape& aNewShape = aFinalIter.NewShape(); + if (!aNewShape.IsNull()) + aCommon.Append(aNewShape); + } } Selector_NExplode aNexp(aCommon); aResult = aNexp.shape(myWeakIndex); } else { // standard case TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases findModificationResult(aFinalsCommon); - if (aFinalsCommon.Extent() == 1) // only in this case result is valid: found only one shape + if (aFinalsCommon.Extent() == 1) { // result is valid: found only one shape aResult = aFinalsCommon.First(); - else if (aFinalsCommon.Extent() > 1 && myWeakIndex) { + } else if (aFinalsCommon.Extent() > 1 && myWeakIndex > 0) { Selector_NExplode aNExp(aFinalsCommon); aResult = aNExp.shape(myWeakIndex); + } else if (aFinalsCommon.Extent() > 1 && myGeometricalNaming) {// if same geometry - compound + TopoDS_ListOfShape::Iterator aCommonIter(aFinalsCommon); + TopoDS_Shape aFirst = aCommonIter.Value(); + for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) { + if (!sameGeometry(aFirst, aCommonIter.Value())) + break; + } + if (!aCommonIter.More()) { // all geometry is same, create a result compound + TopoDS_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound(aCompound); + for(aCommonIter.Initialize(aFinalsCommon); aCommonIter.More(); aCommonIter.Next()) { + aBuilder.Add(aCompound, aCommonIter.Value()); + } + aResult = aCompound; + } + } } break; @@ -847,7 +993,7 @@ bool Selector_Selector::solve(const TopoDS_Shape& theContext) } aNBs.push_back(std::pair(aSubSel->value(), *aLevel)); } - aResult = findNeighbor(theContext, aNBs); + aResult = findNeighbor(theContext, aNBs, myGeometricalNaming); break; } case SELTYPE_WEAK_NAMING: { @@ -885,9 +1031,6 @@ TopoDS_Shape Selector_Selector::value() return TopoDS_Shape(); // empty, error shape } -static const std::string kWEAK_NAME_IDENTIFIER = "weak_name_"; -static const std::string kPUREWEAK_NAME_IDENTIFIER = "_weak_name_"; - std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { switch(myType) { case SELTYPE_CONTAINER: @@ -899,6 +1042,23 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { aResult += '['; aResult += aSubSel->name(theNameGenerator); aResult += ']'; + TopoDS_Shape aSubVal = aSubSel->value(); + if (!aSubVal.IsNull()) { + TopAbs_ShapeEnum aSubType = aSubVal.ShapeType(); + if (aSubType != TopAbs_FACE) { // in case the sub shape type must be stored + switch(aSubType) { + case TopAbs_COMPOUND: aResult += "c"; break; + case TopAbs_COMPSOLID: aResult += "o"; break; + case TopAbs_SOLID: aResult += "s"; break; + case TopAbs_SHELL: aResult += "h"; break; + case TopAbs_WIRE: aResult += "w"; break; + case TopAbs_EDGE: aResult += "e"; break; + case TopAbs_VERTEX: aResult += "v"; break; + default: + ; + } + } + } } if (myWeakIndex != -1) { std::ostringstream aWeakStr; @@ -943,8 +1103,11 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { std::list::iterator aSubSel = mySubSelList.begin(); for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) { aResult += "(" + aSubSel->name(theNameGenerator) + ")"; - if (*aLevel > 1) - aResult += *aLevel; + if (*aLevel > 1) { + std::ostringstream aLevelStr; + aLevelStr<<*aLevel; + aResult += aLevelStr.str(); + } } return aResult; } @@ -965,8 +1128,9 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { TDF_Label Selector_Selector::restoreByName( std::string theName, const TopAbs_ShapeEnum theShapeType, - Selector_NameGenerator* theNameGenerator) + Selector_NameGenerator* theNameGenerator, const bool theGeometricalNaming) { + myGeometricalNaming = theGeometricalNaming; if (theName[0] == '[') { // intersection or container switch(theShapeType) { case TopAbs_COMPOUND: @@ -995,9 +1159,26 @@ TDF_Label Selector_Selector::restoreByName( myWeakIndex = atoi(aWeakIndex.c_str()); continue; } + TopAbs_ShapeEnum aSubShapeType = TopAbs_FACE; + if (anEndPos != std::string::npos && anEndPos + 1 < theName.size()) { + char aShapeChar = theName[anEndPos + 1]; + if (theName[anEndPos + 1] != '[') { + switch(aShapeChar) { + case 'c': aSubShapeType = TopAbs_COMPOUND; break; + case 'o': aSubShapeType = TopAbs_COMPSOLID; break; + case 's': aSubShapeType = TopAbs_SOLID; break; + case 'h': aSubShapeType = TopAbs_SHELL; break; + case 'w': aSubShapeType = TopAbs_WIRE; break; + case 'e': aSubShapeType = TopAbs_EDGE; break; + case 'v': aSubShapeType = TopAbs_VERTEX; break; + default:; + } + } + } mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1))); - TDF_Label aSubContext = - mySubSelList.back().restoreByName(aSubStr, theShapeType, theNameGenerator); + mySubSelList.back().setBaseDocument(myBaseDocumentLab); + TDF_Label aSubContext = mySubSelList.back().restoreByName( + aSubStr, aSubShapeType, theNameGenerator, theGeometricalNaming); if (aSubContext.IsNull()) return aSubContext; // invalid sub-selection parsing if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) { @@ -1010,7 +1191,7 @@ TDF_Label Selector_Selector::restoreByName( return TDF_Label(); // invalid parentheses } return aContext; - } else if (theName[0] == '(') { // filter by neighbours + } else if (theName[0] == '(') { // filter by neighbors myType = SELTYPE_FILTER_BY_NEIGHBOR; TDF_Label aContext; for(size_t aStart = 0; aStart != std::string::npos; @@ -1019,8 +1200,9 @@ TDF_Label Selector_Selector::restoreByName( if (anEndPos != std::string::npos) { std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1); mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1))); - TDF_Label aSubContext = - mySubSelList.back().restoreByName(aSubStr, theShapeType, theNameGenerator); + mySubSelList.back().setBaseDocument(myBaseDocumentLab); + TDF_Label aSubContext = mySubSelList.back().restoreByName( + aSubStr, theShapeType, theNameGenerator, theGeometricalNaming); if (aSubContext.IsNull()) return aSubContext; // invalid sub-selection parsing if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) { @@ -1029,6 +1211,9 @@ TDF_Label Selector_Selector::restoreByName( } else { aContext = aSubContext; } + if (!aContext.IsNull()) // for filters by neighbor the latest context shape is vital + aContext = theNameGenerator->newestContext(aContext); + // searching for the level index std::string aLevel; for(anEndPos++; anEndPos != std::string::npos && @@ -1061,7 +1246,7 @@ TDF_Label Selector_Selector::restoreByName( theNameGenerator->restoreContext(aContextName, aContext, myFinal); } return aContext; - } else if (theName.find('&') == std::string::npos) { // wihtout '&' it can be only primitive + } else if (theName.find('&') == std::string::npos) { // without '&' it can be only primitive myType = SELTYPE_PRIMITIVE; TDF_Label aContext; if (theNameGenerator->restoreContext(theName, aContext, myFinal)) { @@ -1098,11 +1283,15 @@ TDF_Label Selector_Selector::restoreByName( return TDF_Label(); } -bool Selector_Selector::selectBySubSelector( - const TopoDS_Shape theContext, const TopoDS_Shape theValue, const bool theUseNeighbors) +bool Selector_Selector::selectBySubSelector(const TopoDS_Shape theContext, + const TopoDS_Shape theValue, const bool theGeometricalNaming, + const bool theUseNeighbors, const bool theUseIntersections) { mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1))); - if (!mySubSelList.back().select(theContext, theValue, theUseNeighbors)) { + if (!myBaseDocumentLab.IsNull()) + mySubSelList.back().setBaseDocument(myBaseDocumentLab); + if (!mySubSelList.back().select(theContext, theValue, + theGeometricalNaming, theUseNeighbors, theUseIntersections)) { mySubSelList.clear(); // if one of the selector is failed, all become invalid return false; }