X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_AttributeSelection.cpp;h=9133794ae94460375cf53c75b966de982345e221;hb=223db274e2083c0289eb8d8043344ae421e524a8;hp=bcf8a57b3d18bcb63917524d87b95d5b727ee5de;hpb=815d02a699ded50ddf0f82315d48825cc1123f98;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index bcf8a57b3..9133794ae 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -8,13 +8,13 @@ #include "Model_Application.h" #include "Model_Events.h" #include "Model_Data.h" +#include "Model_Document.h" #include #include #include #include #include #include -#include #include #include @@ -51,11 +51,16 @@ #include #include using namespace std; +//#define DEB_NAMING 1 +#ifdef DEB_NAMING +#include +#endif /// adeed to the index in the packed map to signalize that the vertex of edge is seleted /// (multiplied by the index of the edge) static const int kSTART_VERTEX_DELTA = 1000000; // identifier that there is simple reference: selection equals to context Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29"); +Standard_GUID kCONSTUCTION_SIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb28"); // on this label is stored: // TNaming_NamedShape - selected shape @@ -68,19 +73,33 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, const std::shared_ptr& theSubShape) { const std::shared_ptr& anOldShape = value(); - bool isOldShape = + bool isOldContext = theContext == myRef.value(); + bool isOldShape = isOldContext && (theSubShape == anOldShape || (theSubShape && anOldShape && theSubShape->isEqual(anOldShape))); if (isOldShape) return; // shape is the same, so context is also unchanged // update the referenced object if needed - bool isOldContext = theContext == myRef.value(); - - if (!isOldContext) myRef.setValue(theContext); // do noth use naming if selected shape is result shape itself, but not sub-shape TDF_Label aSelLab = selectionLabel(); aSelLab.ForgetAttribute(kSIMPLE_REF_ID); + aSelLab.ForgetAttribute(kCONSTUCTION_SIMPLE_REF_ID); + + bool isDegeneratedEdge = false; + // do not use the degenerated edge as a shape, a null context and shape is used in the case + if (theSubShape.get() && !theSubShape->isNull() && theSubShape->isEdge()) { + const TopoDS_Shape& aSubShape = theSubShape->impl(); + if (aSubShape.ShapeType() == TopAbs_EDGE) + isDegeneratedEdge = BRep_Tool::Degenerated(TopoDS::Edge(aSubShape)); + } + if (!theContext.get() || isDegeneratedEdge) { + // to keep the reference attribute label + TDF_Label aRefLab = myRef.myRef->Label(); + aSelLab.ForgetAllAttributes(true); + myRef.myRef = TDF_Reference::Set(aSelLab, aSelLab); + return; + } if (theContext->groupName() == ModelAPI_ResultBody::group()) { // do not select the whole shape for body:it is already must be in the data framework if (theContext->shape().get() && theContext->shape()->isEqual(theSubShape)) { @@ -90,7 +109,13 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, selectBody(theContext, theSubShape); } } else if (theContext->groupName() == ModelAPI_ResultConstruction::group()) { - selectConstruction(theContext, theSubShape); + if (!theSubShape.get()) { + // to sub, so the whole result is selected + aSelLab.ForgetAllAttributes(true); + TDataStd_UAttribute::Set(aSelLab, kCONSTUCTION_SIMPLE_REF_ID); + } else { + selectConstruction(theContext, theSubShape); + } } myIsInitialized = true; @@ -118,6 +143,9 @@ std::shared_ptr Model_AttributeSelection::value() return aResult; // empty result return aContext->shape(); } + if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value + return aResult; // empty result + } Handle(TNaming_NamedShape) aSelection; if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { @@ -183,6 +211,9 @@ bool Model_AttributeSelection::update() if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape return aContext->shape() && !aContext->shape()->isNull(); } + if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, not sub-shape + return aContext->shape() && !aContext->shape()->isNull(); + } if (aContext->groupName() == ModelAPI_ResultBody::group()) { // body: just a named shape, use selection mechanism from OCCT @@ -193,10 +224,13 @@ bool Model_AttributeSelection::update() } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) { // construction: identification by the results indexes, recompute faces and // take the face that more close by the indexes - std::shared_ptr aWirePtr = - std::dynamic_pointer_cast( - std::dynamic_pointer_cast(aContext)->shape()); - if (aWirePtr && aWirePtr->hasPlane()) { // sketch sub-element + ResultConstructionPtr aConstructionContext = + std::dynamic_pointer_cast(aContext); + FeaturePtr aContextFeature = aContext->document()->feature(aContext); + // sketch sub-element + if (aConstructionContext && + std::dynamic_pointer_cast(aContextFeature).get()) + { TDF_Label aLab = myRef.myRef->Label(); // getting a type of selected shape Handle(TDataStd_Integer) aTypeAttr; @@ -210,24 +244,20 @@ bool Model_AttributeSelection::update() bool aNoIndexes = !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0; // for now working only with composite features - FeaturePtr aContextFeature = aContext->document()->feature(aContext); CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aContextFeature); - if (!aComposite || aComposite->numberOfSubs() == 0) { + if (!aComposite.get() || aComposite->numberOfSubs() == 0) { return false; } - if (aShapeType == TopAbs_FACE) { + if (aShapeType == TopAbs_FACE) { // compound is for the whole sketch selection // If this is a wire with plane defined thin it is a sketch-like object - std::list > aFaces; - GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(), - aWirePtr->dirY(), aWirePtr->norm(), aWirePtr, aFaces); - if (aFaces.empty()) // no faces, update can not work correctly + if (!aConstructionContext->facesNum()) // no faces, update can not work correctly return false; // if there is no edges indexes, any face can be used: take the first std::shared_ptr aNewSelected; if (aNoIndexes) { - aNewSelected = *(aFaces.begin()); + aNewSelected = aConstructionContext->face(0); } else { // searching for most looks-like initial face by the indexes // prepare edges of the current resut for the fast searching TColStd_MapOfTransient allCurves; @@ -252,12 +282,11 @@ bool Model_AttributeSelection::update() } } } - // iterate new result faces and searching for these edges - std::list >::iterator aFacesIter = aFaces.begin(); double aBestFound = 0; // best percentage of found edges - for(; aFacesIter != aFaces.end(); aFacesIter++) { + for(int aFaceIndex = 0; aFaceIndex < aConstructionContext->facesNum(); aFaceIndex++) { int aFound = 0, aNotFound = 0; - TopExp_Explorer anEdgesExp((*aFacesIter)->impl(), TopAbs_EDGE); + TopExp_Explorer anEdgesExp( + aConstructionContext->face(aFaceIndex)->impl(), TopAbs_EDGE); for(; anEdgesExp.More(); anEdgesExp.Next()) { TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current()); if (!anEdge.IsNull()) { @@ -274,7 +303,7 @@ bool Model_AttributeSelection::update() double aPercentage = double(aFound) / double(aFound + aNotFound); if (aPercentage > aBestFound) { aBestFound = aPercentage; - aNewSelected = *aFacesIter; + aNewSelected = aConstructionContext->face(aFaceIndex); } } } @@ -379,12 +408,13 @@ void Model_AttributeSelection::selectBody( return; } } - aSel.Select(aNewShape, aContext); + //BRepTools::Write(aNewShape, "Selection0.brep"); + aSel.Select(aNewShape, aContext); } /// registers the name of the shape in the label (theID == 0) of sub label (theID is a tag) /// if theID is zero, -static void registerSubShape(TDF_Label& theMainLabel, TopoDS_Shape theShape, +static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, const int theID, const FeaturePtr& theContextFeature, std::shared_ptr theDoc, std::string theAdditionalName, Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)()) @@ -594,13 +624,30 @@ bool isTrivial (const TopTools_ListOfShape& theAncestors, TopTools_IndexedMapOfS } std::string Model_AttributeSelection::namingName() { + std::string aName(""); + if(!this->isInitialized()) return aName; + Handle(TDataStd_Name) anAtt; + if(selectionLabel().FindAttribute(TDataStd_Name::GetID(), anAtt)) { + aName = TCollection_AsciiString(anAtt->Get()).ToCString(); + return aName; + } + std::shared_ptr aSubSh = value(); ResultPtr aCont = context(); - std::string aName; - if(!aSubSh.get() || aSubSh->isNull() || !aCont.get() || aCont->shape()->isNull()) + aName = "Undefined name"; + if(!aCont.get() || aCont->shape()->isNull()) return aName; + if (!aSubSh.get() || aSubSh->isNull()) { // no subshape, so just the whole feature name + return aCont->data()->name(); + } TopoDS_Shape aSubShape = aSubSh->impl(); TopoDS_Shape aContext = aCont->shape()->impl(); +#ifdef DEB_NAMING + if(aSubShape.ShapeType() == TopAbs_COMPOUND) { + BRepTools::Write(aSubShape, "Selection.brep"); + BRepTools::Write(aContext, "Context.brep"); + } +#endif std::shared_ptr aDoc = std::dynamic_pointer_cast(aCont->document()); @@ -610,26 +657,35 @@ std::string Model_AttributeSelection::namingName() TopAbs_ShapeEnum aType = aSubShape.ShapeType(); switch (aType) { case TopAbs_FACE: - // the Face should be in DF. If it is not a case, it is an error ==> to be dbugged + // 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 - TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape + // 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++) { +/* 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.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; @@ -669,6 +725,7 @@ std::string Model_AttributeSelection::namingName() case TopAbs_VERTEX: // name structure (Monifold Topology): // 1) F1 | F2 | F3 - intersection of 3 faces defines a vertex - trivial case. + // 2) F1 | F2 | F3 [|F4 [|Fn]] - redundant definition, but it should be kept as is to obtain safe recomputation // 2) F1 | F2 - intersection of 2 faces definses a vertex - applicable for case // when 1 faces is cylindrical, conical, spherical or revolution and etc. // 3) E1 | E2 | E3 - intersection of 3 edges defines a vertex - when we have case of a shell @@ -683,7 +740,7 @@ std::string Model_AttributeSelection::namingName() TopTools_ListOfShape aList; TopTools_MapOfShape aFMap; #ifdef FIX_BUG1 - //int n = aList2.Extent(); //bug! + //int n = aList2.Extent(); //bug! duplication // fix is below TopTools_ListIteratorOfListOfShape itl2(aList2); for (int i = 1;itl2.More();itl2.Next(),i++) { @@ -692,14 +749,48 @@ std::string Model_AttributeSelection::namingName() } //n = aList.Extent(); #endif - TopTools_ListIteratorOfListOfShape itl(aList); - for (int i = 1;itl.More();itl.Next(),i++) { - const TopoDS_Shape& aFace = itl.Value(); - std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel()); - if(i == 1) - aName = aFaceName; - else - aName += "|" + aFaceName; + int n = aList.Extent(); + if(n < 3) { // 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 +#ifdef FIX_BUG1 + + // 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(); +#endif + 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, selectionLabel()); + if(i == 1) + aName = anEdgeName; + else + aName += "|" + anEdgeName; + } + }//reg + else { // dangle vertex: if(aList22.Extent() == 1) + //it should be already in DF + } + } + else { + TopTools_ListIteratorOfListOfShape itl(aList); + for (int i = 1;itl.More();itl.Next(),i++) { + const TopoDS_Shape& aFace = itl.Value(); + std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel()); + if(i == 1) + aName = aFaceName; + else + aName += "|" + aFaceName; + } } } break; @@ -713,25 +804,33 @@ std::string Model_AttributeSelection::namingName() TopAbs_ShapeEnum translateType (const std::string& theType) { - TCollection_AsciiString aStr(theType.c_str()); - aStr.UpperCase(); - if(aStr.IsEqual("COMP")) - return TopAbs_COMPOUND; - else if(aStr.IsEqual("COMS")) - return TopAbs_COMPSOLID; - else if(aStr.IsEqual("SOLD")) - return TopAbs_SOLID; - else if(aStr.IsEqual("SHEL")) - return TopAbs_SHELL; - else if(aStr.IsEqual("FACE")) - return TopAbs_FACE; - else if(aStr.IsEqual("WIRE")) - return TopAbs_WIRE; - else if(aStr.IsEqual("EDGE")) - return TopAbs_EDGE; - else if(aStr.IsEqual("VERT")) - return TopAbs_VERTEX; - + // 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; + } + if (MyShapeTypes.find(theType) != MyShapeTypes.end()) + return MyShapeTypes[theType]; + Events_Error::send("Shape type defined in XML is not implemented!"); return TopAbs_SHAPE; } @@ -785,13 +884,13 @@ const TopoDS_Shape findFaceByName(const std::string& theSubShapeName, std::share return aFace; } -int ParseEdgeName(const std::string& theSubShapeName, std::list& theList) +int 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) { - const std::string aName1 = aName.substr(n1, n2); //name of face + const std::string aName1 = aName.substr(n1, n2 - n1); //name of face theList.push_back(aName1); n1 = n2 + 1; aLastName = aName.substr(n1); @@ -818,36 +917,94 @@ const TopoDS_Shape findCommonShape(const TopAbs_ShapeEnum theType, const TopTool //fill maps TopTools_ListIteratorOfListOfShape it(theList); for(int i = 0;it.More();it.Next(),i++) { - const TopoDS_Shape& aFace = it.Value(); - TopExp_Explorer anExp (aFace, theType); - for(;anExp.More();anExp.Next()) { - const TopoDS_Shape& anEdge = anExp.Current(); - if (!anEdge.IsNull()) - aVec[i].Add(anExp.Current()); + const TopoDS_Shape& aFace = it.Value(); + if(i < 2) { + TopExp_Explorer anExp (aFace, theType); + for(;anExp.More();anExp.Next()) { + const TopoDS_Shape& anEdge = anExp.Current(); + if (!anEdge.IsNull()) + aVec[i].Add(anExp.Current()); + } + } else { + TopExp_Explorer anExp (aFace, TopAbs_VERTEX); + for(;anExp.More();anExp.Next()) { + const TopoDS_Shape& aVertex = anExp.Current(); + if (!aVertex.IsNull()) + aVec[i].Add(anExp.Current()); + } } } //trivial case: 2 faces + TopTools_ListOfShape aList; TopTools_MapIteratorOfMapOfShape it2(aVec[0]); for(;it2.More();it2.Next()) { - if(aVec[1].Contains(it2.Key())) { - aShape = it2.Key(); - break; + if(aVec[1].Contains(it2.Key())) { + aShape = it2.Key(); + if(theList.Extent() == 2) + break; + else + aList.Append(it2.Key()); + } + } + if(aList.Extent() && aVec.size() > 3) {// list of common edges ==> search ny neighbors + if(aVec[2].Extent() && aVec[3].Extent()) { + TopTools_ListIteratorOfListOfShape it(aList); + for(;it.More();it.Next()) { + const TopoDS_Shape& aCand = it.Value(); + // not yet completelly implemented, to be rechecked + TopoDS_Vertex aV1, aV2; + TopExp::Vertices(TopoDS::Edge(aCand), aV1, aV2); + int aNum(0); + if(aVec[2].Contains(aV1)) aNum++; + else if(aVec[2].Contains(aV2)) aNum++; + if(aVec[3].Contains(aV1)) aNum++; + else if(aVec[3].Contains(aV2)) aNum++; + if(aNum == 2) { + aShape = aCand; + break; + } + } + } + } + + if(aList.Extent() && aVec.size() == 3) { + + TopTools_ListIteratorOfListOfShape it(aList); + for(;it.More();it.Next()) { + const TopoDS_Shape& aCand = it.Value(); + if(aVec[2].Contains(aCand)) { + aShape = aCand; + break; + } } } return aShape; } + +std::string getContextName(const std::string& theSubShapeName) +{ + std::string aName; + std::string::size_type n = theSubShapeName.find('/'); + if (n == std::string::npos) return aName; + aName = theSubShapeName.substr(0, n); + return aName; +} // type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT void Model_AttributeSelection::selectSubShape(const std::string& theType, const std::string& theSubShapeName) { if(theSubShapeName.empty() || theType.empty()) return; TopAbs_ShapeEnum aType = translateType(theType); - ResultPtr aCont = context(); + std::shared_ptr aDoc = std::dynamic_pointer_cast(owner()->document());//std::dynamic_pointer_cast(aCont->document()); + std::string aContName = getContextName(theSubShapeName); + if(aContName.empty()) return; + //ResultPtr aCont = context(); + ResultPtr aCont = aDoc->findByName(aContName); if(!aCont.get() || aCont->shape()->isNull()) return; TopoDS_Shape aContext = aCont->shape()->impl(); TopAbs_ShapeEnum aContType = aContext.ShapeType(); if(aType <= aContType) return; // not applicable - - std::shared_ptr aDoc = std::dynamic_pointer_cast(aCont->document()); + + TopoDS_Shape aSelection; switch (aType) { @@ -889,7 +1046,7 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType, const } if(aSelection.IsNull()) { std::list aListofNames; - int n = ParseEdgeName(theSubShapeName, aListofNames); + int n = ParseName(theSubShapeName, aListofNames); if(n > 1 && n < 5) { TopTools_ListOfShape aList; for(std::list::iterator it =aListofNames.begin();it != aListofNames.end();it++){ @@ -907,9 +1064,60 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType, const } break; case TopAbs_VERTEX: + { + TopoDS_Shape aSelection; + const TDF_Label& aLabel = aDoc->findNamingName(theSubShapeName); + if(!aLabel.IsNull()) { + Handle(TNaming_NamedShape) aNS; + if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + const TopoDS_Shape& aShape = aNS->Get(); + if(!aShape.IsNull()) { + if(aShape.ShapeType() == TopAbs_COMPOUND) + aSelection = getShapeFromCompound(theSubShapeName, aShape); + else + aSelection = aShape; + } + } + } + if(aSelection.IsNull()) { + std::list aListofNames; + int n = ParseName(theSubShapeName, aListofNames); + if(n > 1 && n < 4) { // 2 || 3 + TopTools_ListOfShape aList; + for(std::list::iterator it =aListofNames.begin();it != aListofNames.end();it++){ + const TopoDS_Shape aFace = findFaceByName(*it, aDoc); + 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)); + setValue(aCont, aShapeToBeSelected); + } + } break; default: //TopAbs_SHAPE return; } } + +int Model_AttributeSelection::Id() +{ + std::shared_ptr aSelection = value(); + std::shared_ptr aContext = context()->shape(); + const TopoDS_Shape& aMainShape = aContext->impl(); + const TopoDS_Shape& aSubShape = aSelection->impl(); + int anID = 0; + if (aSelection && !aSelection->isNull() && + aContext && !aContext->isNull()) + { + TopTools_IndexedMapOfShape aSubShapesMap; + TopExp::MapShapes(aMainShape, aSubShapesMap); + anID = aSubShapesMap.FindIndex(aSubShape); + } + return anID; +}