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