X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_SelectionNaming.cpp;h=5c5c6132b958b1b4da468cd2d0c010115f6e1080;hb=c62a4254fbf27b069449f4766f9c849fe2286109;hp=5ed01d28b113ba372f6f8e385e5d2ca71bc1edaa;hpb=98e21a8e5e9de9c658c11c19fac5c4c7060396c5;p=modules%2Fshaper.git diff --git a/src/Model/Model_SelectionNaming.cpp b/src/Model/Model_SelectionNaming.cpp index 5ed01d28b..5c5c6132b 100644 --- a/src/Model/Model_SelectionNaming.cpp +++ b/src/Model/Model_SelectionNaming.cpp @@ -7,7 +7,7 @@ #include "Model_SelectionNaming.h" #include "Model_Document.h" #include -#include +#include #include #include @@ -26,11 +26,19 @@ #include #include #include +#include +#include +#include +#include #ifdef DEB_NAMING #include #endif +/// added to the index in the packed map to signalize that the vertex of edge is selected +/// (multiplied by the index of the edge) +static const int kSTART_VERTEX_DELTA = 1000000; + Model_SelectionNaming::Model_SelectionNaming(TDF_Label theSelectionLab) { myLab = theSelectionLab; @@ -109,8 +117,8 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, TopoDS_Shape aContext = theContext->shape()->impl(); #ifdef DEB_NAMING if(aSubShape.ShapeType() == TopAbs_COMPOUND) { - BRepTools::Write(aSubShape, "Selection.brep"); - BRepTools::Write(aContext, "Context.brep"); + BRepTools::Write(aSubShape, "Selection.brep"); + BRepTools::Write(aContext, "Context.brep"); } #endif std::shared_ptr aDoc = @@ -123,69 +131,60 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, switch (aType) { case TopAbs_FACE: // the Face should be in DF. If it is not the case, it is an error ==> to be debugged - break; - case TopAbs_EDGE: - { - // name structure: F1 | F2 [| F3 | F4], where F1 & F2 the faces which gives the Edge in trivial case - // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces - if (BRep_Tool::Degenerated(TopoDS::Edge(aSubShape))) { - aName = "Degenerated_Edge"; - break; - } - TopTools_IndexedDataMapOfShapeListOfShape aMap; - TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap); - TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape - bool isTrivialCase(true); -/* for (int i = 1; i <= aMap.Extent(); i++) { - const TopoDS_Shape& aKey = aMap.FindKey(i); - //if (aKey.IsNotEqual(aSubShape)) continue; // find exactly the selected key - if (aKey.IsSame(aSubShape)) continue; - const TopTools_ListOfShape& anAncestors = aMap.FindFromIndex(i); - // check that it is not a trivial case (F1 & F2: aNumber = 1) - isTrivialCase = isTrivial(anAncestors, aSMap); - break; - }*/ - if(aMap.Contains(aSubShape)) { - const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape); - // check that it is not a trivial case (F1 & F2: aNumber = 1) - isTrivialCase = isTrivial(anAncestors, aSMap); - } else - break; - TopTools_ListOfShape aListOfNbs; - if(!isTrivialCase) { // find Neighbors - TNaming_Localizer aLocalizer; - TopTools_MapOfShape aMap3; - aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3); - //int n = aMap3.Extent(); - TopTools_MapIteratorOfMapOfShape it(aMap3); - for(;it.More();it.Next()) { - const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge - //TopAbs_ShapeEnum aType = aNbShape.ShapeType(); - const TopTools_ListOfShape& aList = aMap.FindFromKey(aNbShape); - TopTools_ListIteratorOfListOfShape it2(aList); - for(;it2.More();it2.Next()) { - if(aSMap.Contains(it2.Value())) continue; // skip this Face - aListOfNbs.Append(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); - std::string aFaceName = getShapeName(aDoc, aFace); - if(i == 1) - aName = aFaceName; - else - aName += "|" + aFaceName; - } - TopTools_ListIteratorOfListOfShape itl(aListOfNbs); - for (;itl.More();itl.Next()) { - std::string aFaceName = getShapeName(aDoc, itl.Value()); - aName += "|" + aFaceName; - } - } - break; + break; + case TopAbs_EDGE: + { + // name structure: F1 & F2 [& F3 & F4], where F1 & F2 the faces which gives the Edge in trivial case + // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces + if (BRep_Tool::Degenerated(TopoDS::Edge(aSubShape))) { + aName = "Degenerated_Edge"; + break; + } + TopTools_IndexedDataMapOfShapeListOfShape aMap; + TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap); + TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape + bool isTrivialCase(true); + if(aMap.Contains(aSubShape)) { + const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape); + // check that it is not a trivial case (F1 & F2: aNumber = 1) + isTrivialCase = isTrivial(anAncestors, aSMap); + } else + break; + TopTools_ListOfShape aListOfNbs; + if(!isTrivialCase) { // find Neighbors + TNaming_Localizer aLocalizer; + TopTools_MapOfShape aMap3; + aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3); + //int n = aMap3.Extent(); + TopTools_MapIteratorOfMapOfShape it(aMap3); + for(;it.More();it.Next()) { + const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge + //TopAbs_ShapeEnum aType = aNbShape.ShapeType(); + const TopTools_ListOfShape& aList = aMap.FindFromKey(aNbShape); + TopTools_ListIteratorOfListOfShape it2(aList); + for(;it2.More();it2.Next()) { + if(aSMap.Contains(it2.Value())) continue; // skip this Face + aListOfNbs.Append(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); + std::string aFaceName = getShapeName(aDoc, aFace); + if(i == 1) + aName = aFaceName; + else + aName += "&" + aFaceName; + } + TopTools_ListIteratorOfListOfShape itl(aListOfNbs); + for (;itl.More();itl.Next()) { + std::string aFaceName = getShapeName(aDoc, itl.Value()); + aName += "&" + aFaceName; + } + } + break; case TopAbs_VERTEX: // name structure (Monifold Topology): @@ -204,16 +203,15 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, const TopTools_ListOfShape& aList2 = aMap.FindFromKey(aSubShape); TopTools_ListOfShape aList; TopTools_MapOfShape aFMap; - //int n = aList2.Extent(); //bug! duplication // fix is below TopTools_ListIteratorOfListOfShape itl2(aList2); for (int i = 1;itl2.More();itl2.Next(),i++) { if(aFMap.Add(itl2.Value())) aList.Append(itl2.Value()); } - //n = aList.Extent(); int n = aList.Extent(); - if(n < 3) { // open topology case or Compound case => via edges + bool isByFaces = n >= 3; + 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); @@ -232,17 +230,22 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, for (int i = 1;itl.More();itl.Next(),i++) { const TopoDS_Shape& anEdge = itl.Value(); std::string anEdgeName = getShapeName(aDoc, anEdge); + if (anEdgeName.empty()) { // edge is not in DS, trying by faces anyway + isByFaces = true; + aName.clear(); + break; + } if(i == 1) aName = anEdgeName; else - aName += "|" + anEdgeName; + aName += "&" + anEdgeName; } }//reg else { // dangle vertex: if(aList22.Extent() == 1) //it should be already in DF } } - else { + if (isByFaces) { TopTools_ListIteratorOfListOfShape itl(aList); for (int i = 1;itl.More();itl.Next(),i++) { const TopoDS_Shape& aFace = itl.Value(); @@ -250,7 +253,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, if(i == 1) aName = aFaceName; else - aName += "|" + aFaceName; + aName += "&" + aFaceName; } } } @@ -266,32 +269,45 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, TopAbs_ShapeEnum translateType (const std::string& theType) { // map from the textual shape types to OCCT enumeration - static std::map MyShapeTypes; - if (MyShapeTypes.size() == 0) { - MyShapeTypes["face"] = TopAbs_FACE; - MyShapeTypes["faces"] = TopAbs_FACE; - MyShapeTypes["vertex"] = TopAbs_VERTEX; - MyShapeTypes["vertices"] = TopAbs_VERTEX; - MyShapeTypes["wire"] = TopAbs_WIRE; - MyShapeTypes["edge"] = TopAbs_EDGE; - MyShapeTypes["edges"] = TopAbs_EDGE; - MyShapeTypes["shell"] = TopAbs_SHELL; - MyShapeTypes["solid"] = TopAbs_SOLID; - MyShapeTypes["solids"] = TopAbs_SOLID; - MyShapeTypes["FACE"] = TopAbs_FACE; - MyShapeTypes["FACES"] = TopAbs_FACE; - MyShapeTypes["VERTEX"] = TopAbs_VERTEX; - MyShapeTypes["VERTICES"] = TopAbs_VERTEX; - MyShapeTypes["WIRE"] = TopAbs_WIRE; - MyShapeTypes["EDGE"] = TopAbs_EDGE; - MyShapeTypes["EDGES"] = TopAbs_EDGE; - MyShapeTypes["SHELL"] = TopAbs_SHELL; - MyShapeTypes["SOLID"] = TopAbs_SOLID; - MyShapeTypes["SOLIDS"] = TopAbs_SOLID; + static std::map aShapeTypes; + + if(aShapeTypes.size() == 0) { + aShapeTypes["compound"] = TopAbs_COMPOUND; + aShapeTypes["compounds"] = TopAbs_COMPOUND; + aShapeTypes["compsolid"] = TopAbs_COMPSOLID; + aShapeTypes["compsolids"] = TopAbs_COMPSOLID; + aShapeTypes["solid"] = TopAbs_SOLID; + aShapeTypes["solids"] = TopAbs_SOLID; + aShapeTypes["shell"] = TopAbs_SHELL; + aShapeTypes["shells"] = TopAbs_SHELL; + aShapeTypes["face"] = TopAbs_FACE; + aShapeTypes["faces"] = TopAbs_FACE; + aShapeTypes["wire"] = TopAbs_WIRE; + aShapeTypes["wires"] = TopAbs_WIRE; + aShapeTypes["edge"] = TopAbs_EDGE; + aShapeTypes["edges"] = TopAbs_EDGE; + aShapeTypes["vertex"] = TopAbs_VERTEX; + aShapeTypes["vertices"] = TopAbs_VERTEX; + aShapeTypes["COMPOUND"] = TopAbs_COMPOUND; + aShapeTypes["COMPOUNDS"] = TopAbs_COMPOUND; + aShapeTypes["COMPSOLID"] = TopAbs_COMPSOLID; + aShapeTypes["COMPSOLIDS"] = TopAbs_COMPSOLID; + aShapeTypes["SOLID"] = TopAbs_SOLID; + aShapeTypes["SOLIDS"] = TopAbs_SOLID; + aShapeTypes["SHELL"] = TopAbs_SHELL; + aShapeTypes["SHELLS"] = TopAbs_SHELL; + aShapeTypes["FACE"] = TopAbs_FACE; + aShapeTypes["FACES"] = TopAbs_FACE; + aShapeTypes["WIRE"] = TopAbs_WIRE; + aShapeTypes["WIRES"] = TopAbs_WIRE; + aShapeTypes["EDGE"] = TopAbs_EDGE; + aShapeTypes["EDGES"] = TopAbs_EDGE; + aShapeTypes["VERTEX"] = TopAbs_VERTEX; + aShapeTypes["VERTICES"] = TopAbs_VERTEX; } - if (MyShapeTypes.find(theType) != MyShapeTypes.end()) - return MyShapeTypes[theType]; - Events_Error::send("Shape type defined in XML is not implemented!"); + if (aShapeTypes.find(theType) != aShapeTypes.end()) + return aShapeTypes[theType]; + Events_InfoMessage("Model_SelectionNaming", "Shape type defined in XML is not implemented!").send(); return TopAbs_SHAPE; } @@ -340,12 +356,12 @@ const TopoDS_Shape findFaceByName( return aFace; } -int ParseName(const std::string& theSubShapeName, std::list& theList) +size_t ParseName(const std::string& theSubShapeName, std::list& theList) { std::string aName = theSubShapeName; std::string aLastName; - int n1(0), n2(0); // n1 - start position, n2 - position of the delimiter - while ((n2 = aName.find('|', n1)) != std::string::npos) { + size_t n1(0), n2(0); // n1 - start position, n2 - position of the delimiter + while ((n2 = aName.find('&', n1)) != std::string::npos) { const std::string aName1 = aName.substr(n1, n2 - n1); //name of face theList.push_back(aName1); n1 = n2 + 1; @@ -442,11 +458,152 @@ std::string getContextName(const std::string& theSubShapeName) { std::string aName; std::string::size_type n = theSubShapeName.find('/'); - if (n == std::string::npos) return aName; + if (n == std::string::npos) return theSubShapeName; aName = theSubShapeName.substr(0, n); return aName; } +/// Parses naming name of sketch sub-elements: takes indices and orientation +/// (if theOriented = true) from this name. Map theIDs constains indices -> +/// orientations and start/end vertices: negative is reversed, 2 - start, 3 - end +bool parseSubIndices(CompositeFeaturePtr theComp, //< to iterate names + const std::string& theName, const char* theShapeType, + std::map& theIDs, const bool theOriented = false) +{ + // collect all IDs in the name + std::map aNames; // short name of sub -> ID of sub of theComp + const int aSubNum = theComp->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + FeaturePtr aSub = theComp->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + // there may be many shapes (circle and center) + for(; aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (aConstr.get()) { + aNames[Model_SelectionNaming::shortName(aConstr)] = theComp->subFeatureId(a); + } + } + } + + size_t aPrevPos = theName.find("/") + 1, aLastNamePos; + bool isShape = false; // anyway the first world must be 'Vertex' + do { + aLastNamePos = theName.find('-', aPrevPos); + std::string anID = theName.substr(aPrevPos, aLastNamePos - aPrevPos); + if (!isShape) { + if (anID != theShapeType) + return false; + isShape = true; + } else { + int anOrientation = 1; // default + if (theOriented) { // here must be a symbol in the end of digit 'f' or 'r' + const char aSymbol = anID.back(); + if (aSymbol == 'r') anOrientation = -1; + anID.pop_back(); + } + // check start/end symbols + if (anID.back() == 's') { + anOrientation *= 2; + anID.pop_back(); + } else if (anID.back() == 'e') { + anOrientation *= 3; + anID.pop_back(); + } + + if (aNames.find(anID) != aNames.end()) { + theIDs[aNames[anID]] = anOrientation; + } + } + aPrevPos = aLastNamePos + 1; + } while (aLastNamePos != std::string::npos); + return true; +} + +/// produces theEdge orientation relatively to theContext face +int Model_SelectionNaming::edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge) +{ + if (theContext.ShapeType() != TopAbs_FACE) + return 0; + TopoDS_Face aContext = TopoDS::Face(theContext); + if (theEdge.Orientation() == TopAbs_FORWARD) + return 1; + if (theEdge.Orientation() == TopAbs_REVERSED) + return -1; + return 0; // unknown +} + +std::shared_ptr Model_SelectionNaming::findAppropriateFace( + std::shared_ptr& theConstr, + NCollection_DataMap& theCurves) +{ + int aBestFound = 0; // best number of found edges (not percentage: issue 1019) + int aBestOrient = 0; // for the equal "BestFound" additional parameter is orientation + std::shared_ptr aResult; + ResultConstructionPtr aConstructionContext = + std::dynamic_pointer_cast(theConstr); + if (!aConstructionContext.get()) + return aResult; + for(int aFaceIndex = 0; aFaceIndex < aConstructionContext->facesNum(); aFaceIndex++) { + int aFound = 0, aNotFound = 0, aSameOrientation = 0; + TopoDS_Face aFace = + TopoDS::Face(aConstructionContext->face(aFaceIndex)->impl()); + TopExp_Explorer anEdgesExp(aFace, TopAbs_EDGE); + TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curved (841) + for(; anEdgesExp.More(); anEdgesExp.Next()) { + TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current()); + if (!anEdge.IsNull()) { + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (alreadyProcessed.Contains(aCurve)) + continue; + alreadyProcessed.Add(aCurve); + if (theCurves.IsBound(aCurve)) { + aFound++; + int anOrient = theCurves.Find(aCurve); + if (anOrient != 0) { // extra comparision score is orientation + if (edgeOrientation(aFace, anEdge) == anOrient) + aSameOrientation++; + } + } else { + aNotFound++; + } + } + } + if (aFound + aNotFound != 0) { + if (aFound > aBestFound || + (aFound == aBestFound && aSameOrientation > aBestOrient)) { + aBestFound = aFound; + aBestOrient = aSameOrientation; + aResult = aConstructionContext->face(aFaceIndex); + } + } + } + return aResult; +} + +std::string Model_SelectionNaming::shortName( + std::shared_ptr& theConstr, const int theEdgeVertexPos) +{ + std::string aName = theConstr->data()->name(); + // remove "-", "/" and "&" command-symbols + aName.erase(std::remove(aName.begin(), aName.end(), '-'), aName.end()); + aName.erase(std::remove(aName.begin(), aName.end(), '/'), aName.end()); + aName.erase(std::remove(aName.begin(), aName.end(), '&'), aName.end()); + // remove the last 's', 'e', 'f' and 'r' symbols: they are used as markers of start/end/forward/rewersed indicators + static const std::string aSyms("sefr"); + while(aSyms.find(aName.back()) != std::string::npos) { + aName.pop_back(); + } + if (theEdgeVertexPos == 1) { + aName += "s"; // start + } else if (theEdgeVertexPos == 2) { + aName += "e"; // end + } + return aName; +} + // type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT bool Model_SelectionNaming::selectSubShape(const std::string& theType, const std::string& theSubShapeName, std::shared_ptr theDoc, @@ -457,40 +614,37 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, std::string aContName = getContextName(theSubShapeName); if(aContName.empty()) return false; ResultPtr aCont = theDoc->findByName(aContName); - if(!aCont.get() || aCont->shape()->isNull()) return false; - TopoDS_Shape aContext = aCont->shape()->impl(); - TopAbs_ShapeEnum aContType = aContext.ShapeType(); - if(aType <= aContType) return false; // not applicable + // possible this is body where postfix is added to distinguish several shapes on the same label + int aSubShapeId = -1; // -1 means sub shape not found + if (!aCont.get() && aContName == theSubShapeName) { + size_t aPostIndex = aContName.rfind('_'); + if (aPostIndex != std::string::npos) { + std::string aSubContName = aContName.substr(0, aPostIndex); + aCont = theDoc->findByName(aSubContName); + if (aCont.get()) { + try { + std::string aNum = aContName.substr(aPostIndex + 1); + aSubShapeId = std::stoi(aNum); + } catch (std::invalid_argument&) { + aSubShapeId = -1; + } + if (aSubShapeId > 0) + aContName = aSubContName; + } + } + } TopoDS_Shape aSelection; switch (aType) { - case TopAbs_COMPOUND: - break; - case TopAbs_COMPSOLID: - break; - case TopAbs_SOLID: - break; - case TopAbs_SHELL: - break; case TopAbs_FACE: { - const TopoDS_Shape aSelection = findFaceByName(theSubShapeName, theDoc); - if(!aSelection.IsNull()) {// Select it - std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); - aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection)); - theShapeToBeSelected = aShapeToBeSelected; - theCont = aCont; - return true; - } + aSelection = findFaceByName(theSubShapeName, theDoc); } break; - case TopAbs_WIRE: - break; case TopAbs_EDGE: { - TopoDS_Shape aSelection;// = findFaceByName(theSubShapeName, aDoc); const TDF_Label& aLabel = theDoc->findNamingName(theSubShapeName); if(!aLabel.IsNull()) { Handle(TNaming_NamedShape) aNS; @@ -498,31 +652,10 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, aSelection = getShapeFromNS(theSubShapeName, aNS); } } - if(aSelection.IsNull()) { - std::list aListofNames; - int n = ParseName(theSubShapeName, aListofNames); - if(n > 1 && n < 5) { - TopTools_ListOfShape aList; - std::list::iterator it =aListofNames.begin(); - for(;it != aListofNames.end();it++){ - const TopoDS_Shape aFace = findFaceByName(*it, theDoc); - aList.Append(aFace); - } - aSelection = findCommonShape(TopAbs_EDGE, aList); - } - } - if(!aSelection.IsNull()) {// Select it - std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); - aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection)); - theShapeToBeSelected = aShapeToBeSelected; - theCont = aCont; - return true; - } } break; case TopAbs_VERTEX: { - TopoDS_Shape aSelection; const TDF_Label& aLabel = theDoc->findNamingName(theSubShapeName); if(!aLabel.IsNull()) { Handle(TNaming_NamedShape) aNS; @@ -530,32 +663,154 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, aSelection = getShapeFromNS(theSubShapeName, aNS); } } - if(aSelection.IsNull()) { - std::list aListofNames; - int n = ParseName(theSubShapeName, aListofNames); - if(n > 1 && n < 4) { // 2 || 3 - TopTools_ListOfShape aList; - std::list::iterator it = aListofNames.begin(); - for(; it != aListofNames.end(); it++){ - const TopoDS_Shape aFace = findFaceByName(*it, theDoc); - if(!aFace.IsNull()) - aList.Append(aFace); - } - aSelection = findCommonShape(TopAbs_VERTEX, aList); - } - } - if(!aSelection.IsNull()) {// Select it - std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); - aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection)); - theShapeToBeSelected = aShapeToBeSelected; + } + break; + case TopAbs_COMPOUND: + case TopAbs_COMPSOLID: + case TopAbs_SOLID: + case TopAbs_SHELL: + case TopAbs_WIRE: + default: {//TopAbs_SHAPE + /// case when the whole sketch is selected, so, selection type is compound, but there is no value + if (aCont.get() && aCont->shape().get()) { + if (aCont->shape()->impl().ShapeType() == aType) { theCont = aCont; return true; + } else if (aSubShapeId > 0) { // try to find sub-shape by the index + TopExp_Explorer anExp(aCont->shape()->impl(), aType); + for(; aSubShapeId > 0 && anExp.More(); aSubShapeId--) { + anExp.Next(); + } + if (anExp.More()) { + std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); + aShapeToBeSelected->setImpl(new TopoDS_Shape(anExp.Current())); + theShapeToBeSelected = aShapeToBeSelected; + theCont = aCont; + return true; + } } } - break; - default: //TopAbs_SHAPE return false; + } + } + // another try to find edge or vertex by faces + std::list aListofNames; + size_t aN = aSelection.IsNull() ? ParseName(theSubShapeName, aListofNames) : 0; + if (aSelection.IsNull() && (aType == TopAbs_EDGE || aType == TopAbs_VERTEX)) { + if(aN > 1 && (aN < 4 || (aType == TopAbs_EDGE && aN < 5))) { // 2 || 3 or 4 for EDGE + TopTools_ListOfShape aList; + std::list::iterator it = aListofNames.begin(); + for(; it != aListofNames.end(); it++){ + const TopoDS_Shape aFace = findFaceByName(*it, theDoc); + if(!aFace.IsNull()) + aList.Append(aFace); + } + aSelection = findCommonShape(aType, aList); + } + } + if (!aSelection.IsNull()) {// Select it + std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); + aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection)); + theShapeToBeSelected = aShapeToBeSelected; + theCont = aCont; + return true; + } + // 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 == 0) { + size_t aConstrNamePos = theSubShapeName.find("/"); + bool isFullName = aConstrNamePos == std::string::npos; + std::string aContrName = aContName; + // isFullName ? theSubShapeName : theSubShapeName.substr(0, aConstrNamePos); + ResultPtr aConstr = theDoc->findByName(aContrName); + if (aConstr.get() && aConstr->groupName() == ModelAPI_ResultConstruction::group()) { + theCont = aConstr; + if (isFullName) { + theShapeToBeSelected = aConstr->shape(); + return true; + } + // for sketch sub-elements selected + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(theDoc->feature(aConstr)); + if (aComposite.get()) { + if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE) { + // collect all IDs in the name + std::map anIDs; + if (!parseSubIndices(aComposite, theSubShapeName, + aType == TopAbs_EDGE ? "Edge" : "Vertex", anIDs)) + return false; + + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + int aCompID = aComposite->subFeatureId(a); + if (anIDs.find(aCompID) != anIDs.end()) { // found the vertex/edge shape + FeaturePtr aSub = aComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRIt = aResults.cbegin(); + // there may be many shapes (circle and center) + for(; aRIt != aResults.cend(); aRIt++) { + ResultConstructionPtr aRes = + std::dynamic_pointer_cast(*aRIt); + if (aRes) { + int anOrientation = abs(anIDs[aCompID]); + TopoDS_Shape aShape = aRes->shape()->impl(); + if (anOrientation == 1) { + if (aType == aShape.ShapeType()) { + theShapeToBeSelected = aRes->shape(); + return true; + } + } else { // take first or second vertex of the edge + TopoDS_Shape aShape = aRes->shape()->impl(); + TopExp_Explorer anExp(aShape, aType); + for(; anExp.More() && anOrientation != 2; anOrientation--) + anExp.Next(); + if (anExp.More()) { + std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); + aShapeToBeSelected->setImpl(new TopoDS_Shape(anExp.Current())); + theShapeToBeSelected = aShapeToBeSelected; + return true; + } + } + } + } + } + } + } else if (aType == TopAbs_FACE) { // sketch faces is identified by format "Sketch_1/Face-2f-8f-11r" + std::map anIDs; + if (!parseSubIndices(aComposite, theSubShapeName, "Face", anIDs, true)) + return false; + + NCollection_DataMap allCurves; // curves and orientations of edges + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + int aSubID = aComposite->subFeatureId(a); + if (anIDs.find(aSubID) != anIDs.end()) { + FeaturePtr aSub = aComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes; + for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (aConstr->shape() && aConstr->shape()->isEdge()) { + const TopoDS_Shape& aResShape = aConstr->shape()->impl(); + TopoDS_Edge anEdge = TopoDS::Edge(aResShape); + if (!anEdge.IsNull()) { + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + allCurves.Bind(aCurve, anIDs[aSubID] > 0 ? 1 : -1); + } + } + } + } + } + std::shared_ptr aFoundFace = findAppropriateFace(aConstr, allCurves); + if (aFoundFace.get()) { + theShapeToBeSelected = aFoundFace; + return true; + } + } + } + } } return false; } -