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