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