Integration of OCCT 6.5.0 from SVN
[occt.git] / src / AIS / AIS_AngleDimension.cxx
1 // File:        AIS_AngleDimension.cdl
2 // Created:     Tue Dec  5 15:09:04 1996
3 // Author:      Arnaud BOUZY/Odile Olivier
4 //              <ODL>
5
6 #define BUC60655        //GG 22/03/00 Enable to compute correctly
7 //                      the arrow size at object creation time.
8
9 #define BUC60915        //GG 05/06/01 Enable to compute the requested arrow size
10 //                      if any in all dimensions.
11
12 #include <Standard_NotImplemented.hxx>
13
14 #include <AIS_AngleDimension.ixx>
15
16 #include <AIS.hxx>
17 #include <AIS_DimensionOwner.hxx>
18 #include <AIS_Drawer.hxx>
19
20 #include <BRepBuilderAPI_MakeFace.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRep_Tool.hxx>
24
25 #include <DsgPrs.hxx>
26 #include <DsgPrs_AnglePresentation.hxx>
27
28 #include <ElCLib.hxx>
29 #include <ElSLib.hxx>
30
31 #include <Geom2d_Circle.hxx>
32 #include <Geom2d_Curve.hxx>
33 #include <Geom2d_Line.hxx>
34 #include <GeomAPI.hxx>
35 #include <Geom_Circle.hxx>
36 #include <Geom_Line.hxx>
37 #include <Geom_Plane.hxx>
38 #include <Geom_TrimmedCurve.hxx>
39 #include <Geom_Surface.hxx>
40 #include <Geom_CylindricalSurface.hxx>
41 #include <Geom_ConicalSurface.hxx>
42 #include <Geom_SurfaceOfRevolution.hxx>
43 #include <Geom_SurfaceOfLinearExtrusion.hxx>
44 #include <Geom_OffsetSurface.hxx>
45
46 #include <IntAna2d_AnaIntersection.hxx>
47 #include <IntAna2d_IntPoint.hxx>
48 #include <IntAna_QuadQuadGeo.hxx>
49 #include <IntAna_ResultType.hxx>
50
51 #include <Precision.hxx>
52
53 #include <ProjLib.hxx>
54
55 #include <Prs3d_AngleAspect.hxx>
56 #include <Prs3d_ArrowAspect.hxx>
57 #include <Prs3d_Drawer.hxx>
58
59 #include <Select3D_SensitiveCurve.hxx>
60 #include <Select3D_SensitiveSegment.hxx>
61 #include <Select3D_SensitiveBox.hxx>
62 #include <SelectMgr_EntityOwner.hxx>
63
64 #include <TColStd_Array1OfReal.hxx>
65
66 #include <TopExp.hxx>
67 #include <TopExp_Explorer.hxx>
68 #include <TopoDS.hxx>
69 #include <TopoDS_Shape.hxx>
70 #include <TopoDS_Vertex.hxx>
71
72 #include <UnitsAPI.hxx>
73
74 #include <gp.hxx>
75 #include <gp_Ax1.hxx>
76 #include <gp_Lin.hxx>
77 #include <gp_Cone.hxx>
78 #include <gp_Pln.hxx>
79 #include <gp_Pnt.hxx>
80 #include <gp_Pnt2d.hxx>
81 #include <gp_Vec.hxx> 
82 #include <gp_XYZ.hxx>
83
84 #include <GC_MakeCircle.hxx>
85 #include <GC_MakeConicalSurface.hxx>
86 #include <gce_MakePln.hxx>
87 #include <gce_MakeCone.hxx>
88 #include <Graphic3d_Array1OfVertex.hxx>  
89
90 //=======================================================================
91 //function : Constructor
92 //purpose  : ConeAngle dimension 
93 //=======================================================================
94
95 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aCone, 
96                                         const Standard_Real aVal,
97                                         const TCollection_ExtendedString& aText,
98                                         const gp_Pnt& aPosition,
99                                         const DsgPrs_ArrowSide /*aSymbolPrs*/,
100                                         const Standard_Real anArrowSize):
101 myNbShape(1)
102 {
103   myCone = aCone;
104   myVal = aVal;
105   myText = aText;
106   myPosition = aPosition; 
107   mySymbolPrs = DsgPrs_AS_BOTHAR;
108   myAutomaticPosition = Standard_True;
109 #ifdef BUC60915
110   SetArrowSize( anArrowSize );
111 #else
112   myArrowSize = anArrowSize;
113 #endif
114 }
115
116 //=======================================================================
117 //function : Constructor
118 //purpose  : ConeAngle dimension 
119 //=======================================================================
120
121 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aCone, 
122                                         const Standard_Real aVal,
123                                         const TCollection_ExtendedString& aText):
124 myNbShape(1)
125 {
126 //#ifdef DEB
127   cout << "Call new AngleDimension for cone's angle" << endl;
128 //#endif
129
130   gp_Pnt tmpPnt(0., 0., 0.); 
131
132   myCone = aCone;
133   myVal = aVal;
134   myText = aText;
135   myPosition = tmpPnt; 
136   mySymbolPrs = DsgPrs_AS_BOTHAR;
137   myAutomaticPosition = Standard_True;
138  
139   myArrowSize = 0.0;
140
141 }
142
143
144 //=======================================================================
145 //function : Constructor
146 //purpose  : TwoEdgesAngle dimension 
147 //=======================================================================
148
149
150 AIS_AngleDimension::AIS_AngleDimension(const TopoDS_Edge& aFirstEdge,
151                                        const TopoDS_Edge& aSecondEdge,
152                                        const Handle (Geom_Plane)& aPlane, 
153                                        const Standard_Real aVal, 
154                                        const TCollection_ExtendedString& aText)
155 :AIS_Relation(),
156  myNbShape(2)
157 {
158 #ifdef DEB
159   cout << endl << "Call new AngleDimension for edges, default" << endl;
160 #endif
161
162   myFShape = aFirstEdge;
163   mySShape = aSecondEdge;
164   myVal = aVal;
165   myPlane = aPlane;
166   myText = aText;
167   mySymbolPrs = DsgPrs_AS_BOTHAR;
168   myAutomaticPosition = Standard_True;
169
170   myArrowSize = myVal / 100.;
171 }
172
173 //=======================================================================
174 //function : Constructor
175 //purpose  : TwoEdgesAngle dimension (avec position et texte)
176 //=======================================================================
177
178 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Edge& aFirstEdge, 
179                                         const TopoDS_Edge& aSecondEdge, 
180                                         const Handle (Geom_Plane)& aPlane,  
181                                         const Standard_Real aVal, 
182                                         const TCollection_ExtendedString& aText, 
183                                         const gp_Pnt& aPosition,
184                                         const DsgPrs_ArrowSide aSymbolPrs,
185                                         const Standard_Real anArrowSize):
186 myNbShape(2)
187 {
188 #ifdef DEB
189   cout << endl << "Call new AngleDimension for edges" << endl;
190 #endif
191
192   myFShape = aFirstEdge;
193   mySShape = aSecondEdge;
194   myVal = aVal;
195   myPlane = aPlane;
196   myText = aText;
197   mySymbolPrs = aSymbolPrs;
198   myAutomaticPosition = Standard_False;
199 #ifdef BUC60915
200   SetArrowSize( anArrowSize );
201 #else
202   myArrowSize = anArrowSize;
203 #endif
204   myPosition = aPosition;
205
206 }
207
208 //=======================================================================
209 //function : Constructor
210 //purpose  : TwoPlanarFacesAngle dimension 
211 //=======================================================================
212
213 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFirstFace, 
214                                         const TopoDS_Face& aSecondFace, 
215                                         const gp_Ax1& anAxis, 
216                                         const Standard_Real aVal,
217                                         const TCollection_ExtendedString& aText):
218 myNbShape(2),
219 myAxis(anAxis)
220 {
221 #ifdef DEB
222   cout << endl << "Call new AngleDimension for planar faces, default" << endl;
223 #endif
224
225   myFShape = aFirstFace;
226   mySShape = aSecondFace;
227
228   AIS::GetPlaneFromFace( aFirstFace, myFirstPlane, myFirstBasisSurf, myFirstSurfType, myFirstOffset );
229   AIS::GetPlaneFromFace( aSecondFace, mySecondPlane, mySecondBasisSurf, mySecondSurfType, mySecondOffset );
230
231 //POP init champ myPlane
232   myPlane = new Geom_Plane(myFirstPlane);
233
234   myVal = aVal;
235   myText = aText;
236   mySymbolPrs = DsgPrs_AS_BOTHAR;
237   myAutomaticPosition = Standard_True;
238
239   myArrowSize = myVal / 100.;
240 }
241
242 //=======================================================================
243 //function : Constructor
244 //purpose  : TwoPlanarFacesAngle dimension  (avec position et texte)
245 //=======================================================================
246
247 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFirstFace, 
248                                         const TopoDS_Face& aSecondFace, 
249                                         const gp_Ax1& anAxis, 
250                                         const Standard_Real aVal, 
251                                         const TCollection_ExtendedString& aText, 
252                                         const gp_Pnt& aPosition, 
253                                         const DsgPrs_ArrowSide aSymbolPrs,
254                                         const Standard_Real anArrowSize):
255 myNbShape(2),
256 myAxis(anAxis)
257 {
258 #ifdef DEB
259   cout << endl << "Call new AngleDimension for planar faces" << endl;
260 #endif
261
262   myFShape = aFirstFace;
263   mySShape = aSecondFace;
264
265   AIS::GetPlaneFromFace( aFirstFace, myFirstPlane, myFirstBasisSurf, myFirstSurfType, myFirstOffset );
266   AIS::GetPlaneFromFace( aSecondFace, mySecondPlane, mySecondBasisSurf, mySecondSurfType, mySecondOffset );
267
268 //POP init champ myPlane
269   myPlane = new Geom_Plane(myFirstPlane);
270
271   myVal = aVal;
272   myText = aText;
273   mySymbolPrs = aSymbolPrs;
274   myAutomaticPosition = Standard_False;
275 #ifdef BUC60915
276   SetArrowSize( anArrowSize );
277 #else
278   myArrowSize = anArrowSize;
279 #endif
280   myPosition = aPosition;
281 }
282
283
284 //=======================================================================
285 //function : AIS_AngleDimension
286 //purpose  : Two curvilinear faces dimension
287 //=======================================================================
288
289 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFFace, 
290                                         const TopoDS_Face& aSFace, 
291                                         const Standard_Real aVal,
292                                         const TCollection_ExtendedString& aText ):
293 myNbShape(2)
294 {
295 #ifdef DEB
296   cout << endl << "Call new AngleDimension for curvilinear faces, default" << endl;
297 #endif
298
299   SetFirstShape( aFFace );
300   SetSecondShape( aSFace );
301   myVal = aVal;
302
303   myText = aText;
304   mySymbolPrs = DsgPrs_AS_BOTHAR;
305   myAutomaticPosition = Standard_True;
306
307   myArrowSize = myVal / 100.;
308 }
309
310 //=======================================================================
311 //function : AIS_AngleDimension
312 //purpose  : 
313 //=======================================================================
314
315 AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFFace, 
316                                         const TopoDS_Face& aSFace, 
317                                         const Standard_Real aVal,
318                                         const TCollection_ExtendedString& aText,
319                                         const gp_Pnt& aPosition, 
320                                         const DsgPrs_ArrowSide aSymbolPrs,
321                                         const Standard_Real anArrowSize):
322 myNbShape(2)
323 {
324 #ifdef DEB
325   cout << endl << "Call new AngleDimension for curvilinear faces" << endl;
326 #endif
327
328   SetFirstShape( aFFace );
329   SetSecondShape( aSFace );
330   myVal = aVal;
331
332   myText = aText;
333   mySymbolPrs = DsgPrs_AS_BOTHAR;
334   myAutomaticPosition = Standard_True;
335
336   mySymbolPrs = aSymbolPrs;
337   myAutomaticPosition = Standard_False;
338 #ifdef BUC60915
339   SetArrowSize( anArrowSize );
340 #else
341   myArrowSize = anArrowSize;
342 #endif
343   myPosition = aPosition;
344 }
345
346
347 //=======================================================================
348 //function : SetConeFace
349 //purpose  : 
350 //=======================================================================
351
352 void AIS_AngleDimension::SetConeFace( const TopoDS_Face& aConeFace )
353 {
354   myCone = aConeFace;
355   myAutomaticPosition = Standard_True;
356 }
357
358
359 //=======================================================================
360 //function : SetFirstShape
361 //purpose  : 
362 //=======================================================================
363
364 void AIS_AngleDimension::SetFirstShape( const TopoDS_Shape& aFShape )
365 {
366   myFShape = aFShape;
367
368   if (myFShape.ShapeType() == TopAbs_FACE)
369     {
370       AIS::GetPlaneFromFace( TopoDS::Face( myFShape ),
371                              myFirstPlane,
372                              myFirstBasisSurf,
373                              myFirstSurfType,
374                              myFirstOffset );
375
376       if (myFirstSurfType == AIS_KOS_Cylinder)
377         myAxis = (Handle( Geom_CylindricalSurface )::DownCast( myFirstBasisSurf ))->Cylinder().Axis();
378       else if (myFirstSurfType == AIS_KOS_Cone)
379         myAxis = (Handle( Geom_ConicalSurface )::DownCast( myFirstBasisSurf ))->Cone().Axis();
380       else if (myFirstSurfType == AIS_KOS_Revolution)
381         myAxis = (Handle( Geom_SurfaceOfRevolution )::DownCast( myFirstBasisSurf ))->Axis();
382       else if (myFirstSurfType == AIS_KOS_Extrusion)
383         {
384           myAxis.SetDirection((Handle( Geom_SurfaceOfLinearExtrusion )::DownCast( myFirstBasisSurf ))
385                               ->Direction() );
386           //myAxis.SetLocation( ??? );
387         }
388     }
389 }
390
391 //=======================================================================
392 //function : SetSecondShape
393 //purpose  : 
394 //=======================================================================
395
396 void AIS_AngleDimension::SetSecondShape( const TopoDS_Shape& aSShape )
397 {
398   mySShape = aSShape;
399
400   if (myFShape.ShapeType() == TopAbs_FACE)
401     AIS::GetPlaneFromFace( TopoDS::Face( mySShape ),
402                            mySecondPlane,
403                            mySecondBasisSurf,
404                            mySecondSurfType,
405                            mySecondOffset );
406 }
407
408
409
410
411 ///=======================================================================
412 //function : Compute
413 //purpose  : 
414 //=======================================================================
415
416 void AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager3d)&, 
417                                  const Handle(Prs3d_Presentation)& aPresentation, 
418                                  const Standard_Integer)
419 {
420   aPresentation->Clear();
421
422   if( myNbShape == 1 ) 
423     {
424      //  cout << "Computing for cone' angle "   << endl;
425      ComputeConeAngle(aPresentation);
426      return;
427     }
428   switch (myFShape.ShapeType()) {
429   case TopAbs_FACE :
430     {
431       // cas angle entre deux faces
432       ComputeTwoFacesAngle(aPresentation);
433     }
434     break;
435   case TopAbs_EDGE :
436     {
437       // cas angle entre deux edges
438       ComputeTwoEdgesAngle(aPresentation);
439     }
440     break;
441   default:
442     break;
443   }
444   
445 }
446
447 //=======================================================================
448 //function : Compute
449 //purpose  : : to avoid warning
450 //=======================================================================
451
452 void AIS_AngleDimension::Compute(const Handle(Prs3d_Projector)& aProjector, 
453                                  const Handle(Prs3d_Presentation)& aPresentation)
454 {
455 // Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
456  PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
457 }
458
459 //=======================================================================
460 //function : Compute
461 //purpose  : : to avoid warning
462 //=======================================================================
463
464 void AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager2d, 
465                                  const Handle(Graphic2d_GraphicObject)& aGraphicObject, 
466                                  const Standard_Integer anInteger)
467 {
468 // Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager2d)&,const Handle(Graphic2d_GraphicObject)&,const Standard_Integer)");
469  PrsMgr_PresentableObject::Compute( aPresentationManager2d ,aGraphicObject,anInteger) ;
470 }
471
472 void AIS_AngleDimension::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
473 {
474 // Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
475  PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
476 }
477
478 //=======================================================================
479 //function : ComputeSelection
480 //purpose  : 
481 //=======================================================================
482
483 void AIS_AngleDimension::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
484                                           const Standard_Integer)
485 {
486
487   if ( myNbShape == 1 ) 
488     {
489     // cout << "Computing selection for cone's angle "   << endl;
490      ComputeConeAngleSelection(aSelection);
491      return;
492     }
493
494
495   if (myFShape.IsNull()) return;
496
497   if (myFShape.ShapeType() == TopAbs_FACE )
498     Compute3DSelection(aSelection);
499   else
500     Compute2DSelection(aSelection);
501
502   // Text
503   Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
504   Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
505   Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
506                                                                    myPosition.X(),
507                                                                    myPosition.Y(),
508                                                                    myPosition.Z(),
509                                                                    myPosition.X() + size,
510                                                                    myPosition.Y() + size,
511                                                                    myPosition.Z() + size);
512   aSelection->Add(box);
513 }
514
515 //=======================================================================
516 //function : ComputeConeAngle
517 //purpose  : 
518 //=======================================================================
519
520 void AIS_AngleDimension::ComputeConeAngle(const Handle(Prs3d_Presentation)& aPresentation)
521 {
522   if( myCone.IsNull() ) return;
523   
524   gp_Pln aPln;
525   gp_Cone aCone;
526   gp_Circ myCircle;
527   gp_Pnt Apex;
528   Handle( Geom_Surface ) aSurf;         //a surface from the Face
529   Handle( Geom_OffsetSurface ) aOffsetSurf; 
530   Handle( Geom_ConicalSurface ) aConicalSurf;
531   Handle( Geom_SurfaceOfRevolution ) aRevSurf; 
532   Handle( Geom_Line ) aLine;
533   BRepAdaptor_Surface tmpSurf(myCone);  
534   TopoDS_Face aFace;
535   AIS_KindOfSurface aSurfType;
536   Standard_Real Offset = 0. ;
537   Handle( Standard_Type ) aType;
538
539   Standard_Real maxV = tmpSurf.FirstVParameter();
540   Standard_Real minV = tmpSurf.LastVParameter();
541
542
543  AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
544
545  if ( aSurfType == AIS_KOS_Revolution ) {                                    //surface of revolution
546
547    aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf ); 
548    gp_Lin ln( aRevSurf->Axis() );
549    Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
550    if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) )  return;        //Must be a part of line
551
552    Standard_Real par;
553    gp_Pnt fst = tmpSurf.Value(0., minV);
554    gp_Pnt lst = tmpSurf.Value(0., maxV);
555  
556    gp_Vec vec1(fst, lst);
557    
558    par = ElCLib::Parameter( ln, fst );
559    gp_Pnt fst2 = ElCLib::Value( par, ln );                         //projection fst on ln
560    par = ElCLib::Parameter( ln, lst );
561    gp_Pnt lst2 = ElCLib::Value( par, ln );                         //projection lst on ln
562
563    gp_Vec vec2(fst2, lst2);
564
565    // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle ) 
566   if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return; 
567  
568   gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
569   aCone =  mkCone.Value();
570   Apex = aCone.Apex();
571  }
572  else {  
573    aType = aSurf->DynamicType();
574    if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) {            //offset surface
575      aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
576      aSurf = aOffsetSurf->Surface();
577      BRepBuilderAPI_MakeFace mkFace(aSurf);
578      mkFace.Build();
579      if( !mkFace.IsDone() ) return;
580      tmpSurf.Initialize( mkFace.Face() );
581    }  
582  
583    aCone = tmpSurf.Cone();
584    aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
585    Apex =  aConicalSurf->Apex();
586  }
587  
588    Handle(Geom_Curve) aCurve;                 //A circle where the angle is drawn
589    if ( myAutomaticPosition ) {
590     Standard_Real midV = ( minV + maxV ) / 2.5; 
591
592     aCurve =   aSurf->VIso(midV);
593     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
594
595     myPosition = ElCLib::Value(Standard_PI/2.0, myCircle);
596     myAutomaticPosition = Standard_False;
597   }
598   else {
599     Standard_Real U, V;
600     ElSLib::Parameters(aCone, myPosition, U, V);
601     aCurve = aSurf->VIso(V); 
602     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
603   }
604   
605  //__________________________________________________________________
606   aCurve = aSurf->VIso(maxV);
607   gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
608   aCurve = aSurf->VIso(minV);
609   gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
610  //__________________________________________________________________
611
612   if( CircVmax.Radius() < CircVmin.Radius() ) {
613    gp_Circ tmpCirc = CircVmax;
614    CircVmax = CircVmin;
615    CircVmin = tmpCirc;
616   }
617
618   DsgPrs_AnglePresentation::Add(aPresentation, myDrawer, myVal, 
619                                 myText, myCircle, myPosition, Apex, CircVmin, CircVmax, myArrowSize);
620 // cout << "ComputeConeAngle is over"   << endl;                                
621 }
622
623
624 //=======================================================================
625 //function : ComputeTwoFacesAngle
626 //purpose  : 
627 //=======================================================================
628
629 void AIS_AngleDimension::ComputeTwoFacesAngle(const Handle(Prs3d_Presentation)& aPresentation)
630 {
631   if (myFirstSurfType == AIS_KOS_Plane)
632     ComputeTwoPlanarFacesAngle( aPresentation );
633   else
634     ComputeTwoCurvilinearFacesAngle( aPresentation );
635 }
636
637 //=======================================================================
638 //function : ComputeTwoCurvilinearFacesAngle
639 //purpose  : 
640 //=======================================================================
641
642 void AIS_AngleDimension::ComputeTwoCurvilinearFacesAngle(const Handle(Prs3d_Presentation)& aPresentation) 
643 {
644   AIS::ComputeAngleBetweenCurvilinearFaces( TopoDS::Face( myFShape ),
645                                             TopoDS::Face( mySShape ),
646                                             myFirstBasisSurf,
647                                             mySecondBasisSurf,
648                                             myFirstSurfType,
649                                             mySecondSurfType,
650                                             myAxis,
651                                             myVal,
652                                             myAutomaticPosition,
653                                             myPosition,
654                                             myCenter,
655                                             myFAttach,
656                                             mySAttach,
657                                             myFDir,
658                                             mySDir,
659                                             myPlane );
660   if (myAutomaticPosition && myIsSetBndBox)
661     myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
662
663   Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
664   Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
665 #ifdef BUC60915
666   if( !myArrowSizeIsDefined ) {
667 #endif
668     Standard_Real arrsize = myCenter.Distance( myPosition );
669       
670     if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
671     if (arrsize == 0.) arrsize = 1.;
672 #ifdef BUC60915
673     myArrowSize = arrsize;
674   }
675   arr->SetLength( myArrowSize );
676 #else
677   arr->SetLength(arrsize);
678 #endif
679       
680
681   if (myVal <= Precision::Angular() || Abs( PI-myVal ) <= Precision::Angular())
682     DsgPrs_AnglePresentation::Add(aPresentation,
683                                   myDrawer,
684                                   myVal,
685                                   myText,
686                                   myCenter,
687                                   myFAttach,
688                                   mySAttach,
689                                   myFDir,
690                                   mySDir,
691                                   myPlane->Pln().Axis().Direction(),
692                                   Standard_False, // not plane
693                                   myAxis,
694                                   myPosition,
695                                   mySymbolPrs);
696   else
697     DsgPrs_AnglePresentation::Add(aPresentation,
698                                   myDrawer,
699                                   myVal,
700                                   myText,
701                                   myCenter,
702                                   myFAttach,
703                                   mySAttach,
704                                   myFDir,
705                                   mySDir,
706                                   myFDir ^ mySDir,
707                                   Standard_False, // not plane
708                                   myAxis,
709                                   myPosition,
710                                   mySymbolPrs);
711 }
712
713 //=======================================================================
714 //function : ComputeTwoPlanarFacesAngle
715 //purpose  : 
716 //=======================================================================
717
718 void AIS_AngleDimension::ComputeTwoPlanarFacesAngle( const Handle( Prs3d_Presentation )& aPresentation )
719 {
720   AIS::ComputeAngleBetweenPlanarFaces( TopoDS::Face( myFShape ),
721                                        TopoDS::Face( mySShape ),
722                                        mySecondBasisSurf,
723                                        myAxis,
724                                        myVal,
725                                        myAutomaticPosition,
726                                        myPosition,
727                                        myCenter,
728                                        myFAttach,
729                                        mySAttach,
730                                        myFDir,
731                                        mySDir );
732   if (myAutomaticPosition && myIsSetBndBox)
733     myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
734
735   Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
736   Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
737 #ifdef BUC60915
738   if( !myArrowSizeIsDefined ) {
739 #endif
740     Standard_Real arrsize = myCenter.Distance( myPosition );
741       
742     if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
743     if (arrsize == 0.) arrsize = 1.;
744 #ifdef BUC60915
745     myArrowSize = arrsize;
746   }
747   arr->SetLength( myArrowSize );
748 #else
749   arr->SetLength(arrsize);
750 #endif
751       
752
753   DsgPrs_AnglePresentation::Add(aPresentation,
754                                 myDrawer,
755                                 myVal,
756                                 myText,
757                                 myCenter,
758                                 myFAttach,
759                                 mySAttach,
760                                 myFDir,
761                                 mySDir,
762                                 myAxis.Direction(),
763                                 Standard_True,
764                                 myAxis,
765                                 myPosition,
766                                 mySymbolPrs);
767      
768 }
769
770 //=======================================================================
771 //function : ComputeTwoEdgesAngle
772 //purpose  : 
773 //=======================================================================
774
775 void AIS_AngleDimension::ComputeTwoEdgesAngle(const Handle(Prs3d_Presentation)& aPresentation)
776 {
777   BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
778   BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
779   if ((cu1.GetType() != GeomAbs_Line) || (cu2.GetType() != GeomAbs_Line)) return;
780
781   // current face
782   BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
783   TopoDS_Face face(makeface.Face());  
784   BRepAdaptor_Surface adp(makeface.Face());
785     
786   // 3d lines
787   Handle(Geom_Line) geom_lin1,geom_lin2;
788   gp_Pnt ptat11,ptat12,ptat21,ptat22;//,pint3d;
789   Standard_Boolean isInfinite1,isInfinite2;
790   Handle(Geom_Curve) extCurv;
791   Standard_Integer copyOfMyExtShape = myExtShape;
792   if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
793                             TopoDS::Edge(mySShape),
794                             myExtShape,
795                             geom_lin1,
796                             geom_lin2,
797                             ptat11,
798                             ptat12,
799                             ptat21,
800                             ptat22,
801                             extCurv,
802                             isInfinite1,
803                             isInfinite2,
804                             myPlane)) {
805     return;
806   }
807   // Temporary: computation of myVal
808   //  myVal = Abs(geom_lin1->Lin().Angle( geom_lin2->Lin())); // Pb avec les angles JPR
809
810   if (copyOfMyExtShape != 0) myExtShape = copyOfMyExtShape;  
811
812   // 2d lines => projection of 3d on current plane
813
814 //POP pour NT
815   Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(geom_lin1,myPlane->Pln());
816   Handle(Geom2d_Line) lin1_2d = *((Handle(Geom2d_Line)*)& geoC1);
817   Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(geom_lin2,myPlane->Pln());
818   Handle(Geom2d_Line) lin2_2d = *((Handle(Geom2d_Line)*)& geoC2);
819
820 #ifdef BUC60915
821   if( !myArrowSizeIsDefined ) {
822 #endif
823     Standard_Real arrSize1(myArrowSize),arrSize2(myArrowSize);
824     if (!isInfinite1) arrSize1 = ptat11.Distance(ptat12)/100.;
825     if (!isInfinite2) arrSize2 = ptat21.Distance(ptat22)/100.;
826 #ifdef BUC60655
827     myArrowSize = Min(myArrowSize,Max(arrSize1,arrSize2));
828 #else
829     myArrowSize = Min(myArrowSize,Min(arrSize1,arrSize2));
830 #endif
831 #ifdef BUC60915
832   }
833 #endif
834
835
836   // Traitement du cas ou les 2 droites sont paralleles
837   if (lin1_2d->Lin2d().Direction()
838       .IsParallel(lin2_2d->Lin2d().Direction(),Precision::Angular())) {    
839     ComputeTwoEdgesNullAngle(aPresentation,
840                              geom_lin1,
841                              geom_lin2,
842                              ptat11,ptat12,
843                              ptat21,ptat22,
844                              isInfinite1,isInfinite2);
845   }
846   
847   // Traitement du cas ou les 2 droites ne sont pas paralleles
848   else {
849     ComputeTwoEdgesNotNullAngle(aPresentation,
850                                 geom_lin1,
851                                 geom_lin2,
852                                 ptat11,
853                                 ptat12,
854                                 ptat21,
855                                 ptat22,
856                                 isInfinite1,isInfinite2);
857   }
858   if ( (myExtShape != 0) &&  !extCurv.IsNull()) {
859     gp_Pnt pf, pl;
860     if ( myExtShape == 1 ) {
861       if (!isInfinite1) {
862         pf = ptat11; 
863         pl = ptat12;
864       }
865       aPresentation->SetInfiniteState(isInfinite1);
866       ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(myFShape),geom_lin1,pf,pl);
867     }
868     else {
869       if (!isInfinite2) {
870         pf = ptat21; 
871         pl = ptat22;
872       }
873       aPresentation->SetInfiniteState(isInfinite2);
874       ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(mySShape),geom_lin2,pf,pl);
875     }
876   }
877 }
878
879
880 //=======================================================================
881 //function : ComputeTwoEdgesNotNullAngle
882 //purpose  : 
883 //=======================================================================
884
885 void AIS_AngleDimension::ComputeTwoEdgesNotNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
886                                                      const Handle(Geom_Line)& l1,
887                                                      const Handle(Geom_Line)& l2,
888                                                      const gp_Pnt& ptat11,
889                                                      const gp_Pnt& ptat12,
890                                                      const gp_Pnt& ptat21,
891                                                      const gp_Pnt& ptat22,
892                                                      const Standard_Boolean isInfinite1,
893                                                      const Standard_Boolean isInfinite2)
894 {
895   // current face
896   BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
897   TopoDS_Face face(makeface.Face());  
898   BRepAdaptor_Surface adp(makeface.Face());
899   // 2d lines => projection of 3d on current plane
900   Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
901   const Handle(Geom2d_Line)& l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
902   Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
903   const Handle(Geom2d_Line)& l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
904
905   //----------------------------------------------------------
906   //          Computation of myCenter
907   //----------------------------------------------------------
908   IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),l2_2d->Lin2d());
909   if (!inter.IsDone()) return;
910   if (!inter.NbPoints()) return;
911   
912   gp_Pnt2d pint(inter.Point(1).Value());
913   myCenter = adp.Value(pint.X(),pint.Y());
914
915   //----------------------------------------------------------
916   //         Computation of the 2 directions
917   //----------------------------------------------------------
918   gp_Dir d1,d2;
919   if (!isInfinite1) {
920     if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
921     else d1 = gp_Dir(gp_Vec(myCenter,ptat12));  
922   }
923   else d1 = l1->Lin().Direction();
924
925   if (!isInfinite2) {
926     if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
927     else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
928   }
929   else d2 = l2->Lin().Direction();
930   if (!isInfinite1) {
931     Standard_Boolean In1(Standard_False);
932     Standard_Boolean In2(Standard_False);
933     if ( !(Abs(d1.Angle(d2) - Abs(myVal)) <= Precision::Confusion())
934          &&  (Abs(myVal) <  PI) ) {
935       Standard_Real parcent1 = ElCLib::Parameter(l1->Lin(), myCenter);
936       Standard_Real par11 = ElCLib::Parameter(l1->Lin(), ptat11);
937       Standard_Real par12 = ElCLib::Parameter(l1->Lin(), ptat12);
938       if ( par11 < par12) {
939         if ( ( parcent1> par11) && (parcent1< par12)) {
940           In1 = Standard_True;
941           d1.Reverse();
942         }
943       }
944       else {
945       if ( ( parcent1> par12) && (parcent1< par11)) {
946         In1 = Standard_True;
947         d1.Reverse();
948       }
949       }
950       if ( !In1) {
951         In2 = Standard_True;
952         d2.Reverse();
953       }
954     }
955   }
956
957   myFDir = d1;
958   mySDir = d2;
959   gp_Lin theaxis;
960   gp_Lin gpl1 = l1->Lin();
961   gp_Lin gpl2 = l2->Lin();
962   theaxis = gp_Lin(myCenter,myFDir^mySDir);
963
964   if (myVal >  PI) {
965     theaxis.Reverse();
966   }
967   
968   gp_Pnt curpos;  
969   TColStd_Array1OfReal tabdist(1,4);
970   if (!isInfinite1) { 
971     tabdist(1) = theaxis.Distance(ptat11);
972     tabdist(2) = theaxis.Distance(ptat12);
973   }
974   else {
975     tabdist(1) = tabdist(2) = 0.;
976   }
977
978   if (!isInfinite2) { 
979     tabdist(3) = theaxis.Distance(ptat21);
980     tabdist(4) = theaxis.Distance(ptat22);
981   }
982   else {
983     tabdist(3) = tabdist(4) = 0.;
984   }
985
986   if (myAutomaticPosition) {
987     Standard_Real length_1(RealLast());
988     if (!isInfinite1) length_1 = .75*Abs(tabdist(2)-tabdist(1))+Min(tabdist(1),tabdist(2));
989
990     Standard_Real length_2(RealLast());
991     if (!isInfinite2) length_2 = .75*Abs(tabdist(4)-tabdist(3))+Min(tabdist(3),tabdist(4));
992     Standard_Real theLength(Min(length_1,length_2));
993     if (Precision::IsInfinite(theLength)) theLength = 50.;
994
995     myFAttach = myCenter.Translated(gp_Vec(d1)*theLength);
996     mySAttach = myCenter.Translated(gp_Vec(d2)*theLength);
997        
998     if (!isInfinite1) {
999       Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,myFAttach));
1000       Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
1001       Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
1002       if (par_p1_attach > par11 && par_p1_attach > par12) {
1003         par_p1_attach = Max(par11,par12);
1004         myFAttach = ElCLib::Value(par_p1_attach,gpl1);
1005       }
1006       else if (par_p1_attach < par11 && par_p1_attach < par12) {
1007         par_p1_attach = Min(par11,par12);
1008         myFAttach = ElCLib::Value(par_p1_attach,gpl1);
1009       }
1010     }
1011
1012     if (!isInfinite2) {
1013       Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,mySAttach));
1014       Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
1015       Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
1016       if (par_p2_attach > par21 && par_p2_attach > par22) {
1017         par_p2_attach = Max(par21,par22);
1018         mySAttach = ElCLib::Value(par_p2_attach,gpl2);
1019       }
1020       else if (par_p2_attach < par21 && par_p2_attach < par22) {
1021         par_p2_attach = Min(par21,par22);
1022         mySAttach = ElCLib::Value(par_p2_attach,gpl2);
1023       }
1024     }
1025     if ( myVal < PI) curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ())); 
1026     else {
1027       curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ())); 
1028       gp_Vec transl(curpos, myCenter);
1029       transl*= 2;
1030       curpos.Translate(transl);
1031     }
1032
1033     gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
1034     gp_Circ circle(ax,theLength);
1035     Standard_Real par = ElCLib::Parameter(circle,curpos);
1036     curpos = ElCLib::Value(par,circle);    
1037
1038     // un petit offset comme LengthDimension
1039     gp_Vec transl(myCenter, curpos);
1040     transl*= 0.3;
1041     curpos.Translate(transl);
1042     
1043     if (myIsSetBndBox)
1044       curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
1045
1046     myPosition = curpos;
1047     myAutomaticPosition = Standard_True;      
1048   }
1049
1050   else {
1051   // on projette le point dans le plan
1052     gp_Pnt2d pointOnPln(ProjLib::Project(myPlane->Pln(),myPosition));
1053     myPosition = BRepAdaptor_Surface(BRepBuilderAPI_MakeFace(myPlane->Pln()).Face()).Value(pointOnPln.X(),pointOnPln.Y());
1054     curpos = myPosition;
1055     Standard_Real dist(curpos.Distance(myCenter));    
1056     if (dist<=Precision::Confusion()) {
1057       gp_XYZ delta(1.,1.,1.);
1058       curpos.SetXYZ(curpos.XYZ()+delta);
1059       dist = curpos.Distance(myCenter);
1060     }
1061     // Pour savoir si on doit prendre la distance -dist ou non
1062     // il faut savoir si on est dans le secteur oppose a l'angle
1063     // ou non : on est dans le secteur oppose si les coordonnees
1064     // de curpos dans le repere (d1,d2) sont negatives
1065     gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
1066     gp_Circ circle(ax,dist);
1067 #ifdef DEB
1068 //    gp_Pnt p1(myCenter.Translated(gp_Vec(d1)*dist));
1069 #endif
1070     gp_Pnt p2(myCenter.Translated(gp_Vec(d2)*dist));
1071     Standard_Real uc1 = 0;
1072     Standard_Real uc2 = ElCLib::Parameter(circle, p2 );
1073     Standard_Real uco = ElCLib::Parameter(circle, curpos );
1074     Standard_Real udeb = uc1;
1075     Standard_Real ufin = uc2;
1076     if (uco > ufin) {
1077       if (Abs(myVal)<PI) {
1078         // test si uco est dans le secteur oppose 
1079         if (uco > udeb+PI && uco < ufin+PI){
1080           dist = -dist;
1081         }
1082       }
1083     }
1084
1085      gp_Pnt p1_attach(myCenter.Translated(gp_Vec(d1)*dist));
1086      gp_Pnt p2_attach(myCenter.Translated(gp_Vec(d2)*dist));
1087     
1088      if (!isInfinite1) {
1089        Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,p1_attach));
1090        Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
1091        Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
1092        if (par_p1_attach > par11 && par_p1_attach > par12) {
1093          par_p1_attach = Max(par11,par12);
1094          p1_attach = ElCLib::Value(par_p1_attach,gpl1);
1095        }
1096        else if (par_p1_attach < par11 && par_p1_attach < par12) {
1097          par_p1_attach = Min(par11,par12);
1098          p1_attach = ElCLib::Value(par_p1_attach,gpl1);
1099        }
1100      }
1101      myFAttach = p1_attach;
1102             
1103      if (!isInfinite2) {
1104        Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,p2_attach));
1105        Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
1106        Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
1107        if (par_p2_attach > par21 && par_p2_attach > par22) {
1108          par_p2_attach = Max(par21,par22);
1109          p2_attach = ElCLib::Value(par_p2_attach,gpl2);
1110        }
1111        else if (par_p2_attach < par21 && par_p2_attach < par22) {
1112          par_p2_attach = Min(par21,par22);
1113          p2_attach = ElCLib::Value(par_p2_attach,gpl2);
1114        }
1115      }
1116      mySAttach = p2_attach;
1117   }  
1118   myAxis = theaxis.Position();
1119
1120   //--------------------------------------------------------
1121   //    Computation of the presentation
1122   //--------------------------------------------------------
1123   Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
1124   Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
1125
1126   arr->SetLength(myArrowSize);
1127
1128   DsgPrs_AnglePresentation::Add(aPresentation,
1129                                 myDrawer,
1130                                 myVal,
1131                                 myText,
1132                                 myCenter,
1133                                 myFAttach,
1134                                 mySAttach,
1135                                 myFDir,
1136                                 mySDir,
1137                                 curpos,
1138                                 mySymbolPrs);
1139 }
1140
1141
1142
1143 //=======================================================================
1144 //function : ComputeTwoEdgesNullAngle
1145 //purpose  : compute the presentation of a angle dimension if it's null.
1146 //             -> the aim of the computation is to have a constant radius 
1147 //                during the dimension moving : the radius is independant
1148 //                of the cursor position, it's equal to a arbitrary value
1149 //=======================================================================
1150
1151 void AIS_AngleDimension::ComputeTwoEdgesNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
1152                                                   const Handle(Geom_Line)& l1,
1153                                                   const Handle(Geom_Line)& l2,
1154                                                   const gp_Pnt& ptat11,
1155                                                   const gp_Pnt& ptat12,
1156                                                   const gp_Pnt& ptat21,
1157                                                   const gp_Pnt& ptat22,
1158                                                   const Standard_Boolean isInfinite1,
1159                                                   const Standard_Boolean isInfinite2)
1160 {
1161   // current face
1162   BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
1163   TopoDS_Face face(makeface.Face());  
1164   BRepAdaptor_Surface adp(makeface.Face());
1165   // 2d lines => projection of 3d on current plane
1166   Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
1167   Handle(Geom2d_Line) l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
1168   Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
1169   Handle(Geom2d_Line) l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
1170
1171   gp_Lin gpl1 = l1->Lin();
1172   gp_Lin gpl2 = l2->Lin();
1173
1174   //------------------------------------------------------------
1175   //                Calcul de myCenter
1176   // -> Point situe sur la ligne mediane des 2 droites,
1177   //    calcule comme etant le milieu des 2 points les plus
1178   //    proches de chaque droite.
1179   //-----------------------------------------------------------
1180      //   theLength : rayon du futur cercle
1181   Standard_Real theLength = gpl1.Distance(gpl2.Location());
1182   // traitement du cas particulier ou les 2 droites sont confondues
1183   Standard_Boolean SameLines(Standard_False);
1184   if ( theLength <= Precision::Confusion()) {
1185     SameLines = Standard_True;
1186     if (!isInfinite1) {
1187       if (!isInfinite2) theLength = 0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1188       else theLength = 0.75*ptat11.Distance(ptat12);
1189     }
1190     else {
1191       if (!isInfinite2) theLength = 0.75*ptat21.Distance(ptat22);
1192       else theLength = 50.;
1193     }
1194   }
1195   else theLength = theLength*8/10;
1196
1197   gp_Pnt pmin1 ,pmin2;
1198   if (!isInfinite1 && !isInfinite2) {
1199     pmin1 = ptat11; pmin2 = ptat21;
1200     Standard_Real dis = ptat11.Distance(ptat21);
1201     Standard_Real dis2 = ptat11.Distance(ptat22);
1202     if ( dis2 < dis)  {
1203       pmin1 = ptat11;
1204       pmin2 = ptat22;
1205       dis = dis2;
1206     }
1207     dis2 = ptat12.Distance(ptat22);
1208     if ( dis2 < dis)  {
1209       pmin1 = ptat12;
1210       pmin2 = ptat22;
1211       dis = dis2;
1212     }
1213     dis2 = ptat12.Distance(ptat21);
1214     if ( dis2 < dis)  {
1215       pmin1 = ptat12;
1216       pmin2 = ptat21;
1217       dis = dis2;
1218     }
1219     myCenter.SetXYZ( (pmin1.XYZ() + pmin2.XYZ()) / 2. );
1220   }
1221   else {
1222     gp_Pnt pntOnl1 = gpl1.Location();
1223     gp_Pnt pntOnl2 = ElCLib::Value(ElCLib::Parameter(gpl1,pntOnl1),gpl2);
1224     myCenter.SetXYZ( (pntOnl1.XYZ() + pntOnl2.XYZ()) / 2. );
1225   }
1226
1227   
1228   // directions 
1229   gp_Dir d1,d2;
1230   if (!isInfinite1) {
1231     if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
1232     else d1 = gp_Dir(gp_Vec(myCenter,ptat12));  
1233   }
1234   else d1 = gpl1.Direction();
1235   
1236   if (!isInfinite2) {
1237     if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
1238     else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
1239   }
1240   else d2 = gpl2.Direction();  
1241
1242   gp_Dir theaxis;
1243   if ( SameLines ) theaxis = myPlane->Pln().Axis().Direction();
1244   else {
1245     theaxis = gp_Dir(d1^d2);
1246     gp_Vec V1(d1); gp_Vec V2(d2);
1247     if ( V1.CrossMagnitude(V2) < 0 ) theaxis.Reverse();
1248   }
1249
1250   gp_Pnt curpos; // position du curseur
1251   TColStd_Array1OfReal tabdist(1,4);
1252   gp_Pnt P1, P2; // points d'intersection du cercle avec les 2 droites
1253  
1254   if (myAutomaticPosition) {
1255     if (!isInfinite1) {
1256       tabdist(1) = myCenter.Distance(ptat11);
1257       tabdist(2) = myCenter.Distance(ptat12);
1258     }
1259     else {
1260       tabdist(1) = tabdist(2) = 0.;
1261     }
1262     if (!isInfinite2) { 
1263       tabdist(3) = myCenter.Distance(ptat21);
1264       tabdist(4) = myCenter.Distance(ptat22);
1265     }
1266     else {
1267       tabdist(3) = tabdist(4) = 0.;
1268     }
1269     if ( SameLines ) {
1270       Standard_Real dist1(RealLast());
1271       if (!isInfinite1) dist1 = Max(tabdist(1),tabdist(2));
1272       Standard_Real dist2(RealLast());
1273       if (!isInfinite2) dist2 = Max(tabdist(3),tabdist(4));      
1274       
1275       myFAttach = myCenter;
1276       mySAttach = myCenter;
1277       P1 = myFAttach;
1278       P2 = mySAttach;
1279
1280       myCenter.Translate(gp_Vec(d1)*theLength);
1281
1282       // calcul des points d'attache de la cote 
1283       //  -> ils sont != des points d'intersection si les 
1284       //     intersection sont en dehors des limites des edges
1285       Standard_Real pparam = ElCLib::Parameter(gpl1,myFAttach);
1286       Standard_Real pparam1 = ElCLib::Parameter(gpl1,ptat11);
1287       Standard_Real pparam2 = ElCLib::Parameter(gpl1,ptat12);
1288       if (!isInfinite1) {
1289         if ( pparam1 < pparam2 ) {
1290           if ( pparam < pparam1 ) myFAttach = ptat11;
1291           else if ( pparam > pparam2) myFAttach = ptat12;
1292         }
1293         else {
1294           if ( pparam < pparam2) myFAttach = ptat12;
1295           else if ( pparam > pparam1) myFAttach = ptat11;
1296         }
1297       }
1298       if (!isInfinite2) {
1299         pparam = ElCLib::Parameter(gpl2,myFAttach);
1300         pparam1 = ElCLib::Parameter(gpl2,ptat21);
1301         pparam2 = ElCLib::Parameter(gpl2,ptat22);
1302         if ( pparam1 < pparam2 ) {
1303           if ( pparam < pparam1 ) mySAttach = ptat21;
1304           else if ( pparam > pparam2) mySAttach = ptat22;
1305         }
1306         else {
1307           if ( pparam < pparam2) mySAttach = ptat22;
1308           else if ( pparam > pparam1) mySAttach = ptat21;
1309         }
1310       }
1311     }
1312     // Case of disconneted lines
1313     else {
1314       gp_Ax2 AX(myCenter,theaxis,d1);
1315       Handle(Geom_Circle)  circle = new Geom_Circle(AX,theLength);
1316       Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
1317       Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
1318       // calcul du point d'intersection du cercle avec l1
1319       Standard_Real pparam; // parametre du point d'intersection sur l1
1320       IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
1321       gp_Pnt2d pint1(inter.Point(1).Value());
1322       gp_Pnt2d pint2(inter.Point(2).Value());
1323       
1324       gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
1325       gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
1326       gp_Dir I1I2(gp_Vec(Int1,Int2));
1327       if ( d1*I1I2 > 0 ) {
1328         myFAttach = Int2;
1329         pparam = inter.Point(2).ParamOnFirst();
1330       }
1331       else {
1332         myFAttach = Int1;
1333         pparam = inter.Point(1).ParamOnFirst();
1334       }
1335       P1 = myFAttach;
1336
1337       Standard_Real pparam1;
1338       Standard_Real pparam2; 
1339       if (!isInfinite1) {
1340         pparam1 = ElCLib::Parameter(gpl1,ptat11);
1341         pparam2 = ElCLib::Parameter(gpl1,ptat12);       
1342         if ( pparam1 < pparam2 ) {
1343           if ( pparam < pparam1 ) myFAttach = ptat11;
1344           else if ( pparam > pparam2) myFAttach = ptat12;
1345         }
1346         else {
1347           if ( pparam < pparam2) myFAttach = ptat12;
1348           else if ( pparam > pparam1) myFAttach = ptat11;
1349         }
1350       }
1351       pparam = ElCLib::Parameter(gpl2,P1);
1352       mySAttach = ElCLib::Value(pparam, gpl2);
1353       P2 = mySAttach;
1354
1355       if (!isInfinite2) {
1356         pparam1 = ElCLib::Parameter(gpl2,ptat21);
1357         pparam2 = ElCLib::Parameter(gpl2,ptat22);
1358         if ( pparam1 < pparam2 ) {
1359           if ( pparam < pparam1 ) mySAttach = ptat21;
1360           else if ( pparam > pparam2) mySAttach = ptat22;
1361         }
1362         else {
1363           if ( pparam < pparam2) mySAttach = ptat22;
1364           else if ( pparam > pparam1) mySAttach = ptat21;
1365         }
1366       }
1367     }
1368     curpos.SetXYZ(.5*(P1.XYZ()+P2.XYZ()));
1369
1370     gp_Ax2 ax(myCenter,theaxis,d1);
1371     gp_Circ circle(ax,theLength);
1372     Standard_Real par = ElCLib::Parameter(circle,curpos);
1373     curpos = ElCLib::Value(par,circle);
1374
1375     if (myIsSetBndBox)
1376       curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
1377     myPosition =curpos;
1378     myAutomaticPosition = Standard_True;      
1379   }
1380   else {
1381     curpos = myPosition;
1382     gp_Lin Media(myCenter, gpl1.Direction());
1383     Standard_Real pcurpos = ElCLib::Parameter(Media, curpos);
1384     myCenter =  ElCLib::Value(pcurpos, Media);
1385     // on translate le centre de facon a avoir un rayon constant!
1386     myCenter.Translate(-theLength*gp_Vec(gpl1.Direction()));
1387     gp_Ax2 AX(myCenter,theaxis,gpl1.Direction());
1388     Handle(Geom_Circle)  circle = new Geom_Circle(AX,theLength);
1389
1390     // remise a jour de curpos
1391     pcurpos = ElCLib::Parameter(circle->Circ(), curpos);
1392     curpos = ElCLib::Value(pcurpos, circle->Circ());
1393
1394     Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
1395     Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
1396     // calcul du point d'intersection du cercle avec l1
1397     IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
1398     gp_Pnt2d pint1(inter.Point(1).Value());
1399     gp_Pnt2d pint2(inter.Point(2).Value());
1400     gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
1401     gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
1402     if ( curpos.SquareDistance(Int1) < curpos.SquareDistance(Int2)) myFAttach = Int1;
1403     else myFAttach = Int2;
1404     P1 = myFAttach;
1405     
1406     // calcul du point d'intersection du cercle avec l2
1407     // -> c'est la projection car le cercle a son centre
1408     //    au milieu de l1 et l2
1409     Standard_Real pparam = ElCLib::Parameter(gpl2,myFAttach);
1410     mySAttach = ElCLib::Value(pparam, gpl2);
1411
1412     P2 = mySAttach;
1413
1414     Standard_Real par_attach(ElCLib::Parameter(gpl1,myFAttach));
1415     Standard_Real par1,par2; 
1416     if (!isInfinite1) {
1417       par1 = ElCLib::Parameter(gpl1,ptat11);
1418       par2 = ElCLib::Parameter(gpl1,ptat12);
1419       if (par1 < par2) {
1420         if ( par_attach < par1 ) myFAttach = ptat11;
1421         else if ( par_attach > par2) myFAttach = ptat12;
1422       }
1423       else {
1424         if ( par_attach < par2 ) myFAttach = ptat12;
1425         else if ( par_attach > par1) myFAttach = ptat11;
1426       }
1427     }
1428     par_attach = ElCLib::Parameter(gpl2,mySAttach);
1429     if (!isInfinite2) {
1430       par1 = ElCLib::Parameter(gpl2,ptat21);
1431       par2 = ElCLib::Parameter(gpl2,ptat22);
1432       if (par1 < par2) {
1433         if ( par_attach < par1 ) mySAttach = ptat21;
1434         else if ( par_attach > par2) mySAttach = ptat22;
1435       }
1436       else {
1437         if ( par_attach < par2 ) mySAttach = ptat22;
1438         else if ( par_attach > par1) mySAttach = ptat21;
1439       }
1440     }
1441   }
1442
1443   myFDir = gp_Dir(gp_Vec(myCenter,P1));
1444   mySDir = gp_Dir(gp_Vec(myCenter,P2));
1445
1446   //--------------------------------------------------------
1447   //    Computation of the presentation
1448   //--------------------------------------------------------
1449   Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
1450   Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
1451
1452   arr->SetLength(myArrowSize);
1453
1454   if (SameLines)
1455     DsgPrs_AnglePresentation::Add(aPresentation,
1456                                   myDrawer,
1457                                   myVal,
1458                                   myText,
1459                                   myCenter,
1460                                   myFAttach,
1461                                   mySAttach,
1462                                   myFDir,
1463                                   mySDir,
1464                                   theaxis,
1465                                   Standard_True,
1466                                   myAxis,
1467                                   curpos,
1468                                   DsgPrs_AS_NONE);
1469   else
1470     DsgPrs_AnglePresentation::Add(aPresentation,
1471                                   myDrawer,
1472                                   myVal,
1473                                   myText,
1474                                   myCenter,
1475                                   myFAttach,
1476                                   mySAttach,
1477                                   myFDir,
1478                                   mySDir,
1479                                   curpos,
1480                                   mySymbolPrs);
1481 }
1482
1483
1484 //=======================================================================
1485 //function : Compute3DSelection
1486 // purpose  : compute the zones of selection for an angle dimension
1487 //            between 2 faces
1488 //=======================================================================
1489
1490 void AIS_AngleDimension::Compute3DSelection( const Handle( SelectMgr_Selection )& aSelection )
1491 {
1492   gp_Circ AngleCirc, AttachCirc;
1493   Standard_Real FirstParAngleCirc, LastParAngleCirc, FirstParAttachCirc, LastParAttachCirc;
1494   gp_Pnt EndOfArrow1, EndOfArrow2, ProjAttachPoint2;
1495   gp_Dir DirOfArrow1, DirOfArrow2;
1496   gp_Dir axisdir = (myVal <= Precision::Angular() || Abs( PI-myVal ) <= Precision::Angular())?
1497                     myPlane->Pln().Axis().Direction() : (myFDir ^ mySDir);
1498   Standard_Boolean isPlane = (myFirstSurfType == AIS_KOS_Plane)? Standard_True : Standard_False;
1499
1500   Standard_Real ArrowLength = myDrawer->AngleAspect()->ArrowAspect()->Length();
1501   DsgPrs::ComputeFacesAnglePresentation( ArrowLength,
1502                                          myVal,
1503                                          myCenter,
1504                                          myFAttach,
1505                                          mySAttach,
1506                                          myFDir,
1507                                          mySDir,
1508                                          axisdir,
1509                                          isPlane,
1510                                          myAxis,
1511                                          myPosition,
1512                                          AngleCirc,
1513                                          FirstParAngleCirc,
1514                                          LastParAngleCirc,
1515                                          EndOfArrow1,
1516                                          EndOfArrow2,
1517                                          DirOfArrow1,
1518                                          DirOfArrow2,
1519                                          ProjAttachPoint2,
1520                                          AttachCirc,
1521                                          FirstParAttachCirc,
1522                                          LastParAttachCirc );
1523   
1524   Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
1525   Handle( Select3D_SensitiveSegment ) seg;
1526   Handle( Geom_TrimmedCurve ) curve; 
1527   Handle( Select3D_SensitiveCurve ) SensCurve;
1528
1529   // Angle's arc or line
1530   if (myVal > Precision::Angular() && Abs( PI-myVal ) > Precision::Angular())
1531     {
1532       curve = new Geom_TrimmedCurve( new Geom_Circle( AngleCirc ), FirstParAngleCirc, LastParAngleCirc );
1533       SensCurve = new Select3D_SensitiveCurve( own, curve );
1534       aSelection->Add( SensCurve );
1535     }
1536   else // angle's line
1537     {
1538       gp_Vec ArrowVec( DirOfArrow1 );
1539       ArrowVec *= ArrowLength;
1540       gp_Pnt FirstPoint, LastPoint;
1541
1542       if (myPosition.Distance( EndOfArrow1 ) > ArrowLength)
1543         {
1544           FirstPoint = myPosition;
1545           LastPoint = EndOfArrow1.Translated( ArrowVec );
1546           if (myPosition.SquareDistance( LastPoint ) < myPosition.SquareDistance( EndOfArrow1 ))
1547             LastPoint = EndOfArrow1.Translated( -ArrowVec );
1548         }
1549       else
1550         {
1551           FirstPoint = EndOfArrow1.Translated( ArrowVec );
1552           LastPoint = EndOfArrow1.Translated( -ArrowVec );
1553         }
1554       seg = new Select3D_SensitiveSegment( own, FirstPoint, LastPoint );
1555       aSelection->Add( seg );
1556     }
1557
1558   if (! myFAttach.IsEqual( EndOfArrow1, Precision::Confusion() ))
1559     {
1560       seg = new Select3D_SensitiveSegment( own, myFAttach, EndOfArrow1 );
1561       aSelection->Add( seg );
1562     }
1563   if (! ProjAttachPoint2.IsEqual( EndOfArrow2, Precision::Confusion() ))
1564     {
1565       seg = new Select3D_SensitiveSegment( own, ProjAttachPoint2, EndOfArrow2 );
1566       aSelection->Add( seg );
1567     }
1568
1569   // Line or arc from mySAttach to its "projection"
1570   if (! mySAttach.IsEqual( ProjAttachPoint2, Precision::Confusion() ))
1571     {
1572       if (isPlane)
1573         {
1574           seg = new Select3D_SensitiveSegment( own, mySAttach, ProjAttachPoint2 );
1575           aSelection->Add( seg );
1576         }
1577       else
1578         {
1579           curve = new Geom_TrimmedCurve( new Geom_Circle( AttachCirc ),
1580                                          FirstParAttachCirc,
1581                                          LastParAttachCirc );
1582           SensCurve = new Select3D_SensitiveCurve( own, curve );
1583           aSelection->Add( SensCurve );
1584         }
1585     }
1586
1587   // Text
1588   Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
1589   Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
1590                                                                    myPosition.X(),
1591                                                                    myPosition.Y(),
1592                                                                    myPosition.Z(),
1593                                                                    myPosition.X() + size,
1594                                                                    myPosition.Y() + size,
1595                                                                    myPosition.Z() + size);  
1596   aSelection->Add(box);
1597 }
1598
1599 //=======================================================================
1600 //function : Compute2DSelection
1601 //purpose  : calcule les zones de selection sur une cote d'angle entre 2
1602 //           edges
1603 //            Traitement particulier pour les angles nuls!
1604 //=======================================================================
1605
1606 void AIS_AngleDimension::Compute2DSelection(const Handle(SelectMgr_Selection)& aSelection)
1607 {
1608   BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
1609   BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
1610
1611   gp_Lin l1(cu1.Line());
1612   gp_Lin l2(cu2.Line());
1613
1614   // it is patch!
1615   if (Abs( myVal ) <= Precision::Angular() || Abs( PI - myVal ) <= Precision::Angular())
1616 /*
1617   //---------------------------------------------------------
1618   //    Cas de droites paralleles ( <=> angle nul a PI pres)
1619   if ((Abs(l1.Angle(l2)) < Precision::Angular()) ||
1620       (Abs((l1.Angle(l2) - PI)) < Precision::Angular()) )
1621 */
1622     {
1623        
1624     Standard_Real distLL= l1.Distance(l2);
1625     if ( Abs(distLL) <= Precision::Confusion() ) {
1626       gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1627       gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1628       gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1629       gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1630       distLL =  0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1631       ComputeNull2DSelection(aSelection, distLL);
1632     }
1633     else {
1634       ComputeNull2DSelection(aSelection, distLL*8/10);
1635     }
1636   }
1637   
1638   //----------------------------------------------------------
1639   //  Cas classique ( angle != 0 )
1640   else {
1641
1642     if (myFDir.IsParallel(mySDir,Precision::Angular())) {
1643       Standard_Real distLL= l1.Distance(l2);
1644       if ( Abs(distLL) <= Precision::Confusion() ) {
1645         gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1646         gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1647         gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1648         gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1649         distLL =  0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1650         ComputeNull2DSelection(aSelection, distLL*8/10);
1651       }
1652     }
1653     else {
1654       gp_Dir Norm = myFDir.Crossed(mySDir);
1655       
1656       gp_Ax2 ax(myCenter,Norm,myFDir);
1657       gp_Circ cer(ax,myCenter.Distance(myPosition));
1658       gp_Vec vec1(myFDir);
1659       
1660       Standard_Boolean nullrad(Standard_False);
1661       if (cer.Radius() == 0.) {
1662         cer.SetRadius(1.);
1663         nullrad = Standard_True;
1664       }
1665       vec1 *= cer.Radius();
1666       gp_Pnt p1 = myCenter.Translated(vec1);
1667       gp_Vec vec2(mySDir);
1668       vec2 *= cer.Radius();
1669       gp_Pnt p2 = myCenter.Translated(vec2);
1670       
1671       Standard_Real uc1 = 0.;
1672       Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1673       Standard_Real uco;
1674       if (nullrad) uco = ElCLib::Parameter(cer,p1);
1675       else uco = ElCLib::Parameter(cer,myPosition);
1676       
1677       Standard_Real udeb = uc1;
1678       Standard_Real ufin = uc2;
1679       
1680       if (uco > ufin) {
1681         if (Abs(myVal)<PI) {
1682           // test si uco est dans le secteur oppose 
1683           if (uco > udeb+PI && uco < ufin+PI){
1684             udeb = udeb + PI;
1685           ufin = ufin + PI;
1686             uc1  = udeb;
1687             uc2  = ufin;
1688           }
1689       }
1690       }  
1691       if (uco > ufin) {
1692         if ((uco-uc2) < (uc1-uco+(2*PI))) ufin = uco;
1693         else udeb = uco - 2*PI;
1694       }
1695       p1   = ElCLib::Value(udeb,cer);
1696       p2   = ElCLib::Value(ufin,cer);
1697       
1698       //Creation des 2 owners pour chaque partie de la fleche
1699       Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1700       Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1701       if (myExtShape != 0) {
1702         if (myExtShape == 1) {
1703           own1->SetShape(mySShape);
1704           own2->SetShape(mySShape);
1705         }
1706         else {
1707           own1->SetShape(myFShape);
1708           own2->SetShape(myFShape);
1709         }
1710       }
1711       else {
1712         own1->SetShape(myFShape);
1713         own2->SetShape(mySShape);
1714       }
1715       
1716       Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1717       
1718       Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1719       Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1720       
1721       Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1722       aSelection->Add(scurv);
1723       scurv = new Select3D_SensitiveCurve(own2,thecu2);
1724       aSelection->Add(scurv);
1725       
1726       Handle(Select3D_SensitiveSegment) seg;
1727       if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1728         seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1729         aSelection->Add(seg);
1730       }
1731       if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1732         seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1733         aSelection->Add(seg);
1734       }
1735     }
1736   }
1737
1738 }
1739 //=======================================================================
1740 //function : Compute2DNullSelection
1741 //purpose  : for dimension of null angle
1742 //=======================================================================
1743
1744 void AIS_AngleDimension::ComputeNull2DSelection(
1745                          const Handle(SelectMgr_Selection)& aSelection,
1746                          const Standard_Real distLL)
1747 {
1748   gp_Dir Norm; 
1749   if ( myFDir.IsParallel(mySDir, Precision::Angular()) ) {
1750     Norm = myPlane->Pln().Axis().Direction();
1751   }
1752   else
1753     Norm = myFDir.Crossed(mySDir);
1754
1755   gp_Ax2 ax(myCenter,Norm,myFDir);
1756   gp_Circ cer(ax,distLL);
1757   
1758   gp_Vec vec1(myFDir);
1759   vec1 *= cer.Radius();
1760   gp_Pnt p1 = myCenter.Translated(vec1);
1761   gp_Vec vec2(mySDir);
1762   vec2 *= cer.Radius();
1763   gp_Pnt p2 = myCenter.Translated(vec2);
1764
1765   // calcul de parametres de debut et de fin des extremites de l'arc
1766   Standard_Real uc1 = 0.;
1767   Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1768   Standard_Real uco = ElCLib::Parameter(cer,myPosition);
1769
1770   Standard_Real udeb = uc1;
1771   Standard_Real ufin = uc2;
1772
1773   if (uco > ufin) {
1774     if (Abs(myVal)<PI) {
1775       // test si uco est dans le secteur oppose 
1776       if (uco > udeb+PI && uco < ufin+PI){
1777         udeb = udeb + PI;
1778         ufin = ufin + PI;
1779         uc1  = udeb;
1780         uc2  = ufin;
1781       }
1782     }
1783   }
1784
1785   if (uco > ufin) {
1786     if ((uco-uc2) < (uc1-uco+(2*PI))) {
1787       ufin = uco;
1788     }
1789     else {
1790       udeb = uco - 2*PI;
1791     }
1792   }
1793
1794   //Creation des 2 owners pour chaque partie de la fleche
1795   Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1796   Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1797   if (myExtShape != 0) {
1798     if (myExtShape == 1) {
1799       own1->SetShape(mySShape);
1800       own2->SetShape(mySShape);
1801     }
1802     else {
1803       own1->SetShape(myFShape);
1804       own2->SetShape(myFShape);
1805     }
1806   }
1807   else {
1808     own1->SetShape(myFShape);
1809     own2->SetShape(mySShape);
1810   }
1811   
1812   Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1813
1814   if ( udeb != ufin ) {
1815     Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1816     Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1817
1818     Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1819     aSelection->Add(scurv);
1820     scurv = new Select3D_SensitiveCurve(own2,thecu2);
1821     aSelection->Add(scurv);
1822   }
1823   else {
1824     // on trace un bout de segment pour permettre la selection
1825     gp_Vec VTrans(myFDir.Crossed(Norm));
1826     Handle(Select3D_SensitiveSegment) seg1;
1827     seg1 = new Select3D_SensitiveSegment(own1, 
1828                                          p1, 
1829                                          p1.Translated( VTrans*distLL/10 ) );
1830     aSelection->Add(seg1);
1831     seg1 = new Select3D_SensitiveSegment(own2, 
1832                                          p2, 
1833                                          p2.Translated(-VTrans*distLL/10 ) );
1834     aSelection->Add(seg1);
1835   }
1836
1837   Handle(Select3D_SensitiveSegment) seg;
1838   if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1839     seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1840     aSelection->Add(seg);
1841   }
1842     
1843   if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1844     seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1845     aSelection->Add(seg);
1846   }
1847 }
1848
1849
1850 //=======================================================================
1851 //function : ComputeConeAngleSelection
1852 //purpose  : for cone angle
1853 //=======================================================================
1854 void AIS_AngleDimension::ComputeConeAngleSelection(const Handle(SelectMgr_Selection)& aSelection)
1855 {
1856   if( myCone.IsNull() ) return;
1857
1858
1859   Handle( SelectMgr_EntityOwner ) owner = new SelectMgr_EntityOwner( this, 7 );
1860   Handle( Select3D_SensitiveSegment ) seg;
1861   
1862   gp_Pln aPln;
1863   gp_Cone aCone;
1864   gp_Circ myCircle;
1865   gp_Pnt Apex;
1866   Handle( Geom_Surface ) aSurf;         //a surface from the Face
1867   Handle( Geom_OffsetSurface ) aOffsetSurf; 
1868   Handle( Geom_ConicalSurface ) aConicalSurf;
1869   Handle( Geom_SurfaceOfRevolution ) aRevSurf; 
1870   Handle( Geom_Line ) aLine;
1871   BRepAdaptor_Surface tmpSurf(myCone);  
1872   TopoDS_Face aFace;
1873   AIS_KindOfSurface aSurfType;
1874   Standard_Real Offset = 0. ;
1875   Handle( Standard_Type ) aType;
1876
1877   Standard_Real maxV = tmpSurf.FirstVParameter();
1878   Standard_Real minV = tmpSurf.LastVParameter();
1879
1880   AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
1881   
1882   if ( aSurfType == AIS_KOS_Revolution ) {                                    //surface of revolution
1883
1884     aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf ); 
1885     gp_Lin ln( aRevSurf->Axis() );
1886     Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
1887     if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) )  return;        //Must be a part of line
1888
1889     Standard_Real par;
1890     gp_Pnt fst = tmpSurf.Value(0., minV);
1891     gp_Pnt lst = tmpSurf.Value(0., maxV);
1892  
1893     gp_Vec vec1(fst, lst);
1894    
1895     par = ElCLib::Parameter( ln, fst );
1896     gp_Pnt fst2 = ElCLib::Value( par, ln );                         //projection fst on ln
1897     par = ElCLib::Parameter( ln, lst );
1898     gp_Pnt lst2 = ElCLib::Value( par, ln );                         //projection lst on ln
1899
1900     gp_Vec vec2(fst2, lst2);
1901
1902    // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle ) 
1903     if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return; 
1904  
1905     gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
1906     aCone =  mkCone.Value();
1907     Apex = aCone.Apex();
1908   }
1909   else {  
1910     aType = aSurf->DynamicType();
1911     if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) {            //offset surface
1912       aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
1913       aSurf = aOffsetSurf->Surface();
1914       BRepBuilderAPI_MakeFace mkFace(aSurf);
1915       mkFace.Build();
1916       if( !mkFace.IsDone() ) return;
1917       tmpSurf.Initialize( mkFace.Face() );
1918     }  
1919  
1920     aCone = tmpSurf.Cone();
1921     aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
1922     Apex =  aConicalSurf->Apex();
1923   }
1924
1925   Handle(Geom_Curve) aCurve;                 //A circle where the angle is drawn
1926   
1927   if ( myAutomaticPosition ) {
1928     Standard_Real midV = ( minV + maxV ) / 2.5; 
1929
1930     aCurve =   aSurf->VIso(midV);
1931     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1932
1933     myPosition = ElCLib::Value(Standard_PI / 2.0, myCircle);
1934     myAutomaticPosition = Standard_False;
1935   }
1936   else {
1937     Standard_Real U, V;
1938     ElSLib::Parameters(aCone, myPosition, U, V);
1939     aCurve = aSurf->VIso(V); 
1940     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1941   }
1942  //__________________________________________________________________
1943   aCurve = aSurf->VIso(maxV);
1944   gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1945   aCurve = aSurf->VIso(minV);
1946   gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1947  //__________________________________________________________________
1948
1949   if( CircVmax.Radius() < CircVmin.Radius() ) {
1950    gp_Circ tmpCirc = CircVmax;
1951    CircVmax = CircVmin;
1952    CircVmin = tmpCirc;
1953   }
1954  
1955   Standard_Boolean IsArrowOut = Standard_True;    //Is arrows inside or outside of the cone
1956   //Standard_Real PntOnMainAxis = 0;   //Is projection of aPosition inside of the cone = 0, above = 1, or below = -1
1957   Standard_Boolean IsConeTrimmed = Standard_False; 
1958
1959   if( CircVmin.Radius() > 0.01 ) IsConeTrimmed = Standard_True;
1960
1961   gp_Pnt AttachmentPnt;
1962   gp_Pnt OppositePnt;
1963   gp_Pnt aPnt, tmpPnt;
1964   Quantity_Length X,Y,Z;
1965
1966   Standard_Real param = ElCLib::Parameter(myCircle, myPosition);
1967
1968   aPnt = Apex;
1969   gp_Pnt P1 = ElCLib::Value(0., myCircle);
1970   gp_Pnt P2 = ElCLib::Value(Standard_PI, myCircle);
1971
1972   gce_MakePln mkPln(P1, P2,  aPnt);   // create a plane whitch defines plane for projection aPosition on it
1973
1974   aPnt =  AIS::ProjectPointOnPlane(myPosition, mkPln.Value()); 
1975   tmpPnt = aPnt;
1976
1977   if( aPnt.Distance(P1) <  aPnt.Distance(P2) ){
1978     AttachmentPnt = P1; 
1979     OppositePnt = P2; 
1980   }
1981   else {
1982     AttachmentPnt = P2; 
1983     OppositePnt = P1;
1984   }
1985   
1986   aPnt = AttachmentPnt ;                          // Creating of circle whitch defines a plane for a dimension arc
1987   gp_Vec Vec(AttachmentPnt, Apex);                // Dimension arc is a part of the circle 
1988   Vec.Scale(2);
1989   aPnt.Translate(Vec);
1990   GC_MakeCircle mkCirc(AttachmentPnt, OppositePnt,  aPnt); 
1991   gp_Circ  aCircle2 = mkCirc.Value()->Circ();
1992
1993   
1994   Standard_Integer i;
1995   Standard_Real AttParam = ElCLib::Parameter(aCircle2, AttachmentPnt);
1996   Standard_Real OppParam = ElCLib::Parameter(aCircle2, OppositePnt);
1997   
1998   while ( AttParam >= 2*Standard_PI ) AttParam -= 2*Standard_PI;
1999   while ( OppParam >= 2*Standard_PI ) OppParam -= 2*Standard_PI;
2000
2001   if( myPosition.Distance( myCircle.Location() ) <= myCircle.Radius() )
2002     if( 2 * myCircle.Radius() > aCircle2.Radius() * 0.4 ) IsArrowOut = Standard_False;  //four times more than an arrow size
2003  
2004   Graphic3d_Array1OfVertex V(1, 12);
2005   
2006   Standard_Real angle;
2007   param = ElCLib::Parameter(aCircle2, tmpPnt);
2008
2009   if(IsArrowOut) {
2010     angle = OppParam - AttParam + Standard_PI/6; //An angle between AttParam and OppParam + 30 degrees
2011     param = AttParam - Standard_PI/12;      //out parts of dimension line are 15 degrees
2012     
2013     while ( angle > 2*Standard_PI ) angle -= 2*Standard_PI;
2014     for( i = 0; i <= 11; i++ ) {       //calculating of arc             
2015       aPnt = ElCLib::Value(param + angle/11 * i, aCircle2);
2016       aPnt.Coord(X, Y, Z);
2017       V(i+1).SetCoord(X, Y, Z);    
2018     }
2019       
2020   }
2021   else {
2022     angle = OppParam - AttParam;
2023     param = AttParam;
2024     while ( angle > 2*Standard_PI ) angle -= 2*Standard_PI;
2025     for( i = 0; i <= 11; i++ ) {       //calculating of arc             
2026       aPnt = ElCLib::Value(param + angle/11 * i, aCircle2);
2027       aPnt.Coord(X, Y, Z);
2028       V(i+1).SetCoord(X, Y, Z);
2029     }
2030   }
2031   
2032   for(i = 1; i<=11; i++) {
2033
2034     V(i).Coord(X, Y, Z);
2035     P1.SetCoord(X, Y, Z);
2036     V(i+1).Coord(X, Y, Z);
2037     P1.SetCoord(X, Y, Z);
2038
2039     seg = new Select3D_SensitiveSegment(owner, P1, P2);
2040     aSelection->Add(seg);   
2041   }
2042
2043   tmpPnt =  tmpPnt.Translated(gp_Vec(0, 0, -1)*2);
2044
2045   Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
2046   Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( owner,
2047                                                                    tmpPnt.X(),
2048                                                                    tmpPnt.Y(),
2049                                                                    tmpPnt.Z(),
2050                                                                    tmpPnt.X() + size,
2051                                                                    tmpPnt.Y() + size,
2052                                                                    tmpPnt.Z() + size);
2053   aSelection->Add(box);
2054 }
2055
2056
2057