0028501: Incomplete result of offset operation in mode Complete with Join type inters...
[occt.git] / src / BRepFeat / BRepFeat_MakePrism.cxx
1 // Created on: 1996-02-13
2 // Created by: Jacques GOUSSARD
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 under
9 // the terms of the GNU Lesser General Public License 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
18 #include <Bnd_Box.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAlgoAPI_Cut.hxx>
21 #include <BRepAlgoAPI_Fuse.hxx>
22 #include <BRepBndLib.hxx>
23 #include <BRepBuilderAPI.hxx>
24 #include <BRepFeat.hxx>
25 #include <BRepFeat_MakePrism.hxx>
26 #include <BRepLib_MakeFace.hxx>
27 #include <BRepPrimAPI_MakeBox.hxx>
28 #include <BRepTools.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom_Line.hxx>
31 #include <Geom_Plane.hxx>
32 #include <Geom_RectangularTrimmedSurface.hxx>
33 #include <Geom_Surface.hxx>
34 #include <gp_Ax1.hxx>
35 #include <gp_Dir.hxx>
36 #include <gp_Pln.hxx>
37 #include <gp_Pnt.hxx>
38 #include <gp_Pnt2d.hxx>
39 #include <gp_Vec.hxx>
40 #include <LocOpe.hxx>
41 #include <LocOpe_CSIntersector.hxx>
42 #include <LocOpe_PntFace.hxx>
43 #include <LocOpe_Prism.hxx>
44 #include <Precision.hxx>
45 #include <Standard_ConstructionError.hxx>
46 #include <TColGeom_SequenceOfCurve.hxx>
47 #include <TColgp_SequenceOfPnt.hxx>
48 #include <TopExp.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopoDS.hxx>
51 #include <TopoDS_Compound.hxx>
52 #include <TopoDS_Edge.hxx>
53 #include <TopoDS_Face.hxx>
54 #include <TopoDS_Shape.hxx>
55 #include <TopoDS_Solid.hxx>
56 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
57 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
58 #include <TopTools_ListIteratorOfListOfShape.hxx>
59 #include <TopTools_ListOfShape.hxx>
60 #include <TopTools_MapOfShape.hxx>
61
62 #ifdef OCCT_DEBUG
63 extern Standard_Boolean BRepFeat_GettraceFEAT();
64 #endif
65
66 static void MajMap(const TopoDS_Shape&, // base
67                    const LocOpe_Prism&,
68                    TopTools_DataMapOfShapeListOfShape&, // myMap
69                    TopoDS_Shape&,  // myFShape
70                    TopoDS_Shape&); // myLShape
71
72 static Standard_Boolean ToFuse(const TopoDS_Face& ,
73                                const TopoDS_Face&);
74
75 static Standard_Real HeightMax(const TopoDS_Shape& theSbase,
76                                const TopoDS_Face& theSkface,
77                                const TopoDS_Shape& theSFrom,
78                                const TopoDS_Shape& theSUntil);
79
80 static Standard_Integer SensOfPrism(const Handle(Geom_Curve) C,
81                                     const TopoDS_Shape& Until);
82
83 static Handle(Geom_Curve) TestCurve(const TopoDS_Shape&,
84                                     const gp_Vec&);
85
86
87 //=======================================================================
88 //function : Init
89 //purpose  : 
90 //=======================================================================
91
92 void BRepFeat_MakePrism::Init(const TopoDS_Shape& Sbase,
93                               const TopoDS_Shape& Pbase,
94                               const TopoDS_Face& Skface,
95                               const gp_Dir& Direc,
96                               const Standard_Integer Mode,
97                               const Standard_Boolean Modify)
98 {
99 #ifdef OCCT_DEBUG
100   Standard_Boolean trc = BRepFeat_GettraceFEAT();
101   if (trc) cout << "BRepFeat_MakePrism::Init" << endl;
102 #endif
103   mySkface = Skface;
104   SketchFaceValid();
105   mySbase  = Sbase;
106   BasisShapeValid();
107   myPbase  = Pbase;
108   mySlface.Clear();
109   myDir    = Direc;
110   if(Mode == 0) {
111     myFuse   = Standard_False;
112     myJustFeat = Standard_False;
113   }
114   else if(Mode == 1) {
115     myFuse   = Standard_True;
116     myJustFeat = Standard_False;
117   }
118   else if(Mode == 2) {
119     myFuse   = Standard_True;
120     myJustFeat = Standard_True;
121   }
122   else {    
123   }
124   myModify = Modify;
125   myJustGluer = Standard_False;
126
127
128   //-------------- ifv
129   //mySkface.Nullify();
130   //-------------- ifv
131
132
133   myShape.Nullify();
134   myNewEdges.Clear();
135   myTgtEdges.Clear();
136   myMap.Clear();
137   myFShape.Nullify();
138   myLShape.Nullify();
139   TopExp_Explorer exp;
140   for (exp.Init(mySbase,TopAbs_FACE);exp.More();exp.Next()) {
141     TopTools_ListOfShape thelist;
142     myMap.Bind(exp.Current(), thelist);
143     myMap(exp.Current()).Append(exp.Current());
144   }
145 #ifdef OCCT_DEBUG
146   if (trc) {
147     if (myJustFeat)  cout << " Just Feature" << endl;
148     if (myFuse)  cout << " Fuse" << endl;
149     if (!myFuse)  cout << " Cut" << endl;
150     if (!myModify) cout << " Modify = 0" << endl;
151   }
152 #endif 
153 }
154
155
156 //=======================================================================
157 //function : Add
158 //purpose  : add elements of sliding (edge on face)
159 //=======================================================================
160
161 void BRepFeat_MakePrism::Add(const TopoDS_Edge& E,
162                              const TopoDS_Face& F)
163 {
164 #ifdef OCCT_DEBUG
165   Standard_Boolean trc = BRepFeat_GettraceFEAT();
166   if (trc) cout << "BRepFeat_MakePrism::Add(Edge,face)" << endl;
167 #endif
168   TopExp_Explorer exp;
169   for (exp.Init(mySbase,TopAbs_FACE);exp.More();exp.Next()) {
170     if (exp.Current().IsSame(F)) {
171       break;
172     }
173   }
174   if (!exp.More()) {
175     throw Standard_ConstructionError();
176   }
177   
178   for (exp.Init(myPbase,TopAbs_EDGE);exp.More();exp.Next()) {
179     if (exp.Current().IsSame(E)) {
180       break;
181     }
182   }
183   if (!exp.More()) {
184     throw Standard_ConstructionError();
185   }
186   
187   if (!mySlface.IsBound(F)) {
188     TopTools_ListOfShape thelist1;
189     mySlface.Bind(F, thelist1);
190   }
191   TopTools_ListIteratorOfListOfShape itl(mySlface(F));
192   for (; itl.More();itl.Next()) {
193     if (itl.Value().IsSame(E)) {
194       break;
195     }
196   }
197   if (!itl.More()) {
198     mySlface(F).Append(E);
199   }
200 }
201
202
203 //=======================================================================
204 //function : Perform
205 //purpose  : construction of prism of length Length and 
206 //           call of reconstruction topo
207 //=======================================================================
208
209 void BRepFeat_MakePrism::Perform(const Standard_Real Length)
210 {
211 #ifdef OCCT_DEBUG
212   Standard_Boolean trc = BRepFeat_GettraceFEAT();
213   if (trc) cout << "BRepFeat_MakePrism::Perform(Length)" << endl;
214 #endif
215   mySFrom.Nullify();
216   ShapeFromValid();
217   mySUntil.Nullify();
218   ShapeUntilValid();
219   myGluedF.Clear();
220   myPerfSelection = BRepFeat_NoSelection;
221   PerfSelectionValid();
222   gp_Vec V(Length*myDir);
223   
224 //construction of prism of height Length
225
226   LocOpe_Prism thePrism(myPbase,V);
227   TopoDS_Shape VraiPrism = thePrism.Shape();
228   
229 // management of descendants
230   MajMap(myPbase,thePrism,myMap,myFShape,myLShape);
231   
232
233   myGShape = VraiPrism;    // the primitive
234   GeneratedShapeValid();
235   
236   TopoDS_Face FFace;
237   
238   Standard_Boolean found = Standard_False;
239
240 // try to detect the faces of gluing 
241 // in case if the top of the prism is tangent to the initial shape
242
243   if(!mySkface.IsNull() || !mySlface.IsEmpty()) {
244     if(myLShape.ShapeType() == TopAbs_WIRE) {
245       TopExp_Explorer ex1(VraiPrism, TopAbs_FACE);
246       for(; ex1.More(); ex1.Next()) {
247         TopExp_Explorer ex2(ex1.Current(), TopAbs_WIRE);
248         for(; ex2.More(); ex2.Next()) {
249           if(ex2.Current().IsSame(myLShape)) {
250             FFace = TopoDS::Face(ex1.Current());
251             found = Standard_True;
252             break;
253           }
254         }
255         if(found) break;
256       }
257     }
258     
259     TopExp_Explorer exp(mySbase, TopAbs_FACE);
260     for(; exp.More(); exp.Next()) {
261       const TopoDS_Face& ff = TopoDS::Face(exp.Current());
262       if(ToFuse(ff, FFace)) {
263         TopTools_DataMapOfShapeListOfShape sl;
264         if(!FFace.IsSame(myPbase) && BRepFeat::IsInside(ff, FFace)) 
265           break;
266       }
267     }
268   }
269
270 // management of faces of gluing given by the user
271
272   GluedFacesValid();
273
274   if(!myGluedF.IsEmpty()) {   // case gluing
275     myJustGluer = Standard_True;
276     thePrism.Curves(myCurves);
277     myBCurve = thePrism.BarycCurve();    
278     GlobalPerform();  // topological reconstruction 
279   }
280
281 // if there is no gluing  -> call of ope topo
282   if(!myJustGluer) {
283     if(myFuse == 1 && !myJustFeat) {
284       BRepAlgoAPI_Fuse f(mySbase, myGShape);
285       myShape = f.Shape();
286       UpdateDescendants(f, myShape, Standard_False);
287       Done();
288     }
289     else if(myFuse == 0) {
290       BRepAlgoAPI_Cut c(mySbase, myGShape);
291       myShape = c.Shape();
292       UpdateDescendants(c, myShape, Standard_False);
293       Done();
294     }
295     else {
296       myShape = myGShape;
297       Done();
298     }
299   }
300 }
301
302
303 //=======================================================================
304 //function : Perform
305 //purpose  : construction of prism oriented at the face Until, sufficiently 
306 //           long; call of topological reconstruction          
307 //=======================================================================
308
309 void BRepFeat_MakePrism::Perform(const TopoDS_Shape& Until)
310 {
311 #ifdef OCCT_DEBUG
312   Standard_Boolean trc = BRepFeat_GettraceFEAT();
313   if (trc) cout << "BRepFeat_MakePrism::Perform(Until)" << endl;
314 #endif
315   if (Until.IsNull()) {
316     throw Standard_ConstructionError();
317   }
318   TopExp_Explorer exp(Until, TopAbs_FACE);
319   if (!exp.More()) {
320     throw Standard_ConstructionError();
321   }
322   myGluedF.Clear();
323   myPerfSelection = BRepFeat_SelectionU;
324   PerfSelectionValid();
325   mySFrom.Nullify();
326   ShapeFromValid();
327   mySUntil = Until;
328   Standard_Boolean Trf = TransformShapeFU(1);  
329   ShapeUntilValid();
330   Handle(Geom_Curve) C = TestCurve(myPbase,myDir);  
331   Standard_Integer sens = SensOfPrism(C, mySUntil);
332   Standard_Real Height = HeightMax(mySbase, mySkface, mySFrom, mySUntil);
333   gp_Vec V(2*sens*Height*myDir);
334
335 // construction of long prism
336   LocOpe_Prism thePrism(myPbase,V);
337   TopoDS_Shape VraiPrism = thePrism.Shape();
338
339 // in case of support of face Until
340   if(!Trf) {    
341     MajMap(myPbase,thePrism,myMap,myFShape,myLShape);    
342     myGShape = VraiPrism;
343     GeneratedShapeValid();
344     GluedFacesValid();
345     thePrism.Curves(myCurves);
346     myBCurve = thePrism.BarycCurve();
347     GlobalPerform();
348   }
349   else {    // until support -> passage to topological operations
350     MajMap(myPbase,thePrism,myMap,myFShape,myLShape);    
351     TColGeom_SequenceOfCurve scur;
352     scur.Clear();    
353     scur.Append(C);
354
355 // direction of the prism depending on Until
356
357     LocOpe_CSIntersector ASI(mySUntil);
358     ASI.Perform(scur);
359     TopAbs_Orientation Or;
360     if (ASI.IsDone() && ASI.NbPoints(1) >=1) {
361       if (myFuse == 1) {
362         Or = ASI.Point(1, 1).Orientation();
363       }
364       else {
365         Or = ASI.Point(1, ASI.NbPoints(1)).Orientation();
366       }
367       if(sens==-1) Or=TopAbs::Reverse(Or);
368       TopoDS_Face FUntil = ASI.Point(1,1).Face();
369       TopoDS_Shape Comp;
370       BRep_Builder B;
371       B.MakeCompound(TopoDS::Compound(Comp));
372       TopoDS_Solid S = BRepFeat::Tool(mySUntil, FUntil, Or);
373       if (!S.IsNull()) B.Add(Comp,S);
374       BRepAlgoAPI_Cut trP(VraiPrism,Comp);
375       UpdateDescendants(trP, trP.Shape(), Standard_False);
376       //
377       TopExp_Explorer ex(trP.Shape(), TopAbs_SOLID);
378       TopoDS_Shape Cutsh = ex.Current();
379       if (myFuse == 1 && !myJustFeat) {
380         BRepAlgoAPI_Fuse f(mySbase, Cutsh);
381         myShape = f.Shape();
382         UpdateDescendants(f, myShape, Standard_False);
383         Done();
384       }
385       else if(myFuse == 0) {
386         BRepAlgoAPI_Cut c(mySbase, Cutsh);
387         myShape = c.Shape();
388         UpdateDescendants(c, myShape, Standard_False);
389         Done();
390       }
391       else {
392         myShape = Cutsh;
393         Done();
394       }
395     }
396   }
397 }
398
399 //=======================================================================
400 //function : Perform
401 //purpose  : construction of a sufficiently long and properly oriented prism
402 //           call of topological reconstruction
403 //=======================================================================
404
405 void BRepFeat_MakePrism::Perform(const TopoDS_Shape& From,
406                                  const TopoDS_Shape& Until)
407 {
408 #ifdef OCCT_DEBUG
409   Standard_Boolean trc = BRepFeat_GettraceFEAT();
410   if (trc) cout << "BRepFeat_MakePrism::Perform(From,Until)" << endl;
411 #endif
412   if (From.IsNull() || Until.IsNull()) {
413     throw Standard_ConstructionError();
414   }
415
416   if (!mySkface.IsNull()) {
417     if (From.IsSame(mySkface)) {
418       myJustGluer = Standard_True;
419       Perform(Until);
420       if (myJustGluer) return;
421     }
422     else if (Until.IsSame(mySkface)) {
423       myJustGluer = Standard_True;
424       Perform(From);
425       if (myJustGluer) return;
426     } 
427   }
428   
429   myGluedF.Clear();
430   myPerfSelection = BRepFeat_SelectionFU;
431   PerfSelectionValid();
432   
433   TopExp_Explorer exp(From, TopAbs_FACE);
434   if (!exp.More()) {
435     throw Standard_ConstructionError();
436   }
437   exp.Init(Until, TopAbs_FACE);
438   if (!exp.More()) {
439     throw Standard_ConstructionError();
440   }
441   mySFrom = From;
442   Standard_Boolean Trff = TransformShapeFU(0);
443   ShapeFromValid();
444   mySUntil = Until;
445   Standard_Boolean Trfu = TransformShapeFU(1);
446   ShapeUntilValid();  
447   if(Trfu != Trff) {
448     NotDone();
449     myStatusError = BRepFeat_IncTypes;
450     return;
451   }
452
453 // length depending on bounding boxes
454
455   Standard_Real Height = HeightMax(mySbase, mySkface, mySFrom, mySUntil);
456   Handle(Geom_Curve) C = TestCurve(myPbase,myDir);  
457   Standard_Integer sens;  // direction of prism
458   Standard_Integer tran;  // transfer of prism
459   if(From.IsSame(Until)) {
460     sens = 1;
461     tran = -1;
462   }
463   else {
464     sens = SensOfPrism(C, mySUntil);
465     tran = sens*SensOfPrism(C, mySFrom);
466   }
467   LocOpe_Prism thePrism;   
468   if(tran < 0) {
469     gp_Vec Vtra(-3*Height*sens/2.*myDir);
470     thePrism.Perform(myPbase,3*sens*Height*myDir,Vtra);
471   }
472   else {
473     thePrism.Perform(myPbase,2*sens*Height*myDir);
474   }
475   TopoDS_Shape VraiPrism = thePrism.Shape();
476   
477   if(!Trff) {
478     MajMap(myPbase,thePrism,myMap,myFShape,myLShape);
479     
480     myGShape = VraiPrism;
481     GeneratedShapeValid();
482     GluedFacesValid();
483     thePrism.Curves(myCurves);
484     myBCurve = thePrism.BarycCurve();
485     GlobalPerform();
486   }
487   else {    // case until support -> topological operation
488     MajMap(myPbase,thePrism,myMap,myFShape,myLShape);    
489     TColGeom_SequenceOfCurve scur;
490     scur.Clear();    
491     scur.Append(C);
492     LocOpe_CSIntersector ASI1(mySUntil);
493     LocOpe_CSIntersector ASI2(mySFrom);
494     ASI1.Perform(scur);
495     ASI2.Perform(scur);
496     TopAbs_Orientation OrU, OrF;
497     TopoDS_Face FFrom, FUntil;
498     Standard_Real ParF, ParU;
499     if (ASI1.IsDone() && ASI1.NbPoints(1) >=1) {
500       if (myFuse == 1) {
501               OrU = ASI1.Point(1,1).Orientation();
502       }
503       else {
504               OrU = ASI1.Point(1,ASI1.NbPoints(1)).Orientation();
505       }
506       if(sens==-1) OrU = TopAbs::Reverse(OrU);
507       FUntil = ASI1.Point(1,1).Face();
508       ParU = ASI1.Point(1,1).Parameter();
509     }
510     else {
511       NotDone();
512       myStatusError = BRepFeat_NoIntersectU;
513       return;
514     }
515     if (ASI2.IsDone() && ASI2.NbPoints(1) >=1) {
516       OrF = ASI2.Point(1,1).Orientation();
517       if(sens==1) OrF = TopAbs::Reverse(OrF);
518       FFrom = ASI2.Point(1,1).Face();
519       ParF = ASI2.Point(1,1).Parameter();
520     }
521     else {
522       NotDone();
523       myStatusError = BRepFeat_NoIntersectF;
524       return;
525     }
526     if(tran > 0 && (Abs(ParU) < Abs(ParF)))
527     {
528       TopAbs_Orientation Or;
529       Or = OrU;
530       OrU = OrF;
531       OrF = Or;
532     }
533     //
534     TopTools_ListOfShape aLTools;
535     TopoDS_Solid S = BRepFeat::Tool(mySUntil, FUntil, OrU);
536     if (!S.IsNull()) {
537       aLTools.Append(S);
538     }
539     else {
540       NotDone();
541       myStatusError = BRepFeat_NullToolU;
542       return;
543     }
544     TopoDS_Solid SS = BRepFeat::Tool(mySFrom, FFrom, OrF);
545     if (!SS.IsNull()) {
546       aLTools.Append(SS);
547     }
548     else {
549       NotDone();
550       myStatusError = BRepFeat_NullToolF;
551       return;
552     }
553     //
554     TopTools_ListOfShape aLObj;
555     aLObj.Append(VraiPrism);
556     //
557     BRepAlgoAPI_Cut trP;
558     trP.SetArguments(aLObj);
559     trP.SetTools(aLTools);
560     trP.Build();
561     UpdateDescendants(trP, trP.Shape(), Standard_False);
562     if(myFuse == 1 && !myJustFeat) {
563       BRepAlgoAPI_Fuse f(mySbase, trP.Shape());
564       myShape = f.Shape();
565       UpdateDescendants(f, myShape, Standard_False);
566       Done();
567     }
568     else if(myFuse == 0) {
569       BRepAlgoAPI_Cut c(mySbase, trP.Shape());
570       myShape = c.Shape();
571       UpdateDescendants(c, myShape, Standard_False);
572       Done();
573     }
574     else {
575       myShape = trP.Shape();
576       Done();
577     }
578   }
579 }
580
581 //=======================================================================
582 //function : PerformUntilEnd
583 //purpose  : construction of a prism and reconstruction
584 //=======================================================================
585
586 void BRepFeat_MakePrism::PerformUntilEnd()
587 {
588 #ifdef OCCT_DEBUG
589   Standard_Boolean trc = BRepFeat_GettraceFEAT();
590   if (trc) cout << "BRepFeat_MakePrism::PerformUntilEnd()" << endl;
591 #endif
592   myPerfSelection = BRepFeat_SelectionSh;
593   PerfSelectionValid();
594   myGluedF.Clear();
595   mySUntil.Nullify();
596   ShapeUntilValid();
597   mySFrom.Nullify();
598   ShapeFromValid();
599   Standard_Real Height = HeightMax(mySbase, mySkface, mySFrom, mySUntil);
600   gp_Vec V(2*Height*myDir);
601   
602   LocOpe_Prism thePrism(myPbase,V);
603   TopoDS_Shape VraiPrism = thePrism.Shape();
604   
605   MajMap(myPbase,thePrism,myMap,myFShape,myLShape);
606   
607   myGShape = VraiPrism;
608   GeneratedShapeValid();
609   GluedFacesValid();
610
611   if(myFuse == 0) {
612     BRepAlgoAPI_Cut c(mySbase, myGShape);
613     if (c.IsDone()) {
614       myShape = c.Shape();
615       UpdateDescendants(c, myShape, Standard_False);
616       Done();
617     }
618   }
619   else {
620     thePrism.Curves(myCurves);
621     myBCurve = thePrism.BarycCurve();
622     GlobalPerform();
623   }
624 }
625
626 //=======================================================================
627 //function : PerformFromEnd
628 //purpose  : 
629 //=======================================================================
630
631 void BRepFeat_MakePrism::PerformFromEnd(const TopoDS_Shape& Until)
632 {
633 #ifdef OCCT_DEBUG
634   Standard_Boolean trc = BRepFeat_GettraceFEAT();
635   if (trc) cout << "BRepFeat_MakePrism::PerformFromEnd(From,Until)" << endl;
636 #endif
637   if (Until.IsNull()) {
638     throw Standard_ConstructionError();
639   }
640   if (!mySkface.IsNull() && Until.IsSame(mySkface)) {
641     myDir.Reverse();
642     PerformUntilEnd();
643     return;
644   }
645   TopExp_Explorer exp;
646   exp.Init(Until, TopAbs_FACE);
647   if (!exp.More()) {
648     throw Standard_ConstructionError();
649   }
650   myPerfSelection = BRepFeat_SelectionShU;
651   PerfSelectionValid();
652   mySFrom.Nullify();
653   ShapeFromValid();
654   mySUntil = Until;
655   Standard_Boolean Trf = TransformShapeFU(1);
656   ShapeUntilValid();
657   Handle(Geom_Curve) C = TestCurve(myPbase,myDir);  
658   Standard_Integer sens = SensOfPrism(C, mySUntil);
659   Standard_Real Height = HeightMax(mySbase, mySkface, mySFrom, mySUntil);
660   gp_Vec Vtra(-3*Height*sens/2.*myDir);
661   gp_Vec Vect(3*sens*Height*myDir);
662   LocOpe_Prism thePrism(myPbase,Vect,Vtra);
663   TopoDS_Shape VraiPrism = thePrism.Shape();
664   
665   if(!Trf) {  // case face until 
666     MajMap(myPbase,thePrism,myMap,myFShape,myLShape);
667     myGShape = VraiPrism;
668     GeneratedShapeValid();
669     myGluedF.Clear();
670     GluedFacesValid();
671     thePrism.Curves(myCurves);
672     myBCurve = thePrism.BarycCurve();
673     GlobalPerform();
674   }
675   else {   // case support
676     MajMap(myPbase,thePrism,myMap,myFShape,myLShape);    
677     TColGeom_SequenceOfCurve scur;
678     scur.Clear();    
679     scur.Append(C);
680     LocOpe_CSIntersector ASI1(mySUntil);
681     LocOpe_CSIntersector ASI2(mySbase);
682     ASI1.Perform(scur);
683     ASI2.Perform(scur);
684     TopAbs_Orientation OrU = TopAbs_FORWARD, OrF = TopAbs_FORWARD;
685     TopoDS_Face FUntil, FFrom;
686     if (ASI1.IsDone() && ASI1.NbPoints(1) >=1) {
687       OrU = ASI1.Point(1,1).Orientation();
688       if(sens==-1) {
689         OrU = TopAbs::Reverse(OrU);
690       }
691       FUntil = ASI1.Point(1,1).Face();
692     }
693     if (ASI2.IsDone() && ASI2.NbPoints(1) >=1) {
694       OrF = ASI2.Point(1,1).Orientation();
695 //      if(sens==1) OrF = TopAbs::Reverse(OrF);
696       FFrom = ASI2.Point(1 ,1).Face();
697       Handle(Geom_Surface) S = BRep_Tool::Surface(FFrom);
698       if (S->DynamicType() == 
699           STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
700         S = Handle(Geom_RectangularTrimmedSurface)::
701           DownCast(S)->BasisSurface();
702       }
703       BRepLib_MakeFace fac(S, Precision::Confusion());
704       mySFrom = fac.Face();  
705       Trf = TransformShapeFU(0);
706       FFrom = TopoDS::Face(mySFrom);
707     }
708
709     TopTools_ListOfShape aLTools;
710     TopoDS_Solid Sol = BRepFeat::Tool(mySUntil, FUntil, OrU);
711     if (!Sol.IsNull()) {
712       aLTools.Append(Sol);
713     }
714     else {
715       NotDone();
716       myStatusError = BRepFeat_NullToolU;
717       return;
718     }
719
720     TopoDS_Solid Sol1 = BRepFeat::Tool(mySFrom, FFrom, OrF);
721     if (!Sol1.IsNull()) {
722       aLTools.Append(Sol1);
723     }
724     else {
725       NotDone();
726       myStatusError = BRepFeat_NullToolF;
727       return;
728     }
729     //
730     TopTools_ListOfShape aLObj;
731     aLObj.Append(VraiPrism);
732     //
733     BRepAlgoAPI_Cut trP;
734     trP.SetArguments(aLObj);
735     trP.SetTools(aLTools);
736     trP.Build();
737     //
738     UpdateDescendants(trP, trP.Shape(), Standard_False);
739     if(myFuse == 1 && !myJustFeat) {
740       BRepAlgoAPI_Fuse f(mySbase, trP.Shape());
741       myShape = f.Shape();
742       UpdateDescendants(f, myShape, Standard_False);
743       Done();
744     }
745     else if(myFuse == 0) {
746       BRepAlgoAPI_Cut c(mySbase, trP.Shape());
747       myShape = c.Shape();
748       UpdateDescendants(c, myShape, Standard_False);
749       Done();
750     }
751     else {
752       myShape = trP.Shape();
753       Done();
754     }
755   }
756 }
757
758 //=======================================================================
759 //function : PerformThruAll
760 //purpose  : 
761 //=======================================================================
762
763 void BRepFeat_MakePrism::PerformThruAll()
764 {
765 #ifdef OCCT_DEBUG
766   Standard_Boolean trc = BRepFeat_GettraceFEAT();
767   if (trc) cout << "BRepFeat_MakePrism::PerformThruAll()" << endl;
768 #endif
769   mySUntil.Nullify();
770   ShapeUntilValid();
771   mySFrom.Nullify();
772   ShapeFromValid();
773   if(myFuse == 0) {
774     myPerfSelection = BRepFeat_NoSelection;
775   }
776   else {
777     myPerfSelection = BRepFeat_SelectionSh;
778   }
779   PerfSelectionValid();
780   myGluedF.Clear();
781   GluedFacesValid();
782
783   Standard_Real Height = HeightMax(mySbase, mySkface, mySFrom, mySUntil);
784   gp_Vec V(3*Height*myDir);
785   gp_Vec Vtra(-3*Height/2.*myDir);
786   LocOpe_Prism thePrism(myPbase,V,Vtra);
787   TopoDS_Shape VraiPrism = thePrism.Shape();
788   MajMap(myPbase,thePrism,myMap,myFShape,myLShape);
789
790   myGShape = VraiPrism;
791   GeneratedShapeValid();  
792
793   if(myFuse == 0) {
794     BRepAlgoAPI_Cut c(mySbase, myGShape);
795     if (c.IsDone()) {
796       myShape = c.Shape();
797       UpdateDescendants(c, myShape, Standard_False);
798       Done();
799     }
800   }
801   else {
802     thePrism.Curves(myCurves);
803     myBCurve = thePrism.BarycCurve();
804     GlobalPerform();
805   }
806 }
807
808 //=======================================================================
809 //function : PerformUntilHauteur
810 //purpose  : 
811 //=======================================================================
812
813 void BRepFeat_MakePrism::PerformUntilHeight(const TopoDS_Shape& Until,
814                                             const Standard_Real Length)
815 {
816 #ifdef OCCT_DEBUG
817   Standard_Boolean trc = BRepFeat_GettraceFEAT();
818   if (trc) cout << "BRepFeat_MakePrism::PerformUntilHeight(Until,Length)" << endl;
819 #endif
820   if (Until.IsNull()) {
821     Perform(Length);
822   }
823   if(Length == 0) {
824     Perform(Until);
825   }
826   TopExp_Explorer exp(Until, TopAbs_FACE);
827   if (!exp.More()) {
828     throw Standard_ConstructionError();
829   }
830   myGluedF.Clear();
831   myPerfSelection = BRepFeat_NoSelection;
832   PerfSelectionValid();
833   mySFrom.Nullify();
834   ShapeFromValid();
835   mySUntil = Until;
836   Standard_Boolean Trf = TransformShapeFU(1);
837   ShapeUntilValid();
838   Handle(Geom_Curve) C = TestCurve(myPbase,myDir);  
839   Standard_Integer sens = SensOfPrism(C, mySUntil);
840   gp_Vec V(sens*Length*myDir);
841   LocOpe_Prism thePrism(myPbase,V);
842   TopoDS_Shape VraiPrism = thePrism.Shape();
843
844   if(!Trf) {
845     MajMap(myPbase,thePrism,myMap,myFShape,myLShape);
846     
847     myGShape = VraiPrism;
848     GeneratedShapeValid();
849     GluedFacesValid();
850     thePrism.Curves(myCurves);
851     myBCurve = thePrism.BarycCurve();
852     GlobalPerform();
853   }
854   else {
855     MajMap(myPbase,thePrism,myMap,myFShape,myLShape);    
856     TColGeom_SequenceOfCurve scur;
857     scur.Clear();    
858     scur.Append(C);
859     LocOpe_CSIntersector ASI(mySUntil);
860     ASI.Perform(scur);
861     TopAbs_Orientation Or;
862     if (ASI.IsDone() && ASI.NbPoints(1) >=1) {
863       if (myFuse == 1) {
864         Or = ASI.Point(1,1).Orientation();
865       }
866       else {
867         Or = ASI.Point(1,ASI.NbPoints(1)).Orientation();
868       }
869       if(sens==-1) Or=TopAbs::Reverse(Or);
870       TopoDS_Face FUntil = ASI.Point(1,1).Face();
871       TopoDS_Shape Comp;
872       BRep_Builder B;
873       B.MakeCompound(TopoDS::Compound(Comp));
874       TopoDS_Solid S = BRepFeat::Tool(mySUntil, FUntil, Or);
875       if (!S.IsNull()) B.Add(Comp,S);
876
877       BRepAlgoAPI_Cut trP(VraiPrism,Comp);
878       UpdateDescendants(trP, trP.Shape(), Standard_False);
879       if(myFuse == 1 && !myJustFeat) {
880         BRepAlgoAPI_Fuse f(mySbase, trP.Shape());
881         myShape = f.Shape();
882         UpdateDescendants(f, myShape, Standard_False);
883         Done();
884       }
885       else if(myFuse == 0) {
886         BRepAlgoAPI_Cut c(mySbase, trP.Shape());
887         myShape = c.Shape();
888         UpdateDescendants(c, myShape, Standard_False);
889         Done();
890       }
891       else {
892         myShape = trP.Shape();
893         Done();
894       }
895     }
896   }
897 }
898
899 //=======================================================================
900 //function : Curves
901 //purpose  : sequence of curves parallel to the axis of prism 
902 //=======================================================================
903
904 void BRepFeat_MakePrism::Curves(TColGeom_SequenceOfCurve& scur)
905 {
906   scur = myCurves;
907 }
908
909 //=======================================================================
910 //function : BarycCurve
911 //purpose  : curve parallel to the axis of the prism passing through the center  
912 //           of masses
913 //=======================================================================
914
915 Handle(Geom_Curve) BRepFeat_MakePrism::BarycCurve()
916 {
917   return myBCurve;
918 }
919
920
921 //=======================================================================
922 //function : HeightMax
923 //purpose  : Calculate the height of the prism following the parameters of
924 //           bounding box
925 //=======================================================================
926
927 static Standard_Real HeightMax(const TopoDS_Shape& theSbase,
928                                const TopoDS_Face&  theSkface,
929                                const TopoDS_Shape& theSFrom,
930                                const TopoDS_Shape& theSUntil)
931 {
932   Bnd_Box Box;
933   BRepBndLib::Add(theSbase,Box);
934   BRepBndLib::Add(theSkface,Box);
935   if(!theSFrom.IsNull()) {
936     Standard_Boolean FacRevolInfini = Standard_False;
937     TopExp_Explorer exp;
938     exp.Init(theSFrom, TopAbs_EDGE);
939     for(; exp.More(); exp.Next()) {
940       TopExp_Explorer exp1;
941       exp1.Init(exp.Current(), TopAbs_VERTEX);
942       if(!exp1.More()) {
943         FacRevolInfini = Standard_True;
944         break;
945       }
946     }
947     if(!FacRevolInfini)
948       BRepBndLib::Add(theSFrom,Box);
949   }
950   if(!theSUntil.IsNull()) 
951   {
952     Standard_Boolean FacRevolInfini = Standard_False;
953     TopExp_Explorer exp;
954     exp.Init(theSUntil, TopAbs_EDGE);
955     for(; exp.More(); exp.Next()) 
956     {
957       TopExp_Explorer exp1;
958       exp1.Init(exp.Current(), TopAbs_VERTEX);
959       if(!exp1.More()) 
960       {
961         FacRevolInfini = Standard_True;
962         break;
963       }
964     }
965     if(!FacRevolInfini)
966       BRepBndLib::Add(theSUntil,Box);
967   }
968
969   Standard_Real c[6];
970
971   Box.Get(c[0],c[2],c[4],c[1],c[3],c[5]);
972   Standard_Real parmin=c[0], parmax = c[0];
973   for(Standard_Integer i = 0 ; i < 6; i++) {
974     if(c[i] > parmax) parmax = c[i];
975     if(c[i] < parmin ) parmin = c[i];    
976   }
977 //#ifndef OCCT_DEBUG
978   Standard_Real Height = fabs(2.*(parmax - parmin));
979 //#else
980 //  Standard_Real Height = abs(2.*(parmax - parmin));
981 //#endif
982   return(Height);
983 }
984
985
986 //=======================================================================
987 //function : SensOfPrism
988 //purpose  : Direction of the prism depending on the shape Until
989 //=======================================================================
990 Standard_Integer SensOfPrism(const Handle(Geom_Curve) C,
991                              const TopoDS_Shape& Until)
992 {
993   LocOpe_CSIntersector ASI1(Until);
994   TColGeom_SequenceOfCurve scur;
995   scur.Append(C);
996   ASI1.Perform(scur);
997   Standard_Integer sens = 1;
998   if(ASI1.IsDone() && ASI1.NbPoints(1) >= 1) {
999     if(ASI1.Point(1, 1).Parameter() < 0. && 
1000        ASI1.Point(1, ASI1.NbPoints(1)).Parameter() < 0.) {
1001       sens = -1;
1002     }
1003   }
1004   else if(BRepFeat::ParametricBarycenter(Until,C) < 0) {
1005       sens = -1;
1006   }
1007   else {}
1008   return sens;
1009 }
1010
1011 //=======================================================================
1012 //function : MajMap
1013 //purpose  : management of descendants
1014 //=======================================================================
1015
1016 static void MajMap(const TopoDS_Shape& theB,
1017                    const LocOpe_Prism& theP,
1018                    TopTools_DataMapOfShapeListOfShape& theMap, // myMap
1019                    TopoDS_Shape& theFShape,  // myFShape
1020                    TopoDS_Shape& theLShape) // myLShape
1021 {
1022   TopExp_Explorer exp(theP.FirstShape(),TopAbs_WIRE);
1023   if (exp.More()) {
1024     theFShape = exp.Current();
1025     TopTools_ListOfShape thelist2;
1026     theMap.Bind(theFShape, thelist2);
1027     for (exp.Init(theP.FirstShape(),TopAbs_FACE);exp.More();exp.Next()) {
1028       theMap(theFShape).Append(exp.Current());
1029     }
1030   }
1031   
1032   exp.Init(theP.LastShape(),TopAbs_WIRE);
1033   if (exp.More()) {
1034     theLShape = exp.Current();
1035     TopTools_ListOfShape thelist3;
1036     theMap.Bind(theLShape, thelist3);
1037     for (exp.Init(theP.LastShape(),TopAbs_FACE);exp.More();exp.Next()) {
1038       theMap(theLShape).Append(exp.Current());
1039     }
1040   }
1041
1042   for (exp.Init(theB,TopAbs_EDGE); exp.More(); exp.Next()) {
1043     if (!theMap.IsBound(exp.Current())) {
1044       TopTools_ListOfShape thelist4;
1045       theMap.Bind(exp.Current(), thelist4);
1046       theMap(exp.Current()) = theP.Shapes(exp.Current());
1047     }
1048   }
1049 }
1050
1051
1052 //=======================================================================
1053 //function : MajMap
1054 //purpose  : management of descendants
1055 //=======================================================================
1056
1057 static Handle(Geom_Curve) TestCurve(const TopoDS_Shape& Base,
1058                                     const gp_Vec& V)
1059 {
1060   gp_Pnt bar(0., 0., 0.);
1061   TColgp_SequenceOfPnt spt;
1062   LocOpe::SampleEdges(Base,spt);
1063   for (Standard_Integer jj=1;jj<=spt.Length(); jj++) {
1064     const gp_Pnt& pvt = spt(jj);
1065     bar.ChangeCoord() += pvt.XYZ();
1066   }
1067   bar.ChangeCoord().Divide(spt.Length());
1068   gp_Ax1 newAx(bar,V);
1069   Handle(Geom_Line) theLin = new Geom_Line(newAx);
1070   return theLin;
1071 }
1072
1073
1074
1075
1076 //=======================================================================
1077 //function : ToFuse
1078 //purpose  : face SameDomaine or not
1079 //=======================================================================
1080
1081 static Standard_Boolean ToFuse (const TopoDS_Face& F1, const TopoDS_Face& F2)
1082 {
1083   if (F1.IsNull() || F2.IsNull()) {
1084     return Standard_False;
1085   }
1086
1087   Handle(Geom_Surface) S1,S2;
1088   TopLoc_Location loc1, loc2;
1089   Handle(Standard_Type) typS1,typS2;
1090   const Standard_Real tollin = Precision::Confusion();
1091   const Standard_Real tolang = Precision::Angular();
1092
1093   S1 = BRep_Tool::Surface(F1,loc1);
1094   S2 = BRep_Tool::Surface(F2,loc2);
1095
1096   typS1 = S1->DynamicType();
1097   typS2 = S2->DynamicType();
1098
1099   if (typS1 == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1100     S1 =  Handle(Geom_RectangularTrimmedSurface)::DownCast (S1)->BasisSurface();
1101     typS1 = S1->DynamicType();
1102   }
1103
1104   if (typS2 == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1105     S2 =  Handle(Geom_RectangularTrimmedSurface)::DownCast (S2)->BasisSurface();
1106     typS2 = S2->DynamicType();
1107   }
1108
1109   if (typS1 != typS2) {
1110     return Standard_False;
1111   }
1112
1113
1114   Standard_Boolean ValRet = Standard_False;
1115   if (typS1 == STANDARD_TYPE(Geom_Plane)) {
1116     gp_Pln pl1( Handle(Geom_Plane)::DownCast (S1)->Pln());
1117     gp_Pln pl2( Handle(Geom_Plane)::DownCast (S2)->Pln());
1118
1119     // apply locations
1120     if (! loc1.IsIdentity())
1121       pl1.Transform (loc1.Transformation());
1122     if (! loc2.IsIdentity())
1123       pl2.Transform (loc2.Transformation());
1124
1125     if (pl1.Position().IsCoplanar(pl2.Position(),tollin,tolang)) {
1126       ValRet = Standard_True;
1127     }
1128   }
1129
1130   return ValRet;
1131 }
1132
1133
1134
1135
1136
1137