0024023: Revamp the OCCT Handle -- ambiguity
[occt.git] / src / BRepLib / BRepLib_MakeShell.cxx
1 // Created on: 1995-01-04
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1995-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 <BRepLib_MakeShell.ixx>
18
19 #include <BRepLib.hxx>
20 #include <BRepLib_MakeFace.hxx>
21 #include <Precision.hxx>
22 #include <TColStd_Array1OfReal.hxx>
23
24 #include <Geom_RectangularTrimmedSurface.hxx>
25 #include <Geom_BSplineSurface.hxx>
26 #include <Geom2d_Line.hxx>
27 #include <GeomAdaptor_Surface.hxx>
28 #include <TColGeom2d_Array1OfCurve.hxx>
29 #include <gp_Pnt.hxx>
30
31 #include <TopoDS.hxx>
32 #include <TopoDS_Face.hxx>
33 #include <TopoDS_Wire.hxx>
34 #include <TopoDS_Edge.hxx>
35 #include <TopoDS_Vertex.hxx>
36 #include <TopTools_Array1OfShape.hxx>
37 #include <BRep_Builder.hxx>
38
39 #include <TopExp_Explorer.hxx>
40 #include <Geom_Surface.hxx>
41
42
43 //=======================================================================
44 //function : BRepLib_MakeShell
45 //purpose  : 
46 //=======================================================================
47
48 BRepLib_MakeShell::BRepLib_MakeShell() :
49        myError(BRepLib_EmptyShell)
50 {
51 }
52
53
54 //=======================================================================
55 //function : BRepLib_MakeShell
56 //purpose  : 
57 //=======================================================================
58
59 BRepLib_MakeShell::BRepLib_MakeShell(const Handle(Geom_Surface)& S,
60                                      const Standard_Boolean Segment)
61 {
62   Standard_Real UMin,UMax,VMin,VMax;
63   S->Bounds(UMin,UMax,VMin,VMax);
64   Init(S,UMin,UMax,VMin,VMax,Segment);
65 }
66
67
68 //=======================================================================
69 //function : BRepLib_MakeShell
70 //purpose  : 
71 //=======================================================================
72
73 BRepLib_MakeShell::BRepLib_MakeShell(const Handle(Geom_Surface)& S, 
74                                      const Standard_Real UMin,
75                                      const Standard_Real UMax, 
76                                      const Standard_Real VMin, 
77                                      const Standard_Real VMax,
78                                      const Standard_Boolean Segment)
79 {
80   Init(S,UMin,UMax,VMin,VMax,Segment);
81 }
82
83
84 //=======================================================================
85 //function : Init
86 //purpose  : 
87 //=======================================================================
88
89 void BRepLib_MakeShell::Init(const Handle(Geom_Surface)& S, 
90                              const Standard_Real UMin, 
91                              const Standard_Real UMax, 
92                              const Standard_Real VMin, 
93                              const Standard_Real VMax,
94                              const Standard_Boolean Segment)
95 {
96   Handle(Geom_Surface) BS = S;
97   if ( S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
98     Handle(Geom_RectangularTrimmedSurface) RTS = 
99       Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
100     BS = RTS->BasisSurface();
101   }
102   myError = BRepLib_EmptyShell;
103   Standard_Real tol = Precision::Confusion();
104
105   // Make a shell from a surface
106   GeomAdaptor_Surface GS(BS,UMin,UMax,VMin,VMax);
107
108   Standard_Integer nu = GS.NbUIntervals(GeomAbs_C2);
109   Standard_Integer nv = GS.NbVIntervals(GeomAbs_C2);
110
111   Standard_Boolean uperiodic = GS.IsUPeriodic();
112   Standard_Boolean vperiodic = GS.IsVPeriodic();
113
114   if (nu == 0 || nv == 0) return;
115
116   // arrays of parameters and pcurves
117   TColStd_Array1OfReal upars(1,nu+1);
118   TColStd_Array1OfReal vpars(1,nv+1);
119   TColGeom2d_Array1OfCurve uisos(1,nu+1);
120   TColGeom2d_Array1OfCurve visos(1,nv+1);
121
122   Standard_Integer iu,iv;
123
124   GS.UIntervals(upars,GeomAbs_C2);
125   gp_Dir2d dv(0,1);
126   for (iu = 1; iu <= nu+1; iu++) {
127     Standard_Real u = upars(iu);
128     if (!Precision::IsInfinite(u))
129       uisos(iu)  = new Geom2d_Line(gp_Pnt2d(u,0.),dv);
130   }
131   
132   GS.VIntervals(vpars,GeomAbs_C2);
133   gp_Dir2d du(1,0);
134   for (iv = 1; iv <= nv+1 ; iv++) {
135     Standard_Real v = vpars(iv);
136     if (!Precision::IsInfinite(v))
137       visos(iv)  = new Geom2d_Line(gp_Pnt2d(0.,v),du);
138   }
139     
140   // create row by row
141
142   // create the shell
143   BRep_Builder B;
144   B.MakeShell(TopoDS::Shell(myShape));
145
146   // arrays of edges and vertices for each row
147   TopTools_Array1OfShape botedges(1,nu);
148   TopTools_Array1OfShape botvertices(1,nu+1);
149
150   // copies of the first ones for periodic case
151   TopTools_Array1OfShape fbotedges(1,nu);
152   TopTools_Array1OfShape fbotvertices(1,nu+1);
153
154   TopoDS_Face F;
155   TopoDS_Wire W;
156   TopoDS_Edge eleft,eright,etop,ebot,feleft;
157   TopoDS_Vertex vlb,vlt,vrb,vrt,fvlt;
158
159
160   // init the botedges and botvertices
161   if (!Precision::IsInfinite(vpars(1))) {
162     if (!Precision::IsInfinite(upars(1)))
163       B.MakeVertex(vrt,S->Value(upars(1),vpars(1)),tol);
164     fbotvertices(1) = botvertices(1) = vrt;
165
166     for (iu = 1; iu <= nu; iu++) {
167       vlt = vrt;
168
169       if (uperiodic && iu == nu)
170         vrt = TopoDS::Vertex(botvertices(1));
171       else if (!Precision::IsInfinite(upars(iu+1)))
172         B.MakeVertex(vrt,S->Value(upars(iu+1),vpars(1)),tol);
173
174       fbotvertices(iu+1) = botvertices(iu+1) = vrt;
175       B.MakeEdge(etop);
176       if (!vlt.IsNull()) {
177         vlt.Orientation(TopAbs_FORWARD);
178         B.Add(etop,vlt);
179       }
180       if (!vrt.IsNull()) {
181         vrt.Orientation(TopAbs_REVERSED);
182         B.Add(etop,vrt);
183       }
184       fbotedges(iu) = botedges(iu) = etop;
185     }
186   }
187
188   for (iv = 1; iv <= nv; iv++) {
189
190     // compute the first edge and vertices of the line
191     vrb = TopoDS::Vertex(botvertices(1));
192
193     if (vperiodic && iv == nv) {
194       vrt = TopoDS::Vertex(fbotvertices(1));
195     }
196     else {
197       vrt.Nullify();
198       if (!Precision::IsInfinite(vpars(iv+1))) {
199         if (!Precision::IsInfinite(upars(1)))
200           B.MakeVertex(vrt,S->Value(upars(1),vpars(iv+1)),tol);
201       }
202     }
203
204     eright.Nullify();
205     if (!Precision::IsInfinite(upars(1))) {
206       B.MakeEdge(eright);
207       if (!vrb.IsNull()) {
208         vrb.Orientation(TopAbs_FORWARD);
209         B.Add(eright,vrb);
210       }
211       if (!vrt.IsNull()) {
212         vrt.Orientation(TopAbs_REVERSED);
213         B.Add(eright,vrt);
214       }
215     }
216
217     fvlt  = vrt;
218     feleft = eright;
219
220
221     // make the row of faces
222     
223     for (iu = 1; iu <= nu; iu++) {
224       
225       // create the face at iu, iv
226
227       // the surface
228       Handle(Geom_Surface) SS = Handle(Geom_Surface)::DownCast(BS->Copy());
229       if (GS.GetType() == GeomAbs_BSplineSurface && Segment) {
230         Handle(Geom_BSplineSurface)::DownCast(SS)
231           ->Segment(upars(iu),upars(iu+1),
232                     vpars(iv),vpars(iv+1) );
233       }
234       B.MakeFace(F,SS,tol);
235
236       // the wire
237
238       B.MakeWire(W);
239
240       // the vertices
241
242       vlb = vrb;
243       vrb = TopoDS::Vertex(botvertices(iu+1));
244       vlt = vrt;
245
246       if (uperiodic && iu == nu)
247         vrt = fvlt;
248       else {
249         vrt.Nullify();
250         if (!Precision::IsInfinite(vpars(iv+1))) {
251           if (!Precision::IsInfinite(upars(iu+1)))
252             B.MakeVertex(vrt,S->Value(upars(iu+1),vpars(iv+1)),tol);
253         }
254       }
255
256       botvertices(iu)   = vlt;
257       botvertices(iu+1) = vrt;
258
259       // the edges
260
261       eleft = eright;
262
263       if  (uperiodic && iu == nu)
264         eright = feleft;
265       else {
266         eright.Nullify();
267         if (!Precision::IsInfinite(upars(iu+1))) {
268           B.MakeEdge(eright);
269           if (!vrb.IsNull()) {
270             vrb.Orientation(TopAbs_FORWARD);
271             B.Add(eright,vrb);
272           }
273           if (!vrt.IsNull()) {
274             vrt.Orientation(TopAbs_REVERSED);
275             B.Add(eright,vrt);
276           }
277         }
278       }
279
280       if ( uperiodic && nu == 1) {
281         if (!eleft.IsNull() && !eright.IsNull()) {
282           B.UpdateEdge(eleft,uisos(2),uisos(1),F,tol);
283           B.Range(eleft,F,vpars(iv),vpars(iv+1));
284         }
285       }
286       else {
287         if (!eleft.IsNull()) {
288           B.UpdateEdge(eleft,uisos(iu),F,tol);
289           B.Range(eleft,F,vpars(iv),vpars(iv+1));
290         }
291         if (!eright.IsNull()) {
292           B.UpdateEdge(eright,uisos(iu+1),F,tol);
293           B.Range(eright,F,vpars(iv),vpars(iv+1));
294         }
295       }
296       
297       ebot = TopoDS::Edge(botedges(iu));
298
299       if (vperiodic && iv == nv) 
300         etop = TopoDS::Edge(fbotedges(iu));
301       else {
302         etop.Nullify();
303         if (!Precision::IsInfinite(vpars(iv+1))) {
304           B.MakeEdge(etop);
305           if (!vlt.IsNull()) {
306             vlt.Orientation(TopAbs_FORWARD);
307             B.Add(etop,vlt);
308           }
309           if (!vrt.IsNull()) {
310             vrt.Orientation(TopAbs_REVERSED);
311             B.Add(etop,vrt);
312           }
313         }
314       }
315
316       if ( vperiodic && nv == 1) {
317         if (!ebot.IsNull() && !etop.IsNull()) {
318           B.UpdateEdge(ebot,visos(1),visos(2),F,tol);
319           B.Range(ebot,F,vpars(iv),vpars(iv+1));
320         }
321       }
322       else {
323         if (!ebot.IsNull()) {
324           B.UpdateEdge(ebot,visos(iv),F,tol);
325           B.Range(ebot,F,upars(iu),upars(iu+1));
326         }
327         if (!etop.IsNull()) {
328           B.UpdateEdge(etop,visos(iv+1),F,tol);
329           B.Range(etop,F,upars(iu),upars(iu+1));
330         }
331       }
332       
333       botedges(iu) = etop;
334
335       if (!eleft.IsNull()) {
336         eleft.Orientation(TopAbs_REVERSED);
337         B.Add(W,eleft);
338       }
339       if (!ebot.IsNull()) {
340         ebot.Orientation(TopAbs_FORWARD);
341         B.Add(W,ebot);
342       }
343       if (!eright.IsNull()) {
344         eright.Orientation(TopAbs_FORWARD);
345         B.Add(W,eright);
346       }
347       if (!etop.IsNull()) {
348         etop.Orientation(TopAbs_REVERSED);
349         B.Add(W,etop);
350       }
351       
352       B.Add(F,W);
353       B.Add(myShape,F);
354     }
355   }
356   
357   // codage des courbes 3d et regularites.
358   BRepLib::BuildCurves3d(myShape,tol);
359   BRepLib::EncodeRegularity(myShape);
360   myShape.Closed (BRep_Tool::IsClosed (myShape));
361
362   // Additional checking for degenerated edges
363   Standard_Boolean isDegenerated;
364   Standard_Real aFirst, aLast;
365   Standard_Real aTol = Precision::Confusion();
366   Standard_Real anActTol;
367   TopExp_Explorer anExp(myShape, TopAbs_EDGE);
368   for ( ; anExp.More(); anExp.Next())
369   {
370     const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
371     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
372     isDegenerated = BRepLib_MakeFace::IsDegenerated(aCurve, aTol, anActTol);
373     B.Degenerated(anEdge, isDegenerated);
374   }
375   
376   myError = BRepLib_ShellDone;
377   Done();
378 }
379
380
381 //=======================================================================
382 //function : Error
383 //purpose  : 
384 //=======================================================================
385
386 BRepLib_ShellError BRepLib_MakeShell::Error() const 
387 {
388   return myError;
389 }
390
391
392 //=======================================================================
393 //function : TopoDS_Shell&
394 //purpose  : 
395 //=======================================================================
396
397 const TopoDS_Shell& BRepLib_MakeShell::Shell() const 
398 {
399   return TopoDS::Shell(myShape);
400 }
401
402
403
404 //=======================================================================
405 //function : TopoDS_Shell
406 //purpose  : 
407 //=======================================================================
408
409 BRepLib_MakeShell::operator TopoDS_Shell() const
410 {
411   return Shell();
412 }
413
414