0028747: Incorrect result of the section operation after edge refinement
[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 (myShapeToModified.UnBind(theRemoved))
116   {
117     Standard_ASSERT_INVOKE_(, myMsgModifiedAndRemoved);
118   }
119
120   myRemoved.Add(theRemoved);
121 }
122
123 //==============================================================================
124 //function : ReplaceGenerated
125 //purpose  :
126 //==============================================================================
127 void BRepTools_History::ReplaceGenerated(
128   const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated)
129 {
130   if (!prepareGenerated(theInitial, theGenerated))
131   {
132     return;
133   }
134
135   TopTools_ListOfShape* aGenerations =
136     myShapeToGenerated.Bound(theInitial, TopTools_ListOfShape());
137   aGenerations->Append(theGenerated);
138 }
139
140 //==============================================================================
141 //function : ReplaceModified
142 //purpose  :
143 //==============================================================================
144 void BRepTools_History::ReplaceModified(
145   const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified)
146 {
147   if (!prepareModified(theInitial, theModified))
148   {
149     return;
150   }
151
152   TopTools_ListOfShape* aModifications =
153     myShapeToModified.Bound(theInitial, TopTools_ListOfShape());
154   aModifications->Append(theModified);
155 }
156
157 //==============================================================================
158 //function : Generated
159 //purpose  :
160 //==============================================================================
161 const TopTools_ListOfShape& BRepTools_History::Generated(
162   const TopoDS_Shape& theInitial) const
163 {
164   // Apply the limitations.
165   Standard_ASSERT_RETURN(theInitial.IsNull() || IsSupportedType(theInitial),
166     myMsgUnsupportedType, emptyList());
167
168   //
169   const TopTools_ListOfShape* aGenerations =
170     myShapeToGenerated.Seek(theInitial);
171   return (aGenerations != NULL) ? *aGenerations : emptyList();
172 }
173
174 //==============================================================================
175 //function : Modified
176 //purpose  :
177 //==============================================================================
178 const TopTools_ListOfShape& BRepTools_History::Modified(
179   const TopoDS_Shape& theInitial) const
180 {
181   // Apply the limitations.
182   Standard_ASSERT_RETURN(IsSupportedType(theInitial),
183     myMsgUnsupportedType, emptyList());
184
185   //
186   const TopTools_ListOfShape* aModifications =
187     myShapeToModified.Seek(theInitial);
188   return (aModifications != NULL) ? *aModifications : emptyList();
189 }
190
191 //==============================================================================
192 //function : IsRemoved
193 //purpose  :
194 //==============================================================================
195 Standard_Boolean BRepTools_History::IsRemoved(
196   const TopoDS_Shape& theInitial) const
197 {
198   // Apply the limitations.
199   Standard_ASSERT_RETURN(IsSupportedType(theInitial),
200     myMsgUnsupportedType, Standard_False);
201
202   //
203   return myRemoved.Contains(theInitial);
204 }
205
206 //==============================================================================
207 //function : Merge
208 //purpose  :
209 //==============================================================================
210 void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
211 {
212   Merge(*theHistory23.get());
213 }
214 //==============================================================================
215 //function : Merge
216 //purpose  :
217 //==============================================================================
218 void BRepTools_History::Merge(const BRepTools_History& theHistory23)
219 {
220   // Propagate R23 directly and M23 and G23 fully to M12 and G12.
221   // Remember the propagated shapes.
222   TopTools_DataMapOfShapeListOfShape* aS1ToGAndM[] =
223     {&myShapeToGenerated, &myShapeToModified};
224   TopTools_MapOfShape aRPropagated;
225   {
226     // Propagate R23, M23 and G23 to M12 and G12 directly.
227     // Remember the propagated shapes.
228     TopTools_MapOfShape aMAndGPropagated;
229     for (Standard_Integer aI = 0; aI < 2; ++aI)
230     {
231       for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt1(*aS1ToGAndM[aI]);
232         aMIt1.More(); aMIt1.Next())
233       {
234         TopTools_ListOfShape& aL12 = aMIt1.ChangeValue();
235         TopTools_MapOfShape aAdditions[2]; // The G and M additions.
236         for (TopTools_ListOfShape::Iterator aSIt2(aL12); aSIt2.More();)
237         {
238           const TopoDS_Shape& aS2 = aSIt2.Value();
239           if (theHistory23.IsRemoved(aS2))
240           {
241             aRPropagated.Add(aS2);
242             aL12.Remove(aSIt2);
243           }
244           else
245           {
246             if (theHistory23.myShapeToGenerated.IsBound(aS2))
247             {
248               add(aAdditions[0], theHistory23.myShapeToGenerated(aS2));
249               aMAndGPropagated.Add(aS2);
250             }
251
252             if (theHistory23.myShapeToModified.IsBound(aS2))
253             {
254               add(aAdditions[aI], theHistory23.myShapeToModified(aS2));
255               aMAndGPropagated.Add(aS2);
256
257               aL12.Remove(aSIt2);
258             }
259             else
260             {
261               aSIt2.Next();
262             }
263           }
264         }
265
266         add(aL12, aAdditions[aI]);
267         if (aI != 0 && !aAdditions[0].IsEmpty())
268         {
269           const TopoDS_Shape& aS1 = aMIt1.Key();
270           TopTools_ListOfShape* aGAndM = aS1ToGAndM[0]->ChangeSeek(aS1);
271           if (aGAndM == NULL)
272           {
273             aGAndM = aS1ToGAndM[0]->Bound(aS1, TopTools_ListOfShape());
274           }
275
276           add(*aGAndM, aAdditions[0]);
277         }
278       }
279     }
280
281     // Propagate M23 and G23 to M12 and G12 sequentially.
282     const TopTools_DataMapOfShapeListOfShape* aS2ToGAndM[] =
283       {&theHistory23.myShapeToGenerated, &theHistory23.myShapeToModified};
284     for (Standard_Integer aI = 0; aI < 2; ++aI)
285     {
286       for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt2(*aS2ToGAndM[aI]);
287         aMIt2.More(); aMIt2.Next())
288       {
289         const TopoDS_Shape& aS2 = aMIt2.Key();
290         if (!aMAndGPropagated.Contains(aS2))
291         {
292           if (!aS1ToGAndM[aI]->IsBound(aS2))
293           {
294             aS1ToGAndM[aI]->Bind(aS2, TopTools_ListOfShape());
295           }
296
297           TopTools_ListOfShape aM2 = aMIt2.Value();
298           ((*aS1ToGAndM[aI])(aS2)).Append(aM2);
299           myRemoved.Remove(aS2);
300         }
301       }
302     }
303   }
304
305   // Unbound the empty M12 and G12.
306   for (Standard_Integer aI = 0; aI < 2; ++aI)
307   {
308     for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt1(*aS1ToGAndM[aI]);
309       aMIt1.More();)
310     {
311       const TopoDS_Shape& aS1 = aMIt1.Key();
312       const TopTools_ListOfShape& aL12 = aMIt1.Value();
313       aMIt1.Next();
314       if (aL12.IsEmpty())
315       {
316         myRemoved.Add(aS1);
317         aS1ToGAndM[aI]->UnBind(aS1);
318       }
319     }
320   }
321
322   // Propagate R23 to R12 sequentially.
323   for (TopTools_MapOfShape::Iterator aRIt23(theHistory23.myRemoved);
324     aRIt23.More(); aRIt23.Next())
325   {
326     const TopoDS_Shape& aS2 = aRIt23.Value();
327     if (!aRPropagated.Contains(aS2) &&
328       !myShapeToModified.IsBound(aS2) &&
329       !myShapeToGenerated.IsBound(aS2))
330     {
331       myRemoved.Add(aS2);
332     }
333   }
334 }
335
336 //==============================================================================
337 //function : prepareGenerated
338 //purpose  :
339 //==============================================================================
340 Standard_Boolean BRepTools_History::prepareGenerated(
341   const TopoDS_Shape& theInitial, const TopoDS_Shape& theGenerated)
342 {
343   Standard_ASSERT_RETURN(theInitial.IsNull() ||
344     IsSupportedType(theInitial), myMsgUnsupportedType, Standard_False);
345
346   if (myShapeToModified.IsBound(theInitial) &&
347     myShapeToModified(theInitial).Remove(theGenerated))
348   {
349     Standard_ASSERT_INVOKE_(, myMsgGeneratedAndModified);
350   }
351
352   return Standard_True;
353 }
354
355 //==============================================================================
356 //function : prepareModified
357 //purpose  :
358 //==============================================================================
359 Standard_Boolean BRepTools_History::prepareModified(
360   const TopoDS_Shape& theInitial, const TopoDS_Shape& theModified)
361 {
362   Standard_ASSERT_RETURN(IsSupportedType(theInitial),
363     myMsgUnsupportedType, Standard_False);
364
365   if (myRemoved.Remove(theInitial))
366   {
367     Standard_ASSERT_INVOKE_(, myMsgModifiedAndRemoved);
368   }
369
370   if (myShapeToGenerated.IsBound(theInitial) &&
371     myShapeToGenerated(theInitial).Remove(theModified))
372   {
373     Standard_ASSERT_INVOKE_(, myMsgGeneratedAndModified);
374   }
375
376   return Standard_True;
377 }
378
379 //==============================================================================
380 //data : myEmptyList
381 //purpose  :
382 //==============================================================================
383 const TopTools_ListOfShape BRepTools_History::myEmptyList;
384
385 //==============================================================================
386 //function : emptyList
387 //purpose  :
388 //==============================================================================
389 const TopTools_ListOfShape& BRepTools_History::emptyList()
390 {
391   return myEmptyList;
392 }
393
394 //==============================================================================
395 //data : myMsgUnsupportedType
396 //purpose  :
397 //==============================================================================
398 const char* BRepTools_History::myMsgUnsupportedType =
399   "Error: unsupported shape type.";
400
401 //==============================================================================
402 //data : myMsgGeneratedAndRemoved
403 //purpose  :
404 //==============================================================================
405 const char* BRepTools_History::myMsgGeneratedAndRemoved =
406   "Error: a shape is generated and removed simultaneously.";
407
408 //==============================================================================
409 //data : myMsgModifiedAndRemoved
410 //purpose  :
411 //==============================================================================
412 const char* BRepTools_History::myMsgModifiedAndRemoved =
413   "Error: a shape is modified and removed simultaneously.";
414
415 //==============================================================================
416 //data : myMsgGeneratedAndModified
417 //purpose  :
418 //==============================================================================
419 const char* BRepTools_History::myMsgGeneratedAndModified =
420   "Error: a shape is generated and modified "
421     "from the same shape simultaneously.";