0031459: Visualization, AIS_TextLabel - add missing getters
[occt.git] / src / PrsDim / PrsDim_IdenticRelation.cxx
1 // Created on: 1997-03-03
2 // Created by: Jean-Pierre COMBE
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <PrsDim_IdenticRelation.hxx>
18
19 #include <PrsDim.hxx>
20 #include <AIS_Shape.hxx>
21 #include <BRep_Tool.hxx>
22 #include <DsgPrs_IdenticPresentation.hxx>
23 #include <ElCLib.hxx>
24 #include <Geom_Circle.hxx>
25 #include <Geom_Ellipse.hxx>
26 #include <Geom_Line.hxx>
27 #include <Geom_Plane.hxx>
28 #include <Geom_TrimmedCurve.hxx>
29 #include <GeomAPI_ProjectPointOnCurve.hxx>
30 #include <gp_Dir.hxx>
31 #include <gp_Pln.hxx>
32 #include <gp_Pnt.hxx>
33 #include <gp_Vec.hxx>
34 #include <Precision.hxx>
35 #include <Prs3d_Drawer.hxx>
36 #include <Prs3d_LineAspect.hxx>
37 #include <Prs3d_Presentation.hxx>
38 #include <Select3D_SensitiveCurve.hxx>
39 #include <Select3D_SensitiveSegment.hxx>
40 #include <SelectMgr_EntityOwner.hxx>
41 #include <SelectMgr_Selection.hxx>
42 #include <Standard_NotImplemented.hxx>
43 #include <TCollection_ExtendedString.hxx>
44 #include <TColStd_ListIteratorOfListOfTransient.hxx>
45 #include <TopAbs.hxx>
46 #include <TopExp.hxx>
47 #include <TopoDS.hxx>
48 #include <TopoDS_Edge.hxx>
49 #include <TopoDS_Shape.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopoDS_Wire.hxx>
52 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
53 #include <TopTools_ListIteratorOfListOfShape.hxx>
54
55 IMPLEMENT_STANDARD_RTTIEXT(PrsDim_IdenticRelation, PrsDim_Relation)
56
57 // jfa 15/10/2000
58 static Standard_Real Modulo2PI(const Standard_Real ANGLE)
59 {
60   if ( ANGLE < 0 )          return Modulo2PI(ANGLE + 2*M_PI);
61   else if ( ANGLE >= 2*M_PI ) return Modulo2PI(ANGLE - 2*M_PI);
62   return ANGLE;
63 }
64
65 static Standard_Boolean IsEqual2PI(const Standard_Real angle1,
66                                    const Standard_Real angle2, const Standard_Real precision)
67 {
68   Standard_Real diff = Abs(angle1-angle2);
69   if ( diff < precision )                return Standard_True;
70   else if ( Abs(diff-2*M_PI) < precision ) return Standard_True;
71   return Standard_False;
72 }
73 // jfa 15/10/2000 end
74
75 //=======================================================================
76 //function : PrsDim_Sort
77 //purpose  : sort an array of parameters <tab1> in increasing order
78 //           updates <tab2> and <tab3> according to <tab1>
79 //=======================================================================
80 static void PrsDim_Sort(Standard_Real tab1[4],
81                      gp_Pnt tab2[4],
82                      Standard_Integer tab3[4])
83 {
84   Standard_Boolean found = Standard_True;
85   Standard_Real cur; gp_Pnt cur1; Standard_Integer cur2;
86   
87   while (found) {
88     found = Standard_False;
89     for (Standard_Integer i=0; i< 3; i++) {
90       if (tab1[i+1] < tab1[i]) {
91         found = Standard_True;
92         cur = tab1[i]; cur1 = tab2[i]; cur2 = tab3[i];
93         tab1[i] = tab1[i+1]; tab2[i] = tab2[i+1]; tab3[i] = tab3[i+1]; 
94         tab1[i+1] = cur; tab2[i+1] = cur1; tab3[i+1] = cur2; 
95       }
96     }
97   }
98 }
99
100 //=======================================================================
101 //function : ConnectedEdges
102 //purpose  : 
103 //=======================================================================
104 static Standard_Boolean ConnectedEdges(const TopoDS_Wire& WIRE,
105                                        const TopoDS_Vertex& V, 
106                                        TopoDS_Edge& E1, 
107                                        TopoDS_Edge& E2)
108 {
109   TopTools_IndexedDataMapOfShapeListOfShape  vertexMap;
110   TopExp::MapShapesAndAncestors (WIRE,TopAbs_VERTEX,TopAbs_EDGE,vertexMap);
111   
112   Standard_Boolean found(Standard_False);
113   TopoDS_Vertex theVertex;
114   for (Standard_Integer i=1; i<=vertexMap.Extent() && !found; i++) {
115     if (vertexMap.FindKey(i).IsSame(V)) {
116       theVertex = TopoDS::Vertex(vertexMap.FindKey(i));
117       found = Standard_True;
118     }
119   }
120   if (!found) {
121     E1.Nullify();
122     E2.Nullify();
123     return Standard_False;
124   }
125   
126   TopTools_ListIteratorOfListOfShape iterator(vertexMap.FindFromKey(theVertex));
127   if (iterator.More()) {
128     E1 = TopoDS::Edge(iterator.Value());
129     iterator.Next();
130   }
131   else {
132     E1.Nullify();
133     return Standard_False;
134   }
135   
136   if (iterator.More()) {
137     E2 = TopoDS::Edge(iterator.Value());
138     iterator.Next();
139   }
140   else {
141     E2.Nullify();
142     return Standard_False;
143   }
144   
145   if (iterator.More()) {
146     E1.Nullify();
147     E2.Nullify();
148     return Standard_False;
149   }
150   return Standard_True;
151 }
152
153 // jfa 16/10/2000
154 //=======================================================================
155 //function : ComputeAttach
156 //purpose  : Compute a point on the arc of <thecirc>
157 //             between <aFAttach> and <aSAttach>
158 //             corresponding to <aPosition>
159 //           Returns result into <aPosition>
160 // Note    : This function is to be used only in the case of circles.
161 //           The <aPosition> parameter is in/out.
162 //=======================================================================
163 static Standard_Boolean ComputeAttach(const gp_Circ& thecirc,
164                                       const gp_Pnt& aFAttach,
165                                       const gp_Pnt& aSAttach,
166                                       gp_Pnt& aPosition)
167 {
168   gp_Pnt curpos = aPosition;
169
170   // Case of confusion between the current position and the center 
171   // of the circle -> we move the current position
172   Standard_Real confusion (Precision::Confusion());
173   gp_Pnt aCenter = thecirc.Location();
174   if ( aCenter.Distance(curpos) <= confusion )
175     {
176       gp_Vec vprec(aCenter, aFAttach);
177       vprec.Normalize();
178       curpos.Translate(vprec*1e-5);
179     }
180   
181   Standard_Real pcurpos  = ElCLib::Parameter(thecirc,curpos);
182   Standard_Real pFAttach = ElCLib::Parameter(thecirc,aFAttach);
183   Standard_Real pSAttach = ElCLib::Parameter(thecirc,aSAttach);
184
185   Standard_Real pSAttachM = pSAttach;
186   Standard_Real deltap = pSAttachM - pFAttach;
187   if ( deltap < 0 )
188     {
189       deltap += 2 * M_PI;
190       pSAttachM += 2 * M_PI;
191     }
192   pSAttachM -= pFAttach;
193
194   Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
195
196   Standard_Real pcurpos1 = pcurpos;
197   // define where curpos lays
198   if ( pcurpos1 < pFAttach )
199     {
200       pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
201       if ( pcurpos1 > pSAttachM ) // out
202         {
203           if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
204           else pcurpos = pSAttach;
205         }
206     }
207   else if ( pcurpos1 > (pFAttach + deltap) ) // out
208     {
209       pcurpos1 -= pFAttach;
210       if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
211       else pcurpos = pSAttach;
212     }
213
214   aPosition = ElCLib::Value(pcurpos,thecirc);
215   return Standard_True;
216 }
217
218 //=======================================================================
219 //function : ComputeAttach
220 //purpose  : Compute a point on the arc of ellipse <theEll>
221 //             between <aFAttach> and <aSAttach>
222 //             corresponding to <aPosition>
223 //           Returns result into <aPosition>
224 // Note    : This function is to be used only in the case of ellipses.
225 //           The <aPosition> parameter is in/out.
226 //=======================================================================
227 static Standard_Boolean ComputeAttach(const gp_Elips& theEll,
228                                       const gp_Pnt& aFAttach,
229                                       const gp_Pnt& aSAttach,
230                                       gp_Pnt& aPosition)
231 {
232   gp_Pnt curpos = aPosition;
233
234   // Case of confusion between the current position and the center 
235   // of the circle -> we move the current position
236   Standard_Real confusion (Precision::Confusion());
237   gp_Pnt aCenter = theEll.Location();
238   if ( aCenter.Distance(curpos) <= confusion )
239     {
240       gp_Vec vprec(aCenter, aFAttach);
241       vprec.Normalize();
242       curpos.Translate(vprec*1e-5);
243     }
244   
245 // for ellipses it's not good  Standard_Real pcurpos  = ElCLib::Parameter(theEll,curpos);
246   Handle(Geom_Ellipse) theEllg = new Geom_Ellipse(theEll);
247   GeomAPI_ProjectPointOnCurve aProj (curpos, theEllg);
248   Standard_Real pcurpos  = aProj.LowerDistanceParameter();
249
250   Standard_Real pFAttach = ElCLib::Parameter(theEll,aFAttach);
251   Standard_Real pSAttach = ElCLib::Parameter(theEll,aSAttach);
252
253   Standard_Real pSAttachM = pSAttach;
254   Standard_Real deltap = pSAttachM - pFAttach;
255   if ( deltap < 0 )
256     {
257       deltap += 2 * M_PI;
258       pSAttachM += 2 * M_PI;
259     }
260   pSAttachM -= pFAttach;
261
262   Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
263
264   Standard_Real pcurpos1 = pcurpos;
265   // define where curpos lays
266   if ( pcurpos1 < pFAttach )
267     {
268       pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
269       if ( pcurpos1 > pSAttachM ) // out
270         {
271           if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
272           else pcurpos = pSAttach;
273         }
274     }
275   else if ( pcurpos1 > (pFAttach + deltap) ) // out
276     {
277       pcurpos1 -= pFAttach;
278       if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
279       else pcurpos = pSAttach;
280     }
281
282   aPosition = ElCLib::Value(pcurpos,theEll);
283   return Standard_True;
284 }
285 // jfa 16/10/2000 end
286
287 //=======================================================================
288 //function : PrsDim_IdenticRelation
289 //purpose  : 
290 //=======================================================================
291 PrsDim_IdenticRelation::PrsDim_IdenticRelation(const TopoDS_Shape& FirstShape, 
292                                          const TopoDS_Shape& SecondShape, 
293                                          const Handle(Geom_Plane)& aPlane)
294   :isCircle(Standard_False)
295 {
296   myFShape = FirstShape;
297   mySShape = SecondShape;
298   myPlane  = aPlane;
299 }
300
301 //=======================================================================
302 //function : Compute
303 //purpose  : 
304 //=======================================================================
305 void PrsDim_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&, 
306                                   const Handle(Prs3d_Presentation)& aprs, 
307                                   const Standard_Integer)
308 {
309   switch ( myFShape.ShapeType() ) {
310     
311   case TopAbs_VERTEX:
312     {
313       switch ( mySShape.ShapeType() ) {
314       case TopAbs_VERTEX:
315         {
316           ComputeTwoVerticesPresentation(aprs);
317         }
318       break;
319       case TopAbs_EDGE:
320         {
321           ComputeOneEdgeOVertexPresentation(aprs);
322         }
323       break;
324       default:
325         break;
326       }
327     }
328     break;
329     
330   case TopAbs_EDGE:
331     {
332       switch ( mySShape.ShapeType() ) {
333       case TopAbs_VERTEX:
334         {
335           ComputeOneEdgeOVertexPresentation(aprs);
336         }
337       break;
338       case TopAbs_EDGE:
339         {
340           ComputeTwoEdgesPresentation(aprs);      
341         }
342       break;
343       default:
344         break;
345       }
346     }
347   break;
348   default: break;
349   }
350 }
351
352 //=======================================================================
353 //function : ComputeSelection
354 //purpose  : function used to compute the selection associated to the 
355 //           "identic" presentation
356 // note    : if we are in the case of lines, we create a segment between
357 //           myFAttach and mySAttach. In the case of Circles, we create
358 //           an arc of circle between the sames points. We Add a segment
359 //           to link Position to its projection on the curve described
360 //           before.
361 //=======================================================================
362
363 void PrsDim_IdenticRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
364                                            const Standard_Integer)
365 {
366   Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
367
368   Handle(Select3D_SensitiveSegment) seg;
369   // attachement point of the segment linking position to the curve
370   gp_Pnt attach; 
371   Standard_Real confusion (Precision::Confusion());
372     
373   if ( myFAttach.IsEqual(mySAttach, confusion) )
374     {
375       attach = myFAttach;
376     }
377   else
378     {    
379 // jfa 24/10/2000
380       if ( myFShape.ShapeType() == TopAbs_EDGE )
381         {
382           Handle(Geom_Curve) curv1,curv2;
383           gp_Pnt firstp1,lastp1,firstp2,lastp2;
384           Standard_Boolean isInfinite1,isInfinite2;
385           Handle(Geom_Curve) extCurv;
386           if ( !PrsDim::ComputeGeometry(TopoDS::Edge(myFShape),TopoDS::Edge(mySShape),
387                                      myExtShape,curv1,curv2,
388                                      firstp1,lastp1,firstp2,lastp2,
389                                      extCurv,isInfinite1,isInfinite2,myPlane) ) return;
390
391           if ( isCircle ) // case of Circles
392             {
393               Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv1);
394               Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFAttach);
395               Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySAttach);
396               Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
397       
398               Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
399               aSelection->Add(scurv);
400       
401               attach = myPosition;
402               ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
403             }
404           else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipses
405             {
406               Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv1);
407
408               Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFAttach);
409               Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySAttach);
410               Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
411       
412               Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
413               aSelection->Add(scurv);
414       
415               attach = myPosition;
416               ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
417             }
418           else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of Lines
419             {
420               seg = new Select3D_SensitiveSegment(own, myFAttach, mySAttach);
421               aSelection->Add(seg);
422               
423               //attach = projection of Position() on the curve;
424               gp_Vec v1 (myFAttach, mySAttach);
425               gp_Vec v2 (myFAttach, myPosition);
426               if ( v1.IsParallel(v2, Precision::Angular()) )
427                 {
428                   attach = mySAttach;
429                 }
430               else
431                 {
432                   gp_Lin ll (myFAttach, gp_Dir(v1));
433                   attach = ElCLib::Value(ElCLib::Parameter(ll,myPosition), ll);
434                 }
435             }
436           else return;
437         }
438 //      else if ( myFShape.ShapeType() == TopAbs_VERTEX )
439 //      {
440 //      }
441 // jfa 24/10/2000 end
442     }
443
444   // Creation of the segment linking the attachement point with the
445   // position
446   if ( !attach.IsEqual(myPosition, confusion) )
447     {
448       seg = new Select3D_SensitiveSegment(own, attach, myPosition);
449       aSelection->Add(seg);
450     }
451 }
452
453 //=======================================================================
454 //function : ComputeTwoEdgesPresentation
455 //purpose  : 
456 //=======================================================================
457 void PrsDim_IdenticRelation::ComputeTwoEdgesPresentation(const Handle(Prs3d_Presentation)& aPrs)
458 {
459   Handle(Geom_Curve) curv1,curv2;
460   gp_Pnt firstp1,lastp1,firstp2,lastp2;
461   Standard_Boolean isInfinite1,isInfinite2;
462
463   Handle(Geom_Curve) extCurv;
464   if (!PrsDim::ComputeGeometry(TopoDS::Edge(myFShape),
465                             TopoDS::Edge(mySShape),
466                             myExtShape,
467                             curv1,
468                             curv2,
469                             firstp1,
470                             lastp1,
471                             firstp2,
472                             lastp2,
473                             extCurv,
474                             isInfinite1,isInfinite2,
475                             myPlane))
476     return;
477   aPrs->SetInfiniteState((isInfinite1 || isInfinite2) && myExtShape != 0);
478
479   // Treatement of the case of lines
480   if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) && curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
481     // we take the line curv1 like support
482     Handle(Geom_Line) thelin;
483     if (isInfinite1 && !isInfinite2) thelin = Handle(Geom_Line)::DownCast (curv2);
484     else if (!isInfinite1 && isInfinite2) thelin = Handle(Geom_Line)::DownCast (curv1);
485     else thelin = Handle(Geom_Line)::DownCast (curv1);
486     ComputeTwoLinesPresentation(aPrs, thelin, firstp1, lastp1, firstp2, lastp2, isInfinite1, isInfinite2);
487   }
488
489   //  Treatement of the case of circles
490   else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) && curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
491     //gp_Pnt curpos;
492     isCircle = Standard_True; // useful for ComputeSelection
493     Handle(Geom_Circle) thecirc (Handle(Geom_Circle)::DownCast (curv1));
494     ComputeTwoCirclesPresentation(aPrs, thecirc, firstp1, lastp1, firstp2, lastp2);
495   }
496
497   // jfa 10/10/2000
498   //  Treatement of the case of ellipses
499   else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) && curv2->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
500       {
501         Handle(Geom_Ellipse) theEll (Handle(Geom_Ellipse)::DownCast (curv1));
502         ComputeTwoEllipsesPresentation(aPrs, theEll, firstp1, lastp1, firstp2, lastp2);
503       }
504   // jfa 10/10/2000 end
505   else
506     return;
507
508  // Calculate presentation of projected edges
509  if ( (myExtShape != 0) &&  !extCurv.IsNull()) {
510    if (myExtShape == 1 )
511      ComputeProjEdgePresentation(aPrs, TopoDS::Edge(myFShape), curv1, firstp1, lastp1);
512    else
513      ComputeProjEdgePresentation(aPrs, TopoDS::Edge(mySShape), curv2, firstp2, lastp2);
514  }
515 }
516
517 //=======================================================================
518 //function : ComputeTwoLinesPresentation
519 //purpose  : Compute the presentation of the 'identic' constraint
520 //           between two lines ( which are equal)
521 //input    : <thelin> : the 
522 //           <firstp1>: first extremity of the 1st curve of the constraint
523 //           <lastp1> : last extremity of the 1st curve of the constraint
524 //           <firstp2>: first extremity of the 2nd curve of the constraint
525 //           <lastp2> :last extremity of the 2nd curve of the constraint
526 //=======================================================================
527 void PrsDim_IdenticRelation::ComputeTwoLinesPresentation(const Handle(Prs3d_Presentation)& aPrs, 
528                                                       const Handle(Geom_Line)& thelin,
529                                                       gp_Pnt& firstp1,
530                                                       gp_Pnt& lastp1,
531                                                       gp_Pnt& firstp2,
532                                                       gp_Pnt& lastp2,
533                                                       const Standard_Boolean isInfinite1,
534                                                       const Standard_Boolean isInfinite2)
535 {
536   if (isInfinite1 && isInfinite2) {
537     if ( myAutomaticPosition ) {
538       myFAttach = mySAttach = thelin->Lin().Location();
539       gp_Pnt curpos;
540       gp_Pln pln(myPlane->Pln());
541       gp_Dir dir(pln.XAxis().Direction());
542       gp_Vec transvec = gp_Vec(dir)*myArrowSize;
543       curpos = myFAttach.Translated(transvec);
544       myPosition = curpos;
545       myAutomaticPosition = Standard_True;
546     }
547     else {
548       myFAttach = mySAttach = ElCLib::Value(ElCLib::Parameter(thelin->Lin(),myPosition),thelin->Lin());            
549     }
550     TCollection_ExtendedString vals(" ==");
551     DsgPrs_IdenticPresentation::Add(aPrs,
552                                     myDrawer,
553                                     vals,
554                                     myFAttach,
555                                     myPosition);    
556   }
557   else {
558     // Computation of the parameters of the 4 points on the line <thelin>
559     Standard_Real pf1, pf2, pl1, pl2;    
560
561     pf1 = ElCLib::Parameter(thelin->Lin(), firstp1);
562     pl1 = ElCLib::Parameter(thelin->Lin(), lastp1);
563
564     pf2 = ElCLib::Parameter(thelin->Lin(), firstp2);
565     pl2 = ElCLib::Parameter(thelin->Lin(), lastp2);
566
567     if (isInfinite1) {
568       pf1 = pf2;
569       pl1 = pl2;
570       firstp1 = firstp2;
571       lastp1 = lastp2;
572     }
573     else if (isInfinite2) {
574       pf2 = pf1;
575       pl2 = pl1;
576       firstp2 = firstp1;
577       lastp2 = lastp1;
578     }
579
580     Standard_Real tabRang1[4];      // array taht contains the parameters of the 4 points
581     // ordered by increasing abscisses.
582
583     gp_Pnt tabRang2[4];             // array containing the points corresponding to the
584     // parameters in tabRang1
585
586     Standard_Integer tabRang3[4];   // array containing the number of the curve( 1 or 2)
587     // of which belongs each point of tabRang2
588
589     // Filling of the arrays
590     tabRang1[0] = pf1; tabRang2[0] = firstp1; tabRang3[0] = 1;
591     tabRang1[1] = pf2; tabRang2[1] = firstp2; tabRang3[1] = 2;
592     tabRang1[2] = pl1; tabRang2[2] = lastp1;  tabRang3[2] = 1;
593     tabRang1[3] = pl2; tabRang2[3] = lastp2;  tabRang3[3] = 2;
594
595   // Sort of the array of parameters (tabRang1)
596     PrsDim_Sort(tabRang1, tabRang2, tabRang3);
597
598     // Computation of myFAttach and mySAttach according to the
599     // position of the 2 linear edges
600     gp_Pnt curpos;
601     gp_Pnt middle;
602   
603     if ( (tabRang1[0] == tabRang1[1]) && (tabRang1[2] == tabRang1[3]) ) {
604       middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
605       Standard_Real pmiddle = (tabRang1[1] + tabRang1[2]) / 2.;
606       Standard_Real delta = (tabRang1[3] - tabRang1[0])/ 5.;
607       myFAttach = ElCLib::Value(pmiddle-delta, thelin->Lin());
608       mySAttach = ElCLib::Value(pmiddle+delta, thelin->Lin());
609     }
610   
611     else if ( tabRang1[1] == tabRang1[2] ) {
612       middle = tabRang2[1];
613       Standard_Real delta1 = tabRang1[1] - tabRang1[0];
614       Standard_Real delta2 = tabRang1[3] - tabRang1[2];
615       if ( delta1 > delta2 ) delta1 = delta2;
616       myFAttach = ElCLib::Value(tabRang1[1]-delta1/2., thelin->Lin());
617       mySAttach = ElCLib::Value(tabRang1[1]+delta1/2., thelin->Lin());
618     }
619   
620     // Case of 2 disconnected segments -> the symbol completes the gap 
621     //                                    between the 2 edges
622     //--------------------------------
623     else if ( (tabRang3[0] == tabRang3[1]) && (tabRang1[1] != tabRang1[2])) {
624       middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
625       myFAttach = tabRang2[1];
626       mySAttach = tabRang2[2];
627     }
628     else if ( (tabRang3[0] != tabRang3[1]) 
629               && (tabRang3[1] != tabRang3[2])    // Intersection
630               && (tabRang1[1] != tabRang1[2]) ) { 
631       middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
632       myFAttach = tabRang2[1];
633       mySAttach = tabRang2[2];
634     }
635     else {                                     // Inclusion
636       myFAttach.SetXYZ((tabRang2[0].XYZ() + tabRang2[1].XYZ())/2. );
637       mySAttach.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
638       middle.SetXYZ( (myFAttach.XYZ() + mySAttach.XYZ() )/2.);
639     }
640   
641
642     if ( myAutomaticPosition ) {
643     
644       gp_Vec vtrans(myFAttach, mySAttach);
645       vtrans.Normalize();
646       vtrans.Cross(gp_Vec(myPlane->Pln().Axis().Direction()));
647       vtrans *= ComputeSegSize();
648       curpos = middle.Translated(vtrans);
649       myPosition = curpos;
650       myAutomaticPosition = Standard_True;
651     }
652
653     else {
654
655       curpos = myPosition;
656       Standard_Real pcurpos = ElCLib::Parameter(thelin->Lin() ,curpos);
657       Standard_Real dist = thelin->Lin().Distance(curpos);
658       gp_Pnt proj = ElCLib::Value( pcurpos, thelin->Lin());
659       gp_Vec  trans;
660       Standard_Real confusion(Precision::Confusion());
661       if ( dist >= confusion ) {
662         trans = gp_Vec(proj, curpos);
663         trans.Normalize();
664       }
665       Standard_Real pf = ElCLib::Parameter(thelin->Lin() ,myFAttach);
666       Standard_Real pl = ElCLib::Parameter(thelin->Lin() ,mySAttach);
667       if ( pcurpos <= pf ) {
668         pcurpos = pf + 1e-5;
669         curpos = ElCLib::Value( pcurpos, thelin->Lin());
670         if ( dist >= confusion ) curpos.Translate(trans*dist);
671       }
672       else if ( pcurpos >= pl ) {
673         pcurpos = pl - 1e-5;
674         curpos = ElCLib::Value( pcurpos, thelin->Lin());
675         if ( dist >= confusion ) curpos.Translate(trans*dist);
676       }
677       SetPosition(curpos);
678     }
679
680     // Display of the presentation
681     TCollection_ExtendedString vals(" ==");
682     DsgPrs_IdenticPresentation::Add(aPrs,
683                                     myDrawer,
684                                     vals,
685                                     myFAttach,
686                                     mySAttach,
687                                     curpos);
688   }
689 }
690
691 // jfa 17/10/2000
692 //=======================================================================
693 //function : ComputeTwoCirclesPresentation
694 //purpose  : Compute the presentation of the 'identic' constraint
695 //           between two circles ( which are equal)
696 //input    : <thecirc>: the circle
697 //           <firstp1>: first extremity of the 1st curve of the constraint
698 //           <lastp1> : last extremity of the 1st curve of the constraint
699 //           <firstp2>: first extremity of the 2nd curve of the constraint
700 //           <lastp2> :last extremity of the 2nd curve of the constraint
701 //=======================================================================
702 void PrsDim_IdenticRelation::ComputeTwoCirclesPresentation(const Handle(Prs3d_Presentation)& aPrs,
703                                                         const Handle(Geom_Circle)& thecirc,
704                                                         const gp_Pnt& firstp1,
705                                                         const gp_Pnt& lastp1,
706                                                         const gp_Pnt& firstp2,
707                                                         const gp_Pnt& lastp2)
708 {
709   Standard_Real confusion (Precision::Confusion());
710
711   // Searching of complete circles
712   Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
713   Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
714     
715   myCenter = thecirc->Location();
716   Standard_Real aSegSize = thecirc->Radius()/5.0;
717   Standard_Real rad = M_PI / 5.0;
718     
719   // I. Case of 2 complete circles
720   if ( circ1complete && circ2complete )
721     {
722       if (myAutomaticPosition)
723         {
724           Standard_Real pfirst1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
725           myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), thecirc->Circ());
726           mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), thecirc->Circ());
727
728           gp_Pnt curpos = ElCLib::Value(pfirst1,thecirc->Circ());
729           gp_Vec vtrans(myCenter, curpos);
730           vtrans.Normalize();
731           vtrans *= aSegSize;
732           curpos.Translate(vtrans);
733           myPosition = curpos;
734         }
735       else ComputeNotAutoCircPresentation(thecirc);
736     }
737
738   // II. Case of one complete circle and one arc
739   else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
740     {
741       gp_Pnt firstp, lastp;
742       if ( circ1complete && !circ2complete)
743         {
744           firstp = firstp2;
745           lastp  = lastp2;
746         }
747       else
748         {
749           firstp = firstp1;
750           lastp  = lastp1;
751         }
752
753       if (myAutomaticPosition)
754         {
755           ComputeAutoArcPresentation(thecirc, firstp, lastp);
756         }
757       else
758         {
759           ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
760         }
761     }
762
763   // III and IV. Case of two arcs
764   else if ( !circ1complete && !circ2complete )
765     {
766       // We project all the points on the circle
767       Standard_Real pf1, pf2, pl1, pl2;
768       pf1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
769       pf2 = ElCLib::Parameter(thecirc->Circ(), firstp2);
770       pl1 = ElCLib::Parameter(thecirc->Circ(), lastp1);
771       pl2 = ElCLib::Parameter(thecirc->Circ(), lastp2);
772
773       // III. Arcs with common ends
774       // III.1. First of one and last of another
775       if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
776         {
777           gp_Pnt curpos(0.,0.,0.);
778           Standard_Real att=0.;
779           if ( IsEqual2PI(pl1,pf2,confusion) )
780             {
781               att = pl1;
782               curpos = lastp1;
783             }
784           else if ( IsEqual2PI(pf1,pl2,confusion) )
785             {
786               att = pf1;
787               curpos = firstp1;
788             }
789           Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
790           if ( rad > maxrad ) rad = maxrad;
791           Standard_Real pFAttach = Modulo2PI(att - rad);
792           Standard_Real pSAttach = Modulo2PI(att + rad);
793           myFAttach = ElCLib::Value(pFAttach, thecirc->Circ());
794           mySAttach = ElCLib::Value(pSAttach, thecirc->Circ());
795           if ( myAutomaticPosition )
796             {
797               gp_Vec vtrans(myCenter,curpos);
798               vtrans.Normalize();
799               vtrans *= aSegSize;
800               curpos.Translate(vtrans);
801               myPosition = curpos;
802             }
803         }
804       // III.2. Two first or two last
805       else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
806         {
807           Standard_Real l1 = Modulo2PI(pl1 - pf1);
808           Standard_Real l2 = Modulo2PI(pl2 - pf2);
809           gp_Pnt firstp,lastp;
810           if ( l1 < l2 )
811             {
812               firstp = firstp1;
813               lastp = lastp1;
814             }
815           else
816             {
817               firstp = firstp2;
818               lastp = lastp2;
819             }
820
821           if ( myAutomaticPosition )
822             {
823               ComputeAutoArcPresentation(thecirc, firstp, lastp);
824             }
825           else
826             {
827               ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
828             }
829         }
830       // IV. All others arcs (without common ends)
831       else
832         {
833           // order the parameters; first will be pf1
834           Standard_Real pl1m = Modulo2PI(pl1 - pf1);
835           Standard_Real pf2m = Modulo2PI(pf2 - pf1);
836           Standard_Real pl2m = Modulo2PI(pl2 - pf1);
837
838           Standard_Boolean case1 = Standard_False;
839           // 1 - not intersecting arcs
840           // 2 - intersecting arcs, but one doesn't contain another
841           // 3a - first arc contains the second one
842           // 3b - second arc contains the first one
843           // 4 - two intersections
844
845           gp_Pnt firstp, lastp;
846
847           if ( pl1m < pf2m ) // 1 or 2b or 3b
848             {
849               if ( pl1m < pl2m ) // 1 or 3b
850                 {
851                   if ( pl2m < pf2m ) // 3b
852                     {
853                       firstp = firstp1;
854                       lastp  = lastp1;
855                     }
856                   else // 1
857                     {
858                       case1 = Standard_True;
859                       Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
860                       Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
861                       if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
862                            ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
863                         {
864                           firstp = lastp1;
865                           lastp  = firstp2;
866                         }
867                       else // deltap1
868                         {
869                           firstp = lastp2;
870                           lastp  = firstp1;
871                         }
872                     }
873                 }
874               else // 2b
875                 {
876                   firstp = firstp1;
877                   lastp  = lastp2;
878                 }
879             }
880           else // 2a or 3a or 4
881             {
882               if ( pl1m < pl2m ) // 2a
883                 {
884                   firstp = firstp2;
885                   lastp  = lastp1;
886                 }
887               else // 3a or 4
888                 {
889                   if ( pl2m > pf2m ) // 3a
890                     {
891                       firstp = firstp2;
892                       lastp  = lastp2;
893                     }
894                   else // 4
895                     {
896                       Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
897                       Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
898                       if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
899                            ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
900                         {
901                           firstp = firstp1;
902                           lastp  = lastp2;
903                         }
904                       else // deltap1
905                         {
906                           firstp = firstp2;
907                           lastp  = lastp1;
908                         }
909                     }
910                 }
911             }
912
913           if ( myAutomaticPosition )
914             {
915               ComputeAutoArcPresentation(thecirc,firstp,lastp,case1);
916             }
917           else
918             {
919               if ( case1 )
920                 {
921                   myFAttach = firstp;
922                   mySAttach = lastp;
923                 }
924               else ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
925             }
926         }
927     }
928
929   // Display of the presentation
930   TCollection_ExtendedString vals(" ==");
931   gp_Pnt attach = myPosition;
932   ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
933   DsgPrs_IdenticPresentation::Add(aPrs,
934                                   myDrawer,
935                                   vals,
936                                   myPlane->Pln().Position().Ax2(),
937                                   myCenter,
938                                   myFAttach,
939                                   mySAttach,
940                                   myPosition,
941                                   attach);
942 }
943
944 //=======================================================================
945 //function : ComputeAutoArcPresentation
946 //purpose  : Compute the presentation of the constraint where we are
947 //           not in the case of dragging.
948 //=======================================================================
949 void PrsDim_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
950                                                      const gp_Pnt& firstp,
951                                                      const gp_Pnt& lastp,
952                                                      const Standard_Boolean isstatic)
953 {
954   Standard_Real aSegSize = thecirc->Radius()/5.0;
955   Standard_Real rad = M_PI / 5.0;
956
957   Standard_Real pFA = ElCLib::Parameter(thecirc->Circ(),firstp);
958   Standard_Real pSA = ElCLib::Parameter(thecirc->Circ(),lastp);
959   Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
960   
961   if ( (rad > maxrad) || isstatic ) rad = maxrad;
962   Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
963   
964   myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),thecirc->Circ());
965   mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),thecirc->Circ());
966   
967   gp_Pnt curpos = ElCLib::Value(pmiddle,thecirc->Circ());
968   gp_Vec vtrans(myCenter, curpos);
969   vtrans.Normalize();
970   vtrans *= aSegSize;
971   myPosition = curpos.Translated(vtrans);
972 }
973
974 //=======================================================================
975 //function : ComputeNotAutoCircPresentation
976 //purpose  : Compute the presentation of the constraint where we are
977 //           in the case of dragging.
978 // Note    : This function is to be used only in the case of full circles.
979 //           The symbol of the constraint moves together with arc
980 //           representing the constraint around all the circle.
981 //=======================================================================
982 void PrsDim_IdenticRelation::ComputeNotAutoCircPresentation(const Handle(Geom_Circle)& thecirc)
983 {
984   gp_Pnt curpos = myPosition;
985
986   Handle(Geom_Circle) cirNotAuto = new Geom_Circle(thecirc->Circ());
987   
988   // Case of confusion between the current position and the center 
989   // of the circle -> we move the current position
990   Standard_Real confusion (Precision::Confusion());
991   if ( myCenter.Distance(curpos) <= confusion )
992     {
993       gp_Vec vprec(myCenter, myFAttach);
994       vprec.Normalize();
995       curpos.Translate(vprec*1e-5);
996     }
997   
998   Standard_Real rad = M_PI / 5.0;
999   Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto->Circ(),curpos);
1000   Standard_Real pFAttach = pcurpos - rad;
1001   Standard_Real pSAttach = pcurpos + rad;
1002   myFAttach = ElCLib::Value(pFAttach,cirNotAuto->Circ());
1003   mySAttach = ElCLib::Value(pSAttach,cirNotAuto->Circ());
1004 }
1005
1006 //=======================================================================
1007 //function : ComputeNotAutoArcPresentation
1008 //purpose  : Compute the presentation of the constraint where we are
1009 //           in the case of dragging.
1010 // Note    : This function is to be used only in the case of circles.
1011 //           The symbol of the constraint moves only between myFAttach
1012 //           and mySAttach.
1013 //=======================================================================
1014 void PrsDim_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
1015                                                         const gp_Pnt& pntfirst,
1016                                                         const gp_Pnt& pntlast)
1017 {
1018   gp_Pnt curpos = myPosition;
1019
1020   gp_Circ cirNotAuto = thecirc->Circ();
1021
1022   Standard_Real pFPnt = ElCLib::Parameter(cirNotAuto, pntfirst);
1023   Standard_Real pSPnt = ElCLib::Parameter(cirNotAuto, pntlast);
1024   Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;
1025
1026   Standard_Real rad = M_PI / 5;
1027   if ( deltap < rad )
1028     {
1029       myFAttach = pntfirst;
1030       mySAttach = pntlast;
1031     }
1032   else
1033     {
1034       gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), cirNotAuto);
1035       gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), cirNotAuto);
1036
1037       ComputeAttach(cirNotAuto,aFPnt,aSPnt,curpos);
1038
1039       Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto,curpos);
1040       myFAttach = ElCLib::Value(pcurpos - rad, cirNotAuto);
1041       mySAttach = ElCLib::Value(pcurpos + rad, cirNotAuto);
1042     }
1043 }
1044 // jfa 17/10/2000 end
1045
1046 // jfa 18/10/2000
1047 //=======================================================================
1048 //function : ComputeTwoEllipsesPresentation
1049 //purpose  : Compute the presentation of the 'identic' constraint
1050 //           between two ellipses (which are equal)
1051 //input    : <theEll>: the ellipse
1052 //           <firstp1>: first extremity of the 1st curve of the constraint
1053 //           <lastp1> : last extremity of the 1st curve of the constraint
1054 //           <firstp2>: first extremity of the 2nd curve of the constraint
1055 //           <lastp2> :last extremity of the 2nd curve of the constraint
1056 //=======================================================================
1057 void PrsDim_IdenticRelation::ComputeTwoEllipsesPresentation(const Handle(Prs3d_Presentation)& aPrs,
1058                                                          const Handle(Geom_Ellipse)& theEll,
1059                                                          const gp_Pnt& firstp1,
1060                                                          const gp_Pnt& lastp1,
1061                                                          const gp_Pnt& firstp2,
1062                                                          const gp_Pnt& lastp2)
1063 {
1064   Standard_Real confusion (Precision::Confusion());
1065
1066   // Searching of complete ellipses
1067   Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
1068   Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
1069     
1070   myCenter = theEll->Location();
1071   Standard_Real aSegSize = theEll->MajorRadius()/5.0;
1072   Standard_Real rad = M_PI / 5.0;
1073     
1074   // I. Case of 2 complete ellipses
1075   if ( circ1complete && circ2complete )
1076     {
1077       if (myAutomaticPosition)
1078         {
1079           Standard_Real pfirst1 = ElCLib::Parameter(theEll->Elips(), firstp1);
1080           myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), theEll->Elips());
1081           mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), theEll->Elips());
1082
1083           gp_Pnt curpos = ElCLib::Value(pfirst1,theEll->Elips());
1084           gp_Vec vtrans(myCenter, curpos);
1085           vtrans.Normalize();
1086           vtrans *= aSegSize;
1087           curpos.Translate(vtrans);
1088           myPosition = curpos;
1089         }
1090       else ComputeNotAutoElipsPresentation(theEll);
1091     }
1092
1093   // II. Case of one complete circle and one arc
1094   else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
1095     {
1096       gp_Pnt firstp, lastp;
1097       if ( circ1complete && !circ2complete)
1098         {
1099           firstp = firstp2;
1100           lastp  = lastp2;
1101         }
1102       else
1103         {
1104           firstp = firstp1;
1105           lastp  = lastp1;
1106         }
1107
1108       if (myAutomaticPosition)
1109         {
1110           ComputeAutoArcPresentation(theEll, firstp, lastp);
1111         }
1112       else
1113         {
1114           ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1115         }
1116     }
1117
1118   // III and IV. Case of two arcs
1119   else if ( !circ1complete && !circ2complete )
1120     {
1121       // We project all the points on the circle
1122       Standard_Real pf1, pf2, pl1, pl2;
1123       pf1 = ElCLib::Parameter(theEll->Elips(), firstp1);
1124       pf2 = ElCLib::Parameter(theEll->Elips(), firstp2);
1125       pl1 = ElCLib::Parameter(theEll->Elips(), lastp1);
1126       pl2 = ElCLib::Parameter(theEll->Elips(), lastp2);
1127
1128       // III. Arcs with common ends
1129       // III.1. First of one and last of another
1130       if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
1131         {
1132           gp_Pnt curpos;
1133           Standard_Real att=0.;
1134           if ( IsEqual2PI(pl1,pf2,confusion) )
1135             {
1136               att = pl1;
1137               curpos = lastp1;
1138             }
1139           else if ( IsEqual2PI(pf1,pl2,confusion) )
1140             {
1141               att = pf1;
1142               curpos = firstp1;
1143             }
1144           Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
1145           if ( rad > maxrad ) rad = maxrad;
1146           Standard_Real pFAttach = Modulo2PI(att - rad);
1147           Standard_Real pSAttach = Modulo2PI(att + rad);
1148           myFAttach = ElCLib::Value(pFAttach, theEll->Elips());
1149           mySAttach = ElCLib::Value(pSAttach, theEll->Elips());
1150           if ( myAutomaticPosition )
1151             {
1152               gp_Vec vtrans(myCenter,curpos);
1153               vtrans.Normalize();
1154               vtrans *= aSegSize;
1155               curpos.Translate(vtrans);
1156               myPosition = curpos;
1157             }
1158         }
1159       // III.2. Two first or two last
1160       else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
1161         {
1162           Standard_Real l1 = Modulo2PI(pl1 - pf1);
1163           Standard_Real l2 = Modulo2PI(pl2 - pf2);
1164           gp_Pnt firstp,lastp;
1165           if ( l1 < l2 )
1166             {
1167               firstp = firstp1;
1168               lastp = lastp1;
1169             }
1170           else
1171             {
1172               firstp = firstp2;
1173               lastp = lastp2;
1174             }
1175
1176           if ( myAutomaticPosition )
1177             {
1178               ComputeAutoArcPresentation(theEll, firstp, lastp);
1179             }
1180           else
1181             {
1182               ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1183             }
1184         }
1185       // IV. All others arcs (without common ends)
1186       else
1187         {
1188           // order the parameters; first will be pf1
1189           Standard_Real pl1m = Modulo2PI(pl1 - pf1);
1190           Standard_Real pf2m = Modulo2PI(pf2 - pf1);
1191           Standard_Real pl2m = Modulo2PI(pl2 - pf1);
1192
1193           Standard_Boolean case1 = Standard_False;
1194           // 1 - not intersecting arcs
1195           // 2 - intersecting arcs, but one doesn't contain another
1196           // 3a - first arc contains the second one
1197           // 3b - second arc contains the first one
1198           // 4 - two intersections
1199
1200           gp_Pnt firstp, lastp;
1201
1202           if ( pl1m < pf2m ) // 1 or 2b or 3b
1203             {
1204               if ( pl1m < pl2m ) // 1 or 3b
1205                 {
1206                   if ( pl2m < pf2m ) // 3b
1207                     {
1208                       firstp = firstp1;
1209                       lastp  = lastp1;
1210                     }
1211                   else // 1
1212                     {
1213                       case1 = Standard_True;
1214                       Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
1215                       Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
1216                       if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
1217                            ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
1218                         {
1219                           firstp = lastp1;
1220                           lastp  = firstp2;
1221                         }
1222                       else // deltap1
1223                         {
1224                           firstp = lastp2;
1225                           lastp  = firstp1;
1226                         }
1227                     }
1228                 }
1229               else // 2b
1230                 {
1231                   firstp = firstp1;
1232                   lastp  = lastp2;
1233                 }
1234             }
1235           else // 2a or 3a or 4
1236             {
1237               if ( pl1m < pl2m ) // 2a
1238                 {
1239                   firstp = firstp2;
1240                   lastp  = lastp1;
1241                 }
1242               else // 3a or 4
1243                 {
1244                   if ( pl2m > pf2m ) // 3a
1245                     {
1246                       firstp = firstp2;
1247                       lastp  = lastp2;
1248                     }
1249                   else // 4
1250                     {
1251                       Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
1252                       Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
1253                       if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
1254                            ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
1255                         {
1256                           firstp = firstp1;
1257                           lastp  = lastp2;
1258                         }
1259                       else // deltap1
1260                         {
1261                           firstp = firstp2;
1262                           lastp  = lastp1;
1263                         }
1264                     }
1265                 }
1266             }
1267
1268           if ( myAutomaticPosition )
1269             {
1270               ComputeAutoArcPresentation(theEll,firstp,lastp,case1);
1271             }
1272           else
1273             {
1274               if ( case1 )
1275                 {
1276                   myFAttach = firstp;
1277                   mySAttach = lastp;
1278                 }
1279               else ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1280             }
1281         }
1282     }
1283
1284   // Display of the presentation
1285   TCollection_ExtendedString vals(" ==");
1286   gp_Pnt attach = myPosition;
1287   ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
1288   DsgPrs_IdenticPresentation::Add(aPrs,
1289                                   myDrawer,
1290                                   vals,
1291                                   theEll->Elips(),
1292                                   myFAttach,
1293                                   mySAttach,
1294                                   myPosition,
1295                                   attach);
1296 }
1297
1298 //=======================================================================
1299 //function : ComputeAutoArcPresentation
1300 //purpose  : Compute the presentation of the constraint where we are
1301 //           not in the case of dragging.
1302 //=======================================================================
1303 void PrsDim_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1304                                                      const gp_Pnt& firstp,
1305                                                      const gp_Pnt& lastp,
1306                                                      const Standard_Boolean isstatic)
1307 {
1308   Standard_Real aSegSize = theEll->MajorRadius()/5.0;
1309   Standard_Real rad = M_PI / 5.0;
1310
1311   gp_Elips anEll = theEll->Elips();
1312   
1313   Standard_Real pFA = ElCLib::Parameter(anEll,firstp);
1314   Standard_Real pSA = ElCLib::Parameter(anEll,lastp);
1315   Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
1316   
1317   if ( (rad > maxrad) || isstatic ) rad = maxrad;
1318   Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
1319   
1320   myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),anEll);
1321   mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),anEll);
1322   
1323   gp_Pnt curpos = ElCLib::Value(pmiddle,anEll);
1324   gp_Vec vtrans(myCenter, curpos);
1325   vtrans.Normalize();
1326   vtrans *= aSegSize;
1327   myPosition = curpos.Translated(vtrans);
1328 }
1329
1330 //=======================================================================
1331 //function : ComputeNotAutoElipsPresentation
1332 //purpose  : Compute the presentation of the constraint where we are
1333 //           in the case of dragging.
1334 // Note    : This function is to be used only in the case of ellipses.
1335 //           The symbol of the constraint moves only between myFAttach
1336 //           and mySAttach.
1337 //=======================================================================
1338 void PrsDim_IdenticRelation::ComputeNotAutoElipsPresentation(const Handle(Geom_Ellipse)& theEll)
1339 {
1340   gp_Pnt curpos = myPosition;
1341
1342   gp_Elips anEll = theEll->Elips();
1343   
1344   // Case of confusion between the current position and the center 
1345   // of the ellipse -> we move the current position
1346   Standard_Real confusion (Precision::Confusion());
1347   if ( myCenter.Distance(curpos) <= confusion )
1348     {
1349       gp_Vec vprec(myCenter, myFAttach);
1350       vprec.Normalize();
1351       curpos.Translate(vprec*1e-5);
1352     }
1353   
1354   Standard_Real rad = M_PI / 5.0;
1355 //  Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1356   GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1357   Standard_Real pcurpos  = aProj.LowerDistanceParameter();
1358
1359   Standard_Real pFAttach = pcurpos - rad;
1360   Standard_Real pSAttach = pcurpos + rad;
1361   myFAttach = ElCLib::Value(pFAttach,anEll);
1362   mySAttach = ElCLib::Value(pSAttach,anEll);
1363 }
1364
1365 //=======================================================================
1366 //function : ComputeNotAutoArcPresentation
1367 //purpose  : Compute the presentation of the constraint where we are
1368 //           in the case of dragging.
1369 // Note    : This function is to be used only in the case of ellipses.
1370 //           The symbol of the constraint moves only between myFAttach
1371 //           and mySAttach.
1372 //=======================================================================
1373 void PrsDim_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1374                                                         const gp_Pnt& pntfirst,
1375                                                         const gp_Pnt& pntlast)
1376 {
1377   gp_Pnt curpos = myPosition;
1378
1379   gp_Elips anEll = theEll->Elips();
1380
1381   Standard_Real pFPnt = ElCLib::Parameter(anEll, pntfirst);
1382   Standard_Real pSPnt = ElCLib::Parameter(anEll, pntlast);
1383   Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;
1384
1385   Standard_Real rad = M_PI / 5;
1386   if ( deltap < rad )
1387     {
1388       myFAttach = pntfirst;
1389       mySAttach = pntlast;
1390     }
1391   else
1392     {
1393       gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), anEll);
1394       gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), anEll);
1395
1396       ComputeAttach(anEll,aFPnt,aSPnt,curpos);
1397
1398 //      Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1399       GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1400       Standard_Real pcurpos  = aProj.LowerDistanceParameter();
1401
1402       myFAttach = ElCLib::Value(pcurpos - rad, anEll);
1403       mySAttach = ElCLib::Value(pcurpos + rad, anEll);
1404     }
1405 }
1406 // jfa 18/10/2000 end
1407
1408 //=======================================================================
1409 //function : ComputeTwoVerticesPresentation
1410 //purpose  : 
1411 //=======================================================================
1412 void PrsDim_IdenticRelation::ComputeTwoVerticesPresentation(const Handle(Prs3d_Presentation)& aPrs)
1413 {
1414   Standard_Boolean isOnPlane1, isOnPlane2;
1415   const TopoDS_Vertex& FVertex = TopoDS::Vertex(myFShape);
1416   const TopoDS_Vertex& SVertex = TopoDS::Vertex(mySShape);
1417   
1418   PrsDim::ComputeGeometry(FVertex, myFAttach, myPlane, isOnPlane1);
1419   PrsDim::ComputeGeometry(SVertex, mySAttach, myPlane, isOnPlane2);
1420   
1421   if (isOnPlane1 && isOnPlane2)
1422     myExtShape = 0;
1423   else if ( isOnPlane1 && !isOnPlane2)
1424     myExtShape = 2;
1425   else if (!isOnPlane1 && isOnPlane2)
1426     myExtShape = 1;
1427   else
1428     return ;
1429
1430   
1431   // The attachement points are the points themselves that must be 
1432   //identical
1433   myFAttach = BRep_Tool::Pnt(FVertex);
1434   mySAttach = myFAttach;
1435
1436   gp_Pnt curpos;
1437   if (myAutomaticPosition)
1438     {
1439       //Computation of the size of the symbol
1440       Standard_Real symbsize = ComputeSegSize();
1441       if (symbsize <= Precision::Confusion()) symbsize = 1.;
1442       symbsize*=5;
1443       // Computation of the direction of the segment of the presentation 
1444       // we take the median of the edges connected to vertices
1445       gp_Dir dF, dS;
1446       gp_Dir myDir;
1447       TColStd_ListIteratorOfListOfTransient it(Users());
1448       if (it.More())
1449         {
1450           Handle(AIS_Shape) USER (Handle(AIS_Shape)::DownCast(it.Value()));
1451           if (!USER.IsNull())
1452             {
1453               const TopoDS_Shape& SH =USER->Shape();
1454               if ( (!SH.IsNull()) && (SH.ShapeType() == TopAbs_WIRE) )
1455                 {
1456                   const TopoDS_Wire& WIRE = TopoDS::Wire(USER->Shape());
1457                   Standard_Boolean done = ComputeDirection(WIRE,FVertex,dF);
1458                   if (!done) return;
1459                   done =  ComputeDirection(WIRE,SVertex,dS);
1460                   if (!done) return;
1461                 }
1462               else return;
1463             }
1464           else return;
1465
1466           // computation of the segment direction like average 
1467           // of the 2 computed directions.
1468           if ( dF.IsParallel(dS, Precision::Angular()) )
1469             {
1470               myDir = dF.Crossed(myPlane->Pln().Axis().Direction());
1471             }
1472           else
1473             {
1474               myDir.SetXYZ(dF.XYZ() + dS.XYZ());
1475             }
1476           curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1477         }
1478 // jfa 11/10/2000
1479       else
1480         {
1481           curpos = myFAttach;
1482         }
1483 // jfa 11/10/2000 end
1484
1485       myPosition = curpos;
1486       myAutomaticPosition = Standard_False;
1487     }
1488   else
1489     {
1490       curpos = myPosition;
1491     }
1492
1493   // Presentation computation
1494   TCollection_ExtendedString vals(" ++");
1495   DsgPrs_IdenticPresentation::Add(aPrs,
1496                                   myDrawer,
1497                                   vals,
1498                                   myFAttach,
1499                                   curpos);
1500   // Calculate the projection of vertex
1501   if ( myExtShape == 1)
1502     ComputeProjVertexPresentation(aPrs,FVertex,myFAttach);
1503   else if ( myExtShape == 2)
1504     ComputeProjVertexPresentation(aPrs,SVertex,mySAttach);
1505 }
1506
1507
1508
1509 //=======================================================================
1510 //function : ComputeSegSize
1511 //purpose  : 
1512 //=======================================================================
1513 Standard_Real PrsDim_IdenticRelation::ComputeSegSize() const 
1514 {
1515   return 1.;
1516 }
1517
1518 //=======================================================================
1519 //function : ComputeDirection
1520 //purpose  : Compute a direction according to the different geometric
1521 //           elements connected to the vertex <VERT>, in way to not have
1522 //           overlap between the symbol and them.
1523 //=======================================================================
1524 Standard_Boolean PrsDim_IdenticRelation::ComputeDirection(const TopoDS_Wire& aWire, 
1525                                                        const TopoDS_Vertex& VERT, 
1526                                                        gp_Dir& dF) const 
1527 {
1528    // we take the median of the edges connected to vertices
1529   TopoDS_Edge edg1,edg2;
1530   ConnectedEdges(aWire,VERT,edg1,edg2);
1531
1532   if ( edg1.IsNull() && edg2.IsNull() ) {
1533     return Standard_False;
1534   }
1535   
1536   Handle(Geom_Curve) curv1,curv2;
1537   gp_Pnt firstp1,lastp1,firstp2,lastp2;
1538
1539   // Case with 2 edges connected to the vertex <VERT>
1540   if ( !edg1.IsNull() && !edg2.IsNull() ) {
1541     if ( !PrsDim::ComputeGeometry(edg1,edg2,
1542                                curv1,curv2,
1543                                firstp1, lastp1,
1544                                firstp2, lastp2,myPlane))
1545       return Standard_False;
1546
1547     gp_Dir d1, d2;
1548     if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1549       d1 = ComputeCircleDirection(Handle(Geom_Circle)::DownCast (curv1), VERT);
1550     }
1551     else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1552       d1 = ComputeLineDirection(Handle(Geom_Line)::DownCast (curv1), firstp1);
1553     }
1554     else 
1555       return Standard_False;
1556     
1557     if ( curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1558       d2 = ComputeCircleDirection( Handle(Geom_Circle)::DownCast (curv2), VERT);
1559     }
1560     else if (curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1561       d2 =ComputeLineDirection( Handle(Geom_Line)::DownCast (curv2), firstp2);
1562     }
1563     else 
1564       return Standard_False;
1565     
1566     if ( !d1.IsParallel(d2, Precision::Angular() ))
1567       dF.SetXYZ( (d1.XYZ() + d2.XYZ())/2 );
1568     else {
1569       dF= d1.Crossed(myPlane->Pln().Axis().Direction());
1570     }
1571   }
1572
1573   // Case where <VERT> is at an extremity of a wire.
1574   else {
1575     TopoDS_Edge VEdge;
1576     if ( !edg1.IsNull() )  
1577       VEdge = edg1;
1578     else if (!edg2.IsNull() )
1579        VEdge = edg2;
1580     else 
1581       return Standard_False;
1582
1583     if ( !PrsDim::ComputeGeometry(VEdge, curv1, firstp1, lastp1) )
1584       return Standard_False; 
1585     if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1586       dF = ComputeCircleDirection( Handle(Geom_Circle)::DownCast (curv1), VERT);
1587     }
1588     else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1589       dF = ComputeLineDirection( Handle(Geom_Line)::DownCast (curv1), firstp1);
1590     }
1591     else
1592       return Standard_False;
1593   }
1594
1595   return Standard_True;
1596 }
1597
1598 //=======================================================================
1599 //function : ComputeLineDirection
1600 //purpose  : 
1601 //=======================================================================
1602 gp_Dir PrsDim_IdenticRelation::ComputeLineDirection(const Handle(Geom_Line)& lin, 
1603                                                  const gp_Pnt& firstP) const 
1604 {
1605   gp_Dir dir;
1606   dir = lin->Lin().Direction();
1607   if ( !myFAttach.IsEqual(firstP, Precision::Confusion()) )
1608     dir.Reverse();
1609   return dir;
1610 }
1611
1612 //=======================================================================
1613 //function : ComputeCircleDirection
1614 //purpose  : 
1615 //=======================================================================
1616 gp_Dir PrsDim_IdenticRelation::ComputeCircleDirection(const Handle(Geom_Circle)& circ, 
1617                                                    const TopoDS_Vertex& VERT) const 
1618 {
1619   gp_Vec V(circ->Location(),BRep_Tool::Pnt(VERT));
1620   return gp_Dir(V);
1621 }
1622
1623 //=======================================================================
1624 //function : ComputeOneEdgeOVertexPresentation
1625 //purpose  : 
1626 //=======================================================================
1627 void PrsDim_IdenticRelation::ComputeOneEdgeOVertexPresentation(const Handle(Prs3d_Presentation)& aPrs)
1628 {
1629   TopoDS_Vertex V;
1630   TopoDS_Edge E;
1631   Standard_Integer numedge;
1632   
1633   if (myFShape.ShapeType() == TopAbs_VERTEX) {
1634     V = TopoDS::Vertex(myFShape);
1635     E = TopoDS::Edge(mySShape);
1636     numedge = 2;// edge = 2nd shape
1637   }
1638   else {
1639     V = TopoDS::Vertex(mySShape);
1640     E   = TopoDS::Edge(myFShape);
1641     numedge = 1;  // edge = 1st shape
1642   }
1643   gp_Pnt ptonedge1,ptonedge2;
1644   Handle(Geom_Curve) aCurve;
1645   Handle(Geom_Curve) extCurv;
1646   Standard_Boolean isInfinite;
1647   Standard_Boolean isOnPlanEdge, isOnPlanVertex;
1648   if (!PrsDim::ComputeGeometry(E,aCurve,ptonedge1,ptonedge2,extCurv,isInfinite,isOnPlanEdge,myPlane))
1649     return;
1650   aPrs->SetInfiniteState(isInfinite);
1651   PrsDim::ComputeGeometry(V, myFAttach, myPlane, isOnPlanVertex);
1652
1653   // only the curve can be projected 
1654   if (!isOnPlanEdge && !isOnPlanVertex) return;
1655
1656   if (!isOnPlanEdge) {
1657     if (numedge == 1) myExtShape = 1;
1658     else myExtShape = 2;
1659   }
1660   else if (!isOnPlanVertex) {
1661     if (numedge == 1) myExtShape = 2;
1662     else myExtShape = 1;
1663   }
1664   // The attachement points are the point 
1665   myFAttach = BRep_Tool::Pnt(V);
1666   mySAttach = myFAttach;
1667
1668   gp_Pnt curpos;
1669   if (myAutomaticPosition) {
1670     //Computation of the size of the symbol
1671     Standard_Real symbsize = ComputeSegSize();
1672     symbsize*=5;
1673     // Computation of the direction of the segment of the presentation 
1674     // we take the median of the edges connected to vertices
1675     gp_Dir myDir;
1676     if ( aCurve->IsKind(STANDARD_TYPE(Geom_Line))) {
1677       myDir = Handle(Geom_Line)::DownCast (aCurve)->Lin().Direction();
1678       myDir.Cross(myPlane->Pln().Axis().Direction());
1679     }
1680     else if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle))) {
1681       Handle(Geom_Circle) CIR = Handle(Geom_Circle)::DownCast (aCurve);
1682       myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1683     }
1684     // jfa 10/10/2000
1685     else if (aCurve->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
1686       Handle(Geom_Ellipse) CIR = Handle(Geom_Ellipse)::DownCast (aCurve);
1687       myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1688     }
1689     // jfa 10/10/2000 end
1690
1691     curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1692     myPosition = curpos;
1693     myAutomaticPosition = Standard_True;
1694   }
1695   else {
1696     curpos = myPosition;
1697   }
1698
1699   // Presentation computation
1700   TCollection_ExtendedString vals(" -+-");
1701   DsgPrs_IdenticPresentation::Add(aPrs,
1702                                   myDrawer,
1703                                   vals,
1704                                   myFAttach,
1705                                   curpos);
1706   if (myExtShape != 0) {
1707     if (!extCurv.IsNull()) { // the edge is not in the WP
1708      ComputeProjEdgePresentation(aPrs,E,Handle(Geom_Line)::DownCast (aCurve),ptonedge1,ptonedge2);
1709     }
1710   }
1711 }