0031459: Visualization, AIS_TextLabel - add missing getters
[occt.git] / src / AIS / AIS_MidPointRelation.cxx
1 // Created on: 2000-10-20
2 // Created by: Julia DOROVSKIKH
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <AIS.hxx>
18 #include <AIS_MidPointRelation.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Curve.hxx>
21 #include <BRepAdaptor_Surface.hxx>
22 #include <DsgPrs_MidPointPresentation.hxx>
23 #include <ElCLib.hxx>
24 #include <gce_MakeLin.hxx>
25 #include <Geom_Circle.hxx>
26 #include <Geom_Ellipse.hxx>
27 #include <Geom_Line.hxx>
28 #include <Geom_Plane.hxx>
29 #include <Geom_Transformation.hxx>
30 #include <Geom_TrimmedCurve.hxx>
31 #include <gp_Ax1.hxx>
32 #include <gp_Ax2.hxx>
33 #include <gp_Circ.hxx>
34 #include <gp_Dir.hxx>
35 #include <gp_Elips.hxx>
36 #include <gp_Lin.hxx>
37 #include <gp_Pln.hxx>
38 #include <gp_Pnt.hxx>
39 #include <Precision.hxx>
40 #include <Prs3d_ArrowAspect.hxx>
41 #include <Prs3d_DimensionAspect.hxx>
42 #include <Prs3d_Drawer.hxx>
43 #include <Prs3d_Presentation.hxx>
44 #include <Select3D_SensitiveCurve.hxx>
45 #include <Select3D_SensitiveSegment.hxx>
46 #include <SelectMgr_EntityOwner.hxx>
47 #include <SelectMgr_Selection.hxx>
48 #include <Standard_NotImplemented.hxx>
49 #include <Standard_Type.hxx>
50 #include <TopExp_Explorer.hxx>
51 #include <TopoDS.hxx>
52 #include <TopoDS_Shape.hxx>
53 #include <TopoDS_Vertex.hxx>
54
55 IMPLEMENT_STANDARD_RTTIEXT(AIS_MidPointRelation,AIS_Relation)
56
57 //=======================================================================
58 //function : AIS_MidPointRelation
59 //purpose  : 
60 //=======================================================================
61 AIS_MidPointRelation::AIS_MidPointRelation(const TopoDS_Shape& aMidPointTool, 
62                                            const TopoDS_Shape& FirstShape, 
63                                            const TopoDS_Shape& SecondShape, 
64                                            const Handle(Geom_Plane)& aPlane)
65 :AIS_Relation(),
66  myTool(aMidPointTool)
67 {
68  SetFirstShape(FirstShape);
69  SetSecondShape(SecondShape);
70  SetPlane(aPlane);
71  myPosition = aPlane->Pln().Location();
72 }
73
74 //=======================================================================
75 //function : Compute
76 //purpose  : 
77 //=======================================================================
78 void AIS_MidPointRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&, 
79                                    const Handle(Prs3d_Presentation)& aprs, 
80                                    const Standard_Integer)
81 {
82   if (myTool.ShapeType() == TopAbs_VERTEX)
83     {
84       gp_Pnt pp;
85       Standard_Boolean isonplane;
86       if ( AIS::ComputeGeometry(TopoDS::Vertex(myTool),pp,myPlane,isonplane) )
87         {
88           if ( !isonplane ) ComputeProjVertexPresentation(aprs,TopoDS::Vertex(myTool),pp);
89         }
90       myMidPoint = pp;
91     }
92   else return;
93
94   if ( myAutomaticPosition ) myPosition = myMidPoint;  
95
96   switch (myFShape.ShapeType())
97     {
98     case TopAbs_FACE :
99       {
100         ComputeFaceFromPnt(aprs, Standard_True);
101       }
102       break;
103     case TopAbs_EDGE :
104       {
105         ComputeEdgeFromPnt(aprs, Standard_True);
106       }
107       break;
108     case TopAbs_VERTEX :
109       {
110         ComputeVertexFromPnt(aprs, Standard_True);
111       }
112       break;
113     default:
114       break;
115     }
116
117   switch (mySShape.ShapeType())
118     {
119     case TopAbs_FACE :
120       {
121         ComputeFaceFromPnt(aprs, Standard_False);
122       }
123       break;
124     case TopAbs_EDGE :
125       {
126         ComputeEdgeFromPnt(aprs, Standard_False);
127       }
128       break;
129     case TopAbs_VERTEX :
130       {
131         ComputeVertexFromPnt(aprs, Standard_False);
132       }
133       break;
134     default:
135       break;
136     }
137 }
138
139 //=======================================================================
140 //function : ComputeSelection
141 //purpose  : 
142 //=======================================================================
143 void AIS_MidPointRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSel, 
144                                             const Standard_Integer)
145 {
146   Handle(Select3D_SensitiveSegment) seg;
147   Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
148
149   if ( !myMidPoint.IsEqual(myFAttach,Precision::Confusion()) )
150     {
151       // segment from mid point to the first geometry
152       seg = new Select3D_SensitiveSegment(own,myFAttach,myMidPoint);
153       aSel->Add(seg);
154       // segment from mid point to the second geometry
155       seg = new Select3D_SensitiveSegment(own,mySAttach,myMidPoint);
156       aSel->Add(seg);
157     }
158   if ( !myMidPoint.IsEqual(myPosition,Precision::Confusion()) )
159     {
160       // segment from mid point to the text position
161       seg = new Select3D_SensitiveSegment(own,myMidPoint,myPosition);
162       aSel->Add(seg);
163     }
164
165   // center of the symmetry - circle around the MidPoint
166   gp_Ax2 ax = myPlane->Pln().Position().Ax2();
167   ax.SetLocation(myMidPoint);
168   Standard_Real rad = myFAttach.Distance(myMidPoint)/20.0;
169   gp_Circ aCircleM (ax,rad);
170   Handle(Geom_Curve) thecir = new Geom_Circle(aCircleM);
171   Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecir);
172   aSel->Add(scurv);
173
174   Handle(Geom_Curve) curv;
175   gp_Pnt firstp,lastp;
176   Standard_Boolean isInfinite,isOnPlane;
177   Handle(Geom_Curve) extCurv;
178
179   // segment on first curve
180   if ( myFShape.ShapeType() == TopAbs_EDGE )
181     {
182       TopoDS_Edge E = TopoDS::Edge(myFShape);
183       if ( !AIS::ComputeGeometry(E,curv,firstp,lastp,extCurv,isInfinite,isOnPlane,myPlane) ) return;
184       if ( curv->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of line
185         {
186           // segment on line
187           seg = new Select3D_SensitiveSegment(own,myFirstPnt1,myFirstPnt2);
188           aSel->Add(seg);
189         }
190       else if ( curv->IsInstance(STANDARD_TYPE(Geom_Circle)) ) // case of circle
191         {
192           // segment on circle
193           Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv);
194           Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFirstPnt1);
195           Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),myFirstPnt2);
196           Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
197           
198           scurv = new Select3D_SensitiveCurve(own, thecu);
199           aSel->Add(scurv);
200         }
201       else if ( curv->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipse
202         {
203           // segment on ellipse
204           Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv);
205           Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFirstPnt1);
206           Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),myFirstPnt2);
207           Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
208           
209           scurv = new Select3D_SensitiveCurve(own, thecu);
210           aSel->Add(scurv);
211         }
212     }
213
214   // segment on second curve
215   if ( mySShape.ShapeType() == TopAbs_EDGE )
216     {
217       TopoDS_Edge E = TopoDS::Edge(mySShape);
218       if ( !AIS::ComputeGeometry(E,curv,firstp,lastp,extCurv,isInfinite,isOnPlane,myPlane) ) return;
219       if ( curv->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of line
220         {
221           // segment on line
222           seg = new Select3D_SensitiveSegment(own,mySecondPnt1,mySecondPnt2);
223           aSel->Add(seg);
224         }
225       else if ( curv->IsInstance(STANDARD_TYPE(Geom_Circle)) ) // case of circle
226         {
227           // segment on circle
228           Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv);
229           Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),mySecondPnt1);
230           Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySecondPnt2);
231           Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
232           
233           scurv = new Select3D_SensitiveCurve(own, thecu);
234           aSel->Add(scurv);
235         }
236       else if ( curv->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipse
237         {
238           // segment on ellipse
239           Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv);
240           Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),mySecondPnt1);
241           Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySecondPnt2);
242           Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
243           
244           scurv = new Select3D_SensitiveCurve(own, thecu);
245           aSel->Add(scurv);
246         }
247     }
248 }
249
250 //=======================================================================
251 //function : ComputeFaceFromPnt
252 //purpose  : 
253 //=======================================================================
254 void AIS_MidPointRelation::ComputeFaceFromPnt(const Handle(Prs3d_Presentation)&,
255                                               const Standard_Boolean /*first*/)
256 {
257 }
258
259 //=======================================================================
260 //function : ComputeEdgeFromPnt
261 //purpose  : 
262 //=======================================================================
263 void AIS_MidPointRelation::ComputeEdgeFromPnt(const Handle(Prs3d_Presentation)& aprs,
264                                               const Standard_Boolean first)
265 {
266   TopoDS_Edge E;
267   if ( first ) E = TopoDS::Edge(myFShape);
268   else         E = TopoDS::Edge(mySShape);
269
270   Handle(Geom_Curve) geom;
271   gp_Pnt ptat1,ptat2;
272   Handle(Geom_Curve) extCurv;
273   Standard_Boolean isInfinite,isOnPlane;
274   if ( !AIS::ComputeGeometry(E, geom, ptat1, ptat2, extCurv, isInfinite, isOnPlane, myPlane) ) return;
275
276   gp_Ax2 ax = myPlane->Pln().Position().Ax2();
277
278   if ( geom->IsInstance(STANDARD_TYPE(Geom_Line)) )
279     {
280       if ( !isInfinite ) ComputePointsOnLine(ptat1,ptat2,first);
281       else
282         {
283           const gp_Lin& line = Handle(Geom_Line)::DownCast (geom)->Lin();
284           ComputePointsOnLine(line,first);
285         }
286       if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,
287                                                     myFAttach,myFirstPnt1,myFirstPnt2,first);
288       else         DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,
289                                                     mySAttach,mySecondPnt1,mySecondPnt2,first);
290     }
291   else if ( geom->IsInstance(STANDARD_TYPE(Geom_Circle)) )
292     {
293       Handle(Geom_Circle) geom_cir (Handle(Geom_Circle)::DownCast (geom));
294       gp_Circ circ (geom_cir->Circ());
295       ComputePointsOnCirc(circ,ptat1,ptat2,first);
296       if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,circ,myMidPoint,myPosition,
297                                                     myFAttach,myFirstPnt1,myFirstPnt2,first);
298       else         DsgPrs_MidPointPresentation::Add(aprs,myDrawer,circ,myMidPoint,myPosition,
299                                                     mySAttach,mySecondPnt1,mySecondPnt2,first);
300     }
301   else if ( geom->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
302     {
303       Handle(Geom_Ellipse) geom_ell (Handle(Geom_Ellipse)::DownCast (geom));
304       gp_Elips elips (geom_ell->Elips());
305       ComputePointsOnElips(elips,ptat1,ptat2,first);
306       if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,elips,myMidPoint,myPosition,
307                                                     myFAttach,myFirstPnt1,myFirstPnt2,first);
308       else         DsgPrs_MidPointPresentation::Add(aprs,myDrawer,elips,myMidPoint,myPosition,
309                                                     mySAttach,mySecondPnt1,mySecondPnt2,first);
310     }
311   else return;
312
313   // projection on myPlane
314   if ( !isOnPlane ) ComputeProjEdgePresentation(aprs,E,geom,ptat1,ptat2);
315 }
316
317 //=======================================================================
318 //function : ComputeVertexFromPnt
319 //purpose  : 
320 //=======================================================================
321 void AIS_MidPointRelation::ComputeVertexFromPnt(const Handle(Prs3d_Presentation)& aprs,
322                                                 const Standard_Boolean first)
323 {
324   gp_Ax2 ax = myPlane->Pln().Position().Ax2();
325   if ( first )
326     {
327       Standard_Boolean isOnPlane;
328       TopoDS_Vertex V = TopoDS::Vertex(myFShape);
329       AIS::ComputeGeometry(V, myFAttach, myPlane, isOnPlane);
330       DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,myFAttach,first);
331       if ( !isOnPlane ) ComputeProjVertexPresentation(aprs,V,myFAttach);
332     }
333   else
334     {
335       Standard_Boolean isOnPlane;
336       TopoDS_Vertex V = TopoDS::Vertex(mySShape);
337       AIS::ComputeGeometry(V, mySAttach, myPlane, isOnPlane);
338       DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,mySAttach,first);
339       if ( !isOnPlane ) ComputeProjVertexPresentation(aprs,V,mySAttach);
340     }
341 }
342
343 //=======================================================================
344 //function : ComputePointsOnLine
345 //purpose  : 
346 //=======================================================================
347 void AIS_MidPointRelation::ComputePointsOnLine(const gp_Lin& aLin,
348                                                const Standard_Boolean first)
349 {
350   Standard_Real ppar = ElCLib::Parameter(aLin,myMidPoint);
351   gp_Pnt anAttach = ElCLib::Value(ppar,aLin);
352
353   Standard_Real dist = anAttach.Distance(myMidPoint)/10.0;
354   if ( dist < Precision::Confusion() ) dist = 10.0;
355
356   Standard_Real fpar = ppar + dist;
357   Standard_Real spar = ppar - dist;
358
359   gp_Pnt aPnt1 = ElCLib::Value(fpar,aLin);
360   gp_Pnt aPnt2 = ElCLib::Value(spar,aLin);
361
362   if ( first )
363     {
364       myFAttach = anAttach;
365       myFirstPnt1 = aPnt1;
366       myFirstPnt2 = aPnt2;
367     }
368   else
369     {
370       mySAttach = anAttach;
371       mySecondPnt1 = aPnt1;
372       mySecondPnt2 = aPnt2;
373     }
374 }
375
376 //=======================================================================
377 //function : ComputePointsOnLine
378 //purpose  : 
379 //=======================================================================
380 void AIS_MidPointRelation::ComputePointsOnLine(const gp_Pnt& pnt1, const gp_Pnt& pnt2,
381                                                const Standard_Boolean first)
382 {
383   gp_Vec aVec (pnt1,pnt2);
384   gp_Lin aLin (pnt1,gp_Dir(aVec));
385
386   Standard_Real fpar = ElCLib::Parameter(aLin,pnt1);
387   Standard_Real spar = ElCLib::Parameter(aLin,pnt2);
388   Standard_Real ppar = ElCLib::Parameter(aLin,myMidPoint);
389
390   gp_Pnt aProjPnt = ElCLib::Value(ppar,aLin);
391   Standard_Real dist = myMidPoint.Distance(aProjPnt);
392   Standard_Real ll = pnt1.Distance(pnt2);
393   Standard_Real segm = Min(dist,ll)*0.75;
394   if ( dist < Precision::Confusion() ) segm = ll*0.75;
395
396   gp_Pnt anAttach,aPnt1,aPnt2;
397   anAttach = aProjPnt;
398   gp_Vec aVecTr;
399   if ( ppar <= fpar )
400     {
401       aPnt2 = pnt1;
402       aVecTr = gp_Vec(pnt2,pnt1);
403       aVecTr.Normalize();
404       aPnt1 = aProjPnt.Translated(aVecTr*segm);
405     }
406   else if ( ppar >= spar )
407     {
408       aPnt1 = pnt2;
409       aVecTr = gp_Vec(pnt1,pnt2);
410       aVecTr.Normalize();
411       aPnt2 = aProjPnt.Translated(aVecTr*segm);
412     }
413   else
414     {
415       Standard_Real dp1 = aProjPnt.Distance(pnt1);
416       Standard_Real dp2 = aProjPnt.Distance(pnt2);
417
418       segm = Min(dist,dp1)*0.75;
419       aVecTr = gp_Vec(aProjPnt,pnt1);
420       aVecTr.Normalize();
421       aPnt1 = aProjPnt.Translated(aVecTr*segm);
422
423       segm = Min(dist,dp2)*0.75;
424       aVecTr = gp_Vec(aProjPnt,pnt2);
425       aVecTr.Normalize();
426       aPnt2 = aProjPnt.Translated(aVecTr*segm);
427     }
428
429   if ( first )
430     {
431       myFAttach = anAttach;
432       myFirstPnt1 = aPnt1;
433       myFirstPnt2 = aPnt2;
434     }
435   else
436     {
437       mySAttach = anAttach;
438       mySecondPnt1 = aPnt1;
439       mySecondPnt2 = aPnt2;
440     }
441 }
442
443 //=======================================================================
444 //function : ComputePointsOnCirc
445 //purpose  : 
446 //=======================================================================
447 void AIS_MidPointRelation::ComputePointsOnCirc(const gp_Circ& aCirc,
448                                                const gp_Pnt& pnt1, const gp_Pnt& pnt2,
449                                                const Standard_Boolean first)
450 {
451   gp_Pnt curpos = myMidPoint;
452
453   // Case of confusion between the current position and the center 
454   // of the circle -> we move the current position
455   Standard_Real confusion (Precision::Confusion());
456   gp_Pnt aCenter = aCirc.Location();
457   if ( aCenter.Distance(curpos) <= confusion )
458     {
459       gp_Vec vprec(aCenter, pnt1);
460       vprec.Normalize();
461       curpos.Translate(vprec*1e-5);
462     }
463   
464   Standard_Real pcurpos = ElCLib::Parameter(aCirc,curpos);
465
466   Standard_Real rad = M_PI / 5.0;
467   Standard_Real segm;
468
469   Standard_Real pFPnt;
470   Standard_Real pSPnt;
471
472   if ( pnt1.IsEqual(pnt2,confusion) ) // full circle
473     {
474       pFPnt = pcurpos - rad;
475       pSPnt = pcurpos + rad;
476     }
477   else
478     {
479       Standard_Real pFAttach = ElCLib::Parameter(aCirc,pnt1);
480       Standard_Real pSAttach = ElCLib::Parameter(aCirc,pnt2);
481
482       Standard_Real pSAttachM = pSAttach;
483       Standard_Real deltap = pSAttachM - pFAttach;
484       if ( deltap < 0 )
485         {
486           deltap += 2 * M_PI;
487           pSAttachM += 2 * M_PI;
488         }
489       pSAttachM -= pFAttach;
490
491       Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
492
493       Standard_Real pcurpos1 = pcurpos;
494       // define where curpos lays
495       if ( pcurpos1 < pFAttach )
496         {
497           pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
498           if ( pcurpos1 > pSAttachM ) // out
499             {
500               segm = Min(rad,deltap*0.75);
501               if ( pcurpos1 > pmiddleout )
502                 {
503                   pcurpos = pFAttach;
504                   pFPnt = pFAttach;
505                   pSPnt = pFAttach + segm;
506                 }
507               else
508                 {
509                   pcurpos = pSAttach;
510                   pFPnt = pSAttach - segm;
511                   pSPnt = pSAttach;
512                 }
513             }
514           else // on arc
515             {
516               Standard_Real dp1 = pcurpos1 - pFAttach;
517               Standard_Real dp2 = pSAttachM - pcurpos1;
518
519               segm = Min(rad,dp1*0.75);
520               pFPnt = pcurpos - segm;
521               
522               segm = Min(rad,dp2*0.75);
523               pSPnt = pcurpos + segm;
524             }
525         }
526       else if ( pcurpos1 > (pFAttach + deltap) ) // out
527         {
528           pcurpos1 -= pFAttach;
529           segm = Min(rad,deltap*0.75);
530           if ( pcurpos1 > pmiddleout )
531             {
532               pcurpos = pFAttach;
533               pFPnt = pFAttach;
534               pSPnt = pFAttach + segm;
535             }
536           else
537             {
538               pcurpos = pSAttach;
539               pFPnt = pSAttach - segm;
540               pSPnt = pSAttach;
541             }
542         }
543       else // on arc
544         {
545           Standard_Real dp1 = pcurpos1 - pFAttach;
546           Standard_Real dp2 = pSAttach - pcurpos1;
547
548           segm = Min(rad,dp1*0.75);
549           pFPnt = pcurpos - segm;
550           
551           segm = Min(rad,dp2*0.75);
552           pSPnt = pcurpos + segm;
553         }
554     }
555
556   if ( first )
557     {
558       myFAttach   = ElCLib::Value(pcurpos,aCirc);
559       myFirstPnt1 = ElCLib::Value(pFPnt,aCirc);
560       myFirstPnt2 = ElCLib::Value(pSPnt,aCirc);
561     }
562   else
563     {
564       mySAttach    = ElCLib::Value(pcurpos,aCirc);
565       mySecondPnt1 = ElCLib::Value(pFPnt,aCirc);
566       mySecondPnt2 = ElCLib::Value(pSPnt,aCirc);
567     }
568 }
569
570 //=======================================================================
571 //function : ComputePointsOnElips
572 //purpose  : 
573 //=======================================================================
574 void AIS_MidPointRelation::ComputePointsOnElips(const gp_Elips& anEll,
575                                                 const gp_Pnt& pnt1, const gp_Pnt& pnt2,
576                                                 const Standard_Boolean first)
577 {
578   gp_Pnt curpos = myMidPoint;
579
580   // Case of confusion between the current position and the center 
581   // of the circle -> we move the current position
582   Standard_Real confusion (Precision::Confusion());
583   gp_Pnt aCenter = anEll.Location();
584   if ( aCenter.Distance(curpos) <= confusion )
585     {
586       gp_Vec vprec(aCenter, pnt1);
587       vprec.Normalize();
588       curpos.Translate(vprec*1e-5);
589     }
590   
591   Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
592
593   Standard_Real rad = M_PI / 5.0;
594   Standard_Real segm;
595
596   Standard_Real pFPnt;
597   Standard_Real pSPnt;
598
599   if ( pnt1.IsEqual(pnt2,confusion) ) // full circle
600     {
601       pFPnt = pcurpos - rad;
602       pSPnt = pcurpos + rad;
603     }
604   else
605     {
606       Standard_Real pFAttach = ElCLib::Parameter(anEll,pnt1);
607       Standard_Real pSAttach = ElCLib::Parameter(anEll,pnt2);
608
609       Standard_Real pSAttachM = pSAttach;
610       Standard_Real deltap = pSAttachM - pFAttach;
611       if ( deltap < 0 )
612         {
613           deltap += 2 * M_PI;
614           pSAttachM += 2 * M_PI;
615         }
616       pSAttachM -= pFAttach;
617
618       Standard_Real pmiddleout = pSAttachM / 2.0 + M_PI;
619
620       Standard_Real pcurpos1 = pcurpos;
621       // define where curpos lays
622       if ( pcurpos1 < pFAttach )
623         {
624           pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
625           if ( pcurpos1 > pSAttachM ) // out
626             {
627               segm = Min(rad,deltap*0.75);
628               if ( pcurpos1 > pmiddleout )
629                 {
630                   pcurpos = pFAttach;
631                   pFPnt = pFAttach;
632                   pSPnt = pFAttach + segm;
633                 }
634               else
635                 {
636                   pcurpos = pSAttach;
637                   pFPnt = pSAttach - segm;
638                   pSPnt = pSAttach;
639                 }
640             }
641           else // on arc
642             {
643               Standard_Real dp1 = pcurpos1 - pFAttach;
644               Standard_Real dp2 = pSAttachM - pcurpos1;
645
646               segm = Min(rad,dp1*0.75);
647               pFPnt = pcurpos - segm;
648               
649               segm = Min(rad,dp2*0.75);
650               pSPnt = pcurpos + segm;
651             }
652         }
653       else if ( pcurpos1 > (pFAttach + deltap) ) // out
654         {
655           pcurpos1 -= pFAttach;
656           segm = Min(rad,deltap*0.75);
657           if ( pcurpos1 > pmiddleout )
658             {
659               pcurpos = pFAttach;
660               pFPnt = pFAttach;
661               pSPnt = pFAttach + segm;
662             }
663           else
664             {
665               pcurpos = pSAttach;
666               pFPnt = pSAttach - segm;
667               pSPnt = pSAttach;
668             }
669         }
670       else // on arc
671         {
672           Standard_Real dp1 = pcurpos1 - pFAttach;
673           Standard_Real dp2 = pSAttach - pcurpos1;
674
675           segm = Min(rad,dp1*0.75);
676           pFPnt = pcurpos - segm;
677           
678           segm = Min(rad,dp2*0.75);
679           pSPnt = pcurpos + segm;
680         }
681     }
682
683   if ( first )
684     {
685       myFAttach   = ElCLib::Value(pcurpos,anEll);
686       myFirstPnt1 = ElCLib::Value(pFPnt,anEll);
687       myFirstPnt2 = ElCLib::Value(pSPnt,anEll);
688     }
689   else
690     {
691       mySAttach    = ElCLib::Value(pcurpos,anEll);
692       mySecondPnt1 = ElCLib::Value(pFPnt,anEll);
693       mySecondPnt2 = ElCLib::Value(pSPnt,anEll);
694     }
695 }