0024624: Lost word in license statement in source files
[occt.git] / src / AIS / AIS_AngleDimension.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 85590f7..48b182a
 // Created on: 1996-12-05
 // Created by: Arnaud BOUZY/Odile Olivier
 // Copyright (c) 1996-1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
-
-#define BUC60655       //GG 22/03/00 Enable to compute correctly
-//                     the arrow size at object creation time.
-
-#define BUC60915        //GG 05/06/01 Enable to compute the requested arrow size
-//                      if any in all dimensions.
-
-#include <Standard_NotImplemented.hxx>
-
-#include <AIS_AngleDimension.ixx>
+#include <AIS_AngleDimension.hxx>
 
 #include <AIS.hxx>
-#include <AIS_DimensionOwner.hxx>
 #include <AIS_Drawer.hxx>
-
 #include <BRepBuilderAPI_MakeFace.hxx>
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Surface.hxx>
+#include <BRepLib_MakeVertex.hxx>
 #include <BRep_Tool.hxx>
-
-#include <DsgPrs.hxx>
-#include <DsgPrs_AnglePresentation.hxx>
-
 #include <ElCLib.hxx>
-#include <ElSLib.hxx>
-
-#include <Geom2d_Circle.hxx>
-#include <Geom2d_Curve.hxx>
-#include <Geom2d_Line.hxx>
-#include <GeomAPI.hxx>
+#include <GCPnts_UniformAbscissa.hxx>
+#include <GC_MakeArcOfCircle.hxx>
+#include <gce_MakeLin2d.hxx>
+#include <gce_MakeLin.hxx>
+#include <gce_MakeCirc.hxx>
+#include <gce_MakeCone.hxx>
+#include <gce_MakePln.hxx>
+#include <gce_MakeDir.hxx>
 #include <Geom_Circle.hxx>
-#include <Geom_Line.hxx>
-#include <Geom_Plane.hxx>
 #include <Geom_TrimmedCurve.hxx>
-#include <Geom_Surface.hxx>
-#include <Geom_CylindricalSurface.hxx>
 #include <Geom_ConicalSurface.hxx>
 #include <Geom_SurfaceOfRevolution.hxx>
-#include <Geom_SurfaceOfLinearExtrusion.hxx>
 #include <Geom_OffsetSurface.hxx>
-
+#include <Graphic3d_ArrayOfSegments.hxx>
+#include <Graphic3d_Group.hxx>
+#include <Graphic3d_ArrayOfPolylines.hxx>
 #include <IntAna2d_AnaIntersection.hxx>
-#include <IntAna2d_IntPoint.hxx>
-#include <IntAna_QuadQuadGeo.hxx>
-#include <IntAna_ResultType.hxx>
-
-#include <Precision.hxx>
-
 #include <ProjLib.hxx>
-
-#include <Prs3d_AngleAspect.hxx>
-#include <Prs3d_ArrowAspect.hxx>
-#include <Prs3d_Drawer.hxx>
-
-#include <Select3D_SensitiveCurve.hxx>
+#include <Prs3d_Root.hxx>
+#include <Prs3d_ShadingAspect.hxx>
+#include <PrsMgr_PresentationManager3d.hxx>
+#include <Select3D_SensitiveGroup.hxx>
 #include <Select3D_SensitiveSegment.hxx>
-#include <Select3D_SensitiveBox.hxx>
-#include <SelectMgr_EntityOwner.hxx>
-
-#include <TColStd_Array1OfReal.hxx>
-
-#include <TopExp.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Shape.hxx>
-#include <TopoDS_Vertex.hxx>
-
+#include <SelectMgr_Selection.hxx>
+#include <Standard_ProgramError.hxx>
 #include <UnitsAPI.hxx>
 
-#include <gp.hxx>
-#include <gp_Ax1.hxx>
-#include <gp_Lin.hxx>
-#include <gp_Cone.hxx>
-#include <gp_Pln.hxx>
-#include <gp_Pnt.hxx>
-#include <gp_Pnt2d.hxx>
-#include <gp_Vec.hxx> 
-#include <gp_XYZ.hxx>
-
-#include <GC_MakeCircle.hxx>
-#include <GC_MakeConicalSurface.hxx>
-#include <gce_MakePln.hxx>
-#include <gce_MakeCone.hxx>
+IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
+IMPLEMENT_STANDARD_RTTIEXT (AIS_AngleDimension, AIS_Dimension)
 
+namespace
+{
+  static const TCollection_ExtendedString THE_EMPTY_LABEL_STRING;
+  static const Standard_Real              THE_EMPTY_LABEL_WIDTH = 0.0;
+  static const Standard_ExtCharacter      THE_DEGREE_SYMBOL (0x00B0);
+  static const Standard_Real              THE_3D_TEXT_MARGIN = 0.1;
+};
 
 //=======================================================================
 //function : Constructor
-//purpose  : ConeAngle dimension 
+//purpose  : 
 //=======================================================================
-
-AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aCone, 
-                                       const Standard_Real aVal,
-                                       const TCollection_ExtendedString& aText,
-                                       const gp_Pnt& aPosition,
-                                       const DsgPrs_ArrowSide /*aSymbolPrs*/,
-                                       const Standard_Real anArrowSize):
-myNbShape(1)
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
+                                        const TopoDS_Edge& theSecondEdge)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-  myCone = aCone;
-  myVal = aVal;
-  myText = aText;
-  myPosition = aPosition; 
-  mySymbolPrs = DsgPrs_AS_BOTHAR;
-  myAutomaticPosition = Standard_True;
-#ifdef BUC60915
-  SetArrowSize( anArrowSize );
-#else
-  myArrowSize = anArrowSize;
-#endif
+  Init();
+  SetMeasuredGeometry (theFirstEdge, theSecondEdge);
 }
 
 //=======================================================================
 //function : Constructor
-//purpose  : ConeAngle dimension 
+//purpose  : 
 //=======================================================================
-
-AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aCone, 
-                                       const Standard_Real aVal,
-                                       const TCollection_ExtendedString& aText):
-myNbShape(1)
+AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
+                                        const gp_Pnt& theSecondPoint,
+                                        const gp_Pnt& theThirdPoint)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-//#ifdef DEB
-  cout << "Call new AngleDimension for cone's angle" << endl;
-//#endif
-
-  gp_Pnt tmpPnt(0., 0., 0.); 
-
-  myCone = aCone;
-  myVal = aVal;
-  myText = aText;
-  myPosition = tmpPnt; 
-  mySymbolPrs = DsgPrs_AS_BOTHAR;
-  myAutomaticPosition = Standard_True;
-  myArrowSize = 0.0;
-
+  Init();
+  SetMeasuredGeometry (theFirstPoint, theSecondPoint, theThirdPoint);
 }
 
-
 //=======================================================================
 //function : Constructor
-//purpose  : TwoEdgesAngle dimension 
+//purpose  : 
 //=======================================================================
-
-
-AIS_AngleDimension::AIS_AngleDimension(const TopoDS_Edge& aFirstEdge,
-                                      const TopoDS_Edge& aSecondEdge,
-                                      const Handle (Geom_Plane)& aPlane, 
-                                      const Standard_Real aVal, 
-                                      const TCollection_ExtendedString& aText)
-:AIS_Relation(),
- myNbShape(2)
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Vertex& theFirstVertex,
+                                        const TopoDS_Vertex& theSecondVertex,
+                                        const TopoDS_Vertex& theThirdVertex)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-#ifdef DEB
-  cout << endl << "Call new AngleDimension for edges, default" << endl;
-#endif
-
-  myFShape = aFirstEdge;
-  mySShape = aSecondEdge;
-  myVal = aVal;
-  myPlane = aPlane;
-  myText = aText;
-  mySymbolPrs = DsgPrs_AS_BOTHAR;
-  myAutomaticPosition = Standard_True;
-
-  myArrowSize = myVal / 100.;
+  Init();
+  SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex);
 }
 
 //=======================================================================
 //function : Constructor
-//purpose  : TwoEdgesAngle dimension (avec position et texte)
-//=======================================================================
-
-AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Edge& aFirstEdge, 
-                                       const TopoDS_Edge& aSecondEdge, 
-                                       const Handle (Geom_Plane)& aPlane,  
-                                       const Standard_Real aVal, 
-                                       const TCollection_ExtendedString& aText, 
-                                       const gp_Pnt& aPosition,
-                                       const DsgPrs_ArrowSide aSymbolPrs,
-                                       const Standard_Real anArrowSize):
-myNbShape(2)
+//purpose  : 
+//=======================================================================
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-#ifdef DEB
-  cout << endl << "Call new AngleDimension for edges" << endl;
-#endif
-
-  myFShape = aFirstEdge;
-  mySShape = aSecondEdge;
-  myVal = aVal;
-  myPlane = aPlane;
-  myText = aText;
-  mySymbolPrs = aSymbolPrs;
-  myAutomaticPosition = Standard_False;
-#ifdef BUC60915
-  SetArrowSize( anArrowSize );
-#else
-  myArrowSize = anArrowSize;
-#endif
-  myPosition = aPosition;
-
+  Init();
+  SetMeasuredGeometry (theCone);
 }
 
 //=======================================================================
 //function : Constructor
-//purpose  : TwoPlanarFacesAngle dimension 
+//purpose  : 
 //=======================================================================
-
-AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFirstFace, 
-                                       const TopoDS_Face& aSecondFace, 
-                                       const gp_Ax1& anAxis, 
-                                       const Standard_Real aVal,
-                                       const TCollection_ExtendedString& aText):
-myNbShape(2),
-myAxis(anAxis)
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
+                                        const TopoDS_Face& theSecondFace)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-#ifdef DEB
-  cout << endl << "Call new AngleDimension for planar faces, default" << endl;
-#endif
-
-  myFShape = aFirstFace;
-  mySShape = aSecondFace;
-
-  AIS::GetPlaneFromFace( aFirstFace, myFirstPlane, myFirstBasisSurf, myFirstSurfType, myFirstOffset );
-  AIS::GetPlaneFromFace( aSecondFace, mySecondPlane, mySecondBasisSurf, mySecondSurfType, mySecondOffset );
-
-//POP init champ myPlane
-  myPlane = new Geom_Plane(myFirstPlane);
-
-  myVal = aVal;
-  myText = aText;
-  mySymbolPrs = DsgPrs_AS_BOTHAR;
-  myAutomaticPosition = Standard_True;
-
-  myArrowSize = myVal / 100.;
+  Init();
+  SetMeasuredGeometry (theFirstFace, theSecondFace);
 }
 
 //=======================================================================
 //function : Constructor
-//purpose  : TwoPlanarFacesAngle dimension  (avec position et texte)
-//=======================================================================
-
-AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFirstFace, 
-                                       const TopoDS_Face& aSecondFace, 
-                                       const gp_Ax1& anAxis, 
-                                       const Standard_Real aVal, 
-                                       const TCollection_ExtendedString& aText, 
-                                       const gp_Pnt& aPosition, 
-                                       const DsgPrs_ArrowSide aSymbolPrs,
-                                       const Standard_Real anArrowSize):
-myNbShape(2),
-myAxis(anAxis)
+//purpose  : 
+//=======================================================================
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
+                                        const TopoDS_Face& theSecondFace,
+                                        const gp_Pnt& thePoint)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-#ifdef DEB
-  cout << endl << "Call new AngleDimension for planar faces" << endl;
-#endif
-
-  myFShape = aFirstFace;
-  mySShape = aSecondFace;
-
-  AIS::GetPlaneFromFace( aFirstFace, myFirstPlane, myFirstBasisSurf, myFirstSurfType, myFirstOffset );
-  AIS::GetPlaneFromFace( aSecondFace, mySecondPlane, mySecondBasisSurf, mySecondSurfType, mySecondOffset );
-
-//POP init champ myPlane
-  myPlane = new Geom_Plane(myFirstPlane);
-
-  myVal = aVal;
-  myText = aText;
-  mySymbolPrs = aSymbolPrs;
-  myAutomaticPosition = Standard_False;
-#ifdef BUC60915
-  SetArrowSize( anArrowSize );
-#else
-  myArrowSize = anArrowSize;
-#endif
-  myPosition = aPosition;
+  Init();
+  SetMeasuredGeometry (theFirstFace, theSecondFace, thePoint);
 }
 
-
 //=======================================================================
-//function : AIS_AngleDimension
-//purpose  : Two curvilinear faces dimension
+//function : SetMeasuredGeometry
+//purpose  : 
 //=======================================================================
-
-AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFFace, 
-                                       const TopoDS_Face& aSFace, 
-                                       const Standard_Real aVal,
-                                       const TCollection_ExtendedString& aText ):
-myNbShape(2)
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
+                                              const TopoDS_Edge& theSecondEdge)
 {
-#ifdef DEB
-  cout << endl << "Call new AngleDimension for curvilinear faces, default" << endl;
-#endif
+  gp_Pln aComputedPlane;
 
-  SetFirstShape( aFFace );
-  SetSecondShape( aSFace );
-  myVal = aVal;
+  myFirstShape   = theFirstEdge;
+  mySecondShape  = theSecondEdge;
+  myThirdShape   = TopoDS_Shape();
+  myGeometryType = GeometryType_Edges;
+  myIsValid      = InitTwoEdgesAngle (aComputedPlane);
 
-  myText = aText;
-  mySymbolPrs = DsgPrs_AS_BOTHAR;
-  myAutomaticPosition = Standard_True;
+  if (myIsValid && !myIsPlaneCustom)
+  {
+    ComputePlane();
+  }
 
-  myArrowSize = myVal / 100.;
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : AIS_AngleDimension
+//function : SetMeasuredGeometry
 //purpose  : 
 //=======================================================================
-
-AIS_AngleDimension::AIS_AngleDimension( const TopoDS_Face& aFFace, 
-                                       const TopoDS_Face& aSFace, 
-                                       const Standard_Real aVal,
-                                       const TCollection_ExtendedString& aText,
-                                       const gp_Pnt& aPosition, 
-                                       const DsgPrs_ArrowSide aSymbolPrs,
-                                       const Standard_Real anArrowSize):
-myNbShape(2)
+void AIS_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
+                                              const gp_Pnt& theSecondPoint,
+                                              const gp_Pnt& theThirdPoint)
 {
-#ifdef DEB
-  cout << endl << "Call new AngleDimension for curvilinear faces" << endl;
-#endif
-
-  SetFirstShape( aFFace );
-  SetSecondShape( aSFace );
-  myVal = aVal;
-
-  myText = aText;
-  mySymbolPrs = DsgPrs_AS_BOTHAR;
-  myAutomaticPosition = Standard_True;
-
-  mySymbolPrs = aSymbolPrs;
-  myAutomaticPosition = Standard_False;
-#ifdef BUC60915
-  SetArrowSize( anArrowSize );
-#else
-  myArrowSize = anArrowSize;
-#endif
-  myPosition = aPosition;
-}
+  myFirstPoint    = theFirstPoint;
+  myCenterPoint   = theSecondPoint;
+  mySecondPoint   = theThirdPoint;
+  myFirstShape    = BRepLib_MakeVertex (myFirstPoint);
+  mySecondShape   = BRepLib_MakeVertex (myCenterPoint);
+  myThirdShape    = BRepLib_MakeVertex (mySecondPoint);
+  myGeometryType  = GeometryType_Points;
+  myIsValid       = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
+
+  if (myIsValid && !myIsPlaneCustom)
+  {
+    ComputePlane();
+  }
 
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
+}
 
 //=======================================================================
-//function : SetConeFace
+//function : SetMeasuredGeometry
 //purpose  : 
 //=======================================================================
-
-void AIS_AngleDimension::SetConeFace( const TopoDS_Face& aConeFace )
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
+                                              const TopoDS_Vertex& theSecondVertex,
+                                              const TopoDS_Vertex& theThirdVertex)
 {
-  myCone = aConeFace;
-  myAutomaticPosition = Standard_True;
-}
+  myFirstShape   = theFirstVertex;
+  mySecondShape  = theSecondVertex;
+  myThirdShape   = theThirdVertex;
+  myFirstPoint   = BRep_Tool::Pnt (theFirstVertex);
+  myCenterPoint  = BRep_Tool::Pnt (theSecondVertex);
+  mySecondPoint  = BRep_Tool::Pnt (theThirdVertex);
+  myGeometryType = GeometryType_Points;
+  myIsValid      = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
+
+  if (myIsValid && !myIsPlaneCustom)
+  {
+    ComputePlane();
+  }
+
+  myIsValid &= CheckPlane (myPlane);
 
+  SetToUpdate();
+}
 
 //=======================================================================
-//function : SetFirstShape
+//function : SetMeasuredGeometry
 //purpose  : 
 //=======================================================================
-
-void AIS_AngleDimension::SetFirstShape( const TopoDS_Shape& aFShape )
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone)
 {
-  myFShape = aFShape;
+  myFirstShape   = theCone;
+  mySecondShape  = TopoDS_Shape();
+  myThirdShape   = TopoDS_Shape();
+  myGeometryType = GeometryType_Face;
+  myIsValid      = InitConeAngle();
 
-  if (myFShape.ShapeType() == TopAbs_FACE)
-    {
-      AIS::GetPlaneFromFace( TopoDS::Face( myFShape ),
-                            myFirstPlane,
-                            myFirstBasisSurf,
-                            myFirstSurfType,
-                            myFirstOffset );
-
-      if (myFirstSurfType == AIS_KOS_Cylinder)
-       myAxis = (Handle( Geom_CylindricalSurface )::DownCast( myFirstBasisSurf ))->Cylinder().Axis();
-      else if (myFirstSurfType == AIS_KOS_Cone)
-       myAxis = (Handle( Geom_ConicalSurface )::DownCast( myFirstBasisSurf ))->Cone().Axis();
-      else if (myFirstSurfType == AIS_KOS_Revolution)
-       myAxis = (Handle( Geom_SurfaceOfRevolution )::DownCast( myFirstBasisSurf ))->Axis();
-      else if (myFirstSurfType == AIS_KOS_Extrusion)
-       {
-         myAxis.SetDirection((Handle( Geom_SurfaceOfLinearExtrusion )::DownCast( myFirstBasisSurf ))
-                             ->Direction() );
-         //myAxis.SetLocation( ??? );
-       }
-    }
+  if (myIsValid && !myIsPlaneCustom)
+  {
+    ComputePlane();
+  }
+
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : SetSecondShape
+//function : SetMeasuredGeometry
 //purpose  : 
 //=======================================================================
-
-void AIS_AngleDimension::SetSecondShape( const TopoDS_Shape& aSShape )
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
+                                              const TopoDS_Face& theSecondFace)
 {
-  mySShape = aSShape;
-
-  if (myFShape.ShapeType() == TopAbs_FACE)
-    AIS::GetPlaneFromFace( TopoDS::Face( mySShape ),
-                          mySecondPlane,
-                          mySecondBasisSurf,
-                          mySecondSurfType,
-                          mySecondOffset );
-}
+  myFirstShape   = theFirstFace;
+  mySecondShape  = theSecondFace;
+  myThirdShape   = TopoDS_Shape();
+  myGeometryType = GeometryType_Faces;
+  myIsValid      = InitTwoFacesAngle();
 
+  if (myIsValid && !myIsPlaneCustom)
+  {
+    ComputePlane();
+  }
 
+  myIsValid &= CheckPlane (myPlane);
 
+  SetToUpdate();
+}
 
-///=======================================================================
-//function : Compute
+//=======================================================================
+//function : SetMeasuredGeometry
 //purpose  : 
 //=======================================================================
-
-void AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager3d)&, 
-                                const Handle(Prs3d_Presentation)& aPresentation, 
-                                const Standard_Integer)
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
+                                              const TopoDS_Face& theSecondFace,
+                                              const gp_Pnt& thePoint)
 {
-  aPresentation->Clear();
+  myFirstShape   = theFirstFace;
+  mySecondShape  = theSecondFace;
+  myThirdShape   = TopoDS_Shape();
+  myGeometryType = GeometryType_Faces;
+  myIsValid      = InitTwoFacesAngle (thePoint);
 
-  if( myNbShape == 1 ) 
-    {
-     //  cout << "Computing for cone' angle "   << endl;
-     ComputeConeAngle(aPresentation);
-     return;
-    }
-  switch (myFShape.ShapeType()) {
-  case TopAbs_FACE :
-    {
-      // cas angle entre deux faces
-      ComputeTwoFacesAngle(aPresentation);
-    }
-    break;
-  case TopAbs_EDGE :
-    {
-      // cas angle entre deux edges
-      ComputeTwoEdgesAngle(aPresentation);
-    }
-    break;
-  default:
-    break;
+  if (myIsValid && !myIsPlaneCustom)
+  {
+    ComputePlane();
   }
-  
+
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : Compute
-//purpose  : : to avoid warning
+//function : Init
+//purpose  : 
 //=======================================================================
-
-void AIS_AngleDimension::Compute(const Handle(Prs3d_Projector)& aProjector, 
-                                const Handle(Prs3d_Presentation)& aPresentation)
+void AIS_AngleDimension::Init()
 {
-// Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
- PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
+  SetSpecialSymbol (THE_DEGREE_SYMBOL);
+  SetDisplaySpecialSymbol (AIS_DSS_After);
+  SetFlyout (15.0);
 }
 
 //=======================================================================
-//function : Compute
-//purpose  : : to avoid warning
+//function: GetCenterOnArc
+//purpose :
 //=======================================================================
-
-void AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager2d, 
-                                const Handle(Graphic2d_GraphicObject)& aGraphicObject, 
-                                const Standard_Integer anInteger)
+gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
+                                           const gp_Pnt& theSecondAttach,
+                                           const gp_Pnt& theCenter) const
 {
-// Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle(PrsMgr_PresentationManager2d)&,const Handle(Graphic2d_GraphicObject)&,const Standard_Integer)");
- PrsMgr_PresentableObject::Compute( aPresentationManager2d ,aGraphicObject,anInteger) ;
-}
+  // construct plane where the circle and the arc are located
+  gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
+  if (!aConstructPlane.IsDone())
+  {
+    return gp::Origin();
+  }
+  
+  gp_Pln aPlane = aConstructPlane.Value();
 
-void AIS_AngleDimension::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
-{
-// Standard_NotImplemented::Raise("AIS_AngleDimension::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
- PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
+  Standard_Real aRadius = theFirstAttach.Distance (theCenter);
+
+  // construct circle forming the arc
+  gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
+  if (!aConstructCircle.IsDone())
+  {
+    return gp::Origin();
+  }
+
+  gp_Circ aCircle = aConstructCircle.Value();
+
+  // compute angle parameters of arc end-points on circle
+  Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
+  Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+
+  return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle);
 }
 
 //=======================================================================
-//function : ComputeSelection
-//purpose  : 
+//function : DrawArc
+//purpose  : draws the arc between two attach points
 //=======================================================================
-
-void AIS_AngleDimension::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
-                                         const Standard_Integer)
+void AIS_AngleDimension::DrawArc (const Handle(Prs3d_Presentation)& thePresentation,
+                                  const gp_Pnt& theFirstAttach,
+                                  const gp_Pnt& theSecondAttach,
+                                  const gp_Pnt& theCenter,
+                                  const Standard_Real theRadius,
+                                  const Standard_Integer theMode)
 {
+  // construct plane where the circle and the arc are located
+  gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
+  if (!aConstructPlane.IsDone())
+  {
+    return;
+  }
 
-  if ( myNbShape == 1 ) 
-    {
-    // cout << "Computing selection for cone's angle "   << endl;
-     ComputeConeAngleSelection(aSelection);
-     return;
-    }
+  gp_Pln aPlane = aConstructPlane.Value();
 
+  // construct circle forming the arc
+  gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
+  if (!aConstructCircle.IsDone())
+  {
+    return;
+  }
 
-  if (myFShape.IsNull()) return;
+  gp_Circ aCircle = aConstructCircle.Value();
 
-  if (myFShape.ShapeType() == TopAbs_FACE )
-    Compute3DSelection(aSelection);
-  else
-    Compute2DSelection(aSelection);
-
-  // Text
-  Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
-  Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
-  Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
-                                                                  myPosition.X(),
-                                                                  myPosition.Y(),
-                                                                  myPosition.Z(),
-                                                                  myPosition.X() + size,
-                                                                  myPosition.Y() + size,
-                                                                  myPosition.Z() + size);
-  aSelection->Add(box);
+  // construct the arc
+  GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True);
+  if (!aConstructArc.IsDone())
+  {
+    return;
+  }
+
+  // generate points with specified deflection
+  const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
+  
+  GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
+
+  // compute number of discretization elements in old-fanshioned way
+  gp_Vec aCenterToFirstVec  (theCenter, theFirstAttach);
+  gp_Vec aCenterToSecondVec (theCenter, theSecondAttach);
+  const Standard_Real anAngle = aCenterToFirstVec.Angle (aCenterToSecondVec);
+  const Standard_Integer aNbPoints = Max (4, Standard_Integer (50.0 * anAngle / M_PI));
+
+  GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
+  if (!aMakePnts.IsDone())
+  {
+    return;
+  }
+
+  // init data arrays for graphical and selection primitives
+  Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
+
+  SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+
+  // load data into arrays
+  for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
+  {
+    gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
+
+    aPrimSegments->AddVertex (aPnt);
+
+    aSensitiveCurve.Append (aPnt);
+  }
+
+  // add display presentation
+  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
+  {
+    Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True);
+  }
+  Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
+  Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle);
+  Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
+  if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All)
+  {
+    Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
+  }
 }
 
 //=======================================================================
-//function : ComputeConeAngle
-//purpose  : 
+//function: DrawArcWithText
+//purpose :
 //=======================================================================
-
-void AIS_AngleDimension::ComputeConeAngle(const Handle(Prs3d_Presentation)& aPresentation)
+void AIS_AngleDimension::DrawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
+                                          const gp_Pnt& theFirstAttach,
+                                          const gp_Pnt& theSecondAttach,
+                                          const gp_Pnt& theCenter,
+                                          const TCollection_ExtendedString& theText,
+                                          const Standard_Real theTextWidth,
+                                          const Standard_Integer theMode,
+                                          const Standard_Integer theLabelPosition)
 {
-  if( myCone.IsNull() ) return;
-  
-  gp_Pln aPln;
-  gp_Cone aCone;
-  gp_Circ myCircle;
-  gp_Pnt Apex;
-  Handle( Geom_Surface ) aSurf;         //a surface from the Face
-  Handle( Geom_OffsetSurface ) aOffsetSurf; 
-  Handle( Geom_ConicalSurface ) aConicalSurf;
-  Handle( Geom_SurfaceOfRevolution ) aRevSurf; 
-  Handle( Geom_Line ) aLine;
-  BRepAdaptor_Surface tmpSurf(myCone);  
-  TopoDS_Face aFace;
-  AIS_KindOfSurface aSurfType;
-  Standard_Real Offset = 0. ;
-  Handle( Standard_Type ) aType;
-
-  Standard_Real maxV = tmpSurf.FirstVParameter();
-  Standard_Real minV = tmpSurf.LastVParameter();
-
-
- AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
-
- if ( aSurfType == AIS_KOS_Revolution ) {                                    //surface of revolution
-
-   aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf ); 
-   gp_Lin ln( aRevSurf->Axis() );
-   Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
-   if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) )  return;        //Must be a part of line
-
-   Standard_Real par;
-   gp_Pnt fst = tmpSurf.Value(0., minV);
-   gp_Pnt lst = tmpSurf.Value(0., maxV);
-   gp_Vec vec1(fst, lst);
-   
-   par = ElCLib::Parameter( ln, fst );
-   gp_Pnt fst2 = ElCLib::Value( par, ln );                         //projection fst on ln
-   par = ElCLib::Parameter( ln, lst );
-   gp_Pnt lst2 = ElCLib::Value( par, ln );                         //projection lst on ln
-
-   gp_Vec vec2(fst2, lst2);
-
-   // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle ) 
-  if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return; 
-  gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
-  aCone =  mkCone.Value();
-  Apex = aCone.Apex();
- }
- else {  
-   aType = aSurf->DynamicType();
-   if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) {            //offset surface
-     aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
-     aSurf = aOffsetSurf->Surface();
-     BRepBuilderAPI_MakeFace mkFace(aSurf, Precision::Confusion());
-     mkFace.Build();
-     if( !mkFace.IsDone() ) return;
-     tmpSurf.Initialize( mkFace.Face() );
-   }  
-   aCone = tmpSurf.Cone();
-   aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
-   Apex =  aConicalSurf->Apex();
- }
-   Handle(Geom_Curve) aCurve;                 //A circle where the angle is drawn
-   if ( myAutomaticPosition ) {
-    Standard_Real midV = ( minV + maxV ) / 2.5; 
-
-    aCurve =   aSurf->VIso(midV);
-    myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
-
-    myPosition = ElCLib::Value(M_PI / 2.0, myCircle);
-    myAutomaticPosition = Standard_False;
+  // construct plane where the circle and the arc are located
+  gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
+  if (!aConstructPlane.IsDone())
+  {
+    return;
   }
-  else {
-    Standard_Real U, V;
-    ElSLib::Parameters(aCone, myPosition, U, V);
-    aCurve = aSurf->VIso(V); 
-    myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
+
+  gp_Pln aPlane = aConstructPlane.Value();
+
+  Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint);
+
+  // construct circle forming the arc
+  gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
+  if (!aConstructCircle.IsDone())
+  {
+    return;
   }
-  
- //__________________________________________________________________
-  aCurve = aSurf->VIso(maxV);
-  gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
-  aCurve = aSurf->VIso(minV);
-  gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
- //__________________________________________________________________
-
-  if( CircVmax.Radius() < CircVmin.Radius() ) {
-   gp_Circ tmpCirc = CircVmax;
-   CircVmax = CircVmin;
-   CircVmin = tmpCirc;
+
+  gp_Circ aCircle = aConstructCircle.Value();
+
+  // compute angle parameters of arc end-points on circle
+  Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach);
+  Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach);
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+
+  // middle point of arc parameter on circle
+  Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5;
+
+  // add text graphical primitives
+  if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
+  {
+    gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
+    gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach);
+
+    // Drawing text
+    DrawText (thePresentation,
+              aTextPos,
+              aTextDir,
+              theText,
+              theLabelPosition);
   }
 
-  DsgPrs_AnglePresentation::Add(aPresentation, myDrawer, myVal, 
-                               myText, myCircle, myPosition, Apex, CircVmin, CircVmax, myArrowSize);
-// cout << "ComputeConeAngle is over"   << endl;                               
-}
+  if (theMode != ComputeMode_All && theMode != ComputeMode_Line)
+  {
+    return;
+  }
 
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
 
-//=======================================================================
-//function : ComputeTwoFacesAngle
-//purpose  : 
-//=======================================================================
+  Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
+                              && aDimensionAspect->IsText3d();
 
-void AIS_AngleDimension::ComputeTwoFacesAngle(const Handle(Prs3d_Presentation)& aPresentation)
-{
-  if (myFirstSurfType == AIS_KOS_Plane)
-    ComputeTwoPlanarFacesAngle( aPresentation );
+  if (isLineBreak)
+  {
+    // compute gap for label as parameteric size of sector on circle segment
+    Standard_Real aSectorOnCircle = theTextWidth / aRadius;
+  
+    gp_Pnt aTextPntBeg = ElCLib::Value (aParamMid - aSectorOnCircle * 0.5, aCircle);
+    gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle);
+
+    // Drawing arcs
+    DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode);
+    DrawArc (thePresentation, theSecondAttach, aTextPntEnd, theCenter, aRadius, theMode);
+  }
   else
-    ComputeTwoCurvilinearFacesAngle( aPresentation );
+  {
+    DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode);
+  }
 }
 
 //=======================================================================
-//function : ComputeTwoCurvilinearFacesAngle
+//function : CheckPlane
 //purpose  : 
 //=======================================================================
-
-void AIS_AngleDimension::ComputeTwoCurvilinearFacesAngle(const Handle(Prs3d_Presentation)& aPresentation) 
+Standard_Boolean AIS_AngleDimension::CheckPlane (const gp_Pln& thePlane)const
 {
-  AIS::ComputeAngleBetweenCurvilinearFaces( TopoDS::Face( myFShape ),
-                                           TopoDS::Face( mySShape ),
-                                           myFirstBasisSurf,
-                                           mySecondBasisSurf,
-                                           myFirstSurfType,
-                                           mySecondSurfType,
-                                           myAxis,
-                                           myVal,
-                                           myAutomaticPosition,
-                                           myPosition,
-                                           myCenter,
-                                           myFAttach,
-                                           mySAttach,
-                                           myFDir,
-                                           mySDir,
-                                           myPlane );
-  if (myAutomaticPosition && myIsSetBndBox)
-    myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
-
-  Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
-  Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
-#ifdef BUC60915
-  if( !myArrowSizeIsDefined ) {
-#endif
-    Standard_Real arrsize = myCenter.Distance( myPosition );
-      
-    if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
-    if (arrsize == 0.) arrsize = 1.;
-#ifdef BUC60915
-    myArrowSize = arrsize;
+  if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
+      !thePlane.Contains (mySecondPoint, Precision::Confusion()) &&
+      !thePlane.Contains (myCenterPoint, Precision::Confusion()))
+  {
+    return Standard_False;
   }
-  arr->SetLength( myArrowSize );
-#else
-  arr->SetLength(arrsize);
-#endif
-      
-
-  if (myVal <= Precision::Angular() || Abs( M_PI-myVal ) <= Precision::Angular())
-    DsgPrs_AnglePresentation::Add(aPresentation,
-                                 myDrawer,
-                                 myVal,
-                                 myText,
-                                 myCenter,
-                                 myFAttach,
-                                 mySAttach,
-                                 myFDir,
-                                 mySDir,
-                                 myPlane->Pln().Axis().Direction(),
-                                 Standard_False, // not plane
-                                 myAxis,
-                                 myPosition,
-                                 mySymbolPrs);
-  else
-    DsgPrs_AnglePresentation::Add(aPresentation,
-                                 myDrawer,
-                                 myVal,
-                                 myText,
-                                 myCenter,
-                                 myFAttach,
-                                 mySAttach,
-                                 myFDir,
-                                 mySDir,
-                                 myFDir ^ mySDir,
-                                 Standard_False, // not plane
-                                 myAxis,
-                                 myPosition,
-                                 mySymbolPrs);
+
+  return Standard_True;
 }
 
 //=======================================================================
-//function : ComputeTwoPlanarFacesAngle
+//function : ComputePlane
 //purpose  : 
 //=======================================================================
-
-void AIS_AngleDimension::ComputeTwoPlanarFacesAngle( const Handle( Prs3d_Presentation )& aPresentation )
+void AIS_AngleDimension::ComputePlane()
 {
-  AIS::ComputeAngleBetweenPlanarFaces( TopoDS::Face( myFShape ),
-                                      TopoDS::Face( mySShape ),
-                                      mySecondBasisSurf,
-                                      myAxis,
-                                      myVal,
-                                      myAutomaticPosition,
-                                      myPosition,
-                                      myCenter,
-                                      myFAttach,
-                                      mySAttach,
-                                      myFDir,
-                                      mySDir );
-  if (myAutomaticPosition && myIsSetBndBox)
-    myPosition = AIS::TranslatePointToBound( myPosition, gp_Dir( gp_Vec( myCenter, myPosition ) ), myBndBox );
-
-  Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
-  Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
-#ifdef BUC60915
-  if( !myArrowSizeIsDefined ) {
-#endif
-    Standard_Real arrsize = myCenter.Distance( myPosition );
-      
-    if ( (myArrowSize-arrsize) < 0.1 ) arrsize = myArrowSize;
-    if (arrsize == 0.) arrsize = 1.;
-#ifdef BUC60915
-    myArrowSize = arrsize;
+  if (!IsValid())
+  {
+    return;
   }
-  arr->SetLength( myArrowSize );
-#else
-  arr->SetLength(arrsize);
-#endif
-      
-
-  DsgPrs_AnglePresentation::Add(aPresentation,
-                               myDrawer,
-                               myVal,
-                               myText,
-                               myCenter,
-                               myFAttach,
-                               mySAttach,
-                               myFDir,
-                               mySDir,
-                               myAxis.Direction(),
-                               Standard_True,
-                               myAxis,
-                               myPosition,
-                               mySymbolPrs);
-     
+
+  gp_Vec aFirstVec   = gp_Vec (myCenterPoint, myFirstPoint).Normalized();
+  gp_Vec aSecondVec  = gp_Vec (myCenterPoint, mySecondPoint).Normalized();
+  gp_Vec aDirectionN = aSecondVec.Crossed (aFirstVec).Normalized();
+  gp_Vec aDirectionY = (aFirstVec + aSecondVec).Normalized();
+  gp_Vec aDirectionX = aDirectionY.Crossed (aDirectionN).Normalized();
+
+  myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX)));
 }
 
 //=======================================================================
-//function : ComputeTwoEdgesAngle
-//purpose  : 
+//function : GetModelUnits
+//purpose  :
+//=======================================================================
+const TCollection_AsciiString& AIS_AngleDimension::GetModelUnits() const
+{
+  return myDrawer->DimAngleModelUnits();
+}
+
+//=======================================================================
+//function : GetDisplayUnits
+//purpose  :
 //=======================================================================
+const TCollection_AsciiString& AIS_AngleDimension::GetDisplayUnits() const
+{
+  return myDrawer->DimAngleDisplayUnits();
+}
 
-void AIS_AngleDimension::ComputeTwoEdgesAngle(const Handle(Prs3d_Presentation)& aPresentation)
+//=======================================================================
+//function : SetModelUnits
+//purpose  :
+//=======================================================================
+void AIS_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
 {
-  BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
-  BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
-  if ((cu1.GetType() != GeomAbs_Line) || (cu2.GetType() != GeomAbs_Line)) return;
-
-  // current face
-  BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
-  TopoDS_Face face(makeface.Face());  
-  BRepAdaptor_Surface adp(makeface.Face());
-    
-  // 3d lines
-  Handle(Geom_Line) geom_lin1,geom_lin2;
-  gp_Pnt ptat11,ptat12,ptat21,ptat22;//,pint3d;
-  Standard_Boolean isInfinite1,isInfinite2;
-  Handle(Geom_Curve) extCurv;
-  Standard_Integer copyOfMyExtShape = myExtShape;
-  if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
-                           TopoDS::Edge(mySShape),
-                           myExtShape,
-                           geom_lin1,
-                           geom_lin2,
-                           ptat11,
-                           ptat12,
-                           ptat21,
-                           ptat22,
-                           extCurv,
-                           isInfinite1,
-                           isInfinite2,
-                           myPlane)) {
-    return;
-  }
-  // Temporary: computation of myVal
-  //  myVal = Abs(geom_lin1->Lin().Angle( geom_lin2->Lin())); // Pb with angles JPR
-
-  if (copyOfMyExtShape != 0) myExtShape = copyOfMyExtShape;  
-
-  // 2d lines => projection of 3d on current plane
-
-//POP pour NT
-  Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(geom_lin1,myPlane->Pln());
-  Handle(Geom2d_Line) lin1_2d = *((Handle(Geom2d_Line)*)& geoC1);
-  Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(geom_lin2,myPlane->Pln());
-  Handle(Geom2d_Line) lin2_2d = *((Handle(Geom2d_Line)*)& geoC2);
-
-#ifdef BUC60915
-  if( !myArrowSizeIsDefined ) {
-#endif
-    Standard_Real arrSize1(myArrowSize),arrSize2(myArrowSize);
-    if (!isInfinite1) arrSize1 = ptat11.Distance(ptat12)/100.;
-    if (!isInfinite2) arrSize2 = ptat21.Distance(ptat22)/100.;
-#ifdef BUC60655
-    myArrowSize = Min(myArrowSize,Max(arrSize1,arrSize2));
-#else
-    myArrowSize = Min(myArrowSize,Min(arrSize1,arrSize2));
-#endif
-#ifdef BUC60915
-  }
-#endif
-
-
-  // Processing in  case of 2 parallel straight lines
-  if (lin1_2d->Lin2d().Direction()
-      .IsParallel(lin2_2d->Lin2d().Direction(),Precision::Angular())) {    
-    ComputeTwoEdgesNullAngle(aPresentation,
-                            geom_lin1,
-                            geom_lin2,
-                            ptat11,ptat12,
-                            ptat21,ptat22,
-                            isInfinite1,isInfinite2);
-  }
-  
-  // Processing in case of 2 non-parallel straight lines
-  else {
-    ComputeTwoEdgesNotNullAngle(aPresentation,
-                               geom_lin1,
-                               geom_lin2,
-                               ptat11,
-                               ptat12,
-                               ptat21,
-                               ptat22,
-                               isInfinite1,isInfinite2);
-  }
-  if ( (myExtShape != 0) &&  !extCurv.IsNull()) {
-    gp_Pnt pf, pl;
-    if ( myExtShape == 1 ) {
-      if (!isInfinite1) {
-       pf = ptat11; 
-       pl = ptat12;
-      }
-      aPresentation->SetInfiniteState(isInfinite1);
-      ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(myFShape),geom_lin1,pf,pl);
-    }
-    else {
-      if (!isInfinite2) {
-       pf = ptat21; 
-       pl = ptat22;
-      }
-      aPresentation->SetInfiniteState(isInfinite2);
-      ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(mySShape),geom_lin2,pf,pl);
-    }
-  }
+  myDrawer->SetDimAngleModelUnits (theUnits);
 }
 
+//=======================================================================
+//function : SetDisplayUnits
+//purpose  :
+//=======================================================================
+void AIS_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
+{
+  myDrawer->SetDimAngleDisplayUnits (theUnits);
+}
 
 //=======================================================================
-//function : ComputeTwoEdgesNotNullAngle
+//function : ComputeValue
 //purpose  : 
 //=======================================================================
-
-void AIS_AngleDimension::ComputeTwoEdgesNotNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
-                                                    const Handle(Geom_Line)& l1,
-                                                    const Handle(Geom_Line)& l2,
-                                                    const gp_Pnt& ptat11,
-                                                    const gp_Pnt& ptat12,
-                                                    const gp_Pnt& ptat21,
-                                                    const gp_Pnt& ptat22,
-                                                    const Standard_Boolean isInfinite1,
-                                                    const Standard_Boolean isInfinite2)
+Standard_Real AIS_AngleDimension::ComputeValue() const
 {
-  // current face
-  BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
-  TopoDS_Face face(makeface.Face());  
-  BRepAdaptor_Surface adp(makeface.Face());
-  // 2d lines => projection of 3d on current plane
-  Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
-  const Handle(Geom2d_Line)& l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
-  Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
-  const Handle(Geom2d_Line)& l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
-
-  //----------------------------------------------------------
-  //          Computation of myCenter
-  //----------------------------------------------------------
-  IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),l2_2d->Lin2d());
-  if (!inter.IsDone()) return;
-  if (!inter.NbPoints()) return;
-  
-  gp_Pnt2d pint(inter.Point(1).Value());
-  myCenter = adp.Value(pint.X(),pint.Y());
-
-  //----------------------------------------------------------
-  //         Computation of the 2 directions
-  //----------------------------------------------------------
-  gp_Dir d1,d2;
-  if (!isInfinite1) {
-    if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
-    else d1 = gp_Dir(gp_Vec(myCenter,ptat12));  
+  if (!IsValid())
+  {
+    return 0.0;
   }
-  else d1 = l1->Lin().Direction();
 
-  if (!isInfinite2) {
-    if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
-    else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
-  }
-  else d2 = l2->Lin().Direction();
-  if (!isInfinite1) {
-    Standard_Boolean In1(Standard_False);
-    Standard_Boolean In2(Standard_False);
-    if ( !(Abs(d1.Angle(d2) - Abs(myVal)) <= Precision::Confusion())
-        &&  (Abs(myVal) <  M_PI) ) {
-      Standard_Real parcent1 = ElCLib::Parameter(l1->Lin(), myCenter);
-      Standard_Real par11 = ElCLib::Parameter(l1->Lin(), ptat11);
-      Standard_Real par12 = ElCLib::Parameter(l1->Lin(), ptat12);
-      if ( par11 < par12) {
-       if ( ( parcent1> par11) && (parcent1< par12)) {
-         In1 = Standard_True;
-         d1.Reverse();
-       }
-      }
-      else {
-      if ( ( parcent1> par12) && (parcent1< par11)) {
-       In1 = Standard_True;
-       d1.Reverse();
-      }
-      }
-      if ( !In1) {
-       In2 = Standard_True;
-       d2.Reverse();
-      }
-    }
-  }
+  gp_Vec aVec1 (myCenterPoint, myFirstPoint);
+  gp_Vec aVec2 (myCenterPoint, mySecondPoint);
 
-  myFDir = d1;
-  mySDir = d2;
-  gp_Lin theaxis;
-  gp_Lin gpl1 = l1->Lin();
-  gp_Lin gpl2 = l2->Lin();
-  theaxis = gp_Lin(myCenter,myFDir^mySDir);
+  Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction());
 
-  if (myVal >  M_PI) {
-    theaxis.Reverse();
-  }
-  
-  gp_Pnt curpos;  
-  TColStd_Array1OfReal tabdist(1,4);
-  if (!isInfinite1) { 
-    tabdist(1) = theaxis.Distance(ptat11);
-    tabdist(2) = theaxis.Distance(ptat12);
+  return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle);
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : Having three gp_Pnt points compute presentation
+//=======================================================================
+void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
+                                  const Handle(Prs3d_Presentation)& thePresentation,
+                                  const Standard_Integer theMode)
+{
+  thePresentation->Clear();
+  mySelectionGeom.Clear (theMode);
+
+  if (!IsValid())
+  {
+    return;
   }
-  else {
-    tabdist(1) = tabdist(2) = 0.;
+
+  // Parameters for presentation
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
+
+  Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+
+  // prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
+
+  // add margins to label width
+  if (aDimensionAspect->IsText3d())
+  {
+    aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
   }
 
-  if (!isInfinite2) { 
-    tabdist(3) = theaxis.Distance(ptat21);
-    tabdist(4) = theaxis.Distance(ptat22);
+  // Get parameters from aspect or adjust it according with custom text position
+  Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+  Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
+
+  if (IsTextPositionCustom())
+  {
+    AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos);
   }
-  else {
-    tabdist(3) = tabdist(4) = 0.;
+
+  // Handle user-defined and automatic arrow placement
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
+
+  FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal);
+
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+
+  //Arrows positions and directions
+  gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
+
+  gp_Dir aFirstExtensionDir  = aWPDir            ^ gp_Vec (myCenterPoint, aFirstAttach);
+  gp_Dir aSecondExtensionDir = aWPDir.Reversed() ^ gp_Vec (myCenterPoint, aSecondAttach);
+
+  gp_Vec aFirstArrowVec  = gp_Vec (aFirstExtensionDir)  * anArrowLength;
+  gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength;
+
+  gp_Pnt aFirstArrowBegin  (0.0, 0.0, 0.0);
+  gp_Pnt aFirstArrowEnd    (0.0, 0.0, 0.0);
+  gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0);
+  gp_Pnt aSecondArrowEnd   (0.0, 0.0, 0.0);
+
+  if (isArrowsExternal)
+  {
+    aFirstArrowVec.Reverse();
+    aSecondArrowVec.Reverse();
   }
 
-  if (myAutomaticPosition) {
-    Standard_Real length_1(RealLast());
-    if (!isInfinite1) length_1 = .75*Abs(tabdist(2)-tabdist(1))+Min(tabdist(1),tabdist(2));
-
-    Standard_Real length_2(RealLast());
-    if (!isInfinite2) length_2 = .75*Abs(tabdist(4)-tabdist(3))+Min(tabdist(3),tabdist(4));
-    Standard_Real theLength(Min(length_1,length_2));
-    if (Precision::IsInfinite(theLength)) theLength = 50.;
-
-    myFAttach = myCenter.Translated(gp_Vec(d1)*theLength);
-    mySAttach = myCenter.Translated(gp_Vec(d2)*theLength);
-       
-    if (!isInfinite1) {
-      Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,myFAttach));
-      Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
-      Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
-      if (par_p1_attach > par11 && par_p1_attach > par12) {
-       par_p1_attach = Max(par11,par12);
-       myFAttach = ElCLib::Value(par_p1_attach,gpl1);
-      }
-      else if (par_p1_attach < par11 && par_p1_attach < par12) {
-       par_p1_attach = Min(par11,par12);
-       myFAttach = ElCLib::Value(par_p1_attach,gpl1);
+  aFirstArrowBegin  = aFirstAttach;
+  aSecondArrowBegin = aSecondAttach;
+  aFirstArrowEnd    = aFirstAttach.Translated (-aFirstArrowVec);
+  aSecondArrowEnd   = aSecondAttach.Translated (-aSecondArrowVec);
+
+  // Group1: stenciling text and the angle dimension arc
+  Prs3d_Root::NewGroup (thePresentation);
+
+  Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
+
+  // draw text label
+  switch (aHPosition)
+  {
+    case LabelPosition_HCenter :
+    {
+      Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
+                                  && aDimensionAspect->IsText3d();
+
+      if (isLineBreak)
+      {
+        DrawArcWithText (thePresentation,
+                         aFirstAttach,
+                         aSecondAttach,
+                         myCenterPoint,
+                         aLabelString,
+                         aLabelWidth,
+                         theMode,
+                         aLabelPosition);
+        break;
       }
-    }
 
-    if (!isInfinite2) {
-      Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,mySAttach));
-      Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
-      Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
-      if (par_p2_attach > par21 && par_p2_attach > par22) {
-       par_p2_attach = Max(par21,par22);
-       mySAttach = ElCLib::Value(par_p2_attach,gpl2);
+      // compute text primitives
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
+      {
+        gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
+        gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
+                                                : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+        gp_Dir aTextDir = aDimensionDir;
+
+        DrawText (thePresentation,
+                  aTextPos,
+                  aTextDir,
+                  aLabelString,
+                  aLabelPosition);
       }
-      else if (par_p2_attach < par21 && par_p2_attach < par22) {
-       par_p2_attach = Min(par21,par22);
-       mySAttach = ElCLib::Value(par_p2_attach,gpl2);
+
+      if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
+      {
+        DrawArc (thePresentation,
+                 isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
+                 isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
+                 myCenterPoint,
+                 Abs (GetFlyout()),
+                 theMode);
       }
     }
-    if ( myVal < M_PI) curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ())); 
-    else {
-      curpos.SetXYZ(.5*(myFAttach.XYZ()+mySAttach.XYZ())); 
-      gp_Vec transl(curpos, myCenter);
-      transl*= 2;
-      curpos.Translate(transl);
+    break;
+
+    case LabelPosition_Left :
+    {
+      DrawExtension (thePresentation,
+                     anExtensionSize,
+                     isArrowsExternal ? aFirstArrowEnd : aFirstAttach,
+                     aFirstExtensionDir,
+                     aLabelString,
+                     aLabelWidth,
+                     theMode,
+                     aLabelPosition);
+    }
+    break;
+
+    case LabelPosition_Right :
+    {
+      DrawExtension (thePresentation,
+                     anExtensionSize,
+                     isArrowsExternal ? aSecondArrowEnd : aSecondAttach,
+                     aSecondExtensionDir,
+                     aLabelString,
+                     aLabelWidth,
+                     theMode,
+                     aLabelPosition);
     }
+    break;
+  }
 
-    gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
-    gp_Circ circle(ax,theLength);
-    Standard_Real par = ElCLib::Parameter(circle,curpos);
-    curpos = ElCLib::Value(par,circle);    
-
-    // small offset like in LengthDimension
-    gp_Vec transl(myCenter, curpos);
-    transl*= 0.3;
-    curpos.Translate(transl);
-    
-    if (myIsSetBndBox)
-      curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
-
-    myPosition = curpos;
-    myAutomaticPosition = Standard_True;      
+  // dimension arc without text
+  if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter)
+  {
+    Prs3d_Root::NewGroup (thePresentation);
+
+    DrawArc (thePresentation,
+             isArrowsExternal ? aFirstAttach  : aFirstArrowEnd,
+             isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
+             myCenterPoint,
+             Abs(GetFlyout ()),
+             theMode);
   }
 
-  else {
-  // point is projected on the plane
-    gp_Pnt2d pointOnPln(ProjLib::Project(myPlane->Pln(),myPosition));
-    myPosition = BRepAdaptor_Surface(BRepBuilderAPI_MakeFace(myPlane->Pln()).Face()).Value(pointOnPln.X(),pointOnPln.Y());
-    curpos = myPosition;
-    Standard_Real dist(curpos.Distance(myCenter));    
-    if (dist<=Precision::Confusion()) {
-      gp_XYZ delta(1.,1.,1.);
-      curpos.SetXYZ(curpos.XYZ()+delta);
-      dist = curpos.Distance(myCenter);
+  // arrows and arrow extensions
+  if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
+  {
+    Prs3d_Root::NewGroup (thePresentation);
+
+    DrawArrow (thePresentation, aFirstArrowBegin,  gp_Dir (aFirstArrowVec));
+    DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
+  }
+
+  if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
+  {
+    Prs3d_Root::NewGroup (thePresentation);
+
+    if (aHPosition != LabelPosition_Left)
+    {
+      DrawExtension (thePresentation,
+                     aDimensionAspect->ArrowTailSize(),
+                     aFirstArrowEnd,
+                     aFirstExtensionDir,
+                     THE_EMPTY_LABEL_STRING,
+                     THE_EMPTY_LABEL_WIDTH,
+                     theMode,
+                     LabelPosition_None);
     }
-    // To learn if it is necessary to take distance -dist or not
-    // it is necessary to know if we are in the sector opposite to the angle
-    // if not : we are in the opposite sector if the coordinates
-    // of curpos in point (d1,d2) are negative
-    gp_Ax2 ax(myCenter,myFDir.Crossed(mySDir),myFDir);
-    gp_Circ circle(ax,dist);
-#ifdef DEB
-//    gp_Pnt p1(myCenter.Translated(gp_Vec(d1)*dist));
-#endif
-    gp_Pnt p2(myCenter.Translated(gp_Vec(d2)*dist));
-    Standard_Real uc1 = 0;
-    Standard_Real uc2 = ElCLib::Parameter(circle, p2 );
-    Standard_Real uco = ElCLib::Parameter(circle, curpos );
-    Standard_Real udeb = uc1;
-    Standard_Real ufin = uc2;
-    if (uco > ufin) {
-      if (Abs(myVal)<M_PI) {
-       // test if uco is in the opposite sector 
-       if (uco > udeb+M_PI && uco < ufin+M_PI){
-         dist = -dist;
-       }
-      }
+
+    if (aHPosition != LabelPosition_Right)
+    {
+      DrawExtension (thePresentation,
+                     aDimensionAspect->ArrowTailSize(),
+                     aSecondArrowEnd,
+                     aSecondExtensionDir,
+                     THE_EMPTY_LABEL_STRING,
+                     THE_EMPTY_LABEL_WIDTH,
+                     theMode,
+                     LabelPosition_None);
     }
+  }
 
-     gp_Pnt p1_attach(myCenter.Translated(gp_Vec(d1)*dist));
-     gp_Pnt p2_attach(myCenter.Translated(gp_Vec(d2)*dist));
-    
-     if (!isInfinite1) {
-       Standard_Real par_p1_attach(ElCLib::Parameter(gpl1,p1_attach));
-       Standard_Real par11 = ElCLib::Parameter(gpl1,ptat11);
-       Standard_Real par12 = ElCLib::Parameter(gpl1,ptat12);
-       if (par_p1_attach > par11 && par_p1_attach > par12) {
-        par_p1_attach = Max(par11,par12);
-        p1_attach = ElCLib::Value(par_p1_attach,gpl1);
-       }
-       else if (par_p1_attach < par11 && par_p1_attach < par12) {
-        par_p1_attach = Min(par11,par12);
-        p1_attach = ElCLib::Value(par_p1_attach,gpl1);
-       }
-     }
-     myFAttach = p1_attach;
-           
-     if (!isInfinite2) {
-       Standard_Real par_p2_attach(ElCLib::Parameter(gpl2,p2_attach));
-       Standard_Real par21 = ElCLib::Parameter(gpl2,ptat21);
-       Standard_Real par22 = ElCLib::Parameter(gpl2,ptat22);
-       if (par_p2_attach > par21 && par_p2_attach > par22) {
-        par_p2_attach = Max(par21,par22);
-        p2_attach = ElCLib::Value(par_p2_attach,gpl2);
-       }
-       else if (par_p2_attach < par21 && par_p2_attach < par22) {
-        par_p2_attach = Min(par21,par22);
-        p2_attach = ElCLib::Value(par_p2_attach,gpl2);
-       }
-     }
-     mySAttach = p2_attach;
-  }  
-  myAxis = theaxis.Position();
-
-  //--------------------------------------------------------
-  //    Computation of the presentation
-  //--------------------------------------------------------
-  Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
-  Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
-
-  arr->SetLength(myArrowSize);
-
-  DsgPrs_AnglePresentation::Add(aPresentation,
-                               myDrawer,
-                               myVal,
-                               myText,
-                               myCenter,
-                               myFAttach,
-                               mySAttach,
-                               myFDir,
-                               mySDir,
-                               curpos,
-                               mySymbolPrs);
-}
+  // flyouts
+  if (theMode == ComputeMode_All)
+  {
+    Prs3d_Root::NewGroup (thePresentation);
+
+    Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
+    aPrimSegments->AddVertex (myCenterPoint);
+    aPrimSegments->AddVertex (aFirstAttach);
+    aPrimSegments->AddVertex (myCenterPoint);
+    aPrimSegments->AddVertex (aSecondAttach);
 
+    Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
+    Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle);
+    Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
+  }
 
+  myIsComputed = Standard_True;
+}
 
 //=======================================================================
-//function : ComputeTwoEdgesNullAngle
-//purpose  : compute the presentation of a angle dimension if it's null.
-//             -> the aim of the computation is to have a constant radius 
-//                during the dimension moving : the radius is independant
-//                of the cursor position, it's equal to a arbitrary value
+//function : ComputeFlyoutSelection
+//purpose  : computes selection for flyouts
 //=======================================================================
+void AIS_AngleDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
+                                                 const Handle(SelectMgr_EntityOwner)& theOwner)
+{
+  gp_Pnt aFirstAttach  = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized()  * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+
+  Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
+  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aFirstAttach));
+  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aSecondAttach));
+
+  theSelection->Add (aSensitiveEntity);
+}
 
-void AIS_AngleDimension::ComputeTwoEdgesNullAngle(const Handle(Prs3d_Presentation)& aPresentation,
-                                                 const Handle(Geom_Line)& l1,
-                                                 const Handle(Geom_Line)& l2,
-                                                 const gp_Pnt& ptat11,
-                                                 const gp_Pnt& ptat12,
-                                                 const gp_Pnt& ptat21,
-                                                 const gp_Pnt& ptat22,
-                                                 const Standard_Boolean isInfinite1,
-                                                 const Standard_Boolean isInfinite2)
+//=======================================================================
+//function : InitTwoEdgesAngle
+//purpose  : 
+//=======================================================================
+Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane)
 {
-  // current face
-  BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
-  TopoDS_Face face(makeface.Face());  
-  BRepAdaptor_Surface adp(makeface.Face());
-  // 2d lines => projection of 3d on current plane
-  Handle(Geom2d_Curve) geoC1 = GeomAPI::To2d(l1,myPlane->Pln());
-  Handle(Geom2d_Line) l1_2d = *((Handle(Geom2d_Line)*)& geoC1);
-  Handle(Geom2d_Curve) geoC2 = GeomAPI::To2d(l2,myPlane->Pln());
-  Handle(Geom2d_Line) l2_2d = *((Handle(Geom2d_Line)*)& geoC2);
-
-  gp_Lin gpl1 = l1->Lin();
-  gp_Lin gpl2 = l2->Lin();
-
-  //------------------------------------------------------------
-  //                Computation of myCenter
-  // -> Point located on the median of 2 straight lines,
-  //    is calculated as located between 2 closest points 
-  //    of each straight line.
-  //-----------------------------------------------------------
-     //   theLength : radius of the future circle
-  Standard_Real theLength = gpl1.Distance(gpl2.Location());
-  // processing of the particular case when 2 straight lines are coincident
-  Standard_Boolean SameLines(Standard_False);
-  if ( theLength <= Precision::Confusion()) {
-    SameLines = Standard_True;
-    if (!isInfinite1) {
-      if (!isInfinite2) theLength = 0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
-      else theLength = 0.75*ptat11.Distance(ptat12);
-    }
-    else {
-      if (!isInfinite2) theLength = 0.75*ptat21.Distance(ptat22);
-      else theLength = 50.;
-    }
-  }
-  else theLength = theLength*8/10;
-
-  gp_Pnt pmin1 ,pmin2;
-  if (!isInfinite1 && !isInfinite2) {
-    pmin1 = ptat11; pmin2 = ptat21;
-    Standard_Real dis = ptat11.Distance(ptat21);
-    Standard_Real dis2 = ptat11.Distance(ptat22);
-    if ( dis2 < dis)  {
-      pmin1 = ptat11;
-      pmin2 = ptat22;
-      dis = dis2;
-    }
-    dis2 = ptat12.Distance(ptat22);
-    if ( dis2 < dis)  {
-      pmin1 = ptat12;
-      pmin2 = ptat22;
-      dis = dis2;
-    }
-    dis2 = ptat12.Distance(ptat21);
-    if ( dis2 < dis)  {
-      pmin1 = ptat12;
-      pmin2 = ptat21;
-      dis = dis2;
-    }
-    myCenter.SetXYZ( (pmin1.XYZ() + pmin2.XYZ()) / 2. );
-  }
-  else {
-    gp_Pnt pntOnl1 = gpl1.Location();
-    gp_Pnt pntOnl2 = ElCLib::Value(ElCLib::Parameter(gpl1,pntOnl1),gpl2);
-    myCenter.SetXYZ( (pntOnl1.XYZ() + pntOnl2.XYZ()) / 2. );
-  }
+  TopoDS_Edge aFirstEdge  = TopoDS::Edge (myFirstShape);
+  TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
 
-  
-  // directions 
-  gp_Dir d1,d2;
-  if (!isInfinite1) {
-    if (myCenter.SquareDistance(ptat11) > myCenter.SquareDistance(ptat12)) d1 = gp_Dir(gp_Vec(myCenter,ptat11));
-    else d1 = gp_Dir(gp_Vec(myCenter,ptat12));  
-  }
-  else d1 = gpl1.Direction();
-  
-  if (!isInfinite2) {
-    if (myCenter.SquareDistance(ptat21) > myCenter.SquareDistance(ptat22)) d2 = gp_Dir(gp_Vec(myCenter,ptat21));
-    else d2 = gp_Dir(gp_Vec(myCenter,ptat22));
+  BRepAdaptor_Curve aMakeFirstLine  (aFirstEdge);
+  BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
+
+  if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
+  {
+    return  Standard_False;
   }
-  else d2 = gpl2.Direction();  
-
-  gp_Dir theaxis;
-  if ( SameLines ) theaxis = myPlane->Pln().Axis().Direction();
-  else {
-    theaxis = gp_Dir(d1^d2);
-    gp_Vec V1(d1); gp_Vec V2(d2);
-    if ( V1.CrossMagnitude(V2) < 0 ) theaxis.Reverse();
+
+  Handle(Geom_Line) aFirstLine  = new Geom_Line (aMakeFirstLine.Line());
+  Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
+
+  gp_Lin aFirstLin  = aFirstLine->Lin();
+  gp_Lin aSecondLin = aSecondLine->Lin();
+
+  Standard_Boolean isParallelLines = Abs (aFirstLin.Angle (aSecondLin) - M_PI) <= Precision::Angular();
+
+  gp_Pnt aPoint  = aFirstLine->Value (0.0);
+  gp_Dir aNormal = isParallelLines
+                     ? gp_Vec (aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
+                     : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
+
+  theComputedPlane = gp_Pln (aPoint, aNormal);
+
+    // Compute geometry for this plane and edges
+  Standard_Boolean isInfinite1,isInfinite2;
+  gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
+  gp_Lin2d aFirstLin2d, aSecondLin2d;
+
+  if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
+                             aFirstLine, aSecondLine,
+                             aFirstPoint1, aLastPoint1,
+                             aFirstPoint2, aLastPoint2,
+                             isInfinite1, isInfinite2))
+  {
+    return Standard_False;
   }
 
-  gp_Pnt curpos; // cursor position
-  TColStd_Array1OfReal tabdist(1,4);
-  gp_Pnt P1, P2; // points at intersection of the circle with 2 straight lines
-  if (myAutomaticPosition) {
-    if (!isInfinite1) {
-      tabdist(1) = myCenter.Distance(ptat11);
-      tabdist(2) = myCenter.Distance(ptat12);
-    }
-    else {
-      tabdist(1) = tabdist(2) = 0.;
-    }
-    if (!isInfinite2) { 
-      tabdist(3) = myCenter.Distance(ptat21);
-      tabdist(4) = myCenter.Distance(ptat22);
-    }
-    else {
-      tabdist(3) = tabdist(4) = 0.;
-    }
-    if ( SameLines ) {
-      Standard_Real dist1(RealLast());
-      if (!isInfinite1) dist1 = Max(tabdist(1),tabdist(2));
-      Standard_Real dist2(RealLast());
-      if (!isInfinite2) dist2 = Max(tabdist(3),tabdist(4));      
-      
-      myFAttach = myCenter;
-      mySAttach = myCenter;
-      P1 = myFAttach;
-      P2 = mySAttach;
-
-      myCenter.Translate(gp_Vec(d1)*theLength);
-
-      // calculate attachments of the face 
-      //  -> they are points of intersection if  
-      //     intersection is outside of the edges
-      Standard_Real pparam = ElCLib::Parameter(gpl1,myFAttach);
-      Standard_Real pparam1 = ElCLib::Parameter(gpl1,ptat11);
-      Standard_Real pparam2 = ElCLib::Parameter(gpl1,ptat12);
-      if (!isInfinite1) {
-       if ( pparam1 < pparam2 ) {
-         if ( pparam < pparam1 ) myFAttach = ptat11;
-         else if ( pparam > pparam2) myFAttach = ptat12;
-       }
-       else {
-         if ( pparam < pparam2) myFAttach = ptat12;
-         else if ( pparam > pparam1) myFAttach = ptat11;
-       }
-      }
-      if (!isInfinite2) {
-       pparam = ElCLib::Parameter(gpl2,myFAttach);
-       pparam1 = ElCLib::Parameter(gpl2,ptat21);
-       pparam2 = ElCLib::Parameter(gpl2,ptat22);
-       if ( pparam1 < pparam2 ) {
-         if ( pparam < pparam1 ) mySAttach = ptat21;
-         else if ( pparam > pparam2) mySAttach = ptat22;
-       }
-       else {
-         if ( pparam < pparam2) mySAttach = ptat22;
-         else if ( pparam > pparam1) mySAttach = ptat21;
-       }
-      }
-    }
-    // Case of disconneted lines
-    else {
-      gp_Ax2 AX(myCenter,theaxis,d1);
-      Handle(Geom_Circle)  circle = new Geom_Circle(AX,theLength);
-      Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
-      Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
-      // calculate the intersection of circle with l1
-      Standard_Real pparam; // parameter of the point of intersection on l1
-      IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
-      gp_Pnt2d pint1(inter.Point(1).Value());
-      gp_Pnt2d pint2(inter.Point(2).Value());
-      
-      gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
-      gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
-      gp_Dir I1I2(gp_Vec(Int1,Int2));
-      if ( d1*I1I2 > 0 ) {
-       myFAttach = Int2;
-       pparam = inter.Point(2).ParamOnFirst();
-      }
-      else {
-       myFAttach = Int1;
-       pparam = inter.Point(1).ParamOnFirst();
-      }
-      P1 = myFAttach;
-
-      Standard_Real pparam1;
-      Standard_Real pparam2; 
-      if (!isInfinite1) {
-       pparam1 = ElCLib::Parameter(gpl1,ptat11);
-       pparam2 = ElCLib::Parameter(gpl1,ptat12);       
-       if ( pparam1 < pparam2 ) {
-         if ( pparam < pparam1 ) myFAttach = ptat11;
-         else if ( pparam > pparam2) myFAttach = ptat12;
-       }
-       else {
-         if ( pparam < pparam2) myFAttach = ptat12;
-         else if ( pparam > pparam1) myFAttach = ptat11;
-       }
-      }
-      pparam = ElCLib::Parameter(gpl2,P1);
-      mySAttach = ElCLib::Value(pparam, gpl2);
-      P2 = mySAttach;
-
-      if (!isInfinite2) {
-       pparam1 = ElCLib::Parameter(gpl2,ptat21);
-       pparam2 = ElCLib::Parameter(gpl2,ptat22);
-       if ( pparam1 < pparam2 ) {
-         if ( pparam < pparam1 ) mySAttach = ptat21;
-         else if ( pparam > pparam2) mySAttach = ptat22;
-       }
-       else {
-         if ( pparam < pparam2) mySAttach = ptat22;
-         else if ( pparam > pparam1) mySAttach = ptat21;
-       }
-      }
-    }
-    curpos.SetXYZ(.5*(P1.XYZ()+P2.XYZ()));
+  if (aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular()))
+  {
+    myFirstPoint  = aFirstLin.Location();
+    mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
 
-    gp_Ax2 ax(myCenter,theaxis,d1);
-    gp_Circ circle(ax,theLength);
-    Standard_Real par = ElCLib::Parameter(circle,curpos);
-    curpos = ElCLib::Value(par,circle);
+    if (mySecondPoint.Distance (myFirstPoint) <= Precision::Confusion())
+    {
+      mySecondPoint.Translate (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
+    }
 
-    if (myIsSetBndBox)
-      curpos = AIS::TranslatePointToBound( curpos, gp_Dir( gp_Vec( myCenter, curpos ) ), myBndBox );
-    myPosition =curpos;
-    myAutomaticPosition = Standard_True;      
+    myCenterPoint.SetXYZ ((myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2.0);
   }
-  else {
-    curpos = myPosition;
-    gp_Lin Media(myCenter, gpl1.Direction());
-    Standard_Real pcurpos = ElCLib::Parameter(Media, curpos);
-    myCenter =  ElCLib::Value(pcurpos, Media);
-    // the centre is translated to avoid a constant radius!
-    myCenter.Translate(-theLength*gp_Vec(gpl1.Direction()));
-    gp_Ax2 AX(myCenter,theaxis,gpl1.Direction());
-    Handle(Geom_Circle)  circle = new Geom_Circle(AX,theLength);
-
-    // re-update curpos
-    pcurpos = ElCLib::Parameter(circle->Circ(), curpos);
-    curpos = ElCLib::Value(pcurpos, circle->Circ());
-
-    Handle(Geom2d_Curve) geoCurve = GeomAPI::To2d(circle,myPlane->Pln());
-    Handle(Geom2d_Circle) c2d = *((Handle(Geom2d_Circle)*)& geoCurve);
-    // calculate the point of intersection of circle with l1
-    IntAna2d_AnaIntersection inter(l1_2d->Lin2d(),c2d->Circ2d());
-    gp_Pnt2d pint1(inter.Point(1).Value());
-    gp_Pnt2d pint2(inter.Point(2).Value());
-    gp_Pnt Int1 = adp.Value(pint1.X(),pint1.Y());
-    gp_Pnt Int2 = adp.Value(pint2.X(),pint2.Y());
-    if ( curpos.SquareDistance(Int1) < curpos.SquareDistance(Int2)) myFAttach = Int1;
-    else myFAttach = Int2;
-    P1 = myFAttach;
-    
-    // calculate the point of intersection of circle with l2
-    // -> this is the projection because the centre of circle
-    //    is in the middle of l1 and l2
-    Standard_Real pparam = ElCLib::Parameter(gpl2,myFAttach);
-    mySAttach = ElCLib::Value(pparam, gpl2);
-
-    P2 = mySAttach;
-
-    Standard_Real par_attach(ElCLib::Parameter(gpl1,myFAttach));
-    Standard_Real par1,par2; 
-    if (!isInfinite1) {
-      par1 = ElCLib::Parameter(gpl1,ptat11);
-      par2 = ElCLib::Parameter(gpl1,ptat12);
-      if (par1 < par2) {
-       if ( par_attach < par1 ) myFAttach = ptat11;
-       else if ( par_attach > par2) myFAttach = ptat12;
-      }
-      else {
-       if ( par_attach < par2 ) myFAttach = ptat12;
-       else if ( par_attach > par1) myFAttach = ptat11;
-      }
+  else
+  {
+    // Find intersection
+    gp_Lin2d aFirstLin2d  = ProjLib::Project (theComputedPlane, aFirstLin);
+    gp_Lin2d aSecondLin2d = ProjLib::Project (theComputedPlane, aSecondLin);
+
+    IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
+    gp_Pnt2d anIntersectPoint;
+    if (!anInt2d.IsDone() || anInt2d.IsEmpty())
+    {
+      return Standard_False;
     }
-    par_attach = ElCLib::Parameter(gpl2,mySAttach);
-    if (!isInfinite2) {
-      par1 = ElCLib::Parameter(gpl2,ptat21);
-      par2 = ElCLib::Parameter(gpl2,ptat22);
-      if (par1 < par2) {
-       if ( par_attach < par1 ) mySAttach = ptat21;
-       else if ( par_attach > par2) mySAttach = ptat22;
-      }
-      else {
-       if ( par_attach < par2 ) mySAttach = ptat22;
-       else if ( par_attach > par1) mySAttach = ptat21;
-      }
+
+    anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
+    myCenterPoint = ElCLib::To3d (theComputedPlane.Position().Ax2(), anIntersectPoint);
+
+    if (isInfinite1 || isInfinite2)
+    {
+      myFirstPoint  = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout()));
+      mySecondPoint = myCenterPoint.Translated (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
+
+      return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
     }
+
+    // |
+    // | <- dimension should be here
+    // *----
+    myFirstPoint  = myCenterPoint.Distance (aFirstPoint1) > myCenterPoint.Distance (aLastPoint1)
+                  ? aFirstPoint1
+                  : aLastPoint1;
+
+    mySecondPoint = myCenterPoint.Distance (aFirstPoint2) > myCenterPoint.Distance (aLastPoint2)
+                  ? aFirstPoint2
+                  : aLastPoint2;
   }
 
-  myFDir = gp_Dir(gp_Vec(myCenter,P1));
-  mySDir = gp_Dir(gp_Vec(myCenter,P2));
-
-  //--------------------------------------------------------
-  //    Computation of the presentation
-  //--------------------------------------------------------
-  Handle(Prs3d_AngleAspect) la = myDrawer->AngleAspect();
-  Handle(Prs3d_ArrowAspect) arr = la->ArrowAspect();
-
-  arr->SetLength(myArrowSize);
-
-  if (SameLines)
-    DsgPrs_AnglePresentation::Add(aPresentation,
-                                 myDrawer,
-                                 myVal,
-                                 myText,
-                                 myCenter,
-                                 myFAttach,
-                                 mySAttach,
-                                 myFDir,
-                                 mySDir,
-                                 theaxis,
-                                 Standard_True,
-                                 myAxis,
-                                 curpos,
-                                 DsgPrs_AS_NONE);
-  else
-    DsgPrs_AnglePresentation::Add(aPresentation,
-                                 myDrawer,
-                                 myVal,
-                                 myText,
-                                 myCenter,
-                                 myFAttach,
-                                 mySAttach,
-                                 myFDir,
-                                 mySDir,
-                                 curpos,
-                                 mySymbolPrs);
+  return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
 }
 
-
 //=======================================================================
-//function : Compute3DSelection
-// purpose  : compute the zones of selection for an angle dimension
-//            between 2 faces
+//function : InitTwoFacesAngle
+//purpose  : initialization of angle dimension between two faces
 //=======================================================================
-
-void AIS_AngleDimension::Compute3DSelection( const Handle( SelectMgr_Selection )& aSelection )
+Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle()
 {
-  gp_Circ AngleCirc, AttachCirc;
-  Standard_Real FirstParAngleCirc, LastParAngleCirc, FirstParAttachCirc, LastParAttachCirc;
-  gp_Pnt EndOfArrow1, EndOfArrow2, ProjAttachPoint2;
-  gp_Dir DirOfArrow1, DirOfArrow2;
-  gp_Dir axisdir = (myVal <= Precision::Angular() || Abs( M_PI-myVal ) <= Precision::Angular())?
-                    myPlane->Pln().Axis().Direction() : (myFDir ^ mySDir);
-  Standard_Boolean isPlane = (myFirstSurfType == AIS_KOS_Plane)? Standard_True : Standard_False;
-
-  Standard_Real ArrowLength = myDrawer->AngleAspect()->ArrowAspect()->Length();
-  DsgPrs::ComputeFacesAnglePresentation( ArrowLength,
-                                        myVal,
-                                        myCenter,
-                                        myFAttach,
-                                        mySAttach,
-                                        myFDir,
-                                        mySDir,
-                                        axisdir,
-                                        isPlane,
-                                        myAxis,
-                                        myPosition,
-                                        AngleCirc,
-                                        FirstParAngleCirc,
-                                        LastParAngleCirc,
-                                        EndOfArrow1,
-                                        EndOfArrow2,
-                                        DirOfArrow1,
-                                        DirOfArrow2,
-                                        ProjAttachPoint2,
-                                        AttachCirc,
-                                        FirstParAttachCirc,
-                                        LastParAttachCirc );
-  
-  Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
-  Handle( Select3D_SensitiveSegment ) seg;
-  Handle( Geom_TrimmedCurve ) curve; 
-  Handle( Select3D_SensitiveCurve ) SensCurve;
+  TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
+  TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
 
-  // Angle's arc or line
-  if (myVal > Precision::Angular() && Abs( M_PI-myVal ) > Precision::Angular())
-    {
-      curve = new Geom_TrimmedCurve( new Geom_Circle( AngleCirc ), FirstParAngleCirc, LastParAngleCirc );
-      SensCurve = new Select3D_SensitiveCurve( own, curve );
-      aSelection->Add( SensCurve );
-    }
-  else // angle's line
-    {
-      gp_Vec ArrowVec( DirOfArrow1 );
-      ArrowVec *= ArrowLength;
-      gp_Pnt FirstPoint, LastPoint;
-
-      if (myPosition.Distance( EndOfArrow1 ) > ArrowLength)
-       {
-         FirstPoint = myPosition;
-         LastPoint = EndOfArrow1.Translated( ArrowVec );
-         if (myPosition.SquareDistance( LastPoint ) < myPosition.SquareDistance( EndOfArrow1 ))
-           LastPoint = EndOfArrow1.Translated( -ArrowVec );
-       }
-      else
-       {
-         FirstPoint = EndOfArrow1.Translated( ArrowVec );
-         LastPoint = EndOfArrow1.Translated( -ArrowVec );
-       }
-      seg = new Select3D_SensitiveSegment( own, FirstPoint, LastPoint );
-      aSelection->Add( seg );
-    }
+  gp_Dir aFirstDir, aSecondDir;
+  gp_Pln aFirstPlane, aSecondPlane;
+  Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
+  AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
+  Standard_Real aFirstOffset, aSecondOffset;
 
-  if (! myFAttach.IsEqual( EndOfArrow1, Precision::Confusion() ))
-    {
-      seg = new Select3D_SensitiveSegment( own, myFAttach, EndOfArrow1 );
-      aSelection->Add( seg );
-    }
-  if (! ProjAttachPoint2.IsEqual( EndOfArrow2, Precision::Confusion() ))
-    {
-      seg = new Select3D_SensitiveSegment( own, ProjAttachPoint2, EndOfArrow2 );
-      aSelection->Add( seg );
-    }
+  AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
+                         aFirstBasisSurf,aFirstSurfType,aFirstOffset);
 
-  // Line or arc from mySAttach to its "projection"
-  if (! mySAttach.IsEqual( ProjAttachPoint2, Precision::Confusion() ))
-    {
-      if (isPlane)
-       {
-         seg = new Select3D_SensitiveSegment( own, mySAttach, ProjAttachPoint2 );
-         aSelection->Add( seg );
-       }
-      else
-       {
-         curve = new Geom_TrimmedCurve( new Geom_Circle( AttachCirc ),
-                                        FirstParAttachCirc,
-                                        LastParAttachCirc );
-         SensCurve = new Select3D_SensitiveCurve( own, curve );
-         aSelection->Add( SensCurve );
-       }
-    }
+  AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
+                         aSecondBasisSurf, aSecondSurfType, aSecondOffset);
 
-  // Text
-  Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
-  Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
-                                                                  myPosition.X(),
-                                                                  myPosition.Y(),
-                                                                  myPosition.Z(),
-                                                                  myPosition.X() + size,
-                                                                  myPosition.Y() + size,
-                                                                  myPosition.Z() + size);  
-  aSelection->Add(box);
+  if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
+  {
+    //Planar faces angle
+    Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
+    Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
+    return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
+                                             aSecondFace,
+                                             myCenterPoint,
+                                             myFirstPoint,
+                                             mySecondPoint)
+           && IsValidPoints (myFirstPoint,
+                             myCenterPoint,
+                             mySecondPoint);
+  }
+  else
+  {
+    // Curvilinear faces angle
+    return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
+                                                  aSecondFace,
+                                                  aFirstSurfType,
+                                                  aSecondSurfType,
+                                                  myCenterPoint,
+                                                  myFirstPoint,
+                                                  mySecondPoint)
+           && IsValidPoints (myFirstPoint,
+                             myCenterPoint,
+                             mySecondPoint);
+  }
 }
 
 //=======================================================================
-//function : Compute2DSelection
-//purpose  : compute zones of selection on a side of angle between 2 edges
-//           Special processing of zero angles!
+//function : InitTwoFacesAngle
+//purpose  : initialization of angle dimension between two faces
 //=======================================================================
+Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace)
+{
+  TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
+  TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
 
-void AIS_AngleDimension::Compute2DSelection(const Handle(SelectMgr_Selection)& aSelection)
+  gp_Dir aFirstDir, aSecondDir;
+  gp_Pln aFirstPlane, aSecondPlane;
+  Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf;
+  AIS_KindOfSurface aFirstSurfType, aSecondSurfType;
+  Standard_Real aFirstOffset, aSecondOffset;
+
+  AIS::GetPlaneFromFace (aFirstFace, aFirstPlane,
+                         aFirstBasisSurf,aFirstSurfType,aFirstOffset);
+
+  AIS::GetPlaneFromFace (aSecondFace, aSecondPlane,
+                         aSecondBasisSurf, aSecondSurfType, aSecondOffset);
+
+  myFirstPoint = thePointOnFirstFace;
+  if (aFirstSurfType == AIS_KOS_Plane && aSecondSurfType == AIS_KOS_Plane)
+  {
+    //Planar faces angle
+    Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf);
+    Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf);
+    return AIS::InitAngleBetweenPlanarFaces (aFirstFace,
+                                             aSecondFace,
+                                             myCenterPoint,
+                                             myFirstPoint,
+                                             mySecondPoint,
+                                             Standard_True)
+           && IsValidPoints (myFirstPoint,
+                             myCenterPoint,
+                             mySecondPoint);
+  }
+  else
+  {
+    // Curvilinear faces angle
+    return AIS::InitAngleBetweenCurvilinearFaces (aFirstFace,
+                                                  aSecondFace,
+                                                  aFirstSurfType,
+                                                  aSecondSurfType,
+                                                  myCenterPoint,
+                                                  myFirstPoint,
+                                                  mySecondPoint,
+                                                  Standard_True)
+           && IsValidPoints (myFirstPoint,
+                             myCenterPoint,
+                             mySecondPoint);
+  }
+}
+
+//=======================================================================
+//function : InitConeAngle
+//purpose  : initialization of the cone angle
+//=======================================================================
+Standard_Boolean AIS_AngleDimension::InitConeAngle()
 {
-  BRepAdaptor_Curve cu1(TopoDS::Edge(myFShape));
-  BRepAdaptor_Curve cu2(TopoDS::Edge(mySShape));
-
-  gp_Lin l1(cu1.Line());
-  gp_Lin l2(cu2.Line());
-
-  // it is patch!
-  if (Abs( myVal ) <= Precision::Angular() || Abs( M_PI - myVal ) <= Precision::Angular())
-/*
-  //---------------------------------------------------------
-  //    Cas de droites paralleles ( <=> angle nul a M_PI pres)
-  if ((Abs(l1.Angle(l2)) < Precision::Angular()) ||
-      (Abs((l1.Angle(l2) - M_PI)) < Precision::Angular()) )
-*/
+  if (myFirstShape.IsNull())
+  {
+    return Standard_False;
+  }
+
+  TopoDS_Face aConeShape = TopoDS::Face (myFirstShape);
+  gp_Pln aPln;
+  gp_Cone aCone;
+  gp_Circ aCircle;
+  // A surface from the Face
+  Handle(Geom_Surface) aSurf;
+  Handle(Geom_OffsetSurface) aOffsetSurf; 
+  Handle(Geom_ConicalSurface) aConicalSurf;
+  Handle(Geom_SurfaceOfRevolution) aRevSurf;
+  Handle(Geom_Line) aLine;
+  BRepAdaptor_Surface aConeAdaptor (aConeShape);
+  TopoDS_Face aFace;
+  AIS_KindOfSurface aSurfType;
+  Standard_Real anOffset = 0.;
+  Handle(Standard_Type) aType;
+
+  Standard_Real aMaxV = aConeAdaptor.FirstVParameter();
+  Standard_Real aMinV = aConeAdaptor.LastVParameter();
+
+  AIS::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset);
+
+  if (aSurfType == AIS_KOS_Revolution)
+  {
+    // Surface of revolution
+    aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf);
+    gp_Lin aLin (aRevSurf->Axis());
+    Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve();
+    //Must be a part of line (basis curve should be linear)
+    if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line))
+      return Standard_False;
+
+    gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV);
+    gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV);
+    gp_Vec aVec1 (aFirst1, aLast1);
+
+    //Projection <aFirst> on <aLin>
+    gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin);
+    // Projection <aLast> on <aLin>
+    gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin);
+
+    gp_Vec aVec2 (aFirst2, aLast2);
+
+    // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle).
+    if (aVec1.IsParallel (aVec2, Precision::Angular())
+        || aVec1.IsNormal (aVec2,Precision::Angular()))
+      return Standard_False;
+
+    gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
+    aCone =  aMkCone.Value();
+    myCenterPoint = aCone.Apex();
+  }
+  else
+  {
+    aType = aSurf->DynamicType();
+    if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
     {
-       
-    Standard_Real distLL= l1.Distance(l2);
-    if ( Abs(distLL) <= Precision::Confusion() ) {
-      gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
-      gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
-      gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
-      gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
-      distLL =  0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
-      ComputeNull2DSelection(aSelection, distLL);
-    }
-    else {
-      ComputeNull2DSelection(aSelection, distLL*8/10);
+      // Offset surface
+      aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset);
+      aSurf = aOffsetSurf->Surface();
+      BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion());
+      aMkFace.Build();
+      if (!aMkFace.IsDone())
+        return Standard_False;
+      aConeAdaptor.Initialize (aMkFace.Face());
     }
+    aCone = aConeAdaptor.Cone();
+    aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf);
+    myCenterPoint =  aConicalSurf->Apex();
   }
-  
-  //----------------------------------------------------------
-  //  Classic case  ( angle != 0 )
-  else {
-
-    if (myFDir.IsParallel(mySDir,Precision::Angular())) {
-      Standard_Real distLL= l1.Distance(l2);
-      if ( Abs(distLL) <= Precision::Confusion() ) {
-       gp_Pnt ptat11 = cu1.Value(cu1.FirstParameter());
-       gp_Pnt ptat12 = cu1.Value(cu1.LastParameter());
-       gp_Pnt ptat21 = cu2.Value(cu2.FirstParameter());
-       gp_Pnt ptat22 = cu2.Value(cu2.LastParameter());
-       distLL =  0.75 * Max( ptat11.Distance(ptat12), ptat21.Distance(ptat22));
-       ComputeNull2DSelection(aSelection, distLL*8/10);
-      }
-    }
-    else {
-      gp_Dir Norm = myFDir.Crossed(mySDir);
-      
-      gp_Ax2 ax(myCenter,Norm,myFDir);
-      gp_Circ cer(ax,myCenter.Distance(myPosition));
-      gp_Vec vec1(myFDir);
-      
-      Standard_Boolean nullrad(Standard_False);
-      if (cer.Radius() == 0.) {
-       cer.SetRadius(1.);
-       nullrad = Standard_True;
-      }
-      vec1 *= cer.Radius();
-      gp_Pnt p1 = myCenter.Translated(vec1);
-      gp_Vec vec2(mySDir);
-      vec2 *= cer.Radius();
-      gp_Pnt p2 = myCenter.Translated(vec2);
-      
-      Standard_Real uc1 = 0.;
-      Standard_Real uc2 = ElCLib::Parameter(cer,p2);
-      Standard_Real uco;
-      if (nullrad) uco = ElCLib::Parameter(cer,p1);
-      else uco = ElCLib::Parameter(cer,myPosition);
-      
-      Standard_Real udeb = uc1;
-      Standard_Real ufin = uc2;
-      
-      if (uco > ufin) {
-       if (Abs(myVal)<M_PI) {
-         // test if uco is in the opposing sector 
-         if (uco > udeb+M_PI && uco < ufin+M_PI){
-           udeb = udeb + M_PI;
-         ufin = ufin + M_PI;
-           uc1  = udeb;
-           uc2  = ufin;
-         }
-      }
-      }  
-      if (uco > ufin) {
-       if ((uco-uc2) < (uc1-uco+(2*M_PI))) ufin = uco;
-       else udeb = uco - 2*M_PI;
-      }
-      p1   = ElCLib::Value(udeb,cer);
-      p2   = ElCLib::Value(ufin,cer);
-      
-      //Create 2 owners for each part of the arrow
-      Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
-      Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
-      if (myExtShape != 0) {
-       if (myExtShape == 1) {
-         own1->SetShape(mySShape);
-         own2->SetShape(mySShape);
-       }
-       else {
-         own1->SetShape(myFShape);
-         own2->SetShape(myFShape);
-       }
-      }
-      else {
-       own1->SetShape(myFShape);
-       own2->SetShape(mySShape);
-      }
-      
-      Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
-      
-      Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
-      Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
-      
-      Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
-      aSelection->Add(scurv);
-      scurv = new Select3D_SensitiveCurve(own2,thecu2);
-      aSelection->Add(scurv);
-      
-      Handle(Select3D_SensitiveSegment) seg;
-      if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
-       seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
-       aSelection->Add(seg);
-      }
-      if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
-       seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
-       aSelection->Add(seg);
-      }
-    }
+
+  // A circle where the angle is drawn
+  Handle(Geom_Curve) aCurve;
+  Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5;
+  aCurve = aSurf->VIso (aMidV);
+  aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
+
+  aCurve = aSurf->VIso(aMaxV);
+  gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
+  aCurve = aSurf->VIso(aMinV);
+  gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
+
+  if (aCircVmax.Radius() < aCircVmin.Radius())
+  {
+   gp_Circ aTmpCirc = aCircVmax;
+   aCircVmax = aCircVmin;
+   aCircVmin = aTmpCirc;
   }
 
+  myFirstPoint  = ElCLib::Value (0, aCircle);
+  mySecondPoint = ElCLib::Value (M_PI, aCircle);
+  return Standard_True;
 }
+
 //=======================================================================
-//function : Compute2DNullSelection
-//purpose  : for dimension of null angle
+//function : IsValidPoints
+//purpose  : 
 //=======================================================================
+Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
+                                                    const gp_Pnt& theCenterPoint,
+                                                    const gp_Pnt& theSecondPoint) const
+{
+  return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion()
+      && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion()
+      && gp_Vec (theCenterPoint, theFirstPoint).Angle (
+           gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();
+}
 
-void AIS_AngleDimension::ComputeNull2DSelection(
-                        const Handle(SelectMgr_Selection)& aSelection,
-                        const Standard_Real distLL)
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_AngleDimension::GetTextPosition() const
 {
-  gp_Dir Norm; 
-  if ( myFDir.IsParallel(mySDir, Precision::Angular()) ) {
-    Norm = myPlane->Pln().Axis().Direction();
+  if (!IsValid())
+  {
+    return gp::Origin();
   }
-  else
-    Norm = myFDir.Crossed(mySDir);
 
-  gp_Ax2 ax(myCenter,Norm,myFDir);
-  gp_Circ cer(ax,distLL);
-  
-  gp_Vec vec1(myFDir);
-  vec1 *= cer.Radius();
-  gp_Pnt p1 = myCenter.Translated(vec1);
-  gp_Vec vec2(mySDir);
-  vec2 *= cer.Radius();
-  gp_Pnt p2 = myCenter.Translated(vec2);
-
-  // calcul de parametres de debut et de fin des extremites de l'arc
-  Standard_Real uc1 = 0.;
-  Standard_Real uc2 = ElCLib::Parameter(cer,p2);
-  Standard_Real uco = ElCLib::Parameter(cer,myPosition);
-
-  Standard_Real udeb = uc1;
-  Standard_Real ufin = uc2;
-
-  if (uco > ufin) {
-    if (Abs(myVal)<M_PI) {
-      // test if uco is in the opposing sector 
-      if (uco > udeb+M_PI && uco < ufin+M_PI){
-       udeb = udeb + M_PI;
-       ufin = ufin + M_PI;
-       uc1  = udeb;
-       uc2  = ufin;
-      }
-    }
+  if (IsTextPositionCustom())
+  {
+    return myFixedTextPosition;
   }
 
-  if (uco > ufin) {
-    if ((uco-uc2) < (uc1-uco+(2*M_PI))) {
-      ufin = uco;
-    }
-    else {
-      udeb = uco - 2*M_PI;
-    }
-  }
+  // Counts text position according to the dimension parameters
+  gp_Pnt aTextPosition (gp::Origin());
+
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  // Prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
 
-  //Create 2 owners for each part of the arrow
-  Handle(AIS_DimensionOwner) own1 = new AIS_DimensionOwner(this,7);
-  Handle(AIS_DimensionOwner) own2 = new AIS_DimensionOwner(this,7);
-  if (myExtShape != 0) {
-    if (myExtShape == 1) {
-      own1->SetShape(mySShape);
-      own2->SetShape(mySShape);
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+
+  // Handle user-defined and automatic arrow placement
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
+  FitTextAlignment (aDimensionAspect->TextHorizontalPosition(),
+                    aLabelPosition, isArrowsExternal);
+
+  // Get text position
+  switch (aLabelPosition & LabelPosition_HMask)
+  {
+  case LabelPosition_HCenter:
+    {
+      aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
     }
-    else {
-      own1->SetShape(myFShape);
-      own2->SetShape(myFShape);
+    break;
+  case LabelPosition_Left:
+    {
+      gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
+      gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec (anExtensionDir) * -anOffset;
+      aTextPosition = aFirstAttach.Translated (anExtensionVec);
     }
+    break;
+  case LabelPosition_Right:
+    {
+      gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
+      gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec (anExtensionDir) * anOffset;
+      aTextPosition = aSecondAttach.Translated (anExtensionVec);
+    }
+    break;
   }
-  else {
-    own1->SetShape(myFShape);
-    own2->SetShape(mySShape);
-  }
-  
-  Handle(Geom_Circle) thecirc = new Geom_Circle(cer);
 
-  if ( udeb != ufin ) {
-    Handle(Geom_TrimmedCurve) thecu1 = new Geom_TrimmedCurve(thecirc,udeb,(udeb+ufin)/2);
-    Handle(Geom_TrimmedCurve) thecu2 = new Geom_TrimmedCurve(thecirc,(udeb+ufin)/2,ufin);
+  return aTextPosition;
+}
 
-    Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own1,thecu1);
-    aSelection->Add(scurv);
-    scurv = new Select3D_SensitiveCurve(own2,thecu2);
-    aSelection->Add(scurv);
-  }
-  else {
-    // find end of segment to allow selection
-    gp_Vec VTrans(myFDir.Crossed(Norm));
-    Handle(Select3D_SensitiveSegment) seg1;
-    seg1 = new Select3D_SensitiveSegment(own1, 
-                                        p1, 
-                                        p1.Translated( VTrans*distLL/10 ) );
-    aSelection->Add(seg1);
-    seg1 = new Select3D_SensitiveSegment(own2, 
-                                        p2, 
-                                        p2.Translated(-VTrans*distLL/10 ) );
-    aSelection->Add(seg1);
+//=======================================================================
+//function : SetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!IsValid())
+  {
+    return;
   }
 
-  Handle(Select3D_SensitiveSegment) seg;
-  if (!myFAttach.IsEqual(p1,Precision::Confusion())) {
-    seg = new Select3D_SensitiveSegment(own1,myFAttach,p1);
-    aSelection->Add(seg);
-  }
-    
-  if (!mySAttach.IsEqual(p2,Precision::Confusion())) {
-    seg = new Select3D_SensitiveSegment(own2,mySAttach,p2);
-    aSelection->Add(seg);
+  // The text position point for angle dimension should belong to the working plane.
+  if (!GetPlane().Contains (theTextPos, Precision::Confusion()))
+  {
+    Standard_ProgramError::Raise ("The text position point for angle dimension doesn't belong to the working plane.");
   }
-}
 
+  myIsTextPositionFixed = Standard_True;
+  myFixedTextPosition = theTextPos;
+}
 
 //=======================================================================
-//function : ComputeConeAngleSelection
-//purpose  : for cone angle
+//function : AdjustAspectParameters
+//purpose  : 
 //=======================================================================
-void AIS_AngleDimension::ComputeConeAngleSelection(const Handle(SelectMgr_Selection)& aSelection)
+void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos,
+                                           Standard_Real& theExtensionSize,
+                                           Prs3d_DimensionTextHorizontalPosition& theAlignment)
 {
-  if( myCone.IsNull() ) return;
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+  Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
 
+  // Compute flyout direction vector.
+  gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+  gp_Dir aTargetPointsDir = gce_MakeDir (myFirstPoint, mySecondPoint);
 
-  Handle( SelectMgr_EntityOwner ) owner = new SelectMgr_EntityOwner( this, 7 );
-  Handle( Select3D_SensitiveSegment ) seg;
-  
-  gp_Pln aPln;
-  gp_Cone aCone;
-  gp_Circ myCircle;
-  gp_Pnt Apex;
-  Handle( Geom_Surface ) aSurf;         //a surface from the Face
-  Handle( Geom_OffsetSurface ) aOffsetSurf; 
-  Handle( Geom_ConicalSurface ) aConicalSurf;
-  Handle( Geom_SurfaceOfRevolution ) aRevSurf; 
-  Handle( Geom_Line ) aLine;
-  BRepAdaptor_Surface tmpSurf(myCone);  
-  TopoDS_Face aFace;
-  AIS_KindOfSurface aSurfType;
-  Standard_Real Offset = 0. ;
-  Handle( Standard_Type ) aType;
+  // Build circle with radius that is equal to distance from text position to the center point.
+  Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude();
 
-  Standard_Real maxV = tmpSurf.FirstVParameter();
-  Standard_Real minV = tmpSurf.LastVParameter();
+  // Set attach points in positive direction of the flyout.
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * aRadius);
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * aRadius);
 
-  AIS::GetPlaneFromFace( myCone, aPln, aSurf, aSurfType, Offset );
-  
-  if ( aSurfType == AIS_KOS_Revolution ) {                                    //surface of revolution
-
-    aRevSurf = Handle( Geom_SurfaceOfRevolution )::DownCast( aSurf ); 
-    gp_Lin ln( aRevSurf->Axis() );
-    Handle( Geom_Curve ) tmpCrv = aRevSurf->BasisCurve();
-    if ( tmpCrv ->DynamicType() != STANDARD_TYPE(Geom_Line) )  return;        //Must be a part of line
-
-    Standard_Real par;
-    gp_Pnt fst = tmpSurf.Value(0., minV);
-    gp_Pnt lst = tmpSurf.Value(0., maxV);
-    gp_Vec vec1(fst, lst);
-   
-    par = ElCLib::Parameter( ln, fst );
-    gp_Pnt fst2 = ElCLib::Value( par, ln );                         //projection fst on ln
-    par = ElCLib::Parameter( ln, lst );
-    gp_Pnt lst2 = ElCLib::Value( par, ln );                         //projection lst on ln
-
-    gp_Vec vec2(fst2, lst2);
-
-   // Check if two parts of revolution are parallel ( it's a cylinder ) or normal (it's a circle ) 
-    if( vec1.IsParallel( vec2,Precision::Angular() ) || vec1.IsNormal( vec2,Precision::Angular() ) ) return; 
-    gce_MakeCone mkCone(aRevSurf->Axis(), fst, lst);
-    aCone =  mkCone.Value();
-    Apex = aCone.Apex();
+  gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius);
+  if (!aConstructCircle.IsDone())
+  {
+    return;
   }
-  else {  
-    aType = aSurf->DynamicType();
-    if ( aType == STANDARD_TYPE(Geom_OffsetSurface) || Offset > 0.01 ) {            //offset surface
-      aOffsetSurf = new Geom_OffsetSurface (aSurf, Offset);
-      aSurf = aOffsetSurf->Surface();
-      BRepBuilderAPI_MakeFace mkFace(aSurf, Precision::Confusion());
-      mkFace.Build();
-      if( !mkFace.IsDone() ) return;
-      tmpSurf.Initialize( mkFace.Face() );
-    }  
-    aCone = tmpSurf.Cone();
-    aConicalSurf = Handle( Geom_ConicalSurface)::DownCast( aSurf );
-    Apex =  aConicalSurf->Apex();
+  gp_Circ aCircle = aConstructCircle.Value();
+
+  // Default values
+  theExtensionSize = aDimensionAspect->ArrowAspect()->Length();
+  theAlignment = Prs3d_DTHP_Center;
+
+  Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach);
+  Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach);
+  if (aParamEnd < aParamBeg)
+  {
+    Standard_Real aParam = aParamEnd;
+    aParamEnd = aParamBeg;
+    aParamBeg = aParam;
   }
 
-  Handle(Geom_Curve) aCurve;                 //A circle where the angle is drawn
-  
-  if ( myAutomaticPosition ) {
-    Standard_Real midV = ( minV + maxV ) / 2.5; 
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+  Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos);
 
-    aCurve =   aSurf->VIso(midV);
-    myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
+  // Horizontal center
+  if (aTextPar > aParamBeg && aTextPar < aParamEnd)
+  {
+    myFlyout = aRadius;
 
-    myPosition = ElCLib::Value(M_PI / 2.0, myCircle);
-    myAutomaticPosition = Standard_False;
-  }
-  else {
-    Standard_Real U, V;
-    ElSLib::Parameters(aCone, myPosition, U, V);
-    aCurve = aSurf->VIso(V); 
-    myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
-  }
- //__________________________________________________________________
-  aCurve = aSurf->VIso(maxV);
-  gp_Circ CircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
-  aCurve = aSurf->VIso(minV);
-  gp_Circ CircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ();
- //__________________________________________________________________
-
-  if( CircVmax.Radius() < CircVmin.Radius() ) {
-   gp_Circ tmpCirc = CircVmax;
-   CircVmax = CircVmin;
-   CircVmin = tmpCirc;
+    SetToUpdate();
+    return;
   }
-  Standard_Boolean IsArrowOut = Standard_True;    //Is arrows inside or outside of the cone
-  //Standard_Real PntOnMainAxis = 0;   //Is projection of aPosition inside of the cone = 0, above = 1, or below = -1
-  Standard_Boolean IsConeTrimmed = Standard_False; 
 
-  if( CircVmin.Radius() > 0.01 ) IsConeTrimmed = Standard_True;
+  aParamBeg += M_PI;
+  aParamEnd += M_PI;
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
 
-  gp_Pnt AttachmentPnt;
-  gp_Pnt OppositePnt;
+  if (aTextPar > aParamBeg  && aTextPar < aParamEnd)
+  {
+    myFlyout = -aRadius;
 
-  Standard_Real param = ElCLib::Parameter(myCircle, myPosition);
+    SetToUpdate();
+    return;
+  }
 
-  gp_Pnt aPnt = Apex;
-  gp_Pnt P1 = ElCLib::Value(0., myCircle);
-  gp_Pnt P2 = ElCLib::Value(M_PI, myCircle);
+  // Text on the extensions
+  gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint);
+  gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint);
+  gp_Pnt aFirstTextProj = AIS::Nearest (aFirstLine, theTextPos);
+  gp_Pnt aSecondTextProj = AIS::Nearest (aSecondLine, theTextPos);
+  Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos);
+  Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos);
 
-  gce_MakePln mkPln(P1, P2, aPnt);   // create a plane whitch defines plane for projection aPosition on it
+  if (aFirstDist <= aSecondDist)
+  {
+    aRadius = myCenterPoint.Distance (aFirstTextProj);
+    Standard_Real aNewExtensionSize = aFirstDist - anArrowLength;
+    theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
+
+    theAlignment = Prs3d_DTHP_Left;
 
-  aPnt = AIS::ProjectPointOnPlane(myPosition, mkPln.Value()); 
-  gp_Pnt tmpPnt = aPnt;
+    gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius);
 
-  if( aPnt.Distance(P1) <  aPnt.Distance(P2) ){
-    AttachmentPnt = P1; 
-    OppositePnt = P2; 
+    myFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
+                ? -aRadius : aRadius;
   }
-  else {
-    AttachmentPnt = P2; 
-    OppositePnt = P1;
+  else
+  {
+    aRadius = myCenterPoint.Distance (aSecondTextProj);
+
+    Standard_Real aNewExtensionSize = aSecondDist - anArrowLength;
+
+    theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
+
+    theAlignment = Prs3d_DTHP_Right;
+
+    gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius);
+
+    myFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
+                ? -aRadius : aRadius;
   }
-  
-  aPnt = AttachmentPnt ;                          // Creating of circle whitch defines a plane for a dimension arc
-  gp_Vec Vec(AttachmentPnt, Apex);                // Dimension arc is a part of the circle 
-  Vec.Scale(2);
-  aPnt.Translate(Vec);
-  GC_MakeCircle mkCirc(AttachmentPnt, OppositePnt,  aPnt); 
-  gp_Circ  aCircle2 = mkCirc.Value()->Circ();
+}
 
-  
-  Standard_Integer i;
-  Standard_Real AttParam = ElCLib::Parameter(aCircle2, AttachmentPnt);
-  Standard_Real OppParam = ElCLib::Parameter(aCircle2, OppositePnt);
-  
-  while ( AttParam >= 2 * M_PI ) AttParam -= 2 * M_PI;
-  while ( OppParam >= 2 * M_PI ) OppParam -= 2 * M_PI;
+//=======================================================================
+//function : FitTextAlignment
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
+                                           Standard_Integer& theLabelPosition,
+                                           Standard_Boolean& theIsArrowsExternal) const
+{
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
 
-  if( myPosition.Distance( myCircle.Location() ) <= myCircle.Radius() )
-    if( 2 * myCircle.Radius() > aCircle2.Radius() * 0.4 ) IsArrowOut = Standard_False;  //four times more than an arrow size
+  Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
 
-  param = AttParam;
-  Standard_Real angle = OppParam - AttParam;
+  // Prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
 
-  if(IsArrowOut)
+  // add margins to label width
+  if (aDimensionAspect->IsText3d())
   {
-    angle += M_PI / 6; //An angle between AttParam and OppParam + 30 degrees
-    param -= M_PI / 12;      //out parts of dimension line are 15 degrees
+    aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
   }
 
-  while ( angle > 2. * M_PI ) angle -= 2. * M_PI;
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
 
-  gp_Pnt Vprev = ElCLib::Value(param, aCircle2);
-  for( i = 1; i <= 11; i++ ) //calculating of arc
+  // Handle user-defined and automatic arrow placement
+  switch (aDimensionAspect->ArrowOrientation())
   {
-    gp_Pnt Vcur = ElCLib::Value(param + angle/11 * i, aCircle2);
-    seg = new Select3D_SensitiveSegment(owner, Vprev, Vcur);
-    aSelection->Add(seg);
-    Vprev = Vcur;
+    case Prs3d_DAO_External: theIsArrowsExternal = true; break;
+    case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
+    case Prs3d_DAO_Fit:
+    {
+      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
+      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+
+      // Add margin to ensure a small tail between text and arrow
+      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
+                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
+                                    : 0.0;
+
+      Standard_Real anArrowsWidth   = (anArrowLength + anArrowMargin) * 2.0;
+
+      theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
+      break;
+    }
   }
 
-  tmpPnt = tmpPnt.Translated(gp_Vec(0, 0, -2));
-
-  const Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
-  Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( owner,
-                                                                  tmpPnt.X(),
-                                                                  tmpPnt.Y(),
-                                                                  tmpPnt.Z(),
-                                                                  tmpPnt.X() + size,
-                                                                  tmpPnt.Y() + size,
-                                                                  tmpPnt.Z() + size);
-  aSelection->Add(box);
+  // Handle user-defined and automatic text placement
+  switch (theHorizontalTextPos)
+  {
+    case Prs3d_DTHP_Left  : theLabelPosition |= LabelPosition_Left; break;
+    case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
+    case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
+    case Prs3d_DTHP_Fit:
+    {
+      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
+      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+      Standard_Real anArrowsWidth   = anArrowLength * 2.0;
+      Standard_Real aContentWidth   = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
+
+      theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
+      break;
+    }
+  }
+
+  switch (aDimensionAspect->TextVerticalPosition())
+  {
+    case Prs3d_DTVP_Above  : theLabelPosition |= LabelPosition_Above; break;
+    case Prs3d_DTVP_Below  : theLabelPosition |= LabelPosition_Below; break;
+    case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
+  }
 }