0026138: Problems with writing periodic BSplines into IGES
[occt.git] / src / BRepToIGES / BRepToIGES_BRWire.cxx
1 // Created on: 1995-01-27
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 //:q4 abv 16.03.99: PRO17828 face 555: transform pcurves on SurfaceOfRevolution
18 //szv#4 S4163
19 //S4181 pdn implementing of writing IGES elementary surfaces.
20
21 #include <BRepToIGES_BRWire.ixx>
22
23 #include <BRep_Tool.hxx>
24 #include <BRepTools.hxx>
25 #include <BRepTools_WireExplorer.hxx>
26
27 #include <gp.hxx>
28 #include <gp_Ax2d.hxx>
29 #include <gp_Dir2d.hxx>
30 #include <gp_Pln.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <gp_Trsf.hxx>
33 #include <gp_Trsf2d.hxx>
34
35 #include <Geom_BSplineSurface.hxx>
36 #include <Geom_CartesianPoint.hxx>
37 #include <Geom_ConicalSurface.hxx>
38 #include <Geom_Curve.hxx>
39 #include <Geom_CylindricalSurface.hxx>
40 #include <Geom_Plane.hxx>
41 #include <Geom_RectangularTrimmedSurface.hxx>
42 #include <Geom_SphericalSurface.hxx>
43 #include <Geom_Surface.hxx>
44 #include <Geom_SurfaceOfLinearExtrusion.hxx>
45 #include <Geom_SurfaceOfRevolution.hxx>
46 #include <Geom_ToroidalSurface.hxx>
47 #include <Geom_TrimmedCurve.hxx>
48
49 #include <Geom2d_Curve.hxx>
50 #include <Geom2d_Line.hxx>
51
52 #include <GeomToIGES_GeomPoint.hxx>
53 #include <GeomToIGES_GeomCurve.hxx>
54
55 #include <Geom2dToIGES_Geom2dCurve.hxx>
56
57 #include <IGESData_HArray1OfIGESEntity.hxx>
58 #include <IGESData_IGESEntity.hxx>
59 #include <IGESData_IGESModel.hxx>
60
61 #include <IGESGeom_CompositeCurve.hxx>
62 #include <IGESGeom_Point.hxx>
63
64 #include <Interface_Macros.hxx>
65
66 #include <Precision.hxx>
67
68 #include <ShapeAnalysis.hxx>
69
70 #include <TColStd_HSequenceOfTransient.hxx>
71
72 #include <TopoDS.hxx>
73 #include <TopoDS_Vertex.hxx>
74 #include <TopoDS_Edge.hxx>
75 #include <TopoDS_Wire.hxx>
76 #include <TopoDS_Shape.hxx>
77
78 #include <TopAbs_ShapeEnum.hxx>
79 #include <TopAbs_Orientation.hxx>
80 #include <TopExp.hxx>
81 #include <TopExp_Explorer.hxx>
82 #include <Interface_Static.hxx>
83 #include <ShapeBuild_Edge.hxx>
84 #include <Geom_OffsetSurface.hxx>
85 #include <ShapeExtend_WireData.hxx>
86 #include <ShapeFix_Wire.hxx>
87
88
89 //=============================================================================
90 // BRepToIGES_BRWire
91 //=============================================================================
92
93 BRepToIGES_BRWire::BRepToIGES_BRWire()
94 {
95 }
96
97
98 //=============================================================================
99 // BRepToIGES_BRWire
100 //=============================================================================
101
102 BRepToIGES_BRWire::BRepToIGES_BRWire
103 (const BRepToIGES_BREntity& BR)
104 : BRepToIGES_BREntity(BR)
105 {
106 }
107
108
109 //=============================================================================
110 // TransferWire
111 //=============================================================================
112
113 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferWire
114 (const TopoDS_Shape& start)
115 {
116   Handle(IGESData_IGESEntity) res;
117
118   if (start.IsNull())  return  res;
119
120   if (start.ShapeType() == TopAbs_VERTEX) {
121     TopoDS_Vertex V =  TopoDS::Vertex(start);
122     res = TransferVertex(V);
123   }  
124   else if (start.ShapeType() == TopAbs_EDGE) {
125     TopoDS_Edge E =  TopoDS::Edge(start);
126     res = TransferEdge(E, Standard_False);
127   }  
128   else if (start.ShapeType() == TopAbs_WIRE) {
129     TopoDS_Wire W =  TopoDS::Wire(start);
130     res = TransferWire(W);
131   }  
132   else {
133     // error message
134   }  
135   return res;
136 }
137
138
139 //=============================================================================
140 // TransferVertex
141 // 
142 //=============================================================================
143
144 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferVertex
145 (const TopoDS_Vertex& myvertex)
146 {
147   Handle(IGESData_IGESEntity) res;
148   if ( myvertex.IsNull()) return res;
149
150   Handle(Geom_CartesianPoint) Point;
151   Point = new Geom_CartesianPoint(BRep_Tool::Pnt(myvertex));
152   Handle(IGESData_IGESEntity) IVertex;
153   if (!Point.IsNull()) {
154     GeomToIGES_GeomPoint GP;
155     GP.SetModel(GetModel());
156     IVertex = GP.TransferPoint(Point);
157   }
158
159   if (!IVertex.IsNull()) res = IVertex;
160   return res;
161 }
162
163
164 //=============================================================================
165 // TransferVertex
166 // 
167 //=============================================================================
168
169 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferVertex
170 (const TopoDS_Vertex& myvertex,
171  const TopoDS_Edge&   myedge,
172  Standard_Real&       parameter)
173 {
174   Handle(IGESData_IGESEntity) res;
175   if ( myvertex.IsNull()) return res;
176
177   Handle(IGESData_IGESEntity) IVertex = TransferVertex(myvertex);
178
179   // returns the parameter of myvertex on myedge
180   parameter = BRep_Tool::Parameter(myvertex,myedge);
181
182   if (!IVertex.IsNull()) res = IVertex;
183   return res;
184 }
185
186
187 //=============================================================================
188 // TransferVertex
189 // 
190 //=============================================================================
191
192 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferVertex
193 (const TopoDS_Vertex& myvertex,
194  const TopoDS_Edge&   myedge,
195  const TopoDS_Face&   myface,
196  Standard_Real&       parameter)
197 {
198   Handle(IGESData_IGESEntity) res;
199   if ( myvertex.IsNull()) return res;
200
201   Handle(IGESData_IGESEntity) IVertex = TransferVertex(myvertex);
202
203   // returns the parameter of myvertex on the pcurve of myedge on myface
204   parameter = BRep_Tool::Parameter(myvertex, myedge, myface);
205
206   if (!IVertex.IsNull()) res = IVertex;
207   return res;
208 }
209
210
211 //=============================================================================
212 // TransferVertex
213 // 
214 //=============================================================================
215
216 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferVertex
217 (const TopoDS_Vertex&          myvertex,
218  const TopoDS_Edge&            myedge,
219  const Handle(Geom_Surface)&   mysurface,
220  const TopLoc_Location&        myloc,
221  Standard_Real&                parameter)
222 {
223   Handle(IGESData_IGESEntity) res;
224   if ( myvertex.IsNull()) return res;
225
226   Handle(IGESData_IGESEntity) IVertex = TransferVertex(myvertex);
227
228   // returns the parameter of myvertex on the pcurve of myedge on mysurface
229   parameter = BRep_Tool::Parameter(myvertex, myedge, mysurface, myloc);
230
231   if (!IVertex.IsNull()) res = IVertex;
232   return res;
233 }
234
235
236 //=============================================================================
237 // TransferVertex
238 // 
239 //=============================================================================
240
241 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferVertex
242 (const TopoDS_Vertex& myvertex,
243  const TopoDS_Face&   myface,
244        gp_Pnt2d&      mypoint)
245 {
246   Handle(IGESData_IGESEntity) res;
247   if ( myvertex.IsNull()) return res;
248
249   Handle(IGESData_IGESEntity) IVertex = TransferVertex(myvertex);
250
251   // returns the parameter of myvertex on myface
252   mypoint = BRep_Tool::Parameters(myvertex, myface);
253
254   if (!IVertex.IsNull()) res = IVertex;
255   return res;
256 }
257
258
259 //=============================================================================
260 // TransferEdge
261 //=============================================================================
262
263 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferEdge
264 (const TopoDS_Edge&     myedge,
265  const Standard_Boolean isBRepMode)
266 {
267   Handle(IGESData_IGESEntity) res;
268   if ( myedge.IsNull()) return res;
269
270   // returns the 3d curve of the edge and the parameter range
271   TopLoc_Location L;
272   Standard_Real First, Last, U1, U2;
273   Handle(IGESData_IGESEntity) ICurve;
274   Handle(Geom_Curve) Curve3d = BRep_Tool::Curve(myedge, L, First, Last);
275
276   //#28 rln 19.10.98 UKI60155, etc.
277   //Only Bezier will be converted into B-Spline, not Conic. This conertation
278   //will be done only inside GeomToIGES package for simplifying the code.
279
280   //#29 rln 19.10.98
281   //Unnecessary duplication of curves is removed.
282
283   if (!Curve3d.IsNull()) {
284     gp_Trsf Tr = L.Transformation();
285     if (Tr.Form() != gp_Identity)
286       Curve3d = Handle(Geom_Curve)::DownCast(Curve3d->Transformed (Tr));
287     else
288       Curve3d = Handle(Geom_Curve)::DownCast(Curve3d->Copy()); 
289
290     if (myedge.Orientation() == TopAbs_REVERSED && !isBRepMode) {
291       U1 = Curve3d->ReversedParameter(Last);
292       U2 = Curve3d->ReversedParameter(First);
293       Curve3d->Reverse();
294     }
295     else {
296       U1 = First;
297       U2 = Last;
298     }
299
300     GeomToIGES_GeomCurve GC;
301     GC.SetModel(GetModel());
302     ICurve = GC.TransferCurve(Curve3d, U1, U2);
303   }
304
305   //#31 rln 19.10.98
306   //Vertices are not translated into IGES anymore since they are not put into
307   //the model
308
309   if (!ICurve.IsNull()) res = ICurve;
310
311   SetShapeResult ( myedge, res );
312
313   return res;
314 }
315
316
317 //=============================================================================
318 // TransferEdge
319 //=============================================================================
320
321 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferEdge (const TopoDS_Edge& myedge,
322                                                               const TopoDS_Face& myface,
323                                                               const Standard_Real length,
324                                                               const Standard_Boolean isBRepMode)
325 {
326   Handle(IGESData_IGESEntity) res;
327   if ( myedge.IsNull() || GetPCurveMode() ==0 ||
328        ( ! isBRepMode && BRep_Tool::Degenerated ( myedge ) ) ) return res;
329
330   //S4181 pdn 23.04.99 adjusting length factor according to analytic mode.
331   Standard_Real myLen = length;
332   Standard_Boolean analyticMode = ( GetConvertSurfaceMode() ==0 && isBRepMode );
333   
334   // returns the 2d curve associated to myedge in the parametric space of myface
335   Standard_Real First, Last;
336   Handle(Geom2d_Curve) Curve2d = BRep_Tool::CurveOnSurface(myedge, myface, First, Last);
337   Handle(IGESData_IGESEntity) ICurve2d;
338   //#29 rln 19.10.98
339
340   if (!Curve2d.IsNull()) {
341     // For "revolution" and "LinearExtrusion" surfaces, it is necessary
342     // to apply a translation of 2D curves to agree on the 
343     // origin (U,V) between IGES and BRep (for Cylindrical,
344     // Conical and SurfaceOfLinearExtrusion)
345     // It is necessary to invert (u,v) surfaces of revolution.
346     
347     TopLoc_Location L;
348     Handle(Geom_Surface) st = BRep_Tool::Surface(myface, L);
349     if (st->IsKind(STANDARD_TYPE(Geom_Plane))){
350       return res;
351     }
352     Standard_Real Ufirst, Ulast, Vfirst, Vlast;
353     BRepTools::UVBounds(myface, Ufirst, Ulast, Vfirst, Vlast);
354     Handle(Geom_Surface) Surf;
355
356     if (st->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { 
357       DeclareAndCast(Geom_RectangularTrimmedSurface, rectang, st);
358       Surf = rectang->BasisSurface();
359     }
360     else 
361       Surf = st;
362
363     //:abv 19.06.02: writing (loopback) on file offseted_sphere.rle in BRep mode
364     if (st->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) { 
365       DeclareAndCast(Geom_OffsetSurface, offset, Surf);
366       Surf = offset->BasisSurface();
367     }
368
369     //S4181 pdn 20.04.99 transformation of pcurves id defined by type of surface 
370     // and analytic mode.
371     // skl 18.07.2005 for OCC9490 : in following if() commented
372     // condition for SurfaceOfLinearExtrusion
373     Standard_Boolean needShift = (!analyticMode&&
374                                   ((Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) ||
375                                    (Surf->IsKind(STANDARD_TYPE(Geom_ConicalSurface)))/* ||
376                                    (Surf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)))*/));
377     //:q4 abv 16 Mar 99: PRO17828 face 555: shift pcurves on SurfaceOfRevolution
378     if (Surf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) { 
379       Handle(Geom_SurfaceOfRevolution) rev = 
380         Handle(Geom_SurfaceOfRevolution)::DownCast ( Surf );
381       Handle(Geom_Curve) curve = rev->BasisCurve();
382       // skl 31.05.2004 for OCC6004
383       if(curve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
384         Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(curve);
385         curve = tc->BasisCurve();
386       }
387       if ( curve->IsKind(STANDARD_TYPE(Geom_Line)) ) needShift = Standard_True;
388     }
389     if ( needShift ) {
390       gp_Trsf2d TR;
391       TR.SetTranslation(gp_Pnt2d(0.,0.),gp_Pnt2d(0.,-Vfirst)); 
392       Curve2d = Handle(Geom2d_Curve)::DownCast(Curve2d->Transformed(TR));
393     }
394     else Curve2d = Handle(Geom2d_Curve)::DownCast(Curve2d->Copy());
395
396     //shift pcurves on periodic BSpline surfaces (issue 26138)
397     if (Surf->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
398       Handle(Geom_BSplineSurface) aBSpline = Handle(Geom_BSplineSurface)::DownCast(Surf);
399       Standard_Real uShift = 0., vShift = 0.;
400       Standard_Real U0, U1, V0, V1;
401       Surf->Bounds(U0, U1, V0, V1);
402       if (aBSpline->IsUPeriodic() && Abs(Ufirst - U0) > Precision::PConfusion()) {
403         uShift = ShapeAnalysis::AdjustToPeriod(Ufirst, U0, U1);
404       }
405       if (aBSpline->IsVPeriodic() && Abs(Vfirst - V0) > Precision::PConfusion()) {
406         vShift = ShapeAnalysis::AdjustToPeriod(Vfirst, V0, V1);
407       }
408       if (Abs(uShift) > Precision::PConfusion() || Abs(vShift) > Precision::PConfusion()) {
409         gp_Trsf2d TR;
410         TR.SetTranslation(gp_Pnt2d(0.,0.),gp_Pnt2d(uShift,vShift));
411         Curve2d = Handle(Geom2d_Curve)::DownCast(Curve2d->Transformed(TR));
412       }
413     }
414
415     if (!analyticMode&&((Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)))  ||
416                         (Surf->IsKind(STANDARD_TYPE(Geom_ConicalSurface)))      ||
417                         (Surf->IsKind(STANDARD_TYPE(Geom_SphericalSurface))))) {
418       //#30 rln 19.10.98 transformation of pcurves for IGES Surface of Revolution
419       Curve2d->Mirror (gp_Ax2d (gp::Origin2d(), gp_Dir2d (1.,1.)));
420       Curve2d->Mirror (gp::OX2d());
421       Curve2d->Translate (gp_Vec2d (0, 2 * M_PI));
422     }
423     
424     if(Surf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))||
425        (Surf->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)))){
426       Curve2d->Mirror (gp_Ax2d (gp::Origin2d(), gp_Dir2d (1.,1.)));
427       Curve2d->Mirror (gp::OX2d());
428       Curve2d->Translate (gp_Vec2d (0, 2 * M_PI));
429     }
430     
431     if (analyticMode&&(Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
432                        Surf->IsKind(STANDARD_TYPE(Geom_ConicalSurface))))
433       myLen = M_PI/180.;
434     
435     if (analyticMode&&(Surf->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
436                        Surf->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)))) {
437       gp_Trsf2d trans;
438       trans.SetScale(gp_Pnt2d(0,0),180./M_PI);
439       Curve2d->Transform(trans);
440       First = Curve2d->TransformedParameter(First,trans);
441       Last  = Curve2d->TransformedParameter(Last, trans);
442     }
443     
444     if (analyticMode&&(Surf->IsKind(STANDARD_TYPE(Geom_ConicalSurface)))) {
445       Handle(Geom_ConicalSurface) con = Handle(Geom_ConicalSurface)::DownCast ( Surf );
446       if(con->SemiAngle() < 0) {
447         Standard_Real vApex = 2 * con->RefRadius() / Sin (con->SemiAngle());
448         Curve2d->Translate (gp_Vec2d (0, vApex));
449       }
450     }
451     //S4181 transfer functionality
452     gp_Trsf2d trans;
453     Standard_Real uFact = 1.;
454     if(isBRepMode && Surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
455       trans.SetScale(gp_Pnt2d(0,0),1./GetUnit());
456     }
457     if(Surf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
458       Standard_Real aDiv = myLen;
459       if(aDiv < gp::Resolution())
460         aDiv = 1.;
461       //emv: changed for bug OCC22126 17.12.2010
462       trans.SetScale(gp_Pnt2d(0,0), 1. / (Vlast - Vfirst));
463       //uFact = myLen; 
464       
465       //added by skl 18.07.2005 for OCC9490
466 //      trans.SetScale(gp_Pnt2d(0,0),1./Vlast);
467
468       Standard_Real du = 1.;
469       Standard_Real us1,us2,vs1,vs2;
470       //scaling parameterization to [0,1]
471       Surf->Bounds(us1,us2,vs1,vs2);
472       du = us2-us1;
473       //emv: changed for bug OCC22126 17.12.2010
474       uFact = (Vlast - Vfirst)/du;
475       //uFact = aDiv/du;
476     }
477     if (Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
478         Surf->IsKind(STANDARD_TYPE(Geom_ConicalSurface)) ||
479         Surf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) { //:q4
480       uFact = 1./myLen; 
481     }
482     
483     ShapeBuild_Edge sbe;
484     Curve2d = sbe.TransformPCurve(Curve2d,trans,uFact,First,Last);
485 //      (Curve2d, Surf, First, Last, myLen, isBRepMode);
486     // if the edge is REVERSED, it is necessary to "REVERSE" the curve 2d.
487
488     // added by skl 18.07.2005 for OCC9490
489     if(Surf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
490       //emv: changed for bug OCC22126 17.12.2010
491       gp_Trsf2d trans1;
492       Standard_Real us1,us2,vs1,vs2,du;
493       //computing shift of pcurves
494       Surf->Bounds(us1,us2,vs1,vs2);
495       du = us2-us1;
496       trans1.SetTranslation(gp_Vec2d(-us1/du,-Vfirst/(Vlast-Vfirst)));
497       Curve2d = sbe.TransformPCurve(Curve2d,trans1,1.,First,Last);
498     }
499
500     if (myedge.Orientation() == TopAbs_REVERSED) {
501       Standard_Real tmpFirst = Curve2d->ReversedParameter(Last),
502                     tmpLast  = Curve2d->ReversedParameter(First);
503       Curve2d->Reverse();
504       First = tmpFirst;
505       Last  = tmpLast;
506     }
507     Geom2dToIGES_Geom2dCurve GC;
508     GC.SetModel(GetModel());
509     ICurve2d = GC.Transfer2dCurve(Curve2d, First, Last);
510   }
511
512   //#31 rln 19.10.98
513   //Vertices are not translated into IGES anymore since they are not put into
514   //the model
515
516   if (!ICurve2d.IsNull()) res = ICurve2d;
517
518   SetShapeResult ( myedge, res );
519
520   return res;
521 }
522
523
524 //=============================================================================
525 // TransferWire
526 //=============================================================================
527
528 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferWire
529 (const TopoDS_Wire& mywire)
530 {
531   Handle(IGESData_IGESEntity) res;
532   if ( mywire.IsNull()) return res;
533
534   //A composite curve is defined as an ordered list of entities
535   //consisting of a point, connect point and parametrised curve
536   //entities (excluding the CompositeCurve entity).
537
538   Handle(IGESData_IGESEntity) ent ;
539   Handle(TColStd_HSequenceOfTransient) Seq = new TColStd_HSequenceOfTransient();
540
541   TopExp_Explorer TE(mywire, TopAbs_VERTEX);
542   if ( TE.More()) {
543     BRepTools_WireExplorer WE;
544     for ( WE.Init(mywire); WE.More(); WE.Next()) {
545       TopoDS_Edge E = WE.Current();
546       if (E.IsNull()) {
547         AddWarning(mywire, "an Edge is a null entity");
548       }
549       else {
550               ent = TransferEdge(E, Standard_False);
551               if (!ent.IsNull()) Seq->Append(ent);
552       }
553     }
554   }
555   else 
556     AddWarning(mywire, " no Vertex associated to the Wire");
557   
558
559   Standard_Integer nbedges = Seq->Length();
560   Handle(IGESData_HArray1OfIGESEntity) Tab;
561   if ( nbedges == 1 ) {
562     res = GetCasted(IGESData_IGESEntity, Seq->Value(1));
563   }
564   else if ( nbedges >= 2) {
565     Tab =  new IGESData_HArray1OfIGESEntity(1,nbedges);
566     for (Standard_Integer itab = 1; itab <= nbedges; itab++) {
567       Handle(IGESData_IGESEntity) item = GetCasted(IGESData_IGESEntity, Seq->Value(itab));
568       Tab->SetValue(itab,item);
569     }
570     Handle(IGESGeom_CompositeCurve) Comp = new IGESGeom_CompositeCurve;
571     Comp->Init(Tab);
572     res = Comp;
573   }
574
575   SetShapeResult ( mywire, res );
576
577   return res;
578 }
579
580
581 //=============================================================================
582 // TransferWire
583 //=============================================================================
584
585 Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferWire
586 (const TopoDS_Wire &          mywire,
587  const TopoDS_Face &          myface,
588  Handle(IGESData_IGESEntity)& mycurve2d,
589  const Standard_Real          length)
590 {
591   Handle(IGESData_IGESEntity) res;
592   if ( mywire.IsNull()) return res;
593
594   Handle(IGESData_IGESEntity) ent3d ;
595   Handle(IGESData_IGESEntity) ent2d ;
596   Handle(TColStd_HSequenceOfTransient) Seq3d = new TColStd_HSequenceOfTransient();
597   Handle(TColStd_HSequenceOfTransient) Seq2d = new TColStd_HSequenceOfTransient();
598
599
600   // create a 3d CompositeCurve and a 2d CompositeCurve
601   TopExp_Explorer TE(mywire, TopAbs_VERTEX);
602   if ( TE.More()) {
603     // PTV OCC908 workaround for KAS:dev version
604     /*
605     BRepTools_WireExplorer WE;
606     for ( WE.Init(mywire,myface); WE.More(); WE.Next()) { 
607       TopoDS_Edge E = WE.Current();
608       if (E.IsNull()) {
609         AddWarning(mywire, "an Edge is a null entity");
610       }
611       else {
612         ent3d = TransferEdge(E, Standard_False);
613         if (!ent3d.IsNull()) Seq3d->Append(ent3d);
614         ent2d = TransferEdge(E, myface, length, Standard_False);
615         if (!ent2d.IsNull()) Seq2d->Append(ent2d);
616       }
617     }
618     */
619     Handle(ShapeFix_Wire) aSFW = 
620       new ShapeFix_Wire( mywire, myface, Precision::Confusion() );
621     aSFW->FixReorder();
622     Handle(ShapeExtend_WireData) aSEWD = aSFW->WireData();
623     Standard_Integer nbE = aSEWD->NbEdges();
624     for (Standard_Integer windex = 1; windex <= nbE; windex++) {
625       TopoDS_Edge E = aSEWD->Edge( windex );
626       if (E.IsNull()) {
627         AddWarning(mywire, "an Edge is a null entity");
628       }
629       else {
630         ent3d = TransferEdge(E, Standard_False);
631         if (!ent3d.IsNull()) Seq3d->Append(ent3d);
632         ent2d = TransferEdge(E, myface, length, Standard_False);
633         if (!ent2d.IsNull()) Seq2d->Append(ent2d);
634       }
635     }
636     // OCC908 end of workaround
637   }
638   else 
639     AddWarning(mywire, " no Vertex associated to the Wire");
640   
641   // Composite Curve 3D
642   Standard_Integer nb3d = Seq3d->Length();
643   Handle(IGESData_HArray1OfIGESEntity) Tab3d;
644   if ( nb3d == 1 ) {
645     res = ent3d;
646   }
647   else if (nb3d >= 2) {
648     Tab3d =  new IGESData_HArray1OfIGESEntity(1,nb3d);
649     //Standard_Integer tabval = nb3d; //szv#4:S4163:12Mar99 unused
650     for (Standard_Integer itab = 1; itab <= nb3d; itab++) {
651       Handle(IGESData_IGESEntity) item = 
652         GetCasted(IGESData_IGESEntity, Seq3d->Value(itab));
653       Tab3d->SetValue(itab,item);
654     }
655     Handle(IGESGeom_CompositeCurve) Comp = new IGESGeom_CompositeCurve;
656     Comp->Init(Tab3d);
657     res = Comp;
658   }
659
660   // Composite Curve 2D
661   Standard_Integer nb2d = Seq2d->Length();
662   Handle(IGESData_HArray1OfIGESEntity) Tab2d;
663   if ( nb2d == 1 ) {
664     mycurve2d = ent2d;
665   }
666   else if (nb2d >= 2) {
667     Tab2d =  new IGESData_HArray1OfIGESEntity(1,nb2d);
668     //Standard_Integer tabval = nb2d; //szv#4:S4163:12Mar99 unused
669     for ( Standard_Integer itab = 1; itab <= nb2d; itab++) {
670       Handle(IGESData_IGESEntity) item = 
671         GetCasted(IGESData_IGESEntity, Seq2d->Value(itab));
672       Tab2d->SetValue(itab,item);
673     }
674     Handle(IGESGeom_CompositeCurve) Comp = new IGESGeom_CompositeCurve;
675     Comp->Init(Tab2d);
676     mycurve2d = Comp;
677   }
678   
679   SetShapeResult ( mywire, res );
680
681   return res;
682 }