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