0022627: Change OCCT memory management defaults
[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, Precision::Confusion());
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(M_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( M_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 with 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   // Processing in  case of 2 parallel straight lines
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   // Processing in case of 2 non-parallel straight lines
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) <  M_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 >  M_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 < M_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     // small offset like in 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   // point is projected on the plane
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     // To learn if it is necessary to take distance -dist or not
1062     // it is necessary to know if we are in the sector opposite to the angle
1063     // if not : we are in the opposite sector if the coordinates
1064     // of curpos in point (d1,d2) are negative
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)<M_PI) {
1078         // test if uco is in the opposite sector 
1079         if (uco > udeb+M_PI && uco < ufin+M_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   //                Computation of myCenter
1176   // -> Point located on the median of 2 straight lines,
1177   //    is calculated as located between 2 closest points 
1178   //    of each straight line.
1179   //-----------------------------------------------------------
1180      //   theLength : radius of the future circle
1181   Standard_Real theLength = gpl1.Distance(gpl2.Location());
1182   // processing of the particular case when 2 straight lines are coincident
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; // cursor position
1251   TColStd_Array1OfReal tabdist(1,4);
1252   gp_Pnt P1, P2; // points at intersection of the circle with 2 straight lines
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       // calculate attachments of the face 
1283       //  -> they are points of intersection if  
1284       //     intersection is outside of the 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       // calculate the intersection of circle with l1
1319       Standard_Real pparam; // parameter of the point of intersection on 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     // the centre is translated to avoid a constant radius!
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     // re-update 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     // calculate the point of intersection of circle with 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     // calculate the point of intersection of circle with l2
1407     // -> this is the projection because the centre of circle
1408     //    is in the middle of l1 and 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( M_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( M_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  : compute zones of selection on a side of angle between 2 edges
1602 //           Special processing of zero angles!
1603 //=======================================================================
1604
1605 void AIS_AngleDimension::Compute2DSelection(const Handle(SelectMgr_Selection)& aSelection)
1606 {
1607   BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
1608   BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
1609
1610   gp_Lin l1(cu1.Line());
1611   gp_Lin l2(cu2.Line());
1612
1613   // it is patch!
1614   if (Abs( myVal ) <= Precision::Angular() || Abs( M_PI - myVal ) <= Precision::Angular())
1615 /*
1616   //---------------------------------------------------------
1617   //    Cas de droites paralleles ( <=> angle nul a M_PI pres)
1618   if ((Abs(l1.Angle(l2)) < Precision::Angular()) ||
1619       (Abs((l1.Angle(l2) - M_PI)) < Precision::Angular()) )
1620 */
1621     {
1622        
1623     Standard_Real distLL= l1.Distance(l2);
1624     if ( Abs(distLL) <= Precision::Confusion() ) {
1625       gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1626       gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1627       gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1628       gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1629       distLL =  0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1630       ComputeNull2DSelection(aSelection, distLL);
1631     }
1632     else {
1633       ComputeNull2DSelection(aSelection, distLL*8/10);
1634     }
1635   }
1636   
1637   //----------------------------------------------------------
1638   //  Classic case  ( angle != 0 )
1639   else {
1640
1641     if (myFDir.IsParallel(mySDir,Precision::Angular())) {
1642       Standard_Real distLL= l1.Distance(l2);
1643       if ( Abs(distLL) <= Precision::Confusion() ) {
1644         gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1645         gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1646         gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1647         gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1648         distLL =  0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1649         ComputeNull2DSelection(aSelection, distLL*8/10);
1650       }
1651     }
1652     else {
1653       gp_Dir Norm = myFDir.Crossed(mySDir);
1654       
1655       gp_Ax2 ax(myCenter,Norm,myFDir);
1656       gp_Circ cer(ax,myCenter.Distance(myPosition));
1657       gp_Vec vec1(myFDir);
1658       
1659       Standard_Boolean nullrad(Standard_False);
1660       if (cer.Radius() == 0.) {
1661         cer.SetRadius(1.);
1662         nullrad = Standard_True;
1663       }
1664       vec1 *= cer.Radius();
1665       gp_Pnt p1 = myCenter.Translated(vec1);
1666       gp_Vec vec2(mySDir);
1667       vec2 *= cer.Radius();
1668       gp_Pnt p2 = myCenter.Translated(vec2);
1669       
1670       Standard_Real uc1 = 0.;
1671       Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1672       Standard_Real uco;
1673       if (nullrad) uco = ElCLib::Parameter(cer,p1);
1674       else uco = ElCLib::Parameter(cer,myPosition);
1675       
1676       Standard_Real udeb = uc1;
1677       Standard_Real ufin = uc2;
1678       
1679       if (uco > ufin) {
1680         if (Abs(myVal)<M_PI) {
1681           // test if uco is in the opposing sector 
1682           if (uco > udeb+M_PI && uco < ufin+M_PI){
1683             udeb = udeb + M_PI;
1684           ufin = ufin + M_PI;
1685             uc1  = udeb;
1686             uc2  = ufin;
1687           }
1688       }
1689       }  
1690       if (uco > ufin) {
1691         if ((uco-uc2) < (uc1-uco+(2*M_PI))) ufin = uco;
1692         else udeb = uco - 2*M_PI;
1693       }
1694       p1   = ElCLib::Value(udeb,cer);
1695       p2   = ElCLib::Value(ufin,cer);
1696       
1697       //Create 2 owners for each part of the arrow
1698       Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1699       Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1700       if (myExtShape != 0) {
1701         if (myExtShape == 1) {
1702           own1->SetShape(mySShape);
1703           own2->SetShape(mySShape);
1704         }
1705         else {
1706           own1->SetShape(myFShape);
1707           own2->SetShape(myFShape);
1708         }
1709       }
1710       else {
1711         own1->SetShape(myFShape);
1712         own2->SetShape(mySShape);
1713       }
1714       
1715       Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1716       
1717       Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1718       Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1719       
1720       Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1721       aSelection->Add(scurv);
1722       scurv = new Select3D_SensitiveCurve(own2,thecu2);
1723       aSelection->Add(scurv);
1724       
1725       Handle(Select3D_SensitiveSegment) seg;
1726       if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1727         seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1728         aSelection->Add(seg);
1729       }
1730       if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1731         seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1732         aSelection->Add(seg);
1733       }
1734     }
1735   }
1736
1737 }
1738 //=======================================================================
1739 //function : Compute2DNullSelection
1740 //purpose  : for dimension of null angle
1741 //=======================================================================
1742
1743 void AIS_AngleDimension::ComputeNull2DSelection(
1744                          const Handle(SelectMgr_Selection)& aSelection,
1745                          const Standard_Real distLL)
1746 {
1747   gp_Dir Norm; 
1748   if ( myFDir.IsParallel(mySDir, Precision::Angular()) ) {
1749     Norm = myPlane->Pln().Axis().Direction();
1750   }
1751   else
1752     Norm = myFDir.Crossed(mySDir);
1753
1754   gp_Ax2 ax(myCenter,Norm,myFDir);
1755   gp_Circ cer(ax,distLL);
1756   
1757   gp_Vec vec1(myFDir);
1758   vec1 *= cer.Radius();
1759   gp_Pnt p1 = myCenter.Translated(vec1);
1760   gp_Vec vec2(mySDir);
1761   vec2 *= cer.Radius();
1762   gp_Pnt p2 = myCenter.Translated(vec2);
1763
1764   // calcul de parametres de debut et de fin des extremites de l'arc
1765   Standard_Real uc1 = 0.;
1766   Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1767   Standard_Real uco = ElCLib::Parameter(cer,myPosition);
1768
1769   Standard_Real udeb = uc1;
1770   Standard_Real ufin = uc2;
1771
1772   if (uco > ufin) {
1773     if (Abs(myVal)<M_PI) {
1774       // test if uco is in the opposing sector 
1775       if (uco > udeb+M_PI && uco < ufin+M_PI){
1776         udeb = udeb + M_PI;
1777         ufin = ufin + M_PI;
1778         uc1  = udeb;
1779         uc2  = ufin;
1780       }
1781     }
1782   }
1783
1784   if (uco > ufin) {
1785     if ((uco-uc2) < (uc1-uco+(2*M_PI))) {
1786       ufin = uco;
1787     }
1788     else {
1789       udeb = uco - 2*M_PI;
1790     }
1791   }
1792
1793   //Create 2 owners for each part of the arrow
1794   Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1795   Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1796   if (myExtShape != 0) {
1797     if (myExtShape == 1) {
1798       own1->SetShape(mySShape);
1799       own2->SetShape(mySShape);
1800     }
1801     else {
1802       own1->SetShape(myFShape);
1803       own2->SetShape(myFShape);
1804     }
1805   }
1806   else {
1807     own1->SetShape(myFShape);
1808     own2->SetShape(mySShape);
1809   }
1810   
1811   Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1812
1813   if ( udeb != ufin ) {
1814     Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1815     Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1816
1817     Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1818     aSelection->Add(scurv);
1819     scurv = new Select3D_SensitiveCurve(own2,thecu2);
1820     aSelection->Add(scurv);
1821   }
1822   else {
1823     // find end of segment to allow selection
1824     gp_Vec VTrans(myFDir.Crossed(Norm));
1825     Handle(Select3D_SensitiveSegment) seg1;
1826     seg1 = new Select3D_SensitiveSegment(own1, 
1827                                          p1, 
1828                                          p1.Translated( VTrans*distLL/10 ) );
1829     aSelection->Add(seg1);
1830     seg1 = new Select3D_SensitiveSegment(own2, 
1831                                          p2, 
1832                                          p2.Translated(-VTrans*distLL/10 ) );
1833     aSelection->Add(seg1);
1834   }
1835
1836   Handle(Select3D_SensitiveSegment) seg;
1837   if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1838     seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1839     aSelection->Add(seg);
1840   }
1841     
1842   if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1843     seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1844     aSelection->Add(seg);
1845   }
1846 }
1847
1848
1849 //=======================================================================
1850 //function : ComputeConeAngleSelection
1851 //purpose  : for cone angle
1852 //=======================================================================
1853 void AIS_AngleDimension::ComputeConeAngleSelection(const Handle(SelectMgr_Selection)& aSelection)
1854 {
1855   if( myCone.IsNull() ) return;
1856
1857
1858   Handle( SelectMgr_EntityOwner ) owner = new SelectMgr_EntityOwner( this, 7 );
1859   Handle( Select3D_SensitiveSegment ) seg;
1860   
1861   gp_Pln aPln;
1862   gp_Cone aCone;
1863   gp_Circ myCircle;
1864   gp_Pnt Apex;
1865   Handle( Geom_Surface ) aSurf;         //a surface from the Face
1866   Handle( Geom_OffsetSurface ) aOffsetSurf; 
1867   Handle( Geom_ConicalSurface ) aConicalSurf;
1868   Handle( Geom_SurfaceOfRevolution ) aRevSurf; 
1869   Handle( Geom_Line ) aLine;
1870   BRepAdaptor_Surface tmpSurf(myCone);  
1871   TopoDS_Face aFace;
1872   AIS_KindOfSurface aSurfType;
1873   Standard_Real Offset = 0. ;
1874   Handle( Standard_Type ) aType;
1875
1876   Standard_Real maxV = tmpSurf.FirstVParameter();
1877   Standard_Real minV = tmpSurf.LastVParameter();
1878
1879   AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
1880   
1881   if ( aSurfType == AIS_KOS_Revolution ) {                                    //surface of revolution
1882
1883     aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf ); 
1884     gp_Lin ln( aRevSurf->Axis() );
1885     Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
1886     if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) )  return;        //Must be a part of line
1887
1888     Standard_Real par;
1889     gp_Pnt fst = tmpSurf.Value(0., minV);
1890     gp_Pnt lst = tmpSurf.Value(0., maxV);
1891  
1892     gp_Vec vec1(fst, lst);
1893    
1894     par = ElCLib::Parameter( ln, fst );
1895     gp_Pnt fst2 = ElCLib::Value( par, ln );                         //projection fst on ln
1896     par = ElCLib::Parameter( ln, lst );
1897     gp_Pnt lst2 = ElCLib::Value( par, ln );                         //projection lst on ln
1898
1899     gp_Vec vec2(fst2, lst2);
1900
1901    // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle ) 
1902     if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return; 
1903  
1904     gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
1905     aCone =  mkCone.Value();
1906     Apex = aCone.Apex();
1907   }
1908   else {  
1909     aType = aSurf->DynamicType();
1910     if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) {            //offset surface
1911       aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
1912       aSurf = aOffsetSurf->Surface();
1913       BRepBuilderAPI_MakeFace mkFace(aSurf, Precision::Confusion());
1914       mkFace.Build();
1915       if( !mkFace.IsDone() ) return;
1916       tmpSurf.Initialize( mkFace.Face() );
1917     }  
1918  
1919     aCone = tmpSurf.Cone();
1920     aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
1921     Apex =  aConicalSurf->Apex();
1922   }
1923
1924   Handle(Geom_Curve) aCurve;                 //A circle where the angle is drawn
1925   
1926   if ( myAutomaticPosition ) {
1927     Standard_Real midV = ( minV + maxV ) / 2.5; 
1928
1929     aCurve =   aSurf->VIso(midV);
1930     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1931
1932     myPosition = ElCLib::Value(M_PI / 2.0, myCircle);
1933     myAutomaticPosition = Standard_False;
1934   }
1935   else {
1936     Standard_Real U, V;
1937     ElSLib::Parameters(aCone, myPosition, U, V);
1938     aCurve = aSurf->VIso(V); 
1939     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1940   }
1941  //__________________________________________________________________
1942   aCurve = aSurf->VIso(maxV);
1943   gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1944   aCurve = aSurf->VIso(minV);
1945   gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1946  //__________________________________________________________________
1947
1948   if( CircVmax.Radius() < CircVmin.Radius() ) {
1949    gp_Circ tmpCirc = CircVmax;
1950    CircVmax = CircVmin;
1951    CircVmin = tmpCirc;
1952   }
1953  
1954   Standard_Boolean IsArrowOut = Standard_True;    //Is arrows inside or outside of the cone
1955   //Standard_Real PntOnMainAxis = 0;   //Is projection of aPosition inside of the cone = 0, above = 1, or below = -1
1956   Standard_Boolean IsConeTrimmed = Standard_False; 
1957
1958   if( CircVmin.Radius() > 0.01 ) IsConeTrimmed = Standard_True;
1959
1960   gp_Pnt AttachmentPnt;
1961   gp_Pnt OppositePnt;
1962   gp_Pnt aPnt, tmpPnt;
1963   Quantity_Length X,Y,Z;
1964
1965   Standard_Real param = ElCLib::Parameter(myCircle, myPosition);
1966
1967   aPnt = Apex;
1968   gp_Pnt P1 = ElCLib::Value(0., myCircle);
1969   gp_Pnt P2 = ElCLib::Value(M_PI, myCircle);
1970
1971   gce_MakePln mkPln(P1, P2,  aPnt);   // create a plane whitch defines plane for projection aPosition on it
1972
1973   aPnt =  AIS::ProjectPointOnPlane(myPosition, mkPln.Value()); 
1974   tmpPnt = aPnt;
1975
1976   if( aPnt.Distance(P1) <  aPnt.Distance(P2) ){
1977     AttachmentPnt = P1; 
1978     OppositePnt = P2; 
1979   }
1980   else {
1981     AttachmentPnt = P2; 
1982     OppositePnt = P1;
1983   }
1984   
1985   aPnt = AttachmentPnt ;                          // Creating of circle whitch defines a plane for a dimension arc
1986   gp_Vec Vec(AttachmentPnt, Apex);                // Dimension arc is a part of the circle 
1987   Vec.Scale(2);
1988   aPnt.Translate(Vec);
1989   GC_MakeCircle mkCirc(AttachmentPnt, OppositePnt,  aPnt); 
1990   gp_Circ  aCircle2 = mkCirc.Value()->Circ();
1991
1992   
1993   Standard_Integer i;
1994   Standard_Real AttParam = ElCLib::Parameter(aCircle2, AttachmentPnt);
1995   Standard_Real OppParam = ElCLib::Parameter(aCircle2, OppositePnt);
1996   
1997   while ( AttParam >= 2 * M_PI ) AttParam -= 2 * M_PI;
1998   while ( OppParam >= 2 * M_PI ) OppParam -= 2 * M_PI;
1999
2000   if( myPosition.Distance( myCircle.Location() ) <= myCircle.Radius() )
2001     if( 2 * myCircle.Radius() > aCircle2.Radius() * 0.4 ) IsArrowOut = Standard_False;  //four times more than an arrow size
2002  
2003   Graphic3d_Array1OfVertex V(1, 12);
2004   
2005   Standard_Real angle;
2006   param = ElCLib::Parameter(aCircle2, tmpPnt);
2007
2008   if(IsArrowOut) {
2009     angle = OppParam - AttParam + M_PI / 6; //An angle between AttParam and OppParam + 30 degrees
2010     param = AttParam - M_PI / 12;      //out parts of dimension line are 15 degrees
2011     
2012     while ( angle > 2 * M_PI ) angle -= 2 * M_PI;
2013     for( i = 0; i <= 11; i++ ) {       //calculating of arc             
2014       aPnt = ElCLib::Value(param + angle/11 * i, aCircle2);
2015       aPnt.Coord(X, Y, Z);
2016       V(i+1).SetCoord(X, Y, Z);    
2017     }
2018       
2019   }
2020   else {
2021     angle = OppParam - AttParam;
2022     param = AttParam;
2023     while ( angle > 2 * M_PI ) angle -= 2 * M_PI;
2024     for( i = 0; i <= 11; i++ ) {       //calculating of arc             
2025       aPnt = ElCLib::Value(param + angle/11 * i, aCircle2);
2026       aPnt.Coord(X, Y, Z);
2027       V(i+1).SetCoord(X, Y, Z);
2028     }
2029   }
2030   
2031   for(i = 1; i<=11; i++) {
2032
2033     V(i).Coord(X, Y, Z);
2034     P1.SetCoord(X, Y, Z);
2035     V(i+1).Coord(X, Y, Z);
2036     P1.SetCoord(X, Y, Z);
2037
2038     seg = new Select3D_SensitiveSegment(owner, P1, P2);
2039     aSelection->Add(seg);   
2040   }
2041
2042   tmpPnt =  tmpPnt.Translated(gp_Vec(0, 0, -1)*2);
2043
2044   Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
2045   Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( owner,
2046                                                                    tmpPnt.X(),
2047                                                                    tmpPnt.Y(),
2048                                                                    tmpPnt.Z(),
2049                                                                    tmpPnt.X() + size,
2050                                                                    tmpPnt.Y() + size,
2051                                                                    tmpPnt.Z() + size);
2052   aSelection->Add(box);
2053 }
2054
2055
2056