X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_AttributeSelection.cpp;h=f610b3dbefb7161ab8e292fcfac57b0dfd7e6539;hb=ecec337d46d54cb79cbca6233fb93449513603af;hp=62659de6c59560f4468b759b0102c7c5b0d09fd6;hpb=8170985e13476f171bb839474ffaf2cce5d0546d;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 62659de6c..f610b3dbe 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -1,3 +1,5 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + // File: Model_AttributeSelection.h // Created: 2 Oct 2014 // Author: Mikhail PONIKAROV @@ -9,18 +11,58 @@ #include #include #include +#include #include +#include +#include +#include #include #include +#include +#include +#include #include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace std; +/// 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; + +// on this label is stored: +// TNaming_NamedShape - selected shape +// TNaming_Naming - topological selection information (for the body) +// TDataStd_IntPackedMap - indexes of edges in composite element (for construction) +// TDataStd_Integer - type of the selected shape (for construction) +// TDF_Reference - from ReferenceAttribute, the context void Model_AttributeSelection::setValue(const ResultPtr& theContext, - const boost::shared_ptr& theSubShape) + const std::shared_ptr& theSubShape) { - const boost::shared_ptr& anOldShape = value(); + const std::shared_ptr& anOldShape = value(); bool isOldShape = (theSubShape == anOldShape || (theSubShape && anOldShape && theSubShape->isEqual(anOldShape))); if (isOldShape) return; // shape is the same, so context is also unchanged @@ -29,35 +71,34 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, if (!isOldContext) myRef.setValue(theContext); - // perform the selection - TNaming_Selector aSel(myRef.myRef->Label()); - TopoDS_Shape aNewShape = theSubShape ? theSubShape->impl() : TopoDS_Shape(); - TopoDS_Shape aContext; + if (theContext->groupName() == ModelAPI_ResultBody::group()) + selectBody(theContext, theSubShape); + else if (theContext->groupName() == ModelAPI_ResultConstruction::group()) + selectConstruction(theContext, theSubShape); - ResultBodyPtr aBody = boost::dynamic_pointer_cast(myRef.value()); - if (aBody) - aContext = aBody->shape()->impl(); - else { - ResultConstructionPtr aConstr = boost::dynamic_pointer_cast(myRef.value()); - if (aConstr) - aContext = aConstr->shape()->impl(); - else - throw std::invalid_argument("a result with shape is expected"); - } - aSel.Select(aNewShape, aContext); - myIsInitialized = true; + std::string aSelName = namingName(); + if(!aSelName.empty()) + TDataStd_Name::Set(selectionLabel(), aSelName.c_str()); //set name + myIsInitialized = true; owner()->data()->sendAttributeUpdated(this); } -boost::shared_ptr Model_AttributeSelection::value() +std::shared_ptr Model_AttributeSelection::value() { - boost::shared_ptr aResult; + std::shared_ptr aResult; if (myIsInitialized) { Handle(TNaming_NamedShape) aSelection; - if (myRef.myRef->Label().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { + if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { TopoDS_Shape aSelShape = aSelection->Get(); - aResult->setImpl(&aSelShape); + aResult = std::shared_ptr(new GeomAPI_Shape); + aResult->setImpl(new TopoDS_Shape(aSelShape)); + } else { // for simple construction element: just shape of this construction element + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(context()); + if (aConstr) { + return aConstr->shape(); + } } } return aResult; @@ -70,11 +111,512 @@ Model_AttributeSelection::Model_AttributeSelection(TDF_Label& theLabel) } ResultPtr Model_AttributeSelection::context() { - return boost::dynamic_pointer_cast(myRef.value()); + return std::dynamic_pointer_cast(myRef.value()); } -void Model_AttributeSelection::setObject(const boost::shared_ptr& theObject) +void Model_AttributeSelection::setObject(const std::shared_ptr& theObject) { + ModelAPI_AttributeSelection::setObject(theObject); myRef.setObject(theObject); } + +TDF_LabelMap& Model_AttributeSelection::scope() +{ + if (myScope.IsEmpty()) { // create a new scope if not yet done + // gets all labels with named shapes that are bofore this feature label (before in history) + TDF_Label aFeatureLab = std::dynamic_pointer_cast( + owner()->data())->label().Father(); + int aFeatureID = aFeatureLab.Tag(); + TDF_ChildIterator aFeaturesIter(aFeatureLab.Father()); + for(; aFeaturesIter.More(); aFeaturesIter.Next()) { + if (aFeaturesIter.Value().Tag() >= aFeatureID) // the left labels are created later + break; + TDF_ChildIDIterator aNSIter(aFeaturesIter.Value(), TNaming_NamedShape::GetID(), 1); + for(; aNSIter.More(); aNSIter.Next()) { + Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value()); + if (!aNS.IsNull() && aNS->Evolution() != TNaming_SELECTED) { + myScope.Add(aNS->Label()); + } + } + } + } + return myScope; +} + +bool Model_AttributeSelection::update() +{ + ResultPtr aContext = context(); + if (!aContext) return false; + if (aContext->groupName() == ModelAPI_ResultBody::group()) { + // body: just a named shape, use selection mechanism from OCCT + TNaming_Selector aSelector(selectionLabel()); + bool aResult = aSelector.Solve(scope()) == Standard_True; + owner()->data()->sendAttributeUpdated(this); + return aResult; + } 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 + TDF_Label aLab = myRef.myRef->Label(); + // getting a type of selected shape + Handle(TDataStd_Integer) aTypeAttr; + if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) { + return false; + } + TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get()); + // selected indexes will be needed in each "if" + Handle(TDataStd_IntPackedMap) aSubIds; + std::shared_ptr aNewSelected; + 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) { + return false; + } + + if (aShapeType == TopAbs_FACE) { + // 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 + 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()); + } else { // searching for most looks-like initial face by the indexes + // prepare edges of the current resut for the fast searching + TColStd_MapOfTransient allCurves; + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + if (aSubIds->Contains(aComposite->subFeatureId(a))) { + 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.Add(aCurve); + } + } + } + } + } + // 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++) { + int aFound = 0, aNotFound = 0; + TopExp_Explorer anEdgesExp((*aFacesIter)->impl(), TopAbs_EDGE); + 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 (allCurves.Contains(aCurve)) { + aFound++; + } else { + aNotFound++; + } + } + } + if (aFound + aNotFound != 0) { + double aPercentage = double(aFound) / double(aFound + aNotFound); + if (aPercentage > aBestFound) { + aBestFound = aPercentage; + aNewSelected = *aFacesIter; + } + } + } + } + if (aNewSelected) { // store this new selection + selectConstruction(aContext, aNewSelected); + owner()->data()->sendAttributeUpdated(this); + return true; + } + } else if (aShapeType == TopAbs_EDGE) { + // just reselect the edge by the id + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + // if aSubIds take any, the first appropriate + if (aSubIds->IsEmpty() || aSubIds->Contains(aComposite->subFeatureId(a))) { + // found the appropriate feature + FeaturePtr aFeature = aComposite->subFeature(a); + std::list >::const_iterator aResIter = + aFeature->results().cbegin(); + for(;aResIter != aFeature->results().cend(); aResIter++) { + ResultConstructionPtr aRes = + std::dynamic_pointer_cast(*aResIter); + if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found! + selectConstruction(aContext, aRes->shape()); + owner()->data()->sendAttributeUpdated(this); + return true; + } + } + } + } + } else if (aShapeType == TopAbs_VERTEX) { + // just reselect the vertex by the id of edge + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + // if aSubIds take any, the first appropriate + int aFeatureID = aComposite->subFeatureId(a); + if (aSubIds->IsEmpty() || aSubIds->Contains(aFeatureID)) { + // searching for deltas + int aVertexNum = 0; + if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1; + else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) aVertexNum = 2; + // found the feature with appropriate edge + FeaturePtr aFeature = aComposite->subFeature(a); + std::list >::const_iterator aResIter = + aFeature->results().cbegin(); + for(;aResIter != aFeature->results().cend(); aResIter++) { + ResultConstructionPtr aRes = + std::dynamic_pointer_cast(*aResIter); + if (aRes && aRes->shape()) { + if (aRes->shape()->isVertex() && aVertexNum == 0) { // found! + selectConstruction(aContext, aRes->shape()); + owner()->data()->sendAttributeUpdated(this); + return true; + } else if (aRes->shape()->isEdge() && aVertexNum > 0) { + const TopoDS_Shape& anEdge = aRes->shape()->impl(); + int aVIndex = 1; + for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { + if (aVIndex == aVertexNum) { // found! + std::shared_ptr aVertex(new GeomAPI_Shape); + aVertex->setImpl(new TopoDS_Shape(aVExp.Current())); + selectConstruction(aContext, aVertex); + owner()->data()->sendAttributeUpdated(this); + return true; + } + aVIndex++; + } + } + } + } + } + } + } + } else { // simple construction element: the selected is that needed + owner()->data()->sendAttributeUpdated(this); + return true; + } + } + return false; // unknown case +} + + +void Model_AttributeSelection::selectBody( + const ResultPtr& theContext, const std::shared_ptr& theSubShape) +{ + // perform the selection + TNaming_Selector aSel(selectionLabel()); + TopoDS_Shape aNewShape = theSubShape ? theSubShape->impl() : TopoDS_Shape(); + TopoDS_Shape aContext; + + ResultBodyPtr aBody = std::dynamic_pointer_cast(myRef.value()); + if (aBody) + aContext = aBody->shape()->impl(); + else { + ResultConstructionPtr aConstr = std::dynamic_pointer_cast(myRef.value()); + if (aConstr) { + aContext = aConstr->shape()->impl(); + } else { + Events_Error::send("A result with shape is expected"); + return; + } + } + aSel.Select(aNewShape, aContext); +} + +void Model_AttributeSelection::selectConstruction( + const ResultPtr& theContext, const std::shared_ptr& theSubShape) +{ + FeaturePtr aContextFeature = theContext->document()->feature(theContext); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aContextFeature); + if (!aComposite || aComposite->numberOfSubs() == 0) { + return; // saving of context is enough: result construction contains exactly the needed shape + } + std::shared_ptr aData = std::dynamic_pointer_cast(owner()->data()); + TDF_Label aLab = myRef.myRef->Label(); + // identify the reuslts of sub-object of the composite by edges + const TopoDS_Shape& aSubShape = theSubShape->impl(); + // save type of the selected shape in integer attribute + TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType(); + TDataStd_Integer::Set(aLab, (int)aShapeType); + gp_Pnt aVertexPos; + TColStd_MapOfTransient allCurves; + if (aShapeType == TopAbs_VERTEX) { // compare positions + aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape)); + } else { + for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) { + TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + allCurves.Add(aCurve); + } + } + // iterate and store the result ids of sub-elements + Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab); + aRefs->Clear(); + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + FeaturePtr aSub = aComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + // there may be many shapes (circle and center): register if at least one is in selection + for(; aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (!aConstr->shape()) { + continue; + } + if (aShapeType == TopAbs_VERTEX) { + if (aConstr->shape()->isVertex()) { // compare vertices positions + const TopoDS_Shape& aVertex = aConstr->shape()->impl(); + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex)); + if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { + aRefs->Add(aComposite->subFeatureId(a)); + } + } else { // get first or last vertex of the edge: last is stored with negative sign + const TopoDS_Shape& anEdge = aConstr->shape()->impl(); + int aDelta = kSTART_VERTEX_DELTA; + for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current())); + if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { + aRefs->Add(aComposite->subFeatureId(a)); + aRefs->Add(aDelta + aComposite->subFeatureId(a)); + break; + } + aDelta += kSTART_VERTEX_DELTA; + } + } + } else { + if (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); + if (allCurves.Contains(aCurve)) { + int anID = aComposite->subFeatureId(a); + aRefs->Add(anID); + // add edges to sub-label to support naming for edges selection + for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) { + TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (aFaceCurve == aCurve) { + TNaming_Builder anEdgeBuilder(selectionLabel().FindChild(anID)); + anEdgeBuilder.Generated(anEdge); + } + } + } + } + } + } + } + } + // store the selected as primitive + TNaming_Builder aBuilder(selectionLabel()); + aBuilder.Generated(aSubShape); +} + +TDF_Label Model_AttributeSelection::selectionLabel() +{ + return myRef.myRef->Label().FindChild(1); +} + +#define FIX_BUG1 1 +std::string GetShapeName(std::shared_ptr theDoc, const TopoDS_Shape& theShape, + const TDF_Label& theLabel) +{ + std::string aName; + // check if the subShape is already in DF + Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(theShape, theLabel); + Handle(TDataStd_Name) anAttr; + if(!aNS.IsNull() && !aNS->IsEmpty()) { // in the document + if(aNS->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) { + aName = TCollection_AsciiString(anAttr->Get()).ToCString(); + if(!aName.empty()) { + const TDF_Label& aLabel = theDoc->findNamingName(aName); + if(!aLabel.IsEqual(aNS->Label())) { + //aName.erase(); //something is wrong, to be checked!!! + aName += "_SomethingWrong"; + return aName; + } + const TopoDS_Shape& aShape = aNS->Get(); + if(aShape.ShapeType() == TopAbs_COMPOUND) { + std::string aPostFix("_"); + TopoDS_Iterator it(aShape); + for (int i = 1;it.More();it.Next(), i++) { + if(it.Value() == theShape) { + aPostFix += TCollection_AsciiString (i).ToCString(); + aName += aPostFix; + break; + } + else continue; + } + } + } + } + } + return aName; +} + +bool isTrivial (const TopTools_ListOfShape& theAncestors, TopTools_IndexedMapOfShape& theSMap) +{ +// a trivial case: F1 & F2, aNumber = 1, i.e. intersection gives 1 edge. + TopoDS_Compound aCmp; + BRep_Builder BB; + BB.MakeCompound(aCmp); + TopTools_ListIteratorOfListOfShape it(theAncestors); + for(;it.More();it.Next()) { + BB.Add(aCmp, it.Value()); + theSMap.Add(it.Value()); + } + int aNumber(0); + TopTools_IndexedDataMapOfShapeListOfShape aMap2; + TopExp::MapShapesAndAncestors(aCmp, TopAbs_EDGE, TopAbs_FACE, aMap2); + for (int i = 1; i <= aMap2.Extent(); i++) { + const TopoDS_Shape& aKey = aMap2.FindKey(i); + const TopTools_ListOfShape& anAncestors = aMap2.FindFromIndex(i); + if(anAncestors.Extent() > 1) aNumber++; + } + if(aNumber > 1) return false; + return true; +} +std::string Model_AttributeSelection::namingName()//std::shared_ptr theSubShape, + // const ResultPtr& theContext) +{ + std::shared_ptr aSubSh = value(); + ResultPtr aCont = context(); + std::string aName; + if(!aSubSh.get() || aSubSh->isNull() || !aCont.get() || aCont->shape()->isNull()) + return aName; + TopoDS_Shape aSubShape = aSubSh->impl(); + TopoDS_Shape aContext = aCont->shape()->impl(); + std::shared_ptr aDoc = + std::dynamic_pointer_cast(aCont->document()); + + // check if the subShape is already in DF + aName = GetShapeName(aDoc, aSubShape, selectionLabel()); + if(aName.empty() ) { // not in the document! + 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 + 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 + TopTools_IndexedDataMapOfShapeListOfShape aMap; + TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap); + 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 + + const TopTools_ListOfShape& anAncestors = aMap.FindFromIndex(i); + // check that it is not a trivial case (F1 & F2: aNumber = 1) + isTrivialCase = isTrivial(anAncestors, aSMap); + 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, selectionLabel()); + if(i == 1) + aName = aFaceName; + else + aName += "|" + aFaceName; + } + TopTools_ListIteratorOfListOfShape itl(aListOfNbs); + for (;itl.More();itl.Next()) { + std::string aFaceName = GetShapeName(aDoc, itl.Value(), selectionLabel()); + aName += "|" + aFaceName; + } + } + break; + + case TopAbs_VERTEX: + // name structure (Monifold Topology): + // 1) F1 | F2 | F3 - intersection of 3 faces defines a vertex - trivial case. + // 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 + // or compound of 2 open faces. + // 4) E1 | E2 - intesection of 2 edges defines a vertex - when we have a case of + // two independent edges (wire or compound) + // implemented 2 first cases + { + TopTools_IndexedDataMapOfShapeListOfShape aMap; + TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_FACE, aMap); + const TopTools_ListOfShape& aList2 = aMap.FindFromKey(aSubShape); + TopTools_ListOfShape aList; + TopTools_MapOfShape aFMap; +#ifdef FIX_BUG1 + //int n = aList2.Extent(); //bug! + // 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(); +#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; + } + } + break; + } + // register name + // aDoc->addNamingName(selectionLabel(), aName); + // the selected sub-shape will not be shared and as result it will not require registration + } + return aName; +}