0031939: Coding - correction of spelling errors in comments [part 10]
[occt.git] / src / StepToGeom / StepToGeom.cxx
1 // Created on: 1993-06-15
2 // Created by: Martine LANGLOIS
3 // Copyright (c) 1993-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 <StepToGeom.hxx>
18
19 #include <BRep_Tool.hxx>
20 #include <BRepBuilderAPI_MakeFace.hxx>
21 #include <ElCLib.hxx>
22
23 #include <Geom_Axis1Placement.hxx>
24 #include <Geom_Axis2Placement.hxx>
25 #include <Geom_BoundedCurve.hxx>
26 #include <Geom_BoundedSurface.hxx>
27 #include <Geom_BSplineCurve.hxx>
28 #include <Geom_BSplineSurface.hxx>
29 #include <Geom_CartesianPoint.hxx>
30 #include <Geom_Circle.hxx>
31 #include <Geom_Conic.hxx>
32 #include <Geom_ConicalSurface.hxx>
33 #include <Geom_Curve.hxx>
34 #include <Geom_CylindricalSurface.hxx>
35 #include <Geom_Direction.hxx>
36 #include <Geom_ElementarySurface.hxx>
37 #include <Geom_Ellipse.hxx>
38 #include <Geom_Hyperbola.hxx>
39 #include <Geom_Line.hxx>
40 #include <Geom_OffsetCurve.hxx>
41 #include <Geom_OffsetSurface.hxx>
42 #include <Geom_Parabola.hxx>
43 #include <Geom_Plane.hxx>
44 #include <Geom_RectangularTrimmedSurface.hxx>
45 #include <Geom_SphericalSurface.hxx>
46 #include <Geom_Surface.hxx>
47 #include <Geom_SurfaceOfLinearExtrusion.hxx>
48 #include <Geom_SurfaceOfRevolution.hxx>
49 #include <Geom_SweptSurface.hxx>
50 #include <Geom_ToroidalSurface.hxx>
51 #include <Geom_TrimmedCurve.hxx>
52 #include <Geom_VectorWithMagnitude.hxx>
53
54 #include <Geom2d_AxisPlacement.hxx>
55 #include <Geom2d_BoundedCurve.hxx>
56 #include <Geom2d_BSplineCurve.hxx>
57 #include <Geom2d_CartesianPoint.hxx>
58 #include <Geom2d_Circle.hxx>
59 #include <Geom2d_Conic.hxx>
60 #include <Geom2d_Curve.hxx>
61 #include <Geom2d_Direction.hxx>
62 #include <Geom2d_Ellipse.hxx>
63 #include <Geom2d_Hyperbola.hxx>
64 #include <Geom2d_Line.hxx>
65 #include <Geom2d_Parabola.hxx>
66 #include <Geom2d_TrimmedCurve.hxx>
67 #include <Geom2d_VectorWithMagnitude.hxx>
68 #include <Geom2dConvert.hxx>
69
70 #include <gp_Trsf.hxx>
71 #include <gp_Trsf2d.hxx>
72 #include <gp_Lin.hxx>
73 #include <gp_Lin2d.hxx>
74
75 #include <ShapeAlgo.hxx>
76 #include <ShapeAlgo_AlgoContainer.hxx>
77 #include <ShapeAnalysis_Curve.hxx>
78
79 #include <StepGeom_Axis1Placement.hxx>
80 #include <StepGeom_Axis2Placement2d.hxx>
81 #include <StepGeom_Axis2Placement3d.hxx>
82 #include <StepGeom_BoundedCurve.hxx>
83 #include <StepGeom_BoundedSurface.hxx>
84 #include <StepGeom_BSplineCurve.hxx>
85 #include <StepGeom_CartesianPoint.hxx>
86 #include <StepGeom_Direction.hxx>
87
88 #include <Standard_ErrorHandler.hxx>
89 #include <Standard_Failure.hxx>
90
91 #include <StepGeom_BezierCurve.hxx>
92 #include <StepGeom_BezierSurface.hxx>
93 #include <StepGeom_BSplineSurface.hxx>
94 #include <StepGeom_BSplineCurveWithKnots.hxx>
95 #include <StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve.hxx>
96 #include <StepGeom_BSplineSurfaceWithKnots.hxx>
97 #include <StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface.hxx>
98 #include <StepGeom_Circle.hxx>
99 #include <StepGeom_Conic.hxx>
100 #include <StepGeom_ConicalSurface.hxx>
101 #include <StepGeom_Curve.hxx>
102 #include <StepGeom_CurveReplica.hxx>
103 #include <StepGeom_CylindricalSurface.hxx>
104 #include <StepGeom_ElementarySurface.hxx>
105 #include <StepGeom_Ellipse.hxx>
106 #include <StepGeom_Hyperbola.hxx>
107 #include <StepGeom_Line.hxx>
108 #include <StepGeom_OffsetCurve3d.hxx>
109 #include <StepGeom_OffsetSurface.hxx>
110 #include <StepGeom_Parabola.hxx>
111 #include <StepGeom_Plane.hxx>
112 #include <StepGeom_Polyline.hxx>
113 #include <StepGeom_QuasiUniformCurve.hxx>
114 #include <StepGeom_QuasiUniformCurveAndRationalBSplineCurve.hxx>
115 #include <StepGeom_QuasiUniformSurface.hxx>
116 #include <StepGeom_QuasiUniformSurfaceAndRationalBSplineSurface.hxx>
117 #include <StepGeom_RectangularTrimmedSurface.hxx>
118 #include <StepGeom_SphericalSurface.hxx>
119 #include <StepGeom_Surface.hxx>
120 #include <StepGeom_SurfaceCurve.hxx>
121 #include <StepGeom_SurfaceOfLinearExtrusion.hxx>
122 #include <StepGeom_SurfaceOfRevolution.hxx>
123 #include <StepGeom_SurfaceReplica.hxx>
124 #include <StepGeom_SweptSurface.hxx>
125 #include <StepGeom_ToroidalSurface.hxx>
126 #include <StepGeom_CartesianTransformationOperator2d.hxx>
127 #include <StepGeom_CartesianTransformationOperator3d.hxx>
128 #include <StepGeom_TrimmedCurve.hxx>
129 #include <StepGeom_UniformCurve.hxx>
130 #include <StepGeom_UniformCurveAndRationalBSplineCurve.hxx>
131 #include <StepGeom_UniformSurface.hxx>
132 #include <StepGeom_UniformSurfaceAndRationalBSplineSurface.hxx>
133 #include <StepGeom_Vector.hxx>
134
135 #include <TopoDS.hxx>
136 #include <TopoDS_Face.hxx>
137
138 #include <UnitsMethods.hxx>
139
140 //=============================================================================
141 // Creation d' un Ax1Placement de Geom a partir d' un axis1_placement de Step
142 //=============================================================================
143
144 Handle(Geom_Axis1Placement) StepToGeom::MakeAxis1Placement (const Handle(StepGeom_Axis1Placement)& SA)
145 {
146   Handle(Geom_CartesianPoint) P = MakeCartesianPoint (SA->Location());
147   if (! P.IsNull())
148   {
149     // sln 22.10.2001. CTS23496: If problems with creation of axis direction occur default direction is used
150     gp_Dir D(0.,0.,1.);
151     if (SA->HasAxis())
152     {
153       Handle(Geom_Direction) D1 = MakeDirection (SA->Axis());
154       if (! D1.IsNull())
155         D = D1->Dir();
156     }
157     return new Geom_Axis1Placement(P->Pnt(),D);
158   }
159   return 0;
160 }
161
162 //=============================================================================
163 // Creation d' un Axis2Placement de Geom a partir d' un axis2_placement_3d de Step
164 //=============================================================================
165
166 Handle(Geom_Axis2Placement) StepToGeom::MakeAxis2Placement (const Handle(StepGeom_Axis2Placement3d)& SA)
167 {
168   Handle(Geom_CartesianPoint) P = MakeCartesianPoint (SA->Location());
169   if (! P.IsNull())
170   {
171     const gp_Pnt Pgp = P->Pnt();
172
173     // sln 22.10.2001. CTS23496: If problems with creation of direction occur default direction is used (MakeLine(...) function)
174     gp_Dir Ngp(0.,0.,1.);
175     if (SA->HasAxis())
176     {
177       Handle(Geom_Direction) D = MakeDirection (SA->Axis());
178       if (! D.IsNull())
179         Ngp = D->Dir();
180     }
181
182     gp_Ax2 gpAx2;
183     Standard_Boolean isDefaultDirectionUsed = Standard_True;
184     if (SA->HasRefDirection())
185     {
186       Handle(Geom_Direction) D = MakeDirection (SA->RefDirection());
187       if (! D.IsNull())
188       {
189         const gp_Dir Vxgp = D->Dir();
190         if (!Ngp.IsParallel(Vxgp,Precision::Angular()))
191         {
192           gpAx2 = gp_Ax2(Pgp, Ngp, Vxgp);
193           isDefaultDirectionUsed = Standard_False;
194         }
195       }
196     }
197     if(isDefaultDirectionUsed)
198       gpAx2 = gp_Ax2(Pgp, Ngp);
199
200     return new Geom_Axis2Placement(gpAx2);
201   }
202   return 0;
203 }
204
205 //=============================================================================
206 // Creation d' un AxisPlacement de Geom2d a partir d' un axis2_placement_3d de Step
207 //=============================================================================
208
209 Handle(Geom2d_AxisPlacement) StepToGeom::MakeAxisPlacement (const Handle(StepGeom_Axis2Placement2d)& SA)
210 {
211   Handle(Geom2d_CartesianPoint) P = MakeCartesianPoint2d (SA->Location());
212   if (! P.IsNull())
213   {
214     // sln 23.10.2001. CTS23496: If problems with creation of direction occur default direction is used
215     gp_Dir2d Vxgp(1.,0.);
216     if (SA->HasRefDirection()) {
217       Handle(Geom2d_Direction) Vx = MakeDirection2d (SA->RefDirection());
218       if (! Vx.IsNull())
219         Vxgp = Vx->Dir2d();
220     }
221
222     return new Geom2d_AxisPlacement(P->Pnt2d(),Vxgp);
223   }
224   return 0;
225 }
226
227 //=============================================================================
228 // Creation d' une BoundedCurve de Geom a partir d' une BoundedCurve de Step
229 //=============================================================================
230
231 Handle(Geom_BoundedCurve) StepToGeom::MakeBoundedCurve (const Handle(StepGeom_BoundedCurve)& SC)
232 {
233   if (SC->IsKind(STANDARD_TYPE(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)))
234   {
235     return MakeBSplineCurve (Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)::DownCast(SC));
236   }
237   if (SC->IsKind(STANDARD_TYPE(StepGeom_BSplineCurveWithKnots)))
238   {
239     return MakeBSplineCurve (Handle(StepGeom_BSplineCurveWithKnots)::DownCast(SC));
240   }
241   if (SC->IsKind(STANDARD_TYPE(StepGeom_TrimmedCurve)))
242   {
243     return MakeTrimmedCurve (Handle(StepGeom_TrimmedCurve)::DownCast(SC));
244   }
245
246   // STEP BezierCurve, UniformCurve and QuasiUniformCurve are transformed into
247   // STEP BSplineCurve before being mapped onto CAS.CADE/SF
248   if (SC->IsKind(STANDARD_TYPE(StepGeom_BezierCurve)))
249   {
250     const Handle(StepGeom_BezierCurve) BzC = Handle(StepGeom_BezierCurve)::DownCast(SC);
251     Standard_Integer aDegree = BzC->Degree();
252     if (aDegree < 1 || aDegree > Geom_BSplineCurve::MaxDegree())
253       return 0;
254     const Handle(StepGeom_BSplineCurveWithKnots) BSPL = new StepGeom_BSplineCurveWithKnots;
255     BSPL->SetDegree(aDegree);
256     BSPL->SetControlPointsList(BzC->ControlPointsList());
257     BSPL->SetCurveForm(BzC->CurveForm());
258     BSPL->SetClosedCurve(BzC->ClosedCurve());
259     BSPL->SetSelfIntersect(BzC->SelfIntersect());
260     // Compute Knots and KnotsMultiplicity
261     const Handle(TColStd_HArray1OfInteger) Kmult = new TColStd_HArray1OfInteger(1,2);
262     const Handle(TColStd_HArray1OfReal) Knots = new TColStd_HArray1OfReal(1,2);
263     Kmult->SetValue(1, BzC->Degree() + 1);
264     Kmult->SetValue(2, BzC->Degree() + 1);
265     Knots->SetValue(1, 0.);
266     Knots->SetValue(2, 1.);
267     BSPL->SetKnotMultiplicities(Kmult);
268     BSPL->SetKnots(Knots);
269
270     return MakeBSplineCurve (BSPL);
271   }
272
273   if (SC->IsKind(STANDARD_TYPE(StepGeom_UniformCurve)))
274   {
275     const Handle(StepGeom_UniformCurve) UC = Handle(StepGeom_UniformCurve)::DownCast(SC);
276     Standard_Integer aDegree = UC->Degree();
277     if (aDegree < 1 || aDegree > Geom_BSplineCurve::MaxDegree())
278       return 0;
279     const Handle(StepGeom_BSplineCurveWithKnots) BSPL = new StepGeom_BSplineCurveWithKnots;
280     BSPL->SetDegree(aDegree);
281     BSPL->SetControlPointsList(UC->ControlPointsList());
282     BSPL->SetCurveForm(UC->CurveForm());
283     BSPL->SetClosedCurve(UC->ClosedCurve());
284     BSPL->SetSelfIntersect(UC->SelfIntersect());
285
286     // Compute Knots and KnotsMultiplicity
287     const Standard_Integer nbK = BSPL->NbControlPointsList() + BSPL->Degree() + 1;
288     const Handle(TColStd_HArray1OfInteger) Kmult = new TColStd_HArray1OfInteger(1,nbK);
289     const Handle(TColStd_HArray1OfReal) Knots = new TColStd_HArray1OfReal(1,nbK);
290     for (Standard_Integer iUC = 1 ; iUC <= nbK ; iUC ++) {
291       Kmult->SetValue(iUC, 1);
292       Knots->SetValue(iUC, iUC - 1.);
293     }
294     BSPL->SetKnotMultiplicities(Kmult);
295     BSPL->SetKnots(Knots);
296
297     return MakeBSplineCurve (BSPL);
298   }
299
300   if (SC->IsKind(STANDARD_TYPE(StepGeom_QuasiUniformCurve)))
301   {
302     const Handle(StepGeom_QuasiUniformCurve) QUC =
303       Handle(StepGeom_QuasiUniformCurve)::DownCast(SC);
304     Standard_Integer aDegree = QUC->Degree();
305     if (aDegree < 1 || aDegree > Geom_BSplineCurve::MaxDegree())
306       return 0;
307     const Handle(StepGeom_BSplineCurveWithKnots) BSPL = new StepGeom_BSplineCurveWithKnots;
308     BSPL->SetDegree(aDegree);
309     BSPL->SetControlPointsList(QUC->ControlPointsList());
310     BSPL->SetCurveForm(QUC->CurveForm());
311     BSPL->SetClosedCurve(QUC->ClosedCurve());
312     BSPL->SetSelfIntersect(QUC->SelfIntersect());
313
314     // Compute Knots and KnotsMultiplicity
315     const Standard_Integer nbK = BSPL->NbControlPointsList() - BSPL->Degree() + 1;
316     const Handle(TColStd_HArray1OfInteger) Kmult = new TColStd_HArray1OfInteger(1,nbK);
317     const Handle(TColStd_HArray1OfReal) Knots = new TColStd_HArray1OfReal(1,nbK);
318     for (Standard_Integer iQUC = 1 ; iQUC <= nbK ; iQUC ++) {
319       Kmult->SetValue(iQUC, 1);
320       Knots->SetValue(iQUC, iQUC - 1.);
321     }
322     Kmult->SetValue(1, BSPL->Degree() + 1);
323     Kmult->SetValue(nbK, BSPL->Degree() + 1);
324     BSPL->SetKnotMultiplicities(Kmult);
325     BSPL->SetKnots(Knots);
326
327     return MakeBSplineCurve (BSPL);
328   }
329
330   if (SC->IsKind(STANDARD_TYPE(StepGeom_UniformCurveAndRationalBSplineCurve)))
331   {
332     const Handle(StepGeom_UniformCurveAndRationalBSplineCurve) RUC =
333       Handle(StepGeom_UniformCurveAndRationalBSplineCurve)::DownCast(SC);
334     Standard_Integer aDegree = RUC->Degree();
335     if (aDegree < 1 || aDegree > Geom_BSplineCurve::MaxDegree())
336       return 0;
337     const Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve) RBSPL =
338       new StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve;
339
340     // Compute Knots and KnotsMultiplicity
341     const Standard_Integer nbK = RUC->NbControlPointsList() + aDegree + 1;
342     const Handle(TColStd_HArray1OfInteger) Kmult = new TColStd_HArray1OfInteger(1,nbK);
343     const Handle(TColStd_HArray1OfReal) Knots = new TColStd_HArray1OfReal(1,nbK);
344     for (Standard_Integer iUC = 1 ; iUC <= nbK ; iUC ++) {
345       Kmult->SetValue(iUC, 1);
346       Knots->SetValue(iUC, iUC - 1.);
347     }
348
349     // Initialize the BSplineCurveWithKnotsAndRationalBSplineCurve
350     RBSPL->Init(RUC->Name(), aDegree, RUC->ControlPointsList(), RUC->CurveForm(),
351                 RUC->ClosedCurve(), RUC->SelfIntersect(), Kmult, Knots, StepGeom_ktUnspecified,
352                 RUC->WeightsData());
353
354     return MakeBSplineCurve (RBSPL);
355   }
356
357   if (SC->IsKind(STANDARD_TYPE(StepGeom_QuasiUniformCurveAndRationalBSplineCurve)))
358   {
359     const Handle(StepGeom_QuasiUniformCurveAndRationalBSplineCurve) RQUC =
360       Handle(StepGeom_QuasiUniformCurveAndRationalBSplineCurve)::DownCast(SC);
361     Standard_Integer aDegree = RQUC->Degree();
362     if (aDegree < 1 || aDegree > Geom_BSplineCurve::MaxDegree())
363       return 0;
364     const Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve) RBSPL =
365       new StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve;
366
367     // Compute Knots and KnotsMultiplicity
368     const Standard_Integer nbK = RQUC->NbControlPointsList() - aDegree + 1;
369     const Handle(TColStd_HArray1OfInteger) Kmult = new TColStd_HArray1OfInteger(1,nbK);
370     const Handle(TColStd_HArray1OfReal) Knots = new TColStd_HArray1OfReal(1,nbK);
371     for (Standard_Integer iRQUC = 1 ; iRQUC <= nbK ; iRQUC ++) {
372       Kmult->SetValue(iRQUC, 1);
373       Knots->SetValue(iRQUC, iRQUC - 1.);
374     }
375     Kmult->SetValue(1, aDegree + 1);
376     Kmult->SetValue(nbK, aDegree + 1);
377     // Initialize the BSplineCurveWithKnotsAndRationalBSplineCurve
378     RBSPL->Init(RQUC->Name(), aDegree, RQUC->ControlPointsList(), RQUC->CurveForm(),
379                 RQUC->ClosedCurve(), RQUC->SelfIntersect(), Kmult, Knots, StepGeom_ktUnspecified,
380                 RQUC->WeightsData());
381
382     return MakeBSplineCurve (RBSPL);
383   }
384
385   if (SC->IsKind(STANDARD_TYPE(StepGeom_Polyline)))
386   { //:n6 abv 15 Feb 99
387     return MakePolyline (Handle(StepGeom_Polyline)::DownCast (SC));
388   }
389
390   return 0;
391 }
392
393 //=============================================================================
394 // Creation d' une BoundedCurve de Geom a partir d' une BoundedCurve de Step
395 //=============================================================================
396
397 Handle(Geom2d_BoundedCurve) StepToGeom::MakeBoundedCurve2d (const Handle(StepGeom_BoundedCurve)& SC)
398 {
399   if (SC->IsKind(STANDARD_TYPE(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)))
400   {
401     return MakeBSplineCurve2d (Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)::DownCast(SC));
402   }
403   if (SC->IsKind(STANDARD_TYPE(StepGeom_BSplineCurveWithKnots)))
404   {
405     return MakeBSplineCurve2d (Handle(StepGeom_BSplineCurveWithKnots)::DownCast(SC));
406   }
407   if (SC->IsKind(STANDARD_TYPE(StepGeom_TrimmedCurve)))
408   {
409     return MakeTrimmedCurve2d (Handle(StepGeom_TrimmedCurve)::DownCast(SC));
410   }
411   if (SC->IsKind(STANDARD_TYPE(StepGeom_Polyline)))
412   { //:n6 abv 15 Feb 99
413     return MakePolyline2d (Handle(StepGeom_Polyline)::DownCast(SC));
414   }
415   return Handle(Geom2d_BoundedCurve)();
416 }
417
418 //=============================================================================
419 // Creation d' une BoundedSurface de Geom a partir d' une BoundedSurface de Step
420 //=============================================================================
421
422 Handle(Geom_BoundedSurface) StepToGeom::MakeBoundedSurface (const Handle(StepGeom_BoundedSurface)& SS)
423 {
424   if (SS->IsKind(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface)))
425   {
426     return MakeBSplineSurface (Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface)::DownCast(SS));
427   }
428   if (SS->IsKind(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnots)))
429   {
430     return MakeBSplineSurface (Handle(StepGeom_BSplineSurfaceWithKnots)::DownCast(SS));
431   }
432   if (SS->IsKind(STANDARD_TYPE(StepGeom_RectangularTrimmedSurface)))
433   {
434     return MakeRectangularTrimmedSurface (Handle(StepGeom_RectangularTrimmedSurface)::DownCast(SS));
435   }
436
437   // STEP BezierSurface, UniformSurface and QuasiUniformSurface are transformed
438   // into STEP BSplineSurface before being mapped onto CAS.CADE/SF
439   if (SS->IsKind(STANDARD_TYPE(StepGeom_BezierSurface))) {
440     const Handle(StepGeom_BezierSurface) BzS = Handle(StepGeom_BezierSurface)::DownCast(SS);
441     const Handle(StepGeom_BSplineSurfaceWithKnots) BSPL = new StepGeom_BSplineSurfaceWithKnots;
442     BSPL->SetUDegree(BzS->UDegree());
443     BSPL->SetVDegree(BzS->VDegree());
444     BSPL->SetControlPointsList(BzS->ControlPointsList());
445     BSPL->SetSurfaceForm(BzS->SurfaceForm());
446     BSPL->SetUClosed(BzS->UClosed());
447     BSPL->SetVClosed(BzS->VClosed());
448     BSPL->SetSelfIntersect(BzS->SelfIntersect());
449
450     // Compute Knots and KnotsMultiplicity
451     const Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,2);
452     const Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,2);
453     const Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,2);
454     const Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,2);
455     UKmult->SetValue(1, BzS->UDegree() + 1);
456     UKmult->SetValue(2, BzS->UDegree() + 1);
457     VKmult->SetValue(1, BzS->VDegree() + 1);
458     VKmult->SetValue(2, BzS->VDegree() + 1);
459     UKnots->SetValue(1, 0.);
460     UKnots->SetValue(2, 1.);
461     VKnots->SetValue(1, 0.);
462     VKnots->SetValue(2, 1.);
463     BSPL->SetUMultiplicities(UKmult);
464     BSPL->SetVMultiplicities(VKmult);
465     BSPL->SetUKnots(UKnots);
466     BSPL->SetVKnots(VKnots);
467
468     return MakeBSplineSurface (BSPL);
469   }
470
471   if (SS->IsKind(STANDARD_TYPE(StepGeom_UniformSurface)))
472   {
473     const Handle(StepGeom_UniformSurface) US = Handle(StepGeom_UniformSurface)::DownCast(SS);
474     const Handle(StepGeom_BSplineSurfaceWithKnots) BSPL = new StepGeom_BSplineSurfaceWithKnots;
475     BSPL->SetUDegree(US->UDegree());
476     BSPL->SetVDegree(US->VDegree());
477     BSPL->SetControlPointsList(US->ControlPointsList());
478     BSPL->SetSurfaceForm(US->SurfaceForm());
479     BSPL->SetUClosed(US->UClosed());
480     BSPL->SetVClosed(US->VClosed());
481     BSPL->SetSelfIntersect(US->SelfIntersect());
482
483     // Compute Knots and KnotsMultiplicity for U Direction
484     const Standard_Integer nbKU = BSPL->NbControlPointsListI() + BSPL->UDegree() + 1;
485     const Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,nbKU);
486     const Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,nbKU);
487     for (Standard_Integer iU = 1 ; iU <= nbKU ; iU ++) {
488       UKmult->SetValue(iU, 1);
489       UKnots->SetValue(iU, iU - 1.);
490     }
491     BSPL->SetUMultiplicities(UKmult);
492     BSPL->SetUKnots(UKnots);
493
494     // Compute Knots and KnotsMultiplicity for V Direction
495     const Standard_Integer nbKV = BSPL->NbControlPointsListJ() + BSPL->VDegree() + 1;
496     const Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,nbKV);
497     const Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,nbKV);
498     for (Standard_Integer iV = 1 ; iV <= nbKV ; iV ++) {
499       VKmult->SetValue(iV, 1);
500       VKnots->SetValue(iV, iV - 1.);
501     }
502     BSPL->SetVMultiplicities(VKmult);
503     BSPL->SetVKnots(VKnots);
504
505     return MakeBSplineSurface (BSPL);
506   }
507
508   if (SS->IsKind(STANDARD_TYPE(StepGeom_QuasiUniformSurface)))
509   {
510     const Handle(StepGeom_QuasiUniformSurface) QUS =
511       Handle(StepGeom_QuasiUniformSurface)::DownCast(SS);
512     const Handle(StepGeom_BSplineSurfaceWithKnots) BSPL = new StepGeom_BSplineSurfaceWithKnots;
513     BSPL->SetUDegree(QUS->UDegree());
514     BSPL->SetVDegree(QUS->VDegree());
515     BSPL->SetControlPointsList(QUS->ControlPointsList());
516     BSPL->SetSurfaceForm(QUS->SurfaceForm());
517     BSPL->SetUClosed(QUS->UClosed());
518     BSPL->SetVClosed(QUS->VClosed());
519     BSPL->SetSelfIntersect(QUS->SelfIntersect());
520
521     // Compute Knots and KnotsMultiplicity for U Direction
522     const Standard_Integer nbKU = BSPL->NbControlPointsListI() - BSPL->UDegree() + 1;
523     const Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,nbKU);
524     const Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,nbKU);
525     for (Standard_Integer iU = 1 ; iU <= nbKU ; iU ++) {
526       UKmult->SetValue(iU, 1);
527       UKnots->SetValue(iU, iU - 1.);
528     }
529     UKmult->SetValue(1, BSPL->UDegree() + 1);
530     UKmult->SetValue(nbKU, BSPL->UDegree() + 1);
531     BSPL->SetUMultiplicities(UKmult);
532     BSPL->SetUKnots(UKnots);
533
534     // Compute Knots and KnotsMultiplicity for V Direction
535     const Standard_Integer nbKV = BSPL->NbControlPointsListJ() - BSPL->VDegree() + 1;
536     const Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,nbKV);
537     const Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,nbKV);
538     for (Standard_Integer iV = 1 ; iV <= nbKV ; iV ++) {
539       VKmult->SetValue(iV, 1);
540       VKnots->SetValue(iV, iV - 1.);
541     }
542     VKmult->SetValue(1, BSPL->VDegree() + 1);
543     VKmult->SetValue(nbKV, BSPL->VDegree() + 1);
544     BSPL->SetVMultiplicities(VKmult);
545     BSPL->SetVKnots(VKnots);
546
547     return MakeBSplineSurface (BSPL);
548   }
549
550   if (SS->IsKind(STANDARD_TYPE(StepGeom_UniformSurfaceAndRationalBSplineSurface)))
551   {
552     const Handle(StepGeom_UniformSurfaceAndRationalBSplineSurface) RUS =
553       Handle(StepGeom_UniformSurfaceAndRationalBSplineSurface)::DownCast(SS);
554     const Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) RBSPL =
555       new StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface;
556
557     // Compute Knots and KnotsMultiplicity for U Direction
558     const Standard_Integer nbKU = RUS->NbControlPointsListI() + RUS->UDegree() + 1;
559     const Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,nbKU);
560     const Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,nbKU);
561     for (Standard_Integer iU = 1 ; iU <= nbKU ; iU ++) {
562       UKmult->SetValue(iU, 1);
563       UKnots->SetValue(iU, iU - 1.);
564     }
565
566     // Compute Knots and KnotsMultiplicity for V Direction
567     const Standard_Integer nbKV = RUS->NbControlPointsListJ() + RUS->VDegree() + 1;
568     const Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,nbKV);
569     const Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,nbKV);
570     for (Standard_Integer iV = 1 ; iV <= nbKV ; iV ++) {
571       VKmult->SetValue(iV, 1);
572       VKnots->SetValue(iV, iV - 1.);
573     }
574
575     // Initialize the BSplineSurfaceWithKnotsAndRationalBSplineSurface
576     RBSPL->Init(RUS->Name(), RUS->UDegree(), RUS->VDegree(),
577                 RUS->ControlPointsList(), RUS->SurfaceForm(),
578                 RUS->UClosed(), RUS->VClosed(), RUS->SelfIntersect(),
579                 UKmult, VKmult, UKnots, VKnots, StepGeom_ktUnspecified,
580                 RUS->WeightsData());
581
582     return MakeBSplineSurface (RBSPL);
583   }
584
585   if (SS->IsKind(STANDARD_TYPE(StepGeom_QuasiUniformSurfaceAndRationalBSplineSurface)))
586   {
587     const Handle(StepGeom_QuasiUniformSurfaceAndRationalBSplineSurface) RQUS =
588       Handle(StepGeom_QuasiUniformSurfaceAndRationalBSplineSurface)::DownCast(SS);
589     const Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) RBSPL =
590       new StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface;
591
592     // Compute Knots and KnotsMultiplicity for U Direction
593     const Standard_Integer nbKU = RQUS->NbControlPointsListI() - RQUS->UDegree() + 1;
594     const Handle(TColStd_HArray1OfInteger) UKmult = new TColStd_HArray1OfInteger(1,nbKU);
595     const Handle(TColStd_HArray1OfReal) UKnots = new TColStd_HArray1OfReal(1,nbKU);
596     for (Standard_Integer iU = 1 ; iU <= nbKU ; iU ++) {
597       UKmult->SetValue(iU, 1);
598       UKnots->SetValue(iU, iU - 1.);
599     }
600     UKmult->SetValue(1, RQUS->UDegree() + 1);
601     UKmult->SetValue(nbKU, RQUS->UDegree() + 1);
602
603     // Compute Knots and KnotsMultiplicity for V Direction
604     const Standard_Integer nbKV = RQUS->NbControlPointsListJ() - RQUS->VDegree() + 1;
605     const Handle(TColStd_HArray1OfInteger) VKmult = new TColStd_HArray1OfInteger(1,nbKV);
606     const Handle(TColStd_HArray1OfReal) VKnots = new TColStd_HArray1OfReal(1,nbKV);
607     for (Standard_Integer iV = 1 ; iV <= nbKV ; iV ++) {
608       VKmult->SetValue(iV, 1);
609       VKnots->SetValue(iV, iV - 1.);
610     }
611     VKmult->SetValue(1, RQUS->VDegree() + 1);
612     VKmult->SetValue(nbKV, RQUS->VDegree() + 1);
613
614     // Initialize the BSplineSurfaceWithKnotsAndRationalBSplineSurface
615     RBSPL->Init(RQUS->Name(), RQUS->UDegree(), RQUS->VDegree(), RQUS->ControlPointsList(),
616                 RQUS->SurfaceForm(), RQUS->UClosed(), RQUS->VClosed(),
617                 RQUS->SelfIntersect(), UKmult, VKmult, UKnots, VKnots, StepGeom_ktUnspecified,
618                 RQUS->WeightsData());
619     return MakeBSplineSurface (RBSPL);
620   }
621
622   return 0;
623 }
624
625 //=============================================================================
626 // Template function for use in MakeBSplineCurve / MakeBSplineCurve2d
627 //=============================================================================
628
629 template
630 <
631   class TPntArray,
632   class TCartesianPoint,
633   class TGpPnt,
634   class TBSplineCurve
635 >
636 Handle(TBSplineCurve) MakeBSplineCurveCommon
637 (
638   const Handle(StepGeom_BSplineCurve)& theStepGeom_BSplineCurve,
639   TGpPnt(TCartesianPoint::* thePntGetterFunction)() const,
640   Handle(TCartesianPoint) (*thePointMakerFunction)(const Handle(StepGeom_CartesianPoint)&)
641 )
642 {
643   Handle(StepGeom_BSplineCurveWithKnots) aBSplineCurveWithKnots;
644   Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve) aBSplineCurveWithKnotsAndRationalBSplineCurve;
645
646   if (theStepGeom_BSplineCurve->IsKind(STANDARD_TYPE(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)))
647   {
648     aBSplineCurveWithKnotsAndRationalBSplineCurve =
649       Handle(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)::DownCast(theStepGeom_BSplineCurve);
650     aBSplineCurveWithKnots = aBSplineCurveWithKnotsAndRationalBSplineCurve->BSplineCurveWithKnots();
651   }
652   else
653     aBSplineCurveWithKnots = Handle(StepGeom_BSplineCurveWithKnots)::DownCast(theStepGeom_BSplineCurve);
654
655   const Standard_Integer aDegree = aBSplineCurveWithKnots->Degree();
656   const Standard_Integer NbPoles = aBSplineCurveWithKnots->NbControlPointsList();
657   const Standard_Integer NbKnots = aBSplineCurveWithKnots->NbKnotMultiplicities();
658
659   const Handle(TColStd_HArray1OfInteger)& aKnotMultiplicities = aBSplineCurveWithKnots->KnotMultiplicities();
660   const Handle(TColStd_HArray1OfReal)& aKnots = aBSplineCurveWithKnots->Knots();
661
662   // Count number of unique knots
663   Standard_Integer NbUniqueKnots = 0;
664   Standard_Real lastKnot = RealFirst();
665   for (Standard_Integer i = 1; i <= NbKnots; ++i)
666   {
667     if (aKnots->Value(i) - lastKnot > Epsilon(Abs(lastKnot)))
668     {
669       NbUniqueKnots++;
670       lastKnot = aKnots->Value(i);
671     }
672   }
673   if (NbUniqueKnots <= 1)
674   {
675     return 0;
676   }
677   TColStd_Array1OfReal aUniqueKnots(1, NbUniqueKnots);
678   TColStd_Array1OfInteger aUniqueKnotMultiplicities(1, NbUniqueKnots);
679   lastKnot = aKnots->Value(1);
680   aUniqueKnots.SetValue(1, aKnots->Value(1));
681   aUniqueKnotMultiplicities.SetValue(1, aKnotMultiplicities->Value(1));
682   Standard_Integer aKnotPosition = 1;
683   for (Standard_Integer i = 2; i <= NbKnots; i++)
684   {
685     if (aKnots->Value(i) - lastKnot > Epsilon(Abs(lastKnot)))
686     {
687       aKnotPosition++;
688       aUniqueKnots.SetValue(aKnotPosition, aKnots->Value(i));
689       aUniqueKnotMultiplicities.SetValue(aKnotPosition, aKnotMultiplicities->Value(i));
690       lastKnot = aKnots->Value(i);
691     }
692     else
693     {
694       // Knot not unique, increase multiplicity
695       Standard_Integer aCurrentMultiplicity = aUniqueKnotMultiplicities.Value(aKnotPosition);
696       aUniqueKnotMultiplicities.SetValue(aKnotPosition, aCurrentMultiplicity + aKnotMultiplicities->Value(i));
697     }
698   }
699
700   Standard_Integer aFirstMuultypisityDifference = 0;
701   Standard_Integer aLastMuultypisityDifference = 0;
702   for (Standard_Integer i = 1; i <= NbUniqueKnots; ++i)
703   {
704     Standard_Integer aCurrentVal = aUniqueKnotMultiplicities.Value(i);
705     if (aCurrentVal > aDegree + 1)
706     {
707       if (i == 1)
708         aFirstMuultypisityDifference = aCurrentVal - aDegree - 1;
709       if (i == NbUniqueKnots)
710         aLastMuultypisityDifference = aCurrentVal - aDegree - 1;
711 #ifdef OCCT_DEBUG
712       std::cout << "\nWrong multiplicity " << aCurrentVal << " on " << i
713         << " knot!" << "\nChanged to " << aDegree + 1 << std::endl;
714 #endif
715       aCurrentVal = aDegree + 1;
716     }
717     aUniqueKnotMultiplicities.SetValue(i, aCurrentVal);
718   }
719
720   const Handle(StepGeom_HArray1OfCartesianPoint)& aControlPointsList = aBSplineCurveWithKnots->ControlPointsList();
721   Standard_Integer aSummaryMuultypisityDifference = aFirstMuultypisityDifference + aLastMuultypisityDifference;
722   Standard_Integer NbUniquePoles = NbPoles - aSummaryMuultypisityDifference;
723   if (NbUniquePoles <= 0)
724   {
725     return 0;
726   }
727   TPntArray Poles(1, NbPoles - aSummaryMuultypisityDifference);
728
729   for (Standard_Integer i = 1 + aFirstMuultypisityDifference; i <= NbPoles - aLastMuultypisityDifference; ++i)
730   {
731     Handle(TCartesianPoint) aPoint = (*thePointMakerFunction)(aControlPointsList->Value(i));
732     if (!aPoint.IsNull())
733     {
734       TCartesianPoint* pPoint = aPoint.get();
735       TGpPnt aGpPnt = (pPoint->*thePntGetterFunction)();
736       Poles.SetValue(i - aFirstMuultypisityDifference, aGpPnt);
737     }
738     else
739     {
740       return 0;
741     }
742   }
743
744   // --- Does the Curve descriptor LOOKS like a periodic descriptor ? ---
745   Standard_Integer aSummaryMuultypisity = 0;
746   for (Standard_Integer i = 1; i <= NbUniqueKnots; i++)
747   {
748     aSummaryMuultypisity += aUniqueKnotMultiplicities.Value(i);
749   }
750
751   Standard_Boolean shouldBePeriodic;
752   if (aSummaryMuultypisity == (NbPoles + aDegree + 1))
753   {
754     shouldBePeriodic = Standard_False;
755   }
756   else if ((aUniqueKnotMultiplicities.Value(1) == aUniqueKnotMultiplicities.Value(NbUniqueKnots)) &&
757     ((aSummaryMuultypisity - aUniqueKnotMultiplicities.Value(1)) == NbPoles))
758   {
759     shouldBePeriodic = Standard_True;
760   }
761   else
762   {  
763     // --- What is that ??? ---
764     shouldBePeriodic = Standard_False;
765   }
766
767   Handle(TBSplineCurve) aBSplineCurve;
768   if (theStepGeom_BSplineCurve->IsKind(STANDARD_TYPE(StepGeom_BSplineCurveWithKnotsAndRationalBSplineCurve)))
769   {
770     const Handle(TColStd_HArray1OfReal)& aWeights = aBSplineCurveWithKnotsAndRationalBSplineCurve->WeightsData();
771     TColStd_Array1OfReal aUniqueWeights(1, NbPoles - aSummaryMuultypisityDifference);
772     for (Standard_Integer i = 1 + aFirstMuultypisityDifference; i <= NbPoles - aLastMuultypisityDifference; ++i)
773       aUniqueWeights.SetValue(i - aFirstMuultypisityDifference, aWeights->Value(i));
774     aBSplineCurve = new TBSplineCurve(Poles, aUniqueWeights, aUniqueKnots, aUniqueKnotMultiplicities, aDegree, shouldBePeriodic);
775   }
776   else
777   {
778     aBSplineCurve = new TBSplineCurve(Poles, aUniqueKnots, aUniqueKnotMultiplicities, aDegree, shouldBePeriodic);
779   }
780
781   // abv 04.07.00 CAX-IF TRJ4: trj4_k1_top-md-203.stp #716 (face #581):
782   // force periodicity on closed curves
783   if (theStepGeom_BSplineCurve->ClosedCurve() && aBSplineCurve->Degree() > 1 && aBSplineCurve->IsClosed())
784   {
785     aBSplineCurve->SetPeriodic();
786   }
787   return aBSplineCurve;
788 }
789
790 //=============================================================================
791 // Creation d' une BSplineCurve de Geom a partir d' une BSplineCurve de Step
792 //=============================================================================
793
794 Handle(Geom_BSplineCurve) StepToGeom::MakeBSplineCurve (const Handle(StepGeom_BSplineCurve)& theStepGeom_BSplineCurve)
795 {
796   return MakeBSplineCurveCommon<TColgp_Array1OfPnt, Geom_CartesianPoint, gp_Pnt, Geom_BSplineCurve>
797     (theStepGeom_BSplineCurve, &Geom_CartesianPoint::Pnt, &MakeCartesianPoint);
798 }
799
800 //=============================================================================
801 // Creation d' une BSplineCurve de Geom2d a partir d' une
802 // BSplineCurveWithKnotsAndRationalBSplineCurve de Step
803 //=============================================================================
804
805 Handle(Geom2d_BSplineCurve) StepToGeom::MakeBSplineCurve2d (const Handle(StepGeom_BSplineCurve)& theStepGeom_BSplineCurve)
806 {
807   return MakeBSplineCurveCommon<TColgp_Array1OfPnt2d, Geom2d_CartesianPoint, gp_Pnt2d, Geom2d_BSplineCurve>
808     (theStepGeom_BSplineCurve, &Geom2d_CartesianPoint::Pnt2d, &MakeCartesianPoint2d);
809 }
810
811 //=============================================================================
812 // Creation d' une BSplineSurface de Geom a partir d' une
813 // BSplineSurface de Step
814 //=============================================================================
815
816 Handle(Geom_BSplineSurface) StepToGeom::MakeBSplineSurface (const Handle(StepGeom_BSplineSurface)& SS)
817 {
818   Standard_Integer                    i, j;
819   Handle(StepGeom_BSplineSurfaceWithKnots) BS;
820   Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface) BSR;
821
822   if (SS->
823       IsKind(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface))) {
824     BSR =
825       Handle(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface)
826         ::DownCast(SS);
827     BS = BSR->BSplineSurfaceWithKnots();
828   }
829   else
830     BS = Handle(StepGeom_BSplineSurfaceWithKnots)::DownCast(SS);
831
832   const Standard_Integer UDeg = BS->UDegree();
833   const Standard_Integer VDeg = BS->VDegree();
834   const Standard_Integer NUPoles = BS->NbControlPointsListI();
835   const Standard_Integer NVPoles = BS->NbControlPointsListJ();
836   const Handle(StepGeom_HArray2OfCartesianPoint)& aControlPointsList = BS->ControlPointsList();
837   TColgp_Array2OfPnt Poles(1,NUPoles,1,NVPoles);
838   for (i=1; i<=NUPoles; i++) {
839     for (j=1; j<=NVPoles; j++) {
840       Handle(Geom_CartesianPoint) P = MakeCartesianPoint (aControlPointsList->Value(i,j));
841       if (! P.IsNull())
842         Poles.SetValue(i,j,P->Pnt());
843       else
844         return 0;
845     }
846   }
847   const Standard_Integer NUKnots = BS->NbUMultiplicities();
848   const Handle(TColStd_HArray1OfInteger)& aUMultiplicities = BS->UMultiplicities();
849   const Handle(TColStd_HArray1OfReal)& aUKnots = BS->UKnots();
850
851   // count number of unique uknots
852   Standard_Real lastKnot = RealFirst();
853   Standard_Integer NUKnotsUnique = 0;
854   for (i=1; i<=NUKnots; i++) {
855     if (aUKnots->Value(i) - lastKnot > Epsilon (Abs(lastKnot))) {
856       NUKnotsUnique++;
857       lastKnot = aUKnots->Value(i);
858     }
859   }
860
861   // set umultiplicities and uknots
862   TColStd_Array1OfInteger UMult(1,NUKnotsUnique);
863   TColStd_Array1OfReal KUn(1,NUKnotsUnique);
864   Standard_Integer pos = 1;
865   lastKnot = aUKnots->Value(1);
866   KUn.SetValue(1, aUKnots->Value(1));
867   UMult.SetValue(1, aUMultiplicities->Value(1));
868   for (i=2; i<=NUKnots; i++) {
869     if (aUKnots->Value(i) - lastKnot > Epsilon (Abs(lastKnot))) {
870       pos++;
871       KUn.SetValue(pos, aUKnots->Value(i));
872       UMult.SetValue(pos, aUMultiplicities->Value(i));
873       lastKnot = aUKnots->Value(i);
874     }
875     else {
876       // Knot not unique, increase multiplicity
877       Standard_Integer curMult = UMult.Value(pos);
878       UMult.SetValue(pos, curMult + aUMultiplicities->Value(i));
879     }
880   }
881   const Standard_Integer NVKnots = BS->NbVMultiplicities();
882   const Handle(TColStd_HArray1OfInteger)& aVMultiplicities = BS->VMultiplicities();
883   const Handle(TColStd_HArray1OfReal)& aVKnots = BS->VKnots();
884
885   // count number of unique vknots
886   lastKnot = RealFirst();
887   Standard_Integer NVKnotsUnique = 0;
888   for (i=1; i<=NVKnots; i++) {
889     if (aVKnots->Value(i) - lastKnot > Epsilon (Abs(lastKnot))) {
890       NVKnotsUnique++;
891       lastKnot = aVKnots->Value(i);
892     }
893   }
894
895   // set vmultiplicities and vknots
896   TColStd_Array1OfInteger VMult(1,NVKnotsUnique);
897   TColStd_Array1OfReal KVn(1,NVKnotsUnique);
898   pos = 1;
899   lastKnot = aVKnots->Value(1);
900   KVn.SetValue(1, aVKnots->Value(1));
901   VMult.SetValue(1, aVMultiplicities->Value(1));
902   for (i=2; i<=NVKnots; i++) {
903     if (aVKnots->Value(i) - lastKnot > Epsilon (Abs(lastKnot))) {
904       pos++;
905       KVn.SetValue(pos, aVKnots->Value(i));
906       VMult.SetValue(pos, aVMultiplicities->Value(i));
907       lastKnot = aVKnots->Value(i);
908     }
909     else {
910       // Knot not unique, increase multiplicity
911       Standard_Integer curMult = VMult.Value(pos);
912       VMult.SetValue(pos, curMult + aVMultiplicities->Value(i));
913     }
914   }
915
916   // --- Does the Surface Descriptor LOOKS like a U and/or V Periodic ---
917   // --- Descriptor ? ---
918
919   // --- U Periodic ? ---
920
921   Standard_Integer SumMult = 0;
922   for (i=1; i<=NUKnotsUnique; i++) {
923     SumMult += UMult.Value(i);
924   }
925
926   Standard_Boolean shouldBeUPeriodic = Standard_False;
927   if (SumMult == (NUPoles + UDeg + 1)) {
928     //shouldBeUPeriodic = Standard_False;
929   }
930   else if ((UMult.Value(1) ==
931             UMult.Value(NUKnotsUnique)) &&
932            ((SumMult - UMult.Value(1))== NUPoles)) {
933     shouldBeUPeriodic = Standard_True;
934   }
935
936   // --- V Periodic ? ---
937
938   SumMult = 0;
939   for (i=1; i<=NVKnotsUnique; i++) {
940     SumMult += VMult.Value(i);
941   }
942
943   Standard_Boolean shouldBeVPeriodic = Standard_False;
944   if (SumMult == (NVPoles + VDeg + 1)) {
945     //shouldBeVPeriodic = Standard_False;
946   }
947   else if ((VMult.Value(1) ==
948             VMult.Value(NVKnotsUnique)) &&
949            ((SumMult - VMult.Value(1)) == NVPoles)) {
950     shouldBeVPeriodic = Standard_True;
951   }
952
953   Handle(Geom_BSplineSurface) CS;
954   if (SS->IsKind(STANDARD_TYPE(StepGeom_BSplineSurfaceWithKnotsAndRationalBSplineSurface))) {
955     const Handle(TColStd_HArray2OfReal)& aWeight = BSR->WeightsData();
956     TColStd_Array2OfReal W(1,NUPoles,1,NVPoles);
957     for (i=1; i<=NUPoles; i++) {
958       for (j=1; j<=NVPoles; j++) {
959         W.SetValue(i,j,aWeight->Value(i,j));
960       }
961     }
962     CS = new Geom_BSplineSurface(Poles, W, KUn, KVn, UMult,
963                                  VMult, UDeg, VDeg,
964                                  shouldBeUPeriodic,
965                                  shouldBeVPeriodic);
966   }
967   else
968     CS = new Geom_BSplineSurface(Poles, KUn, KVn, UMult,
969                                  VMult, UDeg, VDeg,
970                                  shouldBeUPeriodic,
971                                  shouldBeVPeriodic);
972   return CS;
973 }
974
975 //=============================================================================
976 // Creation d' un CartesianPoint de Geom a partir d' un CartesianPoint de Step
977 //=============================================================================
978
979 Handle(Geom_CartesianPoint) StepToGeom::MakeCartesianPoint (const Handle(StepGeom_CartesianPoint)& SP)
980 {
981   if (SP->NbCoordinates() == 3)
982   {
983     const Standard_Real LF = UnitsMethods::LengthFactor();
984     const Standard_Real X = SP->CoordinatesValue(1) * LF;
985     const Standard_Real Y = SP->CoordinatesValue(2) * LF;
986     const Standard_Real Z = SP->CoordinatesValue(3) * LF;
987     return new Geom_CartesianPoint(X, Y, Z);
988   }
989   return 0;
990 }
991
992 //=============================================================================
993 // Creation d' un CartesianPoint de Geom2d a partir d' un CartesianPoint de
994 // Step
995 //=============================================================================
996
997 Handle(Geom2d_CartesianPoint) StepToGeom::MakeCartesianPoint2d (const Handle(StepGeom_CartesianPoint)& SP)
998 {
999   if (SP->NbCoordinates() == 2)
1000   {
1001     const Standard_Real X = SP->CoordinatesValue(1);
1002     const Standard_Real Y = SP->CoordinatesValue(2);
1003     return new Geom2d_CartesianPoint(X, Y);
1004   }
1005   return 0;
1006 }
1007
1008 //=============================================================================
1009 // Creation d' un Circle de Geom a partir d' un Circle de Step
1010 //=============================================================================
1011
1012 Handle(Geom_Circle) StepToGeom::MakeCircle (const Handle(StepGeom_Circle)& SC)
1013 {
1014   const StepGeom_Axis2Placement AxisSelect = SC->Position();
1015   if (AxisSelect.CaseNum(AxisSelect.Value()) == 2)
1016   {
1017     Handle(Geom_Axis2Placement) A =
1018       MakeAxis2Placement (Handle(StepGeom_Axis2Placement3d)::DownCast(AxisSelect.Value()));
1019     if (! A.IsNull())
1020     {
1021       return new Geom_Circle(A->Ax2(),SC->Radius() * UnitsMethods::LengthFactor());
1022     }
1023   }
1024   return 0;
1025 }
1026
1027 //=============================================================================
1028 // Creation d' un Circle de Geom2d a partir d' un Circle de Step
1029 //=============================================================================
1030
1031 Handle(Geom2d_Circle) StepToGeom::MakeCircle2d (const Handle(StepGeom_Circle)& SC)
1032 {
1033   const StepGeom_Axis2Placement AxisSelect = SC->Position();
1034   if (AxisSelect.CaseNum(AxisSelect.Value()) == 1) {
1035     Handle(Geom2d_AxisPlacement) A1 =
1036       MakeAxisPlacement (Handle(StepGeom_Axis2Placement2d)::DownCast(AxisSelect.Value()));
1037     if (! A1.IsNull())
1038     {
1039       return new Geom2d_Circle (A1->Ax2d(), SC->Radius());
1040     }
1041   }
1042   return 0;
1043 }
1044
1045 //=============================================================================
1046 // Creation d' une Conic de Geom a partir d' une Conic de Step
1047 //=============================================================================
1048
1049 Handle(Geom_Conic) StepToGeom::MakeConic (const Handle(StepGeom_Conic)& SC)
1050 {
1051   if (SC->IsKind(STANDARD_TYPE(StepGeom_Circle))) {
1052     return MakeCircle (Handle(StepGeom_Circle)::DownCast(SC));
1053   }
1054   if (SC->IsKind(STANDARD_TYPE(StepGeom_Ellipse))) {
1055     return MakeEllipse (Handle(StepGeom_Ellipse)::DownCast(SC));
1056   }
1057   if (SC->IsKind(STANDARD_TYPE(StepGeom_Hyperbola))) {
1058     return MakeHyperbola (Handle(StepGeom_Hyperbola)::DownCast(SC));
1059   }
1060   if (SC->IsKind(STANDARD_TYPE(StepGeom_Parabola))) {
1061     return MakeParabola (Handle(StepGeom_Parabola)::DownCast(SC));
1062   }
1063   // Attention : Other conic shall be implemented !
1064   return 0;
1065 }
1066
1067 //=============================================================================
1068 // Creation d' une Conic de Geom2d a partir d' une Conic de Step
1069 //=============================================================================
1070
1071 Handle(Geom2d_Conic) StepToGeom::MakeConic2d (const Handle(StepGeom_Conic)& SC)
1072 {
1073   if (SC->IsKind(STANDARD_TYPE(StepGeom_Circle))) {
1074     return MakeCircle2d (Handle(StepGeom_Circle)::DownCast(SC));
1075   }
1076   if (SC->IsKind(STANDARD_TYPE(StepGeom_Ellipse))) {
1077     return MakeEllipse2d (Handle(StepGeom_Ellipse)::DownCast(SC));
1078   }
1079   if (SC->IsKind(STANDARD_TYPE(StepGeom_Hyperbola))) {
1080     return MakeHyperbola2d (Handle(StepGeom_Hyperbola)::DownCast(SC));
1081   }
1082   if (SC->IsKind(STANDARD_TYPE(StepGeom_Parabola))) {
1083     return MakeParabola2d (Handle(StepGeom_Parabola)::DownCast(SC));
1084   }
1085   // Attention : Other conic shall be implemented !
1086   return Handle(Geom2d_Conic)();
1087 }
1088
1089 //=============================================================================
1090 // Creation d' une ConicalSurface de Geom a partir d' une ConicalSurface de
1091 // Step
1092 //=============================================================================
1093
1094 Handle(Geom_ConicalSurface) StepToGeom::MakeConicalSurface (const Handle(StepGeom_ConicalSurface)& SS)
1095 {
1096   Handle(Geom_Axis2Placement) A = MakeAxis2Placement (SS->Position());
1097   if (! A.IsNull())
1098   {
1099     const Standard_Real R = SS->Radius() * UnitsMethods::LengthFactor();
1100     const Standard_Real Ang = SS->SemiAngle() * UnitsMethods::PlaneAngleFactor();
1101     //#2(K3-3) rln 12/02/98 ProSTEP ct_turbine-A.stp entity #518, #3571 (gp::Resolution() is too little)
1102     return new Geom_ConicalSurface(A->Ax2(), Max(Ang, Precision::Angular()), R);
1103   }
1104   return 0;
1105 }
1106
1107 //=============================================================================
1108 // Creation d' une Curve de Geom a partir d' une Curve de Step
1109 //=============================================================================
1110
1111 Handle(Geom_Curve) StepToGeom::MakeCurve (const Handle(StepGeom_Curve)& SC)
1112 {
1113   if (SC.IsNull()){
1114     return Handle(Geom_Curve)();
1115   }
1116   if (SC->IsKind(STANDARD_TYPE(StepGeom_Line))) {
1117     return MakeLine (Handle(StepGeom_Line)::DownCast(SC));
1118   }
1119   if (SC->IsKind(STANDARD_TYPE(StepGeom_TrimmedCurve))) {
1120     return MakeTrimmedCurve (Handle(StepGeom_TrimmedCurve)::DownCast(SC));
1121   }
1122   if (SC->IsKind(STANDARD_TYPE(StepGeom_Conic))) {
1123     return MakeConic (Handle(StepGeom_Conic)::DownCast(SC));
1124   }
1125   if (SC->IsKind(STANDARD_TYPE(StepGeom_BoundedCurve))) {
1126     return MakeBoundedCurve (Handle(StepGeom_BoundedCurve)::DownCast(SC));
1127   }
1128   if (SC->IsKind(STANDARD_TYPE(StepGeom_CurveReplica))) { //:n7 abv 16 Feb 99
1129     const Handle(StepGeom_CurveReplica) CR = Handle(StepGeom_CurveReplica)::DownCast(SC);
1130     const Handle(StepGeom_Curve) PC = CR->ParentCurve();
1131     const Handle(StepGeom_CartesianTransformationOperator3d) T =
1132       Handle(StepGeom_CartesianTransformationOperator3d)::DownCast(CR->Transformation());
1133     // protect against cyclic references and wrong type of cartop
1134     if ( !T.IsNull() && PC != SC )
1135     {
1136       Handle(Geom_Curve) C1 = MakeCurve (PC);
1137       if (! C1.IsNull())
1138       {
1139         gp_Trsf T1;
1140         if (MakeTransformation3d(T,T1))
1141         {
1142           C1->Transform ( T1 );
1143           return C1;
1144         }
1145       }
1146     }
1147   }
1148   else if (SC->IsKind(STANDARD_TYPE(StepGeom_OffsetCurve3d))) { //:o2 abv 17 Feb 99
1149     const Handle(StepGeom_OffsetCurve3d) OC = Handle(StepGeom_OffsetCurve3d)::DownCast(SC);
1150     const Handle(StepGeom_Curve) BC = OC->BasisCurve();
1151     if ( BC != SC ) { // protect against loop
1152       Handle(Geom_Curve) C1 = MakeCurve (BC);
1153       if (! C1.IsNull())
1154       {
1155         Handle(Geom_Direction) RD = MakeDirection(OC->RefDirection());
1156         if (! RD.IsNull())
1157         {
1158           return new Geom_OffsetCurve ( C1, -OC->Distance(), RD->Dir() );
1159         }
1160       }
1161     }
1162   }
1163   else if (SC->IsKind(STANDARD_TYPE(StepGeom_SurfaceCurve))) { //:o5 abv 17 Feb 99
1164     const Handle(StepGeom_SurfaceCurve) SurfC = Handle(StepGeom_SurfaceCurve)::DownCast(SC);
1165     return MakeCurve (SurfC->Curve3d());
1166   }
1167   return 0;
1168 }
1169
1170 //=============================================================================
1171 // Creation d' une Curve de Geom2d a partir d' une Curve de Step
1172 //=============================================================================
1173
1174 Handle(Geom2d_Curve) StepToGeom::MakeCurve2d (const Handle(StepGeom_Curve)& SC)
1175 {
1176   if (SC->IsKind(STANDARD_TYPE(StepGeom_Line))) {
1177     return MakeLine2d (Handle(StepGeom_Line)::DownCast(SC));
1178   }
1179   if (SC->IsKind(STANDARD_TYPE(StepGeom_Conic))) {
1180     return MakeConic2d (Handle(StepGeom_Conic)::DownCast(SC));
1181   }
1182   if (SC->IsKind(STANDARD_TYPE(StepGeom_BoundedCurve))) {
1183     return MakeBoundedCurve2d (Handle(StepGeom_BoundedCurve)::DownCast(SC));
1184   }
1185   if (SC->IsKind(STANDARD_TYPE(StepGeom_CurveReplica))) { //:n7 abv 16 Feb 99
1186     const Handle(StepGeom_CurveReplica) CR = Handle(StepGeom_CurveReplica)::DownCast(SC);
1187     const Handle(StepGeom_Curve) PC = CR->ParentCurve();
1188     const Handle(StepGeom_CartesianTransformationOperator2d) T =
1189       Handle(StepGeom_CartesianTransformationOperator2d)::DownCast(CR->Transformation());
1190     // protect against cyclic references and wrong type of cartop
1191     if ( !T.IsNull() && PC != SC )
1192     {
1193       Handle(Geom2d_Curve) C1 = MakeCurve2d (PC);
1194       if (! C1.IsNull())
1195       {
1196         gp_Trsf2d T1;
1197         if (MakeTransformation2d(T,T1))
1198         {
1199           C1->Transform ( T1 );
1200           return C1;
1201         }
1202       }
1203     }
1204   }
1205   return 0;
1206 }
1207
1208 //=============================================================================
1209 // Creation d' une CylindricalSurface de Geom a partir d' une
1210 // CylindricalSurface de Step
1211 //=============================================================================
1212
1213 Handle(Geom_CylindricalSurface) StepToGeom::MakeCylindricalSurface (const Handle(StepGeom_CylindricalSurface)& SS)
1214 {
1215   Handle(Geom_Axis2Placement) A = MakeAxis2Placement(SS->Position());
1216   if (! A.IsNull())
1217   {
1218     return new Geom_CylindricalSurface(A->Ax2(), SS->Radius() * UnitsMethods::LengthFactor());
1219   }
1220   return 0;
1221 }
1222
1223 //=============================================================================
1224 // Creation d' un Direction de Geom a partir d' un Direction de Step
1225 //=============================================================================
1226
1227 Handle(Geom_Direction) StepToGeom::MakeDirection (const Handle(StepGeom_Direction)& SD)
1228 {
1229   if (SD->NbDirectionRatios() >= 3)
1230   {
1231     const Standard_Real X = SD->DirectionRatiosValue(1);
1232     const Standard_Real Y = SD->DirectionRatiosValue(2);
1233     const Standard_Real Z = SD->DirectionRatiosValue(3);
1234     // sln 22.10.2001. CTS23496: Direction is not created if it has null magnitude
1235     if (gp_XYZ(X, Y, Z).SquareModulus() > gp::Resolution()*gp::Resolution())
1236     {
1237       return new Geom_Direction(X, Y, Z);
1238     }
1239   }
1240   return 0;
1241 }
1242
1243 //=============================================================================
1244 // Creation d' un Direction de Geom2d a partir d' un Direction de Step
1245 //=============================================================================
1246
1247 Handle(Geom2d_Direction) StepToGeom::MakeDirection2d (const Handle(StepGeom_Direction)& SD)
1248 {
1249   if (SD->NbDirectionRatios() >= 2)
1250   {
1251     const Standard_Real X = SD->DirectionRatiosValue(1);
1252     const Standard_Real Y = SD->DirectionRatiosValue(2);
1253     // sln 23.10.2001. CTS23496: Direction is not created if it has null magnitude
1254     if(gp_XY(X,Y).SquareModulus() > gp::Resolution()*gp::Resolution())
1255     {
1256       return  new Geom2d_Direction(X, Y);
1257     }
1258   }
1259   return 0;
1260 }
1261
1262 //=============================================================================
1263 // Creation d' une ElementarySurface de Geom a partir d' une
1264 // ElementarySurface de Step
1265 //=============================================================================
1266
1267 Handle(Geom_ElementarySurface) StepToGeom::MakeElementarySurface (const Handle(StepGeom_ElementarySurface)& SS)
1268 {
1269   if (SS->IsKind(STANDARD_TYPE(StepGeom_Plane))) {
1270     return MakePlane (Handle(StepGeom_Plane)::DownCast(SS));
1271   }
1272   if (SS->IsKind(STANDARD_TYPE(StepGeom_CylindricalSurface))) {
1273     return MakeCylindricalSurface (Handle(StepGeom_CylindricalSurface)::DownCast(SS));
1274   }
1275   if (SS->IsKind(STANDARD_TYPE(StepGeom_ConicalSurface))) {
1276     return MakeConicalSurface (Handle(StepGeom_ConicalSurface)::DownCast(SS));
1277   }
1278   if (SS->IsKind(STANDARD_TYPE(StepGeom_SphericalSurface))) {
1279     return MakeSphericalSurface (Handle(StepGeom_SphericalSurface)::DownCast(SS));
1280   }
1281   if (SS->IsKind(STANDARD_TYPE(StepGeom_ToroidalSurface))) {
1282     return MakeToroidalSurface (Handle(StepGeom_ToroidalSurface)::DownCast(SS));
1283   }
1284   return 0;
1285 }
1286
1287 //=============================================================================
1288 // Creation d' un Ellipse de Geom a partir d' un Ellipse de Step
1289 //=============================================================================
1290
1291 Handle(Geom_Ellipse) StepToGeom::MakeEllipse (const Handle(StepGeom_Ellipse)& SC)
1292 {
1293   const StepGeom_Axis2Placement AxisSelect = SC->Position();
1294   if (AxisSelect.CaseNum(AxisSelect.Value()) == 2) {
1295     Handle(Geom_Axis2Placement) A1 = MakeAxis2Placement (Handle(StepGeom_Axis2Placement3d)::DownCast(AxisSelect.Value()));
1296     if (! A1.IsNull())
1297     {
1298       gp_Ax2 A( A1->Ax2() );
1299       const Standard_Real LF = UnitsMethods::LengthFactor();
1300       const Standard_Real majorR = SC->SemiAxis1() * LF;
1301       const Standard_Real minorR = SC->SemiAxis2() * LF;
1302       if ( majorR - minorR >= 0. ) { //:o9 abv 19 Feb 99
1303         return new Geom_Ellipse(A, majorR, minorR);
1304       }
1305       //:o9 abv 19 Feb 99
1306       else {
1307         A.SetXDirection ( A.XDirection() ^ A.Direction() );
1308         return new Geom_Ellipse(A, minorR, majorR);
1309       }
1310     }
1311   }
1312   return 0;
1313 }
1314
1315 //=============================================================================
1316 // Creation d' un Ellipse de Geom2d a partir d' un Ellipse de Step
1317 //=============================================================================
1318
1319 Handle(Geom2d_Ellipse) StepToGeom::MakeEllipse2d (const Handle(StepGeom_Ellipse)& SC)
1320 {
1321   const StepGeom_Axis2Placement AxisSelect = SC->Position();
1322   if (AxisSelect.CaseNum(AxisSelect.Value()) == 1) {
1323     Handle(Geom2d_AxisPlacement) A1 = MakeAxisPlacement (Handle(StepGeom_Axis2Placement2d)::DownCast(AxisSelect.Value()));
1324     if (! A1.IsNull())
1325     {
1326       gp_Ax22d A( A1->Ax2d() );
1327       const Standard_Real majorR = SC->SemiAxis1();
1328       const Standard_Real minorR = SC->SemiAxis2();
1329       if ( majorR - minorR >= 0. ) { //:o9 abv 19 Feb 99: bm4_id_punch_b.stp #678: protection
1330         return new Geom2d_Ellipse(A, majorR, minorR);
1331       }
1332       else {
1333         const gp_Dir2d X = A.XDirection();
1334         A.SetXDirection ( gp_Dir2d ( X.X(), -X.Y() ) );
1335         return new Geom2d_Ellipse(A, minorR, majorR);
1336       }
1337     }
1338   }
1339   return 0;
1340 }
1341
1342 //=============================================================================
1343 // Creation d' un Hyperbola de Geom a partir d' un Hyperbola de Step
1344 //=============================================================================
1345
1346 Handle(Geom_Hyperbola) StepToGeom::MakeHyperbola (const Handle(StepGeom_Hyperbola)& SC)
1347 {
1348   const StepGeom_Axis2Placement AxisSelect = SC->Position();
1349   if (AxisSelect.CaseNum(AxisSelect.Value()) == 2)
1350   {
1351     Handle(Geom_Axis2Placement) A1 = MakeAxis2Placement (Handle(StepGeom_Axis2Placement3d)::DownCast(AxisSelect.Value()));
1352     if (! A1.IsNull())
1353     {
1354       const gp_Ax2 A( A1->Ax2() );
1355       const Standard_Real LF = UnitsMethods::LengthFactor();
1356       return new Geom_Hyperbola(A, SC->SemiAxis() * LF, SC->SemiImagAxis() * LF);
1357     }
1358   }
1359   return 0;
1360 }
1361
1362 //=============================================================================
1363 // Creation d' un Hyperbola de Geom2d a partir d' un Hyperbola de Step
1364 //=============================================================================
1365
1366 Handle(Geom2d_Hyperbola) StepToGeom::MakeHyperbola2d (const Handle(StepGeom_Hyperbola)& SC)
1367 {
1368   const StepGeom_Axis2Placement AxisSelect = SC->Position();
1369   if (AxisSelect.CaseNum(AxisSelect.Value()) == 1)
1370   {
1371     Handle(Geom2d_AxisPlacement) A1 = MakeAxisPlacement (Handle(StepGeom_Axis2Placement2d)::DownCast(AxisSelect.Value()));
1372     if (! A1.IsNull())
1373     {
1374       const gp_Ax22d A( A1->Ax2d() );
1375       return new Geom2d_Hyperbola(A, SC->SemiAxis(), SC->SemiImagAxis());
1376     }
1377   }
1378   return 0;
1379 }
1380
1381 //=============================================================================
1382 // Creation d' une Line de Geom a partir d' une Line de Step
1383 //=============================================================================
1384
1385 Handle(Geom_Line) StepToGeom::MakeLine (const Handle(StepGeom_Line)& SC)
1386 {
1387   Handle(Geom_CartesianPoint) P = MakeCartesianPoint(SC->Pnt());
1388   if (! P.IsNull())
1389   {
1390     // sln 22.10.2001. CTS23496: Line is not created if direction have not been successfully created
1391     Handle(Geom_VectorWithMagnitude) D = MakeVectorWithMagnitude (SC->Dir());
1392     if (! D.IsNull())
1393     {
1394       if( D->Vec().SquareMagnitude() < Precision::Confusion() * Precision::Confusion())
1395         return 0;
1396       const gp_Dir V(D->Vec());
1397       return new Geom_Line(P->Pnt(), V);
1398     }
1399   }
1400   return 0;
1401 }
1402
1403 //=============================================================================
1404 // Creation d' une Line de Geom2d a partir d' une Line de Step
1405 //=============================================================================
1406
1407 Handle(Geom2d_Line) StepToGeom::MakeLine2d (const Handle(StepGeom_Line)& SC)
1408 {
1409   Handle(Geom2d_CartesianPoint) P = MakeCartesianPoint2d(SC->Pnt());
1410   if (! P.IsNull())
1411   {
1412     // sln 23.10.2001. CTS23496: Line is not created if direction have not been successfully created
1413     Handle(Geom2d_VectorWithMagnitude) D = MakeVectorWithMagnitude2d (SC->Dir());
1414     if (! D.IsNull())
1415     {
1416       const gp_Dir2d D1(D->Vec2d());
1417       return new Geom2d_Line(P->Pnt2d(), D1);
1418     }
1419   }
1420   return 0;
1421 }
1422
1423 //=============================================================================
1424 // Creation d' un Parabola de Geom a partir d' un Parabola de Step
1425 //=============================================================================
1426
1427 Handle(Geom_Parabola) StepToGeom::MakeParabola (const Handle(StepGeom_Parabola)& SC)
1428 {
1429   const StepGeom_Axis2Placement AxisSelect = SC->Position();
1430   if (AxisSelect.CaseNum(AxisSelect.Value()) == 2)
1431   {
1432     Handle(Geom_Axis2Placement) A = MakeAxis2Placement (Handle(StepGeom_Axis2Placement3d)::DownCast(AxisSelect.Value()));
1433     if (! A.IsNull())
1434     {
1435       return new Geom_Parabola(A->Ax2(), SC->FocalDist() * UnitsMethods::LengthFactor());
1436     }
1437   }
1438   return 0;
1439 }
1440
1441 //=============================================================================
1442 // Creation d' un Parabola de Geom2d a partir d' un Parabola de Step
1443 //=============================================================================
1444
1445 Handle(Geom2d_Parabola) StepToGeom::MakeParabola2d (const Handle(StepGeom_Parabola)& SC)
1446 {
1447   const StepGeom_Axis2Placement AxisSelect = SC->Position();
1448   if (AxisSelect.CaseNum(AxisSelect.Value()) == 1) {
1449     Handle(Geom2d_AxisPlacement) A1 = MakeAxisPlacement (Handle(StepGeom_Axis2Placement2d)::DownCast(AxisSelect.Value()));
1450     if (! A1.IsNull())
1451     {
1452       const gp_Ax22d A( A1->Ax2d() );
1453       return new Geom2d_Parabola(A, SC->FocalDist());
1454     }
1455   }
1456   return 0;
1457 }
1458
1459 //=============================================================================
1460 // Creation d' un Plane de Geom a partir d' un plane de Step
1461 //=============================================================================
1462
1463 Handle(Geom_Plane) StepToGeom::MakePlane (const Handle(StepGeom_Plane)& SP)
1464 {
1465   Handle(Geom_Axis2Placement) A = MakeAxis2Placement (SP->Position());
1466   if (! A.IsNull())
1467   {
1468     return new Geom_Plane(A->Ax2());
1469   }
1470   return 0;
1471 }
1472
1473 //=======================================================================
1474 //function : MakePolyline
1475 //purpose  :
1476 //=======================================================================
1477
1478 Handle(Geom_BSplineCurve) StepToGeom::MakePolyline (const Handle(StepGeom_Polyline)& SPL)
1479 {
1480   if (SPL.IsNull())
1481     return Handle(Geom_BSplineCurve)();
1482
1483   const Standard_Integer nbp = SPL->NbPoints();
1484   if (nbp > 1)
1485   {
1486     TColgp_Array1OfPnt Poles ( 1, nbp );
1487     TColStd_Array1OfReal Knots ( 1, nbp );
1488     TColStd_Array1OfInteger Mults ( 1, nbp );
1489
1490     for ( Standard_Integer i=1; i <= nbp; i++ )
1491     {
1492       Handle(Geom_CartesianPoint) P = MakeCartesianPoint (SPL->PointsValue(i));
1493       if (! P.IsNull())
1494         Poles.SetValue ( i, P->Pnt() );
1495       else
1496         return 0;
1497       Knots.SetValue ( i, Standard_Real(i-1) );
1498       Mults.SetValue ( i, 1 );
1499     }
1500     Mults.SetValue ( 1, 2 );
1501     Mults.SetValue ( nbp, 2 );
1502
1503     return new Geom_BSplineCurve ( Poles, Knots, Mults, 1 );
1504   }
1505   return 0;
1506 }
1507
1508 //=======================================================================
1509 //function : MakePolyline2d
1510 //purpose  :
1511 //=======================================================================
1512
1513 Handle(Geom2d_BSplineCurve) StepToGeom::MakePolyline2d (const Handle(StepGeom_Polyline)& SPL)
1514 {
1515   if (SPL.IsNull())
1516     return Handle(Geom2d_BSplineCurve)();
1517
1518   const Standard_Integer nbp = SPL->NbPoints();
1519   if (nbp > 1)
1520   {
1521     TColgp_Array1OfPnt2d Poles ( 1, nbp );
1522     TColStd_Array1OfReal Knots ( 1, nbp );
1523     TColStd_Array1OfInteger Mults ( 1, nbp );
1524
1525     for ( Standard_Integer i=1; i <= nbp; i++ )
1526     {
1527     Handle(Geom2d_CartesianPoint) P = MakeCartesianPoint2d (SPL->PointsValue(i));
1528       if (! P.IsNull())
1529         Poles.SetValue ( i, P->Pnt2d() );
1530       else
1531         return 0;
1532       Knots.SetValue ( i, Standard_Real(i-1) );
1533       Mults.SetValue ( i, 1 );
1534     }
1535     Mults.SetValue ( 1, 2 );
1536     Mults.SetValue ( nbp, 2 );
1537
1538     return new Geom2d_BSplineCurve ( Poles, Knots, Mults, 1 );
1539   }
1540   return 0;
1541 }
1542
1543 //=============================================================================
1544 // Creation d' une RectangularTrimmedSurface de Geom a partir d' une
1545 // RectangularTrimmedSurface de Step
1546 //=============================================================================
1547
1548 Handle(Geom_RectangularTrimmedSurface) StepToGeom::MakeRectangularTrimmedSurface (const Handle(StepGeom_RectangularTrimmedSurface)& SS)
1549 {
1550   Handle(Geom_Surface) theBasis = MakeSurface (SS->BasisSurface());
1551   if (! theBasis.IsNull())
1552   {
1553     // -----------------------------------------
1554     // Modification of the Trimming Parameters ?
1555     // -----------------------------------------
1556
1557     Standard_Real uFact = 1.;
1558     Standard_Real vFact = 1.;
1559     const Standard_Real LengthFact  = UnitsMethods::LengthFactor();
1560     const Standard_Real AngleFact   = UnitsMethods::PlaneAngleFactor(); // abv 30.06.00 trj4_k1_geo-tc-214.stp #1477: PI/180.;
1561
1562     if (theBasis->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
1563         theBasis->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
1564       uFact = vFact = AngleFact;
1565     }
1566     else if (theBasis->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
1567       uFact = AngleFact;
1568       vFact = LengthFact;
1569     }
1570     else if ( theBasis->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1571       uFact = AngleFact;
1572     }
1573     else if (theBasis->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) {
1574       const Handle(Geom_ConicalSurface) conicS = Handle(Geom_ConicalSurface)::DownCast(theBasis);
1575       uFact = AngleFact;
1576       vFact = LengthFact / Cos(conicS->SemiAngle());
1577     }
1578     else if (theBasis->IsKind(STANDARD_TYPE(Geom_Plane))) {
1579       uFact = vFact = LengthFact;
1580     }
1581
1582     const Standard_Real U1 = SS->U1() * uFact;
1583     const Standard_Real U2 = SS->U2() * uFact;
1584     const Standard_Real V1 = SS->V1() * vFact;
1585     const Standard_Real V2 = SS->V2() * vFact;
1586
1587     return new Geom_RectangularTrimmedSurface(theBasis, U1, U2, V1, V2, SS->Usense(), SS->Vsense());
1588   }
1589   return 0;
1590 }
1591
1592 //=============================================================================
1593 // Creation d' une SphericalSurface de Geom a partir d' une
1594 // SphericalSurface de Step
1595 //=============================================================================
1596
1597 Handle(Geom_SphericalSurface) StepToGeom::MakeSphericalSurface (const Handle(StepGeom_SphericalSurface)& SS)
1598 {
1599   Handle(Geom_Axis2Placement) A = MakeAxis2Placement (SS->Position());
1600   if (! A.IsNull())
1601   {
1602     return new Geom_SphericalSurface(A->Ax2(), SS->Radius() * UnitsMethods::LengthFactor());
1603   }
1604   return 0;
1605 }
1606
1607 //=============================================================================
1608 // Creation d' une Surface de Geom a partir d' une Surface de Step
1609 //=============================================================================
1610
1611 Handle(Geom_Surface) StepToGeom::MakeSurface (const Handle(StepGeom_Surface)& SS)
1612 {
1613    // sln 01.10.2001 BUC61003. If entry shell is NULL do nothing
1614   if(SS.IsNull()) {
1615     return Handle(Geom_Surface)();
1616   }
1617
1618   try {
1619     OCC_CATCH_SIGNALS
1620     if (SS->IsKind(STANDARD_TYPE(StepGeom_BoundedSurface))) {
1621       return MakeBoundedSurface (Handle(StepGeom_BoundedSurface)::DownCast(SS));
1622     }
1623     if (SS->IsKind(STANDARD_TYPE(StepGeom_ElementarySurface))) {
1624       const Handle(StepGeom_ElementarySurface) S1 = Handle(StepGeom_ElementarySurface)::DownCast(SS);
1625       if(S1->Position().IsNull())
1626         return Handle(Geom_Surface)();
1627
1628       return MakeElementarySurface (S1);
1629     }
1630     if (SS->IsKind(STANDARD_TYPE(StepGeom_SweptSurface))) {
1631       return MakeSweptSurface (Handle(StepGeom_SweptSurface)::DownCast(SS));
1632     }
1633     if (SS->IsKind(STANDARD_TYPE(StepGeom_OffsetSurface))) { //:d4 abv 12 Mar 98
1634       const Handle(StepGeom_OffsetSurface) OS = Handle(StepGeom_OffsetSurface)::DownCast(SS);
1635
1636       Handle(Geom_Surface) aBasisSurface = MakeSurface (OS->BasisSurface());
1637       if (! aBasisSurface.IsNull())
1638       {
1639         // sln 03.10.01. BUC61003. creation of  offset surface is corrected
1640         const Standard_Real anOffset = OS->Distance() * UnitsMethods::LengthFactor();
1641         if (aBasisSurface->Continuity() == GeomAbs_C0)
1642         {
1643           const BRepBuilderAPI_MakeFace aBFace(aBasisSurface, Precision::Confusion());
1644           if (aBFace.IsDone())
1645           {
1646             const TopoDS_Shape aResult = ShapeAlgo::AlgoContainer()->C0ShapeToC1Shape(aBFace.Face(), Abs(anOffset));
1647             if (aResult.ShapeType() == TopAbs_FACE)
1648             {
1649               aBasisSurface = BRep_Tool::Surface(TopoDS::Face(aResult));
1650             }
1651           }
1652         }
1653         if(aBasisSurface->Continuity() != GeomAbs_C0)
1654         {
1655           return new Geom_OffsetSurface ( aBasisSurface, anOffset );
1656         }
1657       }
1658     }
1659     else if (SS->IsKind(STANDARD_TYPE(StepGeom_SurfaceReplica))) { //:n7 abv 16 Feb 99
1660       const Handle(StepGeom_SurfaceReplica) SR = Handle(StepGeom_SurfaceReplica)::DownCast(SS);
1661       const Handle(StepGeom_Surface) PS = SR->ParentSurface();
1662       const Handle(StepGeom_CartesianTransformationOperator3d) T = SR->Transformation();
1663       // protect against cyclic references and wrong type of cartop
1664       if ( !T.IsNull() && PS != SS ) {
1665         Handle(Geom_Surface) S1 = MakeSurface (PS);
1666         if (! S1.IsNull())
1667         {
1668           gp_Trsf T1;
1669           if (MakeTransformation3d(T,T1))
1670           {
1671             S1->Transform ( T1 );
1672             return S1;
1673           }
1674         }
1675       }
1676     }
1677   }
1678   catch(Standard_Failure const& anException) {
1679 #ifdef OCCT_DEBUG
1680 //   ShapeTool_DB ?
1681 //:s5
1682     std::cout<<"Warning: MakeSurface: Exception:";
1683     anException.Print(std::cout); std::cout << std::endl;
1684 #endif
1685     (void)anException;
1686   }
1687   return 0;
1688 }
1689
1690 //=============================================================================
1691 // Creation d' une SurfaceOfLinearExtrusion de Geom a partir d' une
1692 // SurfaceOfLinearExtrusion de Step
1693 //=============================================================================
1694
1695 Handle(Geom_SurfaceOfLinearExtrusion) StepToGeom::MakeSurfaceOfLinearExtrusion (const Handle(StepGeom_SurfaceOfLinearExtrusion)& SS)
1696 {
1697   Handle(Geom_Curve) C = MakeCurve (SS->SweptCurve());
1698   if (! C.IsNull())
1699   {
1700     // sln 23.10.2001. CTS23496: Surface is not created if extrusion axis have not been successfully created
1701     Handle(Geom_VectorWithMagnitude) V = MakeVectorWithMagnitude (SS->ExtrusionAxis());
1702     if (! V.IsNull())
1703     {
1704       const gp_Dir D(V->Vec());
1705       Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(C);
1706       if (!aLine.IsNull() && aLine->Lin().Direction().IsParallel(D, Precision::Angular()))
1707         return Handle(Geom_SurfaceOfLinearExtrusion)();
1708       return new Geom_SurfaceOfLinearExtrusion(C,D);
1709     }
1710   }
1711   return 0;
1712 }
1713
1714 //=============================================================================
1715 // Creation d' une SurfaceOfRevolution de Geom a partir d' une
1716 // SurfaceOfRevolution de Step
1717 //=============================================================================
1718
1719 Handle(Geom_SurfaceOfRevolution) StepToGeom::MakeSurfaceOfRevolution (const Handle(StepGeom_SurfaceOfRevolution)& SS)
1720 {
1721   Handle(Geom_Curve) C = MakeCurve (SS->SweptCurve());
1722   if (! C.IsNull())
1723   {
1724     Handle(Geom_Axis1Placement) A1 = MakeAxis1Placement (SS->AxisPosition());
1725     if (! A1.IsNull())
1726     {
1727       const gp_Ax1 A( A1->Ax1() );
1728       //skl for OCC952 (one bad case revolution of circle)
1729       if ( C->IsKind(STANDARD_TYPE(Geom_Circle)) || C->IsKind(STANDARD_TYPE(Geom_Ellipse)) )
1730       {
1731         const Handle(Geom_Conic) conic = Handle(Geom_Conic)::DownCast(C);
1732         const gp_Pnt pc = conic->Location();
1733         const gp_Lin rl (A);
1734         if (rl.Distance(pc) < Precision::Confusion()) { //pc lies on A2
1735           const gp_Dir dirline = A.Direction();
1736           const gp_Dir norm = conic->Axis().Direction();
1737           const gp_Dir xAxis = conic->XAxis().Direction();
1738           //checking A2 lies on plane of circle
1739           if( dirline.IsNormal(norm,Precision::Angular()) && (dirline.IsParallel(xAxis,Precision::Angular()) || C->IsKind(STANDARD_TYPE(Geom_Circle)))) {
1740             //change parametrization for trimming
1741             gp_Ax2 axnew(pc,norm,dirline.Reversed());
1742             conic->SetPosition(axnew);
1743             C = new Geom_TrimmedCurve(conic, 0., M_PI);
1744           }
1745         }
1746       }
1747       return new Geom_SurfaceOfRevolution(C, A);
1748     }
1749   }
1750   return 0;
1751 }
1752
1753 //=============================================================================
1754 // Creation d' une SweptSurface de prostep a partir d' une
1755 // SweptSurface de Geom
1756 //=============================================================================
1757
1758 Handle(Geom_SweptSurface) StepToGeom::MakeSweptSurface (const Handle(StepGeom_SweptSurface)& SS)
1759 {
1760   if (SS->IsKind(STANDARD_TYPE(StepGeom_SurfaceOfLinearExtrusion))) {
1761     return MakeSurfaceOfLinearExtrusion (Handle(StepGeom_SurfaceOfLinearExtrusion)::DownCast(SS));
1762   }
1763   if (SS->IsKind(STANDARD_TYPE(StepGeom_SurfaceOfRevolution))) {
1764     return MakeSurfaceOfRevolution (Handle(StepGeom_SurfaceOfRevolution)::DownCast(SS));
1765   }
1766   return Handle(Geom_SweptSurface)();
1767 }
1768
1769 //=============================================================================
1770 // Creation d' une ToroidalSurface de Geom a partir d' une
1771 // ToroidalSurface de Step
1772 //=============================================================================
1773
1774 Handle(Geom_ToroidalSurface) StepToGeom::MakeToroidalSurface (const Handle(StepGeom_ToroidalSurface)& SS)
1775 {
1776   Handle(Geom_Axis2Placement) A = MakeAxis2Placement (SS->Position());
1777   if (! A.IsNull())
1778   {
1779     const Standard_Real LF = UnitsMethods::LengthFactor();
1780     return new Geom_ToroidalSurface(A->Ax2(), Abs(SS->MajorRadius() * LF), Abs(SS->MinorRadius() * LF));
1781   }
1782   return 0;
1783 }
1784
1785 //=======================================================================
1786 //function : MakeTransformation2d
1787 //purpose  :
1788 //=======================================================================
1789 Standard_Boolean StepToGeom::MakeTransformation2d (const Handle(StepGeom_CartesianTransformationOperator2d)& SCTO, gp_Trsf2d& CT)
1790 {
1791   //  NB : on ne s interesse ici qu au deplacement rigide
1792   Handle(Geom2d_CartesianPoint) CP = MakeCartesianPoint2d (SCTO->LocalOrigin());
1793   if (! CP.IsNull())
1794   {
1795     gp_Dir2d D1(1.,0.);
1796     // sln 23.10.2001. CTS23496: If problems with creation of direction occur default direction is used
1797     const Handle(StepGeom_Direction) A = SCTO->Axis1();
1798     if (!A.IsNull())
1799     {
1800       Handle(Geom2d_Direction) D = MakeDirection2d (A);
1801       if (! D.IsNull())
1802         D1 = D->Dir2d();
1803     }
1804     const gp_Ax2d result(CP->Pnt2d(),D1);
1805     CT.SetTransformation(result);
1806     CT = CT.Inverted();
1807     return Standard_True;
1808   }
1809   return Standard_False;
1810 }
1811
1812 //=======================================================================
1813 //function : MakeTransformation3d
1814 //purpose  :
1815 //=======================================================================
1816
1817 Standard_Boolean StepToGeom::MakeTransformation3d (const Handle(StepGeom_CartesianTransformationOperator3d)& SCTO, gp_Trsf& CT)
1818 {
1819   Handle(Geom_CartesianPoint) CP = MakeCartesianPoint (SCTO->LocalOrigin());
1820   if (! CP.IsNull())
1821   {
1822     const gp_Pnt Pgp = CP->Pnt();
1823
1824     // sln 23.10.2001. CTS23496: If problems with creation of direction occur default direction is used
1825     gp_Dir D1(1.,0.,0.);
1826     const Handle(StepGeom_Direction) A1 = SCTO->Axis1();
1827     if (!A1.IsNull()) {
1828       Handle(Geom_Direction) D = MakeDirection (A1);
1829       if (! D.IsNull())
1830         D1 = D->Dir();
1831     }
1832
1833     gp_Dir D2(0.,1.,0.);
1834     const Handle(StepGeom_Direction) A2 = SCTO->Axis2();
1835     if (!A2.IsNull()) {
1836       Handle(Geom_Direction) D = MakeDirection (A2);
1837       if (! D.IsNull())
1838         D2 = D->Dir();
1839     }
1840
1841     Standard_Boolean isDefaultDirectionUsed = Standard_True;
1842     gp_Dir D3;
1843     const Handle(StepGeom_Direction) A3 = SCTO->Axis3();
1844     if (!A3.IsNull()) {
1845       Handle(Geom_Direction) D = MakeDirection (A3);
1846       if (! D.IsNull())
1847       {
1848         D3 = D->Dir();
1849         isDefaultDirectionUsed = Standard_False;
1850       }
1851     }
1852     if(isDefaultDirectionUsed)
1853       D3 = D1.Crossed(D2);
1854
1855     const gp_Ax3 result(Pgp,D3,D1);
1856     CT.SetTransformation(result);
1857     CT = CT.Inverted(); //:n8 abv 16 Feb 99: tr8_as2_db.stp: reverse for accordance with LV tool
1858     return Standard_True;
1859   }
1860   return Standard_False;
1861 }
1862
1863 // ----------------------------------------------------------------
1864 // ExtractParameter
1865 // ----------------------------------------------------------------
1866 //:o6 abv 18 Feb 99: parameter Factor added
1867 //:p3 abv 23 Feb 99: parameter Shift added
1868 static Standard_Boolean  ExtractParameter
1869 (const Handle(Geom_Curve) &  aGeomCurve,
1870  const Handle(StepGeom_HArray1OfTrimmingSelect) & TS,
1871  const Standard_Integer nbSel,
1872  const Standard_Integer MasterRep,
1873  const Standard_Real Factor,
1874  const Standard_Real Shift,
1875  Standard_Real & aParam)
1876 {
1877   Handle(StepGeom_CartesianPoint) aPoint;
1878   Standard_Integer i;
1879 //:S4136  Standard_Real precBrep = BRepAPI::Precision();
1880   for ( i = 1 ; i <= nbSel ; i++) {
1881     StepGeom_TrimmingSelect theSel = TS->Value(i);
1882     if (MasterRep == 2 && theSel.CaseMember() > 0) {
1883       aParam = Shift + Factor * theSel.ParameterValue();
1884       return Standard_True;
1885     }
1886     else if (MasterRep == 1 && theSel.CaseNumber() > 0) {
1887       aPoint = theSel.CartesianPoint();
1888       Handle(Geom_CartesianPoint) theGeomPnt = StepToGeom::MakeCartesianPoint (aPoint);
1889       gp_Pnt thegpPnt = theGeomPnt->Pnt();
1890
1891       //:S4136: use advanced algorithm
1892       ShapeAnalysis_Curve sac;
1893       gp_Pnt p;
1894       sac.Project ( aGeomCurve, thegpPnt, Precision::Confusion(), p, aParam );
1895 /* //:S4136
1896       //Trim == natural boundary ?
1897       if(aGeomCurve->IsKind(STANDARD_TYPE(Geom_BoundedCurve))) {
1898         Standard_Real frstPar = aGeomCurve->FirstParameter();
1899         Standard_Real lstPar = aGeomCurve->LastParameter();
1900         gp_Pnt frstPnt = aGeomCurve->Value(frstPar);
1901         gp_Pnt lstPnt = aGeomCurve->Value(lstPar);
1902         if(frstPnt.IsEqual(thegpPnt,precBrep)) {
1903           aParam = frstPar;
1904           return Standard_True;
1905         }
1906         if(lstPnt.IsEqual(thegpPnt,precBrep)) {
1907           aParam = lstPar;
1908           return Standard_True;
1909         }
1910       }
1911       // Project Point On Curve
1912       GeomAPI_ProjectPointOnCurve PPOC(thegpPnt, aGeomCurve);
1913       if (PPOC.NbPoints() == 0) {
1914         return Standard_False;
1915       }
1916       aParam = PPOC.LowerDistanceParameter();
1917 */
1918       return Standard_True;
1919     }
1920   }
1921 // if the MasterRepresentation is unspecified:
1922 // if a ParameterValue exists, it is preferred
1923
1924   for ( i = 1 ; i <= nbSel ; i++) {
1925     StepGeom_TrimmingSelect theSel = TS->Value(i);
1926     if (theSel.CaseMember() > 0) {
1927       aParam = Shift + Factor * theSel.ParameterValue();
1928
1929       return Standard_True;
1930     }
1931   }
1932 // if no ParameterValue exists, it is created from the CartesianPointValue
1933
1934   for ( i = 1 ; i <= nbSel ; i++) {
1935     StepGeom_TrimmingSelect theSel = TS->Value(i);
1936     if (theSel.CaseNumber() > 0) {
1937       aPoint = theSel.CartesianPoint();
1938       Handle(Geom_CartesianPoint) theGeomPnt = StepToGeom::MakeCartesianPoint (aPoint);
1939       gp_Pnt thegpPnt = theGeomPnt->Pnt();
1940       // Project Point On Curve
1941       ShapeAnalysis_Curve sac;
1942       gp_Pnt p;
1943       sac.Project ( aGeomCurve, thegpPnt, Precision::Confusion(), p, aParam );
1944 /*
1945       GeomAPI_ProjectPointOnCurve PPOC(thegpPnt, aGeomCurve);
1946       if (PPOC.NbPoints() == 0) {
1947         return Standard_False;
1948       }
1949       aParam = PPOC.LowerDistanceParameter();
1950 */
1951       return Standard_True;
1952     }
1953   }
1954   return Standard_False;  // I suppose
1955 }
1956
1957
1958 //=============================================================================
1959 // Creation d' une Trimmed Curve de Geom a partir d' une Trimmed Curve de Step
1960 //=============================================================================
1961
1962 Handle(Geom_TrimmedCurve) StepToGeom::MakeTrimmedCurve (const Handle(StepGeom_TrimmedCurve)& SC)
1963 {
1964   const Handle(StepGeom_Curve) theSTEPCurve = SC->BasisCurve();
1965   Handle(Geom_Curve) theCurve = MakeCurve (theSTEPCurve);
1966   if (theCurve.IsNull())
1967     return Handle(Geom_TrimmedCurve)();
1968
1969   const Handle(StepGeom_HArray1OfTrimmingSelect)& theTrimSel1 = SC->Trim1();
1970   const Handle(StepGeom_HArray1OfTrimmingSelect)& theTrimSel2 = SC->Trim2();
1971   const Standard_Integer nbSel1 = SC->NbTrim1();
1972   const Standard_Integer nbSel2 = SC->NbTrim2();
1973
1974   Standard_Integer MasterRep;
1975   switch (SC->MasterRepresentation())
1976   {
1977     case StepGeom_tpCartesian: MasterRep = 1; break;
1978     case StepGeom_tpParameter: MasterRep = 2; break;
1979     default: MasterRep = 0;
1980   }
1981
1982   //gka 18.02.04 analysis for case when MasterRep = .Unspecified
1983   //and parameters are specified as CARTESIAN_POINT
1984   Standard_Boolean isPoint = Standard_False;
1985   if(MasterRep == 0 || (MasterRep == 2 && nbSel1 >1 && nbSel2 > 1)) {
1986     Standard_Integer ii;
1987     for(ii = 1; ii <= nbSel1; ii++)
1988     {
1989       if (!(theTrimSel1->Value(ii).CartesianPoint().IsNull()))
1990       {
1991         for(ii = 1; ii <= nbSel2; ii++)
1992         {
1993           if (!(theTrimSel2->Value(ii).CartesianPoint().IsNull()))
1994           {
1995             isPoint = Standard_True;
1996             break;
1997           }
1998         }
1999         break;
2000       }
2001     }
2002   }
2003
2004   //:o6 abv 18 Feb 99: computation of factor moved
2005   Standard_Real fact = 1., shift = 0.;
2006   if (theSTEPCurve->IsKind(STANDARD_TYPE(StepGeom_Line))) {
2007     const Handle(StepGeom_Line) theLine =
2008       Handle(StepGeom_Line)::DownCast(theSTEPCurve);
2009     fact = theLine->Dir()->Magnitude() * UnitsMethods::LengthFactor();
2010   }
2011   else if (theSTEPCurve->IsKind(STANDARD_TYPE(StepGeom_Circle)) ||
2012            theSTEPCurve->IsKind(STANDARD_TYPE(StepGeom_Ellipse))) {
2013 //    if (trim1 > 2.1*M_PI || trim2 > 2.1*M_PI) fact = M_PI / 180.;
2014     fact = UnitsMethods::PlaneAngleFactor();
2015     //:p3 abv 23 Feb 99: shift on pi/2 on ellipse with R1 < R2
2016     const Handle(StepGeom_Ellipse) ellipse = Handle(StepGeom_Ellipse)::DownCast(theSTEPCurve);
2017     if ( !ellipse.IsNull() && ellipse->SemiAxis1() - ellipse->SemiAxis2() < 0. )
2018       shift = 0.5 * M_PI;
2019
2020     // skl 04.02.2002 for OCC133: we can not make TrimmedCurve if
2021     // there is no X-direction in StepGeom_Axis2Placement3d
2022     const Handle(StepGeom_Conic) conic = Handle(StepGeom_Conic)::DownCast(theSTEPCurve);
2023     // CKY 6-FEB-2004 for Airbus-MedialAxis :
2024     // this restriction does not apply for trimming by POINTS
2025     if(!conic.IsNull() && MasterRep != 1) {
2026       const StepGeom_Axis2Placement a2p = conic->Position();
2027       if(a2p.CaseNum(a2p.Value())==2) {
2028         if( !a2p.Axis2Placement3d()->HasRefDirection() ) {
2029           ////gka 18.02.04 analysis for case when MasterRep = .Unspecified
2030           //and parameters are specified as CARTESIAN_POINT
2031           if(isPoint /*&& !MasterRep*/)
2032             MasterRep =1;
2033           else {
2034             if ( SC->SenseAgreement() )
2035               return new Geom_TrimmedCurve(theCurve, 0., 2.*M_PI, Standard_True);
2036             else
2037               return new Geom_TrimmedCurve(theCurve, 2.*M_PI, 0., Standard_False);
2038           }
2039         }
2040       }
2041     }
2042   }
2043
2044   Standard_Real trim1 = 0.;
2045   Standard_Real trim2 = 0.;
2046   Handle(StepGeom_CartesianPoint) TrimCP1, TrimCP2;
2047   const Standard_Boolean FoundParam1 = ExtractParameter(theCurve, theTrimSel1, nbSel1, MasterRep, fact, shift, trim1);
2048   const Standard_Boolean FoundParam2 = ExtractParameter(theCurve, theTrimSel2, nbSel2, MasterRep, fact, shift, trim2);
2049
2050   if (FoundParam1 && FoundParam2) {
2051     const Standard_Real cf = theCurve->FirstParameter();
2052     const Standard_Real cl = theCurve->LastParameter();
2053     //: abv 09.04.99: S4136: bm2_ug_t4-B.stp #70610: protect against OutOfRange
2054     if ( !theCurve->IsPeriodic() ) {
2055       if ( trim1 < cf ) trim1 = cf;
2056       else if ( trim1 > cl ) trim1 = cl;
2057       if ( trim2 < cf ) trim2 = cf;
2058       else if ( trim2 > cl ) trim2 = cl;
2059     }
2060     if (Abs(trim1 - trim2) < Precision::PConfusion()) {
2061       if (theCurve->IsPeriodic()) {
2062         ElCLib::AdjustPeriodic(cf,cl,Precision::PConfusion(),trim1,trim2);
2063       }
2064       else if (theCurve->IsClosed()) {
2065         if (Abs(trim1 - cf) < Precision::PConfusion()) {
2066           trim2 += cl;
2067         }
2068         else {
2069           trim1 -= cl;
2070         }
2071       }
2072       else {
2073         return 0;
2074       }
2075     }
2076 //  CKY 16-DEC-1997 : USA60035 le texte de Part42 parle de degres
2077 //    mais des systemes ecrivent en radians. Exploiter UnitsMethods
2078 //:o6    trim1 = trim1 * fact;
2079 //:o6    trim2 = trim2 * fact;
2080     if ( SC->SenseAgreement() )
2081       return new Geom_TrimmedCurve(theCurve, trim1, trim2, Standard_True);
2082     else //:abv 29.09.00 PRO20362: reverse parameters in case of reversed curve
2083       return new Geom_TrimmedCurve(theCurve, trim2, trim1, Standard_False);
2084   }
2085   return 0;
2086 }
2087
2088 //=============================================================================
2089 // Creation d'une Trimmed Curve de Geom2d a partir d' une Trimmed Curve de Step
2090 //=============================================================================
2091 // Shall be completed to treat trimming with points
2092
2093 Handle(Geom2d_BSplineCurve) StepToGeom::MakeTrimmedCurve2d (const Handle(StepGeom_TrimmedCurve)& SC)
2094 {
2095   const Handle(StepGeom_Curve) BasisCurve = SC->BasisCurve();
2096   Handle(Geom2d_Curve) theGeomBasis = MakeCurve2d (BasisCurve);
2097   if (theGeomBasis.IsNull())
2098     return Handle(Geom2d_BSplineCurve)();
2099
2100   if (theGeomBasis->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
2101     return Handle(Geom2d_BSplineCurve)::DownCast(theGeomBasis);
2102   }
2103
2104   const Handle(StepGeom_HArray1OfTrimmingSelect)& theTrimSel1 = SC->Trim1();
2105   const Handle(StepGeom_HArray1OfTrimmingSelect)& theTrimSel2 = SC->Trim2();
2106   const Standard_Integer nbSel1 = SC->NbTrim1();
2107   const Standard_Integer nbSel2 = SC->NbTrim2();
2108   if ((nbSel1 == 1) && (nbSel2 == 1) &&
2109       (theTrimSel1->Value(1).CaseMember() > 0) &&
2110       (theTrimSel2->Value(1).CaseMember() > 0))
2111   {
2112     const Standard_Real u1 = theTrimSel1->Value(1).ParameterValue();
2113     const Standard_Real u2 = theTrimSel2->Value(1).ParameterValue();
2114     Standard_Real fact = 1., shift = 0.;
2115
2116     if (BasisCurve->IsKind(STANDARD_TYPE(StepGeom_Line))) {
2117       const Handle(StepGeom_Line) theLine = Handle(StepGeom_Line)::DownCast(BasisCurve);
2118       fact = theLine->Dir()->Magnitude();
2119     }
2120     else if (BasisCurve->IsKind(STANDARD_TYPE(StepGeom_Circle)) ||
2121              BasisCurve->IsKind(STANDARD_TYPE(StepGeom_Ellipse))) {
2122 //      if (u1 > 2.1*M_PI || u2 > 2.1*M_PI) fact = M_PI / 180.;
2123       fact = UnitsMethods::PlaneAngleFactor();
2124       //:p3 abv 23 Feb 99: shift on pi/2 on ellipse with R1 < R2
2125       const Handle(StepGeom_Ellipse) ellipse = Handle(StepGeom_Ellipse)::DownCast(BasisCurve);
2126       if ( !ellipse.IsNull() && ellipse->SemiAxis1() - ellipse->SemiAxis2() < 0. )
2127         shift = 0.5 * M_PI;
2128     }
2129     else if (BasisCurve->IsKind(STANDARD_TYPE(StepGeom_Parabola)) ||
2130              BasisCurve->IsKind(STANDARD_TYPE(StepGeom_Hyperbola))) {
2131       // LATER !!!
2132     }
2133 //    CKY 16-DEC-1997 : USA60035 le texte de Part42 parle de degres
2134 //      mais des systemes ecrivent en radians. Exploiter UnitsMethods
2135
2136     const Standard_Real newU1 = shift + u1 * fact;
2137     const Standard_Real newU2 = shift + u2 * fact;
2138
2139     const Handle(Geom2d_TrimmedCurve) theTrimmed =
2140       new Geom2d_TrimmedCurve(theGeomBasis, newU1, newU2, SC->SenseAgreement());
2141     return Geom2dConvert::CurveToBSplineCurve(theTrimmed);
2142   }
2143   return 0;
2144 }
2145
2146 //=============================================================================
2147 // Creation d' un VectorWithMagnitude de Geom a partir d' un Vector de Step
2148 //=============================================================================
2149
2150 Handle(Geom_VectorWithMagnitude) StepToGeom::MakeVectorWithMagnitude (const Handle(StepGeom_Vector)& SV)
2151 {
2152   // sln 22.10.2001. CTS23496: Vector is not created if direction have not been successfully created
2153   Handle(Geom_Direction) D = MakeDirection (SV->Orientation());
2154   if (! D.IsNull())
2155   {
2156     const gp_Vec V(D->Dir().XYZ() * SV->Magnitude() * UnitsMethods::LengthFactor());
2157     return new Geom_VectorWithMagnitude(V);
2158   }
2159   return 0;
2160 }
2161
2162 //=============================================================================
2163 // Creation d' un VectorWithMagnitude de Geom2d a partir d' un Vector de Step
2164 //=============================================================================
2165
2166 Handle(Geom2d_VectorWithMagnitude) StepToGeom::MakeVectorWithMagnitude2d (const Handle(StepGeom_Vector)& SV)
2167 {
2168   // sln 23.10.2001. CTS23496: Vector is not created if direction have not been successfully created (MakeVectorWithMagnitude2d(...) function)
2169   Handle(Geom2d_Direction) D = MakeDirection2d (SV->Orientation());
2170   if (! D.IsNull())
2171   {
2172     const gp_Vec2d V(D->Dir2d().XY() * SV->Magnitude());
2173     return new Geom2d_VectorWithMagnitude(V);
2174   }
2175   return 0;
2176 }