0024023: Revamp the OCCT Handle -- general
[occt.git] / src / BRepMAT2d / BRepMAT2d_Explorer.cxx
1 // Created on: 1994-10-04
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1994-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 <BRepMAT2d_Explorer.ixx>
18 #include <MAT2d_SequenceOfSequenceOfCurve.hxx>
19 #include <TColGeom2d_SequenceOfCurve.hxx>
20 #include <TopoDS_Wire.hxx>
21 #include <BRepTools_WireExplorer.hxx>
22 #include <TopLoc_Location.hxx>
23 #include <Geom_Curve.hxx>
24 #include <Geom_TrimmedCurve.hxx>  
25 #include <Geom2d_TrimmedCurve.hxx>
26 #include <GeomAPI.hxx>
27 #include <BRep_Tool.hxx>
28 #include <gp.hxx>
29 #include <gp_Pln.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopAbs.hxx>
32 #include <TopoDS.hxx>
33
34 #include <Precision.hxx>
35 #include <Geom2d_BSplineCurve.hxx>
36 #include <Geom2dConvert.hxx>
37 #include <BRepBuilderAPI_MakeFace.hxx>
38 #include <TopExp.hxx>
39 #include <BRep_Builder.hxx>
40 #include <BRepLib.hxx>
41 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
42 #include <GeomAbs_CurveType.hxx>
43 #include <Geom2d_Circle.hxx>
44 #include <Geom2d_Line.hxx>
45 #include <Geom2d_Ellipse.hxx>
46 #include <Geom2d_Parabola.hxx>
47 #include <Geom2d_Hyperbola.hxx>
48 #include <Geom2d_BezierCurve.hxx>
49 #include <GCE2d_MakeArcOfCircle.hxx>
50 #include <GCE2d_MakeSegment.hxx>
51 #include <Geom2d_BoundedCurve.hxx> 
52 //
53 //  Modified by Sergey KHROMOV - Thu Dec  5 10:38:14 2002 Begin
54 static TopoDS_Edge MakeEdge(const Handle(Geom2d_Curve) &theCurve,
55   const TopoDS_Face          &theFace,
56   const TopoDS_Vertex        &theVFirst,
57   const TopoDS_Vertex        &theVLast);
58 //  Modified by Sergey KHROMOV - Thu Dec  5 10:38:16 2002 End
59 //
60 static GeomAbs_CurveType GetCurveType(const Handle(Geom2d_Curve)& theC2d);
61 static void AdjustCurveEnd(Handle(Geom2d_BoundedCurve)& theC2d, const gp_Pnt2d theP,
62                            const Standard_Boolean isFirst);
63 //
64 //=======================================================================
65 //function : BRepMAT2d_Explorer
66 //purpose  : 
67 //=======================================================================
68
69 BRepMAT2d_Explorer::BRepMAT2d_Explorer()
70 {
71   Clear();
72 }
73
74 //=======================================================================
75 //function : BRepMAT2d_Explorer
76 //purpose  : 
77 //=======================================================================
78
79 BRepMAT2d_Explorer::BRepMAT2d_Explorer(const TopoDS_Face& aFace)
80 {
81   Perform (aFace);
82 }
83
84 //=======================================================================
85 //function : Perform
86 //purpose  : 
87 //=======================================================================
88
89 void BRepMAT2d_Explorer::Perform(const TopoDS_Face& aFace)
90 {
91   Clear();
92   myShape        = aFace;
93   TopoDS_Face  F = TopoDS::Face(aFace);
94   F.Orientation(TopAbs_FORWARD);
95   TopExp_Explorer Exp (F,TopAbs_WIRE);
96   //  Modified by Sergey KHROMOV - Tue Nov 26 16:10:37 2002 Begin
97   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
98   TopoDS_Face          aNewF = BRepBuilderAPI_MakeFace(aSurf, Precision::Confusion());
99
100   while (Exp.More()) {
101     Add (TopoDS::Wire (Exp.Current()),F, aNewF);
102     Exp.Next();
103   }
104
105   BRepLib::BuildCurves3d(aNewF);
106
107   myModifShapes.Add(aFace, aNewF);
108   //   CheckConnection();
109   //  Modified by Sergey KHROMOV - Tue Nov 26 16:10:38 2002 End
110 }
111
112 //=======================================================================
113 //function : Add
114 //purpose  : 
115 //=======================================================================
116
117 void BRepMAT2d_Explorer::Add(const TopoDS_Wire& Spine,
118   const TopoDS_Face& aFace,
119   TopoDS_Face& aNewFace)
120 {  
121   //  Modified by Sergey KHROMOV - Tue Nov 26 14:25:46 2002 Begin
122   // This method is totally rewroted to include check
123   // of connection and creation of a new spine.
124   NewContour();
125   myIsClosed(currentContour) = (Spine.Closed()) ? Standard_True : Standard_False;
126
127   //  Modified by skv - Wed Jun 23 12:23:01 2004 Integration Begin
128   //  Taking into account side of bisecting loci construction.
129   //   TopoDS_Wire                         aWFwd = TopoDS::Wire(Spine.Oriented(TopAbs_FORWARD));
130   //   BRepTools_WireExplorer              anExp(aWFwd, aFace);
131   BRepTools_WireExplorer              anExp(Spine, aFace);
132   //  Modified by skv - Wed Jun 23 12:23:02 2004 Integration End
133   TopTools_IndexedDataMapOfShapeShape anOldNewE;
134
135   if (!anExp.More())
136     return;
137
138   TopoDS_Edge                 aFirstEdge = anExp.Current();
139   TopoDS_Edge                 aPrevEdge = aFirstEdge;
140   Standard_Real               UFirst,ULast, aD;
141   Handle(Geom2d_Curve)        C2d;
142   Handle(Geom2d_TrimmedCurve) CT2d;
143   Handle(Geom2d_TrimmedCurve) aFirstCurve;
144   gp_Pnt2d                    aPFirst;
145   gp_Pnt2d                    aPLast;
146   gp_Pnt2d                    aPCurFirst;
147   //  Modified by skv - Mon Jul 11 19:00:25 2005 Integration Begin
148   //  Set the confusion tolerance in accordance with the further algo
149   //   Standard_Real               aTolConf   = Precision::Confusion();
150   Standard_Real               aTolConf   = 1.e-8;
151   //  Modified by skv - Mon Jul 11 19:00:25 2005 Integration End
152   Standard_Boolean            isModif    = Standard_False;
153
154   // Treatment of the first edge of a wire.
155   anOldNewE.Add(aFirstEdge, aFirstEdge);
156   C2d  = BRep_Tool::CurveOnSurface (aFirstEdge, aFace, UFirst, ULast);
157   CT2d = new Geom2d_TrimmedCurve(C2d,UFirst,ULast);
158
159   if (aFirstEdge.Orientation() == TopAbs_REVERSED)
160     CT2d->Reverse();
161
162   aPFirst = CT2d->Value(CT2d->FirstParameter());
163   aPLast  = CT2d->Value(CT2d->LastParameter());
164
165   Add(CT2d);
166   aFirstCurve = CT2d;
167   anExp.Next();
168
169   // Treatment of the next edges:
170   for (; anExp.More(); anExp.Next()) {
171     TopoDS_Edge  anEdge = anExp.Current();
172
173     anOldNewE.Add(anEdge, anEdge);
174     C2d  = BRep_Tool::CurveOnSurface (anEdge, aFace, UFirst, ULast);
175     CT2d = new Geom2d_TrimmedCurve(C2d,UFirst,ULast);
176
177     if (anEdge.Orientation() == TopAbs_REVERSED)
178       CT2d->Reverse();
179
180     aPCurFirst = CT2d->Value(CT2d->FirstParameter());
181     //
182     aD=aPLast.Distance(aPCurFirst);
183     if (aD > aTolConf) {
184       // There are two ways how to fill holes:
185       //     First,  to create a line between these two points.
186       //     Second, create a BSpline curve and to add the last point of the previous
187       //             curve as the first pole of the current one. Second method which
188       //             is worse was performed before and leaved here. Otherwise too much
189       //             code should be rewritten.
190       isModif = Standard_True;
191       //
192       Standard_Integer aNbC = theCurves.Value(currentContour).Length();
193       Handle(Geom2d_BoundedCurve) CPrev = 
194         Handle(Geom2d_BoundedCurve)::DownCast(theCurves.ChangeValue(currentContour).ChangeValue(aNbC));
195       //
196       GeomAbs_CurveType TCPrev = GetCurveType(CPrev);
197       GeomAbs_CurveType TCCurr = GetCurveType(CT2d);
198       //
199       if(TCCurr <= TCPrev)
200       {
201         AdjustCurveEnd(CT2d, aPLast, Standard_True);
202         // Creation of new edge.
203         TopoDS_Edge aNewEdge;
204         TopoDS_Vertex aVf = TopExp::FirstVertex(anEdge);
205         TopoDS_Vertex aVl = TopExp::LastVertex(anEdge);
206
207         if (anEdge.Orientation() == TopAbs_FORWARD)
208           aNewEdge = MakeEdge(CT2d, aNewFace, aVf, aVl);
209         else 
210           aNewEdge = MakeEdge(CT2d->Reversed(), aNewFace, aVf, aVl);
211
212         aNewEdge.Orientation(anEdge.Orientation());
213
214         anOldNewE.ChangeFromKey(anEdge) = aNewEdge;
215       }
216       else
217       {
218         gp_Pnt2d aP = CT2d->Value(CT2d->FirstParameter());
219         AdjustCurveEnd(CPrev, aP, Standard_False);
220         theCurves.ChangeValue(currentContour).ChangeValue(aNbC) = CPrev;
221         //Change previous edge
222         TopoDS_Edge aNewEdge;
223         TopoDS_Vertex aVf = TopExp::FirstVertex(aPrevEdge);
224         TopoDS_Vertex aVl = TopExp::LastVertex(aPrevEdge);
225
226         if (aPrevEdge.Orientation() == TopAbs_FORWARD)
227           aNewEdge = MakeEdge(CPrev, aNewFace, aVf, aVl);
228         else 
229           aNewEdge = MakeEdge(CPrev->Reversed(), aNewFace, aVf, aVl);
230
231         aNewEdge.Orientation(aPrevEdge.Orientation());
232
233         anOldNewE.ChangeFromKey(aPrevEdge) = aNewEdge;
234         
235       }
236
237     }
238
239     aPLast = CT2d->Value(CT2d->LastParameter());
240     Add(CT2d);
241     aPrevEdge = anEdge;
242   }
243
244   // Check of the distance between the first and the last point of wire
245   // if the wire is closed.
246   if (myIsClosed(currentContour) && aPLast.Distance(aPFirst) > aTolConf) {
247     isModif = Standard_True;
248
249       //
250     Standard_Integer aNbC = theCurves.Value(currentContour).Length();
251     Handle(Geom2d_BoundedCurve) CPrev = 
252         Handle(Geom2d_BoundedCurve)::DownCast(theCurves.ChangeValue(currentContour).ChangeValue(aNbC));
253       //
254     GeomAbs_CurveType TCPrev = GetCurveType(CPrev);
255     GeomAbs_CurveType TCCurr = GetCurveType(aFirstCurve);
256     //
257     if(TCCurr <= TCPrev)
258     {
259       AdjustCurveEnd(aFirstCurve, aPLast, Standard_True);
260       theCurves.ChangeValue(currentContour).ChangeValue(1) = aFirstCurve;
261       // Creation of new edge.
262       TopoDS_Edge aNewEdge;
263       TopoDS_Vertex aVf = TopExp::FirstVertex(aFirstEdge);
264       TopoDS_Vertex aVl = TopExp::LastVertex(aFirstEdge);
265
266       if (aFirstEdge.Orientation() == TopAbs_FORWARD)
267         aNewEdge = MakeEdge(aFirstCurve, aNewFace, aVf, aVl);
268       else 
269         aNewEdge = MakeEdge(aFirstCurve->Reversed(), aNewFace, aVf, aVl);
270
271       aNewEdge.Orientation(aFirstEdge.Orientation());
272
273       anOldNewE.ChangeFromKey(aFirstEdge) = aNewEdge;
274     }
275     else
276     {
277       gp_Pnt2d aP = aFirstCurve->Value(aFirstCurve->FirstParameter());
278       AdjustCurveEnd(CPrev, aP, Standard_False);
279       theCurves.ChangeValue(currentContour).ChangeValue(aNbC) = CPrev;
280       //Change previous edge
281       TopoDS_Edge aNewEdge;
282       TopoDS_Vertex aVf = TopExp::FirstVertex(aPrevEdge);
283       TopoDS_Vertex aVl = TopExp::LastVertex(aPrevEdge);
284
285       if (aPrevEdge.Orientation() == TopAbs_FORWARD)
286         aNewEdge = MakeEdge(CPrev, aNewFace, aVf, aVl);
287       else 
288         aNewEdge = MakeEdge(CPrev->Reversed(), aNewFace, aVf, aVl);
289
290       aNewEdge.Orientation(aPrevEdge.Orientation());
291
292       anOldNewE.ChangeFromKey(aPrevEdge) = aNewEdge;
293
294     }
295
296   }
297
298   TopoDS_Wire  aNewWire;
299   BRep_Builder aBuilder;
300
301   if (isModif) {
302     Standard_Integer i;
303     Standard_Integer aNbEdges = anOldNewE.Extent();
304
305     aBuilder.MakeWire(aNewWire);
306
307     for (i = 1; i <= aNbEdges; i++) {
308       const TopoDS_Shape &aKey     = anOldNewE.FindKey(i);
309       const TopoDS_Shape &aNewEdge = anOldNewE.FindFromIndex(i);
310
311       aBuilder.Add(aNewWire, aNewEdge);
312       myModifShapes.Add(aKey, aNewEdge);
313     }
314
315     if (myIsClosed(currentContour))
316       aNewWire.Closed(Standard_True);
317
318     //  Modified by skv - Fri Nov 12 17:22:12 2004 Integration Begin
319     //  The orientation of wire is already taken into account.
320     //    aNewWire.Orientation(Spine.Orientation());
321     //  Modified by skv - Fri Nov 12 17:22:12 2004 Integration End
322     myModifShapes.Add(Spine, aNewWire);
323   } else
324     aNewWire = Spine;
325
326   aBuilder.Add(aNewFace, aNewWire);
327   //  Modified by Sergey KHROMOV - Tue Nov 26 14:25:53 2002 End
328 }
329
330 //=======================================================================
331 //function : CheckConnection
332 //purpose  : 
333 //=======================================================================
334
335 //  Modified by Sergey KHROMOV - Tue Nov 26 17:21:44 2002 Begin
336 // void BRepMAT2d_Explorer::CheckConnection()
337 // {
338 //   for (Standard_Integer i = 1; i <= theCurves.Length(); i++)
339 //     for (Standard_Integer j = 2; j <= theCurves(i).Length(); j++)
340 //       {
341 //      gp_Pnt2d P1 = theCurves(i)(j-1)->Value( theCurves(i)(j-1)->LastParameter() );
342 //      gp_Pnt2d P2 = theCurves(i)(j)->Value( theCurves(i)(j)->FirstParameter() );
343 //      if (P1.Distance( P2 ) > Precision::Confusion())
344 //        {
345 //          Handle( Geom2d_BSplineCurve ) BCurve;
346 //          if (theCurves(i)(j)->DynamicType() != STANDARD_TYPE(Geom2d_BSplineCurve))
347 //            BCurve = Geom2dConvert::CurveToBSplineCurve( theCurves(i)(j) );
348 //          else
349 //            BCurve = Handle( Geom2d_BSplineCurve )::DownCast( theCurves(i)(j) );
350 //          BCurve->SetPole( 1, P1 );
351 //          theCurves(i)(j) = new Geom2d_TrimmedCurve( BCurve, BCurve->FirstParameter(), BCurve->LastParameter() );
352 //        }
353 //       }
354 // }
355 //  Modified by Sergey KHROMOV - Tue Nov 26 17:21:29 2002 End
356
357 //=======================================================================
358 //function : Clear
359 //purpose  : 
360 //=======================================================================
361
362 void BRepMAT2d_Explorer::Clear()
363 {  
364   theCurves.Clear() ;
365   currentContour = 0;
366   //  Modified by Sergey KHROMOV - Wed Mar  6 16:07:55 2002 Begin
367   myIsClosed.Clear();
368   myModifShapes.Clear();
369   //  Modified by Sergey KHROMOV - Wed Mar  6 16:07:55 2002 End
370 }
371
372
373 //=======================================================================
374 //function : NewContour
375 //purpose  : 
376 //=======================================================================
377
378 void BRepMAT2d_Explorer::NewContour()
379 {  
380   TColGeom2d_SequenceOfCurve Contour;
381   theCurves.Append(Contour);
382   //  Modified by Sergey KHROMOV - Wed Mar  6 16:12:05 2002 Begin
383   myIsClosed.Append(Standard_False);
384   //  Modified by Sergey KHROMOV - Wed Mar  6 16:12:05 2002 End
385   currentContour ++ ;
386 }
387
388
389 //=======================================================================
390 //function : Add
391 //purpose  : 
392 //=======================================================================
393
394 void BRepMAT2d_Explorer::Add(const Handle(Geom2d_Curve)& aCurve)
395 {  
396   theCurves.ChangeValue(currentContour).Append(aCurve);
397 }
398
399 //=======================================================================
400 //function : NumberOfContours
401 //purpose  : 
402 //=======================================================================
403
404 Standard_Integer BRepMAT2d_Explorer::NumberOfContours() const 
405 {  
406   return theCurves.Length() ;
407 }
408
409
410 //=======================================================================
411 //function : NumberOfCurves
412 //purpose  : 
413 //=======================================================================
414
415 Standard_Integer BRepMAT2d_Explorer::NumberOfCurves
416   (const Standard_Integer IndexContour)
417   const 
418 {  
419   return theCurves.Value(IndexContour).Length();
420 }
421
422
423 //=======================================================================
424 //function : Init
425 //purpose  : 
426 //=======================================================================
427
428 void BRepMAT2d_Explorer::Init(const Standard_Integer IndexContour)
429 {  
430   currentContour = IndexContour;
431   current        = 1;
432 }
433
434
435 //=======================================================================
436 //function : More
437 //purpose  : 
438 //=======================================================================
439
440 Standard_Boolean BRepMAT2d_Explorer::More() const 
441 {  
442   return (current <= NumberOfCurves(currentContour));
443 }
444
445
446 //=======================================================================
447 //function : Next
448 //purpose  : 
449 //=======================================================================
450
451 void BRepMAT2d_Explorer::Next()
452
453   current++;
454 }
455
456
457 //=======================================================================
458 //function : Value
459 //purpose  : 
460 //=======================================================================
461
462 Handle(Geom2d_Curve) BRepMAT2d_Explorer::Value() const 
463 {  
464   return theCurves.Value(currentContour).Value(current);
465 }
466
467 //=======================================================================
468 //function : Shape
469 //purpose  : 
470 //=======================================================================
471
472 TopoDS_Shape BRepMAT2d_Explorer::Shape() const
473 {
474   return myShape;
475 }
476
477
478 //=======================================================================
479 //function : Contour
480 //purpose  : 
481 //=======================================================================
482
483 const TColGeom2d_SequenceOfCurve& BRepMAT2d_Explorer::Contour
484   (const Standard_Integer IC)
485   const
486 {
487   return theCurves.Value(IC);
488 }
489
490
491 //  Modified by Sergey KHROMOV - Wed Mar  6 17:40:07 2002 Begin
492 //=======================================================================
493 //function : IsModified
494 //purpose  : 
495 //=======================================================================
496
497 Standard_Boolean BRepMAT2d_Explorer::IsModified
498   (const TopoDS_Shape &aShape) const
499 {
500   if (myModifShapes.Contains(aShape)) {
501     const TopoDS_Shape     &aNewShape = myModifShapes.FindFromKey(aShape);
502     const Standard_Boolean  isSame    = aNewShape.IsSame(aShape);
503
504     return !isSame;
505   }
506
507   return Standard_False;
508 }
509
510 //=======================================================================
511 //function : ModifiedShape
512 //purpose  : 
513 //=======================================================================
514
515 TopoDS_Shape BRepMAT2d_Explorer::ModifiedShape
516   (const TopoDS_Shape &aShape) const
517 {
518   if (myModifShapes.Contains(aShape)) {
519     const TopoDS_Shape &aNewShape = myModifShapes.FindFromKey(aShape);
520
521     return aNewShape;
522   }
523
524   return aShape;
525 }
526
527 //=======================================================================
528 //function : GetIsClosed
529 //purpose  : 
530 //=======================================================================
531
532 const TColStd_SequenceOfBoolean &BRepMAT2d_Explorer::GetIsClosed() const
533 {
534   return myIsClosed;
535 }
536
537 //=======================================================================
538 //function : MakeEdge
539 //purpose  : Creation of an edge by 2d curve, face and two vertices.
540 //=======================================================================
541
542 TopoDS_Edge MakeEdge(const Handle(Geom2d_Curve) &theCurve,
543   const TopoDS_Face          &theFace,
544   const TopoDS_Vertex        &theVFirst,
545   const TopoDS_Vertex        &theVLast)
546 {
547   TopoDS_Edge   aNewEdge;
548   BRep_Builder  aBuilder;
549   Standard_Real aTol  = Precision::Confusion();
550   Standard_Real aFPar = theCurve->FirstParameter();
551   Standard_Real aLPar = theCurve->LastParameter();
552
553   aBuilder.MakeEdge(aNewEdge);
554   aBuilder.UpdateEdge(aNewEdge, theCurve, theFace, aTol);
555   aBuilder.Add(aNewEdge, theVFirst.Oriented(TopAbs_FORWARD));
556   aBuilder.Add(aNewEdge, theVLast.Oriented(TopAbs_REVERSED));
557   aBuilder.Range(aNewEdge, aFPar, aLPar);
558
559   return aNewEdge;
560 }
561 //  Modified by Sergey KHROMOV - Wed Mar  6 17:40:14 2002 End
562 //
563 //=======================================================================
564 //function : GetCurveType
565 //purpose  : Get curve type.
566 //=======================================================================
567
568 GeomAbs_CurveType GetCurveType(const Handle(Geom2d_Curve)& theC2d)
569 {
570   GeomAbs_CurveType aTypeCurve = GeomAbs_OtherCurve;
571   Handle(Standard_Type) TheType = theC2d->DynamicType();
572   if ( TheType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
573     TheType = (*((Handle(Geom2d_TrimmedCurve)*)&theC2d))->BasisCurve()->DynamicType();
574   }
575
576   if ( TheType ==  STANDARD_TYPE(Geom2d_Circle)) {
577     aTypeCurve = GeomAbs_Circle;
578   }
579   else if ( TheType ==STANDARD_TYPE(Geom2d_Line)) {
580     aTypeCurve = GeomAbs_Line;
581   }
582   else if ( TheType == STANDARD_TYPE(Geom2d_Ellipse)) {
583     aTypeCurve = GeomAbs_Ellipse;
584   }
585   else if ( TheType == STANDARD_TYPE(Geom2d_Parabola)) {
586     aTypeCurve = GeomAbs_Parabola;
587   }
588   else if ( TheType == STANDARD_TYPE(Geom2d_Hyperbola)) {
589     aTypeCurve = GeomAbs_Hyperbola;
590   }
591   else if ( TheType == STANDARD_TYPE(Geom2d_BezierCurve)) {
592     aTypeCurve = GeomAbs_BezierCurve;
593   }
594   else if ( TheType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
595     aTypeCurve = GeomAbs_BSplineCurve;
596   }
597   else {
598     aTypeCurve = GeomAbs_OtherCurve;
599   }
600   return aTypeCurve;    
601 }
602 //=======================================================================
603 //function : AdjustCurveEnd
604 //purpose  : 
605 //=======================================================================
606 void AdjustCurveEnd(Handle(Geom2d_BoundedCurve)& theC2d, const gp_Pnt2d theP,
607                            const Standard_Boolean isFirst)
608 {
609   GeomAbs_CurveType aType = GetCurveType(theC2d);
610   if(aType == GeomAbs_Line)
611   {
612     //create new line
613     if(isFirst)
614     {
615       gp_Pnt2d aP = theC2d->Value(theC2d->LastParameter());
616       theC2d = GCE2d_MakeSegment(theP, aP).Value();
617     }
618     else
619     {
620       gp_Pnt2d aP = theC2d->Value(theC2d->FirstParameter());
621       theC2d = GCE2d_MakeSegment(aP, theP).Value();
622     }
623   }
624   else
625   {
626     //Convert to BSpline and adjust first pole
627     Handle(Geom2d_BSplineCurve) BCurve = 
628       Geom2dConvert::CurveToBSplineCurve(theC2d, Convert_QuasiAngular);
629     if(isFirst)
630     {
631       BCurve->SetPole(1, theP);
632       theC2d = new Geom2d_TrimmedCurve(BCurve, BCurve->FirstParameter(),
633                                                BCurve->LastParameter());
634     }
635     else
636     {
637       BCurve->SetPole(BCurve->NbPoles(), theP);
638       theC2d = new Geom2d_TrimmedCurve(BCurve, BCurve->FirstParameter(),
639                                                BCurve->LastParameter());
640     }
641   }
642
643 }