0024428: Implementation of LGPL license
[occt.git] / src / BRepFeat / BRepFeat_Form.cxx
1 // Created on: 1996-02-13
2 // Created by: Olga KOULECHOVA
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and / or modify it
9 // under the terms of the GNU Lesser General Public version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <BRepFeat_Form.ixx>
18
19 #include <LocOpe.hxx>
20 #include <LocOpe_Gluer.hxx>
21 #include <LocOpe_FindEdges.hxx>
22 #include <LocOpe_CSIntersector.hxx>
23 #include <LocOpe_SequenceOfCirc.hxx>
24 #include <LocOpe_PntFace.hxx>
25 #include <LocOpe_BuildShape.hxx>
26
27 #include <TopExp_Explorer.hxx>
28 #include <TopOpeBRepBuild_HBuilder.hxx>
29 #include <TopTools_MapOfShape.hxx>
30 #include <TopTools_ListIteratorOfListOfShape.hxx>
31 #include <TopTools_MapIteratorOfMapOfShape.hxx>
32 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
33 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
34 #include <TColgp_SequenceOfPnt.hxx>
35 #include <Standard_NoSuchObject.hxx>
36 #include <Precision.hxx>
37
38 #include <BRep_Tool.hxx>
39 #include <Geom_RectangularTrimmedSurface.hxx>
40 #include <Geom_Plane.hxx>
41 #include <Geom_CylindricalSurface.hxx>
42 #include <Geom_ConicalSurface.hxx>
43
44 #include <TopoDS_Solid.hxx>
45 #include <TopoDS_Compound.hxx>
46 #include <BRepTools_Modifier.hxx>
47 #include <BRepTools_TrsfModification.hxx>
48 #include <BRepFeat.hxx>
49 #include <BRepCheck_Analyzer.hxx>
50 #include <TopoDS.hxx>
51
52 #include <Bnd_Box.hxx>
53 #include <BRepBndLib.hxx>
54 #include <BRepLib.hxx>
55
56 #include <ElCLib.hxx>
57
58 #include <BRepAlgo.hxx>
59 //modified by NIZNHY-PKV Thu Mar 21 17:30:25 2002 f
60 //#include <BRepAlgo_Cut.hxx>
61 //#include <BRepAlgo_Fuse.hxx>
62
63 #include <BRepAlgoAPI_Cut.hxx>
64 #include <BRepAlgoAPI_Fuse.hxx>
65 #include <BRepFeat_Builder.hxx>
66 //modified by NIZNHY-PKV Thu Mar 21 17:30:29 2002 t
67
68 #ifdef DEB
69 extern Standard_Boolean BRepFeat_GettraceFEAT();
70 #endif
71
72 static void Descendants(const TopoDS_Shape&,
73                         BRepFeat_Builder&,
74                         TopTools_MapOfShape&);
75
76 //=======================================================================
77 //function : Perform
78 //purpose  : topological reconstruction of the result
79 //=======================================================================
80   void BRepFeat_Form::GlobalPerform () 
81 {
82
83 #ifdef DEB
84   Standard_Boolean trc = BRepFeat_GettraceFEAT();
85   if (trc) cout << "BRepFeat_Form::GlobalPerform ()" << endl;
86 #endif
87
88   if (!mySbOK || !myGSOK || !mySFOK || !mySUOK || !myGFOK || 
89       !mySkOK || !myPSOK) {
90 #ifdef DEB
91     if (trc) cout << " Fields not initialized in BRepFeat_Form" << endl;
92 #endif
93     myStatusError = BRepFeat_NotInitialized;
94     NotDone();
95     return;
96   }
97
98 //--- Initialisation
99   TopExp_Explorer exp,exp2;
100   Standard_Integer theOpe = 2;
101   TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
102
103   if(myJustFeat && !myFuse) {
104 #ifdef DEB
105     if (trc) cout << " Invalid option : myJustFeat + Cut" << endl;
106 #endif
107     myStatusError = BRepFeat_InvOption;
108     NotDone();
109     return;    
110   }
111   else if(myJustFeat) {
112     theOpe = 2;
113   }
114   else if (!myGluedF.IsEmpty()) {
115     theOpe = 1;
116   }
117   else {}
118   Standard_Boolean ChangeOpe = Standard_False;
119
120   Standard_Boolean FromInShape = Standard_False;
121   Standard_Boolean UntilInShape = Standard_False;
122   
123   if (!mySFrom.IsNull()) {
124     FromInShape = Standard_True;
125     for (exp2.Init(mySFrom,TopAbs_FACE); exp2.More(); exp2.Next()) {
126       const TopoDS_Shape& ffrom = exp2.Current();
127       for (exp.Init(mySbase,TopAbs_FACE); exp.More(); exp.Next()) {
128         if (exp.Current().IsSame(ffrom)) {
129           break;
130         }
131       }
132       if (!exp.More()) {
133         FromInShape = Standard_False;
134 #ifdef DEB
135         if (trc) cout << " From not in Shape" << endl;
136 #endif
137         break;
138       }
139     }
140   }
141
142   if (!mySUntil.IsNull()) {
143     UntilInShape = Standard_True;
144     for (exp2.Init(mySUntil,TopAbs_FACE); exp2.More(); exp2.Next()) {
145       const TopoDS_Shape& funtil = exp2.Current();
146       for (exp.Init(mySbase,TopAbs_FACE); exp.More(); exp.Next()) {
147         if (exp.Current().IsSame(funtil)) {
148           break;
149         }
150       }
151       if (!exp.More()) {
152         UntilInShape = Standard_False;
153 #ifdef DEB
154         if (trc) cout << " Until not in Shape" << endl;
155 #endif
156         break;
157       }
158     }
159   }
160
161   TopTools_ListIteratorOfListOfShape it,it2;
162   Standard_Integer sens = 0;
163
164   TColGeom_SequenceOfCurve scur;
165   Curves(scur);
166
167   Standard_Integer tempo;
168   Standard_Real locmin;
169   Standard_Real locmax;
170   Standard_Real mf, Mf, mu, Mu;
171
172   TopAbs_Orientation Orifuntil = TopAbs_INTERNAL;
173   TopAbs_Orientation Oriffrom = TopAbs_INTERNAL;
174   TopoDS_Face FFrom,FUntil;
175   
176   LocOpe_CSIntersector ASI1;
177   LocOpe_CSIntersector ASI2;
178
179   TopTools_ListOfShape IntList;
180   IntList.Clear();
181
182 //--- 1) by intersection
183
184 // Intersection Tool Shape From
185   if (!mySFrom.IsNull()) {
186     ASI1.Init(mySFrom);
187     ASI1.Perform(scur);
188   }
189
190 // Intersection Tool Shape Until
191   if (!mySUntil.IsNull()) {
192     ASI2.Init(mySUntil);
193     ASI2.Perform(scur);
194   }
195
196   {
197 //  Find sens, locmin, locmax, FFrom, FUntil
198     tempo=0;
199     locmin = RealFirst();
200     locmax = RealLast();
201     for (Standard_Integer jj=1; jj<=scur.Length(); jj++) {
202       if (ASI1.IsDone() && ASI2.IsDone()) {
203         if (ASI1.NbPoints(jj) <= 0) {
204           continue;
205         }
206         mf = ASI1.Point(jj,1).Parameter();
207         Mf = ASI1.Point(jj,ASI1.NbPoints(jj)).Parameter();
208         if (ASI2.NbPoints(jj) <= 0) {
209           continue;
210         }
211         mu = ASI2.Point(jj,1).Parameter();
212         Mu = ASI2.Point(jj,ASI2.NbPoints(jj)).Parameter();
213         if (scur(jj)->IsPeriodic()) {
214           Standard_Real period = scur(jj)->Period();
215           locmin = mf;
216           locmax = ElCLib::InPeriod(Mu,locmin,locmin+period);
217         }
218         else {
219           Standard_Integer ku, kf;
220           if (! (mu > Mf || mf > Mu)) { //overlapping intervals
221             sens = 1;
222             kf = 1;
223             ku = ASI2.NbPoints(jj);
224             locmin = mf;
225             locmax = Max(Mf, Mu);
226           }   
227           else if (mu > Mf) {    
228             if (sens == -1) {
229               myStatusError = BRepFeat_IntervalOverlap;
230               NotDone();
231               return;
232             }
233             sens = 1;
234             kf = 1;
235             ku = ASI2.NbPoints(jj);
236             locmin = mf;
237             locmax = Mu;
238           }
239           else {
240             if (sens == 1) {
241               myStatusError = BRepFeat_IntervalOverlap;
242               NotDone();
243               return;
244             }
245             sens = -1;
246             kf = ASI1.NbPoints(jj);
247             ku = 1;
248             locmin = mu;
249             locmax = Mf;
250           }
251           if (Oriffrom == TopAbs_INTERNAL) {
252             TopAbs_Orientation Oript = ASI1.Point(jj,kf).Orientation();
253             if (Oript == TopAbs_FORWARD || Oript == TopAbs_REVERSED) {
254               if (sens == -1) {
255                 Oript = TopAbs::Reverse(Oript);
256               }
257               Oriffrom = TopAbs::Reverse(Oript);
258               FFrom = ASI1.Point(jj,kf).Face();
259             }
260           }
261           if (Orifuntil == TopAbs_INTERNAL) {
262             TopAbs_Orientation Oript = ASI2.Point(jj,ku).Orientation();
263             if (Oript == TopAbs_FORWARD || Oript == TopAbs_REVERSED) {
264               if (sens == -1) {
265                 Oript = TopAbs::Reverse(Oript);
266               }
267               Orifuntil = Oript;
268               FUntil = ASI2.Point(jj,ku).Face();
269             }
270           }
271         }
272       }
273       else if (ASI2.IsDone()) {
274         if (ASI2.NbPoints(jj) <= 0) 
275           continue;
276
277 // for base case prism on mySUntil -> ambivalent direction
278 //      ->  preferrable direction = 1
279         if(sens != 1) {
280           if (ASI2.Point(jj,1).Parameter()*
281               ASI2.Point(jj,ASI2.NbPoints(jj)).Parameter()<=0) 
282             sens=1;
283           else if (ASI2.Point(jj,1).Parameter()<0.) 
284             sens =-1;
285           else 
286             sens =1;
287         }
288
289         Standard_Integer ku;
290         if (sens == -1) {
291           ku = 1;
292           locmax = -ASI2.Point(jj,ku).Parameter();
293           locmin = 0.;
294         }
295         else {
296           ku = ASI2.NbPoints(jj);
297           locmin = 0;
298           locmax =  ASI2.Point(jj,ku).Parameter();
299         }
300         if (Orifuntil == TopAbs_INTERNAL && sens != 0) {
301           TopAbs_Orientation Oript = ASI2.Point(jj,ku).Orientation();
302           if (Oript == TopAbs_FORWARD || Oript == TopAbs_REVERSED) {
303             if (sens == -1) {
304               Oript = TopAbs::Reverse(Oript);
305             }
306             Orifuntil = Oript;
307             FUntil = ASI2.Point(jj,ku).Face();
308           }
309         }
310       }
311       else { 
312         locmin = 0.;
313         locmax = RealLast();
314         sens = 1;
315         break;
316       }
317     }
318   }
319
320   LocOpe_Gluer theGlue;
321   
322 //--- case of gluing
323
324   if (theOpe == 1) {
325 #ifdef DEB
326     if (trc) cout << " Gluer" << endl;
327 #endif
328     Standard_Boolean Collage = Standard_True;  
329     // cut by FFrom && FUntil
330     TopoDS_Shape Comp;
331     BRep_Builder B;
332     B.MakeCompound(TopoDS::Compound(Comp));
333     if (!mySFrom.IsNull()) {
334       TopoDS_Solid S = BRepFeat::Tool(mySFrom,FFrom,Oriffrom);
335       if (!S.IsNull()) {
336         B.Add(Comp,S);
337       }
338     }
339     if (!mySUntil.IsNull()) {
340       TopoDS_Solid S = BRepFeat::Tool(mySUntil,FUntil,Orifuntil);
341       if (!S.IsNull()) {
342         B.Add(Comp,S);
343       }
344     }
345
346     LocOpe_FindEdges theFE;
347     TopTools_DataMapOfShapeListOfShape locmap;
348     TopExp_Explorer expp(Comp, TopAbs_SOLID);
349     if(expp.More() && !Comp.IsNull() && !myGShape.IsNull())  {
350       //modified by NIZNHY-PKV Thu Mar 21 17:15:36 2002 f
351       //BRepAlgo_Cut trP(myGShape,Comp);
352       BRepAlgoAPI_Cut trP(myGShape, Comp);
353       //modified by NIZNHY-PKV Thu Mar 21 17:15:58 2002 t
354       exp.Init(trP.Shape(), TopAbs_SOLID);
355       if (exp.Current().IsNull()) {
356         theOpe = 2;
357         ChangeOpe = Standard_True;
358         Collage = Standard_False;
359       }
360       else {// else X0
361         // Only solids are preserved
362         TopoDS_Shape theGShape;
363         BRep_Builder B;
364         B.MakeCompound(TopoDS::Compound(theGShape));
365         for (; exp.More(); exp.Next()) {
366           B.Add(theGShape,exp.Current());
367         }
368         if (!BRepAlgo::IsValid(theGShape)) {
369           theOpe = 2;
370           ChangeOpe = Standard_True;
371           Collage = Standard_False;
372         }
373         else {// else X1
374           if(!mySFrom.IsNull()) { 
375             TopExp_Explorer ex;
376             ex.Init(mySFrom, TopAbs_FACE);
377             for(; ex.More(); ex.Next()) {
378               const TopoDS_Face& fac = TopoDS::Face(ex.Current());
379               if (!FromInShape) {
380                 TopTools_ListOfShape thelist;
381                 myMap.Bind(fac, thelist);
382               }
383               else {
384                 TopTools_ListOfShape thelist1;
385                 locmap.Bind(fac, thelist1);
386               }
387               if (trP.IsDeleted(fac)) {
388               }
389               else if (!FromInShape) {
390                 myMap(fac) = trP.Modified(fac);
391                 if (myMap(fac).IsEmpty()) myMap(fac).Append(fac);
392               }
393               else {
394                 locmap(fac) =trP.Modified(fac) ;
395                 if (locmap(fac).IsEmpty()) locmap(fac).Append(fac);
396               }
397             }
398           }// if(!mySFrom.IsNull()) 
399           //
400           if(!mySUntil.IsNull()) { 
401             TopExp_Explorer ex;
402             ex.Init(mySUntil, TopAbs_FACE);
403             for(; ex.More(); ex.Next()) {
404               const TopoDS_Face& fac = TopoDS::Face(ex.Current());
405               if (!UntilInShape) {                
406                 TopTools_ListOfShape thelist2;
407                 myMap.Bind(fac,thelist2);
408               }
409               else {
410                 TopTools_ListOfShape thelist3;
411                 locmap.Bind(fac,thelist3);
412               }
413               if (trP.IsDeleted(fac)) {
414               }
415               else if (!UntilInShape) {
416                 myMap(fac) = trP.Modified(fac);
417                 if (myMap(fac).IsEmpty()) myMap(fac).Append(fac);
418               }
419               else {
420                 locmap(fac) = trP.Modified(fac);
421                 if (locmap(fac).IsEmpty()) locmap(fac).Append(fac);
422               }
423             }
424           }// if(!mySUntil.IsNull())
425           //
426           //modified by NIZNHY-PKV Thu Mar 21 17:21:49 2002 f
427           //UpdateDescendants(trP.Builder(),theGShape,Standard_True); // skip faces
428           UpdateDescendants(trP,theGShape,Standard_True); // skip faces
429           //modified by NIZNHY-PKV Thu Mar 21 17:22:32 2002 t
430
431           theGlue.Init(mySbase,theGShape);
432           for (itm.Initialize(myGluedF);itm.More();itm.Next()) {
433             const TopoDS_Face& gl = TopoDS::Face(itm.Key());
434             TopTools_ListOfShape ldsc;
435             if (trP.IsDeleted(gl)) {
436             }
437             else {
438               ldsc = trP.Modified(gl);
439               if (ldsc.IsEmpty()) ldsc.Append(gl);
440             }
441             const TopoDS_Face& glface = TopoDS::Face(itm.Value());        
442             for (it.Initialize(ldsc);it.More();it.Next()) {
443               const TopoDS_Face& fac = TopoDS::Face(it.Value());
444               Collage = BRepFeat::IsInside(fac, glface);
445               if(!Collage) {
446                 theOpe = 2;
447                 ChangeOpe = Standard_True;
448                 break;
449               }
450               else {
451                 theGlue.Bind(fac,glface);
452                 theFE.Set(fac,glface);
453                 for (theFE.InitIterator(); theFE.More();theFE.Next()) {
454                   theGlue.Bind(theFE.EdgeFrom(),theFE.EdgeTo());
455                 }
456               }
457             }
458           }
459         }// else X1
460       }// else X0
461     }// if(expp.More() && !Comp.IsNull() && !myGShape.IsNull()) 
462     else {
463       theGlue.Init(mySbase,myGShape);
464       for (itm.Initialize(myGluedF); itm.More();itm.Next()) {
465         const TopoDS_Face& glface = TopoDS::Face(itm.Key());
466         const TopoDS_Face& fac = TopoDS::Face(myGluedF(glface));
467         for (exp.Init(myGShape,TopAbs_FACE); exp.More(); exp.Next()) {
468           if (exp.Current().IsSame(glface)) {
469             break;
470           }
471         }
472         if (exp.More()) {
473           Collage = BRepFeat::IsInside(glface, fac);
474           if(!Collage) {
475             theOpe = 2;
476             ChangeOpe = Standard_True;
477             break;
478           }
479           else {
480             theGlue.Bind(glface, fac);
481             theFE.Set(glface, fac);
482             for (theFE.InitIterator(); theFE.More();theFE.Next()) {
483               theGlue.Bind(theFE.EdgeFrom(),theFE.EdgeTo());
484             }
485           }
486         }
487       }
488     }
489
490     // Add gluing on start and end face if necessary !!!
491     if (FromInShape && Collage) {
492       TopExp_Explorer ex(mySFrom,TopAbs_FACE);
493       for(; ex.More(); ex.Next()) {
494         const TopoDS_Face& fac2 = TopoDS::Face(ex.Current());
495 //        for (it.Initialize(myMap(fac2)); it.More(); it.Next()) {
496         for (it.Initialize(locmap(fac2)); it.More(); it.Next()) {
497           const TopoDS_Face& fac1 = TopoDS::Face(it.Value());
498           theFE.Set(fac1, fac2);
499           theGlue.Bind(fac1, fac2);
500           for (theFE.InitIterator(); theFE.More();theFE.Next()) {
501             theGlue.Bind(theFE.EdgeFrom(),theFE.EdgeTo());
502           }
503         }
504 //        myMap.UnBind(fac2);
505       }
506     }
507
508     if (UntilInShape && Collage) {
509       TopExp_Explorer ex(mySUntil, TopAbs_FACE);
510       for(; ex.More(); ex.Next()) {
511         const TopoDS_Face& fac2 = TopoDS::Face(ex.Current());
512 //        for (it.Initialize(myMap(fac2)); it.More(); it.Next()) {
513         for (it.Initialize(locmap(fac2)); it.More(); it.Next()) {
514           const TopoDS_Face& fac1 = TopoDS::Face(it.Value());
515           theGlue.Bind(fac1, fac2);
516           theFE.Set(fac1, fac2);
517           for (theFE.InitIterator(); theFE.More();theFE.Next()) {
518             theGlue.Bind(theFE.EdgeFrom(),theFE.EdgeTo());
519           }
520         }
521         //myMap.UnBind(fac2); // to avoid fac2 in Map when
522         // UpdateDescendants(theGlue) is called
523       }
524     }
525
526     LocOpe_Operation ope = theGlue.OpeType();
527     if (ope == LocOpe_INVALID ||
528         (myFuse && ope != LocOpe_FUSE) ||
529         (!myFuse && ope != LocOpe_CUT) ||
530         (!Collage)) {
531       theOpe = 2;
532       ChangeOpe = Standard_True;
533     }
534   }
535
536 //--- if the gluing is always applicable
537
538   if (theOpe == 1) {
539 #ifdef DEB
540     if (trc) cout << " still Gluer" << endl;
541 #endif
542     theGlue.Perform();
543     if (theGlue.IsDone()) {
544       TopoDS_Shape shshs = theGlue.ResultingShape();
545 //      if (BRepOffsetAPI::IsTopologicallyValid(shshs)) {
546       if (BRepAlgo::IsValid(shshs)) {
547         UpdateDescendants(theGlue);
548         myNewEdges = theGlue.Edges();
549         myTgtEdges = theGlue.TgtEdges();
550 #ifdef DEB
551           if (trc) cout << " Gluer result" << endl;
552 #endif
553         Done();
554         myShape = theGlue.ResultingShape();
555       }
556       else {
557         theOpe = 2;
558         ChangeOpe = Standard_True;
559       }
560     }
561     else {
562       theOpe = 2;
563       ChangeOpe = Standard_True;
564     }
565   }
566
567
568 //--- case without gluing + Tool with proper dimensions
569
570   if (theOpe == 2 && ChangeOpe && myJustGluer) {
571 #ifdef DEB
572     if (trc) cout << " Gluer failure" << endl;
573 #endif
574     myJustGluer = Standard_False;
575     theOpe = 0;
576 //    Done();
577 //    return;
578   }
579
580 //--- case without gluing
581
582   if (theOpe == 2) {
583 #ifdef DEB
584     if (trc) cout << " No Gluer" << endl;
585 #endif
586     TopoDS_Shape theGShape = myGShape;
587     if (ChangeOpe) {
588 #ifdef DEB
589       if (trc) cout << " Passage to topological operations" << endl;
590 #endif
591     }    
592
593     TopoDS_Shape Comp;
594     BRep_Builder B;
595     B.MakeCompound(TopoDS::Compound(Comp));
596     if (!mySFrom.IsNull() || !mySUntil.IsNull()) {
597       if (!mySFrom.IsNull() && !FromInShape) {
598         TopoDS_Solid S = BRepFeat::Tool(mySFrom,FFrom,Oriffrom);
599         if (!S.IsNull()) {
600           B.Add(Comp,S);
601         }
602       }
603       if (!mySUntil.IsNull() && !UntilInShape) {
604         if (!mySFrom.IsNull()) {
605           if (!mySFrom.IsSame(mySUntil)) {
606             TopoDS_Solid S = BRepFeat::Tool(mySUntil,FUntil,Orifuntil);
607             if (!S.IsNull()) {
608               B.Add(Comp,S);
609             }
610           }
611         }
612         else {
613           TopoDS_Solid S = BRepFeat::Tool(mySUntil,FUntil,Orifuntil);
614           if (!S.IsNull()) {
615             B.Add(Comp,S);
616           }
617         }
618       }
619     }
620
621 // update type of selection
622     if(myPerfSelection == BRepFeat_SelectionU && !UntilInShape) {
623       myPerfSelection = BRepFeat_NoSelection;
624     }
625     else if(myPerfSelection == BRepFeat_SelectionFU &&
626             !FromInShape && !UntilInShape) {
627       myPerfSelection = BRepFeat_NoSelection;
628     }
629     else if(myPerfSelection == BRepFeat_SelectionShU && !UntilInShape) {
630       myPerfSelection = BRepFeat_NoSelection;
631     }
632     else {}
633
634     TopExp_Explorer expp(Comp, TopAbs_SOLID);
635     if(expp.More() && !Comp.IsNull() && !myGShape.IsNull())  {
636       //modified by NIZNHY-PKV Thu Mar 21 17:24:52 2002 f
637       //BRepAlgo_Cut trP(myGShape,Comp);
638       BRepAlgoAPI_Cut trP(myGShape, Comp);
639       //modified by NIZNHY-PKV Thu Mar 21 17:24:56 2002 t
640       // the result is necessarily a compound.
641       exp.Init(trP.Shape(),TopAbs_SOLID);
642       if (!exp.More()) {
643         myStatusError = BRepFeat_EmptyCutResult;
644         NotDone();
645         return;
646       }
647       // Only solids are preserved
648       theGShape.Nullify();
649       BRep_Builder B;
650       B.MakeCompound(TopoDS::Compound(theGShape));
651       for (; exp.More(); exp.Next()) {
652         B.Add(theGShape,exp.Current());
653       }
654       if (!BRepAlgo::IsValid(theGShape)) {
655         myStatusError = BRepFeat_InvShape;
656         NotDone();
657         return;
658       }
659       if(!mySFrom.IsNull()) {
660         if(!FromInShape) {
661           TopExp_Explorer ex(mySFrom, TopAbs_FACE);
662           for(; ex.More(); ex.Next()) {
663             const TopoDS_Face& fac = TopoDS::Face(ex.Current());
664             TopTools_ListOfShape thelist4;
665             myMap.Bind(fac,thelist4);
666             if (trP.IsDeleted(fac)) {
667             }
668             else {
669               myMap(fac) = trP.Modified(fac);
670              if (myMap(fac).IsEmpty())  myMap(fac).Append(fac);
671             }
672           }
673         }
674       }
675       if(!mySUntil.IsNull()) {
676         if(!UntilInShape) {
677           TopExp_Explorer ex(mySUntil, TopAbs_FACE);
678           for(; ex.More(); ex.Next()) {
679             const TopoDS_Face& fac = TopoDS::Face(ex.Current());
680             TopTools_ListOfShape thelist5;
681             myMap.Bind(fac,thelist5);
682             if (trP.IsDeleted(fac)) {
683             }
684             else {
685               myMap(fac) = trP.Modified(fac);
686               if (myMap.IsEmpty()) myMap(fac).Append(fac);
687             }
688           }
689         }
690       }
691       //modified by NIZNHY-PKV Thu Mar 21 17:27:23 2002 f
692       //UpdateDescendants(trP.Builder(),theGShape,Standard_True); 
693       UpdateDescendants(trP,theGShape,Standard_True); 
694       //modified by NIZNHY-PKV Thu Mar 21 17:27:31 2002 t
695     }//if(expp.More() && !Comp.IsNull() && !myGShape.IsNull())  {
696     //
697
698 //--- generation of "just feature" for assembly = Parts of tool
699     Standard_Boolean bFlag = (myPerfSelection == BRepFeat_NoSelection) ? 0 : 1;
700     BRepFeat_Builder theBuilder;
701     theBuilder.Init(mySbase, theGShape);
702     theBuilder.SetOperation(myFuse, bFlag);
703     theBuilder.Perform();
704     //
705     TopTools_ListOfShape lshape;
706     theBuilder.PartsOfTool(lshape);
707     //
708     Standard_Real pbmin = RealLast(), pbmax = RealFirst();
709     Standard_Real prmin = RealLast()  - 2*Precision::Confusion();
710     Standard_Real prmax = RealFirst() + 2*Precision::Confusion();
711     Standard_Boolean flag1 = Standard_False;
712     Handle(Geom_Curve) C;
713
714 //--- Selection of pieces of tool to be preserved
715     if(!lshape.IsEmpty() && myPerfSelection != BRepFeat_NoSelection) {
716 //      Find ParametricMinMax depending on the constraints of Shape From and Until
717 //   -> prmin, prmax, pbmin and pbmax
718       C = BarycCurve();
719       if (C.IsNull()) {
720         myStatusError = BRepFeat_EmptyBaryCurve; 
721         NotDone();
722         return;
723       }
724
725       if(myPerfSelection == BRepFeat_SelectionSh) {
726         BRepFeat::ParametricMinMax(mySbase,C, 
727                                    prmin, prmax, pbmin, pbmax, flag1);
728       }
729       else if(myPerfSelection == BRepFeat_SelectionFU) {
730         Standard_Real prmin1, prmax1, prmin2, prmax2;
731         Standard_Real prbmin1, prbmax1, prbmin2, prbmax2;
732       
733         BRepFeat::ParametricMinMax(mySFrom,C, 
734                                    prmin1, prmax1, prbmin1, prbmax1, flag1);
735         BRepFeat::ParametricMinMax(mySUntil,C, 
736                                    prmin2, prmax2, prbmin2, prbmax2, flag1);
737
738 // case of revolutions
739         if (C->IsPeriodic()) {
740           Standard_Real period = C->Period();
741           prmax = prmax2;
742           if (flag1) {
743             prmin = ElCLib::InPeriod(prmin1,prmax-period,prmax);
744           }
745           else {
746             prmin = Min(prmin1, prmin2);
747           }
748           pbmax = prbmax2;
749           pbmin = ElCLib::InPeriod(prbmin1,pbmax-period,pbmax);
750         }
751         else {
752           prmin = Min(prmin1, prmin2);
753           prmax = Max(prmax1, prmax2);
754           pbmin = Min(prbmin1, prbmin2);
755           pbmax = Max(prbmax1, prbmax2);
756         }
757       }
758       else if(myPerfSelection == BRepFeat_SelectionShU) {
759         Standard_Real prmin1, prmax1, prmin2, prmax2;
760         Standard_Real prbmin1, prbmax1, prbmin2, prbmax2;
761         
762         if(!myJustFeat && sens == 0) sens =1;
763         if (sens == 0) {
764           myStatusError = BRepFeat_IncDirection;
765           NotDone();
766           return;
767         }
768         
769         BRepFeat::ParametricMinMax(mySUntil,C, 
770                                    prmin1, prmax1, prbmin1, prbmax1, flag1);
771
772         BRepFeat::ParametricMinMax(mySbase,C, 
773                                    prmin2, prmax2, prbmin2, prbmax2, flag1);
774         if (sens == 1) {
775           prmin = prmin2;
776           prmax = prmax1;
777           pbmin = prbmin2;
778           pbmax = prbmax1;
779         }
780         else if (sens == -1) {
781           prmin = prmin1;
782           prmax = prmax2;
783           pbmin = prbmin1;
784           pbmax = prbmax2;
785         }
786       }
787       else if (myPerfSelection == BRepFeat_SelectionU) {
788         Standard_Real prmin1, prmax1, prbmin1, prbmax1;
789               if (sens == 0) {
790           myStatusError = BRepFeat_IncDirection;
791           NotDone();
792           return;
793         }
794         
795         // Find parts of the tool containing descendants of Shape Until
796         BRepFeat::ParametricMinMax(mySUntil,C, 
797                                    prmin1, prmax1, prbmin1, prbmax1, flag1);
798         if (sens == 1) {
799           prmin = RealFirst();
800           prmax = prmax1;
801           pbmin = RealFirst();
802           pbmax = prbmax1;
803         }
804         else if(sens == -1) {
805           prmin = prmin1;
806           prmax = RealLast();
807           pbmin = prbmin1;
808           pbmax = RealLast();
809         }
810       }
811
812
813 // Finer choice of ParametricMinMax in case when the tool 
814 // intersects Shapes From and Until
815 //       case of several intersections (keep PartsOfTool according to the selection)  
816 //       position of the face of intersection in PartsOfTool (before or after)
817       Standard_Real delta = Precision::Confusion();
818
819       if (myPerfSelection != BRepFeat_NoSelection) {
820 // modif of the test for cts21181 : (prbmax2 and prnmin2) -> (prbmin1 and prbmax1)
821 // correction take into account flag2 for pro15323 and flag3 for pro16060
822         if (!mySUntil.IsNull()) {
823           TopTools_MapOfShape mapFuntil;
824           Descendants(mySUntil,theBuilder,mapFuntil);
825           if (!mapFuntil.IsEmpty()) {
826             for (it.Initialize(lshape); it.More(); it.Next()) {
827               TopExp_Explorer expf;
828               for (expf.Init(it.Value(),TopAbs_FACE); 
829                    expf.More(); expf.Next()) {
830                 if (mapFuntil.Contains(expf.Current())) {
831                   Standard_Boolean flag2,flag3;
832                   Standard_Real prmin1, prmax1, prbmin1, prbmax1;
833                   Standard_Real prmin2, prmax2, prbmin2, prbmax2;
834                   BRepFeat::ParametricMinMax(expf.Current(),C, prmin1, prmax1,
835                                              prbmin1, prbmax1,flag3);
836                   BRepFeat::ParametricMinMax(it.Value(),C, prmin2, prmax2,
837                                              prbmin2, prbmax2,flag2);
838                   if (sens == 1) {
839                     Standard_Boolean testOK = !flag2;
840                     if (flag2) {
841                       testOK = !flag1;
842                       if (flag1 && prmax2 > prmin + delta) {
843                         testOK = !flag3;
844                         if (flag3 && prmax1 == prmax2) {
845                           testOK = Standard_True;
846                         }
847                       }
848                     }
849                     if (prbmin1 < pbmax && testOK) {
850                       if (flag2) {
851                         flag1 = flag2;
852                         prmax  = prmax2;
853                       }
854                       pbmax = prbmin1;
855                     }
856                   }
857                   else if (sens == -1){ 
858                     Standard_Boolean testOK = !flag2;
859                     if (flag2) {
860                       testOK = !flag1;
861                       if (flag1 && prmin2 < prmax - delta) {
862                         testOK = !flag3;
863                         if (flag3 && prmin1 == prmin2) {
864                           testOK = Standard_True;
865                         }
866                       }
867                     }
868                     if (prbmax1 > pbmin && testOK) {
869                       if (flag2) {
870                         flag1 = flag2;
871                         prmin  = prmin2;
872                       }
873                       pbmin = prbmax1;
874                     }
875                   }
876                   break;
877                 }                
878               }
879             }
880             it.Initialize(lshape);
881           }
882         }
883         if (!mySFrom.IsNull()) {
884           TopTools_MapOfShape mapFfrom;
885           Descendants(mySFrom, theBuilder, mapFfrom);
886           if (!mapFfrom.IsEmpty()) {
887             for (it.Initialize(lshape); it.More(); it.Next()) {
888               TopExp_Explorer expf;
889               for (expf.Init(it.Value(),TopAbs_FACE); 
890                    expf.More(); expf.Next()) {
891                 if (mapFfrom.Contains(expf.Current())) {
892                   Standard_Boolean flag2,flag3;
893                   Standard_Real prmin1, prmax1, prbmin1, prbmax1;
894                   Standard_Real prmin2, prmax2, prbmin2, prbmax2;
895                   BRepFeat::ParametricMinMax(expf.Current(),C, prmin1, prmax1,
896                                              prbmin1, prbmax1,flag3);
897                   BRepFeat::ParametricMinMax(it.Value(),C, prmin2, prmax2,
898                                              prbmin2, prbmax2,flag2);
899                   if (sens == 1) {
900                     Standard_Boolean testOK = !flag2;
901                     if (flag2) {
902                       testOK = !flag1;
903                       if (flag1 && prmin2 < prmax - delta) {
904                         testOK = !flag3;
905                         if (flag3 && prmin1 == prmin2) {
906                           testOK = Standard_True;
907                         }
908                       }
909                     }
910                     if (prbmax1 > pbmin && testOK) {
911                       if (flag2) {
912                         flag1 = flag2;
913                         prmin  = prmin2;
914                       }
915                       pbmin = prbmax1;
916                     }
917                   }
918                   else if (sens == -1){
919                     Standard_Boolean testOK = !flag2;
920                     if (flag2) {
921                       testOK = !flag1;
922                       if (flag1 && prmax2 > prmin + delta) {
923                         testOK = !flag3;
924                         if (flag3 && prmax1 == prmax2) {
925                           testOK = Standard_True;
926                         }
927                       }
928                     }
929                     if (prbmin1 < pbmax && testOK) {
930                       if (flag2) {
931                         flag1 = flag2;
932                         prmax  = prmax2;
933                       }
934                       pbmax = prbmin1;
935                     }
936                   }
937                   break;
938                 }                
939               }
940             }
941             it.Initialize(lshape);
942           }
943         }
944       }
945
946
947 // Parse PartsOfTool to preserve or not depending on ParametricMinMax
948       if (!myJustFeat) {
949         Standard_Boolean KeepParts = Standard_False;
950         Standard_Real prmin1, prmax1, prbmin1, prbmax1;
951         Standard_Real min, max, pmin, pmax;
952         Standard_Boolean flag2;
953         for (it.Initialize(lshape); it.More(); it.Next()) {
954           if (C->IsPeriodic()) {
955             Standard_Real period = C->Period();
956             Standard_Real pr, prb;
957             BRepFeat::ParametricMinMax(it.Value(),C, pr, prmax1,
958                                        prb, prbmax1,flag2,Standard_True);
959             if (flag2) {
960               prmin1 = ElCLib::InPeriod(pr,prmax1-period,prmax1);
961             }
962             else {
963               prmin1 = pr;
964             }
965             prbmin1 = ElCLib::InPeriod(prb,prbmax1-period,prbmax1);
966           }
967           else {
968             BRepFeat::ParametricMinMax(it.Value(),C, 
969                                        prmin1, prmax1, prbmin1, prbmax1,flag2);
970           }
971           if(flag2 == Standard_False || flag1 == Standard_False) {
972             pmin = pbmin;
973             pmax = pbmax;
974             min = prbmin1;
975             max = prbmax1;
976           }
977           else {
978             pmin = prmin;
979             pmax = prmax;
980             min = prmin1;
981             max = prmax1;
982           }
983           if (!((min > pmax - delta) || 
984                 (max < pmin + delta))) {
985             KeepParts = Standard_True;
986             const TopoDS_Shape& S = it.Value();
987             theBuilder.KeepPart(S);
988           }
989         }
990
991 // Case when no part of the tool is preserved
992         if (!KeepParts) {
993 #ifdef DEB
994           if (trc) cout << " No parts of tool kept" << endl;
995 #endif
996           myStatusError = BRepFeat_NoParts;
997           NotDone();
998           return;
999         }
1000       }
1001       else {
1002 // case JustFeature -> all PartsOfTool are preserved
1003         Standard_Real prmin1, prmax1, prbmin1, prbmax1;
1004         Standard_Real min, max, pmin, pmax;
1005         Standard_Boolean flag2;
1006         TopoDS_Shape Compo;
1007         BRep_Builder B;
1008         B.MakeCompound(TopoDS::Compound(Compo));
1009         for (it.Initialize(lshape); it.More(); it.Next()) {
1010           BRepFeat::ParametricMinMax(it.Value(),C, 
1011                                      prmin1, prmax1, prbmin1, prbmax1,flag2);
1012           if(flag2 == Standard_False || flag1 == Standard_False) {
1013             pmin = pbmin;
1014             pmax = pbmax;
1015             min = prbmin1;
1016             max = prbmax1;
1017           }
1018           else { 
1019             pmin = prmin;
1020             pmax = prmax;
1021             min = prmin1;
1022             max = prmax1;
1023           }
1024           if ((min < pmax - delta) && 
1025               (max > pmin + delta)){
1026             if (!it.Value().IsNull()) {
1027               B.Add(Compo,it.Value());
1028             }
1029           }
1030         }
1031         myShape = Compo;
1032       }
1033     }
1034  
1035 //--- Generation of result myShape
1036
1037     if (!myJustFeat) {
1038       // removal of edges of section that have no common vertices
1039       // with PartsOfTool preserved
1040       //modified by NIZHNY-EMV Thu May 10 15:56:24 2012
1041       if (bFlag) { 
1042         theBuilder.PerformResult();
1043         myShape = theBuilder.Shape();
1044       } else {
1045         myShape = theBuilder.Shape();
1046       }
1047       //modified by NIZHNY-EMV Thu May 10 15:56:26 2012
1048       Done();
1049     }
1050     else {
1051       // all is already done
1052       Done();
1053     }
1054   }
1055
1056   myStatusError = BRepFeat_OK;
1057 }
1058
1059 //=======================================================================
1060 //function : IsDeleted
1061 //purpose  : 
1062 //=======================================================================
1063
1064 Standard_Boolean BRepFeat_Form::IsDeleted(const TopoDS_Shape& F)
1065 {
1066   return (myMap(F).IsEmpty());
1067 }
1068
1069 //=======================================================================
1070 //function : Modified
1071 //purpose  : 
1072 //=======================================================================
1073
1074 const TopTools_ListOfShape& BRepFeat_Form::Modified
1075    (const TopoDS_Shape& F)
1076 {
1077   if (myMap.IsBound(F)) {
1078     static TopTools_ListOfShape list;
1079     list.Clear(); // For the second passage DPF
1080     TopTools_ListIteratorOfListOfShape ite(myMap(F));
1081     for(; ite.More(); ite.Next()) {
1082       const TopoDS_Shape& sh = ite.Value();
1083       if(!sh.IsSame(F)) 
1084         list.Append(sh);
1085     }
1086     return list;
1087   }
1088   return myGenerated; // empty list
1089 }
1090
1091 //=======================================================================
1092 //function : Generated
1093 //purpose  : 
1094 //=======================================================================
1095
1096 const TopTools_ListOfShape& BRepFeat_Form::Generated
1097    (const TopoDS_Shape& S)
1098 {
1099   if (myMap.IsBound(S) && 
1100       S.ShapeType() != TopAbs_FACE) { // check if filter on face or not
1101     static TopTools_ListOfShape list;
1102     list.Clear(); // For the second passage DPF
1103     TopTools_ListIteratorOfListOfShape ite(myMap(S));
1104     for(; ite.More(); ite.Next()) {
1105       const TopoDS_Shape& sh = ite.Value();
1106       if(!sh.IsSame(S)) 
1107         list.Append(sh);
1108     }
1109     return list;
1110   }
1111   else return myGenerated;
1112 }
1113
1114
1115
1116 //=======================================================================
1117 //function : UpdateDescendants
1118 //purpose  : 
1119 //=======================================================================
1120
1121 void BRepFeat_Form::UpdateDescendants(const LocOpe_Gluer& G)
1122 {
1123   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm;
1124   TopTools_ListIteratorOfListOfShape it,it2;
1125   TopTools_MapIteratorOfMapOfShape itm;
1126
1127   for (itdm.Initialize(myMap);itdm.More();itdm.Next()) {
1128     const TopoDS_Shape& orig = itdm.Key();
1129     TopTools_MapOfShape newdsc;
1130     for (it.Initialize(itdm.Value());it.More();it.Next()) {
1131       const TopoDS_Face& fdsc = TopoDS::Face(it.Value()); 
1132       for (it2.Initialize(G.DescendantFaces(fdsc));
1133            it2.More();it2.Next()) {
1134         newdsc.Add(it2.Value());
1135       }
1136     }
1137     myMap.ChangeFind(orig).Clear();
1138     for (itm.Initialize(newdsc);itm.More();itm.Next()) {
1139       myMap.ChangeFind(orig).Append(itm.Key());
1140     }
1141   }
1142 }
1143
1144
1145
1146
1147
1148 //=======================================================================
1149 //function : FirstShape
1150 //purpose  : 
1151 //=======================================================================
1152
1153 const TopTools_ListOfShape& BRepFeat_Form::FirstShape() const
1154 {
1155   if (!myFShape.IsNull()) {
1156     return myMap(myFShape);
1157   }
1158   return myGenerated; // empty list
1159 }
1160
1161
1162 //=======================================================================
1163 //function : LastShape
1164 //purpose  : 
1165 //=======================================================================
1166
1167 const TopTools_ListOfShape& BRepFeat_Form::LastShape() const
1168 {
1169   if (!myLShape.IsNull()) {
1170     return myMap(myLShape);
1171   }
1172   return myGenerated; // empty list
1173 }
1174
1175
1176 //=======================================================================
1177 //function : NewEdges
1178 //purpose  : 
1179 //=======================================================================
1180
1181 const TopTools_ListOfShape& BRepFeat_Form::NewEdges() const
1182 {
1183   return myNewEdges;
1184 }
1185
1186
1187 //=======================================================================
1188 //function : NewEdges
1189 //purpose  : 
1190 //=======================================================================
1191
1192 const TopTools_ListOfShape& BRepFeat_Form::TgtEdges() const
1193 {
1194   return myTgtEdges;
1195 }
1196
1197
1198 //=======================================================================
1199 //function : TransformSUntil
1200 //purpose  : Limitation of the shape until the case of infinite faces
1201 //=======================================================================
1202
1203 Standard_Boolean BRepFeat_Form::TransformShapeFU(const Standard_Integer flag)
1204 {
1205 #ifdef DEB
1206   Standard_Boolean trc = BRepFeat_GettraceFEAT();
1207 #endif
1208   Standard_Boolean Trf = Standard_False;
1209
1210   TopoDS_Shape shapefu;
1211   if(flag == 0)
1212     shapefu = mySFrom;
1213   else if(flag == 1)
1214     shapefu = mySUntil;
1215   else 
1216     return Trf;
1217
1218   TopExp_Explorer exp(shapefu, TopAbs_FACE);
1219   if (!exp.More()) { // no faces... It is necessary to return an error
1220 #ifdef DEB
1221     if (trc) cout << " BRepFeat_Form::TransformShapeFU : invalid Shape" << endl;
1222 #endif
1223     return Trf;
1224   }
1225
1226   exp.Next();
1227   if (!exp.More()) { // the only face. Is it infinite?
1228     exp.ReInit();
1229     TopoDS_Face fac = TopoDS::Face(exp.Current());
1230
1231     Handle(Geom_Surface) S = BRep_Tool::Surface(fac);
1232     Handle(Standard_Type) styp = S->DynamicType();
1233     if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1234       S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
1235       styp =  S->DynamicType();
1236     }
1237
1238     if (styp == STANDARD_TYPE(Geom_Plane) ||
1239         styp == STANDARD_TYPE(Geom_CylindricalSurface) ||
1240         styp == STANDARD_TYPE(Geom_ConicalSurface)) {
1241       TopExp_Explorer exp1(fac, TopAbs_WIRE);
1242       if (!exp1.More()) {
1243         Trf = Standard_True;
1244       }
1245       else {
1246         Trf = BRep_Tool::NaturalRestriction(fac);
1247       }
1248
1249     }
1250     if (Trf) {
1251       BRepFeat::FaceUntil(mySbase, fac);
1252     }
1253
1254     if(flag == 0) {
1255       TopTools_ListOfShape thelist6;
1256       myMap.Bind(mySFrom,thelist6);
1257       myMap(mySFrom).Append(fac);
1258       mySFrom = fac;
1259     }
1260     else if(flag == 1) {
1261       TopTools_ListOfShape thelist7;
1262       myMap.Bind(mySUntil,thelist7);
1263       myMap(mySUntil).Append(fac);
1264       mySUntil = fac;
1265     }
1266     else {
1267     }
1268   }
1269   else {
1270     for (exp.ReInit(); exp.More(); exp.Next()) {
1271       const TopoDS_Shape& fac = exp.Current();
1272       TopTools_ListOfShape thelist8;
1273       myMap.Bind(fac,thelist8);
1274       myMap(fac).Append(fac);
1275     }
1276   }
1277 #ifdef DEB
1278   if (trc) {
1279     if (Trf && (flag == 0)) cout << " TransformShapeFU From" << endl;
1280     if (Trf && (flag == 1)) cout << " TransformShapeFU Until" << endl;
1281   }
1282 #endif
1283   return Trf;
1284 }
1285
1286
1287 //=======================================================================
1288 //function : CurrentStatusError
1289 //purpose  : 
1290 //=======================================================================
1291
1292 BRepFeat_StatusError BRepFeat_Form::CurrentStatusError() const
1293 {
1294   return myStatusError;
1295 }
1296
1297 //=======================================================================
1298 //function : Descendants
1299 //purpose  : 
1300 //=======================================================================
1301
1302 static void Descendants(const TopoDS_Shape& S,
1303                         BRepFeat_Builder& theFB,
1304                         TopTools_MapOfShape& mapF)
1305 {
1306   mapF.Clear();
1307   TopTools_ListIteratorOfListOfShape it;
1308   TopExp_Explorer exp;
1309   for (exp.Init(S,TopAbs_FACE); exp.More(); exp.Next()) {
1310    
1311     const TopoDS_Face& fdsc = TopoDS::Face(exp.Current());
1312     const TopTools_ListOfShape& aLM=theFB.Modified(fdsc);
1313     it.Initialize(aLM);
1314     for (; it.More(); it.Next()) {
1315       mapF.Add(it.Value());
1316     }
1317     
1318   }
1319 }
1320
1321 //=======================================================================
1322 //function : UpdateDescendants
1323 //purpose  : 
1324 //=======================================================================
1325   void BRepFeat_Form::UpdateDescendants(const Handle(TopOpeBRepBuild_HBuilder)& B,
1326                                         const TopoDS_Shape& S,
1327                                         const Standard_Boolean SkipFace)
1328 {
1329   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm;
1330   TopTools_ListIteratorOfListOfShape it,it2;
1331   TopTools_MapIteratorOfMapOfShape itm;
1332   TopExp_Explorer exp;
1333
1334   for (itdm.Initialize(myMap);itdm.More();itdm.Next()) {
1335     const TopoDS_Shape& orig = itdm.Key();
1336     if (SkipFace && orig.ShapeType() == TopAbs_FACE) {
1337       continue;
1338     }
1339     TopTools_MapOfShape newdsc;
1340
1341     if (itdm.Value().IsEmpty()) {myMap.ChangeFind(orig).Append(orig);}
1342
1343     for (it.Initialize(itdm.Value());it.More();it.Next()) {
1344       const TopoDS_Shape& sh = it.Value();
1345       if(sh.ShapeType() != TopAbs_FACE) continue;
1346       const TopoDS_Face& fdsc = TopoDS::Face(it.Value()); 
1347       for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1348         if (exp.Current().IsSame(fdsc)) { // preserved
1349           newdsc.Add(fdsc);
1350           break;
1351         }
1352       }
1353       if (!exp.More()) {
1354         if (B->IsSplit(fdsc, TopAbs_OUT)) {
1355           for (it2.Initialize(B->Splits(fdsc,TopAbs_OUT));
1356                it2.More();it2.Next()) {
1357             newdsc.Add(it2.Value());
1358           }
1359         }
1360         if (B->IsSplit(fdsc, TopAbs_IN)) {
1361           for (it2.Initialize(B->Splits(fdsc,TopAbs_IN));
1362                it2.More();it2.Next()) {
1363             newdsc.Add(it2.Value());
1364           }
1365         }
1366         if (B->IsSplit(fdsc, TopAbs_ON)) {
1367           for (it2.Initialize(B->Splits(fdsc,TopAbs_ON));
1368                it2.More();it2.Next()) {
1369             newdsc.Add(it2.Value());
1370           }
1371         }
1372         if (B->IsMerged(fdsc, TopAbs_OUT)) {
1373           for (it2.Initialize(B->Merged(fdsc,TopAbs_OUT));
1374                it2.More();it2.Next()) {
1375             newdsc.Add(it2.Value());
1376           }
1377         }
1378         if (B->IsMerged(fdsc, TopAbs_IN)) {
1379           for (it2.Initialize(B->Merged(fdsc,TopAbs_IN));
1380                it2.More();it2.Next()) {
1381             newdsc.Add(it2.Value());
1382           }
1383         }
1384         if (B->IsMerged(fdsc, TopAbs_ON)) {
1385           for (it2.Initialize(B->Merged(fdsc,TopAbs_ON));
1386                it2.More();it2.Next()) {
1387             newdsc.Add(it2.Value());
1388           }
1389         }
1390       }
1391     }
1392     myMap.ChangeFind(orig).Clear();
1393     for (itm.Initialize(newdsc); itm.More(); itm.Next()) {
1394        // check the appartenance to the shape...
1395       for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1396         if (exp.Current().IsSame(itm.Key())) {
1397 //          const TopoDS_Shape& sh = itm.Key();
1398           myMap.ChangeFind(orig).Append(itm.Key());
1399           break;
1400         }
1401       }
1402     }
1403   }
1404 }
1405 //modified by NIZNHY-PKV Thu Mar 21 18:43:18 2002 f
1406 //=======================================================================
1407 //function : UpdateDescendants
1408 //purpose  : 
1409 //=======================================================================
1410   void BRepFeat_Form::UpdateDescendants(const BRepAlgoAPI_BooleanOperation& aBOP,
1411                                         const TopoDS_Shape& S,
1412                                         const Standard_Boolean SkipFace)
1413 {
1414   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm;
1415   TopTools_ListIteratorOfListOfShape it,it2;
1416   TopTools_MapIteratorOfMapOfShape itm;
1417   TopExp_Explorer exp;
1418
1419   for (itdm.Initialize(myMap);itdm.More();itdm.Next()) {
1420     const TopoDS_Shape& orig = itdm.Key();
1421     if (SkipFace && orig.ShapeType() == TopAbs_FACE) {
1422       continue;
1423     }
1424     TopTools_MapOfShape newdsc;
1425
1426     if (itdm.Value().IsEmpty()) {myMap.ChangeFind(orig).Append(orig);}
1427
1428     for (it.Initialize(itdm.Value());it.More();it.Next()) {
1429       const TopoDS_Shape& sh = it.Value();
1430       if(sh.ShapeType() != TopAbs_FACE) continue;
1431       const TopoDS_Face& fdsc = TopoDS::Face(it.Value()); 
1432       for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1433         if (exp.Current().IsSame(fdsc)) { // preserved
1434           newdsc.Add(fdsc);
1435           break;
1436         }
1437       }
1438       if (!exp.More()) {
1439         BRepAlgoAPI_BooleanOperation* pBOP=(BRepAlgoAPI_BooleanOperation*)&aBOP;
1440         const TopTools_ListOfShape& aLM=pBOP->Modified(fdsc);
1441         it2.Initialize(aLM);
1442         for (; it2.More(); it2.Next()) {
1443           const TopoDS_Shape& aS=it2.Value();
1444           newdsc.Add(aS);
1445         }
1446         
1447       }
1448     }
1449     myMap.ChangeFind(orig).Clear();
1450     for (itm.Initialize(newdsc); itm.More(); itm.Next()) {
1451        // check the appartenance to the shape...
1452       for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1453         if (exp.Current().IsSame(itm.Key())) {
1454 //          const TopoDS_Shape& sh = itm.Key();
1455           myMap.ChangeFind(orig).Append(itm.Key());
1456           break;
1457         }
1458       }
1459     }
1460   }
1461 }
1462 //modified by NIZNHY-PKV Thu Mar 21 18:43:36 2002 t