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