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