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