]> SALOME platform Git repositories - modules/shaper.git/blob - src/Model/Model_AttributeSelection.cpp
Salome HOME
ac7f99bf604a6e5d2b2222cc63b5e4daf9500157
[modules/shaper.git] / src / Model / Model_AttributeSelection.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        Model_AttributeSelection.h
4 // Created:     2 Oct 2014
5 // Author:      Mikhail PONIKAROV
6
7 #include "Model_AttributeSelection.h"
8 #include "Model_Application.h"
9 #include "Model_Events.h"
10 #include "Model_Data.h"
11 #include <ModelAPI_Feature.h>
12 #include <ModelAPI_ResultBody.h>
13 #include <ModelAPI_ResultConstruction.h>
14 #include <ModelAPI_CompositeFeature.h>
15 #include <GeomAPI_Shape.h>
16 #include <GeomAPI_PlanarEdges.h>
17 #include <GeomAlgoAPI_SketchBuilder.h>
18 #include <Events_Error.h>
19
20 #include <TNaming_Selector.hxx>
21 #include <TNaming_NamedShape.hxx>
22 #include <TNaming_Tool.hxx>
23 #include <TNaming_Builder.hxx>
24 #include <TNaming_Localizer.hxx>
25 #include <TopoDS_Shape.hxx>
26 #include <TopoDS_Compound.hxx>
27 #include <TDataStd_IntPackedMap.hxx>
28 #include <TDataStd_Integer.hxx>
29 #include <TDataStd_UAttribute.hxx>
30 #include <TopTools_MapOfShape.hxx>
31 #include <TopTools_IndexedMapOfShape.hxx>
32 #include <TopTools_MapIteratorOfMapOfShape.hxx>
33 #include <TopTools_ListOfShape.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <TDF_LabelMap.hxx>
36 #include <BRep_Tool.hxx>
37 #include <BRep_Builder.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS.hxx>
40 #include <TopExp.hxx>
41 #include <TColStd_MapOfTransient.hxx>
42 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
43 #include <TopTools_ListIteratorOfListOfShape.hxx>
44 #include <gp_Pnt.hxx>
45 #include <Precision.hxx>
46 #include <TDF_ChildIterator.hxx>
47 #include <TDF_ChildIDIterator.hxx>
48 #include <TDataStd_Name.hxx>
49 #include <TopAbs_ShapeEnum.hxx>
50 #include <TopoDS_Iterator.hxx>
51 using namespace std;
52 /// adeed to the index in the packed map to signalize that the vertex of edge is seleted
53 /// (multiplied by the index of the edge)
54 static const int kSTART_VERTEX_DELTA = 1000000;
55 // identifier that there is simple reference: selection equals to context
56 Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29");
57
58 // on this label is stored:
59 // TNaming_NamedShape - selected shape
60 // TNaming_Naming - topological selection information (for the body)
61 // TDataStd_IntPackedMap - indexes of edges in composite element (for construction)
62 // TDataStd_Integer - type of the selected shape (for construction)
63 // TDF_Reference - from ReferenceAttribute, the context
64
65 void Model_AttributeSelection::setValue(const ResultPtr& theContext,
66   const std::shared_ptr<GeomAPI_Shape>& theSubShape)
67 {
68   const std::shared_ptr<GeomAPI_Shape>& anOldShape = value();
69   bool isOldShape = 
70     (theSubShape == anOldShape || (theSubShape && anOldShape && theSubShape->isEqual(anOldShape)));
71   if (isOldShape) return; // shape is the same, so context is also unchanged
72   // update the referenced object if needed
73   bool isOldContext = theContext == myRef.value();
74
75
76   if (!isOldContext)
77     myRef.setValue(theContext);
78
79   // do noth use naming if selected shape is result shape itself, but not sub-shape
80   TDF_Label aSelLab = selectionLabel();
81   if (theContext->shape().get() && theContext->shape()->isEqual(theSubShape)) {
82     aSelLab.ForgetAllAttributes(true);
83     TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID);
84   } else {
85     aSelLab.ForgetAttribute(kSIMPLE_REF_ID);
86     if (theContext->groupName() == ModelAPI_ResultBody::group())
87       selectBody(theContext, theSubShape);
88     else if (theContext->groupName() == ModelAPI_ResultConstruction::group())
89       selectConstruction(theContext, theSubShape);
90   }
91
92   std::string aSelName = namingName();
93   if(!aSelName.empty())
94           TDataStd_Name::Set(selectionLabel(), aSelName.c_str()); //set name
95
96   myIsInitialized = true;
97   owner()->data()->sendAttributeUpdated(this);
98 }
99
100 std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
101 {
102   std::shared_ptr<GeomAPI_Shape> aResult;
103   if (myIsInitialized) {
104     TDF_Label aSelLab = selectionLabel();
105     if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape
106       ResultPtr aContext = context();
107       if (!aContext.get()) 
108         return aResult; // empty result
109       return aContext->shape();
110     }
111
112     Handle(TNaming_NamedShape) aSelection;
113     if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
114       TopoDS_Shape aSelShape = aSelection->Get();
115       aResult = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
116       aResult->setImpl(new TopoDS_Shape(aSelShape));
117     } else { // for simple construction element: just shape of this construction element
118       ResultConstructionPtr aConstr = 
119         std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(context());
120       if (aConstr) {
121         return aConstr->shape();
122       }
123     }
124   }
125   return aResult;
126 }
127
128 Model_AttributeSelection::Model_AttributeSelection(TDF_Label& theLabel)
129   : myRef(theLabel)
130 {
131   myIsInitialized = myRef.isInitialized();
132 }
133
134 ResultPtr Model_AttributeSelection::context() {
135   return std::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
136 }
137
138
139 void Model_AttributeSelection::setObject(const std::shared_ptr<ModelAPI_Object>& theObject)
140 {
141   ModelAPI_AttributeSelection::setObject(theObject);
142   myRef.setObject(theObject);
143 }
144
145 TDF_LabelMap& Model_AttributeSelection::scope()
146 {
147   if (myScope.IsEmpty()) { // create a new scope if not yet done
148     // gets all labels with named shapes that are bofore this feature label (before in history)
149     TDF_Label aFeatureLab = std::dynamic_pointer_cast<Model_Data>(
150       owner()->data())->label().Father();
151     int aFeatureID = aFeatureLab.Tag();
152     TDF_ChildIterator aFeaturesIter(aFeatureLab.Father());
153     for(; aFeaturesIter.More(); aFeaturesIter.Next()) {
154       if (aFeaturesIter.Value().Tag() >= aFeatureID) // the left labels are created later
155         break;
156       TDF_ChildIDIterator aNSIter(aFeaturesIter.Value(), TNaming_NamedShape::GetID(), 1);
157       for(; aNSIter.More(); aNSIter.Next()) {
158         Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value());
159         if (!aNS.IsNull() && aNS->Evolution() != TNaming_SELECTED) {
160           myScope.Add(aNS->Label());
161         }
162       }
163     }
164   }
165   return myScope;
166 }
167
168 bool Model_AttributeSelection::update()
169 {
170   ResultPtr aContext = context();
171   if (!aContext.get()) return false;
172   TDF_Label aSelLab = selectionLabel();
173   if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape
174     return aContext->shape() && !aContext->shape()->isNull();
175   }
176
177   if (aContext->groupName() == ModelAPI_ResultBody::group()) {
178     // body: just a named shape, use selection mechanism from OCCT
179     TNaming_Selector aSelector(aSelLab);
180     bool aResult = aSelector.Solve(scope()) == Standard_True;
181     owner()->data()->sendAttributeUpdated(this);
182     return aResult;
183   } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) {
184     // construction: identification by the results indexes, recompute faces and
185     // take the face that more close by the indexes
186     std::shared_ptr<GeomAPI_PlanarEdges> aWirePtr = 
187       std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(
188       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext)->shape());
189     if (aWirePtr && aWirePtr->hasPlane()) { // sketch sub-element
190       TDF_Label aLab = myRef.myRef->Label();
191       // getting a type of selected shape
192       Handle(TDataStd_Integer) aTypeAttr;
193       if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) {
194         return false;
195       }
196       TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get());
197       // selected indexes will be needed in each "if"
198       Handle(TDataStd_IntPackedMap) aSubIds;
199       std::shared_ptr<GeomAPI_Shape> aNewSelected;
200       bool aNoIndexes = 
201         !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0;
202       // for now working only with composite features
203       FeaturePtr aContextFeature = aContext->document()->feature(aContext);
204       CompositeFeaturePtr aComposite = 
205         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature);
206       if (!aComposite || aComposite->numberOfSubs() == 0) {
207         return false;
208       }
209
210       if (aShapeType == TopAbs_FACE) {
211         // If this is a wire with plane defined thin it is a sketch-like object
212         std::list<std::shared_ptr<GeomAPI_Shape> > aFaces;
213         GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(),
214           aWirePtr->dirY(), aWirePtr->norm(), aWirePtr, aFaces);
215         if (aFaces.empty()) // no faces, update can not work correctly
216           return false;
217         // if there is no edges indexes, any face can be used: take the first
218         std::shared_ptr<GeomAPI_Shape> aNewSelected;
219         if (aNoIndexes) {
220           aNewSelected = *(aFaces.begin());
221         } else { // searching for most looks-like initial face by the indexes
222           // prepare edges of the current resut for the fast searching
223           TColStd_MapOfTransient allCurves;
224           const int aSubNum = aComposite->numberOfSubs();
225           for(int a = 0; a < aSubNum; a++) {
226             if (aSubIds->Contains(aComposite->subFeatureId(a))) {
227               FeaturePtr aSub = aComposite->subFeature(a);
228               const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
229               std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes;
230               for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) {
231                 ResultConstructionPtr aConstr = 
232                   std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
233                 if (aConstr->shape() && aConstr->shape()->isEdge()) {
234                   const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
235                   TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
236                   if (!anEdge.IsNull()) {
237                     Standard_Real aFirst, aLast;
238                     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
239                     allCurves.Add(aCurve);
240                   }
241                 }
242               }
243             }
244           }
245           // iterate new result faces and searching for these edges
246           std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aFacesIter = aFaces.begin();
247           double aBestFound = 0; // best percentage of found edges
248           for(; aFacesIter != aFaces.end(); aFacesIter++) {
249             int aFound = 0, aNotFound = 0;
250             TopExp_Explorer anEdgesExp((*aFacesIter)->impl<TopoDS_Shape>(), TopAbs_EDGE);
251             for(; anEdgesExp.More(); anEdgesExp.Next()) {
252               TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current());
253               if (!anEdge.IsNull()) {
254                 Standard_Real aFirst, aLast;
255                 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
256                 if (allCurves.Contains(aCurve)) {
257                   aFound++;
258                 } else {
259                   aNotFound++;
260                 }
261               }
262             }
263             if (aFound + aNotFound != 0) {
264               double aPercentage = double(aFound) / double(aFound + aNotFound);
265               if (aPercentage > aBestFound) {
266                 aBestFound = aPercentage;
267                 aNewSelected = *aFacesIter;
268               }
269             }
270           }
271         }
272         if (aNewSelected) { // store this new selection
273           selectConstruction(aContext, aNewSelected);
274           owner()->data()->sendAttributeUpdated(this);
275           return true;
276         }
277       } else if (aShapeType == TopAbs_EDGE) {
278         // just reselect the edge by the id
279         const int aSubNum = aComposite->numberOfSubs();
280         for(int a = 0; a < aSubNum; a++) {
281           // if aSubIds take any, the first appropriate
282           if (aSubIds->IsEmpty() || aSubIds->Contains(aComposite->subFeatureId(a))) {
283             // found the appropriate feature
284             FeaturePtr aFeature = aComposite->subFeature(a);
285             std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
286               aFeature->results().cbegin();
287             for(;aResIter != aFeature->results().cend(); aResIter++) {
288               ResultConstructionPtr aRes = 
289                 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIter);
290               if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found!
291                 selectConstruction(aContext, aRes->shape());
292                 owner()->data()->sendAttributeUpdated(this);
293                 return true;
294               }
295             }
296           }
297         }
298       } else if (aShapeType == TopAbs_VERTEX) {
299         // just reselect the vertex by the id of edge
300         const int aSubNum = aComposite->numberOfSubs();
301         for(int a = 0; a < aSubNum; a++) {
302           // if aSubIds take any, the first appropriate
303           int aFeatureID = aComposite->subFeatureId(a);
304           if (aSubIds->IsEmpty() || aSubIds->Contains(aFeatureID)) {
305             // searching for deltas
306             int aVertexNum = 0;
307             if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1;
308             else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) aVertexNum = 2;
309             // found the feature with appropriate edge
310             FeaturePtr aFeature = aComposite->subFeature(a);
311             std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
312               aFeature->results().cbegin();
313             for(;aResIter != aFeature->results().cend(); aResIter++) {
314               ResultConstructionPtr aRes = 
315                 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIter);
316               if (aRes && aRes->shape()) {
317                 if (aRes->shape()->isVertex() && aVertexNum == 0) { // found!
318                   selectConstruction(aContext, aRes->shape());
319                   owner()->data()->sendAttributeUpdated(this);
320                   return true;
321                 } else if (aRes->shape()->isEdge() && aVertexNum > 0) {
322                   const TopoDS_Shape& anEdge = aRes->shape()->impl<TopoDS_Shape>();
323                   int aVIndex = 1;
324                   for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
325                     if (aVIndex == aVertexNum) { // found!
326                       std::shared_ptr<GeomAPI_Shape> aVertex(new GeomAPI_Shape);
327                       aVertex->setImpl(new TopoDS_Shape(aVExp.Current()));
328                       selectConstruction(aContext, aVertex);
329                       owner()->data()->sendAttributeUpdated(this);
330                       return true;
331                     }
332                     aVIndex++;
333                   }
334                 }
335               }
336             }
337           }
338         }
339       }
340     } else { // simple construction element: the selected is that needed
341       owner()->data()->sendAttributeUpdated(this);
342       return true;
343     }
344   }
345   return false; // unknown case
346 }
347
348
349 void Model_AttributeSelection::selectBody(
350     const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape)
351 {
352   // perform the selection
353   TNaming_Selector aSel(selectionLabel());
354   TopoDS_Shape aNewShape = theSubShape ? theSubShape->impl<TopoDS_Shape>() : TopoDS_Shape();
355   TopoDS_Shape aContext;
356
357   ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myRef.value());
358   if (aBody)
359     aContext = aBody->shape()->impl<TopoDS_Shape>();
360   else {
361     ResultConstructionPtr aConstr = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(myRef.value());
362     if (aConstr) {
363       aContext = aConstr->shape()->impl<TopoDS_Shape>();
364     } else {
365       Events_Error::send("A result with shape is expected");
366       return;
367     }
368   }
369   aSel.Select(aNewShape, aContext);
370 }
371
372 void Model_AttributeSelection::selectConstruction(
373     const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape)
374 {
375   FeaturePtr aContextFeature = theContext->document()->feature(theContext);
376   CompositeFeaturePtr aComposite = 
377     std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature);
378   if (!aComposite || aComposite->numberOfSubs() == 0) {
379     return; // saving of context is enough: result construction contains exactly the needed shape
380   }
381   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(owner()->data());
382   TDF_Label aLab = myRef.myRef->Label();
383   // identify the reuslts of sub-object of the composite by edges
384   const TopoDS_Shape& aSubShape = theSubShape->impl<TopoDS_Shape>();
385   // save type of the selected shape in integer attribute
386   TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType();
387   TDataStd_Integer::Set(aLab, (int)aShapeType);
388   gp_Pnt aVertexPos;
389   TColStd_MapOfTransient allCurves;
390   if (aShapeType == TopAbs_VERTEX) { // compare positions
391     aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape));
392   } else { 
393     for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) {
394       TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
395       Standard_Real aFirst, aLast;
396       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
397       allCurves.Add(aCurve);
398     }
399   }
400   // iterate and store the result ids of sub-elements
401   Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab);
402   aRefs->Clear();
403   const int aSubNum = aComposite->numberOfSubs();
404   for(int a = 0; a < aSubNum; a++) {
405     FeaturePtr aSub = aComposite->subFeature(a);
406     const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
407     std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
408     // there may be many shapes (circle and center): register if at least one is in selection
409     for(; aRes != aResults.cend(); aRes++) {
410       ResultConstructionPtr aConstr = 
411         std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
412       if (!aConstr->shape()) {
413         continue;
414       }
415       if (aShapeType == TopAbs_VERTEX) {
416         if (aConstr->shape()->isVertex()) { // compare vertices positions
417           const TopoDS_Shape& aVertex = aConstr->shape()->impl<TopoDS_Shape>();
418           gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
419           if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
420             aRefs->Add(aComposite->subFeatureId(a));
421           }
422         } else { // get first or last vertex of the edge: last is stored with negative sign
423           const TopoDS_Shape& anEdge = aConstr->shape()->impl<TopoDS_Shape>();
424           int aDelta = kSTART_VERTEX_DELTA;
425           for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
426             gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current()));
427             if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
428               aRefs->Add(aComposite->subFeatureId(a));
429               aRefs->Add(aDelta + aComposite->subFeatureId(a));
430               break;
431             }
432             aDelta += kSTART_VERTEX_DELTA;
433           }
434         }
435       } else {
436         if (aConstr->shape()->isEdge()) {
437           const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
438           TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
439           if (!anEdge.IsNull()) {
440             Standard_Real aFirst, aLast;
441             Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
442             if (allCurves.Contains(aCurve)) {
443               int anID = aComposite->subFeatureId(a);
444               aRefs->Add(anID);
445               // add edges to sub-label to support naming for edges selection
446               TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE);
447               for(; anEdgeExp.More(); anEdgeExp.Next()) {
448                 TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
449                 Standard_Real aFirst, aLast;
450                 Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
451                 if (aFaceCurve == aCurve) {
452                   TNaming_Builder anEdgeBuilder(selectionLabel().FindChild(anID));
453                   anEdgeBuilder.Generated(anEdge);
454                 }
455               }
456             }
457           }
458         }
459       }
460     }
461   }
462   // store the selected as primitive
463   TNaming_Builder aBuilder(selectionLabel());
464   aBuilder.Generated(aSubShape);
465 }
466
467 TDF_Label Model_AttributeSelection::selectionLabel()
468 {
469   return myRef.myRef->Label().FindChild(1);
470 }
471
472 #define FIX_BUG1 1
473 std::string GetShapeName(std::shared_ptr<Model_Document> theDoc, const TopoDS_Shape& theShape, 
474                                              const TDF_Label& theLabel)
475 {
476   std::string aName;
477   // check if the subShape is already in DF
478   Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(theShape, theLabel);
479   Handle(TDataStd_Name) anAttr;
480   if(!aNS.IsNull() && !aNS->IsEmpty()) { // in the document    
481         if(aNS->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) {
482           aName = TCollection_AsciiString(anAttr->Get()).ToCString();
483           if(!aName.empty()) {      
484             const TDF_Label& aLabel = theDoc->findNamingName(aName);
485                 if(!aLabel.IsEqual(aNS->Label())) {
486                   //aName.erase(); //something is wrong, to be checked!!!
487                   aName += "_SomethingWrong";
488                   return aName;
489                 }
490                 const TopoDS_Shape& aShape = aNS->Get();
491                 if(aShape.ShapeType() == TopAbs_COMPOUND) {
492                   std::string aPostFix("_");
493                   TopoDS_Iterator it(aShape);                   
494                   for (int i = 1;it.More();it.Next(), i++) {
495                     if(it.Value() == theShape) {
496                           aPostFix += TCollection_AsciiString (i).ToCString();
497                           aName    += aPostFix;
498                           break;
499                         }
500                         else continue;                                          
501                   }
502                 }
503           }     
504         }
505   }
506   return aName;
507 }
508
509 bool isTrivial (const TopTools_ListOfShape& theAncestors, TopTools_IndexedMapOfShape& theSMap)
510 {
511 // a trivial case: F1 & F2,  aNumber = 1, i.e. intersection gives 1 edge.
512   TopoDS_Compound aCmp;
513   BRep_Builder BB;
514   BB.MakeCompound(aCmp);
515   TopTools_ListIteratorOfListOfShape it(theAncestors);
516   for(;it.More();it.Next()) {
517         BB.Add(aCmp, it.Value());
518         theSMap.Add(it.Value());
519   }
520   int aNumber(0);
521   TopTools_IndexedDataMapOfShapeListOfShape aMap2;
522   TopExp::MapShapesAndAncestors(aCmp, TopAbs_EDGE, TopAbs_FACE, aMap2);
523   for (int i = 1; i <= aMap2.Extent(); i++) {
524         const TopoDS_Shape& aKey = aMap2.FindKey(i);
525         const TopTools_ListOfShape& anAncestors = aMap2.FindFromIndex(i);
526         if(anAncestors.Extent() > 1) aNumber++;
527   }
528   if(aNumber > 1) return false;
529   return true;
530 }
531 std::string Model_AttributeSelection::namingName()//std::shared_ptr<GeomAPI_Shape> theSubShape, 
532                                                         // const ResultPtr& theContext)
533 {
534   std::shared_ptr<GeomAPI_Shape> aSubSh = value();
535   ResultPtr aCont = context();
536   std::string aName;
537   if(!aSubSh.get() || aSubSh->isNull() || !aCont.get() || aCont->shape()->isNull()) 
538     return aName;
539   TopoDS_Shape aSubShape = aSubSh->impl<TopoDS_Shape>();
540   TopoDS_Shape aContext  = aCont->shape()->impl<TopoDS_Shape>();
541   std::shared_ptr<Model_Document> aDoc = 
542     std::dynamic_pointer_cast<Model_Document>(aCont->document());
543
544   // check if the subShape is already in DF
545   aName = GetShapeName(aDoc, aSubShape, selectionLabel());
546   if(aName.empty() ) { // not in the document!
547     TopAbs_ShapeEnum aType = aSubShape.ShapeType();
548         switch (aType) {
549           case TopAbs_FACE:
550       // the Face should be in DF. If it is not a case, it is an error ==> to be dbugged                
551                 break;
552           case TopAbs_EDGE:
553                   {
554                   // name structure: F1 | F2 [| F3 | F4], where F1 & F2 the faces which gives the Edge in trivial case
555                   // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces
556                   TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape
557                   TopTools_IndexedDataMapOfShapeListOfShape aMap;
558                   TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap);
559                   bool isTrivialCase(true);
560                   for (int i = 1; i <= aMap.Extent(); i++) {
561                         const TopoDS_Shape& aKey = aMap.FindKey(i);
562                         if (aKey.IsNotEqual(aSubShape)) continue; // find exactly the selected key
563
564             const TopTools_ListOfShape& anAncestors = aMap.FindFromIndex(i);
565                         // check that it is not a trivial case (F1 & F2: aNumber = 1)
566                         isTrivialCase = isTrivial(anAncestors, aSMap);                  
567                         break;
568                   }
569
570                   TopTools_ListOfShape aListOfNbs;
571                   if(!isTrivialCase) { // find Neighbors
572                         TNaming_Localizer aLocalizer;
573                         TopTools_MapOfShape aMap3;
574                         aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3);
575                         //int n = aMap3.Extent();
576                         TopTools_MapIteratorOfMapOfShape it(aMap3);
577                         for(;it.More();it.Next()) {
578                           const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge
579                           //TopAbs_ShapeEnum aType = aNbShape.ShapeType();
580                           const TopTools_ListOfShape& aList  = aMap.FindFromKey(aNbShape);
581                           TopTools_ListIteratorOfListOfShape it2(aList);
582                           for(;it2.More();it2.Next()) {
583                                 if(aSMap.Contains(it2.Value())) continue; // skip this Face
584                                 aListOfNbs.Append(it2.Value());
585                           }
586                         }
587                   }  // else a trivial case
588                   
589                   // build name of the sub-shape Edge
590                   for(int i=1; i <= aSMap.Extent(); i++) {
591                         const TopoDS_Shape& aFace = aSMap.FindKey(i);
592                         std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel());
593                         if(i == 1)
594                           aName = aFaceName;
595                         else 
596                           aName += "|" + aFaceName;
597                   }
598                   TopTools_ListIteratorOfListOfShape itl(aListOfNbs);
599                   for (;itl.More();itl.Next()) {
600                         std::string aFaceName = GetShapeName(aDoc, itl.Value(), selectionLabel());
601                         aName += "|" + aFaceName;
602                   }               
603                   }
604                   break;
605
606           case TopAbs_VERTEX:
607                   // name structure (Monifold Topology): 
608                   // 1) F1 | F2 | F3 - intersection of 3 faces defines a vertex - trivial case.
609                   // 2) F1 | F2      - intersection of 2 faces definses a vertex - applicable for case
610                   //                   when 1 faces is cylindrical, conical, spherical or revolution and etc.
611                   // 3) E1 | E2 | E3 - intersection of 3 edges defines a vertex - when we have case of a shell
612                   //                   or compound of 2 open faces.
613                   // 4) E1 | E2      - intesection of 2 edges defines a vertex - when we have a case of 
614                   //                   two independent edges (wire or compound)
615                   // implemented 2 first cases
616                   {
617                         TopTools_IndexedDataMapOfShapeListOfShape aMap;
618                     TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_FACE, aMap);
619                         const TopTools_ListOfShape& aList2  = aMap.FindFromKey(aSubShape);
620                         TopTools_ListOfShape aList;
621                         TopTools_MapOfShape aFMap;
622 #ifdef FIX_BUG1
623                         //int n = aList2.Extent(); //bug!
624                         // fix is below
625                         TopTools_ListIteratorOfListOfShape itl2(aList2);
626                     for (int i = 1;itl2.More();itl2.Next(),i++) {
627                           if(aFMap.Add(itl2.Value()))
628                                 aList.Append(itl2.Value());
629                         }
630                         //n = aList.Extent();
631 #endif
632                         TopTools_ListIteratorOfListOfShape itl(aList);
633                     for (int i = 1;itl.More();itl.Next(),i++) {
634                           const TopoDS_Shape& aFace = itl.Value();
635                           std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel());
636                           if(i == 1)
637                             aName = aFaceName;
638                           else 
639                             aName += "|" + aFaceName;
640                         }
641                   }
642                   break;
643         }
644     // register name                    
645     // aDoc->addNamingName(selectionLabel(), aName);
646         // the selected sub-shape will not be shared and as result it will not require registration
647   }
648   return aName;
649 }