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