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