Salome HOME
Issue #2021
[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   const bool theIsStoreAsGenerated)
353 {
354   int anIndex = 1;
355   int aTag = theTag;
356   bool isBuilt = !theName.empty();
357   std::string aName = theName;
358   std::ostringstream aStream;
359   GeomShapePtr aResultShape = shape();
360   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
361   TopTools_MapOfShape aView;
362   TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
363   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
364     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
365     if (!aView.Add(aRoot)) continue;
366     ListOfShape aList;
367     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
368     aRShape->setImpl((new TopoDS_Shape(aRoot)));
369     theMS->modified(aRShape, aList);
370     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator
371       anIt = aList.begin(), aLast = aList.end();
372     for (; anIt != aLast; anIt++) {
373       TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();
374       if (theSubShapes.isBound(*anIt)) {
375         std::shared_ptr<GeomAPI_Shape> aMapShape(theSubShapes.find(*anIt));
376         aNewShape.Orientation(aMapShape->impl<TopoDS_Shape>().Orientation());
377       }
378       GeomShapePtr aGeomNewShape(new GeomAPI_Shape());
379       aGeomNewShape->setImpl(new TopoDS_Shape(aNewShape));
380       if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(aGeomNewShape)) {
381         if(theIsStoreAsGenerated) {
382           // Here we store shapes as generated, to avoid problem when one parent shape produce
383           // several child shapes. In this case naming could not determine which shape to select.
384           builder(aTag)->Generated(aRoot,aNewShape);
385         } else {
386           builder(aTag)->Modify(aRoot,aNewShape);
387         }
388         if(isBuilt) {
389           if(theIsStoreSeparate) {
390             aStream.str(std::string());
391             aStream.clear();
392             aStream << theName << "_" << anIndex++;
393             aName = aStream.str();
394           }
395           buildName(aTag, aName);
396         }
397         if(theIsStoreSeparate) {
398           aTag++;
399         }
400       }
401     }
402   }
403 }
404
405 void Model_BodyBuilder::loadAndOrientGeneratedShapes (
406   GeomAlgoAPI_MakeShape* theMS,
407   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
408   const int  theKindOfShape,
409   const int  theTag,
410   const std::string& theName,
411   GeomAPI_DataMapOfShapeShape& theSubShapes)
412 {
413   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
414   TopTools_MapOfShape aView;
415   bool isBuilt = !theName.empty();
416   TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
417   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
418     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
419     if (!aView.Add(aRoot)) continue;
420     ListOfShape aList;
421     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
422     aRShape->setImpl((new TopoDS_Shape(aRoot)));
423     theMS->generated(aRShape, aList);
424     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator
425       anIt = aList.begin(), aLast = aList.end();
426     for (; anIt != aLast; anIt++) {
427       TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();
428       if (theSubShapes.isBound(*anIt)) {
429         std::shared_ptr<GeomAPI_Shape> aMapShape(theSubShapes.find(*anIt));
430         aNewShape.Orientation(aMapShape->impl<TopoDS_Shape>().Orientation());
431       }
432       if (!aRoot.IsSame (aNewShape)) {
433         builder(theTag)->Generated(aRoot,aNewShape);
434         if(isBuilt)
435           buildName(theTag, theName);
436       }
437       TopAbs_ShapeEnum aGenShapeType = aNewShape.ShapeType();
438       if(aGenShapeType == TopAbs_WIRE || aGenShapeType == TopAbs_SHELL) {
439         TopAbs_ShapeEnum anExplodeShapeType =
440           aGenShapeType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE;
441         const TDF_Label aLabel = builder(theTag)->NamedShape()->Label();
442         int aTag = 1;
443         std::shared_ptr<Model_Document> aDoc =
444           std::dynamic_pointer_cast<Model_Document>(document());
445         for(TopExp_Explorer anExp(aNewShape, anExplodeShapeType); anExp.More(); anExp.Next()) {
446           TDF_Label aChildLabel = aLabel.FindChild(aTag);
447           TNaming_Builder aBuilder(aChildLabel);
448           aBuilder.Generated(aRoot, anExp.Current());
449           TCollection_AsciiString aChildName =
450             TCollection_AsciiString((theName + "_").c_str()) + aTag;
451           TDataStd_Name::Set(aChildLabel, aChildName.ToCString());
452           aTag++;
453         }
454       }
455     }
456   }
457 }
458
459 //=======================================================================
460 int getDangleShapes(const TopoDS_Shape&           theShapeIn,
461   const TopAbs_ShapeEnum        theGeneratedFrom,
462   TopTools_DataMapOfShapeShape& theDangles)
463 {
464   theDangles.Clear();
465   TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors;
466   TopAbs_ShapeEnum GeneratedTo;
467   if (theGeneratedFrom == TopAbs_FACE) GeneratedTo = TopAbs_EDGE;
468   else if (theGeneratedFrom == TopAbs_EDGE) GeneratedTo = TopAbs_VERTEX;
469   else return Standard_False;
470   TopExp::MapShapesAndAncestors(theShapeIn, GeneratedTo, theGeneratedFrom, subShapeAndAncestors);
471   for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) {
472     const TopoDS_Shape& mayBeDangle = subShapeAndAncestors.FindKey(i);
473     const TopTools_ListOfShape& ancestors = subShapeAndAncestors.FindFromIndex(i);
474     if (ancestors.Extent() == 1) theDangles.Bind(ancestors.First(), mayBeDangle);
475   }
476   return theDangles.Extent();
477 }
478
479 //=======================================================================
480 void loadGeneratedDangleShapes(
481   const TopoDS_Shape&      theShapeIn,
482   const TopAbs_ShapeEnum   theGeneratedFrom,
483   TNaming_Builder *        theBuilder)
484 {
485   TopTools_DataMapOfShapeShape dangles;
486   if (!getDangleShapes(theShapeIn, theGeneratedFrom, dangles)) return;
487   TopTools_DataMapIteratorOfDataMapOfShapeShape itr(dangles);
488   for (; itr.More(); itr.Next())
489     theBuilder->Generated(itr.Key(), itr.Value());
490 }
491
492 //=======================================================================
493 void Model_BodyBuilder::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape,
494   const std::string& theName, int&  theTag)
495 {
496   if(theShape->isNull()) return;
497   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
498   std::string aName;
499   if (aShape.ShapeType() == TopAbs_SOLID) {
500     TopExp_Explorer expl(aShape, TopAbs_FACE);
501     for (; expl.More(); expl.Next()) {
502       builder(theTag)->Generated(expl.Current());
503       TCollection_AsciiString aStr(theTag);
504       aName = theName + aStr.ToCString();
505       buildName(theTag, aName);
506       theTag++;
507     }
508   }
509   else if (aShape.ShapeType() == TopAbs_SHELL || aShape.ShapeType() == TopAbs_FACE) {
510     // load faces and all the free edges
511     TopTools_IndexedMapOfShape Faces;
512     TopExp::MapShapes(aShape, TopAbs_FACE, Faces);
513     if (Faces.Extent() > 1 || (aShape.ShapeType() == TopAbs_SHELL && Faces.Extent() == 1)) {
514       TopExp_Explorer expl(aShape, TopAbs_FACE);
515       for (; expl.More(); expl.Next()) {
516         builder(theTag)->Generated(expl.Current());
517         TCollection_AsciiString aStr(theTag);
518         aName = theName + aStr.ToCString();
519         buildName(theTag, aName);
520         theTag++;
521       }
522     }
523     TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces;
524     TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, anEdgeAndNeighbourFaces);
525     for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++)
526     {
527       const TopTools_ListOfShape& aLL = anEdgeAndNeighbourFaces.FindFromIndex(i);
528       if (aLL.Extent() < 2) {
529         if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i))))
530           continue;
531         builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
532         TCollection_AsciiString aStr(theTag);
533         aName = theName + aStr.ToCString();
534         buildName(theTag, aName);
535         theTag++;
536       } else {
537         TopTools_ListIteratorOfListOfShape anIter(aLL);
538         const TopoDS_Face& aFace = TopoDS::Face(anIter.Value());
539         anIter.Next();
540         if(aFace.IsEqual(anIter.Value())) {
541           builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
542           TCollection_AsciiString aStr(theTag);
543           aName = theName + aStr.ToCString();
544           buildName(theTag, aName);
545           theTag++;
546         }
547       }
548     }
549   } else if (aShape.ShapeType() == TopAbs_WIRE) {
550     TopTools_IndexedMapOfShape Edges;
551     BRepTools::Map3DEdges(aShape, Edges);
552     if (Edges.Extent() == 1) {
553       builder(++theTag)->Generated(Edges.FindKey(1));
554       TopExp_Explorer expl(aShape, TopAbs_VERTEX);
555       for (; expl.More(); expl.Next()) {
556         builder(theTag)->Generated(expl.Current());
557         TCollection_AsciiString aStr(theTag);
558         aName = theName + aStr.ToCString();
559         buildName(theTag, aName);
560         theTag++;
561       }
562     } else {
563       TopExp_Explorer expl(aShape, TopAbs_EDGE);
564       for (; expl.More(); expl.Next()) {
565         builder(theTag)->Generated(expl.Current());
566         TCollection_AsciiString aStr(theTag);
567         aName = theName + aStr.ToCString();
568         buildName(theTag, aName);
569         theTag++;
570       }
571       // and load generated vertices.
572       TopTools_DataMapOfShapeShape generated;
573       if (getDangleShapes(aShape, TopAbs_EDGE, generated))
574       {
575         TNaming_Builder* pBuilder = builder(theTag++);
576         loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder);
577       }
578     }
579   } else if (aShape.ShapeType() == TopAbs_EDGE) {
580     TopExp_Explorer expl(aShape, TopAbs_VERTEX);
581     for (; expl.More(); expl.Next()) {
582       builder(theTag)->Generated(expl.Current());
583       TCollection_AsciiString aStr(theTag);
584       aName = theName + aStr.ToCString();
585       buildName(theTag, aName);
586       theTag++;
587     }
588   }
589 }
590
591 //=======================================================================
592 int findAmbiguities(const TopoDS_Shape&           theShapeIn,
593   TopTools_ListOfShape&   theList)
594 {
595   int aNumEdges(0);
596   theList.Clear();
597   TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors;
598   TopAbs_ShapeEnum aTS(TopAbs_EDGE);
599   TopAbs_ShapeEnum aTA(TopAbs_FACE);
600   TopTools_MapOfShape aMap1, aMap2; // map1 - for edge ancestors; map2 - for keys => edges
601   TopTools_ListOfShape aKeyList;
602   TopExp::MapShapesAndAncestors(theShapeIn, aTS, aTA, subShapeAndAncestors);
603   for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) {
604     const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i);
605     const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i);
606     aMap1.Clear();
607     TopTools_ListIteratorOfListOfShape it(ancestors1);
608     for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1
609     for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) {
610       if (i == j) continue;
611       const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j);
612       const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j);
613       if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) {
614         int aNum (ancestors2.Extent());
615         TopTools_ListIteratorOfListOfShape it(ancestors2);
616         for(;it.More();it.Next())
617           if(aMap1.Contains(it.Value())) aNum--;
618         if(aNum == 0) {
619           if(aMap2.Add(aKeyEdge1))
620             aKeyList.Append(aKeyEdge1);
621           if(aMap2.Add(aKeyEdge2))
622             aKeyList.Append(aKeyEdge2);
623         }
624       }
625     } // at the end ==> List of edges to be named in addition
626   }
627   aNumEdges = aKeyList.Extent();
628   if(aNumEdges)
629     theList.Assign(aKeyList);
630   return aNumEdges;
631 }
632
633 //=======================================================================
634 void Model_BodyBuilder::loadFirstLevel(
635   std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int&  theTag)
636 {
637   if(theShape->isNull()) return;
638   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
639   std::string aName;
640   if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) {
641     TopoDS_Iterator itr(aShape);
642     for (; itr.More(); itr.Next(),theTag++) {
643       builder(theTag)->Generated(itr.Value());
644       TCollection_AsciiString aStr(theTag);
645       aName = theName + aStr.ToCString();
646       buildName(theTag, aName);
647       if(!theName.empty()) buildName(theTag, aName);
648       if (itr.Value().ShapeType() == TopAbs_COMPOUND ||
649         itr.Value().ShapeType() == TopAbs_COMPSOLID)
650       {
651         std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
652         itrShape->setImpl(new TopoDS_Shape(itr.Value()));
653         loadFirstLevel(itrShape, theName, theTag);
654       } else {
655         std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
656         itrShape->setImpl(new TopoDS_Shape(itr.Value()));
657         loadNextLevels(itrShape, theName, theTag);
658       }
659     }
660   } else {
661     std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
662     itrShape->setImpl(new TopoDS_Shape(aShape));
663     loadNextLevels(itrShape, theName, theTag);
664   }
665   TopTools_ListOfShape   aList;
666   if(findAmbiguities(aShape, aList)) {
667     TopTools_ListIteratorOfListOfShape it(aList);
668     for (; it.More(); it.Next(),theTag++) {
669       builder(theTag)->Generated(it.Value());
670       TCollection_AsciiString aStr(theTag);
671       aName = theName + aStr.ToCString();
672       buildName(theTag, aName);
673     }
674   }
675 }
676
677 //=======================================================================
678 void Model_BodyBuilder::loadDisconnectedEdges(
679   std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int&  theTag)
680 {
681   if(theShape->isNull()) return;
682   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
683   TopTools_DataMapOfShapeListOfShape edgeNaborFaces;
684   TopTools_ListOfShape empty;
685   TopExp_Explorer explF(aShape, TopAbs_FACE);
686   for (; explF.More(); explF.Next()) {
687     const TopoDS_Shape& aFace = explF.Current();
688     TopExp_Explorer explV(aFace, TopAbs_EDGE);
689     for (; explV.More(); explV.Next()) {
690       const TopoDS_Shape& anEdge = explV.Current();
691       if (!edgeNaborFaces.IsBound(anEdge)) edgeNaborFaces.Bind(anEdge, empty);
692       Standard_Boolean faceIsNew = Standard_True;
693       TopTools_ListIteratorOfListOfShape itrF(edgeNaborFaces.Find(anEdge));
694       for (; itrF.More(); itrF.Next()) {
695         if (itrF.Value().IsSame(aFace)) {
696           faceIsNew = Standard_False;
697           break;
698         }
699       }
700       if (faceIsNew)
701         edgeNaborFaces.ChangeFind(anEdge).Append(aFace);
702     }
703   }
704
705   TopTools_MapOfShape anEdgesToDelete;
706   TopExp_Explorer anEx(aShape,TopAbs_EDGE);
707   std::string aName;
708   for(;anEx.More();anEx.Next()) {
709     Standard_Boolean aC0 = Standard_False;
710     TopoDS_Shape anEdge1 = anEx.Current();
711     if (edgeNaborFaces.IsBound(anEdge1)) {
712       const TopTools_ListOfShape& aList1 = edgeNaborFaces.Find(anEdge1);
713       if (aList1.Extent()<2) continue;
714       TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(edgeNaborFaces);
715       for (; itr.More(); itr.Next()) {
716         TopoDS_Shape anEdge2 = itr.Key();
717         if(anEdgesToDelete.Contains(anEdge2)) continue;
718         if (anEdge1.IsSame(anEdge2)) continue;
719         const TopTools_ListOfShape& aList2 = itr.Value();
720         // compare lists of the neighbour faces of edge1 and edge2
721         if (aList1.Extent() == aList2.Extent()) {
722           Standard_Integer aMatches = 0;
723           for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next())
724             for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next())
725               if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++;
726           if (aMatches == aList1.Extent()) {
727             aC0=Standard_True;
728             builder(theTag)->Generated(anEdge2);
729             anEdgesToDelete.Add(anEdge2);
730             TCollection_AsciiString aStr(theTag);
731             aName = theName + aStr.ToCString();
732             buildName(theTag, aName);
733             theTag++;
734           }
735         }
736       }
737       TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete);
738       for(;itDelete.More();itDelete.Next())
739         edgeNaborFaces.UnBind(itDelete.Key());
740       edgeNaborFaces.UnBind(anEdge1);
741     }
742     if (aC0) {
743       builder(theTag)->Generated(anEdge1);
744       TCollection_AsciiString aStr(theTag);
745       aName = theName + aStr.ToCString();
746       buildName(theTag, aName);
747       theTag++;
748     }
749   }
750 }
751
752 void Model_BodyBuilder::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape> theShape,
753                                                  const std::string& theName, int&  theTag)
754 {
755   if(theShape->isNull()) return;
756   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
757   TopTools_DataMapOfShapeListOfShape vertexNaborEdges;
758   TopTools_ListOfShape empty;
759   TopExp_Explorer explF(aShape, TopAbs_EDGE);
760   for (; explF.More(); explF.Next()) {
761     const TopoDS_Shape& anEdge = explF.Current();
762     TopExp_Explorer explV(anEdge, TopAbs_VERTEX);
763     for (; explV.More(); explV.Next()) {
764       const TopoDS_Shape& aVertex = explV.Current();
765       if (!vertexNaborEdges.IsBound(aVertex)) vertexNaborEdges.Bind(aVertex, empty);
766       Standard_Boolean faceIsNew = Standard_True;
767       TopTools_ListIteratorOfListOfShape itrF(vertexNaborEdges.Find(aVertex));
768       for (; itrF.More(); itrF.Next()) {
769         if (itrF.Value().IsSame(anEdge)) {
770           faceIsNew = Standard_False;
771           break;
772         }
773       }
774       if (faceIsNew) {
775         vertexNaborEdges.ChangeFind(aVertex).Append(anEdge);
776       }
777     }
778   }
779   std::string aName;
780   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(vertexNaborEdges);
781   for (; itr.More(); itr.Next()) {
782     const TopTools_ListOfShape& naborEdges = itr.Value();
783     if (naborEdges.Extent() < 2) {
784       builder(theTag)->Generated(itr.Key());
785       TCollection_AsciiString aStr(theTag);
786       aName = theName + aStr.ToCString();
787       buildName(theTag, aName);
788       theTag++;
789     }
790   }
791 }
792
793 std::shared_ptr<GeomAPI_Shape> Model_BodyBuilder::shape()
794 {
795   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
796   if (aData) {
797     TDF_Label aShapeLab = aData->shapeLab();
798     Handle(TDF_Reference) aRef;
799     if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
800       aShapeLab = aRef->Get();
801     }
802     Handle(TNaming_NamedShape) aName;
803     if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
804       TopoDS_Shape aShape = aName->Get();
805       if (!aShape.IsNull()) {
806         std::shared_ptr<GeomAPI_Shape> aRes(new GeomAPI_Shape);
807         aRes->setImpl(new TopoDS_Shape(aShape));
808         return aRes;
809       }
810     }
811   }
812   return std::shared_ptr<GeomAPI_Shape>();
813 }
814
815 bool Model_BodyBuilder::isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape)
816 {
817   if (theShape.get()) {
818     TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
819     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
820     if (aData) {
821       TDF_Label& aShapeLab = aData->shapeLab();
822       Handle(TNaming_NamedShape) aName;
823       if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
824         TopoDS_Shape aLatest = TNaming_Tool::CurrentShape(aName);
825         if (aLatest.IsNull())
826           return false;
827         if (aLatest.IsEqual(aShape))
828           return true;
829         // check sub-shapes for comp-solids:
830         for (TopExp_Explorer anExp(aShape, aLatest.ShapeType()); anExp.More(); anExp.Next()) {
831           if (aLatest.IsEqual(anExp.Current()))
832             return true;
833         }
834       }
835     }
836   }
837   return false;
838 }