Salome HOME
38d349bd7386b89dd822b2ab45ff9d03d22b4c22
[modules/shaper.git] / src / Model / Model_BodyBuilder.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        Model_ResultBody.cpp
4 // Created:     08 Jul 2014
5 // Author:      Mikhail PONIKAROV
6
7 #include <Model_BodyBuilder.h>
8
9 #include <Model_Data.h>
10 #include <Model_Document.h>
11 #include <TNaming_Builder.hxx>
12 #include <TNaming_NamedShape.hxx>
13 #include <TNaming_Iterator.hxx>
14 #include <TNaming_Tool.hxx>
15 #include <TDataStd_Name.hxx>
16 #include <TDataStd_Integer.hxx>
17 #include <TopoDS.hxx>
18 #include <TopoDS_Face.hxx>
19 #include <TDF_ChildIterator.hxx>
20 #include <TDF_Reference.hxx>
21 #include <TopTools_MapOfShape.hxx>
22 #include <TopExp_Explorer.hxx>
23 #include <TopTools_ListOfShape.hxx>
24 #include <TopTools_ListIteratorOfListOfShape.hxx>
25 #include <TopTools_DataMapOfShapeListOfShape.hxx>
26 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
27 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
28 #include <TopTools_MapIteratorOfMapOfShape.hxx>
29 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
30 #include <TopTools_IndexedMapOfShape.hxx>
31 #include <TopTools_DataMapOfShapeShape.hxx>
32 #include <TopExp.hxx>
33 #include <BRepTools.hxx>
34 #include <BRep_Tool.hxx>
35 #include <GeomAPI_Shape.h>
36 #include <GeomAlgoAPI_MakeShape.h>
37 #include <Config_PropManager.h>
38 // DEB
39 //#include <TCollection_AsciiString.hxx>
40 //#include <TDF_Tool.hxx>
41 //#define DEB_IMPORT 1
42
43 Model_BodyBuilder::Model_BodyBuilder(ModelAPI_Object* theOwner)
44 : ModelAPI_BodyBuilder(theOwner)
45 {
46 }
47
48 // Converts evolution of naming shape to selection evelution and back to avoid
49 // naming support on the disabled results. Deeply in the labels tree, recursively.
50 static void evolutionToSelectionRec(TDF_Label theLab, const bool theFlag) {
51   std::list<std::pair<TopoDS_Shape, TopoDS_Shape> > aShapePairs; // to store old and new shapes
52   Handle(TNaming_NamedShape) aName;
53   int anEvolution = -1;
54   if (theLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
55     TNaming_Evolution aNSEvol = aName->Evolution();
56     if ((aNSEvol == TNaming_SELECTED && theFlag) ||
57         (aNSEvol != TNaming_SELECTED && !theFlag)) { // nothing to do, it is already correct
58       return;
59     }
60     anEvolution = (int)(aNSEvol);
61     if (!theFlag) {
62       Handle(TDataStd_Integer) anAttrEvol;
63       if (theLab.FindAttribute(TDataStd_Integer::GetID(), anAttrEvol)) {
64         anEvolution = anAttrEvol->Get();
65       }
66     } else {
67       TDataStd_Integer::Set(theLab, anEvolution);
68     }
69
70     for(TNaming_Iterator anIter(aName); anIter.More(); anIter.Next()) {
71       // iterator goes in reversed order relatively to the Builder, to, make the list reversed
72       aShapePairs.push_front(std::pair<TopoDS_Shape, TopoDS_Shape>
73         (anIter.OldShape(), anIter.NewShape()));
74     }
75
76     // create new
77     TNaming_Builder aBuilder(theLab);
78     TNaming_Evolution anEvol = (TNaming_Evolution)(anEvolution);
79     std::list<std::pair<TopoDS_Shape, TopoDS_Shape> >::iterator aPairsIter = aShapePairs.begin();
80     for(; aPairsIter != aShapePairs.end(); aPairsIter++) {
81       if (theFlag) { // disabled => make selection
82         aBuilder.Select(aPairsIter->second, aPairsIter->first);
83       } else if (anEvol == TNaming_GENERATED) {
84         aBuilder.Generated(aPairsIter->first, aPairsIter->second);
85       } else if (anEvol == TNaming_MODIFY) {
86         aBuilder.Modify(aPairsIter->first, aPairsIter->second);
87       } else if (anEvol == TNaming_DELETE) {
88         aBuilder.Delete(aPairsIter->first);
89       } else if (anEvol == TNaming_PRIMITIVE) {
90         aBuilder.Generated(aPairsIter->second);
91       } else if (anEvol == TNaming_SELECTED) {
92         aBuilder.Select(aPairsIter->second, aPairsIter->first);
93       }
94     }
95   }
96   // recursive call for all sub-labels
97   TDF_ChildIterator anIter(theLab, Standard_False);
98   for(; anIter.More(); anIter.Next()) {
99     evolutionToSelectionRec(anIter.Value(), theFlag);
100   }
101 }
102
103 void Model_BodyBuilder::evolutionToSelection(const bool theFlag)
104 {
105   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
106   if (!aData) // unknown case
107     return;
108   TDF_Label& aShapeLab = aData->shapeLab();
109   evolutionToSelectionRec(aShapeLab, theFlag);
110 }
111
112 void Model_BodyBuilder::store(const std::shared_ptr<GeomAPI_Shape>& theShape,
113                               const bool theIsStoreSameShapes)
114 {
115   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
116   if (aData) {
117     TDF_Label& aShapeLab = aData->shapeLab();
118     // clean builders
119     clean();
120     // store the new shape as primitive
121     TNaming_Builder aBuilder(aShapeLab);
122     if (!theShape)
123       return;  // bad shape
124     TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
125     if (aShape.IsNull())
126       return;  // null shape inside
127
128     if(!theIsStoreSameShapes) {
129       Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aShape, aShapeLab);
130       if(!aNS.IsNull() && !aNS->IsEmpty()) {
131         // This shape is already in document, store reference instead of shape;
132         const TDF_Label aFoundLabel = aNS->Label();
133         TDF_Reference::Set(aShapeLab, aFoundLabel);
134         aShapeLab.ForgetAttribute(TNaming_NamedShape::GetID());
135         return;
136       }
137     }
138
139     aBuilder.Generated(aShape);
140     // register name
141     aShapeLab.ForgetAttribute(TDF_Reference::GetID());
142     if(!aBuilder.NamedShape()->IsEmpty()) {
143       Handle(TDataStd_Name) anAttr;
144       if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
145         std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
146         if(!aName.empty()) {
147           std::shared_ptr<Model_Document> aDoc =
148             std::dynamic_pointer_cast<Model_Document>(document());
149           aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
150         }
151       }
152     }
153   }
154 }
155
156 void Model_BodyBuilder::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& theFromShape,
157   const std::shared_ptr<GeomAPI_Shape>& theToShape)
158 {
159   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
160   if (aData) {
161     TDF_Label& aShapeLab = aData->shapeLab();
162     // clean builders
163     clean();
164     // store the new shape as primitive
165     TNaming_Builder aBuilder(aShapeLab);
166     if (!theFromShape || !theToShape)
167       return;  // bad shape
168     TopoDS_Shape aShapeBasis = theFromShape->impl<TopoDS_Shape>();
169     if (aShapeBasis.IsNull())
170       return;  // null shape inside
171     TopoDS_Shape aShapeNew = theToShape->impl<TopoDS_Shape>();
172     if (aShapeNew.IsNull())
173       return;  // null shape inside
174     aBuilder.Generated(aShapeBasis, aShapeNew);
175     // register name
176     if(!aBuilder.NamedShape()->IsEmpty()) {
177       Handle(TDataStd_Name) anAttr;
178       if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
179         std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
180         if(!aName.empty()) {
181           std::shared_ptr<Model_Document> aDoc =
182             std::dynamic_pointer_cast<Model_Document>(document());
183           aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
184         }
185       }
186     }
187   }
188 }
189
190 void Model_BodyBuilder::storeModified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
191   const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theDecomposeSolidsTag)
192 {
193   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
194   if (aData) {
195     TDF_Label& aShapeLab = aData->shapeLab();
196     // clean builders
197     clean();
198     // store the new shape as primitive
199     TNaming_Builder aBuilder(aShapeLab);
200     if (!theOldShape || !theNewShape)
201       return;  // bad shape
202     TopoDS_Shape aShapeOld = theOldShape->impl<TopoDS_Shape>();
203     if (aShapeOld.IsNull())
204       return;  // null shape inside
205     TopoDS_Shape aShapeNew = theNewShape->impl<TopoDS_Shape>();
206     if (aShapeNew.IsNull())
207       return;  // null shape inside
208     aBuilder.Modify(aShapeOld, aShapeNew);
209     if(!aBuilder.NamedShape()->IsEmpty()) {
210       Handle(TDataStd_Name) anAttr;
211       if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
212         std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
213         if(!aName.empty()) {
214           std::shared_ptr<Model_Document> aDoc =
215             std::dynamic_pointer_cast<Model_Document>(document());
216           aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
217         }
218       }
219     }
220   }
221 }
222
223 void  Model_BodyBuilder::storeWithoutNaming(const std::shared_ptr<GeomAPI_Shape>& theShape)
224 {
225   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
226   if (aData) {
227     clean();
228     if (!theShape.get())
229       return; // bad shape
230     TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
231     if (aShape.IsNull())
232       return;  // null shape inside
233     TNaming_Builder aBuilder(aData->shapeLab());
234     aBuilder.Select(aShape, aShape);
235   }
236 }
237
238 void Model_BodyBuilder::clean()
239 {
240   std::vector<TNaming_Builder*>::iterator aBuilder = myBuilders.begin();
241   for(; aBuilder != myBuilders.end(); aBuilder++)
242     delete *aBuilder;
243   myBuilders.clear();
244 }
245
246 Model_BodyBuilder::~Model_BodyBuilder()
247 {
248   clean();
249 }
250
251 TNaming_Builder* Model_BodyBuilder::builder(const int theTag)
252 {
253   if (myBuilders.size() <= (unsigned int)theTag) {
254     myBuilders.insert(myBuilders.end(), theTag - myBuilders.size() + 1, NULL);
255   }
256   if (!myBuilders[theTag]) {
257     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
258     myBuilders[theTag] = new TNaming_Builder(aData->shapeLab().FindChild(theTag));
259     //TCollection_AsciiString entry;//
260     //TDF_Tool::Entry(aData->shapeLab().FindChild(theTag), entry);
261     //cout << "Label = " <<entry.ToCString() <<endl;
262   }
263   return myBuilders[theTag];
264 }
265
266 void Model_BodyBuilder::buildName(const int theTag, const std::string& theName)
267 {
268   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
269   //aDoc->addNamingName(builder(theTag)->NamedShape()->Label(), theName);
270   TDataStd_Name::Set(builder(theTag)->NamedShape()->Label(), theName.c_str());
271 }
272 void Model_BodyBuilder::generated(
273   const std::shared_ptr<GeomAPI_Shape>& theNewShape, const std::string& theName, const int theTag)
274 {
275   TopoDS_Shape aShape = theNewShape->impl<TopoDS_Shape>();
276   builder(theTag)->Generated(aShape);
277   if(!theName.empty())
278     buildName(theTag, theName);
279 }
280
281 void Model_BodyBuilder::generated(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
282   const std::shared_ptr<GeomAPI_Shape>& theNewShape, const std::string& theName, const int theTag)
283 {
284   TopoDS_Shape anOldShape = theOldShape->impl<TopoDS_Shape>();
285   TopoDS_Shape aNewShape = theNewShape->impl<TopoDS_Shape>();
286   builder(theTag)->Generated(anOldShape, aNewShape);
287   if(!theName.empty())
288     buildName(theTag, theName);
289   TopAbs_ShapeEnum aGenShapeType = aNewShape.ShapeType();
290   if(aGenShapeType == TopAbs_WIRE || aGenShapeType == TopAbs_SHELL) {
291     TopAbs_ShapeEnum anExplodeShapeType = aGenShapeType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE;
292     const TDF_Label aLabel = builder(theTag)->NamedShape()->Label();
293     int aTag = 1;
294     std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
295     for(TopExp_Explorer anExp(aNewShape, anExplodeShapeType); anExp.More(); anExp.Next()) {
296       TDF_Label aChildLabel = aLabel.FindChild(aTag);
297       TNaming_Builder aBuilder(aChildLabel);
298       aBuilder.Generated(anOldShape, anExp.Current());
299       TCollection_AsciiString aChildName = TCollection_AsciiString((theName + "_").c_str()) + aTag;
300       //aDoc->addNamingName(aChildLabel, aChildName.ToCString());
301       TDataStd_Name::Set(aChildLabel, aChildName.ToCString());
302       aTag++;
303     }
304   }
305 }
306
307
308 void Model_BodyBuilder::modified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
309   const std::shared_ptr<GeomAPI_Shape>& theNewShape, const std::string& theName, const int theTag)
310 {
311   TopoDS_Shape anOldShape = theOldShape->impl<TopoDS_Shape>();
312   TopoDS_Shape aNewShape = theNewShape->impl<TopoDS_Shape>();
313   builder(theTag)->Modify(anOldShape, aNewShape);
314   if(!theName.empty())
315     buildName(theTag, theName);
316 }
317
318 void Model_BodyBuilder::deleted(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
319   const int theTag)
320 {
321   TopoDS_Shape aShape = theOldShape->impl<TopoDS_Shape>();
322   builder(theTag)->Delete(aShape);
323 }
324
325 void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS,
326   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
327   const int  theKindOfShape,
328   const int  theTag)
329 {
330   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
331   TopTools_MapOfShape aView;
332   TopExp_Explorer ShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
333   for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
334     const TopoDS_Shape& aRoot = ShapeExplorer.Current ();
335     if (!aView.Add(aRoot)) continue;
336     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
337     aRShape->setImpl((new TopoDS_Shape(aRoot)));
338     if (theMS->isDeleted (aRShape)) {
339       builder(theTag)->Delete(aRoot);
340     }
341   }
342 }
343
344 void Model_BodyBuilder::loadAndOrientModifiedShapes (
345   GeomAlgoAPI_MakeShape* theMS,
346   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
347   const int  theKindOfShape,
348   const int  theTag,
349   const std::string& theName,
350   GeomAPI_DataMapOfShapeShape& theSubShapes,
351   const bool theIsStoreSeparate)
352 {
353   int anIndex = 1;
354   int aTag = theTag;
355   bool isBuilt = !theName.empty();
356   std::string aName = theName;
357   std::ostringstream aStream;
358   GeomShapePtr aResultShape = shape();
359   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
360   TopTools_MapOfShape aView;
361   TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
362   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
363     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
364     if (!aView.Add(aRoot)) continue;
365     ListOfShape aList;
366     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
367     aRShape->setImpl((new TopoDS_Shape(aRoot)));
368     theMS->modified(aRShape, aList);
369     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator
370       anIt = aList.begin(), aLast = aList.end();
371     for (; anIt != aLast; anIt++) {
372       TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();
373       if (theSubShapes.isBound(*anIt)) {
374         std::shared_ptr<GeomAPI_Shape> aMapShape(theSubShapes.find(*anIt));
375         aNewShape.Orientation(aMapShape->impl<TopoDS_Shape>().Orientation());
376       }
377       GeomShapePtr aGeomNewShape(new GeomAPI_Shape());
378       aGeomNewShape->setImpl(new TopoDS_Shape(aNewShape));
379       if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(aGeomNewShape)) {
380         builder(aTag)->Modify(aRoot,aNewShape);
381         if(isBuilt) {
382           if(theIsStoreSeparate) {
383             aStream.str(std::string());
384             aStream.clear();
385             aStream << theName << "_" << anIndex++;
386             aName = aStream.str();
387           }
388           buildName(aTag, aName);
389         }
390         if(theIsStoreSeparate) {
391           aTag++;
392         }
393       }
394     }
395   }
396 }
397
398 void Model_BodyBuilder::loadAndOrientGeneratedShapes (
399   GeomAlgoAPI_MakeShape* theMS,
400   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
401   const int  theKindOfShape,
402   const int  theTag,
403   const std::string& theName,
404   GeomAPI_DataMapOfShapeShape& theSubShapes)
405 {
406   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
407   TopTools_MapOfShape aView;
408   bool isBuilt = !theName.empty();
409   TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
410   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
411     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
412     if (!aView.Add(aRoot)) continue;
413     ListOfShape aList;
414     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
415     aRShape->setImpl((new TopoDS_Shape(aRoot)));
416     theMS->generated(aRShape, aList);
417     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator
418       anIt = aList.begin(), aLast = aList.end();
419     for (; anIt != aLast; anIt++) {
420       TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();
421       if (theSubShapes.isBound(*anIt)) {
422         std::shared_ptr<GeomAPI_Shape> aMapShape(theSubShapes.find(*anIt));
423         aNewShape.Orientation(aMapShape->impl<TopoDS_Shape>().Orientation());
424       }
425       if (!aRoot.IsSame (aNewShape)) {
426         builder(theTag)->Generated(aRoot,aNewShape);
427         if(isBuilt)
428           buildName(theTag, theName);
429       }
430       TopAbs_ShapeEnum aGenShapeType = aNewShape.ShapeType();
431       if(aGenShapeType == TopAbs_WIRE || aGenShapeType == TopAbs_SHELL) {
432         TopAbs_ShapeEnum anExplodeShapeType =
433           aGenShapeType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE;
434         const TDF_Label aLabel = builder(theTag)->NamedShape()->Label();
435         int aTag = 1;
436         std::shared_ptr<Model_Document> aDoc =
437           std::dynamic_pointer_cast<Model_Document>(document());
438         for(TopExp_Explorer anExp(aNewShape, anExplodeShapeType); anExp.More(); anExp.Next()) {
439           TDF_Label aChildLabel = aLabel.FindChild(aTag);
440           TNaming_Builder aBuilder(aChildLabel);
441           aBuilder.Generated(aRoot, anExp.Current());
442           TCollection_AsciiString aChildName =
443             TCollection_AsciiString((theName + "_").c_str()) + aTag;
444           TDataStd_Name::Set(aChildLabel, aChildName.ToCString());
445           aTag++;
446         }
447       }
448     }
449   }
450 }
451
452 //=======================================================================
453 int getDangleShapes(const TopoDS_Shape&           theShapeIn,
454   const TopAbs_ShapeEnum        theGeneratedFrom,
455   TopTools_DataMapOfShapeShape& theDangles)
456 {
457   theDangles.Clear();
458   TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors;
459   TopAbs_ShapeEnum GeneratedTo;
460   if (theGeneratedFrom == TopAbs_FACE) GeneratedTo = TopAbs_EDGE;
461   else if (theGeneratedFrom == TopAbs_EDGE) GeneratedTo = TopAbs_VERTEX;
462   else return Standard_False;
463   TopExp::MapShapesAndAncestors(theShapeIn, GeneratedTo, theGeneratedFrom, subShapeAndAncestors);
464   for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) {
465     const TopoDS_Shape& mayBeDangle = subShapeAndAncestors.FindKey(i);
466     const TopTools_ListOfShape& ancestors = subShapeAndAncestors.FindFromIndex(i);
467     if (ancestors.Extent() == 1) theDangles.Bind(ancestors.First(), mayBeDangle);
468   }
469   return theDangles.Extent();
470 }
471
472 //=======================================================================
473 void loadGeneratedDangleShapes(
474   const TopoDS_Shape&      theShapeIn,
475   const TopAbs_ShapeEnum   theGeneratedFrom,
476   TNaming_Builder *        theBuilder)
477 {
478   TopTools_DataMapOfShapeShape dangles;
479   if (!getDangleShapes(theShapeIn, theGeneratedFrom, dangles)) return;
480   TopTools_DataMapIteratorOfDataMapOfShapeShape itr(dangles);
481   for (; itr.More(); itr.Next())
482     theBuilder->Generated(itr.Key(), itr.Value());
483 }
484
485 //=======================================================================
486 void Model_BodyBuilder::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape,
487   const std::string& theName, int&  theTag)
488 {
489   if(theShape->isNull()) return;
490   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
491   std::string aName;
492   if (aShape.ShapeType() == TopAbs_SOLID) {
493     TopExp_Explorer expl(aShape, TopAbs_FACE);
494     for (; expl.More(); expl.Next()) {
495       builder(theTag)->Generated(expl.Current());
496       TCollection_AsciiString aStr(theTag);
497       aName = theName + aStr.ToCString();
498       buildName(theTag, aName);
499       theTag++;
500     }
501   }
502   else if (aShape.ShapeType() == TopAbs_SHELL || aShape.ShapeType() == TopAbs_FACE) {
503     // load faces and all the free edges
504     TopTools_IndexedMapOfShape Faces;
505     TopExp::MapShapes(aShape, TopAbs_FACE, Faces);
506     if (Faces.Extent() > 1 || (aShape.ShapeType() == TopAbs_SHELL && Faces.Extent() == 1)) {
507       TopExp_Explorer expl(aShape, TopAbs_FACE);
508       for (; expl.More(); expl.Next()) {
509         builder(theTag)->Generated(expl.Current());
510         TCollection_AsciiString aStr(theTag);
511         aName = theName + aStr.ToCString();
512         buildName(theTag, aName);
513         theTag++;
514       }
515     }
516     TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces;
517     TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, anEdgeAndNeighbourFaces);
518     for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++)
519     {
520       const TopTools_ListOfShape& aLL = anEdgeAndNeighbourFaces.FindFromIndex(i);
521       if (aLL.Extent() < 2) {
522         if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i))))
523           continue;
524         builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
525         TCollection_AsciiString aStr(theTag);
526         aName = theName + aStr.ToCString();
527         buildName(theTag, aName);
528         theTag++;
529       } else {
530         TopTools_ListIteratorOfListOfShape anIter(aLL);
531         const TopoDS_Face& aFace = TopoDS::Face(anIter.Value());
532         anIter.Next();
533         if(aFace.IsEqual(anIter.Value())) {
534           builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
535           TCollection_AsciiString aStr(theTag);
536           aName = theName + aStr.ToCString();
537           buildName(theTag, aName);
538           theTag++;
539         }
540       }
541     }
542   } else if (aShape.ShapeType() == TopAbs_WIRE) {
543     TopTools_IndexedMapOfShape Edges;
544     BRepTools::Map3DEdges(aShape, Edges);
545     if (Edges.Extent() == 1) {
546       builder(++theTag)->Generated(Edges.FindKey(1));
547       TopExp_Explorer expl(aShape, TopAbs_VERTEX);
548       for (; expl.More(); expl.Next()) {
549         builder(theTag)->Generated(expl.Current());
550         TCollection_AsciiString aStr(theTag);
551         aName = theName + aStr.ToCString();
552         buildName(theTag, aName);
553         theTag++;
554       }
555     } else {
556       TopExp_Explorer expl(aShape, TopAbs_EDGE);
557       for (; expl.More(); expl.Next()) {
558         builder(theTag)->Generated(expl.Current());
559         TCollection_AsciiString aStr(theTag);
560         aName = theName + aStr.ToCString();
561         buildName(theTag, aName);
562         theTag++;
563       }
564       // and load generated vertices.
565       TopTools_DataMapOfShapeShape generated;
566       if (getDangleShapes(aShape, TopAbs_EDGE, generated))
567       {
568         TNaming_Builder* pBuilder = builder(theTag++);
569         loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder);
570       }
571     }
572   } else if (aShape.ShapeType() == TopAbs_EDGE) {
573     TopExp_Explorer expl(aShape, TopAbs_VERTEX);
574     for (; expl.More(); expl.Next()) {
575       builder(theTag)->Generated(expl.Current());
576       TCollection_AsciiString aStr(theTag);
577       aName = theName + aStr.ToCString();
578       buildName(theTag, aName);
579       theTag++;
580     }
581   }
582 }
583
584 //=======================================================================
585 int findAmbiguities(const TopoDS_Shape&           theShapeIn,
586   TopTools_ListOfShape&   theList)
587 {
588   int aNumEdges(0);
589   theList.Clear();
590   TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors;
591   TopAbs_ShapeEnum aTS(TopAbs_EDGE);
592   TopAbs_ShapeEnum aTA(TopAbs_FACE);
593   TopTools_MapOfShape aMap1, aMap2; // map1 - for edge ancestors; map2 - for keys => edges
594   TopTools_ListOfShape aKeyList;
595   TopExp::MapShapesAndAncestors(theShapeIn, aTS, aTA, subShapeAndAncestors);
596   for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) {
597     const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i);
598     const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i);
599     aMap1.Clear();
600     TopTools_ListIteratorOfListOfShape it(ancestors1);
601     for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1
602     for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) {
603       if (i == j) continue;
604       const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j);
605       const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j);
606       if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) {
607         int aNum (ancestors2.Extent());
608         TopTools_ListIteratorOfListOfShape it(ancestors2);
609         for(;it.More();it.Next())
610           if(aMap1.Contains(it.Value())) aNum--;
611         if(aNum == 0) {
612           if(aMap2.Add(aKeyEdge1))
613             aKeyList.Append(aKeyEdge1);
614           if(aMap2.Add(aKeyEdge2))
615             aKeyList.Append(aKeyEdge2);
616         }
617       }
618     } // at the end ==> List of edges to be named in addition
619   }
620   aNumEdges = aKeyList.Extent();
621   if(aNumEdges)
622     theList.Assign(aKeyList);
623   return aNumEdges;
624 }
625
626 //=======================================================================
627 void Model_BodyBuilder::loadFirstLevel(
628   std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int&  theTag)
629 {
630   if(theShape->isNull()) return;
631   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
632   std::string aName;
633   if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) {
634     TopoDS_Iterator itr(aShape);
635     for (; itr.More(); itr.Next(),theTag++) {
636       builder(theTag)->Generated(itr.Value());
637       TCollection_AsciiString aStr(theTag);
638       aName = theName + aStr.ToCString();
639       buildName(theTag, aName);
640       if(!theName.empty()) buildName(theTag, aName);
641       if (itr.Value().ShapeType() == TopAbs_COMPOUND ||
642         itr.Value().ShapeType() == TopAbs_COMPSOLID)
643       {
644         std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
645         itrShape->setImpl(new TopoDS_Shape(itr.Value()));
646         loadFirstLevel(itrShape, theName, theTag);
647       } else {
648         std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
649         itrShape->setImpl(new TopoDS_Shape(itr.Value()));
650         loadNextLevels(itrShape, theName, theTag);
651       }
652     }
653   } else {
654     std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
655     itrShape->setImpl(new TopoDS_Shape(aShape));
656     loadNextLevels(itrShape, theName, theTag);
657   }
658   TopTools_ListOfShape   aList;
659   if(findAmbiguities(aShape, aList)) {
660     TopTools_ListIteratorOfListOfShape it(aList);
661     for (; it.More(); it.Next(),theTag++) {
662       builder(theTag)->Generated(it.Value());
663       TCollection_AsciiString aStr(theTag);
664       aName = theName + aStr.ToCString();
665       buildName(theTag, aName);
666     }
667   }
668 }
669
670 //=======================================================================
671 void Model_BodyBuilder::loadDisconnectedEdges(
672   std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int&  theTag)
673 {
674   if(theShape->isNull()) return;
675   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
676   TopTools_DataMapOfShapeListOfShape edgeNaborFaces;
677   TopTools_ListOfShape empty;
678   TopExp_Explorer explF(aShape, TopAbs_FACE);
679   for (; explF.More(); explF.Next()) {
680     const TopoDS_Shape& aFace = explF.Current();
681     TopExp_Explorer explV(aFace, TopAbs_EDGE);
682     for (; explV.More(); explV.Next()) {
683       const TopoDS_Shape& anEdge = explV.Current();
684       if (!edgeNaborFaces.IsBound(anEdge)) edgeNaborFaces.Bind(anEdge, empty);
685       Standard_Boolean faceIsNew = Standard_True;
686       TopTools_ListIteratorOfListOfShape itrF(edgeNaborFaces.Find(anEdge));
687       for (; itrF.More(); itrF.Next()) {
688         if (itrF.Value().IsSame(aFace)) {
689           faceIsNew = Standard_False;
690           break;
691         }
692       }
693       if (faceIsNew)
694         edgeNaborFaces.ChangeFind(anEdge).Append(aFace);
695     }
696   }
697
698   TopTools_MapOfShape anEdgesToDelete;
699   TopExp_Explorer anEx(aShape,TopAbs_EDGE);
700   std::string aName;
701   for(;anEx.More();anEx.Next()) {
702     Standard_Boolean aC0 = Standard_False;
703     TopoDS_Shape anEdge1 = anEx.Current();
704     if (edgeNaborFaces.IsBound(anEdge1)) {
705       const TopTools_ListOfShape& aList1 = edgeNaborFaces.Find(anEdge1);
706       if (aList1.Extent()<2) continue;
707       TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(edgeNaborFaces);
708       for (; itr.More(); itr.Next()) {
709         TopoDS_Shape anEdge2 = itr.Key();
710         if(anEdgesToDelete.Contains(anEdge2)) continue;
711         if (anEdge1.IsSame(anEdge2)) continue;
712         const TopTools_ListOfShape& aList2 = itr.Value();
713         // compare lists of the neighbour faces of edge1 and edge2
714         if (aList1.Extent() == aList2.Extent()) {
715           Standard_Integer aMatches = 0;
716           for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next())
717             for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next())
718               if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++;
719           if (aMatches == aList1.Extent()) {
720             aC0=Standard_True;
721             builder(theTag)->Generated(anEdge2);
722             anEdgesToDelete.Add(anEdge2);
723             TCollection_AsciiString aStr(theTag);
724             aName = theName + aStr.ToCString();
725             buildName(theTag, aName);
726             theTag++;
727           }
728         }
729       }
730       TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete);
731       for(;itDelete.More();itDelete.Next())
732         edgeNaborFaces.UnBind(itDelete.Key());
733       edgeNaborFaces.UnBind(anEdge1);
734     }
735     if (aC0) {
736       builder(theTag)->Generated(anEdge1);
737       TCollection_AsciiString aStr(theTag);
738       aName = theName + aStr.ToCString();
739       buildName(theTag, aName);
740       theTag++;
741     }
742   }
743 }
744
745 void Model_BodyBuilder::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape> theShape,
746                                                  const std::string& theName, int&  theTag)
747 {
748   if(theShape->isNull()) return;
749   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
750   TopTools_DataMapOfShapeListOfShape vertexNaborEdges;
751   TopTools_ListOfShape empty;
752   TopExp_Explorer explF(aShape, TopAbs_EDGE);
753   for (; explF.More(); explF.Next()) {
754     const TopoDS_Shape& anEdge = explF.Current();
755     TopExp_Explorer explV(anEdge, TopAbs_VERTEX);
756     for (; explV.More(); explV.Next()) {
757       const TopoDS_Shape& aVertex = explV.Current();
758       if (!vertexNaborEdges.IsBound(aVertex)) vertexNaborEdges.Bind(aVertex, empty);
759       Standard_Boolean faceIsNew = Standard_True;
760       TopTools_ListIteratorOfListOfShape itrF(vertexNaborEdges.Find(aVertex));
761       for (; itrF.More(); itrF.Next()) {
762         if (itrF.Value().IsSame(anEdge)) {
763           faceIsNew = Standard_False;
764           break;
765         }
766       }
767       if (faceIsNew) {
768         vertexNaborEdges.ChangeFind(aVertex).Append(anEdge);
769       }
770     }
771   }
772   std::string aName;
773   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(vertexNaborEdges);
774   for (; itr.More(); itr.Next()) {
775     const TopTools_ListOfShape& naborEdges = itr.Value();
776     if (naborEdges.Extent() < 2) {
777       builder(theTag)->Generated(itr.Key());
778       TCollection_AsciiString aStr(theTag);
779       aName = theName + aStr.ToCString();
780       buildName(theTag, aName);
781       theTag++;
782     }
783   }
784 }
785
786 std::shared_ptr<GeomAPI_Shape> Model_BodyBuilder::shape()
787 {
788   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
789   if (aData) {
790     TDF_Label aShapeLab = aData->shapeLab();
791     Handle(TDF_Reference) aRef;
792     if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
793       aShapeLab = aRef->Get();
794     }
795     Handle(TNaming_NamedShape) aName;
796     if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
797       TopoDS_Shape aShape = aName->Get();
798       if (!aShape.IsNull()) {
799         std::shared_ptr<GeomAPI_Shape> aRes(new GeomAPI_Shape);
800         aRes->setImpl(new TopoDS_Shape(aShape));
801         return aRes;
802       }
803     }
804   }
805   return std::shared_ptr<GeomAPI_Shape>();
806 }
807
808 bool Model_BodyBuilder::isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape)
809 {
810   if (theShape.get()) {
811     TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
812     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
813     if (aData) {
814       TDF_Label& aShapeLab = aData->shapeLab();
815       Handle(TNaming_NamedShape) aName;
816       if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
817         TopoDS_Shape aLatest = TNaming_Tool::CurrentShape(aName);
818         if (aLatest.IsNull())
819           return false;
820         if (aLatest.IsEqual(aShape))
821           return true;
822         // check sub-shapes for comp-solids:
823         for (TopExp_Explorer anExp(aShape, aLatest.ShapeType()); anExp.More(); anExp.Next()) {
824           if (aLatest.IsEqual(anExp.Current()))
825             return true;
826         }
827       }
828     }
829   }
830   return false;
831 }