0023845: New auxiliary method concatenating a wire into an edge based on C0-continuou...
[occt.git] / src / BRepAlgo / BRepAlgo.cxx
1 // Created on: 1997-03-10
2 // Created by: Stagiaire Francois DUMONT
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <BRepAlgo.ixx>
24 #include <BRepTools_WireExplorer.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepLib_MakeEdge.hxx>
27 #include <BRepLib_MakeWire.hxx>
28 #include <gp_Pnt.hxx>
29 #include <GeomConvert.hxx>
30 #include <GeomLProp.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <Precision.hxx>
33 #include <Standard_ConstructionError.hxx>
34 #include <TColGeom_Array1OfBSplineCurve.hxx>
35 #include <TColGeom_HArray1OfBSplineCurve.hxx>
36 #include <TColStd_Array1OfReal.hxx>
37 #include <TColStd_Array1OfBoolean.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Vertex.hxx>
40 #include <TopLoc_Location.hxx>
41 #include <TopExp.hxx>
42
43 #include <TColGeom_SequenceOfCurve.hxx>
44 #include <TopTools_SequenceOfShape.hxx>
45 #include <TColStd_SequenceOfReal.hxx>
46 #include <GeomAbs_CurveType.hxx>
47 #include <BRepAdaptor_Curve.hxx>
48 #include <ElCLib.hxx>
49 #include <BRepLib.hxx>
50 #include <TopoDS.hxx>
51 #include <ShapeFix_Shape.hxx>
52 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
53
54 //Temporary
55 #//include <DrawTrSurf.hxx>
56
57
58 //=======================================================================
59 //function : ConcatenateWire
60 //purpose  : 
61 //=======================================================================
62
63 TopoDS_Wire  BRepAlgo::ConcatenateWire(const TopoDS_Wire& W,
64                                        const GeomAbs_Shape Option,
65                                        const Standard_Real TolAngular) 
66 {
67
68
69   Standard_Integer        nb_curve,                         //number of curves in the Wire
70                           index;
71   BRepTools_WireExplorer  WExp(W) ;
72   TopoDS_Edge             edge;
73   TopLoc_Location         L ;
74   Standard_Real           First=0.,Last=0.,                       //extremal values for the curve
75                           First0 =0.,
76                           toler =0.,
77                           tolleft,tolright;                 //Vertex tolerances
78   TopoDS_Vertex           Vfirst,Vlast;                     //Vertex of the Wire
79   gp_Pnt                  Pfirst,Plast;            //, Pint;  corresponding points
80
81   BRepLib_MakeWire        MakeResult;                       
82   Standard_Real           closed_tolerance =0.0;
83   Standard_Boolean        closed_flag = Standard_False ;
84   
85   nb_curve = 0;
86   
87   while ( WExp.More()){                                     //computation of the curve number
88     nb_curve++ ;
89     WExp.Next();
90   }
91   
92   if (nb_curve > 1) {
93     TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);          //array of the wire's curve
94     TColStd_Array1OfReal tabtolvertex(0,nb_curve-2);          //array of the tolerance's vertex
95     
96     WExp.Init(W);
97     
98     for (index=0 ;index<nb_curve; index++){                   //main loop
99       edge = WExp.Current() ;
100       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(edge, L, First, Last);
101       Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, First, Last);
102       tab(index) = GeomConvert::CurveToBSplineCurve(aTrCurve); //storage in a array 
103       tab(index)->Transform(L.Transformation());
104       GeomConvert::C0BSplineToC1BSplineCurve(tab(index),Precision::Confusion());
105       
106       if (index >= 1){                                         //continuity test loop
107         if (edge.Orientation()==TopAbs_REVERSED)
108           tab(index)->Reverse();
109         tolleft=BRep_Tool::Tolerance(TopExp::LastVertex(edge));
110         tolright=BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
111         tabtolvertex(index-1)=Max(tolleft,tolright);
112       }
113       
114       if(index==0){                                           //storage of the first edge features
115         First0=First;
116         if(edge.Orientation()==TopAbs_REVERSED){             //(usefull for the closed wire) 
117           Vfirst=TopExp::LastVertex(edge);
118           tab(index)->Reverse();
119         }
120         else
121           Vfirst=TopExp::FirstVertex(edge);
122       }
123       
124       if(index==nb_curve-1){                                  //storage of the last edge features
125         if(edge.Orientation()==TopAbs_REVERSED)
126           Vlast=TopExp::FirstVertex(edge);
127         else
128           Vlast=TopExp::LastVertex(edge);
129       }
130       WExp.Next() ; 
131     }
132   
133     if (BRep_Tool::Tolerance(Vfirst)>BRep_Tool::Tolerance(Vlast)) //computation of the closing tolerance
134       toler=BRep_Tool::Tolerance(Vfirst);
135     else
136       toler=BRep_Tool::Tolerance(Vlast);
137     
138     Pfirst=BRep_Tool::Pnt(Vfirst);
139     Plast=BRep_Tool::Pnt(Vlast); 
140     
141     if ((Pfirst.Distance(Plast)<=toler)&&                   //C0 continuity test at the closing point
142         (GeomLProp::Continuity(tab(nb_curve-1),tab(0),Last,First0,
143                                Standard_True,Standard_True, 
144                                toler, TolAngular)>=GeomAbs_G1)) 
145       {
146         closed_tolerance =toler;                                        //if ClosedG1!=0 it will be True and
147         closed_flag = Standard_True ;
148       }                                                        //with the toler value
149     Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
150     Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
151     if (Option==GeomAbs_G1)
152       GeomConvert::ConcatG1(tab,
153                             tabtolvertex,
154                             concatcurve,
155                             closed_flag,
156                             closed_tolerance) ;    //G1 concatenation
157     else
158       GeomConvert::ConcatC1(tab,
159                             tabtolvertex,
160                             ArrayOfIndices,
161                             concatcurve,
162                             closed_flag,
163                             closed_tolerance);   //C1 concatenation
164     
165     for (index=0;index<=(concatcurve->Length()-1);index++){    //building of the resulting Wire
166       BRepLib_MakeEdge EdgeBuilder(concatcurve->Value(index));
167       edge = EdgeBuilder.Edge();
168       MakeResult.Add(edge);
169     } 
170
171   }
172   else {
173     TColGeom_Array1OfBSplineCurve tab(0,0);          //array of the wire's curve
174     TColStd_Array1OfReal tabtolvertex(0,0);          //array of the tolerance's vertex 
175     WExp.Init(W);
176     
177     edge = WExp.Current() ;
178     tab(0)  = GeomConvert::CurveToBSplineCurve(new      //storage in a array 
179                                                      Geom_TrimmedCurve(BRep_Tool::Curve(edge,L,First,Last),First,Last));
180     tab(0)->Transform(L.Transformation());
181     GeomConvert::C0BSplineToC1BSplineCurve(tab(0),Precision::Confusion());
182     if (edge.Orientation()==TopAbs_REVERSED)
183           tab(0)->Reverse();
184     tolleft=BRep_Tool::Tolerance(TopExp::LastVertex(edge));
185     tolright=BRep_Tool::Tolerance(TopExp::FirstVertex(edge));
186     tabtolvertex(0)=Max(tolleft,tolright);
187     if(edge.Orientation()==TopAbs_REVERSED){             //(usefull for the closed wire) 
188           Vfirst=TopExp::LastVertex(edge);
189           Vlast=TopExp::FirstVertex(edge);
190     }
191     else {
192       
193       Vfirst=TopExp::FirstVertex(edge);
194       Vlast = TopExp::LastVertex(edge) ;
195     }
196     Pfirst=BRep_Tool::Pnt(Vfirst);
197     Plast=BRep_Tool::Pnt(Vlast); 
198     if ((Pfirst.Distance(Plast)<=toler)&&                   //C0 continuity test at the closing point
199         (GeomLProp::Continuity(tab(0),tab(0),Last,First,
200                                Standard_True,Standard_True,
201                                toler, TolAngular)>=GeomAbs_G1)) 
202       {
203         closed_tolerance =toler;                                        //if ClosedG1!=0 it will be True and
204         closed_flag = Standard_True ;
205       }                                                        //with the toler value
206     Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
207     Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
208     if (Option==GeomAbs_G1)
209       GeomConvert::ConcatG1(tab,
210                             tabtolvertex,
211                             concatcurve,
212                             closed_flag,
213                             closed_tolerance) ;    //G1 concatenation
214     else
215       GeomConvert::ConcatC1(tab,
216                             tabtolvertex,
217                             ArrayOfIndices,
218                             concatcurve,
219                             closed_flag,
220                             closed_tolerance);   //C1 concatenation
221     
222     for (index=0;index<=(concatcurve->Length()-1);index++){    //building of the resulting Wire
223       BRepLib_MakeEdge EdgeBuilder(concatcurve->Value(index));
224       edge = EdgeBuilder.Edge();
225       MakeResult.Add(edge);
226     } 
227   }
228   return MakeResult.Wire() ;  
229   
230 }
231
232 //=======================================================================
233 //function : ConcatenateWireC0
234 //purpose  : 
235 //=======================================================================
236
237 TopoDS_Edge  BRepAlgo::ConcatenateWireC0(const TopoDS_Wire& aWire)
238 {
239   Standard_Real LinTol = Precision::Confusion();
240   Standard_Real AngTol = Precision::Angular();
241
242   TopoDS_Edge ResEdge;
243
244   TopoDS_Wire theWire = aWire;
245   BRepLib::BuildCurves3d(theWire);
246   Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(theWire);
247   Fixer->SetPrecision(LinTol);
248   Fixer->SetMaxTolerance(LinTol);
249   Fixer->Perform();
250   theWire = TopoDS::Wire(Fixer->Shape());
251
252   TColGeom_SequenceOfCurve CurveSeq;
253   TopTools_SequenceOfShape LocSeq;
254   TColStd_SequenceOfReal FparSeq;
255   TColStd_SequenceOfReal LparSeq;
256   TColStd_SequenceOfReal TolSeq;
257   GeomAbs_CurveType CurType;
258   TopoDS_Vertex FirstVertex, LastVertex;
259   Standard_Boolean FinalReverse = Standard_False;
260
261   BRepTools_WireExplorer wexp(theWire) ;
262   for (; wexp.More(); wexp.Next())
263     {
264       TopoDS_Edge anEdge = wexp.Current();
265       Standard_Real fpar, lpar;
266       TopLoc_Location aLoc;
267       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
268       if (aCurve.IsNull())
269         continue;
270
271       BRepAdaptor_Curve BAcurve(anEdge);
272       GeomAbs_CurveType aType = BAcurve.GetType();
273
274       Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
275
276       if (aBasisCurve->IsPeriodic())
277         ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
278                                Precision::PConfusion(), fpar, lpar);
279
280       if (CurveSeq.IsEmpty())
281         {
282           CurveSeq.Append(aCurve);
283           TopoDS_Shape aLocShape;
284           aLocShape.Location(aLoc);
285           aLocShape.Orientation(wexp.Orientation());
286           LocSeq.Append(aLocShape);
287           FparSeq.Append(fpar);
288           LparSeq.Append(lpar);
289           CurType = aType;
290           FirstVertex = wexp.CurrentVertex();
291           if (anEdge.Orientation() == TopAbs_REVERSED)
292             FinalReverse = Standard_True;
293         }
294       else
295         {
296           Standard_Boolean Done = Standard_False;
297           Standard_Real NewFpar, NewLpar;
298           GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
299           TopoDS_Vertex CurVertex = wexp.CurrentVertex();
300           TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
301           TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
302           if (aCurve == CurveSeq.Last())
303             {
304               NewFpar = fpar;
305               NewLpar = lpar;
306               if (aBasisCurve->IsPeriodic())
307                 {
308                   if (NewLpar < NewFpar)
309                     NewLpar += aBasisCurve->Period();
310                   if (ConnectByOrigin == TopAbs_FORWARD)
311                     ElCLib::AdjustPeriodic(FparSeq.Last(),
312                                            FparSeq.Last() + aBasisCurve->Period(),
313                                            Precision::PConfusion(), NewFpar, NewLpar);
314                   else
315                     ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
316                                            FparSeq.Last(),
317                                            Precision::PConfusion(), NewFpar, NewLpar);
318                 }
319               Done = Standard_True;
320             }
321           else if (aType == CurType &&
322                    aType != GeomAbs_BezierCurve &&
323                    aType != GeomAbs_BSplineCurve &&
324                    aType != GeomAbs_OtherCurve)
325             switch (aType)
326               {
327               case GeomAbs_Line:
328                 {
329                   gp_Lin aLine    = BAcurve.Line();
330                   gp_Lin PrevLine = GAprevcurve.Line(); 
331                   if (aLine.Contains(PrevLine.Location(), LinTol) &&
332                       aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
333                     {
334                       gp_Pnt P1 = ElCLib::Value(fpar, aLine);
335                       gp_Pnt P2 = ElCLib::Value(lpar, aLine);
336                       NewFpar = ElCLib::Parameter(PrevLine, P1);
337                       NewLpar = ElCLib::Parameter(PrevLine, P2);
338                       if (NewLpar < NewFpar)
339                         {
340                           Standard_Real MemNewFpar = NewFpar;
341                           NewFpar = NewLpar;
342                           NewLpar = MemNewFpar;
343                           ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
344                         }
345                       Done = Standard_True;
346                     }
347                   break;
348                 }
349               case GeomAbs_Circle:
350                 {
351                   gp_Circ aCircle    = BAcurve.Circle();
352                   gp_Circ PrevCircle = GAprevcurve.Circle();
353                   if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
354                       Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
355                       aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
356                     {
357                       if (aCircle.Axis().Direction() * PrevCircle.Axis().Direction() < 0.)
358                         {
359                           Standard_Real memfpar = fpar;
360                           fpar = lpar;
361                           lpar = memfpar;
362                           ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
363                         }
364                       gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
365                       gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
366                       NewFpar = ElCLib::Parameter(PrevCircle, P1);
367                       NewLpar = ElCLib::Parameter(PrevCircle, P2);
368                       if (NewLpar < NewFpar)
369                         NewLpar += 2.*M_PI;
370                       //Standard_Real MemNewFpar = NewFpar, MemNewLpar =  NewLpar;
371                       if (ConnectByOrigin == TopAbs_FORWARD)
372                         ElCLib::AdjustPeriodic(FparSeq.Last(),
373                                                FparSeq.Last() + 2.*M_PI,
374                                                Precision::PConfusion(), NewFpar, NewLpar);
375                       else
376                         ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
377                                                FparSeq.Last(),
378                                                Precision::PConfusion(), NewFpar, NewLpar);
379                       Done = Standard_True;
380                     }
381                   break;
382                 }
383               case GeomAbs_Ellipse:
384                 {
385                   gp_Elips anEllipse   = BAcurve.Ellipse();
386                   gp_Elips PrevEllipse = GAprevcurve.Ellipse();
387                   if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
388                       anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
389                       Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
390                       Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
391                       anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
392                     {
393                       if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
394                         {
395                           Standard_Real memfpar = fpar;
396                           fpar = lpar;
397                           lpar = memfpar;
398                           ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
399                         }
400                       gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
401                       gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
402                       NewFpar = ElCLib::Parameter(PrevEllipse, P1);
403                       NewLpar = ElCLib::Parameter(PrevEllipse, P2);
404                       if (NewLpar < NewFpar)
405                         NewLpar += 2.*M_PI;
406                       if (ConnectByOrigin == TopAbs_FORWARD)
407                         ElCLib::AdjustPeriodic(FparSeq.Last(),
408                                                FparSeq.Last() + 2.*M_PI,
409                                                Precision::PConfusion(), NewFpar, NewLpar);
410                       else
411                         ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
412                                                FparSeq.Last(),
413                                                Precision::PConfusion(), NewFpar, NewLpar);
414                       Done = Standard_True;
415                     }
416                   break;
417                 }
418               case GeomAbs_Hyperbola:
419                 {
420                   gp_Hypr aHypr    = BAcurve.Hyperbola();
421                   gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
422                   if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
423                       aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
424                       Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
425                       Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
426                       aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
427                     {
428                       gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
429                       gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
430                       NewFpar = ElCLib::Parameter(PrevHypr, P1);
431                       NewLpar = ElCLib::Parameter(PrevHypr, P2);
432                       if (NewLpar < NewFpar)
433                         {
434                           Standard_Real MemNewFpar = NewFpar;
435                           NewFpar = NewLpar;
436                           NewLpar = MemNewFpar;
437                           ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
438                         }
439                       Done = Standard_True;
440                     }
441                   break;
442                 }
443               case GeomAbs_Parabola:
444                 {
445                   gp_Parab aParab    = BAcurve.Parabola();
446                   gp_Parab PrevParab = GAprevcurve.Parabola();
447                   if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
448                       aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
449                       Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
450                       aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
451                     {
452                       gp_Pnt P1 = ElCLib::Value(fpar, aParab);
453                       gp_Pnt P2 = ElCLib::Value(lpar, aParab);
454                       NewFpar = ElCLib::Parameter(PrevParab, P1);
455                       NewLpar = ElCLib::Parameter(PrevParab, P2);
456                       if (NewLpar < NewFpar)
457                         {
458                           Standard_Real MemNewFpar = NewFpar;
459                           NewFpar = NewLpar;
460                           NewLpar = MemNewFpar;
461                           ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
462                         }
463                       Done = Standard_True;
464                     }
465                   break;
466                 }
467               } //end of switch and else
468           if (Done)
469             {
470               if (NewFpar < FparSeq.Last())
471                 FparSeq(FparSeq.Length()) = NewFpar;
472               else
473                 LparSeq(LparSeq.Length()) = NewLpar;
474             }
475           else
476             {
477               CurveSeq.Append(aCurve);
478               TopoDS_Shape aLocShape;
479               aLocShape.Location(aLoc);
480               aLocShape.Orientation(wexp.Orientation());
481               LocSeq.Append(aLocShape);
482               FparSeq.Append(fpar);
483               LparSeq.Append(lpar);
484               TolSeq.Append(BRep_Tool::Tolerance(CurVertex));
485               CurType = aType;
486             }
487         } //end of else (not first time)
488     }
489   LastVertex = wexp.CurrentVertex();
490   TolSeq.Append(BRep_Tool::Tolerance(LastVertex));
491
492   TopoDS_Vertex FirstVtx_final = (FinalReverse)? LastVertex : FirstVertex;
493   FirstVtx_final.Orientation(TopAbs_FORWARD);
494   TopoDS_Vertex LastVtx_final = (FinalReverse)? FirstVertex : LastVertex;
495   LastVtx_final.Orientation(TopAbs_REVERSED);
496   
497   if (CurveSeq.IsEmpty())
498     return ResEdge;
499
500   Standard_Integer nb_curve = CurveSeq.Length();   //number of curves
501   TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);                    //array of the curves
502   TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
503
504   Standard_Integer i;
505
506   if (nb_curve > 1)
507     {
508       for (i = 1; i <= nb_curve; i++)
509         {
510           if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
511             CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
512           
513           Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
514           tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
515           tab(i-1)->Transform(LocSeq(i).Location().Transformation());
516           GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
517           if (LocSeq(i).Orientation() == TopAbs_REVERSED)
518             tab(i-1)->Reverse();
519           
520           //Temporary
521           //char* name = new char[100];
522           //sprintf(name, "c%d", i);
523           //DrawTrSurf::Set(name, tab(i-1));
524           
525           if (i > 1)
526             tabtolvertex(i-2) = TolSeq(i-1) * 5.;
527         }
528       tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length()) * 5.;
529       
530       Standard_Boolean closed_flag = Standard_False;
531       Standard_Real closed_tolerance = 0.;
532       if (FirstVertex.IsSame(LastVertex) &&
533           GeomLProp::Continuity(tab(0), tab(nb_curve-1),
534                                 tab(0)->FirstParameter(),
535                                 tab(nb_curve-1)->LastParameter(),
536                                 Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
537         {
538           closed_flag = Standard_True ;
539           closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
540         }
541       
542       Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
543       Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
544       GeomConvert::ConcatC1(tab,
545                             tabtolvertex,
546                             ArrayOfIndices,
547                             concatcurve,
548                             closed_flag,
549                             closed_tolerance);   //C1 concatenation
550
551       if (concatcurve->Length() > 1)
552         {
553           Standard_Real MaxTolVer = LinTol;
554           for (i = 1; i <= TolSeq.Length(); i++)
555             if (TolSeq(i) > MaxTolVer)
556               MaxTolVer = TolSeq(i);
557           MaxTolVer *= 5.;
558           
559           GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
560           
561           for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
562             Concat.Add( concatcurve->Value(i), MaxTolVer, Standard_True );
563           
564           concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
565         }
566
567       ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
568                                  FirstVtx_final, LastVtx_final,
569                                  concatcurve->Value(concatcurve->Lower())->FirstParameter(),
570                                  concatcurve->Value(concatcurve->Lower())->LastParameter());
571     }
572   else
573     {
574       if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
575         CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
576           
577       CurveSeq(1)->Transform(LocSeq(1).Location().Transformation());
578       ResEdge = BRepLib_MakeEdge(CurveSeq(1),
579                                  FirstVtx_final, LastVtx_final,
580                                  FparSeq(1), LparSeq(1));
581     }
582
583   if (FinalReverse)
584     ResEdge.Reverse();
585   
586   return ResEdge;
587 }