0025748: Parallel version of progress indicator
[occt.git] / src / BRepToIGES / BRepToIGES_BRShell.cxx
1 // Created on: 1995-01-30
2 // Created by: Marie Jose MARTZ
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 //:n3 abv 8 Feb 99: PRO17820: BRepTools::OuterWire() -> ShapeAnalysis::OuterWire
18 //szv#4 S4163
19
20 #include <BRep_Builder.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepToIGES_BREntity.hxx>
23 #include <BRepToIGES_BRShell.hxx>
24 #include <BRepToIGES_BRWire.hxx>
25 #include <BRepTools.hxx>
26 #include <Geom2d_Curve.hxx>
27 #include <Geom_ConicalSurface.hxx>
28 #include <Geom_CylindricalSurface.hxx>
29 #include <Geom_Plane.hxx>
30 #include <Geom_RectangularTrimmedSurface.hxx>
31 #include <Geom_SphericalSurface.hxx>
32 #include <Geom_Surface.hxx>
33 #include <Geom_SurfaceOfRevolution.hxx>
34 #include <Geom_ToroidalSurface.hxx>
35 #include <GeomToIGES_GeomSurface.hxx>
36 #include <gp.hxx>
37 #include <gp_Trsf.hxx>
38 #include <IGESBasic_Group.hxx>
39 #include <IGESData_HArray1OfIGESEntity.hxx>
40 #include <IGESData_IGESEntity.hxx>
41 #include <IGESGeom_CurveOnSurface.hxx>
42 #include <IGESGeom_HArray1OfCurveOnSurface.hxx>
43 #include <IGESGeom_SurfaceOfRevolution.hxx>
44 #include <IGESGeom_TrimmedSurface.hxx>
45 #include <Interface_Macros.hxx>
46 #include <Message_ProgressScope.hxx>
47 #include <NCollection_IncAllocator.hxx>
48 #include <NCollection_Map.hxx>
49 #include <ShapeAlgo.hxx>
50 #include <ShapeAlgo_AlgoContainer.hxx>
51 #include <TColStd_HSequenceOfTransient.hxx>
52 #include <TopAbs_ShapeEnum.hxx>
53 #include <TopExp.hxx>
54 #include <TopExp_Explorer.hxx>
55 #include <TopLoc_Location.hxx>
56 #include <TopoDS.hxx>
57 #include <TopoDS_Edge.hxx>
58 #include <TopoDS_Face.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopoDS_Shell.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <TopoDS_Wire.hxx>
63 #include <TopTools_ShapeMapHasher.hxx>
64 #include <Transfer_FinderProcess.hxx>
65
66 //=============================================================================
67 // BRepToIGES_BRShell
68 //=============================================================================
69 BRepToIGES_BRShell::BRepToIGES_BRShell()
70 {
71 }
72
73
74 //=============================================================================
75 // BRepToIGES_BRShell
76 //=============================================================================
77
78 BRepToIGES_BRShell::BRepToIGES_BRShell
79 (const BRepToIGES_BREntity& BR)
80 : BRepToIGES_BREntity(BR)
81 {
82 }
83
84
85 //=============================================================================
86 // TransferShell
87 //=============================================================================
88
89 Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferShell(const TopoDS_Shape& start,
90                                                                const Message_ProgressRange& theProgress)
91 {
92   Handle(IGESData_IGESEntity) res;
93
94   if (start.IsNull())  return  res;
95
96   if (start.ShapeType() == TopAbs_FACE) {
97     TopoDS_Face F =  TopoDS::Face(start);
98     res = TransferFace(F, theProgress);
99   }  
100   else if (start.ShapeType() == TopAbs_SHELL) {
101     TopoDS_Shell S =  TopoDS::Shell(start);
102     res = TransferShell(S, theProgress);
103   }  
104   else {
105     // message d`erreur
106   }  
107   return res;
108 }
109
110
111 //=============================================================================
112 // TransferFace
113 // 
114 //=============================================================================
115
116 Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face& start,
117                                                               const Message_ProgressRange&)
118 {
119   Handle(IGESData_IGESEntity) res;
120   
121   if ( start.IsNull()) {
122     return res;
123   }
124
125   // pour explorer la face , il faut la mettre fORWARD.
126   TopoDS_Face myface;
127   if (start.Orientation() == TopAbs_REVERSED) {
128     //create face with redirected surface
129     BRep_Builder B;
130     TopLoc_Location aLoc;
131     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(start, aLoc);
132     while (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
133     {
134       // take basis surface, because pcurves will be transformed, so trim will be shifted,
135       // accorded to new face bounds
136       Handle(Geom_RectangularTrimmedSurface) aTrimmedSurf = 
137         Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf);
138       aSurf = aTrimmedSurf->BasisSurface();
139     }
140     aSurf = aSurf->UReversed();
141     Standard_Real aTol = BRep_Tool::Tolerance(start);
142     B.MakeFace(myface, aSurf, aLoc ,aTol);
143     // set specifics flags of a Face
144     B.NaturalRestriction(myface, BRep_Tool::NaturalRestriction(start));
145     //add wires
146     TopoDS_Wire anOuter = TopoDS::Wire(ShapeAlgo::AlgoContainer()->OuterWire(start));
147     TopExp_Explorer ex;
148     for (ex.Init(start,TopAbs_WIRE); ex.More(); ex.Next()) {
149       TopoDS_Wire W = TopoDS::Wire(ex.Current());
150       if (!W.IsNull() && W.IsSame(anOuter)) {
151         B.Add(myface, W);
152         break;
153       }
154     }     
155     for (ex.Init(start,TopAbs_WIRE); ex.More(); ex.Next()) {
156       TopoDS_Wire W = TopoDS::Wire(ex.Current());
157       if (!W.IsNull() && !W.IsSame(anOuter)) {
158         B.Add(myface, W);
159       }
160     }
161
162     // mirror pcurves
163     Standard_Real U1, U2, V1, V2;
164     aSurf->Bounds(U1, U2, V1, V2);
165     Standard_Real aCenter = 0.5 * (U1 + U2);
166     gp_Trsf2d T;
167     gp_Ax2d axis(gp_Pnt2d(aCenter, V1), gp_Dir2d(0.,1.));
168     T.SetMirror(axis);
169     NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> aMap (101, new NCollection_IncAllocator);
170     for (ex.Init(myface,TopAbs_EDGE);ex.More(); ex.Next()) {
171       TopoDS_Edge anEdge = TopoDS::Edge(ex.Current());
172       if (!aMap.Add(anEdge))
173         // seam edge has been already updated
174         continue;
175       Standard_Real f, l;
176       Handle(Geom2d_Curve) aCurve1, aCurve2;
177       aCurve1 = BRep_Tool::CurveOnSurface(anEdge, start, f, l);
178       aTol = BRep_Tool::Tolerance(anEdge);
179       if (!aCurve1.IsNull()) {
180         aCurve1 = Handle(Geom2d_Curve)::DownCast(aCurve1->Transformed(T));
181         if (BRepTools::IsReallyClosed(anEdge, start)) {
182           TopoDS_Edge revEdge = TopoDS::Edge(anEdge.Reversed());
183           aCurve2 = BRep_Tool::CurveOnSurface(revEdge, start, f, l);
184           if (!aCurve2.IsNull()) {
185             aCurve2 = Handle(Geom2d_Curve)::DownCast(aCurve2->Transformed(T));
186             if (anEdge.Orientation() == TopAbs_FORWARD)
187               B.UpdateEdge(anEdge, aCurve1, aCurve2, myface, aTol);
188             else
189               B.UpdateEdge(anEdge, aCurve2, aCurve1, myface, aTol);
190           }
191           else {
192             B.UpdateEdge(anEdge, aCurve1, myface, aTol);
193           }
194         }
195         else {
196           B.UpdateEdge(anEdge, aCurve1, myface, aTol);
197         }
198         // set range for degenerated edges
199         if (BRep_Tool::Degenerated(anEdge)) {
200           B.Range(anEdge, myface, f, l);
201         }
202       }
203     }
204   }
205   else {
206     myface = start;
207   }
208
209   //Standard_Integer Nb = 0; //szv#4:S4163:12Mar99 unused
210   Standard_Real Length = 1.;
211   Handle(IGESData_IGESEntity) ISurf;
212
213   // returns the face surface
214   // ------------------------
215
216   Handle(Geom_Surface) Surf = BRep_Tool::Surface(myface);
217   Handle(Geom_Surface) Surf1;
218
219   if (!Surf.IsNull()) {
220     Standard_Real U1, U2, V1, V2;
221     // pour limiter les surfaces de base
222     BRepTools::UVBounds(myface, U1, U2, V1, V2);  
223     GeomToIGES_GeomSurface GS;
224     GS.SetModel(GetModel());
225     ISurf = GS.TransferSurface(Surf, U1, U2, V1, V2);
226     if (ISurf.IsNull()) {
227       AddWarning (start, "the basic surface is a null entity");
228       return res;
229     }
230     Length = GS.Length();
231
232     // modif mjm du 17/07/97
233     if (Surf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { 
234       DeclareAndCast(Geom_RectangularTrimmedSurface, rectang, Surf);
235       Surf1 = rectang->BasisSurface();
236     }
237     else 
238       Surf1 = Surf;
239   }
240
241
242   // returns the wires of the face
243   // -----------------------------
244
245   BRepToIGES_BRWire BW(*this);
246   Standard_Integer Imode = 0; 
247   Standard_Integer Iprefer = 0; 
248   Handle(IGESData_IGESEntity) ICurve2d;
249
250   // outer wire
251   //:n3  TopoDS_Wire Outer = BRepTools::OuterWire(myface);
252   TopoDS_Wire Outer = ShapeAlgo::AlgoContainer()->OuterWire(myface); //:n3 
253   Handle(IGESGeom_CurveOnSurface) IOuter = new IGESGeom_CurveOnSurface;
254   if (!Outer.IsNull()) {
255     Handle(IGESData_IGESEntity) ICurve3d = 
256       BW.TransferWire(Outer, myface, ICurve2d, Length);
257     if ((!ICurve3d.IsNull()) && (!ICurve2d.IsNull())) Iprefer = 3; 
258     if ((!ICurve3d.IsNull()) && (ICurve2d.IsNull())) Iprefer = 2; 
259     if ((ICurve3d.IsNull()) && (!ICurve2d.IsNull())) Iprefer = 1; 
260     IOuter -> Init (Imode, ISurf, ICurve2d, ICurve3d, Iprefer);
261   }
262
263   // inners wires
264   TopExp_Explorer Ex;
265   Handle(TColStd_HSequenceOfTransient) Seq = new TColStd_HSequenceOfTransient();
266
267   for (Ex.Init(myface,TopAbs_WIRE); Ex.More(); Ex.Next()) {
268     TopoDS_Wire W = TopoDS::Wire(Ex.Current());
269     Handle(IGESGeom_CurveOnSurface) Curve = new IGESGeom_CurveOnSurface;
270     if (W.IsNull()) {
271       AddWarning(start," an Wire is a null entity");
272     }
273     else if (!W.IsSame(Outer)) {
274       Handle(IGESData_IGESEntity) ICurve3d = 
275               BW.TransferWire(W, myface, ICurve2d, Length);
276       if ((!ICurve3d.IsNull()) && (!ICurve2d.IsNull())) Iprefer = 3; 
277       if ((!ICurve3d.IsNull()) && (ICurve2d.IsNull())) Iprefer = 2; 
278       if ((ICurve3d.IsNull()) && (!ICurve2d.IsNull())) Iprefer = 1; 
279       Curve-> Init (Imode, ISurf, ICurve2d, ICurve3d, Iprefer);
280       if (!Curve.IsNull()) Seq->Append(Curve);
281     }
282   }
283
284   // all inners edges not in a wire
285   for (Ex.Init(myface,TopAbs_EDGE,TopAbs_WIRE); Ex.More(); Ex.Next()) {
286     TopoDS_Edge E = TopoDS::Edge(Ex.Current());
287     Handle(IGESGeom_CurveOnSurface) Curve = new IGESGeom_CurveOnSurface;
288     if (E.IsNull()) {
289       AddWarning(start," an Edge is a null entity");
290     }
291     else {
292       Handle(IGESData_IGESEntity) ICurve3d = BW.TransferEdge(E, Standard_False);
293       Handle(IGESData_IGESEntity) newICurve2d = BW.TransferEdge(E, myface, Length, Standard_False);
294       if ((!ICurve3d.IsNull()) && (!newICurve2d.IsNull())) Iprefer = 3; 
295       if ((!ICurve3d.IsNull()) && (newICurve2d.IsNull())) Iprefer = 2; 
296       if ((ICurve3d.IsNull()) && (!newICurve2d.IsNull())) Iprefer = 1; 
297       Curve-> Init (Imode, ISurf, newICurve2d, ICurve3d, Iprefer);
298       if (!Curve.IsNull()) Seq->Append(Curve);
299     }
300   }
301
302
303   Standard_Integer nbent = Seq->Length();
304   Handle(IGESGeom_HArray1OfCurveOnSurface) Tab;
305   if (nbent >=1) {
306     Tab = new IGESGeom_HArray1OfCurveOnSurface(1,nbent);
307     for (Standard_Integer itab = 1; itab <= nbent; itab++) {
308       Handle(IGESGeom_CurveOnSurface) item = GetCasted(IGESGeom_CurveOnSurface, Seq->Value(itab));
309       Tab->SetValue(itab,item);
310     }
311   }
312
313   // protection against faces on infinite surfaces with mistaken natural restriction flag
314   Standard_Boolean isWholeSurface = BRep_Tool::NaturalRestriction(start);
315   if ((Surf->IsKind(STANDARD_TYPE(Geom_Plane)) ||
316        Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
317        Surf->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) && !IOuter.IsNull())
318     isWholeSurface = Standard_False;
319   // returns the TrimmedSurface
320   // --------------------------
321   Handle(IGESGeom_TrimmedSurface) TrimmedSurf = new IGESGeom_TrimmedSurface;
322   if (isWholeSurface) {
323     //if face bounds and surface bounds are same, outer wire is unnecessary
324     TrimmedSurf-> Init (ISurf, Standard_False, NULL, Tab);
325   }
326   else
327     TrimmedSurf-> Init (ISurf, Standard_True, IOuter, Tab);
328
329   res = TrimmedSurf;
330   SetShapeResult ( start, res );
331   return res;
332 }
333
334
335 //=============================================================================
336 // TransferShell
337 //=============================================================================
338
339 Handle(IGESData_IGESEntity) BRepToIGES_BRShell::TransferShell(const TopoDS_Shell& start,
340                                                               const Message_ProgressRange& theProgress)
341 {
342   Handle(IGESData_IGESEntity) res;
343   if ( start.IsNull()) return res;
344
345   TopExp_Explorer Ex;
346   Handle(IGESBasic_Group) IGroup = new IGESBasic_Group;
347   Handle(TColStd_HSequenceOfTransient) Seq = new TColStd_HSequenceOfTransient();
348   Handle(IGESData_IGESEntity) IFace;
349
350   Standard_Integer nbshapes = 0;
351   for (Ex.Init(start, TopAbs_FACE); Ex.More(); Ex.Next())
352     nbshapes++;
353   Message_ProgressScope aPS(theProgress, NULL, nbshapes);
354   for (Ex.Init(start,TopAbs_FACE); Ex.More() && aPS.More(); Ex.Next())
355   {
356     Message_ProgressRange aRange = aPS.Next();
357     TopoDS_Face F = TopoDS::Face(Ex.Current());
358     if (F.IsNull()) {
359       AddWarning(start," a Face is a null entity");
360     }
361     else {
362       IFace = TransferFace (F, aRange);
363       if (!IFace.IsNull()) Seq->Append(IFace);
364     }
365   }
366
367
368   Standard_Integer nbfaces = Seq->Length();  
369   Handle(IGESData_HArray1OfIGESEntity) Tab;
370   if ( nbfaces >= 1) {
371     Tab = new IGESData_HArray1OfIGESEntity(1,nbfaces);
372     for (Standard_Integer itab = 1; itab <= nbfaces; itab++) {
373       Handle(IGESData_IGESEntity) item = GetCasted(IGESData_IGESEntity, Seq->Value(itab));
374       Tab->SetValue(itab,item);
375     }
376   }
377
378   if (nbfaces == 1) {
379     res = IFace;
380   }
381   else {
382     IGroup->Init(Tab);
383     res = IGroup;
384   }
385
386   SetShapeResult ( start, res );
387
388   return res;
389 }
390
391
392
393