0026419: [Regression?] Export of a reversed face leads to crash in 6.9.0 although...
[occt.git] / src / BRepToIGES / BRepToIGES_BRShell.cxx
CommitLineData
b311480e 1// Created on: 1995-01-30
2// Created by: Marie Jose MARTZ
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
7fd59977 17//:n3 abv 8 Feb 99: PRO17820: BRepTools::OuterWire() -> ShapeAnalysis::OuterWire
18//szv#4 S4163
19
2157cfd0 20#include <BRep_Builder.hxx>
7fd59977 21#include <BRep_Tool.hxx>
42cf5bc1 22#include <BRepToIGES_BREntity.hxx>
23#include <BRepToIGES_BRShell.hxx>
24#include <BRepToIGES_BRWire.hxx>
7fd59977 25#include <BRepTools.hxx>
42cf5bc1 26#include <Geom2d_Curve.hxx>
7fd59977 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>
7fd59977 34#include <GeomToIGES_GeomSurface.hxx>
42cf5bc1 35#include <gp.hxx>
36#include <gp_Trsf.hxx>
7fd59977 37#include <IGESBasic_Group.hxx>
38#include <IGESData_HArray1OfIGESEntity.hxx>
39#include <IGESData_IGESEntity.hxx>
7fd59977 40#include <IGESGeom_CurveOnSurface.hxx>
41#include <IGESGeom_HArray1OfCurveOnSurface.hxx>
7fd59977 42#include <IGESGeom_SurfaceOfRevolution.hxx>
42cf5bc1 43#include <IGESGeom_TrimmedSurface.hxx>
7fd59977 44#include <Interface_Macros.hxx>
42cf5bc1 45#include <Message_ProgressIndicator.hxx>
2157cfd0 46#include <NCollection_IncAllocator.hxx>
42cf5bc1 47#include <NCollection_Map.hxx>
48#include <ShapeAlgo.hxx>
49#include <ShapeAlgo_AlgoContainer.hxx>
7fd59977 50#include <TColStd_HSequenceOfTransient.hxx>
42cf5bc1 51#include <TopAbs_ShapeEnum.hxx>
52#include <TopExp.hxx>
53#include <TopExp_Explorer.hxx>
7fd59977 54#include <TopLoc_Location.hxx>
7fd59977 55#include <TopoDS.hxx>
7fd59977 56#include <TopoDS_Edge.hxx>
57#include <TopoDS_Face.hxx>
42cf5bc1 58#include <TopoDS_Shape.hxx>
7fd59977 59#include <TopoDS_Shell.hxx>
42cf5bc1 60#include <TopoDS_Vertex.hxx>
7fd59977 61#include <TopoDS_Wire.hxx>
42cf5bc1 62#include <TopTools_ShapeMapHasher.hxx>
7fd59977 63#include <Transfer_FinderProcess.hxx>
64
65//=============================================================================
66// BRepToIGES_BRShell
67//=============================================================================
7fd59977 68BRepToIGES_BRShell::BRepToIGES_BRShell()
69{
70}
71
72
73//=============================================================================
74// BRepToIGES_BRShell
75//=============================================================================
76
77BRepToIGES_BRShell::BRepToIGES_BRShell
78(const BRepToIGES_BREntity& BR)
79: BRepToIGES_BREntity(BR)
80{
81}
82
83
84//=============================================================================
85// TransferShell
86//=============================================================================
87
88Handle(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
114Handle(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 }
2157cfd0 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);
eeec0986 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 }
2157cfd0 143 aSurf = aSurf->UReversed();
2157cfd0 144 Standard_Real aTol = BRep_Tool::Tolerance(start);
145 B.MakeFace(myface, aSurf, aLoc ,aTol);
146 // set specifics flags of a Face
eeec0986 147 B.NaturalRestriction(myface, BRep_Tool::NaturalRestriction(start));
2157cfd0 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 }
eeec0986 164
2157cfd0 165 // mirror pcurves
eeec0986 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);
2157cfd0 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);
2157cfd0 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));
eeec0986 189 if (anEdge.Orientation() == TopAbs_FORWARD)
190 B.UpdateEdge(anEdge, aCurve1, aCurve2, myface, aTol);
191 else
192 B.UpdateEdge(anEdge, aCurve2, aCurve1, myface, aTol);
2157cfd0 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
7fd59977 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
2157cfd0 215 Handle(Geom_Surface) Surf = BRep_Tool::Surface(myface);
7fd59977 216 Handle(Geom_Surface) Surf1;
217
218 if (!Surf.IsNull()) {
219 Standard_Real U1, U2, V1, V2;
220 // pour limiter les surfaces de base
2157cfd0 221 BRepTools::UVBounds(myface, U1, U2, V1, V2);
7fd59977 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;
7fd59977 248
249 // outer wire
2157cfd0 250 //:n3 TopoDS_Wire Outer = BRepTools::OuterWire(myface);
7fd59977 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 =
2157cfd0 274 BW.TransferWire(W, myface, ICurve2d, Length);
7fd59977 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 // --------------------------
7fd59977 314 Handle(IGESGeom_TrimmedSurface) TrimmedSurf = new IGESGeom_TrimmedSurface;
fdabc211 315 if (BRep_Tool::NaturalRestriction(start)) {
316 //if face bounds and surface bounds are same, outer wire is unnecessary
51740958 317 TrimmedSurf-> Init (ISurf, Standard_False, NULL, Tab);
fdabc211 318 }
319 else
51740958 320 TrimmedSurf-> Init (ISurf, Standard_True, IOuter, Tab);
7fd59977 321
322 res = TrimmedSurf;
7fd59977 323 SetShapeResult ( start, res );
7fd59977 324 return res;
325}
326
327
328//=============================================================================
329// TransferShell
330//=============================================================================
331
332Handle(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