0023634: Eliminate Polyline and Polygon usage in drawers
[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 //=======================================================================
476 //function : Compute
477 //purpose  : : to avoid warning
478 //=======================================================================
479
480 void AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager2d, 
481                                  const Handle(Graphic2d_GraphicObject)& aGraphicObject, 
482                                  const Standard_Integer anInteger)
483 {
484 // Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager2d)&,const Handle(Graphic2d_GraphicObject)&,const Standard_Integer)");
485  PrsMgr_PresentableObject::Compute( aPresentationManager2d ,aGraphicObject,anInteger) ;
486 }
487
488 void AIS_AngleDimension::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
489 {
490 // Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
491  PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
492 }
493
494 //=======================================================================
495 //function : ComputeSelection
496 //purpose  : 
497 //=======================================================================
498
499 void AIS_AngleDimension::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
500                                           const Standard_Integer)
501 {
502
503   if ( myNbShape == 1 ) 
504     {
505     // cout << "Computing selection for cone's angle "   << endl;
506      ComputeConeAngleSelection(aSelection);
507      return;
508     }
509
510
511   if (myFShape.IsNull()) return;
512
513   if (myFShape.ShapeType() == TopAbs_FACE )
514     Compute3DSelection(aSelection);
515   else
516     Compute2DSelection(aSelection);
517
518   // Text
519   Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
520   Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
521   Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
522                                                                    myPosition.X(),
523                                                                    myPosition.Y(),
524                                                                    myPosition.Z(),
525                                                                    myPosition.X() + size,
526                                                                    myPosition.Y() + size,
527                                                                    myPosition.Z() + size);
528   aSelection->Add(box);
529 }
530
531 //=======================================================================
532 //function : ComputeConeAngle
533 //purpose  : 
534 //=======================================================================
535
536 void AIS_AngleDimension::ComputeConeAngle(const Handle(Prs3d_Presentation)& aPresentation)
537 {
538   if( myCone.IsNull() ) return;
539   
540   gp_Pln aPln;
541   gp_Cone aCone;
542   gp_Circ myCircle;
543   gp_Pnt Apex;
544   Handle( Geom_Surface ) aSurf;         //a surface from the Face
545   Handle( Geom_OffsetSurface ) aOffsetSurf; 
546   Handle( Geom_ConicalSurface ) aConicalSurf;
547   Handle( Geom_SurfaceOfRevolution ) aRevSurf; 
548   Handle( Geom_Line ) aLine;
549   BRepAdaptor_Surface tmpSurf(myCone);  
550   TopoDS_Face aFace;
551   AIS_KindOfSurface aSurfType;
552   Standard_Real Offset = 0. ;
553   Handle( Standard_Type ) aType;
554
555   Standard_Real maxV = tmpSurf.FirstVParameter();
556   Standard_Real minV = tmpSurf.LastVParameter();
557
558
559  AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
560
561  if ( aSurfType == AIS_KOS_Revolution ) {                                    //surface of revolution
562
563    aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf ); 
564    gp_Lin ln( aRevSurf->Axis() );
565    Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
566    if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) )  return;        //Must be a part of line
567
568    Standard_Real par;
569    gp_Pnt fst = tmpSurf.Value(0., minV);
570    gp_Pnt lst = tmpSurf.Value(0., maxV);
571  
572    gp_Vec vec1(fst, lst);
573    
574    par = ElCLib::Parameter( ln, fst );
575    gp_Pnt fst2 = ElCLib::Value( par, ln );                         //projection fst on ln
576    par = ElCLib::Parameter( ln, lst );
577    gp_Pnt lst2 = ElCLib::Value( par, ln );                         //projection lst on ln
578
579    gp_Vec vec2(fst2, lst2);
580
581    // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle ) 
582   if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return; 
583  
584   gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
585   aCone =  mkCone.Value();
586   Apex = aCone.Apex();
587  }
588  else {  
589    aType = aSurf->DynamicType();
590    if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) {            //offset surface
591      aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
592      aSurf = aOffsetSurf->Surface();
593      BRepBuilderAPI_MakeFace mkFace(aSurf, Precision::Confusion());
594      mkFace.Build();
595      if( !mkFace.IsDone() ) return;
596      tmpSurf.Initialize( mkFace.Face() );
597    }  
598  
599    aCone = tmpSurf.Cone();
600    aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
601    Apex =  aConicalSurf->Apex();
602  }
603  
604    Handle(Geom_Curve) aCurve;                 //A circle where the angle is drawn
605    if ( myAutomaticPosition ) {
606     Standard_Real midV = ( minV + maxV ) / 2.5; 
607
608     aCurve =   aSurf->VIso(midV);
609     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
610
611     myPosition = ElCLib::Value(M_PI / 2.0, myCircle);
612     myAutomaticPosition = Standard_False;
613   }
614   else {
615     Standard_Real U, V;
616     ElSLib::Parameters(aCone, myPosition, U, V);
617     aCurve = aSurf->VIso(V); 
618     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
619   }
620   
621  //__________________________________________________________________
622   aCurve = aSurf->VIso(maxV);
623   gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
624   aCurve = aSurf->VIso(minV);
625   gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
626  //__________________________________________________________________
627
628   if( CircVmax.Radius() < CircVmin.Radius() ) {
629    gp_Circ tmpCirc = CircVmax;
630    CircVmax = CircVmin;
631    CircVmin = tmpCirc;
632   }
633
634   DsgPrs_AnglePresentation::Add(aPresentation, myDrawer, myVal, 
635                                 myText, myCircle, myPosition, Apex, CircVmin, CircVmax, myArrowSize);
636 // cout << "ComputeConeAngle is over"   << endl;                                
637 }
638
639
640 //=======================================================================
641 //function : ComputeTwoFacesAngle
642 //purpose  : 
643 //=======================================================================
644
645 void AIS_AngleDimension::ComputeTwoFacesAngle(const Handle(Prs3d_Presentation)& aPresentation)
646 {
647   if (myFirstSurfType == AIS_KOS_Plane)
648     ComputeTwoPlanarFacesAngle( aPresentation );
649   else
650     ComputeTwoCurvilinearFacesAngle( aPresentation );
651 }
652
653 //=======================================================================
654 //function : ComputeTwoCurvilinearFacesAngle
655 //purpose  : 
656 //=======================================================================
657
658 void AIS_AngleDimension::ComputeTwoCurvilinearFacesAngle(const Handle(Prs3d_Presentation)& aPresentation) 
659 {
660   AIS::ComputeAngleBetweenCurvilinearFaces( TopoDS::Face( myFShape ),
661                                             TopoDS::Face( mySShape ),
662                                             myFirstBasisSurf,
663                                             mySecondBasisSurf,
664                                             myFirstSurfType,
665                                             mySecondSurfType,
666                                             myAxis,
667                                             myVal,
668                                             myAutomaticPosition,
669                                             myPosition,
670                                             myCenter,
671                                             myFAttach,
672                                             mySAttach,
673                                             myFDir,
674                                             mySDir,
675                                             myPlane );
676   if (myAutomaticPosition && myIsSetBndBox)
677     myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
678
679   Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
680   Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
681 #ifdef BUC60915
682   if( !myArrowSizeIsDefined ) {
683 #endif
684     Standard_Real arrsize = myCenter.Distance( myPosition );
685       
686     if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
687     if (arrsize == 0.) arrsize = 1.;
688 #ifdef BUC60915
689     myArrowSize = arrsize;
690   }
691   arr->SetLength( myArrowSize );
692 #else
693   arr->SetLength(arrsize);
694 #endif
695       
696
697   if (myVal <= Precision::Angular() || Abs( M_PI-myVal ) <= Precision::Angular())
698     DsgPrs_AnglePresentation::Add(aPresentation,
699                                   myDrawer,
700                                   myVal,
701                                   myText,
702                                   myCenter,
703                                   myFAttach,
704                                   mySAttach,
705                                   myFDir,
706                                   mySDir,
707                                   myPlane->Pln().Axis().Direction(),
708                                   Standard_False, // not plane
709                                   myAxis,
710                                   myPosition,
711                                   mySymbolPrs);
712   else
713     DsgPrs_AnglePresentation::Add(aPresentation,
714                                   myDrawer,
715                                   myVal,
716                                   myText,
717                                   myCenter,
718                                   myFAttach,
719                                   mySAttach,
720                                   myFDir,
721                                   mySDir,
722                                   myFDir ^ mySDir,
723                                   Standard_False, // not plane
724                                   myAxis,
725                                   myPosition,
726                                   mySymbolPrs);
727 }
728
729 //=======================================================================
730 //function : ComputeTwoPlanarFacesAngle
731 //purpose  : 
732 //=======================================================================
733
734 void AIS_AngleDimension::ComputeTwoPlanarFacesAngle( const Handle( Prs3d_Presentation )& aPresentation )
735 {
736   AIS::ComputeAngleBetweenPlanarFaces( TopoDS::Face( myFShape ),
737                                        TopoDS::Face( mySShape ),
738                                        mySecondBasisSurf,
739                                        myAxis,
740                                        myVal,
741                                        myAutomaticPosition,
742                                        myPosition,
743                                        myCenter,
744                                        myFAttach,
745                                        mySAttach,
746                                        myFDir,
747                                        mySDir );
748   if (myAutomaticPosition && myIsSetBndBox)
749     myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
750
751   Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
752   Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
753 #ifdef BUC60915
754   if( !myArrowSizeIsDefined ) {
755 #endif
756     Standard_Real arrsize = myCenter.Distance( myPosition );
757       
758     if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
759     if (arrsize == 0.) arrsize = 1.;
760 #ifdef BUC60915
761     myArrowSize = arrsize;
762   }
763   arr->SetLength( myArrowSize );
764 #else
765   arr->SetLength(arrsize);
766 #endif
767       
768
769   DsgPrs_AnglePresentation::Add(aPresentation,
770                                 myDrawer,
771                                 myVal,
772                                 myText,
773                                 myCenter,
774                                 myFAttach,
775                                 mySAttach,
776                                 myFDir,
777                                 mySDir,
778                                 myAxis.Direction(),
779                                 Standard_True,
780                                 myAxis,
781                                 myPosition,
782                                 mySymbolPrs);
783      
784 }
785
786 //=======================================================================
787 //function : ComputeTwoEdgesAngle
788 //purpose  : 
789 //=======================================================================
790
791 void AIS_AngleDimension::ComputeTwoEdgesAngle(const Handle(Prs3d_Presentation)& aPresentation)
792 {
793   BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
794   BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
795   if ((cu1.GetType() != GeomAbs_Line) || (cu2.GetType() != GeomAbs_Line)) return;
796
797   // current face
798   BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
799   TopoDS_Face face(makeface.Face());  
800   BRepAdaptor_Surface adp(makeface.Face());
801     
802   // 3d lines
803   Handle(Geom_Line) geom_lin1,geom_lin2;
804   gp_Pnt ptat11,ptat12,ptat21,ptat22;//,pint3d;
805   Standard_Boolean isInfinite1,isInfinite2;
806   Handle(Geom_Curve) extCurv;
807   Standard_Integer copyOfMyExtShape = myExtShape;
808   if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
809                             TopoDS::Edge(mySShape),
810                             myExtShape,
811                             geom_lin1,
812                             geom_lin2,
813                             ptat11,
814                             ptat12,
815                             ptat21,
816                             ptat22,
817                             extCurv,
818                             isInfinite1,
819                             isInfinite2,
820                             myPlane)) {
821     return;
822   }
823   // Temporary: computation of myVal
824   //  myVal = Abs(geom_lin1->Lin().Angle( geom_lin2->Lin())); // Pb with angles JPR
825
826   if (copyOfMyExtShape != 0) myExtShape = copyOfMyExtShape;  
827
828   // 2d lines => projection of 3d on current plane
829
830 //POP pour NT
831   Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(geom_lin1,myPlane->Pln());
832   Handle(Geom2d_Line) lin1_2d = *((Handle(Geom2d_Line)*)& geoC1);
833   Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(geom_lin2,myPlane->Pln());
834   Handle(Geom2d_Line) lin2_2d = *((Handle(Geom2d_Line)*)& geoC2);
835
836 #ifdef BUC60915
837   if( !myArrowSizeIsDefined ) {
838 #endif
839     Standard_Real arrSize1(myArrowSize),arrSize2(myArrowSize);
840     if (!isInfinite1) arrSize1 = ptat11.Distance(ptat12)/100.;
841     if (!isInfinite2) arrSize2 = ptat21.Distance(ptat22)/100.;
842 #ifdef BUC60655
843     myArrowSize = Min(myArrowSize,Max(arrSize1,arrSize2));
844 #else
845     myArrowSize = Min(myArrowSize,Min(arrSize1,arrSize2));
846 #endif
847 #ifdef BUC60915
848   }
849 #endif
850
851
852   // Processing in  case of 2 parallel straight lines
853   if (lin1_2d->Lin2d().Direction()
854       .IsParallel(lin2_2d->Lin2d().Direction(),Precision::Angular())) {    
855     ComputeTwoEdgesNullAngle(aPresentation,
856                              geom_lin1,
857                              geom_lin2,
858                              ptat11,ptat12,
859                              ptat21,ptat22,
860                              isInfinite1,isInfinite2);
861   }
862   
863   // Processing in case of 2 non-parallel straight lines
864   else {
865     ComputeTwoEdgesNotNullAngle(aPresentation,
866                                 geom_lin1,
867                                 geom_lin2,
868                                 ptat11,
869                                 ptat12,
870                                 ptat21,
871                                 ptat22,
872                                 isInfinite1,isInfinite2);
873   }
874   if ( (myExtShape != 0) &&  !extCurv.IsNull()) {
875     gp_Pnt pf, pl;
876     if ( myExtShape == 1 ) {
877       if (!isInfinite1) {
878         pf = ptat11; 
879         pl = ptat12;
880       }
881       aPresentation->SetInfiniteState(isInfinite1);
882       ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(myFShape),geom_lin1,pf,pl);
883     }
884     else {
885       if (!isInfinite2) {
886         pf = ptat21; 
887         pl = ptat22;
888       }
889       aPresentation->SetInfiniteState(isInfinite2);
890       ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(mySShape),geom_lin2,pf,pl);
891     }
892   }
893 }
894
895
896 //=======================================================================
897 //function : ComputeTwoEdgesNotNullAngle
898 //purpose  : 
899 //=======================================================================
900
901 void AIS_AngleDimension::ComputeTwoEdgesNotNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
902                                                      const Handle(Geom_Line)& l1,
903                                                      const Handle(Geom_Line)& l2,
904                                                      const gp_Pnt& ptat11,
905                                                      const gp_Pnt& ptat12,
906                                                      const gp_Pnt& ptat21,
907                                                      const gp_Pnt& ptat22,
908                                                      const Standard_Boolean isInfinite1,
909                                                      const Standard_Boolean isInfinite2)
910 {
911   // current face
912   BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
913   TopoDS_Face face(makeface.Face());  
914   BRepAdaptor_Surface adp(makeface.Face());
915   // 2d lines => projection of 3d on current plane
916   Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
917   const Handle(Geom2d_Line)& l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
918   Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
919   const Handle(Geom2d_Line)& l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
920
921   //----------------------------------------------------------
922   //          Computation of myCenter
923   //----------------------------------------------------------
924   IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),l2_2d->Lin2d());
925   if (!inter.IsDone()) return;
926   if (!inter.NbPoints()) return;
927   
928   gp_Pnt2d pint(inter.Point(1).Value());
929   myCenter = adp.Value(pint.X(),pint.Y());
930
931   //----------------------------------------------------------
932   //         Computation of the 2 directions
933   //----------------------------------------------------------
934   gp_Dir d1,d2;
935   if (!isInfinite1) {
936     if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
937     else d1 = gp_Dir(gp_Vec(myCenter,ptat12));  
938   }
939   else d1 = l1->Lin().Direction();
940
941   if (!isInfinite2) {
942     if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
943     else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
944   }
945   else d2 = l2->Lin().Direction();
946   if (!isInfinite1) {
947     Standard_Boolean In1(Standard_False);
948     Standard_Boolean In2(Standard_False);
949     if ( !(Abs(d1.Angle(d2) - Abs(myVal)) <= Precision::Confusion())
950          &&  (Abs(myVal) <  M_PI) ) {
951       Standard_Real parcent1 = ElCLib::Parameter(l1->Lin(), myCenter);
952       Standard_Real par11 = ElCLib::Parameter(l1->Lin(), ptat11);
953       Standard_Real par12 = ElCLib::Parameter(l1->Lin(), ptat12);
954       if ( par11 < par12) {
955         if ( ( parcent1> par11) && (parcent1< par12)) {
956           In1 = Standard_True;
957           d1.Reverse();
958         }
959       }
960       else {
961       if ( ( parcent1> par12) && (parcent1< par11)) {
962         In1 = Standard_True;
963         d1.Reverse();
964       }
965       }
966       if ( !In1) {
967         In2 = Standard_True;
968         d2.Reverse();
969       }
970     }
971   }
972
973   myFDir = d1;
974   mySDir = d2;
975   gp_Lin theaxis;
976   gp_Lin gpl1 = l1->Lin();
977   gp_Lin gpl2 = l2->Lin();
978   theaxis = gp_Lin(myCenter,myFDir^mySDir);
979
980   if (myVal >  M_PI) {
981     theaxis.Reverse();
982   }
983   
984   gp_Pnt curpos;  
985   TColStd_Array1OfReal tabdist(1,4);
986   if (!isInfinite1) { 
987     tabdist(1) = theaxis.Distance(ptat11);
988     tabdist(2) = theaxis.Distance(ptat12);
989   }
990   else {
991     tabdist(1) = tabdist(2) = 0.;
992   }
993
994   if (!isInfinite2) { 
995     tabdist(3) = theaxis.Distance(ptat21);
996     tabdist(4) = theaxis.Distance(ptat22);
997   }
998   else {
999     tabdist(3) = tabdist(4) = 0.;
1000   }
1001
1002   if (myAutomaticPosition) {
1003     Standard_Real length_1(RealLast());
1004     if (!isInfinite1) length_1 = .75*Abs(tabdist(2)-tabdist(1))+Min(tabdist(1),tabdist(2));
1005
1006     Standard_Real length_2(RealLast());
1007     if (!isInfinite2) length_2 = .75*Abs(tabdist(4)-tabdist(3))+Min(tabdist(3),tabdist(4));
1008     Standard_Real theLength(Min(length_1,length_2));
1009     if (Precision::IsInfinite(theLength)) theLength = 50.;
1010
1011     myFAttach = myCenter.Translated(gp_Vec(d1)*theLength);
1012     mySAttach = myCenter.Translated(gp_Vec(d2)*theLength);
1013        
1014     if (!isInfinite1) {
1015       Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,myFAttach));
1016       Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
1017       Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
1018       if (par_p1_attach > par11 && par_p1_attach > par12) {
1019         par_p1_attach = Max(par11,par12);
1020         myFAttach = ElCLib::Value(par_p1_attach,gpl1);
1021       }
1022       else if (par_p1_attach < par11 && par_p1_attach < par12) {
1023         par_p1_attach = Min(par11,par12);
1024         myFAttach = ElCLib::Value(par_p1_attach,gpl1);
1025       }
1026     }
1027
1028     if (!isInfinite2) {
1029       Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,mySAttach));
1030       Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
1031       Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
1032       if (par_p2_attach > par21 && par_p2_attach > par22) {
1033         par_p2_attach = Max(par21,par22);
1034         mySAttach = ElCLib::Value(par_p2_attach,gpl2);
1035       }
1036       else if (par_p2_attach < par21 && par_p2_attach < par22) {
1037         par_p2_attach = Min(par21,par22);
1038         mySAttach = ElCLib::Value(par_p2_attach,gpl2);
1039       }
1040     }
1041     if ( myVal < M_PI) curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ())); 
1042     else {
1043       curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ())); 
1044       gp_Vec transl(curpos, myCenter);
1045       transl*= 2;
1046       curpos.Translate(transl);
1047     }
1048
1049     gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
1050     gp_Circ circle(ax,theLength);
1051     Standard_Real par = ElCLib::Parameter(circle,curpos);
1052     curpos = ElCLib::Value(par,circle);    
1053
1054     // small offset like in LengthDimension
1055     gp_Vec transl(myCenter, curpos);
1056     transl*= 0.3;
1057     curpos.Translate(transl);
1058     
1059     if (myIsSetBndBox)
1060       curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
1061
1062     myPosition = curpos;
1063     myAutomaticPosition = Standard_True;      
1064   }
1065
1066   else {
1067   // point is projected on the plane
1068     gp_Pnt2d pointOnPln(ProjLib::Project(myPlane->Pln(),myPosition));
1069     myPosition = BRepAdaptor_Surface(BRepBuilderAPI_MakeFace(myPlane->Pln()).Face()).Value(pointOnPln.X(),pointOnPln.Y());
1070     curpos = myPosition;
1071     Standard_Real dist(curpos.Distance(myCenter));    
1072     if (dist<=Precision::Confusion()) {
1073       gp_XYZ delta(1.,1.,1.);
1074       curpos.SetXYZ(curpos.XYZ()+delta);
1075       dist = curpos.Distance(myCenter);
1076     }
1077     // To learn if it is necessary to take distance -dist or not
1078     // it is necessary to know if we are in the sector opposite to the angle
1079     // if not : we are in the opposite sector if the coordinates
1080     // of curpos in point (d1,d2) are negative
1081     gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
1082     gp_Circ circle(ax,dist);
1083 #ifdef DEB
1084 //    gp_Pnt p1(myCenter.Translated(gp_Vec(d1)*dist));
1085 #endif
1086     gp_Pnt p2(myCenter.Translated(gp_Vec(d2)*dist));
1087     Standard_Real uc1 = 0;
1088     Standard_Real uc2 = ElCLib::Parameter(circle, p2 );
1089     Standard_Real uco = ElCLib::Parameter(circle, curpos );
1090     Standard_Real udeb = uc1;
1091     Standard_Real ufin = uc2;
1092     if (uco > ufin) {
1093       if (Abs(myVal)<M_PI) {
1094         // test if uco is in the opposite sector 
1095         if (uco > udeb+M_PI && uco < ufin+M_PI){
1096           dist = -dist;
1097         }
1098       }
1099     }
1100
1101      gp_Pnt p1_attach(myCenter.Translated(gp_Vec(d1)*dist));
1102      gp_Pnt p2_attach(myCenter.Translated(gp_Vec(d2)*dist));
1103     
1104      if (!isInfinite1) {
1105        Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,p1_attach));
1106        Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
1107        Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
1108        if (par_p1_attach > par11 && par_p1_attach > par12) {
1109          par_p1_attach = Max(par11,par12);
1110          p1_attach = ElCLib::Value(par_p1_attach,gpl1);
1111        }
1112        else if (par_p1_attach < par11 && par_p1_attach < par12) {
1113          par_p1_attach = Min(par11,par12);
1114          p1_attach = ElCLib::Value(par_p1_attach,gpl1);
1115        }
1116      }
1117      myFAttach = p1_attach;
1118             
1119      if (!isInfinite2) {
1120        Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,p2_attach));
1121        Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
1122        Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
1123        if (par_p2_attach > par21 && par_p2_attach > par22) {
1124          par_p2_attach = Max(par21,par22);
1125          p2_attach = ElCLib::Value(par_p2_attach,gpl2);
1126        }
1127        else if (par_p2_attach < par21 && par_p2_attach < par22) {
1128          par_p2_attach = Min(par21,par22);
1129          p2_attach = ElCLib::Value(par_p2_attach,gpl2);
1130        }
1131      }
1132      mySAttach = p2_attach;
1133   }  
1134   myAxis = theaxis.Position();
1135
1136   //--------------------------------------------------------
1137   //    Computation of the presentation
1138   //--------------------------------------------------------
1139   Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
1140   Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
1141
1142   arr->SetLength(myArrowSize);
1143
1144   DsgPrs_AnglePresentation::Add(aPresentation,
1145                                 myDrawer,
1146                                 myVal,
1147                                 myText,
1148                                 myCenter,
1149                                 myFAttach,
1150                                 mySAttach,
1151                                 myFDir,
1152                                 mySDir,
1153                                 curpos,
1154                                 mySymbolPrs);
1155 }
1156
1157
1158
1159 //=======================================================================
1160 //function : ComputeTwoEdgesNullAngle
1161 //purpose  : compute the presentation of a angle dimension if it's null.
1162 //             -> the aim of the computation is to have a constant radius 
1163 //                during the dimension moving : the radius is independant
1164 //                of the cursor position, it's equal to a arbitrary value
1165 //=======================================================================
1166
1167 void AIS_AngleDimension::ComputeTwoEdgesNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
1168                                                   const Handle(Geom_Line)& l1,
1169                                                   const Handle(Geom_Line)& l2,
1170                                                   const gp_Pnt& ptat11,
1171                                                   const gp_Pnt& ptat12,
1172                                                   const gp_Pnt& ptat21,
1173                                                   const gp_Pnt& ptat22,
1174                                                   const Standard_Boolean isInfinite1,
1175                                                   const Standard_Boolean isInfinite2)
1176 {
1177   // current face
1178   BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
1179   TopoDS_Face face(makeface.Face());  
1180   BRepAdaptor_Surface adp(makeface.Face());
1181   // 2d lines => projection of 3d on current plane
1182   Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
1183   Handle(Geom2d_Line) l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
1184   Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
1185   Handle(Geom2d_Line) l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
1186
1187   gp_Lin gpl1 = l1->Lin();
1188   gp_Lin gpl2 = l2->Lin();
1189
1190   //------------------------------------------------------------
1191   //                Computation of myCenter
1192   // -> Point located on the median of 2 straight lines,
1193   //    is calculated as located between 2 closest points 
1194   //    of each straight line.
1195   //-----------------------------------------------------------
1196      //   theLength : radius of the future circle
1197   Standard_Real theLength = gpl1.Distance(gpl2.Location());
1198   // processing of the particular case when 2 straight lines are coincident
1199   Standard_Boolean SameLines(Standard_False);
1200   if ( theLength <= Precision::Confusion()) {
1201     SameLines = Standard_True;
1202     if (!isInfinite1) {
1203       if (!isInfinite2) theLength = 0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1204       else theLength = 0.75*ptat11.Distance(ptat12);
1205     }
1206     else {
1207       if (!isInfinite2) theLength = 0.75*ptat21.Distance(ptat22);
1208       else theLength = 50.;
1209     }
1210   }
1211   else theLength = theLength*8/10;
1212
1213   gp_Pnt pmin1 ,pmin2;
1214   if (!isInfinite1 && !isInfinite2) {
1215     pmin1 = ptat11; pmin2 = ptat21;
1216     Standard_Real dis = ptat11.Distance(ptat21);
1217     Standard_Real dis2 = ptat11.Distance(ptat22);
1218     if ( dis2 < dis)  {
1219       pmin1 = ptat11;
1220       pmin2 = ptat22;
1221       dis = dis2;
1222     }
1223     dis2 = ptat12.Distance(ptat22);
1224     if ( dis2 < dis)  {
1225       pmin1 = ptat12;
1226       pmin2 = ptat22;
1227       dis = dis2;
1228     }
1229     dis2 = ptat12.Distance(ptat21);
1230     if ( dis2 < dis)  {
1231       pmin1 = ptat12;
1232       pmin2 = ptat21;
1233       dis = dis2;
1234     }
1235     myCenter.SetXYZ( (pmin1.XYZ() + pmin2.XYZ()) / 2. );
1236   }
1237   else {
1238     gp_Pnt pntOnl1 = gpl1.Location();
1239     gp_Pnt pntOnl2 = ElCLib::Value(ElCLib::Parameter(gpl1,pntOnl1),gpl2);
1240     myCenter.SetXYZ( (pntOnl1.XYZ() + pntOnl2.XYZ()) / 2. );
1241   }
1242
1243   
1244   // directions 
1245   gp_Dir d1,d2;
1246   if (!isInfinite1) {
1247     if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
1248     else d1 = gp_Dir(gp_Vec(myCenter,ptat12));  
1249   }
1250   else d1 = gpl1.Direction();
1251   
1252   if (!isInfinite2) {
1253     if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
1254     else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
1255   }
1256   else d2 = gpl2.Direction();  
1257
1258   gp_Dir theaxis;
1259   if ( SameLines ) theaxis = myPlane->Pln().Axis().Direction();
1260   else {
1261     theaxis = gp_Dir(d1^d2);
1262     gp_Vec V1(d1); gp_Vec V2(d2);
1263     if ( V1.CrossMagnitude(V2) < 0 ) theaxis.Reverse();
1264   }
1265
1266   gp_Pnt curpos; // cursor position
1267   TColStd_Array1OfReal tabdist(1,4);
1268   gp_Pnt P1, P2; // points at intersection of the circle with 2 straight lines
1269  
1270   if (myAutomaticPosition) {
1271     if (!isInfinite1) {
1272       tabdist(1) = myCenter.Distance(ptat11);
1273       tabdist(2) = myCenter.Distance(ptat12);
1274     }
1275     else {
1276       tabdist(1) = tabdist(2) = 0.;
1277     }
1278     if (!isInfinite2) { 
1279       tabdist(3) = myCenter.Distance(ptat21);
1280       tabdist(4) = myCenter.Distance(ptat22);
1281     }
1282     else {
1283       tabdist(3) = tabdist(4) = 0.;
1284     }
1285     if ( SameLines ) {
1286       Standard_Real dist1(RealLast());
1287       if (!isInfinite1) dist1 = Max(tabdist(1),tabdist(2));
1288       Standard_Real dist2(RealLast());
1289       if (!isInfinite2) dist2 = Max(tabdist(3),tabdist(4));      
1290       
1291       myFAttach = myCenter;
1292       mySAttach = myCenter;
1293       P1 = myFAttach;
1294       P2 = mySAttach;
1295
1296       myCenter.Translate(gp_Vec(d1)*theLength);
1297
1298       // calculate attachments of the face 
1299       //  -> they are points of intersection if  
1300       //     intersection is outside of the edges
1301       Standard_Real pparam = ElCLib::Parameter(gpl1,myFAttach);
1302       Standard_Real pparam1 = ElCLib::Parameter(gpl1,ptat11);
1303       Standard_Real pparam2 = ElCLib::Parameter(gpl1,ptat12);
1304       if (!isInfinite1) {
1305         if ( pparam1 < pparam2 ) {
1306           if ( pparam < pparam1 ) myFAttach = ptat11;
1307           else if ( pparam > pparam2) myFAttach = ptat12;
1308         }
1309         else {
1310           if ( pparam < pparam2) myFAttach = ptat12;
1311           else if ( pparam > pparam1) myFAttach = ptat11;
1312         }
1313       }
1314       if (!isInfinite2) {
1315         pparam = ElCLib::Parameter(gpl2,myFAttach);
1316         pparam1 = ElCLib::Parameter(gpl2,ptat21);
1317         pparam2 = ElCLib::Parameter(gpl2,ptat22);
1318         if ( pparam1 < pparam2 ) {
1319           if ( pparam < pparam1 ) mySAttach = ptat21;
1320           else if ( pparam > pparam2) mySAttach = ptat22;
1321         }
1322         else {
1323           if ( pparam < pparam2) mySAttach = ptat22;
1324           else if ( pparam > pparam1) mySAttach = ptat21;
1325         }
1326       }
1327     }
1328     // Case of disconneted lines
1329     else {
1330       gp_Ax2 AX(myCenter,theaxis,d1);
1331       Handle(Geom_Circle)  circle = new Geom_Circle(AX,theLength);
1332       Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
1333       Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
1334       // calculate the intersection of circle with l1
1335       Standard_Real pparam; // parameter of the point of intersection on l1
1336       IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
1337       gp_Pnt2d pint1(inter.Point(1).Value());
1338       gp_Pnt2d pint2(inter.Point(2).Value());
1339       
1340       gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
1341       gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
1342       gp_Dir I1I2(gp_Vec(Int1,Int2));
1343       if ( d1*I1I2 > 0 ) {
1344         myFAttach = Int2;
1345         pparam = inter.Point(2).ParamOnFirst();
1346       }
1347       else {
1348         myFAttach = Int1;
1349         pparam = inter.Point(1).ParamOnFirst();
1350       }
1351       P1 = myFAttach;
1352
1353       Standard_Real pparam1;
1354       Standard_Real pparam2; 
1355       if (!isInfinite1) {
1356         pparam1 = ElCLib::Parameter(gpl1,ptat11);
1357         pparam2 = ElCLib::Parameter(gpl1,ptat12);       
1358         if ( pparam1 < pparam2 ) {
1359           if ( pparam < pparam1 ) myFAttach = ptat11;
1360           else if ( pparam > pparam2) myFAttach = ptat12;
1361         }
1362         else {
1363           if ( pparam < pparam2) myFAttach = ptat12;
1364           else if ( pparam > pparam1) myFAttach = ptat11;
1365         }
1366       }
1367       pparam = ElCLib::Parameter(gpl2,P1);
1368       mySAttach = ElCLib::Value(pparam, gpl2);
1369       P2 = mySAttach;
1370
1371       if (!isInfinite2) {
1372         pparam1 = ElCLib::Parameter(gpl2,ptat21);
1373         pparam2 = ElCLib::Parameter(gpl2,ptat22);
1374         if ( pparam1 < pparam2 ) {
1375           if ( pparam < pparam1 ) mySAttach = ptat21;
1376           else if ( pparam > pparam2) mySAttach = ptat22;
1377         }
1378         else {
1379           if ( pparam < pparam2) mySAttach = ptat22;
1380           else if ( pparam > pparam1) mySAttach = ptat21;
1381         }
1382       }
1383     }
1384     curpos.SetXYZ(.5*(P1.XYZ()+P2.XYZ()));
1385
1386     gp_Ax2 ax(myCenter,theaxis,d1);
1387     gp_Circ circle(ax,theLength);
1388     Standard_Real par = ElCLib::Parameter(circle,curpos);
1389     curpos = ElCLib::Value(par,circle);
1390
1391     if (myIsSetBndBox)
1392       curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
1393     myPosition =curpos;
1394     myAutomaticPosition = Standard_True;      
1395   }
1396   else {
1397     curpos = myPosition;
1398     gp_Lin Media(myCenter, gpl1.Direction());
1399     Standard_Real pcurpos = ElCLib::Parameter(Media, curpos);
1400     myCenter =  ElCLib::Value(pcurpos, Media);
1401     // the centre is translated to avoid a constant radius!
1402     myCenter.Translate(-theLength*gp_Vec(gpl1.Direction()));
1403     gp_Ax2 AX(myCenter,theaxis,gpl1.Direction());
1404     Handle(Geom_Circle)  circle = new Geom_Circle(AX,theLength);
1405
1406     // re-update curpos
1407     pcurpos = ElCLib::Parameter(circle->Circ(), curpos);
1408     curpos = ElCLib::Value(pcurpos, circle->Circ());
1409
1410     Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
1411     Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
1412     // calculate the point of intersection of circle with l1
1413     IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
1414     gp_Pnt2d pint1(inter.Point(1).Value());
1415     gp_Pnt2d pint2(inter.Point(2).Value());
1416     gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
1417     gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
1418     if ( curpos.SquareDistance(Int1) < curpos.SquareDistance(Int2)) myFAttach = Int1;
1419     else myFAttach = Int2;
1420     P1 = myFAttach;
1421     
1422     // calculate the point of intersection of circle with l2
1423     // -> this is the projection because the centre of circle
1424     //    is in the middle of l1 and l2
1425     Standard_Real pparam = ElCLib::Parameter(gpl2,myFAttach);
1426     mySAttach = ElCLib::Value(pparam, gpl2);
1427
1428     P2 = mySAttach;
1429
1430     Standard_Real par_attach(ElCLib::Parameter(gpl1,myFAttach));
1431     Standard_Real par1,par2; 
1432     if (!isInfinite1) {
1433       par1 = ElCLib::Parameter(gpl1,ptat11);
1434       par2 = ElCLib::Parameter(gpl1,ptat12);
1435       if (par1 < par2) {
1436         if ( par_attach < par1 ) myFAttach = ptat11;
1437         else if ( par_attach > par2) myFAttach = ptat12;
1438       }
1439       else {
1440         if ( par_attach < par2 ) myFAttach = ptat12;
1441         else if ( par_attach > par1) myFAttach = ptat11;
1442       }
1443     }
1444     par_attach = ElCLib::Parameter(gpl2,mySAttach);
1445     if (!isInfinite2) {
1446       par1 = ElCLib::Parameter(gpl2,ptat21);
1447       par2 = ElCLib::Parameter(gpl2,ptat22);
1448       if (par1 < par2) {
1449         if ( par_attach < par1 ) mySAttach = ptat21;
1450         else if ( par_attach > par2) mySAttach = ptat22;
1451       }
1452       else {
1453         if ( par_attach < par2 ) mySAttach = ptat22;
1454         else if ( par_attach > par1) mySAttach = ptat21;
1455       }
1456     }
1457   }
1458
1459   myFDir = gp_Dir(gp_Vec(myCenter,P1));
1460   mySDir = gp_Dir(gp_Vec(myCenter,P2));
1461
1462   //--------------------------------------------------------
1463   //    Computation of the presentation
1464   //--------------------------------------------------------
1465   Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
1466   Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
1467
1468   arr->SetLength(myArrowSize);
1469
1470   if (SameLines)
1471     DsgPrs_AnglePresentation::Add(aPresentation,
1472                                   myDrawer,
1473                                   myVal,
1474                                   myText,
1475                                   myCenter,
1476                                   myFAttach,
1477                                   mySAttach,
1478                                   myFDir,
1479                                   mySDir,
1480                                   theaxis,
1481                                   Standard_True,
1482                                   myAxis,
1483                                   curpos,
1484                                   DsgPrs_AS_NONE);
1485   else
1486     DsgPrs_AnglePresentation::Add(aPresentation,
1487                                   myDrawer,
1488                                   myVal,
1489                                   myText,
1490                                   myCenter,
1491                                   myFAttach,
1492                                   mySAttach,
1493                                   myFDir,
1494                                   mySDir,
1495                                   curpos,
1496                                   mySymbolPrs);
1497 }
1498
1499
1500 //=======================================================================
1501 //function : Compute3DSelection
1502 // purpose  : compute the zones of selection for an angle dimension
1503 //            between 2 faces
1504 //=======================================================================
1505
1506 void AIS_AngleDimension::Compute3DSelection( const Handle( SelectMgr_Selection )& aSelection )
1507 {
1508   gp_Circ AngleCirc, AttachCirc;
1509   Standard_Real FirstParAngleCirc, LastParAngleCirc, FirstParAttachCirc, LastParAttachCirc;
1510   gp_Pnt EndOfArrow1, EndOfArrow2, ProjAttachPoint2;
1511   gp_Dir DirOfArrow1, DirOfArrow2;
1512   gp_Dir axisdir = (myVal <= Precision::Angular() || Abs( M_PI-myVal ) <= Precision::Angular())?
1513                     myPlane->Pln().Axis().Direction() : (myFDir ^ mySDir);
1514   Standard_Boolean isPlane = (myFirstSurfType == AIS_KOS_Plane)? Standard_True : Standard_False;
1515
1516   Standard_Real ArrowLength = myDrawer->AngleAspect()->ArrowAspect()->Length();
1517   DsgPrs::ComputeFacesAnglePresentation( ArrowLength,
1518                                          myVal,
1519                                          myCenter,
1520                                          myFAttach,
1521                                          mySAttach,
1522                                          myFDir,
1523                                          mySDir,
1524                                          axisdir,
1525                                          isPlane,
1526                                          myAxis,
1527                                          myPosition,
1528                                          AngleCirc,
1529                                          FirstParAngleCirc,
1530                                          LastParAngleCirc,
1531                                          EndOfArrow1,
1532                                          EndOfArrow2,
1533                                          DirOfArrow1,
1534                                          DirOfArrow2,
1535                                          ProjAttachPoint2,
1536                                          AttachCirc,
1537                                          FirstParAttachCirc,
1538                                          LastParAttachCirc );
1539   
1540   Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
1541   Handle( Select3D_SensitiveSegment ) seg;
1542   Handle( Geom_TrimmedCurve ) curve; 
1543   Handle( Select3D_SensitiveCurve ) SensCurve;
1544
1545   // Angle's arc or line
1546   if (myVal > Precision::Angular() && Abs( M_PI-myVal ) > Precision::Angular())
1547     {
1548       curve = new Geom_TrimmedCurve( new Geom_Circle( AngleCirc ), FirstParAngleCirc, LastParAngleCirc );
1549       SensCurve = new Select3D_SensitiveCurve( own, curve );
1550       aSelection->Add( SensCurve );
1551     }
1552   else // angle's line
1553     {
1554       gp_Vec ArrowVec( DirOfArrow1 );
1555       ArrowVec *= ArrowLength;
1556       gp_Pnt FirstPoint, LastPoint;
1557
1558       if (myPosition.Distance( EndOfArrow1 ) > ArrowLength)
1559         {
1560           FirstPoint = myPosition;
1561           LastPoint = EndOfArrow1.Translated( ArrowVec );
1562           if (myPosition.SquareDistance( LastPoint ) < myPosition.SquareDistance( EndOfArrow1 ))
1563             LastPoint = EndOfArrow1.Translated( -ArrowVec );
1564         }
1565       else
1566         {
1567           FirstPoint = EndOfArrow1.Translated( ArrowVec );
1568           LastPoint = EndOfArrow1.Translated( -ArrowVec );
1569         }
1570       seg = new Select3D_SensitiveSegment( own, FirstPoint, LastPoint );
1571       aSelection->Add( seg );
1572     }
1573
1574   if (! myFAttach.IsEqual( EndOfArrow1, Precision::Confusion() ))
1575     {
1576       seg = new Select3D_SensitiveSegment( own, myFAttach, EndOfArrow1 );
1577       aSelection->Add( seg );
1578     }
1579   if (! ProjAttachPoint2.IsEqual( EndOfArrow2, Precision::Confusion() ))
1580     {
1581       seg = new Select3D_SensitiveSegment( own, ProjAttachPoint2, EndOfArrow2 );
1582       aSelection->Add( seg );
1583     }
1584
1585   // Line or arc from mySAttach to its "projection"
1586   if (! mySAttach.IsEqual( ProjAttachPoint2, Precision::Confusion() ))
1587     {
1588       if (isPlane)
1589         {
1590           seg = new Select3D_SensitiveSegment( own, mySAttach, ProjAttachPoint2 );
1591           aSelection->Add( seg );
1592         }
1593       else
1594         {
1595           curve = new Geom_TrimmedCurve( new Geom_Circle( AttachCirc ),
1596                                          FirstParAttachCirc,
1597                                          LastParAttachCirc );
1598           SensCurve = new Select3D_SensitiveCurve( own, curve );
1599           aSelection->Add( SensCurve );
1600         }
1601     }
1602
1603   // Text
1604   Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
1605   Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
1606                                                                    myPosition.X(),
1607                                                                    myPosition.Y(),
1608                                                                    myPosition.Z(),
1609                                                                    myPosition.X() + size,
1610                                                                    myPosition.Y() + size,
1611                                                                    myPosition.Z() + size);  
1612   aSelection->Add(box);
1613 }
1614
1615 //=======================================================================
1616 //function : Compute2DSelection
1617 //purpose  : compute zones of selection on a side of angle between 2 edges
1618 //           Special processing of zero angles!
1619 //=======================================================================
1620
1621 void AIS_AngleDimension::Compute2DSelection(const Handle(SelectMgr_Selection)& aSelection)
1622 {
1623   BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
1624   BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
1625
1626   gp_Lin l1(cu1.Line());
1627   gp_Lin l2(cu2.Line());
1628
1629   // it is patch!
1630   if (Abs( myVal ) <= Precision::Angular() || Abs( M_PI - myVal ) <= Precision::Angular())
1631 /*
1632   //---------------------------------------------------------
1633   //    Cas de droites paralleles ( <=> angle nul a M_PI pres)
1634   if ((Abs(l1.Angle(l2)) < Precision::Angular()) ||
1635       (Abs((l1.Angle(l2) - M_PI)) < Precision::Angular()) )
1636 */
1637     {
1638        
1639     Standard_Real distLL= l1.Distance(l2);
1640     if ( Abs(distLL) <= Precision::Confusion() ) {
1641       gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1642       gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1643       gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1644       gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1645       distLL =  0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1646       ComputeNull2DSelection(aSelection, distLL);
1647     }
1648     else {
1649       ComputeNull2DSelection(aSelection, distLL*8/10);
1650     }
1651   }
1652   
1653   //----------------------------------------------------------
1654   //  Classic case  ( angle != 0 )
1655   else {
1656
1657     if (myFDir.IsParallel(mySDir,Precision::Angular())) {
1658       Standard_Real distLL= l1.Distance(l2);
1659       if ( Abs(distLL) <= Precision::Confusion() ) {
1660         gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
1661         gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
1662         gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
1663         gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
1664         distLL =  0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
1665         ComputeNull2DSelection(aSelection, distLL*8/10);
1666       }
1667     }
1668     else {
1669       gp_Dir Norm = myFDir.Crossed(mySDir);
1670       
1671       gp_Ax2 ax(myCenter,Norm,myFDir);
1672       gp_Circ cer(ax,myCenter.Distance(myPosition));
1673       gp_Vec vec1(myFDir);
1674       
1675       Standard_Boolean nullrad(Standard_False);
1676       if (cer.Radius() == 0.) {
1677         cer.SetRadius(1.);
1678         nullrad = Standard_True;
1679       }
1680       vec1 *= cer.Radius();
1681       gp_Pnt p1 = myCenter.Translated(vec1);
1682       gp_Vec vec2(mySDir);
1683       vec2 *= cer.Radius();
1684       gp_Pnt p2 = myCenter.Translated(vec2);
1685       
1686       Standard_Real uc1 = 0.;
1687       Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1688       Standard_Real uco;
1689       if (nullrad) uco = ElCLib::Parameter(cer,p1);
1690       else uco = ElCLib::Parameter(cer,myPosition);
1691       
1692       Standard_Real udeb = uc1;
1693       Standard_Real ufin = uc2;
1694       
1695       if (uco > ufin) {
1696         if (Abs(myVal)<M_PI) {
1697           // test if uco is in the opposing sector 
1698           if (uco > udeb+M_PI && uco < ufin+M_PI){
1699             udeb = udeb + M_PI;
1700           ufin = ufin + M_PI;
1701             uc1  = udeb;
1702             uc2  = ufin;
1703           }
1704       }
1705       }  
1706       if (uco > ufin) {
1707         if ((uco-uc2) < (uc1-uco+(2*M_PI))) ufin = uco;
1708         else udeb = uco - 2*M_PI;
1709       }
1710       p1   = ElCLib::Value(udeb,cer);
1711       p2   = ElCLib::Value(ufin,cer);
1712       
1713       //Create 2 owners for each part of the arrow
1714       Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1715       Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1716       if (myExtShape != 0) {
1717         if (myExtShape == 1) {
1718           own1->SetShape(mySShape);
1719           own2->SetShape(mySShape);
1720         }
1721         else {
1722           own1->SetShape(myFShape);
1723           own2->SetShape(myFShape);
1724         }
1725       }
1726       else {
1727         own1->SetShape(myFShape);
1728         own2->SetShape(mySShape);
1729       }
1730       
1731       Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1732       
1733       Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1734       Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1735       
1736       Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1737       aSelection->Add(scurv);
1738       scurv = new Select3D_SensitiveCurve(own2,thecu2);
1739       aSelection->Add(scurv);
1740       
1741       Handle(Select3D_SensitiveSegment) seg;
1742       if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1743         seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1744         aSelection->Add(seg);
1745       }
1746       if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1747         seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1748         aSelection->Add(seg);
1749       }
1750     }
1751   }
1752
1753 }
1754 //=======================================================================
1755 //function : Compute2DNullSelection
1756 //purpose  : for dimension of null angle
1757 //=======================================================================
1758
1759 void AIS_AngleDimension::ComputeNull2DSelection(
1760                          const Handle(SelectMgr_Selection)& aSelection,
1761                          const Standard_Real distLL)
1762 {
1763   gp_Dir Norm; 
1764   if ( myFDir.IsParallel(mySDir, Precision::Angular()) ) {
1765     Norm = myPlane->Pln().Axis().Direction();
1766   }
1767   else
1768     Norm = myFDir.Crossed(mySDir);
1769
1770   gp_Ax2 ax(myCenter,Norm,myFDir);
1771   gp_Circ cer(ax,distLL);
1772   
1773   gp_Vec vec1(myFDir);
1774   vec1 *= cer.Radius();
1775   gp_Pnt p1 = myCenter.Translated(vec1);
1776   gp_Vec vec2(mySDir);
1777   vec2 *= cer.Radius();
1778   gp_Pnt p2 = myCenter.Translated(vec2);
1779
1780   // calcul de parametres de debut et de fin des extremites de l'arc
1781   Standard_Real uc1 = 0.;
1782   Standard_Real uc2 = ElCLib::Parameter(cer,p2);
1783   Standard_Real uco = ElCLib::Parameter(cer,myPosition);
1784
1785   Standard_Real udeb = uc1;
1786   Standard_Real ufin = uc2;
1787
1788   if (uco > ufin) {
1789     if (Abs(myVal)<M_PI) {
1790       // test if uco is in the opposing sector 
1791       if (uco > udeb+M_PI && uco < ufin+M_PI){
1792         udeb = udeb + M_PI;
1793         ufin = ufin + M_PI;
1794         uc1  = udeb;
1795         uc2  = ufin;
1796       }
1797     }
1798   }
1799
1800   if (uco > ufin) {
1801     if ((uco-uc2) < (uc1-uco+(2*M_PI))) {
1802       ufin = uco;
1803     }
1804     else {
1805       udeb = uco - 2*M_PI;
1806     }
1807   }
1808
1809   //Create 2 owners for each part of the arrow
1810   Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
1811   Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
1812   if (myExtShape != 0) {
1813     if (myExtShape == 1) {
1814       own1->SetShape(mySShape);
1815       own2->SetShape(mySShape);
1816     }
1817     else {
1818       own1->SetShape(myFShape);
1819       own2->SetShape(myFShape);
1820     }
1821   }
1822   else {
1823     own1->SetShape(myFShape);
1824     own2->SetShape(mySShape);
1825   }
1826   
1827   Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
1828
1829   if ( udeb != ufin ) {
1830     Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
1831     Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
1832
1833     Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
1834     aSelection->Add(scurv);
1835     scurv = new Select3D_SensitiveCurve(own2,thecu2);
1836     aSelection->Add(scurv);
1837   }
1838   else {
1839     // find end of segment to allow selection
1840     gp_Vec VTrans(myFDir.Crossed(Norm));
1841     Handle(Select3D_SensitiveSegment) seg1;
1842     seg1 = new Select3D_SensitiveSegment(own1, 
1843                                          p1, 
1844                                          p1.Translated( VTrans*distLL/10 ) );
1845     aSelection->Add(seg1);
1846     seg1 = new Select3D_SensitiveSegment(own2, 
1847                                          p2, 
1848                                          p2.Translated(-VTrans*distLL/10 ) );
1849     aSelection->Add(seg1);
1850   }
1851
1852   Handle(Select3D_SensitiveSegment) seg;
1853   if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
1854     seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
1855     aSelection->Add(seg);
1856   }
1857     
1858   if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
1859     seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
1860     aSelection->Add(seg);
1861   }
1862 }
1863
1864
1865 //=======================================================================
1866 //function : ComputeConeAngleSelection
1867 //purpose  : for cone angle
1868 //=======================================================================
1869 void AIS_AngleDimension::ComputeConeAngleSelection(const Handle(SelectMgr_Selection)& aSelection)
1870 {
1871   if( myCone.IsNull() ) return;
1872
1873
1874   Handle( SelectMgr_EntityOwner ) owner = new SelectMgr_EntityOwner( this, 7 );
1875   Handle( Select3D_SensitiveSegment ) seg;
1876   
1877   gp_Pln aPln;
1878   gp_Cone aCone;
1879   gp_Circ myCircle;
1880   gp_Pnt Apex;
1881   Handle( Geom_Surface ) aSurf;         //a surface from the Face
1882   Handle( Geom_OffsetSurface ) aOffsetSurf; 
1883   Handle( Geom_ConicalSurface ) aConicalSurf;
1884   Handle( Geom_SurfaceOfRevolution ) aRevSurf; 
1885   Handle( Geom_Line ) aLine;
1886   BRepAdaptor_Surface tmpSurf(myCone);  
1887   TopoDS_Face aFace;
1888   AIS_KindOfSurface aSurfType;
1889   Standard_Real Offset = 0. ;
1890   Handle( Standard_Type ) aType;
1891
1892   Standard_Real maxV = tmpSurf.FirstVParameter();
1893   Standard_Real minV = tmpSurf.LastVParameter();
1894
1895   AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
1896   
1897   if ( aSurfType == AIS_KOS_Revolution ) {                                    //surface of revolution
1898
1899     aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf ); 
1900     gp_Lin ln( aRevSurf->Axis() );
1901     Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
1902     if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) )  return;        //Must be a part of line
1903
1904     Standard_Real par;
1905     gp_Pnt fst = tmpSurf.Value(0., minV);
1906     gp_Pnt lst = tmpSurf.Value(0., maxV);
1907  
1908     gp_Vec vec1(fst, lst);
1909    
1910     par = ElCLib::Parameter( ln, fst );
1911     gp_Pnt fst2 = ElCLib::Value( par, ln );                         //projection fst on ln
1912     par = ElCLib::Parameter( ln, lst );
1913     gp_Pnt lst2 = ElCLib::Value( par, ln );                         //projection lst on ln
1914
1915     gp_Vec vec2(fst2, lst2);
1916
1917    // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle ) 
1918     if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return; 
1919  
1920     gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
1921     aCone =  mkCone.Value();
1922     Apex = aCone.Apex();
1923   }
1924   else {  
1925     aType = aSurf->DynamicType();
1926     if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) {            //offset surface
1927       aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
1928       aSurf = aOffsetSurf->Surface();
1929       BRepBuilderAPI_MakeFace mkFace(aSurf, Precision::Confusion());
1930       mkFace.Build();
1931       if( !mkFace.IsDone() ) return;
1932       tmpSurf.Initialize( mkFace.Face() );
1933     }  
1934  
1935     aCone = tmpSurf.Cone();
1936     aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
1937     Apex =  aConicalSurf->Apex();
1938   }
1939
1940   Handle(Geom_Curve) aCurve;                 //A circle where the angle is drawn
1941   
1942   if ( myAutomaticPosition ) {
1943     Standard_Real midV = ( minV + maxV ) / 2.5; 
1944
1945     aCurve =   aSurf->VIso(midV);
1946     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1947
1948     myPosition = ElCLib::Value(M_PI / 2.0, myCircle);
1949     myAutomaticPosition = Standard_False;
1950   }
1951   else {
1952     Standard_Real U, V;
1953     ElSLib::Parameters(aCone, myPosition, U, V);
1954     aCurve = aSurf->VIso(V); 
1955     myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1956   }
1957  //__________________________________________________________________
1958   aCurve = aSurf->VIso(maxV);
1959   gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1960   aCurve = aSurf->VIso(minV);
1961   gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
1962  //__________________________________________________________________
1963
1964   if( CircVmax.Radius() < CircVmin.Radius() ) {
1965    gp_Circ tmpCirc = CircVmax;
1966    CircVmax = CircVmin;
1967    CircVmin = tmpCirc;
1968   }
1969  
1970   Standard_Boolean IsArrowOut = Standard_True;    //Is arrows inside or outside of the cone
1971   //Standard_Real PntOnMainAxis = 0;   //Is projection of aPosition inside of the cone = 0, above = 1, or below = -1
1972   Standard_Boolean IsConeTrimmed = Standard_False; 
1973
1974   if( CircVmin.Radius() > 0.01 ) IsConeTrimmed = Standard_True;
1975
1976   gp_Pnt AttachmentPnt;
1977   gp_Pnt OppositePnt;
1978
1979   Standard_Real param = ElCLib::Parameter(myCircle, myPosition);
1980
1981   gp_Pnt aPnt = Apex;
1982   gp_Pnt P1 = ElCLib::Value(0., myCircle);
1983   gp_Pnt P2 = ElCLib::Value(M_PI, myCircle);
1984
1985   gce_MakePln mkPln(P1, P2, aPnt);   // create a plane whitch defines plane for projection aPosition on it
1986
1987   aPnt = AIS::ProjectPointOnPlane(myPosition, mkPln.Value()); 
1988   gp_Pnt tmpPnt = aPnt;
1989
1990   if( aPnt.Distance(P1) <  aPnt.Distance(P2) ){
1991     AttachmentPnt = P1; 
1992     OppositePnt = P2; 
1993   }
1994   else {
1995     AttachmentPnt = P2; 
1996     OppositePnt = P1;
1997   }
1998   
1999   aPnt = AttachmentPnt ;                          // Creating of circle whitch defines a plane for a dimension arc
2000   gp_Vec Vec(AttachmentPnt, Apex);                // Dimension arc is a part of the circle 
2001   Vec.Scale(2);
2002   aPnt.Translate(Vec);
2003   GC_MakeCircle mkCirc(AttachmentPnt, OppositePnt,  aPnt); 
2004   gp_Circ  aCircle2 = mkCirc.Value()->Circ();
2005
2006   
2007   Standard_Integer i;
2008   Standard_Real AttParam = ElCLib::Parameter(aCircle2, AttachmentPnt);
2009   Standard_Real OppParam = ElCLib::Parameter(aCircle2, OppositePnt);
2010   
2011   while ( AttParam >= 2 * M_PI ) AttParam -= 2 * M_PI;
2012   while ( OppParam >= 2 * M_PI ) OppParam -= 2 * M_PI;
2013
2014   if( myPosition.Distance( myCircle.Location() ) <= myCircle.Radius() )
2015     if( 2 * myCircle.Radius() > aCircle2.Radius() * 0.4 ) IsArrowOut = Standard_False;  //four times more than an arrow size
2016
2017   param = AttParam;
2018   Standard_Real angle = OppParam - AttParam;
2019
2020   if(IsArrowOut)
2021   {
2022     angle += M_PI / 6; //An angle between AttParam and OppParam + 30 degrees
2023     param -= M_PI / 12;      //out parts of dimension line are 15 degrees
2024   }
2025
2026   while ( angle > 2. * M_PI ) angle -= 2. * M_PI;
2027
2028   gp_Pnt Vprev = ElCLib::Value(param, aCircle2);
2029   for( i = 1; i <= 11; i++ ) //calculating of arc
2030   {
2031     gp_Pnt Vcur = ElCLib::Value(param + angle/11 * i, aCircle2);
2032     seg = new Select3D_SensitiveSegment(owner, Vprev, Vcur);
2033     aSelection->Add(seg);
2034     Vprev = Vcur;
2035   }
2036
2037   tmpPnt = tmpPnt.Translated(gp_Vec(0, 0, -2));
2038
2039   const Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
2040   Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( owner,
2041                                                                    tmpPnt.X(),
2042                                                                    tmpPnt.Y(),
2043                                                                    tmpPnt.Z(),
2044                                                                    tmpPnt.X() + size,
2045                                                                    tmpPnt.Y() + size,
2046                                                                    tmpPnt.Z() + size);
2047   aSelection->Add(box);
2048 }