8ad7a59adf5f1311f8711a2948731d38a4286b41
[occt.git] / src / BRepTools / BRepTools_History.cxx
1 // Created on: 2017-04-21
2 // Created by: Alexander Bobkov
3 // Copyright (c) 2017 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BRepTools_History.hxx>
17
18 #include <TopExp.hxx>
19 #include <TopTools_IndexedMapOfShape.hxx>
20
21 // Implement the OCCT RTTI for the type.
22 IMPLEMENT_STANDARD_RTTIEXT(BRepTools_History, Standard_Transient)
23
24 namespace
25 {
26
27 //==============================================================================
28 //function : add
29 //purpose  : Adds the elements of the list to the map.
30 //==============================================================================
31 void add(TopTools_MapOfShape& theMap, const TopTools_ListOfShape& theList)
32 {
33   for (TopTools_ListOfShape::Iterator aSIt(theList); aSIt.More(); aSIt.Next())
34   {
35     theMap.Add(aSIt.Value());
36   }
37 }
38
39 //==============================================================================
40 //function : add
41 //purpose  : Adds the elements of the collection to the list.
42 //==============================================================================
43 template<typename TCollection>
44 void add(TopTools_ListOfShape& theList, const TCollection& theCollection)
45 {
46   for (typename TCollection::Iterator aSIt(theCollection);
47     aSIt.More(); aSIt.Next())
48   {
49     theList.Append(aSIt.Value());
50   }
51 }
52
53 }
54
55 //==============================================================================
56 //function : AddGenerated
57 //purpose  :
58 //==============================================================================
59 void BRepTools_History::AddGenerated(
60   const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated)
61 {
62   if (!prepareGenerated(theInitial, theGenerated))
63   {
64     return;
65   }
66
67   TopTools_ListOfShape* aGenerations =
68     myShapeToGenerated.ChangeSeek(theInitial);
69   if (aGenerations == NULL)
70   {
71     aGenerations = myShapeToGenerated.Bound(theInitial, TopTools_ListOfShape());
72   }
73
74   Standard_ASSERT_VOID(!aGenerations->Contains(theGenerated),
75     "Error: a duplicated generation of a shape.");
76
77   aGenerations->Append(theGenerated);
78 }
79
80 //==============================================================================
81 //function : AddModified
82 //purpose  :
83 //==============================================================================
84 void BRepTools_History::AddModified(
85   const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified)
86 {
87   if (!prepareModified(theInitial, theModified))
88   {
89     return;
90   }
91
92   TopTools_ListOfShape* aModifications =
93     myShapeToModified.ChangeSeek(theInitial);
94   if (aModifications == NULL)
95   {
96     aModifications =
97       myShapeToModified.Bound(theInitial, TopTools_ListOfShape());
98   }
99
100   Standard_ASSERT_VOID(!aModifications->Contains(theModified),
101     "Error: a duplicated modification of a shape.");
102
103   aModifications->Append(theModified);
104 }
105
106 //==============================================================================
107 //function : Remove
108 //purpose  :
109 //==============================================================================
110 void BRepTools_History::Remove(const TopoDS_Shape& theRemoved)
111 {
112   // Apply the limitations.
113   Standard_ASSERT_RETURN(IsSupportedType(theRemoved), myMsgUnsupportedType,);
114
115   if (myShapeToGenerated.UnBind(theRemoved))
116   {
117     Standard_ASSERT_INVOKE_(, myMsgGeneratedAndRemoved);
118   }
119
120   if (myShapeToModified.UnBind(theRemoved))
121   {
122     Standard_ASSERT_INVOKE_(, myMsgModifiedAndRemoved);
123   }
124
125   //
126   myRemoved.Add(theRemoved);
127 }
128
129 //==============================================================================
130 //function : ReplaceGenerated
131 //purpose  :
132 //==============================================================================
133 void BRepTools_History::ReplaceGenerated(
134   const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated)
135 {
136   if (!prepareGenerated(theInitial, theGenerated))
137   {
138     return;
139   }
140
141   TopTools_ListOfShape* aGenerations =
142     myShapeToGenerated.Bound(theInitial, TopTools_ListOfShape());
143   aGenerations->Append(theGenerated);
144 }
145
146 //==============================================================================
147 //function : ReplaceModified
148 //purpose  :
149 //==============================================================================
150 void BRepTools_History::ReplaceModified(
151   const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified)
152 {
153   if (!prepareModified(theInitial, theModified))
154   {
155     return;
156   }
157
158   TopTools_ListOfShape* aModifications =
159     myShapeToModified.Bound(theInitial, TopTools_ListOfShape());
160   aModifications->Append(theModified);
161 }
162
163 //==============================================================================
164 //function : Generated
165 //purpose  :
166 //==============================================================================
167 const TopTools_ListOfShape& BRepTools_History::Generated(
168   const TopoDS_Shape& theInitial) const
169 {
170   // Apply the limitations.
171   Standard_ASSERT_RETURN(theInitial.IsNull() || IsSupportedType(theInitial),
172     myMsgUnsupportedType, emptyList());
173
174   //
175   const TopTools_ListOfShape* aGenerations =
176     myShapeToGenerated.Seek(theInitial);
177   return (aGenerations != NULL) ? *aGenerations : emptyList();
178 }
179
180 //==============================================================================
181 //function : Modified
182 //purpose  :
183 //==============================================================================
184 const TopTools_ListOfShape& BRepTools_History::Modified(
185   const TopoDS_Shape& theInitial) const
186 {
187   // Apply the limitations.
188   Standard_ASSERT_RETURN(IsSupportedType(theInitial),
189     myMsgUnsupportedType, emptyList());
190
191   //
192   const TopTools_ListOfShape* aModifications =
193     myShapeToModified.Seek(theInitial);
194   return (aModifications != NULL) ? *aModifications : emptyList();
195 }
196
197 //==============================================================================
198 //function : IsRemoved
199 //purpose  :
200 //==============================================================================
201 Standard_Boolean BRepTools_History::IsRemoved(
202   const TopoDS_Shape& theInitial) const
203 {
204   // Apply the limitations.
205   Standard_ASSERT_RETURN(IsSupportedType(theInitial),
206     myMsgUnsupportedType, Standard_False);
207
208   //
209   return myRemoved.Contains(theInitial);
210 }
211
212 //==============================================================================
213 //function : Merge
214 //purpose  :
215 //==============================================================================
216 void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
217 {
218   Merge(*theHistory23.get());
219 }
220 //==============================================================================
221 //function : Merge
222 //purpose  :
223 //==============================================================================
224 void BRepTools_History::Merge(const BRepTools_History& theHistory23)
225 {
226   // Propagate R23 directly and M23 and G23 fully to M12 and G12.
227   // Remember the propagated shapes.
228   TopTools_DataMapOfShapeListOfShape* aS1ToGAndM[] =
229     {&myShapeToGenerated, &myShapeToModified};
230   TopTools_MapOfShape aRPropagated;
231   {
232     // Propagate R23, M23 and G23 to M12 and G12 directly.
233     // Remember the propagated shapes.
234     TopTools_MapOfShape aMAndGPropagated;
235     for (Standard_Integer aI = 0; aI < 2; ++aI)
236     {
237       for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt1(*aS1ToGAndM[aI]);
238         aMIt1.More(); aMIt1.Next())
239       {
240         TopTools_ListOfShape& aL12 = aMIt1.ChangeValue();
241         TopTools_MapOfShape aAdditions[2]; // The G and M additions.
242         for (TopTools_ListOfShape::Iterator aSIt2(aL12); aSIt2.More();)
243         {
244           const TopoDS_Shape& aS2 = aSIt2.Value();
245           if (theHistory23.IsRemoved(aS2))
246           {
247             aRPropagated.Add(aS2);
248             aL12.Remove(aSIt2);
249           }
250           else
251           {
252             if (theHistory23.myShapeToGenerated.IsBound(aS2))
253             {
254               add(aAdditions[0], theHistory23.myShapeToGenerated(aS2));
255               aMAndGPropagated.Add(aS2);
256             }
257
258             if (theHistory23.myShapeToModified.IsBound(aS2))
259             {
260               add(aAdditions[aI], theHistory23.myShapeToModified(aS2));
261               aMAndGPropagated.Add(aS2);
262
263               aL12.Remove(aSIt2);
264             }
265             else
266             {
267               aSIt2.Next();
268             }
269           }
270         }
271
272         add(aL12, aAdditions[aI]);
273         if (aI != 0 && !aAdditions[0].IsEmpty())
274         {
275           const TopoDS_Shape& aS1 = aMIt1.Key();
276           TopTools_ListOfShape* aGAndM = aS1ToGAndM[0]->ChangeSeek(aS1);
277           if (aGAndM == NULL)
278           {
279             aGAndM = aS1ToGAndM[0]->Bound(aS1, TopTools_ListOfShape());
280           }
281
282           add(*aGAndM, aAdditions[0]);
283         }
284       }
285     }
286
287     // Propagate M23 and G23 to M12 and G12 sequentially.
288     const TopTools_DataMapOfShapeListOfShape* aS2ToGAndM[] =
289       {&theHistory23.myShapeToGenerated, &theHistory23.myShapeToModified};
290     for (Standard_Integer aI = 0; aI < 2; ++aI)
291     {
292       for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt2(*aS2ToGAndM[aI]);
293         aMIt2.More(); aMIt2.Next())
294       {
295         const TopoDS_Shape& aS2 = aMIt2.Key();
296         if (!aMAndGPropagated.Contains(aS2))
297         {
298           if (!aS1ToGAndM[aI]->IsBound(aS2))
299           {
300             aS1ToGAndM[aI]->Bind(aS2, TopTools_ListOfShape());
301           }
302
303           TopTools_ListOfShape aM2 = aMIt2.Value();
304           ((*aS1ToGAndM[aI])(aS2)).Append(aM2);
305         }
306       }
307     }
308   }
309
310   // Unbound the empty M12 and G12.
311   for (Standard_Integer aI = 0; aI < 2; ++aI)
312   {
313     for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt1(*aS1ToGAndM[aI]);
314       aMIt1.More();)
315     {
316       const TopoDS_Shape& aS1 = aMIt1.Key();
317       const TopTools_ListOfShape& aL12 = aMIt1.Value();
318       aMIt1.Next();
319       if (aL12.IsEmpty())
320       {
321         myRemoved.Add(aS1);
322         aS1ToGAndM[aI]->UnBind(aS1);
323       }
324     }
325   }
326
327   // Propagate R23 to R12 sequentially.
328   for (TopTools_MapOfShape::Iterator aRIt23(theHistory23.myRemoved);
329     aRIt23.More(); aRIt23.Next())
330   {
331     const TopoDS_Shape& aS2 = aRIt23.Value();
332     if (!aRPropagated.Contains(aS2) &&
333       !myShapeToModified.IsBound(aS2) &&
334       !myShapeToGenerated.IsBound(aS2))
335     {
336       myRemoved.Add(aS2);
337     }
338   }
339 }
340
341 //==============================================================================
342 //function : prepareGenerated
343 //purpose  :
344 //==============================================================================
345 Standard_Boolean BRepTools_History::prepareGenerated(
346   const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated)
347 {
348   Standard_ASSERT_RETURN(theInitial.IsNull() ||
349     IsSupportedType(theInitial), myMsgUnsupportedType, Standard_False);
350
351   if (myRemoved.Remove(theInitial))
352   {
353     Standard_ASSERT_INVOKE_(, myMsgGeneratedAndRemoved);
354   }
355
356   if (myShapeToModified.IsBound(theInitial) &&
357     myShapeToModified(theInitial).Remove(theGenerated))
358   {
359     Standard_ASSERT_INVOKE_(, myMsgGeneratedAndModified);
360   }
361
362   return Standard_True;
363 }
364
365 //==============================================================================
366 //function : prepareModified
367 //purpose  :
368 //==============================================================================
369 Standard_Boolean BRepTools_History::prepareModified(
370   const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified)
371 {
372   Standard_ASSERT_RETURN(IsSupportedType(theInitial),
373     myMsgUnsupportedType, Standard_False);
374
375   if (myRemoved.Remove(theInitial))
376   {
377     Standard_ASSERT_INVOKE_(, myMsgModifiedAndRemoved);
378   }
379
380   if (myShapeToGenerated.IsBound(theInitial) &&
381     myShapeToGenerated(theInitial).Remove(theModified))
382   {
383     Standard_ASSERT_INVOKE_(, myMsgGeneratedAndModified);
384   }
385
386   return Standard_True;
387 }
388
389 //==============================================================================
390 //data : myEmptyList
391 //purpose  :
392 //==============================================================================
393 const TopTools_ListOfShape BRepTools_History::myEmptyList;
394
395 //==============================================================================
396 //function : emptyList
397 //purpose  :
398 //==============================================================================
399 const TopTools_ListOfShape& BRepTools_History::emptyList()
400 {
401   return myEmptyList;
402 }
403
404 //==============================================================================
405 //data : myMsgUnsupportedType
406 //purpose  :
407 //==============================================================================
408 const char* BRepTools_History::myMsgUnsupportedType =
409   "Error: unsupported shape type.";
410
411 //==============================================================================
412 //data : myMsgGeneratedAndRemoved
413 //purpose  :
414 //==============================================================================
415 const char* BRepTools_History::myMsgGeneratedAndRemoved =
416   "Error: a shape is generated and removed simultaneously.";
417
418 //==============================================================================
419 //data : myMsgModifiedAndRemoved
420 //purpose  :
421 //==============================================================================
422 const char* BRepTools_History::myMsgModifiedAndRemoved =
423   "Error: a shape is modified and removed simultaneously.";
424
425 //==============================================================================
426 //data : myMsgGeneratedAndModified
427 //purpose  :
428 //==============================================================================
429 const char* BRepTools_History::myMsgGeneratedAndModified =
430   "Error: a shape is generated and modified "
431     "from the same shape simultaneously.";