0024947: Redesign OCCT legacy type system -- automatic
[occt.git] / src / ShapeBuild / ShapeBuild_Edge.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 //#4  szv          S4163: optimizing
15 //    pdn 20.04.99 S4181  Moving algorithm for transforming pcurves from IGES processor
16 //    abv 05.05.99 S4137: adding methods for copying ranges, reassigning pcurves etc.
17 #include <ShapeBuild_Edge.ixx>
18 #include <Standard_ErrorHandler.hxx>
19 #include <Standard_Failure.hxx>
20
21 #include <TopoDS.hxx>
22 #include <TopoDS_Iterator.hxx>
23 #include <TopExp.hxx>
24 #include <BRep_Builder.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRep_TEdge.hxx>
27 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
28 #include <BRep_GCurve.hxx>
29 #include <BRepLib.hxx>
30 #include <BRepBuilderAPI_MakeEdge.hxx>
31
32 #include <gp_Pnt.hxx>
33 #include <gp_Lin2d.hxx>
34 #include <gp_GTrsf2d.hxx>
35 #include <gp_Pln.hxx>
36 #include <ElCLib.hxx>
37 #include <Precision.hxx>
38
39 #include <Geom2d_TrimmedCurve.hxx>
40 #include <Geom2d_Line.hxx>
41 #include <Geom2d_BSplineCurve.hxx>
42 #include <Geom2d_Conic.hxx>
43 #include <Geom2dConvert.hxx>
44 #include <Geom2dConvert_ApproxCurve.hxx>
45 #include <GeomAPI.hxx>
46 #include <Geom2d_BezierCurve.hxx>
47 #include <Geom2d_TrimmedCurve.hxx>
48 #include <BRep_Curve3D.hxx>
49 #include <BRep_CurveOnSurface.hxx>
50 #include <Geom2d_OffsetCurve.hxx>
51 #include <Geom_TrimmedCurve.hxx>
52 #include <Geom_OffsetCurve.hxx>
53 #include <TopTools_SequenceOfShape.hxx>
54 #include <Geom2d_Curve.hxx>
55
56 //=======================================================================
57 //function : CopyReplaceVertices
58 //purpose  : 
59 //=======================================================================
60
61 TopoDS_Edge ShapeBuild_Edge::CopyReplaceVertices (const TopoDS_Edge& edge,
62   const TopoDS_Vertex& V1,
63   const TopoDS_Vertex& V2) const
64 {
65   TopTools_SequenceOfShape aNMVertices;
66   TopoDS_Vertex newV1 = V1, newV2 = V2;
67   if ( newV1.IsNull() || newV2.IsNull() ) {
68     TopoDS_Iterator it;
69     if(edge.Orientation() == TopAbs_FORWARD ||
70        edge.Orientation() == TopAbs_REVERSED)
71     {
72       it.Initialize(edge, Standard_True, Standard_True);
73     }
74     else
75     {
76       it.Initialize(edge, Standard_False, Standard_True);
77     }
78     for ( ; it.More(); it.Next() ) {
79       TopoDS_Vertex V = TopoDS::Vertex ( it.Value() );
80       if ( V.Orientation() == TopAbs_FORWARD ) {
81         if ( newV1.IsNull() ) newV1 = V;
82       }
83       else if ( V.Orientation() == TopAbs_REVERSED ) {
84         if ( newV2.IsNull() ) newV2 = V;
85       }
86       else if(V1.IsNull() && V2.IsNull())
87         aNMVertices.Append(V);
88     }
89   }
90   newV1.Orientation ( TopAbs_FORWARD );
91   newV2.Orientation ( TopAbs_REVERSED );
92
93   //szv#4:S4163:12Mar99 SGI warns
94   TopoDS_Shape sh = edge.EmptyCopied();
95   TopoDS_Edge E = TopoDS::Edge( sh );
96
97   BRep_Builder B;
98   if ( ! newV1.IsNull() ) B.Add ( E, newV1 );
99   if ( ! newV2.IsNull() ) B.Add ( E, newV2 );
100
101   //addition of the internal or external vertices to edge
102   Standard_Integer i =1; 
103   for( ; i <= aNMVertices.Length(); i++)
104     B.Add ( E,TopoDS::Vertex(aNMVertices.Value(i)));
105
106   //S4054, rln 17.11.98 annie_surf.igs entity D77, 3D and pcurve have different
107   //ranges, after B.Range all the ranges become as 3D
108   CopyRanges ( E, edge );
109   /*
110   for (BRep_ListIteratorOfListOfCurveRepresentation itcr
111   ((*((Handle(BRep_TEdge)*)&edge.TShape()))->ChangeCurves()); itcr.More(); itcr.Next()) {
112   Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
113   if ( GC.IsNull() ) continue;
114   Standard_Real first, last;
115   GC->Range ( first, last );
116   if ( GC->IsCurve3D() ) 
117   B.Range ( E, first, last );
118   else if ( GC->IsCurveOnSurface() )
119   B.Range (E, GC->Surface(), edge.Location().Multiplied (GC->Location()), first, last);//BUC50003 entity 132 edge 1
120   }
121   */
122   return E;
123 }
124
125 //=======================================================================
126 //function : CopyRanges
127 //purpose  : 
128 //=======================================================================
129
130 // Added, cause invoke ShapeAnalysis leads to cyclic dependancy.
131 static Standard_Real AdjustByPeriod(const Standard_Real Val,
132   const Standard_Real ToVal,
133   const Standard_Real Period)
134 {
135   Standard_Real diff = Val - ToVal;
136   Standard_Real D = Abs ( diff );
137   Standard_Real P = Abs ( Period );
138   if ( D <= 0.5 * P ) return 0.;
139   if ( P < 1e-100 ) return diff;
140   return ( diff >0 ? -P : P ) * (Standard_Integer)( D / P + 0.5 );
141 }
142
143 static Standard_Boolean IsPeriodic(const Handle(Geom_Curve)& theCurve)
144 {
145   // 15.11.2002 PTV OCC966
146   // remove regressions in DE tests (diva, divb, divc, toe3) in KAS:dev
147   // ask IsPeriodic on BasisCurve
148   Handle(Geom_Curve) aTmpCurve = theCurve;
149   while ( (aTmpCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) ||
150     (aTmpCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) ) {
151       if (aTmpCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
152         aTmpCurve = Handle(Geom_OffsetCurve)::DownCast(aTmpCurve)->BasisCurve();
153       if (aTmpCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
154         aTmpCurve = Handle(Geom_TrimmedCurve)::DownCast(aTmpCurve)->BasisCurve();
155   }
156   return aTmpCurve->IsPeriodic();
157 }
158
159 Standard_Boolean IsPeriodic(const Handle(Geom2d_Curve)& theCurve)
160 {
161   // 15.11.2002 PTV OCC966
162   // remove regressions in DE tests (diva, divb, divc, toe3) in KAS:dev
163   // ask IsPeriodic on BasisCurve
164   Handle(Geom2d_Curve) aTmpCurve = theCurve;
165   while ( (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) ||
166     (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) ) {
167       if (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
168         aTmpCurve = Handle(Geom2d_OffsetCurve)::DownCast(aTmpCurve)->BasisCurve();
169       if (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
170         aTmpCurve = Handle(Geom2d_TrimmedCurve)::DownCast(aTmpCurve)->BasisCurve();
171   }
172   return aTmpCurve->IsPeriodic();
173 }
174
175 void ShapeBuild_Edge::CopyRanges (const TopoDS_Edge& toedge, 
176   const TopoDS_Edge& fromedge,
177   const Standard_Real alpha,
178   const Standard_Real beta) const
179 {
180   /*  BRep_Builder B;
181   for (BRep_ListIteratorOfListOfCurveRepresentation itcr
182   ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); itcr.More(); itcr.Next()) {
183   Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
184   if ( GC.IsNull() ) continue;
185   Standard_Real first, last;
186   GC->Range ( first, last );
187   if ( GC->IsCurve3D() ) 
188   B.Range ( toedge, first, last );
189   else if ( GC->IsCurveOnSurface() )
190   B.Range ( toedge, GC->Surface(), fromedge.Location().Multiplied (GC->Location()), first, last);
191   }
192   */
193   for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
194     ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
195       Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
196       if ( fromGC.IsNull() ) continue;
197       Standard_Boolean isC3d = fromGC->IsCurve3D();
198       if(isC3d) {
199         if(fromGC->Curve3D().IsNull()) continue; }
200       else {
201         if(fromGC->PCurve().IsNull()) continue; }
202
203       if ( ! isC3d && ! fromGC->IsCurveOnSurface()) continue; // only 3d curves and pcurves are treated
204
205       Handle(Geom_Surface) surface;
206       TopLoc_Location L;
207       if ( ! isC3d ) {
208         surface = fromGC->Surface();
209         L = fromGC->Location();
210       } 
211
212       BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
213       Handle(BRep_GCurve) toGC;
214       for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More(); toitcr.Next()) {
215         toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
216         if ( toGC.IsNull() ) continue;
217         if ( isC3d ) {
218           if ( ! toGC->IsCurve3D() ) continue;
219         }
220         else if ( ! toGC->IsCurveOnSurface() || 
221           surface != toGC->Surface() || L != toGC->Location() ) continue;
222         Standard_Real first = fromGC->First();
223         Standard_Real last = fromGC->Last();
224         Standard_Real len = last - first;
225         Standard_Real newF = first+alpha*len;
226         Standard_Real newL = first+beta*len;
227
228         // PTV: 22.03.2002 fix for edge range. 
229         // file test-m020306-v2.step Shell #665 (Faces #40110. #40239).
230         Standard_Real aPeriod=1., aCrvF=0., aCrvL=1.;
231         Standard_Boolean doCheck = Standard_False;
232         if (toGC->IsKind(STANDARD_TYPE(BRep_Curve3D))) {
233           Handle(Geom_Curve) aCrv3d = Handle(BRep_Curve3D)::DownCast(toGC)->Curve3D();
234           // 15.11.2002 PTV OCC966
235           if ( ! aCrv3d.IsNull() && IsPeriodic(aCrv3d) ) {
236             aPeriod = aCrv3d->Period();
237             aCrvF = aCrv3d->FirstParameter();
238             aCrvL = aCrv3d->LastParameter();
239             doCheck = Standard_True;
240           }
241         }
242         else if  (toGC->IsKind(STANDARD_TYPE(BRep_CurveOnSurface))) {
243           Handle(Geom2d_Curve) aCrv2d = Handle(BRep_CurveOnSurface)::DownCast(toGC)->PCurve();
244           // 15.11.2002 PTV OCC966
245           if (!aCrv2d.IsNull() && IsPeriodic(aCrv2d)) {
246             aPeriod = aCrv2d->Period();
247             aCrvF = aCrv2d->FirstParameter();
248             aCrvL = aCrv2d->LastParameter();
249             doCheck = Standard_True;
250           }
251         }
252         if ( doCheck && ( (fabs(newF -aCrvF ) > Precision::PConfusion() && newF < aCrvF) || newF >= aCrvL ) ) {
253           Standard_Real aShift = AdjustByPeriod(newF, 0.5*(aCrvF+aCrvL), aPeriod);
254           newF += aShift;
255           newL += aShift;
256           BRep_Builder().SameRange(toedge,Standard_False);
257           BRep_Builder().SameParameter(toedge,Standard_False);
258         }
259
260         toGC->SetRange ( newF, newL );
261         break;
262       }
263   }
264 }
265
266 //=======================================================================
267 //function : SetRange3d
268 //purpose  : 
269 //=======================================================================
270
271 void ShapeBuild_Edge::SetRange3d (const TopoDS_Edge& edge, 
272   const Standard_Real first,
273   const Standard_Real last) const
274 {
275
276   for (BRep_ListIteratorOfListOfCurveRepresentation itcr
277     ((*((Handle(BRep_TEdge)*)&edge.TShape()))->ChangeCurves()); itcr.More(); itcr.Next()) {
278       Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
279       if ( GC.IsNull() || !GC->IsCurve3D() ) continue;
280       GC->SetRange ( first, last );
281       break;
282   }
283 }
284
285 //=======================================================================
286 //function : CopyPCurves
287 //purpose  : 
288 //=======================================================================
289
290 void ShapeBuild_Edge::CopyPCurves (const TopoDS_Edge& toedge, const TopoDS_Edge& fromedge) const
291 {
292   TopLoc_Location fromLoc = fromedge.Location();
293   TopLoc_Location toLoc = toedge.Location();
294   for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
295     ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
296       Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
297       if ( fromGC.IsNull() ) continue;
298       if ( fromGC->IsCurveOnSurface() ) {
299         Handle(Geom_Surface) surface = fromGC->Surface();
300         TopLoc_Location L = fromGC->Location();
301         Standard_Boolean found = Standard_False;
302         BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
303         Handle(BRep_GCurve) toGC;
304         for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More() && !found; toitcr.Next()) {
305           toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
306           if ( toGC.IsNull() || !toGC->IsCurveOnSurface() || 
307             surface != toGC->Surface() || L != toGC->Location() ) continue;
308           found = Standard_True;
309           break;
310         }
311         if (!found) {
312           toGC = Handle(BRep_GCurve)::DownCast(fromGC->Copy());
313           tolist.Append (toGC);
314         }
315         Handle(Geom2d_Curve) pcurve = fromGC->PCurve();
316         toGC->PCurve(Handle(Geom2d_Curve)::DownCast(pcurve->Copy()));
317
318         //bug OCC209 invalid location of pcurve in the edge after copying
319         TopLoc_Location newLoc = (fromLoc*L).Predivided(toLoc);//(L * fromLoc).Predivided(toLoc);
320         toGC->Location(newLoc);
321         if ( fromGC->IsCurveOnClosedSurface() ) {
322           pcurve = fromGC->PCurve2();
323           toGC->PCurve2(Handle(Geom2d_Curve)::DownCast(pcurve->Copy()));
324         }
325       }
326   }
327 }
328 //=======================================================================
329 //function : Copy
330 //purpose  : 
331 //=======================================================================
332
333 TopoDS_Edge ShapeBuild_Edge::Copy (const TopoDS_Edge &edge, 
334   const Standard_Boolean sharepcurves) const
335 {
336   TopoDS_Vertex dummy1, dummy2;
337   TopoDS_Edge newedge = CopyReplaceVertices ( edge, dummy1, dummy2 );
338   if ( ! sharepcurves ) CopyPCurves ( newedge, edge );
339   return newedge;
340 }
341
342 //=======================================================================
343 //function : RemovePCurve
344 //purpose  : 
345 //=======================================================================
346
347 void ShapeBuild_Edge::RemovePCurve (const TopoDS_Edge& edge, 
348   const TopoDS_Face& face) const
349 {
350   BRep_Builder B;
351   Handle(Geom2d_Curve) c2dNull;
352   //:S4136  Standard_Real tol = BRep_Tool::Tolerance ( edge );
353   if ( BRep_Tool::IsClosed ( edge, face ) )
354     B.UpdateEdge ( edge, c2dNull, c2dNull, face, 0. ); //:S4136: tol
355   else B.UpdateEdge ( edge, c2dNull,          face, 0. ); //:S4136: tol
356 }
357
358 //=======================================================================
359 //function : RemovePCurve
360 //purpose  : 
361 //=======================================================================
362
363 void ShapeBuild_Edge::RemovePCurve (const TopoDS_Edge& edge,
364   const Handle(Geom_Surface)& surf) const
365 {
366   RemovePCurve ( edge, surf, TopLoc_Location() );
367 }
368
369 //=======================================================================
370 //function : RemovePCurve
371 //purpose  : 
372 //=======================================================================
373
374 void ShapeBuild_Edge::RemovePCurve (const TopoDS_Edge& edge,
375   const Handle(Geom_Surface)& surf,
376   const TopLoc_Location &loc) const
377 {
378   BRep_Builder B;
379   Handle(Geom2d_Curve) c2dNull;
380   //:S4136  Standard_Real tol = BRep_Tool::Tolerance ( edge );
381   if ( BRep_Tool::IsClosed ( edge, surf, loc ) )
382     B.UpdateEdge ( edge, c2dNull, c2dNull, surf, loc, 0. ); //:S4136: tol
383   else B.UpdateEdge ( edge, c2dNull,          surf, loc, 0. ); //:S4136: tol
384 }
385
386 //=======================================================================
387 //function : ReplacePCurve
388 //purpose  : 
389 //=======================================================================
390
391 void ShapeBuild_Edge::ReplacePCurve (const TopoDS_Edge& edge,
392   const Handle(Geom2d_Curve)& pcurve,
393   const TopoDS_Face& face) const
394 {
395   BRep_Builder B;
396   Standard_Real f,l;
397   TopoDS_Shape dummy = edge.Reversed();
398   TopoDS_Edge edgerev = TopoDS::Edge(dummy);
399   // reverse face to take second pcurve for seams like SA_Edge::PCurve() does
400   TopoDS_Face F = TopoDS::Face(face.Oriented ( TopAbs_FORWARD ) );
401   Handle(Geom2d_Curve) pcurve0 = BRep_Tool::CurveOnSurface(edge,F,f,l);
402   Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(edgerev,F,f,l);
403   // Add pcurve to edge (either as single, or as seam)
404   if ( c2d.IsNull() || c2d == pcurve0 ) { // non-seam 
405     B.UpdateEdge(edge,pcurve,face,0);
406   }
407   else { // seam
408     if(edge.Orientation()==TopAbs_FORWARD)
409       B.UpdateEdge(edge,pcurve,c2d,face,0);
410     else
411       B.UpdateEdge(edge,c2d,pcurve,face,0);
412   }
413   B.Range ( edge, face, f, l );
414 }
415
416 //=======================================================================
417 //function : ReassignPCurve
418 //purpose  : 
419 //=======================================================================
420
421 // Count exact number of pcurves STORED in edge for face
422 // This makes difference for faces based on plane surfaces where pcurves can be 
423 // not stored but returned by BRep_Tools::CurveOnSurface
424 static Standard_Integer CountPCurves (const TopoDS_Edge &edge, 
425   const TopoDS_Face &face)
426 {
427   TopLoc_Location L;
428   Handle(Geom_Surface) S = BRep_Tool::Surface ( face, L );
429   TopLoc_Location l = L.Predivided(edge.Location());
430
431   for (BRep_ListIteratorOfListOfCurveRepresentation itcr
432     ((*((Handle(BRep_TEdge)*)&edge.TShape()))->ChangeCurves()); itcr.More(); itcr.Next()) {
433       Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
434       if ( ! GC.IsNull() && GC->IsCurveOnSurface ( S, l ) ) 
435         return ( GC->IsCurveOnClosedSurface() ? 2 : 1 );
436   }
437   return 0;
438 }
439
440 Standard_Boolean ShapeBuild_Edge::ReassignPCurve (const TopoDS_Edge& edge,
441   const TopoDS_Face& old,
442   const TopoDS_Face& sub) const
443 {
444   Standard_Integer npcurves = CountPCurves ( edge, old );
445   //if ( npcurves <1 ) return Standard_False; //gka
446
447   Standard_Real f, l;
448   Handle(Geom2d_Curve) pc;
449   pc = BRep_Tool::CurveOnSurface ( edge, old, f, l );
450   if ( pc.IsNull() ) return Standard_False;
451   else if( npcurves == 0)  npcurves =1; //gka
452
453
454   BRep_Builder B;
455
456   // if the pcurve was only one, remove; else leave second one
457   if ( npcurves >1 ) {
458     //smh#8 Porting AIX
459     TopoDS_Shape tmpshape = edge.Reversed();
460     TopoDS_Edge erev = TopoDS::Edge (tmpshape);
461     Handle(Geom2d_Curve) pc2 = BRep_Tool::CurveOnSurface ( erev, old, f, l );
462     B.UpdateEdge ( edge, pc2, old, 0. );
463     B.Range ( edge, old, f, l );
464   }
465   else RemovePCurve ( edge, old );
466
467   // if edge does not have yet pcurves on sub, just add; else add as first
468   Standard_Integer npcs = CountPCurves ( edge, sub );
469   if ( npcs <1 ) B.UpdateEdge ( edge, pc, sub, 0. );
470   else {
471     //smh#8 Porting AIX
472     TopoDS_Shape tmpshape = edge.Reversed();
473     TopoDS_Edge erev = TopoDS::Edge (tmpshape);
474     Standard_Real cf, cl;
475     Handle(Geom2d_Curve) pcs = BRep_Tool::CurveOnSurface ( erev, sub, cf, cl );
476     if ( edge.Orientation() == TopAbs_REVERSED ) // because B.UpdateEdge does not check edge orientation
477       B.UpdateEdge ( edge, pcs, pc, sub, 0. );
478     else B.UpdateEdge ( edge, pc, pcs, sub, 0. );
479   }
480
481   B.Range ( edge, sub, f, l );
482
483   return Standard_True;
484 }
485
486 //=======================================================================
487 //function : TransformPCurve
488 //purpose  : 
489 //=======================================================================
490
491 Handle(Geom2d_Curve) ShapeBuild_Edge::TransformPCurve(const Handle(Geom2d_Curve)& pcurve,
492   const gp_Trsf2d& trans,
493   const Standard_Real uFact,
494   Standard_Real& aFirst,
495   Standard_Real& aLast) const
496 {
497   Handle(Geom2d_Curve) result = Handle(Geom2d_Curve)::DownCast(pcurve->Copy());
498   if(trans.Form()!=gp_Identity) {
499     result->Transform (trans);
500     aFirst = result->TransformedParameter(aFirst,trans);
501     aLast  = result->TransformedParameter(aLast, trans);
502   }
503   if(uFact==1.) 
504     return result;
505
506   if (result->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { 
507     Handle(Geom2d_TrimmedCurve) thecurve = Handle(Geom2d_TrimmedCurve)::DownCast(result);
508     result = thecurve->BasisCurve();
509   }
510
511   gp_GTrsf2d  tMatu;
512   tMatu.SetAffinity(gp::OY2d(), uFact);
513   gp_XY  pXY;
514
515   if (result->IsKind(STANDARD_TYPE(Geom2d_Line))) {
516     Handle(Geom2d_Line) aLine2d = Handle(Geom2d_Line)::DownCast(result);
517     gp_Pnt2d Pf, Pl;
518     aLine2d->D0(aFirst,Pf);
519     pXY = Pf.XY();
520     tMatu.Transforms(pXY);
521     Pf.SetXY(pXY);
522     aLine2d->D0(aLast, Pl);
523     pXY = Pl.XY();
524     tMatu.Transforms(pXY);
525     Pl.SetXY(pXY);
526     gp_Lin2d line2d(Pf, gp_Dir2d(gp_Vec2d(Pf,Pl)));
527     aFirst = ElCLib::Parameter(line2d, Pf);
528     aLast = ElCLib::Parameter(line2d, Pl);
529     Handle(Geom2d_Line) Gline2d = new Geom2d_Line(line2d);
530     return Gline2d;
531   } 
532   else if(result->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) {
533     Handle(Geom2d_BezierCurve) bezier = Handle(Geom2d_BezierCurve)::DownCast(result);
534     // transform the Poles of the BSplineCurve 
535     Standard_Integer nbPol = bezier->NbPoles();
536     gp_Pnt2d Pt1;
537     for (Standard_Integer i = 1; i<=nbPol ; i++) {
538       pXY = bezier->Pole(i).XY();
539       tMatu.Transforms(pXY);
540       Pt1.SetXY(pXY);
541       bezier->SetPole(i, Pt1);
542     }
543     return bezier;
544   } else {
545     Handle(Geom2d_BSplineCurve) aBSpline2d; 
546     if(result->IsKind(STANDARD_TYPE(Geom2d_Conic))) {
547       //gp_Pln pln(gp_Pnt(0,0,0),gp_Dir(0,0,1));
548       //Handle(Geom_Curve) curve = GeomAPI::To3d(result,pln);
549       Handle(Geom2d_TrimmedCurve) tcurve = new Geom2d_TrimmedCurve(result,aFirst,aLast); //protection agains parabols ets
550       Geom2dConvert_ApproxCurve approx (tcurve, Precision::Approximation(), 
551         GeomAbs_C1, 100, 6 );
552       if ( approx.HasResult() )
553         aBSpline2d = Handle(Geom2d_BSplineCurve)::DownCast(approx.Curve());
554       else
555         aBSpline2d = Geom2dConvert::CurveToBSplineCurve(tcurve,Convert_QuasiAngular);
556       aFirst = aBSpline2d->FirstParameter();
557       aLast =  aBSpline2d->LastParameter();
558     } 
559     else if(!result->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
560       aBSpline2d = Geom2dConvert::CurveToBSplineCurve(result,Convert_QuasiAngular);
561     }
562     else
563       aBSpline2d = Handle(Geom2d_BSplineCurve)::DownCast(result);
564
565     // transform the Poles of the BSplineCurve 
566     Standard_Integer nbPol = aBSpline2d->NbPoles();
567     gp_Pnt2d Pt1;
568     for (Standard_Integer i = 1; i<=nbPol ; i++) {
569       pXY = aBSpline2d->Pole(i).XY();
570       tMatu.Transforms(pXY);
571       Pt1.SetXY(pXY);
572       aBSpline2d->SetPole(i, Pt1);
573     }
574     return aBSpline2d;
575   }
576 }
577
578 //=======================================================================
579 //function : RemoveCurve3d
580 //purpose  : 
581 //=======================================================================
582
583 void ShapeBuild_Edge::RemoveCurve3d (const TopoDS_Edge& edge) const
584 {
585   BRep_Builder B;
586   Handle(Geom_Curve) c3dNull;
587   //:S4136  Standard_Real tol = BRep_Tool::Tolerance (edge);
588   B.UpdateEdge (edge, c3dNull, 0. ); //:S4136: tol
589 }
590
591 //=======================================================================
592 //function : BuildCurve3d
593 //purpose  : 
594 //=======================================================================
595
596 Standard_Boolean ShapeBuild_Edge::BuildCurve3d (const TopoDS_Edge& edge) const
597 {
598   try {
599     OCC_CATCH_SIGNALS
600       //#48 rln 10.12.98 S4054 UKI60107-5 entity 365
601       //C0 surface (but curve 3d is required as C1) and tolerance is 1e-07
602       //lets use maximum of tolerance and default parameter 1.e-5
603       //Another solutions: use quite big Tolerance or require C0 curve on C0 surface
604       if ( BRepLib::BuildCurve3d (edge, Max (1.e-5, BRep_Tool::Tolerance(edge) ) ) ) {
605         //#50 S4054 rln 14.12.98 write cylinder in BRep mode into IGES and read back
606         //with 2DUse_Forced - pcurve and removed 3D curves have different ranges
607         if (BRep_Tool::SameRange (edge)) {
608           Standard_Real first, last;
609           BRep_Tool::Range (edge, first, last);
610           BRep_Builder().Range (edge, first, last);//explicit setting for all reps
611         }
612         Handle(Geom_Curve) c3d;
613         Standard_Real f,l;
614         c3d = BRep_Tool::Curve(edge,f,l);
615         if (c3d.IsNull())
616           return Standard_False;
617         // 15.11.2002 PTV OCC966
618         if(!IsPeriodic(c3d)) {
619           Standard_Boolean isLess = Standard_False;
620           if(f < c3d->FirstParameter()) {
621             isLess = Standard_True;
622             f = c3d->FirstParameter();
623           }
624           if(l > c3d->LastParameter()) {
625             isLess = Standard_True;
626             l = c3d->LastParameter();
627           }
628           if(isLess) {
629             SetRange3d(edge,f,l);
630             BRep_Builder().SameRange(edge,Standard_False);
631           }
632         }
633
634         return Standard_True;
635       }
636   }
637   catch(Standard_Failure) {
638 #ifdef OCCT_DEBUG
639     cout << "\nWarning: ShapeBuild_Edge: Exception in BuildCurve3d: "; 
640     Standard_Failure::Caught()->Print(cout); cout << endl;
641 #endif
642   }
643   return Standard_False;
644 }
645
646
647 //=======================================================================
648 //function : MakeEdge
649 //purpose  : 
650 //=======================================================================
651
652 void ShapeBuild_Edge::MakeEdge(TopoDS_Edge& edge,const Handle(Geom_Curve)& curve,const TopLoc_Location& L) const
653 {
654   MakeEdge (edge,curve, L, curve->FirstParameter(), curve->LastParameter());
655 }
656
657 //=======================================================================
658 //function : MakeEdge
659 //purpose  : 
660 //=======================================================================
661
662 void ShapeBuild_Edge::MakeEdge(TopoDS_Edge& edge,const Handle(Geom_Curve)& curve,const TopLoc_Location& L,const Standard_Real p1,const Standard_Real p2) const
663 {
664   BRepBuilderAPI_MakeEdge ME (curve, p1, p2);
665   if (!ME.IsDone()) {
666 #ifdef OCCT_DEBUG
667     cout << "\nWarning: ShapeBuild_Edge::MakeEdge BRepAPI_NotDone";
668 #endif
669     return;
670   }
671   TopoDS_Edge E = ME.Edge();
672   if (!L.IsIdentity()) {
673     BRep_Builder B;
674     B.UpdateEdge (E, curve, L, 0.);
675     B.Range (E, p1, p2);
676
677     TopoDS_Vertex V1, V2;
678     TopExp::Vertices (E, V1, V2);
679     gp_Pnt P1 = BRep_Tool::Pnt (V1), P2 = BRep_Tool::Pnt (V2);
680     B.UpdateVertex (V1, P1.Transformed (L.Transformation()), 0.);
681     B.UpdateVertex (V2, P2.Transformed (L.Transformation()), 0.);
682   }
683   edge = E;
684   return;
685 }
686
687 //=======================================================================
688 //function : MakeEdge
689 //purpose  : 
690 //=======================================================================
691
692 void ShapeBuild_Edge::MakeEdge(TopoDS_Edge& edge,const Handle(Geom2d_Curve)& pcurve,const TopoDS_Face& face) const
693 {
694   MakeEdge (edge, pcurve, face, pcurve->FirstParameter(), pcurve->LastParameter());
695 }
696
697 //=======================================================================
698 //function : MakeEdge
699 //purpose  : 
700 //=======================================================================
701
702 void ShapeBuild_Edge::MakeEdge(TopoDS_Edge& edge,const Handle(Geom2d_Curve)& pcurve,const TopoDS_Face& face,const Standard_Real p1,const Standard_Real p2) const
703 {
704   TopLoc_Location L;
705   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
706   MakeEdge (edge, pcurve, S, L, p1, p2);
707 }
708
709 //=======================================================================
710 //function : MakeEdge
711 //purpose  : 
712 //=======================================================================
713
714 void ShapeBuild_Edge::MakeEdge(TopoDS_Edge& edge,const Handle(Geom2d_Curve)& pcurve,
715   const Handle(Geom_Surface)& S,const TopLoc_Location& L) const
716 {
717   MakeEdge(edge, pcurve, S, L, pcurve->FirstParameter(), pcurve->LastParameter());
718 }
719
720 //=======================================================================
721 //function : MakeEdge
722 //purpose  : 
723 //=======================================================================
724
725 void ShapeBuild_Edge::MakeEdge(TopoDS_Edge& edge,const Handle(Geom2d_Curve)& pcurve,
726   const Handle(Geom_Surface)& S,const TopLoc_Location& L,
727   const Standard_Real p1,const Standard_Real p2) const
728 {
729   BRepBuilderAPI_MakeEdge ME (pcurve, S, p1, p2);
730   if (!ME.IsDone()) {
731 #ifdef OCCT_DEBUG
732     cout << "\nWarning: ShapeBuild_Edge::MakeEdge BRepAPI_NotDone";
733 #endif
734     return;
735   }
736   TopoDS_Edge E = ME.Edge();
737   if (!L.IsIdentity()) {
738     RemovePCurve (E, S);
739     BRep_Builder B;
740     B.UpdateEdge (E, pcurve, S, L, 0.);
741     B.Range (E, S, L, p1, p2);
742
743     TopoDS_Vertex V1, V2;
744     TopExp::Vertices (E, V1, V2);
745     gp_Pnt P1 = BRep_Tool::Pnt (V1), P2 = BRep_Tool::Pnt (V2);
746     B.UpdateVertex (V1, P1.Transformed (L.Transformation()), 0.);
747     B.UpdateVertex (V2, P2.Transformed (L.Transformation()), 0.);
748   }
749   edge = E;
750   return;
751 }
752