1 // Created on: 1998-06-08
2 // Created by: Stephanie HUMEAU
3 // Copyright (c) 1998-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 #include <BRepFill_Draft.hxx>
18 
19 #include <Adaptor3d_Curve.hxx>
20 #include <Adaptor3d_Surface.hxx>
21 #include <Bnd_Box.hxx>
22 #include <BndLib_Add3dCurve.hxx>
23 #include <BndLib_AddSurface.hxx>
24 #include <BOPAlgo_Builder.hxx>
25 #include <BOPAlgo_PaveFiller.hxx>
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepAdaptor_Curve.hxx>
29 #include <BRepAdaptor_Surface.hxx>
30 #include <BRepAlgoAPI_Section.hxx>
31 #include <BRepBuilderAPI_Sewing.hxx>
32 #include <BRepClass3d_SolidClassifier.hxx>
33 #include <BRepExtrema_DistShapeShape.hxx>
34 #include <BRepFill_DataMapOfShapeHArray2OfShape.hxx>
35 #include <BRepFill_DraftLaw.hxx>
36 #include <BRepFill_SectionLaw.hxx>
37 #include <BRepFill_ShapeLaw.hxx>
38 #include <BRepFill_Sweep.hxx>
39 #include <BRepLib_FindSurface.hxx>
40 #include <BRepLib_MakeEdge.hxx>
41 #include <BRepLib_MakeFace.hxx>
42 #include <BRepLib_MakeWire.hxx>
43 #include <BRepTools.hxx>
44 #include <Geom_Geometry.hxx>
45 #include <Geom_Line.hxx>
46 #include <Geom_Plane.hxx>
47 #include <Geom_RectangularTrimmedSurface.hxx>
48 #include <Geom_Surface.hxx>
49 #include <Geom_TrimmedCurve.hxx>
50 #include <GeomAdaptor_Surface.hxx>
51 #include <GeomFill_LocationDraft.hxx>
52 #include <GeomLProp_SLProps.hxx>
53 #include <gp_Ax3.hxx>
54 #include <gp_Dir.hxx>
55 #include <gp_Lin.hxx>
56 #include <gp_Mat.hxx>
57 #include <gp_Pnt.hxx>
58 #include <gp_Trsf.hxx>
59 #include <Precision.hxx>
60 #include <Standard_NoSuchObject.hxx>
61 #include <StdFail_NotDone.hxx>
62 #include <TColgp_Array1OfPnt.hxx>
63 #include <TColStd_Array1OfReal.hxx>
64 #include <TopAbs.hxx>
65 #include <TopExp.hxx>
66 #include <TopExp_Explorer.hxx>
67 #include <TopoDS.hxx>
68 #include <TopoDS_Edge.hxx>
69 #include <TopoDS_Iterator.hxx>
70 #include <TopoDS_Shape.hxx>
71 #include <TopoDS_Shell.hxx>
72 #include <TopoDS_Solid.hxx>
73 #include <TopoDS_Wire.hxx>
74 #include <TopTools_ListIteratorOfListOfShape.hxx>
75 #include <TopTools_ListOfShape.hxx>
76 
77 #ifdef DRAW
78 #include <Geom_Circle.hxx>
79 #include <gp.hxx>
80 #include <DBRep.hxx>
81 #include <DrawTrSurf.hxx>
82 static Standard_Boolean Affich = 0;
83 #endif
84 
85 //=======================================================================
86 //function : Trsf
87 //purpose  :
88 //======================================================================
ComputeTrsf(const TopoDS_Wire & W,const gp_Dir & D,Bnd_Box & Box,gp_Trsf & Tf)89 static void ComputeTrsf(const TopoDS_Wire& W,
90 			const gp_Dir& D,
91 			Bnd_Box& Box,
92 			gp_Trsf& Tf)
93 {
94   // Calculate approximate barycenter
95   BRepTools_WireExplorer Exp(W);
96 // Class BRep_Tool without fields and without Constructor :
97 //  BRep_Tool BT;
98   gp_XYZ Bary(0.,0.,0.);
99   Standard_Integer nb;
100 
101   for (nb=0; Exp.More(); Exp.Next()) {
102 //    Bary += BT.Pnt(Exp.CurrentVertex()).XYZ();
103     Bary += BRep_Tool::Pnt(Exp.CurrentVertex()).XYZ();
104     nb++;
105   }
106   Bary /= nb;
107 
108   // Calculate the Transformation
109   gp_Ax3 N(Bary, D);
110   Tf.SetTransformation(N);
111   BRepAdaptor_Curve AC;
112 //  BndLib_Add3dCurve BC;
113 
114   // transformation to the wire
115   TopoDS_Wire TheW = W;
116   TopLoc_Location Loc(Tf);
117   TheW.Location(Loc);
118 
119 
120   // Calculate the box
121   Box.SetVoid();
122   for (Exp.Init(TheW); Exp.More(); Exp.Next()) {
123     AC.Initialize(Exp.Current());
124 //    BC.Add(AC, 0.1, Box);
125     BndLib_Add3dCurve::Add(AC, 0.1, Box);
126   }
127 }
128 
129 //=======================================================================
130 //function : Length
131 //purpose  :
132 //======================================================================
Longueur(const Bnd_Box & WBox,const Bnd_Box & SBox,gp_Dir & D,gp_Pnt & P)133 static Standard_Real Longueur(const Bnd_Box& WBox,
134 			      const Bnd_Box& SBox,
135 			      gp_Dir& D,
136 			      gp_Pnt& P)
137 {
138   // face of the box most remoted from the face input in
139   // the direction of skin
140   Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax,WZmin,WZmax,L;
141 
142   //"coord" of the box
143   WBox.Get(Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
144   WZmin = Zmin;
145   WZmax = Zmax;
146 
147   SBox.Get(Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
148   P.SetCoord( (Xmin+Xmax)/2, (Ymin+Ymax)/2, Zmax);
149 
150   if (Zmax < WZmin) {
151     // Skin in the wrong direction. Invert...
152     D.Reverse();
153     L = WZmax - Zmin;
154     P.SetZ(Zmin);
155   }
156   else {
157     L = Zmax - WZmin;
158   }
159   return L;
160 }
161 
162 //=======================================================================
163 //function : GoodOrientation
164 //purpose  : Check if the law is oriented to have an exterior skin
165 //======================================================================
GoodOrientation(const Bnd_Box & B,const Handle (BRepFill_LocationLaw)& Law,const gp_Dir & D)166 static Standard_Boolean GoodOrientation(const Bnd_Box& B,
167 					const Handle(BRepFill_LocationLaw)& Law,
168 					const gp_Dir& D)
169 {
170   Standard_Real f, l, r, t;
171   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
172 
173   B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
174   gp_Pnt P1(aXmin, aYmin, aZmin), P2(aXmax, aYmax, aZmax);
175   gp_Vec V(P1, P2);
176 
177   Law->CurvilinearBounds(Law->NbLaw(), f, l);
178   r = V.Magnitude()/l;
179 
180   Standard_Integer ii, Ind;
181 //#ifndef OCCT_DEBUG
182   Standard_Integer Nb = (Standard_Integer) (4+(10*r));
183 //#else
184 //  Standard_Integer Nb = 4+(10*r);
185 //#endif
186   r = l/Nb;
187 
188   Nb++; // Number of points
189 
190   TColgp_Array1OfPnt Pnts(1, Nb);
191   Handle(Adaptor3d_Curve) AC;
192   gp_XYZ Bary(0.,0.,0.);
193 
194   for (ii=1; ii<=Nb; ii++) {
195     Law->Parameter((ii-1)*r, Ind, t);
196     AC = Law->Law(Ind)->GetCurve();
197     AC->D0(t,  Pnts(ii));
198     Bary+= Pnts(ii).XYZ();
199   }
200 
201   Bary /= Nb;
202   gp_Pnt Centre(Bary);
203   gp_Vec Normal(D.XYZ());
204   Standard_Real Angle = 0;
205   gp_Vec Ref(Centre,  Pnts(1));
206 
207   for (ii=2; ii<=Nb; ii++) {
208     gp_Vec R(Centre, Pnts(ii));
209     Angle += Ref.AngleWithRef(R, Normal);
210     Ref = R;
211   }
212 
213   return (Angle >= 0);
214 }
215 
216 //=======================================================================
217 //function : Constructeur
218 //purpose  :
219 //======================================================================
BRepFill_Draft(const TopoDS_Shape & S,const gp_Dir & Dir,const Standard_Real Angle)220  BRepFill_Draft::BRepFill_Draft(const TopoDS_Shape& S,
221 				const gp_Dir& Dir,
222 				const Standard_Real Angle)
223 {
224   myLoc.Nullify();
225   mySec.Nullify();
226   myFaces.Nullify();
227   mySections.Nullify();
228 
229   switch (S.ShapeType()) {
230   case TopAbs_WIRE :
231     {
232       myWire = TopoDS::Wire(S);
233       break;
234     }
235   case TopAbs_FACE :
236     {
237       TopoDS_Iterator Exp (S);
238       myWire = TopoDS::Wire(Exp.Value());
239       break;
240     }
241   case TopAbs_SHELL :
242     {
243       TopTools_ListOfShape List;
244       TopTools_IndexedDataMapOfShapeListOfShape edgemap;
245       TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,edgemap);
246       Standard_Integer iedge, nbf;
247       for (iedge = 1; iedge <= edgemap.Extent(); iedge++) {
248 	const TopoDS_Edge& theEdge = TopoDS::Edge(edgemap.FindKey(iedge));
249 	// skip degenerated edges
250 	if (!BRep_Tool::Degenerated(theEdge)) {
251 	  nbf = edgemap(iedge).Extent();
252 	  if (nbf==1) List.Append(theEdge);
253 	}
254       }
255 
256       if( List.Extent()>0) {
257 	BRepLib_MakeWire MW;
258 	MW.Add(List);
259 	BRepLib_WireError Err = MW.Error();
260 	if (Err == BRepLib_WireDone) {
261 	  myWire = MW.Wire();
262 	}
263 	else {
264 #ifdef OCCT_DEBUG
265 	  std::cout << "Error in MakeWire" << std::endl;
266 #endif
267 	  throw Standard_ConstructionError("BRepFill_Draft");
268 	}
269       }
270       else {
271 #ifdef OCCT_DEBUG
272 	  std::cout << "No Free Borders !" << std::endl;
273 #endif
274 	  throw Standard_ConstructionError("BRepFill_Draft");
275       }
276       break;
277     }
278     default :
279       throw Standard_ConstructionError("BRepFill_Draft");
280   }
281 
282   // Attention to closed non declared wires !
283   if (!myWire.Closed()) {
284     TopoDS_Vertex Vf, Vl;
285     TopExp::Vertices(myWire, Vf, Vl);
286     if (Vf.IsSame(Vl)) myWire.Closed(Standard_True);
287   }
288 #ifdef DRAW
289   if (Affich) {
290     DBRep::Set("TheWire", myWire);
291   }
292 #endif
293 
294   myAngle = Abs(Angle);
295   myDir = Dir;
296   myTop = S;
297   myDone = Standard_False;
298   myTol = 1.e-4;
299   myCont = GeomAbs_C1;
300   SetOptions();
301   SetDraft();
302 }
303 
304 //=======================================================================
305 //function :SetOptions
306 //purpose  : Defines the style
307 //======================================================================
SetOptions(const BRepFill_TransitionStyle Style,const Standard_Real Min,const Standard_Real Max)308  void BRepFill_Draft::SetOptions(const BRepFill_TransitionStyle Style,
309 				 const Standard_Real Min,
310 				 const Standard_Real Max)
311 {
312   myStyle =  Style;
313   angmin = Min;
314   angmax = Max;
315 }
316 
317 //=======================================================================
318 //function :SetDraft
319 //purpose  :
320 //======================================================================
SetDraft(const Standard_Boolean Internal)321  void BRepFill_Draft::SetDraft(const Standard_Boolean Internal)
322 {
323   IsInternal = Internal;
324 }
325 
326 
327 //=======================================================================
328 //function :Perform
329 //purpose  : calculate a surface of skinning
330 //======================================================================
Perform(const Standard_Real LengthMax)331  void BRepFill_Draft::Perform(const Standard_Real LengthMax)
332 {
333   Handle(Geom_Surface) S;
334   S.Nullify();
335   Bnd_Box WBox;//, SBox;
336   gp_Trsf Trsf;
337 
338 
339   ComputeTrsf(myWire, myDir, WBox, Trsf);
340   Init(S, LengthMax, WBox);
341   BuildShell(S);
342   Sewing();
343 }
344 
345 //=======================================================================
346 //function :Perform
347 //purpose  : calculate a surface of skinning
348 //======================================================================
Perform(const Handle (Geom_Surface)& Surface,const Standard_Boolean KeepInsideSurface)349  void BRepFill_Draft::Perform(const Handle(Geom_Surface)& Surface,
350 			      const Standard_Boolean KeepInsideSurface)
351 {
352   Bnd_Box WBox, SBox;
353   gp_Trsf Trsf;
354   gp_Pnt Pt;
355   Standard_Real L;
356 
357   ComputeTrsf(myWire, myDir, WBox, Trsf);
358 
359   // box with bounds of the stop surface
360   Handle(Geom_Surface) Surf;
361   Surf =   Handle(Geom_Surface)::DownCast(Surface->Transformed(Trsf));
362   GeomAdaptor_Surface S1 (Surf);
363 //  BndLib_AddSurface AS;
364 //  AS.Add(S1, 0.1, SBox);
365   BndLib_AddSurface::Add(S1, 0.1, SBox);
366 
367   // calculate the maximum length of the rule.
368   L = Longueur(WBox, SBox, myDir, Pt);
369   L /= Abs(Cos(myAngle));
370 
371   // Construction
372   Init(Surface, L, WBox);
373   BuildShell(Surface, !KeepInsideSurface);
374   Sewing();
375 }
376 
377 //================================================================
378 //function :Perform
379 //purpose  : calculate the surface of skinning, stopped by a shape
380 //================================================================
Perform(const TopoDS_Shape & StopShape,const Standard_Boolean KeepOutSide)381  void BRepFill_Draft::Perform(const TopoDS_Shape& StopShape,
382 			      const Standard_Boolean KeepOutSide)
383 {
384   Bnd_Box WBox, SBox;
385   gp_Trsf Trsf;
386   gp_Pnt Pt;
387   Standard_Real L;
388 
389   ComputeTrsf(myWire, myDir, WBox, Trsf);
390 
391 // bounding box of the stop shape
392   Bnd_Box BSurf;//, TheBox;
393   Standard_Real Umin, Umax, Vmin, Vmax;
394 //  BRepTools B;
395 //  BRep_Tool BT;
396   Handle(Geom_Surface) Surf;
397 
398 //  BndLib_AddSurface AS;
399 
400   TopExp_Explorer Ex (StopShape, TopAbs_FACE);
401 
402   SBox.SetVoid();
403   while (Ex.More()) { // parse faces of the stop shape
404 //    B.UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax);
405     BRepTools::UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax);
406     Surf = Handle(Geom_Surface)::DownCast(
407 //     BT.Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) );
408      BRep_Tool::Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) );
409     GeomAdaptor_Surface S1 (Surf);
410 // bounding box of the current face
411 //    AS.Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf);
412     BndLib_AddSurface::Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf);
413     SBox.Add(BSurf);	// group boxes
414     Ex.Next();
415   }// while_Ex
416 
417   // calculate the maximum length of the rule.
418   L = Longueur(WBox, SBox, myDir, Pt);
419   L /= Abs(Cos(myAngle));
420 
421 // surface of stop
422   gp_Trsf Inv;
423   Inv = Trsf.Inverted(); // inverted transformation
424   Pt.Transform(Inv); // coordinate in the absolute reference
425   Handle(Geom_Plane) Plan = new (Geom_Plane)(Pt, myDir);
426   Surf = new (Geom_RectangularTrimmedSurface) (Plan,-L, L, -L, L);
427 
428 #ifdef DRAW
429   if (Affich) {
430     char* Temp = "ThePlan" ;
431     DrawTrSurf::Set(Temp, Surf);
432 //    DrawTrSurf::Set("ThePlan", Surf);
433   }
434 #endif
435 
436 // Sweeping and restriction
437   Init(Plan,  L*1.01, WBox);
438   BuildShell(Surf, Standard_False);
439   Fuse(StopShape,  KeepOutSide);
440   Sewing();
441 }
442 
443 //=======================================================================
444 //function : Init
445 //purpose  : Construction of laws.
446 //======================================================================
Init(const Handle (Geom_Surface)&,const Standard_Real Length,const Bnd_Box & Box)447  void BRepFill_Draft::Init(const Handle(Geom_Surface)& ,
448                            const Standard_Real Length,
449 			   const Bnd_Box&  Box)
450 {
451   Standard_Boolean B;
452 
453 // law of positioning
454   Handle(GeomFill_LocationDraft) Loc
455     = new (GeomFill_LocationDraft) (myDir, myAngle);
456   myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
457 
458   B = GoodOrientation(Box, myLoc, myDir);
459 
460   if (IsInternal ^ (!B) )  {
461     myAngle = - myAngle;
462     Loc->SetAngle(myAngle);
463     myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
464   }
465 
466   myLoc->CleanLaw(angmin); // Clean small discontinuities.
467 
468 // law of section
469 // generating line is straight and parallel to binormal.
470   gp_Pnt P(0, 0, 0);
471   gp_Vec D (0., 1., 0.);
472 
473 // Control of the orientation
474   Standard_Real f,l;
475   myLoc->Law(1)->GetDomain(f,l);
476   gp_Mat M;
477 
478   gp_Vec Bid;
479   myLoc->Law(1)->D0( (f+l)/2, M, Bid);
480   gp_Dir BN(M.Column(2));
481 
482   Standard_Real ang = myDir.Angle(BN);
483   if (ang > M_PI/2) D.Reverse();
484   Handle(Geom_Line) L = new (Geom_Line) (P, D);
485 
486   Handle(Geom_Curve) TC = new (Geom_TrimmedCurve) (L, 0, Length);
487 
488 
489 #ifdef DRAW
490   if (Affich > 2) {
491      TC = new (Geom_Circle) (gp::XOY(), Length);
492   }
493 #endif
494 
495   BRepLib_MakeEdge ME(TC);
496   TopoDS_Edge EG = ME.Edge();
497 
498   BRepLib_MakeWire MW(EG);
499   TopoDS_Wire G = MW.Wire();
500 
501   mySec = new (BRepFill_ShapeLaw) (G, Standard_True);
502 }
503 
504 
505 //=======================================================================
506 //function : BuildShell
507 //purpose  : Construction of the skinning surface
508 //======================================================================
BuildShell(const Handle (Geom_Surface)& Surf,const Standard_Boolean KeepOutSide)509  void BRepFill_Draft::BuildShell(const Handle(Geom_Surface)& Surf,
510 				 const Standard_Boolean  KeepOutSide)
511 {
512 // construction of the surface
513   BRepFill_Sweep Sweep(mySec, myLoc, Standard_True);
514   Sweep.SetTolerance(myTol);
515   Sweep.SetAngularControl(angmin, angmax);
516   TopTools_MapOfShape Dummy;
517   BRepFill_DataMapOfShapeHArray2OfShape Dummy2;
518   BRepFill_DataMapOfShapeHArray2OfShape Dummy3;
519   Sweep.Build(Dummy, Dummy2, Dummy3, myStyle, myCont);
520   if (Sweep.IsDone()) {
521     myShape = Sweep.Shape();
522     myShell = TopoDS::Shell(myShape);
523     myFaces    = Sweep.SubShape();
524     mySections = Sweep.Sections();
525     myDone = Standard_True;
526     // Control of the orientation
527     Standard_Boolean out=Standard_True;
528     TopExp_Explorer ex(myShell,TopAbs_FACE);
529     TopoDS_Face F;
530     F = TopoDS::Face(ex.Current());
531     BRepAdaptor_Surface SF(F);
532     Standard_Real u, v;
533     gp_Pnt P;
534     gp_Vec V1, V2, V;
535     u = SF.FirstUParameter();
536     v = SF.FirstVParameter();
537     SF.D1(u,v,P,V1,V2);
538     V = V1.Crossed(V2);
539     if (F.Orientation() == TopAbs_REVERSED) V.Reverse();
540     if (V.Magnitude() > 1.e-10) {
541       out = myDir.Angle(V) > M_PI/2;
542     }
543     if (out == IsInternal) {
544       myShell.Reverse();
545       myShape.Reverse();
546     }
547   }
548   else {
549     myDone = Standard_False;
550     return;
551   }
552 
553   if (!Surf.IsNull()) { // Add the face at end
554 
555   // Waiting the use of traces & retriction in BRepFill_Sweep
556   // Make Fuse.
557     BRepLib_MakeFace MkF;
558     MkF.Init(Surf, Standard_True, Precision::Confusion());
559     Fuse(MkF.Face(), KeepOutSide);
560   }
561 }
562 
563 
564 //=======================================================================
565 //function : Fuse
566 //purpose  : Boolean operation between the skin and the
567 //           stop shape
568 //======================================================================
Fuse(const TopoDS_Shape & StopShape,const Standard_Boolean KeepOutSide)569  Standard_Boolean BRepFill_Draft::Fuse(const TopoDS_Shape& StopShape,
570 			   const Standard_Boolean KeepOutSide)
571 {
572   BRep_Builder B;
573   Standard_Boolean issolid = Standard_False;
574   TopoDS_Solid Sol1, Sol2;
575   TopAbs_State State1 = TopAbs_OUT,  State2 = TopAbs_OUT;
576 
577 
578   if (myShape.ShapeType()==TopAbs_SOLID) {
579     Sol1 = TopoDS::Solid(myShape);
580     issolid = Standard_True;
581   }
582   else {
583     B.MakeSolid(Sol1);
584     B.Add(Sol1, myShape); // shell => solid (for fusion)
585   }
586 
587 
588   switch (StopShape.ShapeType()) {
589   case TopAbs_COMPOUND :
590     {
591       TopoDS_Iterator It(StopShape);
592       return Fuse(It.Value(), KeepOutSide);
593     }
594   case TopAbs_SOLID :
595     {
596       Sol2 = TopoDS::Solid(StopShape);
597       break;
598     }
599  case TopAbs_SHELL :
600     {
601       B.MakeSolid(Sol2);
602       B.Add(Sol2, StopShape); // shell => solid (for fusion)
603       break;
604     }
605 
606  case TopAbs_FACE :
607     {
608       TopoDS_Shell S;
609       B.MakeShell(S);
610       B.Add(S, StopShape);
611       S.Closed (BRep_Tool::IsClosed (S));
612       B.MakeSolid(Sol2);
613       B.Add(Sol2, S); // shell => solid (for fusion)
614       break;
615     }
616 
617   default :
618     {
619       return Standard_False; // Impossible to do
620     }
621   }
622 
623   // Perform intersection of solids
624   BOPAlgo_PaveFiller aPF;
625   TopTools_ListOfShape anArgs;
626   anArgs.Append(Sol1);
627   anArgs.Append(Sol2);
628   aPF.SetArguments(anArgs);
629   aPF.Perform();
630   if (aPF.HasErrors())
631     return Standard_False;
632 
633   BRepAlgoAPI_Section aSec(Sol1, Sol2, aPF);
634   const TopoDS_Shape& aSection = aSec.Shape();
635 
636   TopExp_Explorer exp(aSection, TopAbs_EDGE);
637   if (!exp.More())
638     // No section edges produced
639     return Standard_False;
640 
641   if (StopShape.ShapeType() != TopAbs_SOLID)
642   {
643     // It is required to choose the state by the geometry
644 
645     // We need to find the section edge, closest to myWire
646     TopoDS_Edge aSEMin;
647     Standard_Real Dmin = Precision::Infinite();
648     BRepExtrema_DistShapeShape DistTool;
649     DistTool.LoadS1(myWire);
650 
651     for (; exp.More(); exp.Next())
652     {
653       const TopoDS_Shape& aSE = exp.Current();
654       DistTool.LoadS2(aSE);
655       DistTool.Perform();
656       if (DistTool.IsDone())
657       {
658         Standard_Real D = DistTool.Value();
659         if (D < Dmin)
660         {
661           Dmin = D;
662           aSEMin = TopoDS::Edge(aSE);
663           if (Dmin < Precision::Confusion())
664             break;
665         }
666       }
667     }
668 
669     if (!aSEMin.IsNull())
670     {
671       // Get geometry of StopShape
672       Handle(Geom_Surface) S;
673       Handle(Geom2d_Curve) C2d;
674       gp_Pnt2d P2d;
675       Standard_Real f, l;
676       TopLoc_Location L;
677       BRep_Tool::CurveOnSurface(aSEMin, C2d, S, L, f, l, 2);
678 
679       // Find a normal.
680       C2d->D0((f + l) / 2, P2d);
681       GeomLProp_SLProps SP(S, P2d.X(), P2d.Y(), 1, 1.e-12);
682       if (!SP.IsNormalDefined())
683       {
684         C2d->D0((3 * f + l) / 4, P2d);
685         SP.SetParameters(P2d.X(), P2d.Y());
686         if (!SP.IsNormalDefined())
687         {
688           C2d->D0((f + 3 * l) / 4, P2d);
689           SP.SetParameters(P2d.X(), P2d.Y());
690         }
691       }
692 
693       if (SP.IsNormalDefined())
694       {
695         // Subtract State1
696         if (myDir.Angle(SP.Normal()) < M_PI / 2)  State1 = TopAbs_IN;
697         else  State1 = TopAbs_OUT;
698       }
699     }
700   }
701 
702   if (! KeepOutSide) { // Invert State2;
703     if (State2 == TopAbs_IN) State2 = TopAbs_OUT;
704     else State2 = TopAbs_IN;
705   }
706 
707   // Perform Boolean operation
708   BOPAlgo_Builder aBuilder;
709   aBuilder.AddArgument(Sol1);
710   aBuilder.AddArgument(Sol2);
711   aBuilder.PerformWithFiller(aPF);
712   if (aBuilder.HasErrors())
713     return Standard_False;
714 
715   TopoDS_Shape result;
716   Handle(BRepTools_History) aHistory = new BRepTools_History;
717 
718   Standard_Boolean isSingleOpNeeded = Standard_True;
719   // To get rid of the unnecessary parts of first solid make the cutting first
720   if (State1 == TopAbs_OUT)
721   {
722     TopTools_ListOfShape aLO, aLT;
723     aLO.Append(Sol1);
724     aLT.Append(Sol2);
725     aBuilder.BuildBOP(aLO, aLT, BOPAlgo_CUT, Message_ProgressRange());
726     if (!aBuilder.HasErrors())
727     {
728       TopoDS_Solid aCutMin;
729       TopExp_Explorer anExpS(aBuilder.Shape(), TopAbs_SOLID);
730       if (anExpS.More())
731       {
732         aCutMin = TopoDS::Solid(anExpS.Current());
733         anExpS.Next();
734         if (anExpS.More())
735         {
736           Standard_Real aDMin = Precision::Infinite();
737           BRepExtrema_DistShapeShape DistTool;
738           DistTool.LoadS1(myWire);
739 
740           for (anExpS.ReInit(); anExpS.More(); anExpS.Next())
741           {
742             const TopoDS_Shape& aCut = anExpS.Current();
743             DistTool.LoadS2(aCut);
744             DistTool.Perform();
745             if (DistTool.IsDone())
746             {
747               Standard_Real D = DistTool.Value();
748               if (D < aDMin)
749               {
750                 aDMin = D;
751                 aCutMin = TopoDS::Solid(aCut);
752               }
753             }
754           }
755         }
756       }
757 
758       if (!aCutMin.IsNull())
759       {
760         // Save history for first argument only
761         aHistory->Merge(aLO, aBuilder);
762 
763         // Perform needed operation with result of Cut
764         BOPAlgo_Builder aGluer;
765         aGluer.AddArgument(aCutMin);
766         aGluer.AddArgument(Sol2);
767         aGluer.SetGlue(BOPAlgo_GlueShift);
768         aGluer.Perform();
769 
770         aLO.Clear();
771         aLO.Append(aCutMin);
772         aGluer.BuildBOP(aLO, State1, aLT, State2, Message_ProgressRange());
773 
774         if (!aGluer.HasErrors())
775         {
776           aHistory->Merge(aGluer.History());
777 
778           result = aGluer.Shape();
779           anExpS.Init(result, TopAbs_SOLID);
780           isSingleOpNeeded = !anExpS.More();
781         }
782       }
783     }
784   }
785 
786   if (isSingleOpNeeded)
787   {
788     aHistory->Clear();
789 
790     TopTools_ListOfShape aLO, aLT;
791     aLO.Append(Sol1);
792     aLT.Append(Sol2);
793 
794     aBuilder.BuildBOP(aLO, State1, aLT, State2, Message_ProgressRange());
795     if (aBuilder.HasErrors())
796       return Standard_False;
797 
798     aHistory->Merge(aBuilder.History());
799     result = aBuilder.Shape();
800   }
801 
802   if (issolid) myShape =  result;
803   else {
804     TopExp_Explorer Exp;
805     Exp.Init(result, TopAbs_SHELL);
806     if (Exp.More()) myShape = Exp.Current();
807   }
808 
809   // Update the History
810   Standard_Integer ii;
811   for (ii=1; ii<=myLoc->NbLaw(); ii++) {
812     const TopTools_ListOfShape& L = aHistory->Modified(myFaces->Value(1,ii));
813     if (L.Extent()>0)
814       myFaces->SetValue(1, ii, L.First());
815   }
816   for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
817     const TopTools_ListOfShape& L = aHistory->Modified(mySections->Value(1,ii));
818     if (L.Extent()>0)
819       mySections->SetValue(1, ii, L.First());
820   }
821 
822   return Standard_True;
823 }
824 
825 //=======================================================================
826 //function : Sewing
827 //purpose  : Assemble the skin with the above face
828 //======================================================================
Sewing()829  Standard_Boolean BRepFill_Draft::Sewing()
830 {
831   Standard_Boolean ToAss;
832   Standard_Boolean Ok = Standard_False;
833   ToAss = (myTop.ShapeType() != TopAbs_WIRE);
834 
835   if ((!ToAss) || (!myDone)) return Standard_False;
836 
837    // Assembly make a shell from the faces of the shape + the input shape
838   Handle(BRepBuilderAPI_Sewing) Ass =  new BRepBuilderAPI_Sewing(5*myTol, Standard_True,
839    		                                     Standard_True, Standard_False);
840   Ass->Add(myShape);
841   Ass->Add(myTop);
842   ToAss = Standard_True;
843 
844 
845   Standard_Integer NbCE;
846 
847   Ass->Perform();
848   // Check if the assembly is real.
849   NbCE = Ass->NbContigousEdges();
850 
851   if (NbCE > 0) {
852     TopoDS_Shape res;
853     res = Ass->SewedShape();
854     if ((res.ShapeType() == TopAbs_SHELL)||
855 	(res.ShapeType() == TopAbs_SOLID))  {
856       myShape = res;
857       Ok = Standard_True;
858     }
859     else if (res.ShapeType() == TopAbs_COMPOUND) {
860       TopoDS_Iterator It(res);
861       res = It.Value();
862       It.Next();
863       if (!It.More()) {//Only one part => this is correct
864 	myShape = res;
865 	Ok = Standard_True;
866       }
867     }
868   }
869 
870   if (Ok) {
871     // Update the History
872     Standard_Integer ii;
873     for (ii=1; ii<=myLoc->NbLaw(); ii++) {
874       if (Ass->IsModified(myFaces->Value(1,ii)))
875 	myFaces->SetValue(1, ii,
876 			  Ass->Modified(myFaces->Value(1,ii)));
877     }
878     for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
879       if (Ass->IsModified(mySections->Value(1,ii)))
880 	mySections->SetValue(1, ii,
881 			     Ass->Modified(mySections->Value(1,ii)));
882     }
883 
884     if (myShape.Closed()) { // Make a Solid
885       TopoDS_Solid solid;
886       BRep_Builder BS;
887       BS.MakeSolid(solid);
888       BS.Add(solid,TopoDS::Shell(myShape));
889 
890       BRepClass3d_SolidClassifier SC(solid);
891       SC.PerformInfinitePoint(Precision::Confusion());
892       if ( SC.State() == TopAbs_IN) {
893 	BS.MakeSolid(solid);
894 	myShape.Reverse();
895 	BS.Add(solid,TopoDS::Shell(myShape));
896       }
897       myShape = solid;
898     }
899   }
900 #ifdef OCCT_DEBUG
901   else std::cout << "Draft : No assembly !" << std::endl;
902 #endif
903   return Ok;
904 }
905 
906 //=======================================================================
907 //function : Generated
908 //purpose  : return a sub-part generated by sweeping
909 //======================================================================
910  const TopTools_ListOfShape&
Generated(const TopoDS_Shape & S)911  BRepFill_Draft::Generated(const TopoDS_Shape& S)
912 {
913   myGenerated.Clear();
914   TopoDS_Edge E;
915   Standard_Integer ii;
916   E = TopoDS::Edge(S);
917   if (E.IsNull()) {
918    for (ii=0; ii<=myLoc->NbLaw(); ii++)
919       if (E.IsSame(myLoc->Vertex(ii))) {
920 	myGenerated.Append(mySections->Value(1, ii+1));
921 	break;
922       }
923   }
924   else {
925     for (ii=1; ii<=myLoc->NbLaw(); ii++)
926       if (E.IsSame(myLoc->Edge(ii))) {
927 	myGenerated.Append(myFaces->Value(1, ii));
928 	break;
929       }
930   }
931 
932   return myGenerated;
933 }
934 
935 //=======================================================================
936 //function : Shape
937 //purpose  : return the complete shape
938 //======================================================================
Shape() const939  TopoDS_Shape BRepFill_Draft::Shape()const
940 {
941   return myShape;
942 }
943 
944 //=====================================================================
945 //function : Shell
946 //purpose  : surface of skinning with the input face (=>shell)
947 //=====================================================================
Shell() const948  TopoDS_Shell BRepFill_Draft::Shell()const
949 {
950   return myShell;
951 }
952 
953 //=======================================================================
954 //function : IsDone
955 //purpose  :
956 //======================================================================
IsDone() const957  Standard_Boolean BRepFill_Draft::IsDone()const
958 {
959   return myDone;
960 }
961