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