Salome HOME
Boost has been removed from code
[modules/shaper.git] / src / Model / Model_ResultBody.cpp
1 // File:        Model_ResultBody.cpp
2 // Created:     08 Jul 2014
3 // Author:      Mikhail PONIKAROV
4
5 #include <Model_ResultBody.h>
6 #include <Model_Data.h>
7 #include <TNaming_Builder.hxx>
8 #include <TNaming_NamedShape.hxx>
9 #include <TopoDS.hxx>
10 #include <TopoDS_Shape.hxx>
11 #include <TopoDS_Face.hxx>
12 #include <TDF_ChildIterator.hxx>
13 #include <TopTools_MapOfShape.hxx>
14 #include <TopExp_Explorer.hxx>
15 #include <TopTools_ListOfShape.hxx>
16 #include <TopTools_ListIteratorOfListOfShape.hxx>
17 #include <TopTools_DataMapOfShapeListOfShape.hxx>
18 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
19 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
20 #include <TopTools_MapIteratorOfMapOfShape.hxx>
21 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
22 #include <TopTools_IndexedMapOfShape.hxx>
23 #include <TopTools_DataMapOfShapeShape.hxx>
24 #include <TopExp.hxx>
25 #include <BRepTools.hxx>
26 #include <GeomAPI_Shape.h>
27 #include <GeomAlgoAPI_MakeShape.h>
28 // DEB
29 //#include <TCollection_AsciiString.hxx>
30 //#include <TDF_Tool.hxx>
31 Model_ResultBody::Model_ResultBody()
32 {
33   setIsConcealed(false);
34 }
35
36 void Model_ResultBody::store(const std::shared_ptr<GeomAPI_Shape>& theShape)
37 {
38   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
39   if (aData) {
40     TDF_Label& aShapeLab = aData->shapeLab();
41     // clean builders
42     clean();   
43     // store the new shape as primitive
44     TNaming_Builder aBuilder(aShapeLab);
45     if (!theShape)
46       return;  // bad shape
47     TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
48     if (aShape.IsNull())
49       return;  // null shape inside
50
51     aBuilder.Generated(aShape);
52   }
53 }
54
55 void Model_ResultBody::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& theFromShape,
56   const std::shared_ptr<GeomAPI_Shape>& theToShape)
57 {
58   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
59   if (aData) {
60     TDF_Label& aShapeLab = aData->shapeLab();
61     // clean builders
62     clean();   
63     // store the new shape as primitive
64     TNaming_Builder aBuilder(aShapeLab);
65     if (!theFromShape || !theToShape)
66       return;  // bad shape
67     TopoDS_Shape aShapeBasis = theFromShape->impl<TopoDS_Shape>();
68     if (aShapeBasis.IsNull())
69       return;  // null shape inside
70     TopoDS_Shape aShapeNew = theToShape->impl<TopoDS_Shape>();
71     if (aShapeNew.IsNull())
72       return;  // null shape inside
73     aBuilder.Generated(aShapeBasis, aShapeNew);
74   }
75 }
76
77 void Model_ResultBody::storeModified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
78   const std::shared_ptr<GeomAPI_Shape>& theNewShape)
79 {
80   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
81   if (aData) {
82     TDF_Label& aShapeLab = aData->shapeLab();
83     // clean builders
84     clean();   
85     // store the new shape as primitive
86     TNaming_Builder aBuilder(aShapeLab);
87     if (!theOldShape || !theNewShape)
88       return;  // bad shape
89     TopoDS_Shape aShapeOld = theOldShape->impl<TopoDS_Shape>();
90     if (aShapeOld.IsNull())
91       return;  // null shape inside
92     TopoDS_Shape aShapeNew = theNewShape->impl<TopoDS_Shape>();
93     if (aShapeNew.IsNull())
94       return;  // null shape inside
95     aBuilder.Generated(aShapeOld, aShapeNew);
96   }
97 }
98
99 std::shared_ptr<GeomAPI_Shape> Model_ResultBody::shape()
100 {
101   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
102   if (aData) {
103     TDF_Label& aShapeLab = aData->shapeLab();
104     Handle(TNaming_NamedShape) aName;
105     if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
106       TopoDS_Shape aShape = aName->Get();
107       if (!aShape.IsNull()) {
108         std::shared_ptr<GeomAPI_Shape> aRes(new GeomAPI_Shape);
109         aRes->setImpl(new TopoDS_Shape(aShape));
110         return aRes;
111       }
112     }
113   }
114   return std::shared_ptr<GeomAPI_Shape>();
115 }
116
117 void Model_ResultBody::clean()
118 {
119   std::vector<TNaming_Builder*>::iterator aBuilder = myBuilders.begin();
120   for(; aBuilder != myBuilders.end(); aBuilder++)
121     delete *aBuilder;
122   myBuilders.clear();
123 }
124
125 Model_ResultBody::~Model_ResultBody()
126 {
127   clean();
128 }
129
130 TNaming_Builder* Model_ResultBody::builder(const int theTag)
131 {
132   if (myBuilders.size() <= (unsigned int)theTag) {
133     myBuilders.insert(myBuilders.end(), theTag - myBuilders.size() + 1, NULL);
134   }
135   if (!myBuilders[theTag]) {
136     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
137     myBuilders[theTag] = new TNaming_Builder(aData->shapeLab().FindChild(theTag));
138     //TCollection_AsciiString entry;//
139     //TDF_Tool::Entry(aData->shapeLab().FindChild(theTag), entry);
140     //cout << "Label = " <<entry.ToCString() <<endl;
141   }
142   return myBuilders[theTag];
143 }
144
145 void Model_ResultBody::generated(
146   const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theTag)
147 {
148   TopoDS_Shape aShape = theNewShape->impl<TopoDS_Shape>();
149   builder(theTag)->Generated(aShape);
150 }
151
152 void Model_ResultBody::generated(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
153   const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theTag)
154 {
155   TopoDS_Shape anOldShape = theOldShape->impl<TopoDS_Shape>();
156   TopoDS_Shape aNewShape = theNewShape->impl<TopoDS_Shape>();
157   builder(theTag)->Generated(anOldShape, aNewShape);
158 }
159
160
161 void Model_ResultBody::modified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
162   const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theTag)
163 {
164   TopoDS_Shape anOldShape = theOldShape->impl<TopoDS_Shape>();
165   TopoDS_Shape aNewShape = theNewShape->impl<TopoDS_Shape>();
166   builder(theTag)->Modify(anOldShape, aNewShape);
167 }
168
169 void Model_ResultBody::deleted(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
170   const int theTag)
171 {
172   TopoDS_Shape aShape = theOldShape->impl<TopoDS_Shape>();
173   builder(theTag)->Delete(aShape);
174 }
175
176 void Model_ResultBody::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS,
177   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
178   const int  theKindOfShape,
179   const int  theTag)
180 {
181   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
182   TopTools_MapOfShape aView;
183   TopExp_Explorer ShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
184   for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
185     const TopoDS_Shape& aRoot = ShapeExplorer.Current ();
186     if (!aView.Add(aRoot)) continue;
187     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
188     aRShape->setImpl((new TopoDS_Shape(aRoot)));
189     if (theMS->isDeleted (aRShape)) {
190       builder(theTag)->Delete(aRoot);
191     }
192   }
193 }
194
195 void Model_ResultBody::loadAndOrientModifiedShapes (
196   GeomAlgoAPI_MakeShape* theMS,
197   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
198   const int  theKindOfShape,
199   const int  theTag,
200   GeomAPI_DataMapOfShapeShape& theSubShapes)
201 {
202   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
203   TopTools_MapOfShape aView;
204   TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
205   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
206     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
207     if (!aView.Add(aRoot)) continue;
208     ListOfShape aList;
209     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
210     aRShape->setImpl((new TopoDS_Shape(aRoot)));
211         theMS->modified(aRShape, aList);
212     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = aList.begin(), aLast = aList.end();
213     for (; anIt != aLast; anIt++) {
214       TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();     
215       if (theSubShapes.isBound(*anIt)) {
216         std::shared_ptr<GeomAPI_Shape> aMapShape(theSubShapes.find(*anIt));
217         aNewShape.Orientation(aMapShape->impl<TopoDS_Shape>().Orientation());
218       }
219       if (!aRoot.IsSame (aNewShape)) 
220         builder(theTag)->Modify(aRoot,aNewShape);
221     }
222   }
223 }
224
225 void Model_ResultBody::loadAndOrientGeneratedShapes (
226   GeomAlgoAPI_MakeShape* theMS,
227   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
228   const int  theKindOfShape,
229   const int  theTag,
230   GeomAPI_DataMapOfShapeShape& theSubShapes)
231 {
232   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
233   TopTools_MapOfShape aView;
234   TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
235   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
236     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
237     if (!aView.Add(aRoot)) continue;
238     ListOfShape aList;
239     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
240     aRShape->setImpl((new TopoDS_Shape(aRoot)));
241     theMS->generated(aRShape, aList);
242     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = aList.begin(), aLast = aList.end();
243     for (; anIt != aLast; anIt++) {
244       TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();     
245       if (theSubShapes.isBound(*anIt)) {
246         std::shared_ptr<GeomAPI_Shape> aMapShape(theSubShapes.find(*anIt));
247         aNewShape.Orientation(aMapShape->impl<TopoDS_Shape>().Orientation());
248       }
249       if (!aRoot.IsSame (aNewShape)) 
250         builder(theTag)->Generated(aRoot,aNewShape);
251     }
252   }
253 }
254
255 //=======================================================================
256 int getDangleShapes(const TopoDS_Shape&           theShapeIn, 
257                                         const TopAbs_ShapeEnum        theGeneratedFrom,
258                                     TopTools_DataMapOfShapeShape& theDangles) 
259 {
260   theDangles.Clear();
261   TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors;
262   TopAbs_ShapeEnum GeneratedTo;
263   if (theGeneratedFrom == TopAbs_FACE) GeneratedTo = TopAbs_EDGE;
264   else if (theGeneratedFrom == TopAbs_EDGE) GeneratedTo = TopAbs_VERTEX;
265   else return Standard_False;
266   TopExp::MapShapesAndAncestors(theShapeIn, GeneratedTo, theGeneratedFrom, subShapeAndAncestors);
267   for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) {
268     const TopoDS_Shape& mayBeDangle = subShapeAndAncestors.FindKey(i);
269     const TopTools_ListOfShape& ancestors = subShapeAndAncestors.FindFromIndex(i);
270     if (ancestors.Extent() == 1) theDangles.Bind(ancestors.First(), mayBeDangle);
271   }
272   return theDangles.Extent();
273 }
274
275 //=======================================================================
276 void loadGeneratedDangleShapes(
277                                                            const TopoDS_Shape&      theShapeIn,
278                                                const TopAbs_ShapeEnum   theGeneratedFrom,
279                                                TNaming_Builder *        theBuilder)
280 {
281   TopTools_DataMapOfShapeShape dangles;
282   if (!getDangleShapes(theShapeIn, theGeneratedFrom, dangles)) return;
283   TopTools_DataMapIteratorOfDataMapOfShapeShape itr(dangles);
284   for (; itr.More(); itr.Next()) 
285         theBuilder->Generated(itr.Key(), itr.Value());
286 }
287
288 //=======================================================================
289 void Model_ResultBody::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape, 
290                                           int&  theTag)
291 {
292   if(theShape->isNull()) return;
293   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();    
294   if (aShape.ShapeType() == TopAbs_SOLID) {                 
295     TopExp_Explorer expl(aShape, TopAbs_FACE);
296     for (; expl.More(); expl.Next())      
297           builder(++theTag)->Generated(expl.Current());     
298   }
299   else if (aShape.ShapeType() == TopAbs_SHELL || aShape.ShapeType() == TopAbs_FACE) {
300     // load faces and all the free edges
301     TopTools_IndexedMapOfShape Faces;
302     TopExp::MapShapes(aShape, TopAbs_FACE, Faces);
303     if (Faces.Extent() > 1 || (aShape.ShapeType() == TopAbs_SHELL && Faces.Extent() == 1)) {
304       TopExp_Explorer expl(aShape, TopAbs_FACE);
305       for (; expl.More(); expl.Next()) 
306                   builder(++theTag)->Generated(expl.Current());          
307         }
308     TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces;
309     TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, anEdgeAndNeighbourFaces);
310     for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++) 
311         {
312       const TopTools_ListOfShape& aLL = anEdgeAndNeighbourFaces.FindFromIndex(i);
313       if (aLL.Extent() < 2) {
314             builder(++theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));    
315       } else {
316           TopTools_ListIteratorOfListOfShape anIter(aLL);
317           const TopoDS_Face& aFace = TopoDS::Face(anIter.Value());
318           anIter.Next();
319           if(aFace.IsEqual(anIter.Value())) {
320                 builder(++theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
321           }
322           }
323         }
324   } else if (aShape.ShapeType() == TopAbs_WIRE) {
325     TopTools_IndexedMapOfShape Edges;
326     BRepTools::Map3DEdges(aShape, Edges);
327     if (Edges.Extent() == 1) {
328           builder(++theTag)->Generated(Edges.FindKey(1));
329       TopExp_Explorer expl(aShape, TopAbs_VERTEX);
330       for (; expl.More(); expl.Next()) {
331             builder(++theTag)->Generated(expl.Current());
332           }
333         } else {
334       TopExp_Explorer expl(aShape, TopAbs_EDGE); 
335       for (; expl.More(); expl.Next()) {        
336                 builder(++theTag)->Generated(expl.Current());
337           }   
338       // and load generated vertices.
339       TopTools_DataMapOfShapeShape generated;
340       if (getDangleShapes(aShape, TopAbs_EDGE, generated)) 
341           {
342                 TNaming_Builder* pBuilder = builder(++theTag);
343                 loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder);  
344           }
345         }
346   } else if (aShape.ShapeType() == TopAbs_EDGE) {
347     TopExp_Explorer expl(aShape, TopAbs_VERTEX);
348     for (; expl.More(); expl.Next()) {      
349                 builder(++theTag)->Generated(expl.Current());
350         }
351   }
352 }
353 //=======================================================================
354 void Model_ResultBody::loadFirstLevel(
355                      std::shared_ptr<GeomAPI_Shape> theShape, int&  theTag)
356 {
357  if(theShape->isNull()) return;
358  TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();    
359   if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) {
360     TopoDS_Iterator itr(aShape);
361     for (; itr.More(); itr.Next()) {
362           builder(++theTag)->Generated(itr.Value());     
363       if (itr.Value().ShapeType() == TopAbs_COMPOUND || 
364                   itr.Value().ShapeType() == TopAbs_COMPSOLID) 
365           {
366                 std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
367         itrShape->setImpl(new TopoDS_Shape(itr.Value()));
368             loadFirstLevel(itrShape, theTag);
369       } else {
370                 std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
371         itrShape->setImpl(new TopoDS_Shape(itr.Value()));
372                 loadNextLevels(itrShape, theTag);
373           }
374     }
375   } else {
376     std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
377     itrShape->setImpl(new TopoDS_Shape(aShape));
378         loadNextLevels(itrShape, theTag); 
379   }
380 }
381
382 //=======================================================================
383 void Model_ResultBody::loadDisconnectedEdges(
384                      std::shared_ptr<GeomAPI_Shape> theShape, int&  theTag)
385 {
386   if(theShape->isNull()) return;
387   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();  
388   TopTools_DataMapOfShapeListOfShape edgeNaborFaces;
389   TopTools_ListOfShape empty;
390   TopExp_Explorer explF(aShape, TopAbs_FACE);
391   for (; explF.More(); explF.Next()) {
392     const TopoDS_Shape& aFace = explF.Current();
393     TopExp_Explorer explV(aFace, TopAbs_EDGE);
394     for (; explV.More(); explV.Next()) {
395       const TopoDS_Shape& anEdge = explV.Current();
396       if (!edgeNaborFaces.IsBound(anEdge)) edgeNaborFaces.Bind(anEdge, empty);
397       Standard_Boolean faceIsNew = Standard_True;
398       TopTools_ListIteratorOfListOfShape itrF(edgeNaborFaces.Find(anEdge));
399       for (; itrF.More(); itrF.Next()) {
400             if (itrF.Value().IsSame(aFace)) {
401             faceIsNew = Standard_False;
402             break;
403                 }
404           }
405       if (faceIsNew) 
406             edgeNaborFaces.ChangeFind(anEdge).Append(aFace);      
407         }
408   }
409   
410   TopTools_MapOfShape anEdgesToDelete;
411   TopExp_Explorer anEx(aShape,TopAbs_EDGE); 
412   for(;anEx.More();anEx.Next()) {
413     Standard_Boolean aC0 = Standard_False;
414     TopoDS_Shape anEdge1 = anEx.Current();
415     if (edgeNaborFaces.IsBound(anEdge1)) {
416       const TopTools_ListOfShape& aList1 = edgeNaborFaces.Find(anEdge1);
417       if (aList1.Extent()<2) continue;
418       TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(edgeNaborFaces);
419       for (; itr.More(); itr.Next()) {
420             TopoDS_Shape anEdge2 = itr.Key();
421             if(anEdgesToDelete.Contains(anEdge2)) continue;
422             if (anEdge1.IsSame(anEdge2)) continue;
423             const TopTools_ListOfShape& aList2 = itr.Value();
424             // compare lists of the neighbour faces of edge1 and edge2
425             if (aList1.Extent() == aList2.Extent()) {
426             Standard_Integer aMatches = 0;
427             for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next())
428               for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next())
429                 if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++;
430                 if (aMatches == aList1.Extent()) {
431                   aC0=Standard_True;
432                           builder(++theTag)->Generated(anEdge2);              
433                   anEdgesToDelete.Add(anEdge2);
434                         }
435                 }
436           }      
437       TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete);
438       for(;itDelete.More();itDelete.Next()) 
439             edgeNaborFaces.UnBind(itDelete.Key());      
440       edgeNaborFaces.UnBind(anEdge1);
441         }
442     if (aC0) 
443           builder(++theTag)->Generated(anEdge1);                  
444   }
445 }
446
447 void Model_ResultBody::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape> theShape, int&  theTag)
448 {
449   if(theShape->isNull()) return;
450   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();  
451   TopTools_DataMapOfShapeListOfShape vertexNaborFaces;
452   TopTools_ListOfShape empty;
453   TopExp_Explorer explF(aShape, TopAbs_FACE);
454   for (; explF.More(); explF.Next()) {
455     const TopoDS_Shape& aFace = explF.Current();
456     TopExp_Explorer explV(aFace, TopAbs_VERTEX);
457     for (; explV.More(); explV.Next()) {
458       const TopoDS_Shape& aVertex = explV.Current();
459       if (!vertexNaborFaces.IsBound(aVertex)) vertexNaborFaces.Bind(aVertex, empty);
460       Standard_Boolean faceIsNew = Standard_True;
461       TopTools_ListIteratorOfListOfShape itrF(vertexNaborFaces.Find(aVertex));
462       for (; itrF.More(); itrF.Next()) {
463         if (itrF.Value().IsSame(aFace)) {
464           faceIsNew = Standard_False;
465           break;
466         }
467       }
468       if (faceIsNew) {
469         vertexNaborFaces.ChangeFind(aVertex).Append(aFace);
470       }
471     }
472   }
473
474   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(vertexNaborFaces);
475   for (; itr.More(); itr.Next()) {
476     const TopTools_ListOfShape& naborFaces = itr.Value();
477     if (naborFaces.Extent() < 3) 
478                 builder(++theTag)->Generated(itr.Key());         
479   }
480 }