0024425: Improve usage ergonomics of new dimension presentations
authoraba <aba@opencascade.com>
Wed, 11 Dec 2013 15:16:07 +0000 (19:16 +0400)
committerabv <abv@opencascade.com>
Thu, 12 Dec 2013 15:36:55 +0000 (19:36 +0400)
- Added format for value string.
- Construction and validness.
- Revise modification of properties and update of presentations.
- Units moved to Drawer; code revisions.
- Length and angle initialization was changed. Type of geometry filed was added to AIS_Dimension.
- Method for test case bugs/vis/buc60915 was corrected. Description of the dimension classes was corrected.
- Fixed initialization of angle and length.

44 files changed:
samples/mfc/standard/Common/AngleParamsVerticesPage.cpp
samples/mfc/standard/Common/DimensionDlg.cpp
samples/mfc/standard/Common/DimensionDlg.h
samples/mfc/standard/Common/LengthParamsEdgePage.cpp
samples/mfc/standard/Common/LengthParamsEdgesPage.cpp
samples/mfc/standard/Common/LengthParamsVerticesPage.cpp
samples/mfc/standard/Common/ParamsFacesPage.cpp [new file with mode: 0644]
samples/mfc/standard/Common/ParamsFacesPage.h [new file with mode: 0644]
samples/mfc/standard/Common/RadiusParamsPage.cpp
samples/mfc/standard/Common/res/OCC_Resource.h
samples/mfc/standard/Common/res/OCC_Resource.rc
samples/mfc/standard/mfcsample/adm/win/vc10/mfcsample.vcxproj
samples/mfc/standard/mfcsample/adm/win/vc10/mfcsample.vcxproj.filters
samples/mfc/standard/mfcsample/adm/win/vc11/mfcsample.vcxproj
samples/mfc/standard/mfcsample/adm/win/vc11/mfcsample.vcxproj.filters
samples/mfc/standard/mfcsample/adm/win/vc8/mfcsample.vcproj
samples/mfc/standard/mfcsample/adm/win/vc9/mfcsample.vcproj
src/AIS/AIS.cdl
src/AIS/AIS.cxx
src/AIS/AIS_AngleDimension.cxx
src/AIS/AIS_AngleDimension.hxx
src/AIS/AIS_DiameterDimension.cxx
src/AIS/AIS_DiameterDimension.hxx
src/AIS/AIS_Dimension.cxx
src/AIS/AIS_Dimension.hxx
src/AIS/AIS_Drawer.cdl
src/AIS/AIS_Drawer.cxx
src/AIS/AIS_Drawer.lxx
src/AIS/AIS_LengthDimension.cxx
src/AIS/AIS_LengthDimension.hxx
src/AIS/AIS_RadiusDimension.cxx
src/AIS/AIS_RadiusDimension.hxx
src/Prs3d/FILES
src/Prs3d/Prs3d.cdl
src/Prs3d/Prs3d_DimensionAspect.cdl
src/Prs3d/Prs3d_DimensionAspect.cxx
src/Prs3d/Prs3d_DimensionUnits.cxx [new file with mode: 0644]
src/Prs3d/Prs3d_DimensionUnits.hxx [new file with mode: 0644]
src/Prs3d/Prs3d_Drawer.cdl
src/Prs3d/Prs3d_Drawer.cxx
src/QABugs/QABugs_16.cxx
src/QABugs/QABugs_17.cxx
src/TPrsStd/TPrsStd_ConstraintTools.cxx
src/ViewerTest/ViewerTest_RelationCommands.cxx

index 62f6c30..9767f58 100644 (file)
@@ -142,13 +142,13 @@ void CAngleParamsVerticesPage::OnBnClickedVertex3Btn()
   anAspect->TextAspect()->SetHeight (aDimDlg->GetFontHeight());
   anAspect->MakeTextShaded (aDimDlg->IsText3dShaded());
   anAspect->SetCommonColor (aDimDlg->GetDimensionColor());
-  anAngleDim->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
-  if (anAngleDim->IsUnitsDisplayed())
+  anAngleDim->DimensionAspect()->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
+  if (aDimDlg->IsUnitsDisplayed())
   {
     anAngleDim->SetDisplayUnits (aDimDlg->GetUnits());
-    if ((anAngleDim->DisplayUnits().IsEqual (TCollection_AsciiString ("deg"))))
+    if ((anAngleDim->GetDisplayUnits().IsEqual (TCollection_AsciiString ("deg"))))
     {
-      anAngleDim->MakeUnitsDisplayed (Standard_False);
+      anAngleDim->DimensionAspect()->MakeUnitsDisplayed (Standard_False);
     }
     else
     {
index 2179bf6..872dcf9 100644 (file)
@@ -9,6 +9,7 @@
 #include "LengthParamsEdgesPage.h"
 #include "AngleParamsVerticesPage.h"
 #include "RadiusParamsPage.h"
+#include "ParamsFacesPage.h"
 #include <Standard_Macro.hxx>
 #include <AIS_InteractiveContext.hxx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
@@ -30,6 +31,7 @@ BEGIN_MESSAGE_MAP(CDimensionDlg, CDialog)
   ON_BN_CLICKED(IDC_2DText, &CDimensionDlg::OnBnClicked2dText)
   ON_BN_CLICKED(IDC_3DText, &CDimensionDlg::OnBnClicked3dText)
   ON_BN_CLICKED(IDC_DimensionColor, &CDimensionDlg::OnBnClickedDimensionColor)
+  ON_WM_CLOSE()
 END_MESSAGE_MAP()
 
 //=======================================================================
@@ -171,6 +173,8 @@ void CDimensionDlg::CreateLengthParamsTab()
   myLengthParams->InsertItem (1, &aTabItem);
   aTabItem.pszText = "Parallel edges";
   myLengthParams->InsertItem (2, &aTabItem);
+  aTabItem.pszText = "Parallel faces";
+  myLengthParams->InsertItem (3, &aTabItem);
 
   CLengthParamsEdgePage *aPage1 = new CLengthParamsEdgePage (myAISContext);
   aTabItem.mask = TCIF_PARAM;
@@ -186,6 +190,7 @@ void CDimensionDlg::CreateLengthParamsTab()
   myLengthParams->SetItem (1, &aTabItem);
   VERIFY (aPage2->Create (CLengthParamsVerticesPage::IDD,myLengthParams));
   aPage2->SetWindowPos (NULL,10,30,0,0,SWP_NOSIZE | SWP_NOZORDER);
+  aPage2->ShowWindow (SW_HIDE);
 
   CLengthParamsEdgesPage *aPage3 = new CLengthParamsEdgesPage (myAISContext);
   aTabItem.mask = TCIF_PARAM;
@@ -193,6 +198,15 @@ void CDimensionDlg::CreateLengthParamsTab()
   myLengthParams->SetItem (2, &aTabItem);
   VERIFY (aPage3->Create (CLengthParamsEdgesPage::IDD,myLengthParams));
   aPage3->SetWindowPos (NULL,10,30,0,0,SWP_NOSIZE | SWP_NOZORDER);
+  aPage3->ShowWindow (SW_HIDE);
+
+  CParamsFacesPage *aPage4 = new CParamsFacesPage (myAISContext);
+  aTabItem.mask = TCIF_PARAM;
+  aTabItem.lParam = (LPARAM)aPage4;
+  myLengthParams->SetItem (3, &aTabItem);
+  VERIFY (aPage4->Create (CParamsFacesPage::IDD,myLengthParams));
+  aPage4->SetWindowPos (NULL,10,30,0,0,SWP_NOSIZE | SWP_NOZORDER);
+  aPage4->ShowWindow (SW_HIDE);
 }
 
 //=======================================================================
@@ -208,6 +222,8 @@ void CDimensionDlg::CreateAngleParamsTab()
   myAngleParams->InsertItem (0, &aTabItem);
   aTabItem.pszText = "Three vertices";
   myAngleParams->InsertItem (1, &aTabItem);
+  aTabItem.pszText = "Two faces";
+  myAngleParams->InsertItem (2, &aTabItem);
 
   CLengthParamsEdgesPage *aPage1 = new CLengthParamsEdgesPage (myAISContext, true);
   aTabItem.mask = TCIF_PARAM;
@@ -223,6 +239,15 @@ void CDimensionDlg::CreateAngleParamsTab()
   myAngleParams->SetItem (1, &aTabItem);
   VERIFY (aPage2->Create (CAngleParamsVerticesPage::IDD,myAngleParams));
   aPage2->SetWindowPos (NULL,10,30,0,0,SWP_NOSIZE | SWP_NOZORDER);
+  aPage2->ShowWindow (SW_HIDE);
+
+  CParamsFacesPage *aPage3 = new CParamsFacesPage (myAISContext, true);
+  aTabItem.mask = TCIF_PARAM;
+  aTabItem.lParam = (LPARAM)aPage3;
+  myAngleParams->SetItem (2, &aTabItem);
+  VERIFY (aPage3->Create (CParamsFacesPage::IDD,myAngleParams));
+  aPage3->SetWindowPos (NULL,10,30,0,0,SWP_NOSIZE | SWP_NOZORDER);
+  aPage3->ShowWindow (SW_HIDE);
 }
 
 //=======================================================================
@@ -275,7 +300,22 @@ void CDimensionDlg::UpdateStandardModeForAngle()
   int aTabNum = ((CTabCtrl*) GetDlgItem (IDC_AngleTab))->GetCurSel();
   myAISContext->CloseAllContexts();
   myAISContext->OpenLocalContext();
-  myAISContext->ActivateStandardMode (aTabNum == 1 ? TopAbs_VERTEX : TopAbs_EDGE);
+  TopAbs_ShapeEnum aMode;
+
+  if (aTabNum == 1)
+  {
+    aMode = TopAbs_VERTEX;
+  }
+  else if (aTabNum == 2)
+  {
+    aMode = TopAbs_FACE;
+  }
+  else
+  {
+   aMode = TopAbs_EDGE;
+  }
+
+  myAISContext->ActivateStandardMode (aMode);
 }
 
 //=======================================================================
@@ -288,7 +328,21 @@ void CDimensionDlg::UpdateStandardModeForLength()
   int aTabNum = ((CTabCtrl*) GetDlgItem (IDC_LengthTab))->GetCurSel();
   myAISContext->CloseAllContexts();
   myAISContext->OpenLocalContext();
-  myAISContext->ActivateStandardMode (aTabNum == 1 ? TopAbs_VERTEX : TopAbs_EDGE);
+  TopAbs_ShapeEnum aMode;
+
+  if (aTabNum == 1)
+  {
+    aMode = TopAbs_VERTEX;
+  }
+  else if (aTabNum == 3)
+  {
+    aMode = TopAbs_FACE;
+  }
+  else
+  {
+   aMode = TopAbs_EDGE;
+  }
+  myAISContext->ActivateStandardMode (aMode);
 }
 
 //=======================================================================
@@ -500,11 +554,12 @@ void CDimensionDlg::OnDestroy()
   {
     myAISContext->CloseAllContexts();
   }
-  // Destroy length tab
   CWnd *aWnd;
   TC_ITEM anItem;
   anItem.mask = TCIF_PARAM;
-  for (int i = 2; i >= 0; --i)
+
+  // Destroy length tab
+  for (int i = 3; i >= 0; --i)
   {
     ((CTabCtrl*) GetDlgItem (IDC_LengthTab))->GetItem (i, &anItem);
     ASSERT (anItem.lParam);
@@ -513,7 +568,7 @@ void CDimensionDlg::OnDestroy()
     delete aWnd;
   }
   // Destroy angle tab
-  for (int i = 1; i >= 0; --i)
+  for (int i = 2; i >= 0; --i)
   {
     ((CTabCtrl*) GetDlgItem (IDC_AngleTab))->GetItem (i, &anItem);
     ASSERT(anItem.lParam);
@@ -522,6 +577,20 @@ void CDimensionDlg::OnDestroy()
     delete aWnd;
   }
 
+  // Destroy radius tab
+    ((CTabCtrl*) GetDlgItem (IDC_RadiusTab))->GetItem (0, &anItem);
+    ASSERT(anItem.lParam);
+    aWnd  = (CWnd*) anItem.lParam;
+    aWnd->DestroyWindow();
+    delete aWnd;
+
+  // Destroy diameter tab
+  ((CTabCtrl*) GetDlgItem (IDC_DiameterTab))->GetItem (0, &anItem);
+  ASSERT(anItem.lParam);
+  aWnd  = (CWnd*) anItem.lParam;
+  aWnd->DestroyWindow();
+  delete aWnd;
+
   CDialog::OnDestroy();
 }
 
@@ -684,3 +753,12 @@ const Quantity_Color CDimensionDlg::GetDimensionColor() const
 {
   return myDimensionColor;
 }
+
+void CDimensionDlg::OnClose()
+{
+  if (myAISContext->HasOpenedContext())
+  {
+    myAISContext->CloseAllContexts();
+  }
+  CDialog::OnClose();
+}
index 5a5e479..2e01419 100644 (file)
@@ -76,4 +76,5 @@ public:
   afx_msg void OnBnClicked2dText();
   afx_msg void OnBnClicked3dText();
   afx_msg void OnBnClickedDimensionColor();
+  afx_msg void OnClose();
 };
index 1fac26f..a29426c 100644 (file)
@@ -96,8 +96,8 @@ void CLengthParamsEdgePage::OnBnClickedChooseEdgeBtn()
   anAspect->TextAspect()->SetHeight (aDimDlg->GetFontHeight());
   anAspect->MakeTextShaded (aDimDlg->IsText3dShaded());
   anAspect->SetCommonColor (aDimDlg->GetDimensionColor());
-  aLenDim->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
-  if (aLenDim->IsUnitsDisplayed())
+  aLenDim->DimensionAspect()->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
+  if (aDimDlg->IsUnitsDisplayed())
   {
     aLenDim->SetDisplayUnits (aDimDlg->GetUnits());
   }
index 1c126b0..6865b04 100644 (file)
@@ -127,13 +127,13 @@ void CLengthParamsEdgesPage::OnBnClickedEdge2Btn()
     // Build an angle dimension between two non-parallel edges
     Handle(AIS_AngleDimension) anAngleDim = new AIS_AngleDimension (myFirstEdge, mySecondEdge);
     anAngleDim->SetDimensionAspect (anAspect);
-    anAngleDim->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
-    if (anAngleDim->IsUnitsDisplayed())
+    anAngleDim->DimensionAspect()->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
+    if (aDimDlg->IsUnitsDisplayed())
     {
       anAngleDim->SetDisplayUnits (aDimDlg->GetUnits ());
-      if ((anAngleDim->DisplayUnits().IsEqual (TCollection_AsciiString ("deg"))))
+      if ((anAngleDim->GetDisplayUnits().IsEqual (TCollection_AsciiString ("deg"))))
       {
-        anAngleDim->MakeUnitsDisplayed (Standard_False);
+        anAngleDim->DimensionAspect()->MakeUnitsDisplayed (Standard_False);
       }
       else
       {
@@ -148,8 +148,8 @@ void CLengthParamsEdgesPage::OnBnClickedEdge2Btn()
   {
     Handle(AIS_LengthDimension) aLenDim = new AIS_LengthDimension (myFirstEdge, mySecondEdge, aPlane->Pln());
     aLenDim->SetDimensionAspect (anAspect);
-    aLenDim->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
-    if (aLenDim->IsUnitsDisplayed())
+    aLenDim->DimensionAspect()->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
+    if (aDimDlg->IsUnitsDisplayed())
     {
       aLenDim->SetFlyout (aDimDlg->GetFlyout());
       aLenDim->SetDisplayUnits (aDimDlg->GetUnits());
index ca51dd7..2cea959 100644 (file)
@@ -117,8 +117,8 @@ void CLengthParamsVerticesPage::OnBnClickedVertex2Btn()
   anAspect->MakeText3d (aDimDlg->GetTextType());
   anAspect->TextAspect()->SetHeight (aDimDlg->GetFontHeight());
   anAspect->MakeTextShaded (aDimDlg->IsText3dShaded());
-  aLenDim->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
-  if (aLenDim->IsUnitsDisplayed ())
+  aLenDim->DimensionAspect()->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
+  if (aDimDlg->IsUnitsDisplayed())
   {
     aLenDim->SetDisplayUnits (aDimDlg->GetUnits ());
   }
diff --git a/samples/mfc/standard/Common/ParamsFacesPage.cpp b/samples/mfc/standard/Common/ParamsFacesPage.cpp
new file mode 100644 (file)
index 0000000..c22e582
--- /dev/null
@@ -0,0 +1,120 @@
+// ParamsFacesPage.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "ParamsFacesPage.h"
+#include "DimensionDlg.h"
+#include <AIS_InteractiveContext.hxx>
+#include <AIS_LocalContext.hxx>
+#include <AIS_LengthDimension.hxx>
+#include <AIS_AngleDimension.hxx>
+
+// CParamsFacesPage dialog
+
+IMPLEMENT_DYNAMIC(CParamsFacesPage, CDialog)
+
+CParamsFacesPage::CParamsFacesPage (Handle(AIS_InteractiveContext) theAISContext,
+                                    bool isAngleDimension /*= false*/,
+                                    CWnd* pParent         /*=NULL*/)
+ : CDialog(CParamsFacesPage::IDD, pParent),
+   myAISContext (theAISContext),
+   myIsAngleDimension (isAngleDimension)
+{
+}
+
+CParamsFacesPage::~CParamsFacesPage()
+{
+}
+
+void CParamsFacesPage::DoDataExchange(CDataExchange* pDX)
+{
+  CDialog::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CParamsFacesPage, CDialog)
+  ON_BN_CLICKED(IDC_FacesBtn1, &CParamsFacesPage::OnBnClickedFacesbtn1)
+  ON_BN_CLICKED(IDC_FacesBtn2, &CParamsFacesPage::OnBnClickedFacesbtn2)
+END_MESSAGE_MAP()
+
+
+// CParamsFacesPage message handlers
+
+void CParamsFacesPage::OnBnClickedFacesbtn1()
+{
+  // Check if face is selected
+  myAISContext->LocalContext()->InitSelected();
+  if (!myAISContext->LocalContext()->MoreSelected())
+  {
+    AfxMessageBox(_T("Choose the face and press the button again"),
+                    MB_ICONINFORMATION | MB_OK);
+    return;
+  }
+
+  myFirstFace = TopoDS::Face (myAISContext->LocalContext()->SelectedShape());
+  myAISContext->LocalContext()->ClearSelected();
+}
+
+void CParamsFacesPage::OnBnClickedFacesbtn2()
+{
+  // Check if face is selected
+  myAISContext->LocalContext()->InitSelected();
+  if (!myAISContext->LocalContext()->MoreSelected())
+  {
+    AfxMessageBox(_T("Choose the face and press the button again"),
+                    MB_ICONINFORMATION | MB_OK);
+    return;
+  }
+
+  mySecondFace = TopoDS::Face (myAISContext->LocalContext()->SelectedShape());
+  myAISContext->LocalContext()->ClearSelected();
+
+  CDimensionDlg *aDimDlg = (CDimensionDlg*)(GetParentOwner());
+
+  myAISContext->CloseAllContexts();
+
+  Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
+  anAspect->MakeArrows3d (Standard_False);
+  anAspect->MakeText3d (aDimDlg->GetTextType());
+  anAspect->TextAspect()->SetHeight (aDimDlg->GetFontHeight());
+  anAspect->MakeTextShaded (aDimDlg->IsText3dShaded());
+  anAspect->SetCommonColor (aDimDlg->GetDimensionColor());
+  if (myIsAngleDimension)
+  {
+    // Build an angle dimension between two non-parallel edges
+    Handle(AIS_AngleDimension) anAngleDim = new AIS_AngleDimension (myFirstFace, mySecondFace);
+    anAngleDim->SetDimensionAspect (anAspect);
+    anAngleDim->DimensionAspect()->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
+    if (aDimDlg->IsUnitsDisplayed())
+    {
+      anAngleDim->SetDisplayUnits (aDimDlg->GetUnits ());
+      if ((anAngleDim->GetDisplayUnits().IsEqual (TCollection_AsciiString ("deg"))))
+      {
+        anAngleDim->DimensionAspect()->MakeUnitsDisplayed (Standard_False);
+      }
+      else
+      {
+        anAngleDim->SetDisplaySpecialSymbol (AIS_DSS_No);
+      }
+    }
+
+    anAngleDim->SetFlyout (aDimDlg->GetFlyout());
+    myAISContext->Display (anAngleDim);
+  }
+  else
+  {
+    Handle(AIS_LengthDimension) aLenDim = new AIS_LengthDimension (myFirstFace, mySecondFace);
+    aLenDim->SetDimensionAspect (anAspect);
+    aLenDim->DimensionAspect()->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
+    if (aLenDim->DimensionAspect()->IsUnitsDisplayed())
+    {
+      aLenDim->SetFlyout (aDimDlg->GetFlyout());
+      aLenDim->SetDisplayUnits (aDimDlg->GetUnits());
+    }
+
+    myAISContext->Display (aLenDim);
+  }
+
+  myAISContext->OpenLocalContext();
+  myAISContext->ActivateStandardMode (TopAbs_FACE);
+}
diff --git a/samples/mfc/standard/Common/ParamsFacesPage.h b/samples/mfc/standard/Common/ParamsFacesPage.h
new file mode 100644 (file)
index 0000000..0ce2282
--- /dev/null
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "res\OCC_Resource.h"
+// CParamsFacesPage dialog
+
+class CParamsFacesPage : public CDialog
+{
+  DECLARE_DYNAMIC(CParamsFacesPage)
+private:
+  Handle(AIS_InteractiveContext) myAISContext;
+  bool myIsAngleDimension;
+  TopoDS_Face myFirstFace;
+  TopoDS_Face mySecondFace;
+public:
+  CParamsFacesPage (Handle(AIS_InteractiveContext) theAISContext,
+                    bool isAngleDimension = false,
+                    CWnd* pParent = NULL);    // standard constructor
+
+  virtual ~CParamsFacesPage();
+
+  // Dialog Data
+  enum { IDD = IDD_ParamsFacesPage };
+
+protected:
+  virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+
+  DECLARE_MESSAGE_MAP()
+public:
+  afx_msg void OnBnClickedFacesbtn1();
+  afx_msg void OnBnClickedFacesbtn2();
+};
index c810a16..d8b03f1 100644 (file)
@@ -98,14 +98,12 @@ void CRadiusParamsPage::OnBnClickedObjectBtn()
   Handle(AIS_Dimension) aDim;
   if (myIsDiameterDimension)
   {
-    aDim = isAttachPoint ? new AIS_DiameterDimension (aCircle, ElCLib::Value ((aFirstPar + aLastPar) / 2.0, aCircle))
-                         : new AIS_DiameterDimension (aCircle);
+    aDim = new AIS_DiameterDimension (aCircle);
     Handle(AIS_DiameterDimension)::DownCast(aDim)->SetFlyout (aDimDlg->GetFlyout());
   }
   else
   {
-    aDim = isAttachPoint ? new AIS_RadiusDimension (aCircle, ElCLib::Value ((aFirstPar + aLastPar) / 2.0, aCircle))
-                         : new AIS_RadiusDimension (aCircle);
+    aDim = new AIS_RadiusDimension (aCircle);
     Handle(AIS_RadiusDimension)::DownCast(aDim)->SetFlyout (aDimDlg->GetFlyout());
   }
 
@@ -115,8 +113,8 @@ void CRadiusParamsPage::OnBnClickedObjectBtn()
   anAspect->TextAspect()->SetHeight (aDimDlg->GetFontHeight());
   anAspect->MakeTextShaded (aDimDlg->IsText3dShaded());
   anAspect->SetCommonColor (aDimDlg->GetDimensionColor());
-  aDim->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
-  if (aDim->IsUnitsDisplayed())
+  aDim->DimensionAspect()->MakeUnitsDisplayed (aDimDlg->IsUnitsDisplayed());
+  if (aDimDlg->IsUnitsDisplayed())
   {
     aDim->SetDisplayUnits (aDimDlg->GetUnits());
   }
index 3e31ed7..3575ca3 100755 (executable)
@@ -2,6 +2,7 @@
 // Microsoft Visual C++ generated include file.
 // Used by OCC_Resource.rc
 //
+#define IDD_ParamsFacesPage             101
 #define IDR_POPUP                       116
 #define IDD_Dimension                   119
 #define IDD_LengthParamsEdgePage        122
 #define IDC_TextDisplayMode             1047
 #define IDC_TextDisplayModeStatic       1048
 #define IDC_DimensionColor              1049
+#define IDC_FacesSt1                    1052
+#define IDC_FacesSt2                    1053
+#define IDC_FacesBtn1                   1054
+#define IDC_FacesBtn2                   1055
 #define ID_WINDOW_NEW3D                 1151
 #define ID_OBJECT_DISPLAYALL            1201
 #define ID_OBJECT_MATERIAL              1205
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE        131
 #define _APS_NEXT_COMMAND_VALUE         40038
-#define _APS_NEXT_CONTROL_VALUE         1052
+#define _APS_NEXT_CONTROL_VALUE         1055
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif
index 3cb627e..f138f53 100755 (executable)
@@ -281,6 +281,16 @@ BEGIN
     CONTROL         "",IDC_Flyout,"msctls_trackbar32",TBS_TOP | TBS_TOOLTIPS | WS_TABSTOP,73,112,100,20
 END
 
+IDD_ParamsFacesPage DIALOGEX 0, 0, 134, 73
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+    LTEXT           "Face1",IDC_FacesSt1,18,14,20,8
+    LTEXT           "Face2",IDC_FacesSt2,18,35,20,8
+    PUSHBUTTON      "Click to set up selected face",IDC_FacesBtn1,63,7,52,24,BS_MULTILINE
+    PUSHBUTTON      "Click to set up selected face",IDC_FacesBtn2,64,39,51,24,BS_MULTILINE
+END
+
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -475,6 +485,14 @@ BEGIN
         BOTTOMMARGIN, 336
         HORZGUIDE, 336
     END
+
+    IDD_ParamsFacesPage, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 127
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 66
+    END
 END
 #endif    // APSTUDIO_INVOKED
 
index 853b503..2d7a927 100644 (file)
     <ClCompile Include="..\..\..\..\Common\LengthParamsEdgesPage.cpp" />
     <ClCompile Include="..\..\..\..\Common\LengthParamsVerticesPage.cpp" />
     <ClCompile Include="..\..\..\..\Common\RadiusParamsPage.cpp" />
+    <ClCompile Include="..\..\..\..\Common\ParamsFacesPage.cpp" />
     <ClCompile Include="..\..\..\src\mfcsample.cpp">
       <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     <ClInclude Include="..\..\..\..\Common\OCC_BaseView.h" />
     <ClInclude Include="..\..\..\..\Common\OCC_MainFrame.h" />
     <ClInclude Include="..\..\..\..\Common\RadiusParamsPage.h" />
+    <ClInclude Include="..\..\..\..\Common\ParamsFacesPage.h" />
     <ClInclude Include="..\..\..\..\Common\res\OCC_Resource.h" />
     <ClInclude Include="..\..\..\..\Common\ResultDialog.h" />
     <ClInclude Include="..\..\..\..\Common\ImportExport\SaveCSFDBDlg.h" />
index 2163d8a..65bb538 100644 (file)
     <ClCompile Include="..\..\..\..\Common\RadiusParamsPage.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\..\Common\ParamsFacesPage.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\..\..\Common\res\OCC_Resource.rc">
     <ClInclude Include="..\..\..\..\Common\RadiusParamsPage.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\..\Common\ParamsFacesPage.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\..\..\..\Common\res\2dChildFrameTB.bmp">
index f6c613f..5e3ab7c 100644 (file)
     <ClCompile Include="..\..\..\..\Common\LengthParamsEdgesPage.cpp" />
     <ClCompile Include="..\..\..\..\Common\LengthParamsVerticesPage.cpp" />
     <ClCompile Include="..\..\..\..\Common\RadiusParamsPage.cpp" />
+    <ClCompile Include="..\..\..\..\Common\ParamsFacesPage.cpp" />
     <ClCompile Include="..\..\..\src\mfcsample.cpp">
       <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     <ClInclude Include="..\..\..\..\Common\OCC_BaseView.h" />
     <ClInclude Include="..\..\..\..\Common\OCC_MainFrame.h" />
     <ClInclude Include="..\..\..\..\Common\RadiusParamsPage.h" />
+    <ClInclude Include="..\..\..\..\Common\ParamsFacesPage.h" />
     <ClInclude Include="..\..\..\..\Common\res\OCC_Resource.h" />
     <ClInclude Include="..\..\..\..\Common\ResultDialog.h" />
     <ClInclude Include="..\..\..\..\Common\ImportExport\SaveCSFDBDlg.h" />
index 2163d8a..65bb538 100644 (file)
     <ClCompile Include="..\..\..\..\Common\RadiusParamsPage.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\..\Common\ParamsFacesPage.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\..\..\Common\res\OCC_Resource.rc">
     <ClInclude Include="..\..\..\..\Common\RadiusParamsPage.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\..\Common\ParamsFacesPage.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\..\..\..\Common\res\2dChildFrameTB.bmp">
index 0731b3c..b4c98d2 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\..\..\..\Common\ParamsFacesPage.cpp"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\..\..\Common\ResultDialog.cpp"
                                >
                                <FileConfiguration
                                >
                        </File>
                        <File
+                               RelativePath="..\..\..\..\Common\ParamsFacesPage.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\..\..\Common\ResultDialog.h"
                                >
                        </File>
index 52bae88..344cc6a 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\..\..\..\Common\ParamsFacesPage.cpp"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\..\..\Common\DimensionDlg.cpp"
                                >
                        </File>
                                >
                        </File>
                        <File
+                               RelativePath="..\..\..\..\Common\ParamsFacesPage.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\..\..\Common\LengthParamsEdgesPage.h"
                                >
                        </File>
index 31bfd96..1fc8025 100755 (executable)
@@ -464,29 +464,56 @@ is
         ---Purpose:
         -- Returns the nearest point in a shape. This is used by
         -- several classes in calculation of dimensions.
-    
+
+    Nearest (theLine : Lin from gp;
+             thePoint  : Pnt from gp)
+    returns Pnt from gp;
+    ---Purpose:
+    -- @return the nearest point on the line.
+
+    Nearest (theCurve        : Curve from Geom;
+             thePoint        : Pnt from gp;
+             theFirstPoint     : Pnt from gp;
+             theLastPoint      : Pnt from gp;
+             theNearestPoint : out Pnt from gp)
+    returns Boolean from Standard;
+    ---Purpose:
+    -- For the given point finds nearest point on the curve,
+    -- @return TRUE if found point is belongs to the curve
+    -- and FALSE otherwise.
+
     Farest( aShape : Shape from TopoDS;
             aPoint : Pnt from gp )
     returns Pnt from gp;
 
-    ComputeGeometry(anEdge   : Edge from TopoDS;
-                   aCurve   : out Curve from Geom;
-                   FirstPnt : out Pnt from gp;
-                   LastPnt  : out Pnt from gp)
+    ComputeGeometry (theEdge     : Edge from TopoDS;
+                     theCurve    : out Curve from Geom;
+                     theFirstPnt : out Pnt from gp;
+                     theLastPnt  : out Pnt from gp)
     ---Purpose: Used by 2d Relation only
     --          Computes the 3d geometry of <anEdge> in the current WorkingPlane
     --          and the extremities if any
-    --          Return TRUE if ok
+    --          Return TRUE if ok.
     returns Boolean  from Standard;
-    
-    ComputeGeometry(anEdge   : Edge from TopoDS;
-                   aCurve   : out Curve from Geom;
-                   FirstPnt : out Pnt from gp;
-                   LastPnt  : out Pnt from gp;
-                   extCurve : out Curve from Geom;
-                   isinfinite: out Boolean from Standard;
-                   isOnPlane : out Boolean from Standard;      
-                   aPlane   : Plane from Geom)
+
+    ComputeGeometry (theEdge       : Edge from TopoDS;
+                     theCurve      : out Curve from Geom;
+                     theFirstPnt   : out Pnt from gp;
+                     theLastPnt    : out Pnt from gp;
+                     theIsInfinite : out Boolean from Standard)
+    ---Purpose: Used by dimensions only.
+    --          Computes the 3d geometry of <anEdge>.
+    --          Return TRUE if ok.
+    returns Boolean  from Standard;
+
+    ComputeGeometry (theEdge       : Edge from TopoDS;
+                     theCurve      : out Curve from Geom;
+                     theFirstPnt   : out Pnt from gp;
+                     theLastPnt    : out Pnt from gp;
+                     theExtCurve   : out Curve from Geom;
+                     theIsInfinite : out Boolean from Standard;
+                     theIsOnPlane  : out Boolean from Standard;
+                     thePlane      : Plane from Geom)
     ---Purpose: Used by 2d Relation only
     --          Computes the 3d geometry of <anEdge> in the current WorkingPlane
     --          and the extremities if any.
@@ -494,39 +521,51 @@ is
     --          the not projected curve associated to <anEdge>.
     --          If <anEdge> is infinite, <isinfinite> = true and the 2
     --          parameters <FirstPnt> and <LastPnt> have no signification.
-    --          Return TRUE if ok
+    --          Return TRUE if ok.
     returns Boolean from Standard;
-    
-    ComputeGeometry     (anEdge1   : Edge from TopoDS;
-                        anEdge2   : Edge from TopoDS;
-                        aCurve1   : out Curve from Geom;
-                        aCurve2   : out Curve from Geom;
-                        FirstPnt1 : out Pnt from gp;
-                        LastPnt1  : out Pnt from gp;
-                        FirstPnt2 : out Pnt from gp;
-                        LastPnt2  : out Pnt from gp;
-                        aPlane    : Plane from Geom)
+
+    ComputeGeometry (theFirstEdge   : Edge from TopoDS;
+                     theSecondEdge  : Edge from TopoDS;
+                     theFirstCurve  : out Curve from Geom;
+                     theSecondCurve : out Curve from Geom;
+                     theFirstPnt1   : out Pnt from gp;
+                     theLastPnt1    : out Pnt from gp;
+                     theFirstPnt2   : out Pnt from gp;
+                     theLastPnt2    : out Pnt from gp;
+                     thePlane       : Plane from Geom)
     ---Purpose: Used by 2d Relation only
     --          Computes the 3d geometry of <anEdge> in the current WorkingPlane
     --          and the extremities if any
-    --          Return TRUE if ok
+    --          Return TRUE if ok.
     returns Boolean from Standard;
 
+    ComputeGeometry (theFirstEdge   : Edge from TopoDS;
+                     theSecondEdge  : Edge from TopoDS;
+                     theFirstCurve  : out Curve from Geom;
+                     theSecondCurve : out Curve from Geom;
+                     theFirstPnt1   : out Pnt from gp;
+                     theLastPnt1    : out Pnt from gp;
+                     theFirstPnt2   : out Pnt from gp;
+                     theLastPnt2    : out Pnt from gp;
+                     theIsinfinite1 : out Boolean from Standard;
+                     theIsinfinite2 : out Boolean from Standard)
+    ---Purpose: Used  by  dimensions  only.Computes  the  3d geometry
+    --          of<anEdge1> and <anEdge2> and checks if they are infinite.
+    returns Boolean from Standard;
 
-    ComputeGeometry    (anEdge1   : Edge from TopoDS;
-                       anEdge2   : Edge from TopoDS;
-                       indexExt  : out Integer from Standard;
-                       aCurve1   : out Curve from Geom;
-                       aCurve2   : out Curve from Geom;
-                       FirstPnt1 : out Pnt from gp;
-                       LastPnt1  : out Pnt from gp;
-                       FirstPnt2 : out Pnt from gp;
-                       LastPnt2  : out Pnt from gp;
-                       ExtCurve  : out Curve from Geom;
-                       isinfinite1 : out Boolean from Standard;
-                       isinfinite2 : out Boolean from Standard;                        
-                       aPlane    : Plane from Geom)
-                       
+    ComputeGeometry (theFirstEdge   : Edge from TopoDS;
+                     theSecondEdge  : Edge from TopoDS;
+                     theExtIndex    : out Integer from Standard;
+                     theFirstCurve  : out Curve from Geom;
+                     theSecondCurve : out Curve from Geom;
+                     theFirstPnt1   : out Pnt from gp;
+                     theLastPnt1    : out Pnt from gp;
+                     theFirstPnt2   : out Pnt from gp;
+                     theLastPnt2    : out Pnt from gp;
+                     theExtCurve    : out Curve from Geom;
+                     theIsinfinite1 : out Boolean from Standard;
+                     theIsinfinite2 : out Boolean from Standard;
+                     thePlane       : Plane from Geom)
     ---Purpose: Used  by  2d Relation  only Computes  the  3d geometry
     --          of<anEdge1> and <anEdge2> in the current Plane and the
     --          extremities if any.   Return in ExtCurve  the 3d curve
@@ -538,102 +577,78 @@ is
     --          significant.  Return TRUE if ok
     returns Boolean from Standard;
 
-    ComputeGeomCurve   (aCurve    : in out Curve from Geom;
-                       first1    : Real from Standard;
-                       last1     : Real from Standard;
-                       FirstPnt1 : out Pnt from gp;
-                       LastPnt1  : out Pnt from gp;
-                       aPlane    : Plane from Geom;
-                       isOnPlane: out Boolean from Standard)
-                       
+    ComputeGeomCurve (aCurve    : in out Curve from Geom;
+                      first1    : Real from Standard;
+                      last1     : Real from Standard;
+                      FirstPnt1 : out Pnt from gp;
+                      LastPnt1  : out Pnt from gp;
+                      aPlane    : Plane from Geom;
+                      isOnPlane: out Boolean from Standard)
     ---Purpose: Checks if aCurve belongs to aPlane; if not, projects aCurve in aPlane 
     --          and returns aCurve;
     --          Return TRUE if ok
     returns Boolean from Standard;
 
-    ComputeGeometry(aVertex  : Vertex      from TopoDS;
-                   point    : out Pnt     from gp;
-                   aPlane   : Plane       from Geom;
-                   isOnPlane: out Boolean from Standard)
+    ComputeGeometry (aVertex  : Vertex      from TopoDS;
+                     point    : out Pnt     from gp;
+                     aPlane   : Plane       from Geom;
+                     isOnPlane: out Boolean from Standard)
     returns Boolean from Standard;
-    
 
-    GetPlaneFromFace( aFace     : Face            from TopoDS;
-                     aPlane    : out Pln         from gp;
-                     aSurf     : out Surface     from Geom;
-                     aSurfType : out KindOfSurface from AIS;
-                     Offset    : out Real from Standard )
+    GetPlaneFromFace (aFace     : Face from TopoDS;
+                      aPlane    : out Pln         from gp;
+                      aSurf     : out Surface     from Geom;
+                      aSurfType : out KindOfSurface from AIS;
+                      Offset    : out Real from Standard)
     returns Boolean from Standard;
     ---Purpose: Tryes to get Plane from Face.  Returns Surface of Face
     --          in aSurf.  Returns Standard_True  and Plane of Face in
     --           aPlane in following  cases:
     --          Face is Plane, Offset of Plane,
     --                  Extrusion of Line  and Offset of  Extrusion of Line
-    --         Returns pure type of Surface which can be:
-    --         Plane, Cylinder, Cone, Sphere, Torus, 
-    --         SurfaceOfRevolution, SurfaceOfExtrusion
-
-    InitFaceLength(  aFace         :  Face                from  TopoDS; 
-                    aPlane        :  out  Pln            from  gp; 
-                    aSurface      :  out  Surface        from  Geom; 
-                    aSurfaceType  :  out  KindOfSurface  from  AIS; 
-                    anOffset      :  out  Real           from  Standard  ); 
-                    
-    ComputeLengthBetweenPlanarFaces( FirstFace     : Face        from TopoDS;
-                                    SecondFace    : Face        from TopoDS;
-                                    Plane1        : Pln         from gp;
-                                    Plane2        : Pln         from gp;
-                                    Value         : out Real    from Standard;
-                                    FirstAttach   : out Pnt     from gp ;
-                                    SecondAttach  : out Pnt     from gp ;
-                                    DirAttach     : out Dir     from gp ;
-                                    AutomaticPos  : Boolean     from Standard;
-                                    Position      : in out Pnt  from gp);
-    
-     ComputeLengthBetweenCurvilinearFaces( FirstFace      : Face from TopoDS;
-                                          SecondFace     : Face from TopoDS;
-                                          FirstSurf      : in out Surface from Geom;
-                                          SecondSurf     : in out Surface from Geom;
-                                          AutomaticPos   : Boolean from Standard; 
-                                          Value          : out Real from Standard;
-                                          Position       : out Pnt from gp;
-                                          FirstAttach    : out Pnt from gp;
-                                          SecondAttach   : out Pnt from gp;
-                                          DirAttach      : out Dir from gp );
-                                         
-     ComputeAngleBetweenPlanarFaces( FirstFace    : Face from TopoDS;
-                                    SecondFace   : Face from TopoDS;
-                                    Surf2        : Surface from Geom;
-                                    Axis         : Ax1 from gp;
-                                    Value        : Real from Standard;
-                                    AutomaticPos : Boolean from Standard; 
-                                    Position     : out Pnt from gp;
-                                    Center       : out Pnt from gp;
-                                    FirstAttach  : out Pnt from gp;
-                                    SecondAttach : out Pnt from gp;
-                                    FirstDir     : out Dir from gp;
-                                    SecondDir    : out Dir from gp);
-    ---Purpose: Computes geometric   parameters for planar   faces for
-    --          Angular dimensions
-     ComputeAngleBetweenCurvilinearFaces( FirstFace    : Face from TopoDS;
-                                         SecondFace   : Face from TopoDS;
-                                         FirstSurf    : Surface from Geom;
-                                         SecondSurf   : Surface from Geom;
-                                         FirstSurfType  : KindOfSurface from AIS;
-                                         SecondSurfType : KindOfSurface from AIS;
-                                         Axis         : Ax1 from gp;
-                                         Value        : Real from Standard;
-                                         AutomaticPos : Boolean from Standard; 
-                                         Position     : out Pnt from gp;
-                                         Center       : out Pnt from gp;
-                                         FirstAttach  : out Pnt from gp;
-                                         SecondAttach : out Pnt from gp;
-                                         FirstDir     : out Dir from gp;
-                                         SecondDir    : out Dir from gp;
-                                         Plane        : out Plane from Geom );
-    ---Purpose: Computes geometric   parameters for curvilinear   faces for
-    --          Angular dimensions
+    --          Returns pure type of Surface which can be:
+    --          Plane, Cylinder, Cone, Sphere, Torus, 
+    --          SurfaceOfRevolution, SurfaceOfExtrusion
+
+   InitFaceLength (aFace        : Face from TopoDS;
+                   aPlane       : out Pln from gp;
+                   aSurface     : out Surface from Geom;
+                   aSurfaceType : out KindOfSurface from AIS;
+                   anOffset     : out Real from Standard );
+
+     InitLengthBetweenCurvilinearFaces (theFirstFace    : Face from TopoDS;
+                                        theSecondFace   : Face from TopoDS;
+                                        theFirstSurf    : in out Surface from Geom;
+                                        theSecondSurf   : in out Surface from Geom;
+                                        theFirstAttach  : out Pnt from gp;
+                                        theSecondAttach : out Pnt from gp;
+                                        theDirOnPlane   : out Dir from gp);
+     ---Purpose: Finds attachment points on two curvilinear faces for length dimension.
+     -- @param thePlaneDir [in] the direction on the dimension plane to
+     -- compute the plane automatically. It will not be taken into account if
+     -- plane is defined by user.
+
+    InitAngleBetweenPlanarFaces (theFirstFace      : Face from TopoDS;
+                                 theSecondFace     : Face from TopoDS;
+                                 theCenter          : out Pnt from gp;
+                                 theFirstAttach     : out Pnt from gp;
+                                 theSecondAttach    : out Pnt from gp;
+                                 theIsFirstPointSet : Boolean from Standard = Standard_False)
+    returns Boolean from Standard;
+    ---Purpose: Finds three points for the angle dimension between
+    -- two planes.
+
+    InitAngleBetweenCurvilinearFaces (theFirstFace      : Face from TopoDS;
+                                      theSecondFace     : Face from TopoDS;
+                                      theFirstSurfType   : KindOfSurface from AIS;
+                                      theSecondSurfType  : KindOfSurface from AIS;
+                                      theCenter          : out Pnt from gp;
+                                      theFirstAttach     : out Pnt from gp;
+                                      theSecondAttach    : out Pnt from gp;
+                                      theIsFirstPointSet : Boolean from Standard = Standard_False)
+    returns Boolean from Standard;
+    ---Purpose: Finds three points for the angle dimension between
+    -- two curvilinear surfaces.
 
     ProjectPointOnPlane( aPoint : Pnt from gp; aPlane : Pln from gp )
     returns Pnt from gp;
index 68b04f4..ee8186d 100755 (executable)
 #include <BRepAdaptor_Surface.hxx>
 #include <BRepTopAdaptor_FClass2d.hxx>
 #include <BRep_Tool.hxx>
+#include <BRepTools.hxx>
 #include <Bnd_Box.hxx>
 
 #include <ElCLib.hxx>
 #include <ElSLib.hxx>
 
 #include <GccEnt_QualifiedLin.hxx>
+#include <gce_MakeDir.hxx>
+#include <gce_MakeLin.hxx>
 #include <Geom2d_Circle.hxx>
 #include <GeomAPI_ExtremaCurveCurve.hxx>
+#include <GeomAPI_IntSS.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
 #include <GeomAPI_ProjectPointOnSurf.hxx>
 #include <GeomLib.hxx>
 #include <GeomProjLib.hxx>
 #include <Geom_SurfaceOfRevolution.hxx>
 #include <Geom_ToroidalSurface.hxx>
 #include <Geom_TrimmedCurve.hxx>
+#include <gp_Ax1.hxx>
+#include <gp_Ax3.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Elips.hxx>
+#include <gp_Lin.hxx>
+#include <gp_Pln.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <gp_XYZ.hxx>
 #include <Precision.hxx>
 #include <Prs3d_LineAspect.hxx>
 #include <Prs3d_PointAspect.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #include <TopoDS.hxx>
-#include <gce_MakeLin.hxx>
-#include <gp_Ax1.hxx>
-#include <gp_Ax3.hxx>
-#include <gp_Dir.hxx>
-#include <gp_Elips.hxx>
-#include <gp_Lin.hxx>
-#include <gp_Pln.hxx>
-#include <gp_Pnt.hxx>
-#include <gp_Vec.hxx>
-#include <gp_XYZ.hxx>
 
 const Standard_Real SquareTolerance = Precision::SquareConfusion();
 
@@ -86,7 +90,6 @@ const Standard_Real SquareTolerance = Precision::SquareConfusion();
 //function : Nearest
 //purpose  :
 //=======================================================================
-
 gp_Pnt AIS::Nearest(const TopoDS_Shape& ashape, const gp_Pnt& apoint)
 {
   Standard_Real dist2 = RealLast();
@@ -109,10 +112,47 @@ gp_Pnt AIS::Nearest(const TopoDS_Shape& ashape, const gp_Pnt& apoint)
 }
 
 //=======================================================================
+//function : Nearest
+//purpose  : For <thePoint> finds the nearest point on <theLine>.
+//=======================================================================
+gp_Pnt AIS::Nearest (const gp_Lin& theLine, const gp_Pnt& thePoint)
+{
+  Handle(Geom_Line) aLine = new Geom_Line (theLine);
+
+  GeomAPI_ProjectPointOnCurve aPointProj (thePoint, aLine);
+  return aPointProj.Point (1);
+}
+
+//=======================================================================
+//function : Nearest
+//purpose  : For the given point finds nearest point on the curve,
+//           return TRUE if found point is belongs to curve
+//              and FALSE otherwise.
+//=======================================================================
+Standard_Boolean AIS::Nearest (const Handle(Geom_Curve)& theCurve,
+                               const gp_Pnt& thePoint,
+                               const gp_Pnt& theFirstPoint,
+                               const gp_Pnt& theLastPoint,
+                               gp_Pnt& theNearestPoint)
+{
+  GeomAPI_ProjectPointOnCurve aPointProj (thePoint, theCurve);
+  theNearestPoint = theCurve->Value (aPointProj.LowerDistanceParameter());
+
+  Standard_Real aLength = theFirstPoint.Distance (theLastPoint);
+
+  if (theNearestPoint.Distance (theFirstPoint) > aLength
+      || theNearestPoint.Distance (theLastPoint) >aLength)
+  {
+    return Standard_False;
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
 //function : Farest
 //purpose  :
 //=======================================================================
-
 gp_Pnt AIS::Farest( const TopoDS_Shape& aShape, const gp_Pnt& aPoint )
 {
   Standard_Real MaxDist2 = 0.0e0, curdist2;
@@ -135,56 +175,102 @@ gp_Pnt AIS::Farest( const TopoDS_Shape& aShape, const gp_Pnt& aPoint )
 
 //=======================================================================
 //function : ComputeGeometry
-//purpose  : for line, circle, ellipse 
+//purpose  : for line, circle, ellipse.
 //=======================================================================
+Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge&  theEdge,
+                                       Handle(Geom_Curve)& theCurve,
+                                       gp_Pnt&             theFirstPnt,
+                                       gp_Pnt&             theLastPnt)
+{
+  TopLoc_Location anEdgeLoc;
+  Standard_Real aFirst, aLast;
+  theCurve = BRep_Tool::Curve (theEdge, anEdgeLoc, aFirst, aLast);
+  if (theCurve.IsNull())
+  {
+    return Standard_False;
+  }
+
+  if (!anEdgeLoc.IsIdentity())
+  {
+    Handle(Geom_Geometry) aGeometry = theCurve->Transformed (anEdgeLoc.Transformation());
+    theCurve = (Handle(Geom_Curve)&) aGeometry;
+  }
+
+  if (theCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
+  {
+    theCurve = ((Handle(Geom_TrimmedCurve)&) theCurve)->BasisCurve();
+  }
+
+  if (theCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
+  {
+    Handle(Geom_Line) aLine = (Handle(Geom_Line)&) theCurve;
+    theFirstPnt = ElCLib::Value (aFirst, aLine->Lin());
+    theLastPnt = ElCLib::Value (aLast, aLine->Lin());
+  }
+  else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
+  {
+    Handle(Geom_Circle) aCirc = (Handle(Geom_Circle)&) theCurve;
 
-Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge,
-                                     Handle(Geom_Curve)& aCurve,
-                                     gp_Pnt& FirstPnt,
-                                     gp_Pnt& LastPnt)
+    theFirstPnt = ElCLib::Value (aFirst, aCirc->Circ());
+    theLastPnt = ElCLib::Value (aLast, aCirc->Circ());
+  }
+  else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Ellipse)))
+  {
+    Handle(Geom_Ellipse) anEllipse = (Handle(Geom_Ellipse)&) theCurve;
+    theFirstPnt = ElCLib::Value (aFirst, anEllipse->Elips());
+    theLastPnt = ElCLib::Value (aLast, anEllipse->Elips());
+  }
+  else
+  {
+    return Standard_False;
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : ComputeGeometry
+//purpose  : for line, circle, ellipse.
+//=======================================================================
+Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theEdge,
+                                       Handle(Geom_Curve)& theCurve,
+                                       gp_Pnt& theFirstPnt,
+                                       gp_Pnt& theLastPnt,
+                                       Standard_Boolean& theIsInfinite)
 {
-  TopLoc_Location loc_edge;
-  Standard_Real first,last;
-  aCurve = BRep_Tool::Curve(anEdge,loc_edge,first,last);
-  if (aCurve.IsNull()) return Standard_False;
-  if (!loc_edge.IsIdentity()) {
-//#ifndef DEB
-    Handle(Geom_Geometry) aGeomGeometry = aCurve->Transformed(loc_edge.Transformation());
-    aCurve = (Handle(Geom_Curve)&) aGeomGeometry ;
-//#else
-//    aCurve = (Handle(Geom_Curve)&) aCurve->Transformed(loc_edge.Transformation());
-//#endif
-  }
-  if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
-    aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
-  }
-
-  if (aCurve->IsInstance(STANDARD_TYPE(Geom_Line))) {
-    // CLE
-    // const Handle(Geom_Line)& line = (Handle(Geom_Line)&) aCurve;
-    Handle(Geom_Line) line = (Handle(Geom_Line)&) aCurve;
-    // ENDCLE
+  Standard_Real aFirst, aLast;
+
+  BRepAdaptor_Curve anAdaptor (theEdge);
+
+  theCurve = Handle(Geom_Curve)::DownCast
+    (anAdaptor.Curve().Curve()->Transformed (anAdaptor.Trsf()));
 
-    FirstPnt = ElCLib::Value(first,line->Lin());
-    LastPnt = ElCLib::Value(last,line->Lin());
+  if (theCurve.IsNull())
+  {
+    return Standard_False;
   }
-  else if (aCurve->IsInstance(STANDARD_TYPE(Geom_Circle))) {
-    // CLE
-    // const Handle(Geom_Circle)& circ = (Handle(Geom_Circle)&) aCurve;
-    Handle(Geom_Circle) circ = (Handle(Geom_Circle)&) aCurve;
-    // ENDCLE
-    FirstPnt = ElCLib::Value(first,circ->Circ());
-    LastPnt = ElCLib::Value(last,circ->Circ());
+
+  aFirst = anAdaptor.FirstParameter();
+  aLast = anAdaptor.LastParameter();
+
+  theIsInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
+
+  if (theCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
+  {
+    theCurve = ((Handle(Geom_TrimmedCurve)&) theCurve)->BasisCurve();
   }
-  else if (aCurve->IsInstance(STANDARD_TYPE(Geom_Ellipse))) {
-    // CLE
-    // const Handle(Geom_Ellipse)& elips = (Handle(Geom_Ellipse)&) aCurve;
-    Handle(Geom_Ellipse) elips = (Handle(Geom_Ellipse)&) aCurve;
-    // ENDCLE
-    FirstPnt = ElCLib::Value(first, elips->Elips());
-    LastPnt = ElCLib::Value(last, elips->Elips());
+
+  if (!theIsInfinite)
+  {
+    theFirstPnt = theCurve->Value (aFirst);
+    theLastPnt  = theCurve->Value (aLast);
   }
-  else return Standard_False;
+  else
+  {
+    theFirstPnt = gp::Origin();
+    theLastPnt  = gp::Origin();
+  }
+
   return Standard_True;
 }
 
@@ -193,89 +279,95 @@ Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge,
 //purpose  :
 //=======================================================================
 
-Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge,
-                                      Handle(Geom_Curve)& aCurve,
-                                      gp_Pnt& FirstPnt,
-                                      gp_Pnt& LastPnt,
-                                      Handle(Geom_Curve)& extCurve,
-                                      Standard_Boolean& isInfinite,
-                                      Standard_Boolean& isOnPlane,
-                                      const Handle(Geom_Plane)& aPlane)
+Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theEdge,
+                                       Handle(Geom_Curve)& theCurve,
+                                       gp_Pnt& theFirstPnt,
+                                       gp_Pnt& theLastPnt,
+                                       Handle(Geom_Curve)& theExtCurve,
+                                       Standard_Boolean& theIsInfinite,
+                                       Standard_Boolean& theIsOnPlane,
+                                       const Handle(Geom_Plane)& thePlane)
 {
-  if (aPlane.IsNull()) return Standard_False;
+  if (thePlane.IsNull())
+  {
+    return Standard_False;
+  }
 
-  Standard_Real first,last;
-  BRepAdaptor_Curve brepCurv(anEdge);
-  aCurve = Handle(Geom_Curve)::DownCast(brepCurv.Curve().Curve()->Transformed(brepCurv.Trsf()));
-  first = brepCurv.FirstParameter();
-  last = brepCurv.LastParameter();
+  Standard_Real aFirst, aLast;
+  BRepAdaptor_Curve aCurveAdaptor (theEdge);
+  theCurve = Handle(Geom_Curve)::DownCast (aCurveAdaptor.Curve().Curve()->Transformed (aCurveAdaptor.Trsf()));
+  aFirst = aCurveAdaptor.FirstParameter();
+  aLast = aCurveAdaptor.LastParameter();
 
-  if (aCurve.IsNull()) return Standard_False;
+  if (theCurve.IsNull())
+  {
+    return Standard_False;
+  }
   
-  extCurve = aCurve;
-  isInfinite = (Precision::IsInfinite(first) || Precision::IsInfinite(last));
-
-  // Checks that the projcurve is not in the plane
-  isOnPlane = Standard_True;
-  if (extCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
-    extCurve = ((Handle(Geom_TrimmedCurve)&) extCurve)->BasisCurve();
+  theExtCurve = theCurve;
+  theIsInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
+
+  // Checks that the projected curve is not in the plane.
+  theIsOnPlane = Standard_True;
+  if (theExtCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
+  {
+    theExtCurve = ((Handle(Geom_TrimmedCurve)&) theExtCurve)->BasisCurve();
   }
 
-  if ( extCurve->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
-    // CLE
-    // const Handle(Geom_Line) & gl = (Handle(Geom_Line)&) extCurve;
-    Handle(Geom_Line) gl = (Handle(Geom_Line)&) extCurve;
-    // ENDCLE
-    isOnPlane = aPlane->Pln().Contains( gl->Lin(), Precision::Confusion(), Precision::Angular() );
+  if (theExtCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
+  {
+    Handle(Geom_Line) aLine = (Handle(Geom_Line)&) theExtCurve;
+    theIsOnPlane = thePlane->Pln().Contains (aLine->Lin(),
+                                             Precision::Confusion(),
+                                             Precision::Angular());
   }
-  else if (extCurve->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
-    // CLE
-    // const Handle(Geom_Circle) & gc = (Handle(Geom_Circle)&) extCurve;
-    Handle(Geom_Circle) gc = (Handle(Geom_Circle)&) extCurve;
-    // ENDCLE
-    gp_Ax3 ax(gc->Position());
-    isOnPlane = ax.IsCoplanar(aPlane->Pln().Position(),
-                              Precision::Confusion(),
-                              Precision::Angular());
+  else if (theExtCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
+  {
+    Handle(Geom_Circle) aCircle = (Handle(Geom_Circle)&) theExtCurve;
+
+    gp_Ax3 aCircPos (aCircle->Position());
+    theIsOnPlane = aCircPos.IsCoplanar (thePlane->Pln().Position(),
+                                                Precision::Confusion(),
+                                                Precision::Angular());
   }
-  if ( isOnPlane ) {
-    extCurve.Nullify();
+
+  if (theIsOnPlane)
+  {
+    theExtCurve.Nullify();
   }
-  
-//#ifndef DEB
-  Handle(Geom_Curve) aGeomCurve = GeomProjLib::ProjectOnPlane(aCurve,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
-  aCurve = aGeomCurve ;
-//#else
-//  aCurve = (Handle(Geom_Curve)&) GeomProjLib::ProjectOnPlane(aCurve,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
-//#endif
-  
-  if (aCurve->IsInstance(STANDARD_TYPE(Geom_Line))) {
-    // CLE
-    // const Handle(Geom_Line)& line = (Handle(Geom_Line)&) aCurve;
-    Handle(Geom_Line) line = (Handle(Geom_Line)&) aCurve;
-    // EDNCLE
-    if (!isInfinite) {
-      FirstPnt = ElCLib::Value(first,line->Lin());
-      LastPnt = ElCLib::Value(last,line->Lin());
+
+  theCurve = GeomProjLib::ProjectOnPlane (theCurve, thePlane,
+                                          thePlane->Pln().Axis().Direction(),
+                                          Standard_False);
+
+  if (theCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
+  {
+    Handle(Geom_Line) aLine = (Handle(Geom_Line)&) theCurve;
+    if (!theIsInfinite)
+    {
+      theFirstPnt = ElCLib::Value (aFirst, aLine->Lin());
+      theLastPnt = ElCLib::Value (aLast, aLine->Lin());
     }
   }
-  else if (aCurve->IsInstance(STANDARD_TYPE(Geom_Circle))) {
-    // CLE
-    // const Handle(Geom_Circle)& circ = (Handle(Geom_Circle)&) aCurve;
-    Handle(Geom_Circle) circ = (Handle(Geom_Circle)&) aCurve;
-    // ENDCLE
-    FirstPnt = ElCLib::Value(first,circ->Circ());
-    LastPnt = ElCLib::Value(last,circ->Circ());
+  else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
+  {
+    Handle(Geom_Circle) aCirc = (Handle(Geom_Circle)&) theCurve;
+
+    theFirstPnt = ElCLib::Value (aFirst, aCirc->Circ());
+    theLastPnt = ElCLib::Value (aLast, aCirc->Circ());
   }
-  // jfa 10/10/2000
-  else if (aCurve->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
+  else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Ellipse)))
     {
-      Handle(Geom_Ellipse) ell = (Handle(Geom_Ellipse)&) aCurve;
-      FirstPnt = ElCLib::Value(first,ell->Elips());
-      LastPnt = ElCLib::Value(last,ell->Elips());
+      Handle(Geom_Ellipse) anEllipse = (Handle(Geom_Ellipse)&) theCurve;
+
+      theFirstPnt = ElCLib::Value (aFirst, anEllipse->Elips());
+      theLastPnt = ElCLib::Value (aLast, anEllipse->Elips());
     }
-  // jfa 10/10/2000 end
-  else return Standard_False;
+  else
+  {
+    return Standard_False;
+  }
+
   return Standard_True;
 }
 
@@ -283,106 +375,185 @@ Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge,
 //function : ComputeGeometry
 //purpose  :
 //=======================================================================
-
-Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge1,
-                                     const TopoDS_Edge& anEdge2,
-                                     Handle(Geom_Curve)& aCurve1,
-                                     Handle(Geom_Curve)& aCurve2,
-                                     gp_Pnt& FirstPnt1,
-                                     gp_Pnt& LastPnt1,
-                                     gp_Pnt& FirstPnt2,
-                                     gp_Pnt& LastPnt2,
-                                     const Handle(Geom_Plane)& aPlane)
+Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
+                                      const TopoDS_Edge& theSecondEdge,
+                                      Handle(Geom_Curve)& theFirstCurve,
+                                      Handle(Geom_Curve)& theSecondCurve,
+                                      gp_Pnt& theFirstPnt1,
+                                      gp_Pnt& theLastPnt1,
+                                      gp_Pnt& theFirstPnt2,
+                                      gp_Pnt& theLastPnt2,
+                                      const Handle(Geom_Plane)& thePlane)
 {
-  if (aPlane.IsNull()) return Standard_False;
+  if (thePlane.IsNull())
+  {
+    return Standard_False;
+  }
 
-  TopLoc_Location loc_edge1,loc_edge2;
-  Standard_Real first1,last1,first2,last2;
+  TopLoc_Location aFirstEdgeLoc, aSecondEdgeLoc;
+  Standard_Real aFirst1, aLast1, aFirst2, aLast2;
   
-  aCurve1 = BRep_Tool::Curve(anEdge1,loc_edge1,first1,last1);
-  aCurve2 = BRep_Tool::Curve(anEdge2,loc_edge2,first2,last2);
+  theFirstCurve = BRep_Tool::Curve (theFirstEdge, aFirstEdgeLoc, aFirst1, aLast1);
+  theSecondCurve = BRep_Tool::Curve (theSecondEdge, aSecondEdgeLoc, aFirst2, aLast2);
 
-  if (aCurve1.IsNull()) return Standard_False;
-  if (aCurve2.IsNull()) return Standard_False;
+  if (theFirstCurve.IsNull())
+  {
+    return Standard_False;
+  }
+    
+  if (theSecondCurve.IsNull())
+  {
+    return Standard_False;
+  }
   
-  if (!loc_edge1.IsIdentity()) {
-//#ifndef DEB
-    Handle(Geom_Geometry) aGeomGeometry = aCurve1->Transformed(loc_edge1.Transformation());
-    aCurve1 = (Handle(Geom_Curve)&) aGeomGeometry ;
-//#else
-//    aCurve1 = (Handle(Geom_Curve)&) aCurve1->Transformed(loc_edge1.Transformation());
-//#endif
-  }
-  if (!loc_edge2.IsIdentity()) {
-//#ifndef DEB
-    Handle(Geom_Geometry) aGeomGeometry = aCurve2->Transformed(loc_edge2.Transformation());
-    aCurve2 = (Handle(Geom_Curve)&) aGeomGeometry ;
-//#else
-//    aCurve2 = (Handle(Geom_Curve)&) aCurve2->Transformed(loc_edge2.Transformation());
-//#endif
-  }
-
-//#ifndef DEB
-  Handle(Geom_Curve) aGeomCurve = GeomProjLib::ProjectOnPlane(aCurve1,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
-  aCurve1 = aGeomCurve ;
-//#else
-//  aCurve1 =  (Handle(Geom_Curve)&) GeomProjLib::ProjectOnPlane(aCurve1,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
-//#endif
-//#ifndef DEB
-  aGeomCurve = GeomProjLib::ProjectOnPlane(aCurve2,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
-  aCurve2 = aGeomCurve;
-//#else
-//  aCurve2 =  (Handle(Geom_Curve)&) GeomProjLib::ProjectOnPlane(aCurve2,aPlane,aPlane->Pln().Axis().Direction(),Standard_False);
-//#endif
-
-  if (aCurve1->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
-    aCurve1 = ((Handle(Geom_TrimmedCurve)&) aCurve1)->BasisCurve();
-  }
-  if (aCurve2->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
-    aCurve2 = ((Handle(Geom_TrimmedCurve)&) aCurve2)->BasisCurve();
-  }
-
-  if (aCurve1->IsInstance(STANDARD_TYPE(Geom_Line))) {
-    // CLE
-    // const Handle(Geom_Line)& line = (Handle(Geom_Line)&) aCurve1;
-    Handle(Geom_Line) line = (Handle(Geom_Line)&) aCurve1;
-    // ENDCLE
-    FirstPnt1 = ElCLib::Value(first1,line->Lin());
-    LastPnt1 = ElCLib::Value(last1,line->Lin());
+  if (!aFirstEdgeLoc.IsIdentity())
+  {
+    Handle(Geom_Geometry) aGeomGeometry = theFirstCurve->Transformed (aFirstEdgeLoc.Transformation());
+    theFirstCurve = (Handle(Geom_Curve)&) aGeomGeometry;
   }
-  else if (aCurve1->IsInstance(STANDARD_TYPE(Geom_Circle))) {
-    // CLE
-    // const Handle(Geom_Circle)& circ = (Handle(Geom_Circle)&) aCurve1;
-    Handle(Geom_Circle) circ = (Handle(Geom_Circle)&) aCurve1;
-    // ENDCLE
-    FirstPnt1 = ElCLib::Value(first1,circ->Circ());
-    LastPnt1 = ElCLib::Value(last1,circ->Circ());
+    
+  if (!aSecondEdgeLoc.IsIdentity())
+  {
+    Handle(Geom_Geometry) aGeomGeometry = theSecondCurve->Transformed (aSecondEdgeLoc.Transformation());
+    theSecondCurve = (Handle(Geom_Curve)&) aGeomGeometry;
   }
-  else return Standard_False;
 
-  if (aCurve2->IsInstance(STANDARD_TYPE(Geom_Line))) {
-    // CLE
-    // const Handle(Geom_Line)& line = (Handle(Geom_Line)&) aCurve2;
-    Handle(Geom_Line) line = (Handle(Geom_Line)&) aCurve2;
-    // ENDCLE
-    FirstPnt2 = ElCLib::Value(first2,line->Lin());
-    LastPnt2 = ElCLib::Value(last2,line->Lin());
+  theFirstCurve = GeomProjLib::ProjectOnPlane (theFirstCurve, thePlane,
+                                               thePlane->Pln().Axis().Direction(),
+                                               Standard_False);
+
+
+  theSecondCurve = GeomProjLib::ProjectOnPlane (theSecondCurve, thePlane,
+                                                thePlane->Pln().Axis().Direction(),
+                                                Standard_False);
+
+
+  if (theFirstCurve->IsInstance (STANDARD_TYPE(Geom_TrimmedCurve)))
+  {
+    theFirstCurve = ((Handle(Geom_TrimmedCurve)&) theFirstCurve)->BasisCurve();
   }
-  else if (aCurve2->IsInstance(STANDARD_TYPE(Geom_Circle))) {
-    // CLE
-    // const Handle(Geom_Circle)& circ = (Handle(Geom_Circle)&) aCurve2;
-    Handle(Geom_Circle) circ = (Handle(Geom_Circle)&) aCurve2;
-    // ENDCLE
-    FirstPnt2 = ElCLib::Value(first2,circ->Circ());
-    LastPnt2 = ElCLib::Value(last2,circ->Circ());
+    
+  if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
+  {
+    theSecondCurve = ((Handle(Geom_TrimmedCurve)&) theSecondCurve)->BasisCurve();
+  }
+
+  if (theFirstCurve->IsInstance(STANDARD_TYPE(Geom_Line)))
+  {
+    Handle(Geom_Line) aLine = (Handle(Geom_Line)&) theFirstCurve;
+
+    theFirstPnt1 = ElCLib::Value (aFirst1, aLine->Lin());
+    theLastPnt1 = ElCLib::Value (aLast1, aLine->Lin());
+  }
+  else if (theFirstCurve->IsInstance(STANDARD_TYPE(Geom_Circle)))
+  {
+    Handle(Geom_Circle) aCirc = (Handle(Geom_Circle)&) theFirstCurve;
+      
+    theFirstPnt1 = ElCLib::Value (aFirst1, aCirc->Circ());
+    theLastPnt1 = ElCLib::Value (aLast1, aCirc->Circ());
+  }
+  else
+  {
+    return Standard_False;
+  }
+
+  if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
+{
+    Handle(Geom_Line) aLine = (Handle(Geom_Line)&) theSecondCurve;
+
+    theFirstPnt2 = ElCLib::Value (aFirst2, aLine->Lin());
+    theLastPnt2 = ElCLib::Value (aLast2, aLine->Lin());
+  }
+  else if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
+  {
+    Handle(Geom_Circle) aCirc = (Handle(Geom_Circle)&) theSecondCurve;
+
+    theFirstPnt2 = ElCLib::Value (aFirst2, aCirc->Circ());
+    theLastPnt2 = ElCLib::Value (aLast2, aCirc->Circ());
+  }
+  else
+  {
+    return Standard_False;
   }
-  else return Standard_False;
 
   return Standard_True;
 }
 
 //=======================================================================
 //function : ComputeGeometry
+//purpose  : Computes the geometry of the 2 edges.
+//=======================================================================
+Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
+                                       const TopoDS_Edge& theSecondEdge,
+                                       Handle(Geom_Curve)& theFirstCurve,
+                                       Handle(Geom_Curve)& theSecondCurve,
+                                       gp_Pnt& theFirstPnt1,
+                                       gp_Pnt& theLastPnt1,
+                                       gp_Pnt& theFirstPnt2,
+                                       gp_Pnt& theLastPnt2,
+                                       Standard_Boolean& theIsInfinite1,
+                                       Standard_Boolean& theIsInfinite2)
+{
+    theIsInfinite1 = theIsInfinite2 = Standard_False;
+
+   if (!AIS::ComputeGeometry (theFirstEdge, theFirstCurve,theFirstPnt1, theLastPnt1, theIsInfinite1))
+   {
+     return Standard_False;
+   }
+
+   if (!AIS::ComputeGeometry (theSecondEdge, theSecondCurve,theFirstPnt2, theLastPnt2, theIsInfinite2))
+   {
+     return Standard_False;
+   }
+
+  if (theIsInfinite1 || theIsInfinite2)
+  {
+      if (theFirstCurve->DynamicType() == theSecondCurve->DynamicType())
+      {
+          gp_Lin aLin1 = ((Handle(Geom_Line)&) theFirstCurve)->Lin();
+          gp_Lin aLin2 = ((Handle(Geom_Line)&) theSecondCurve)->Lin();
+
+          if (theIsInfinite1)
+          {
+              theFirstPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theFirstPnt2), aLin1);
+              theLastPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theLastPnt2), aLin1);
+          }
+          else if (theIsInfinite2)
+          {
+              theFirstPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theFirstPnt1), aLin2);
+              theLastPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theLastPnt1), aLin2);
+          }
+      }
+      else
+      {
+        if (theIsInfinite1 && !theIsInfinite2)
+        {
+          GeomAPI_ProjectPointOnCurve aProjector (theFirstPnt2, theFirstCurve);
+          theFirstPnt1 = theFirstCurve->Value (aProjector.LowerDistanceParameter ());
+
+          aProjector.Init (theLastPnt2, theFirstCurve);
+          theLastPnt1 = theFirstCurve->Value (aProjector.LowerDistanceParameter ());
+        }
+        else if (!theIsInfinite1 && theIsInfinite2)
+        {
+          GeomAPI_ProjectPointOnCurve aProjector (theFirstPnt1, theSecondCurve);
+          theFirstPnt2 = theSecondCurve->Value (aProjector.LowerDistanceParameter ());
+
+          aProjector.Init (theLastPnt1, theSecondCurve);
+          theLastPnt2 = theSecondCurve->Value (aProjector.LowerDistanceParameter ());
+        }
+        else
+        {
+          return Standard_False;
+        }
+      }
+  }
+
+    return Standard_True;
+}
+
+//=======================================================================
+//function : ComputeGeometry
 //purpose  : Computes the geometry of the 2 edges in the current wp
 //           and the 'right' geometry of the edges if one doesn't
 //           belong to the current working plane.
@@ -396,160 +567,183 @@ Standard_Boolean AIS::ComputeGeometry(const TopoDS_Edge& anEdge1,
 //           if none of the two edges is in the current wp ,
 //           it returns Standard_False
 //=======================================================================
-
-Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& anEdge1,
-                                       const TopoDS_Edge& anEdge2,
-                                       Standard_Integer& indexExt,
-                                       Handle(Geom_Curve)& aCurve1,
-                                       Handle(Geom_Curve)& aCurve2,
-                                       gp_Pnt& FirstPnt1,
-                                       gp_Pnt& LastPnt1,
-                                       gp_Pnt& FirstPnt2,
-                                       gp_Pnt& LastPnt2,
-                                       Handle(Geom_Curve)& extCurve,
-                                       Standard_Boolean& isInfinite1,
-                                       Standard_Boolean& isInfinite2,
-                                       const Handle(Geom_Plane)& aPlane)
+Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
+                                       const TopoDS_Edge& theSecondEdge,
+                                       Standard_Integer& theExtIndex,
+                                       Handle(Geom_Curve)& theFirstCurve,
+                                       Handle(Geom_Curve)& theSecondCurve,
+                                       gp_Pnt& theFirstPnt1,
+                                       gp_Pnt& theLastPnt1,
+                                       gp_Pnt& theFirstPnt2,
+                                       gp_Pnt& theLastPnt2,
+                                       Handle(Geom_Curve)& theExtCurve,
+                                       Standard_Boolean& theIsInfinite1,
+                                       Standard_Boolean& theIsInfinite2,
+                                       const Handle(Geom_Plane)& thePlane)
 {
-  if (aPlane.IsNull()) return Standard_False;
-  extCurve.Nullify();
-  indexExt = 0;
+  if (thePlane.IsNull())
+  {
+    return Standard_False;
+  }
+
+  theExtCurve.Nullify();
+  theExtIndex = 0;
 
-  Standard_Real first1,last1,first2,last2;
-  isInfinite1 = isInfinite2 = Standard_False;
+  Standard_Real aFirst1, aLast1, aFirst2, aLast2;
+  theIsInfinite1 = theIsInfinite2 = Standard_False;
 
-  BRepAdaptor_Curve brepCurv1(anEdge1);
-  BRepAdaptor_Curve brepCurv2(anEdge2);
-  aCurve1 = Handle(Geom_Curve)::DownCast(brepCurv1.Curve().Curve()->Transformed(brepCurv1.Trsf()));
-  aCurve2 = Handle(Geom_Curve)::DownCast(brepCurv2.Curve().Curve()->Transformed(brepCurv2.Trsf()));
-  if (aCurve1->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
-    aCurve1 = ((Handle(Geom_TrimmedCurve)&) aCurve1)->BasisCurve();
+  BRepAdaptor_Curve aFirstAdaptor (theFirstEdge);
+  BRepAdaptor_Curve aSecondAdaptor (theSecondEdge);
+
+  theFirstCurve = Handle(Geom_Curve)::DownCast
+                  (aFirstAdaptor.Curve().Curve()->Transformed (aFirstAdaptor.Trsf()));
+  theSecondCurve = Handle(Geom_Curve)::DownCast
+                  (aSecondAdaptor.Curve().Curve()->Transformed (aSecondAdaptor.Trsf()));
+
+  if (theFirstCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
+  {
+    theFirstCurve = ((Handle(Geom_TrimmedCurve)&) theFirstCurve)->BasisCurve();
   }
-  if (aCurve2->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
-    aCurve2 = ((Handle(Geom_TrimmedCurve)&) aCurve2)->BasisCurve();
+  if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
+  {
+    theSecondCurve = ((Handle(Geom_TrimmedCurve)&) theSecondCurve)->BasisCurve();
   }
 
-  first1 = brepCurv1.FirstParameter();
-  last1 = brepCurv1.LastParameter();
-  first2 = brepCurv2.FirstParameter();
-  last2 = brepCurv2.LastParameter();
+  aFirst1 = aFirstAdaptor.FirstParameter();
+  aLast1 = aFirstAdaptor.LastParameter();
 
-  if (aCurve1.IsNull()) return Standard_False;
-  if (aCurve2.IsNull()) return Standard_False;
-  
-  Handle(Geom_Curve) aSov1 = aCurve1;
-  Handle(Geom_Curve) aSov2 = aCurve2;
-  // Checks that the projcurve is not in the plane
-  Standard_Boolean isOnPlanC1,isOnPlanC2;
-  if ((!ComputeGeomCurve(aCurve1,first1,last1,FirstPnt1,LastPnt1,aPlane,isOnPlanC1))
-      || (!ComputeGeomCurve(aCurve2,first2,last2,FirstPnt2,LastPnt2,aPlane,isOnPlanC2)))
+  aFirst2 = aSecondAdaptor.FirstParameter();
+  aLast2 = aSecondAdaptor.LastParameter();
+
+  if (theFirstCurve.IsNull() || theSecondCurve.IsNull())
+  {
     return Standard_False;
-  
-  if (Precision::IsInfinite(first1) || Precision::IsInfinite(last1)) {
-    isInfinite1 = Standard_True;
-    indexExt = 1;
-  }
-  if (Precision::IsInfinite(first2) || Precision::IsInfinite(last2)) {
-    isInfinite2 = Standard_True;    
-    indexExt = 2;
-  }
-  if (isInfinite1 && isInfinite2) indexExt = 0;  //New
-
-  if (isInfinite1 || isInfinite2) {
-    if (aCurve1->DynamicType() == aCurve2->DynamicType()) {
-      // CLE
-      // const gp_Lin& lin1 = ((Handle(Geom_Line)&) aCurve1)->Lin();
-      // const gp_Lin& lin2 = ((Handle(Geom_Line)&) aCurve2)->Lin();
-      gp_Lin lin1 = ((Handle(Geom_Line)&) aCurve1)->Lin();
-      gp_Lin lin2 = ((Handle(Geom_Line)&) aCurve2)->Lin();
-      // ENDCLE
-      if (indexExt == 1) {
-        FirstPnt1 = ElCLib::Value(ElCLib::Parameter(lin2,FirstPnt2),lin1);
-        LastPnt1 = ElCLib::Value(ElCLib::Parameter(lin2,LastPnt2),lin1);
+  }
+
+  Handle(Geom_Curve) aFirstSaved = theFirstCurve;
+  Handle(Geom_Curve) aSecondSaved = theSecondCurve;
+
+  // Checks that the projected curve is not in the plane
+  Standard_Boolean isFirstOnPlane,isSecondOnPlane;
+
+  if ((!ComputeGeomCurve (theFirstCurve, aFirst1, aLast1, theFirstPnt1, theLastPnt1, thePlane, isFirstOnPlane))
+      || (!ComputeGeomCurve( theSecondCurve, aFirst2, aLast2, theFirstPnt2, theLastPnt2, thePlane,isSecondOnPlane)))
+  {
+    return Standard_False;
+  }
+
+  if (Precision::IsInfinite (aFirst1) || Precision::IsInfinite (aLast1))
+  {
+    theIsInfinite1 = Standard_True;
+    theExtIndex = 1;
+  }
+  if (Precision::IsInfinite (aFirst2) || Precision::IsInfinite (aLast2))
+  {
+    theIsInfinite2 = Standard_True;
+    theExtIndex = 2;
+  }
+  if (theIsInfinite1 && theIsInfinite2)
+  {
+    theExtIndex = 0;
+  }
+
+  if (theIsInfinite1 || theIsInfinite2)
+  {
+    if (theFirstCurve->DynamicType() == theSecondCurve->DynamicType())
+    {
+      gp_Lin aLin1 = ((Handle(Geom_Line)&) theFirstCurve)->Lin();
+      gp_Lin aLin2 = ((Handle(Geom_Line)&) theSecondCurve)->Lin();
+
+      if (theExtIndex == 1)
+      {
+        theFirstPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theFirstPnt2), aLin1);
+        theLastPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theLastPnt2), aLin1);
       }
-      else if (indexExt == 2) {
-       FirstPnt2 = ElCLib::Value(ElCLib::Parameter(lin1,FirstPnt1),lin2);
-       LastPnt2 = ElCLib::Value(ElCLib::Parameter(lin1,LastPnt1),lin2);
+      else if (theExtIndex == 2)
+      {
+        theFirstPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theFirstPnt1), aLin2);
+        theLastPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theLastPnt1), aLin2);
       }
     }
   }
 
-  if (isOnPlanC1 && isOnPlanC2) return Standard_True;
+  if (isFirstOnPlane && isSecondOnPlane)
+  {
+    return Standard_True;
+  }
 
-  if (!isOnPlanC1 && isOnPlanC2) {// curve 2 only in the plane
-    indexExt = 1;
-    extCurve = aSov1;
+  if (!isFirstOnPlane && isSecondOnPlane)
+  {// curve 2 only in the plane
+    theExtIndex = 1;
+    theExtCurve = aFirstSaved;
   }
-  else if (isOnPlanC1 && !isOnPlanC2) {// curve 1 only in the plane
-    indexExt = 2;
-    extCurve = aSov2;
+  else if (isFirstOnPlane && !isSecondOnPlane)
+  {// curve 1 only in the plane
+    theExtIndex = 2;
+    theExtCurve = aSecondSaved;
   }
   else
+  {
     return Standard_False;
-  
+  }
+
   return Standard_True;
 }
 
-
-// it is patch!
-
 //=======================================================================
 //function : ComputeGeomCurve
 //purpose  : Checks if aCurve belongs to aPlane; if not, projects aCurve in aPlane
 //           and returns aCurveproj;
 //           Return TRUE if ok
 //=======================================================================
-
-Standard_Boolean AIS::ComputeGeomCurve(Handle(Geom_Curve)& aCurve,
-                                          const Standard_Real first1,
-                                          const Standard_Real last1,
-                                          gp_Pnt& FirstPnt1,
-                                          gp_Pnt& LastPnt1,
-                                          const Handle(Geom_Plane)& aPlane,
-                                          Standard_Boolean& isOnPlane)
+Standard_Boolean AIS::ComputeGeomCurve (Handle(Geom_Curve)& aCurve,
+                                        const Standard_Real first1,
+                                        const Standard_Real last1,
+                                        gp_Pnt& FirstPnt1,
+                                        gp_Pnt& LastPnt1,
+                                        const Handle(Geom_Plane)& aPlane,
+                                        Standard_Boolean& isOnPlane)
 {
   isOnPlane = Standard_True;
-
   const Standard_Integer NodeNumber = 20;
   Standard_Real Delta = (last1 - first1) / (NodeNumber - 1);
   if (Delta <= Precision::PConfusion())
+  {
     Delta = last1 - first1;
-  gp_Pnt CurPnt(0.0,0.0,0.0);
+  }
+
+  gp_Pnt CurPnt(0.0, 0.0, 0.0);
   Standard_Real CurPar = first1;
   for (Standard_Integer i = 1; i <= NodeNumber; i++)
+  {
+    CurPnt = aCurve->Value( CurPar );
+    if (aPlane->Pln().SquareDistance( CurPnt ) > SquareTolerance)
     {
-      CurPnt = aCurve->Value( CurPar );
-      if (aPlane->Pln().SquareDistance( CurPnt ) > SquareTolerance)
-       {
-         isOnPlane = Standard_False;
-         break;
-       }
-      CurPar += Delta;
+      isOnPlane = Standard_False;
+      break;
     }
-  
-  if (! Precision::IsInfinite(first1) && ! Precision::IsInfinite(last1))
+    CurPar += Delta;
+  }
+
+  if (!Precision::IsInfinite(first1) && !Precision::IsInfinite(last1))
+  {
+    FirstPnt1 = aCurve->Value (first1);
+    LastPnt1  = aCurve->Value (last1);
+  }
+
+  if (!isOnPlane)
+  {
+    Handle(Geom_Curve) aGeomCurve = GeomProjLib::ProjectOnPlane (aCurve,
+                                                                aPlane,
+                                                                aPlane->Pln().Axis().Direction(),
+                                                                Standard_False);
+    aCurve = aGeomCurve;
+    if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
     {
-      FirstPnt1 = aCurve->Value( first1 );
-      LastPnt1  = aCurve->Value( last1 );
-    }
-  if (!isOnPlane) {
-//#ifndef DEB
-    Handle( Geom_Curve ) aGeomCurve = GeomProjLib::ProjectOnPlane( aCurve,
-                                                                  aPlane,
-                                                                  aPlane->Pln().Axis().Direction(),
-                                                                  Standard_False);
-    aCurve = aGeomCurve ;
-//#else
-//    aCurve =  (Handle( Geom_Curve )&) GeomProjLib::ProjectOnPlane( aCurve,
-//                                                                aPlane,
-//                                                                aPlane->Pln().Axis().Direction(),
-//                                                                Standard_False);
-//#endif
-    if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) {
       aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
     }
-    if (! Precision::IsInfinite(first1) && ! Precision::IsInfinite(last1)) {
+    if (! Precision::IsInfinite(first1) && ! Precision::IsInfinite(last1))
+    {
       FirstPnt1 = AIS::ProjectPointOnPlane( FirstPnt1, aPlane->Pln() );
       LastPnt1 = AIS::ProjectPointOnPlane( LastPnt1, aPlane->Pln() );
     }
@@ -557,7 +751,6 @@ Standard_Boolean AIS::ComputeGeomCurve(Handle(Geom_Curve)& aCurve,
   return Standard_True;
 }
 
-
 //=======================================================================
 //function : ComputeGeometry
 //purpose  : computes the point corresponding to the vertex <aVertex>
@@ -565,7 +758,6 @@ Standard_Boolean AIS::ComputeGeomCurve(Handle(Geom_Curve)& aCurve,
 //           <isOnPlane>, <isOnPlane> = true.
 //           <point> is the projected vertex in the plane.
 //=======================================================================
-
 Standard_Boolean  AIS::ComputeGeometry(const TopoDS_Vertex& aVertex,
                                        gp_Pnt& point,
                                        const Handle(Geom_Plane)& aPlane,
@@ -584,26 +776,24 @@ Standard_Boolean  AIS::ComputeGeometry(const TopoDS_Vertex& aVertex,
 //purpose  :
 //           Returns type of surface which can be Plane or OtherSurface
 //=======================================================================
-
-Standard_Boolean AIS::GetPlaneFromFace( const TopoDS_Face&            aFace,
+Standard_Boolean AIS::GetPlaneFromFace(const TopoDS_Face&            aFace,
                                         gp_Pln &                     aPlane,
                                         Handle( Geom_Surface )&      aSurf,
                                         AIS_KindOfSurface &          aSurfType,
-                                        Standard_Real &              Offset )
+                                        Standard_Real &              Offset)
 
 {
   Standard_Boolean Result = Standard_False;
   BRepAdaptor_Surface surf1( aFace );
   Handle( Adaptor3d_HSurface ) surf2;
-  //gp_Vec OffsetVec( 1.0e0, 0.0e0, 0.0e0 );
   Standard_Boolean isOffset = Standard_False;
 
   if (surf1.GetType() == GeomAbs_OffsetSurface)
-    {
-      // Extracting Basis Surface
-      surf2 = surf1.BasisSurface();
-      isOffset = Standard_True;
-    }
+  {
+    // Extracting Basis Surface
+    surf2 = surf1.BasisSurface();
+    isOffset = Standard_True;
+  }
   else
     surf2 = new BRepAdaptor_HSurface( surf1 );
 
@@ -612,81 +802,71 @@ Standard_Boolean AIS::GetPlaneFromFace( const TopoDS_Face&            aFace,
   aSurf = Handle( Geom_Surface )::DownCast( aSurf->Transformed( surf1.Trsf() ) );
 
   if (surf2->GetType() == GeomAbs_Plane)
+  {
+    aPlane = surf2->Plane();
+    aSurfType = AIS_KOS_Plane;
+    Offset = 0.;
+    Result = Standard_True;
+  }
+
+  else if (surf2->GetType() == GeomAbs_SurfaceOfExtrusion)
+  {
+    Handle( Adaptor3d_HCurve ) BasisCurve = surf2->BasisCurve();
+    gp_Dir ExtrusionDir = surf2->Direction();
+    if (BasisCurve->GetType() == GeomAbs_Line)
     {
-      aPlane = surf2->Plane();
+      gp_Lin BasisLine = BasisCurve->Line();
+      gp_Dir LineDir = BasisLine.Direction();
+      gp_Pnt LinePos = BasisLine.Location();
+      gp_Pln thePlane( LinePos, LineDir ^ ExtrusionDir);
+      aPlane = thePlane;
       aSurfType = AIS_KOS_Plane;
       Offset = 0.;
       Result = Standard_True;
     }
-
-  else if (surf2->GetType() == GeomAbs_SurfaceOfExtrusion)
-    {
-      Handle( Adaptor3d_HCurve ) BasisCurve = surf2->BasisCurve();
-      gp_Dir ExtrusionDir = surf2->Direction();
-      if (BasisCurve->GetType() == GeomAbs_Line)
-        {
-          gp_Lin BasisLine = BasisCurve->Line();
-          gp_Dir LineDir = BasisLine.Direction();
-          gp_Pnt LinePos = BasisLine.Location();
-          gp_Pln thePlane( LinePos, LineDir ^ ExtrusionDir);
-          aPlane = thePlane;
-          aSurfType = AIS_KOS_Plane;
-          Offset = 0.;
-          Result = Standard_True;
-        }
-    }
+  }
 
   if (Result == Standard_True && isOffset)
-    {
-      aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
-      aPlane = (Handle( Geom_Plane )::DownCast( aSurf ))->Pln();
-      /*
-      Handle( Geom_OffsetSurface ) OffsetSurf = Handle( Geom_OffsetSurface )::DownCast( aSurf );
-      gp_Pnt PointOnPlane;
-      gp_Vec D1u, D1v;
-      OffsetSurf->D1( 0, 0, PointOnPlane, D1u, D1v );
-      D1u.Normalize();
-      D1v.Normalize();
-      OffsetVec = D1u ^ D1v;
-      aPlane.Translate( OffsetValue * OffsetVec );
-      */
-      Offset = 0.0e0;
-    }
+  {
+    aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
+    aPlane = (Handle( Geom_Plane )::DownCast( aSurf ))->Pln();
+    Offset = 0.0e0;
+  }
   if (Result == Standard_False)
+  {
+    if (isOffset)
     {
-      if (isOffset)
-       {
-         Handle( Standard_Type ) TheType = aSurf->DynamicType();
-         if (TheType == STANDARD_TYPE(Geom_CylindricalSurface) ||
-             TheType == STANDARD_TYPE(Geom_ConicalSurface)     ||
-             TheType == STANDARD_TYPE(Geom_SphericalSurface)   ||
-             TheType == STANDARD_TYPE(Geom_ToroidalSurface))
-           {
-             aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
-             Offset = 0.0e0;
-           }
-         else
-           {
-             Offset = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Offset();
-             aSurf =  (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->BasisSurface();
-           }
-       }
       Handle( Standard_Type ) TheType = aSurf->DynamicType();
-      if (TheType == STANDARD_TYPE(Geom_CylindricalSurface))
-        aSurfType = AIS_KOS_Cylinder;
-      else if (TheType == STANDARD_TYPE(Geom_ConicalSurface))
-        aSurfType = AIS_KOS_Cone;
-      else if (TheType == STANDARD_TYPE(Geom_SphericalSurface))
-        aSurfType = AIS_KOS_Sphere;
-      else if (TheType == STANDARD_TYPE(Geom_ToroidalSurface))
-        aSurfType = AIS_KOS_Torus;
-      else if (TheType == STANDARD_TYPE(Geom_SurfaceOfRevolution))
-        aSurfType = AIS_KOS_Revolution;
-      else if (TheType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
-        aSurfType = AIS_KOS_Extrusion;
+      if (TheType == STANDARD_TYPE(Geom_CylindricalSurface) ||
+        TheType == STANDARD_TYPE(Geom_ConicalSurface)     ||
+        TheType == STANDARD_TYPE(Geom_SphericalSurface)   ||
+        TheType == STANDARD_TYPE(Geom_ToroidalSurface))
+      {
+        aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
+        Offset = 0.0e0;
+      }
       else
-        aSurfType = AIS_KOS_OtherSurface;
+      {
+        Offset = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Offset();
+        aSurf =  (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->BasisSurface();
+      }
     }
+    Handle( Standard_Type ) TheType = aSurf->DynamicType();
+    if (TheType == STANDARD_TYPE(Geom_CylindricalSurface))
+      aSurfType = AIS_KOS_Cylinder;
+    else if (TheType == STANDARD_TYPE(Geom_ConicalSurface))
+      aSurfType = AIS_KOS_Cone;
+    else if (TheType == STANDARD_TYPE(Geom_SphericalSurface))
+      aSurfType = AIS_KOS_Sphere;
+    else if (TheType == STANDARD_TYPE(Geom_ToroidalSurface))
+      aSurfType = AIS_KOS_Torus;
+    else if (TheType == STANDARD_TYPE(Geom_SurfaceOfRevolution))
+      aSurfType = AIS_KOS_Revolution;
+    else if (TheType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
+      aSurfType = AIS_KOS_Extrusion;
+    else
+      aSurfType = AIS_KOS_OtherSurface;
+  }
   return Result;
 }
 
@@ -719,17 +899,15 @@ gp_Pnt AIS::ProjectPointOnLine( const gp_Pnt & aPoint, const gp_Lin & aLine )
   return Result;
 }
 
-
 //=======================================================================
 //function : InitFaceLength
 //purpose  : 
 //=======================================================================
-
-void AIS::InitFaceLength( const TopoDS_Face& aFace, 
-                        gp_Pln               & aPlane,
-                        Handle(Geom_Surface) & aSurface,
-                        AIS_KindOfSurface    & aSurfaceType,
-                        Standard_Real        & anOffset) 
+void AIS::InitFaceLength (const TopoDS_Face& aFace,
+                          gp_Pln               & aPlane,
+                          Handle(Geom_Surface) & aSurface,
+                          AIS_KindOfSurface    & aSurfaceType,
+                          Standard_Real        & anOffset)
 {
   AIS::GetPlaneFromFace( aFace, aPlane, aSurface, aSurfaceType, anOffset );
   
@@ -742,449 +920,321 @@ void AIS::InitFaceLength( const TopoDS_Face& aFace,
 }
 
 //=======================================================================
-//function : ComputeLengthBetweenPlanarFaces
+//function : InitAngleBetweenPlanarFaces
 //purpose  :
 //=======================================================================
-
-void AIS::ComputeLengthBetweenPlanarFaces( const TopoDS_Face &      FirstFace,
-                                           const TopoDS_Face &      SecondFace,
-                                           const gp_Pln &           Plane1,
-                                           const gp_Pln &           Plane2,
-                                           Standard_Real &          Value,
-                                           gp_Pnt &                 FirstAttach,
-                                           gp_Pnt &                 SecondAttach,
-                                           gp_Dir       &           DirAttach,
-                                           const Standard_Boolean   AutomaticPos,
-                                           gp_Pnt &                 Position )
+Standard_Boolean AIS::InitAngleBetweenPlanarFaces (const TopoDS_Face&          theFirstFace,
+                                                   const TopoDS_Face&          theSecondFace,
+                                                   gp_Pnt &                    theCenter,
+                                                   gp_Pnt &                    theFirstAttach,
+                                                   gp_Pnt &                    theSecondAttach,
+                                                   const Standard_Boolean      theIsFirstPointSet)
 {
-  TopExp_Explorer aExp( FirstFace, TopAbs_VERTEX );
-  // case of infinite planes. SMO.
-  if (!aExp.More())
-    FirstAttach = Plane1.Location();
-  else  
-    FirstAttach = BRep_Tool::Pnt( TopoDS::Vertex( aExp.Current() ) );
-  SecondAttach = AIS::ProjectPointOnPlane( FirstAttach, Plane2 );
-
-  Value = FirstAttach.Distance( SecondAttach );
-
-  gp_Dir LengthDir = Plane1.Axis().Direction();
-  /*
-  if (Value > Precision::Confusion())
-    LengthDir = gp_Dir( gp_Vec( FirstAttach, SecondAttach ) );
-    */
-  DirAttach = Plane1.Position().XDirection();
-
-  if (AutomaticPos)
-    Position.SetXYZ((FirstAttach.XYZ() + SecondAttach.XYZ())/2.0e0) ;
-  else // position is given
-    {
-      FirstAttach = AIS::Nearest( FirstFace, Position );
-      SecondAttach = AIS::ProjectPointOnPlane( FirstAttach, Plane2 );
-    }
+  Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (BRep_Tool::Surface (theFirstFace));
+  Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (BRep_Tool::Surface (theSecondFace));
 
-  Quantity_Parameter U, V ;
-  ElSLib::Parameters( Plane2, SecondAttach, U, V );
-  BRepTopAdaptor_FClass2d aClassifier( SecondFace, Precision::Confusion() );
-  TopAbs_State State = aClassifier.Perform( gp_Pnt2d( U, V ), Standard_False );
-  if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
-    {
-      SecondAttach = AIS::Nearest( SecondFace, Position );
-      if (Value > Precision::Confusion())
-        {
-          gp_Vec aVector = gp_Vec( FirstAttach, SecondAttach ) ^ LengthDir;
-          if (aVector.SquareMagnitude() > SquareTolerance)
-            DirAttach = aVector ^ LengthDir;
-        }
-      else
-        {
-          gp_Vec DirVec( FirstAttach, SecondAttach );
-          if (DirVec.SquareMagnitude() > SquareTolerance)
-            DirAttach = gp_Dir( DirVec );
-        }
-    }
-  if (!AutomaticPos)
-    {
-      gp_Pln PlaneOfDim( FirstAttach, DirAttach ^ LengthDir );
-      Position = AIS::ProjectPointOnPlane( Position, PlaneOfDim );
-    }
-}
+  GeomAPI_IntSS aPlaneIntersector (aFirstPlane, aSecondPlane, Precision::Confusion());
 
+  // Fails if two planes haven't only one intersection line.
+  if (!aPlaneIntersector.IsDone())
+  {
+    return Standard_False;
+  }
 
-// Purpose: Return the point from <aFace> wich is the more distant
-//          from <anAxis>
-static gp_Pnt FindFarPoint (const gp_Ax1 &           anAxis,
-                            const TopoDS_Face &      aFace )
-{
-  gp_Pnt ResPnt(0.0,0.0,0.0);
-  Standard_Real MaxDist = 0.e0, curdist2;
-
-  gp_Lin Line (anAxis);
-
-  TopExp_Explorer Explo (aFace, TopAbs_VERTEX);
-
-  if (!Explo.More()) {
-    // Case of infinite planes (no Vertex, no edge)
-    gp_Pln plane;
-    Handle( Geom_Surface ) aSurf;
-    AIS_KindOfSurface KOS;
-    Standard_Real offset;
-    AIS::GetPlaneFromFace (aFace,plane,aSurf,KOS,offset );
-    gp_Pnt aPoint = plane.Location();
-    MaxDist = Line.SquareDistance (aPoint);
-    if (MaxDist <= SquareTolerance)  {
-      MaxDist = 100;
-      gp_Dir DMove = plane.Axis().Direction()^anAxis.Direction();
-      gp_Vec VMove (DMove.XYZ()*100);
-      ResPnt = aPoint.Translated (VMove);
-    }
+  if (aPlaneIntersector.NbLines() != 1)
+  {
+    return Standard_False;
   }
 
-  for (; Explo.More(); Explo.Next())
-    {
-      // CLE
-      // const TopoDS_Vertex & aVertex = TopoDS::Vertex( Explo.Current() );
-      TopoDS_Vertex aVertex = TopoDS::Vertex( Explo.Current() );
-      // ENDCLE
-      gp_Pnt aPoint = BRep_Tool::Pnt( aVertex );
-      curdist2 = Line.SquareDistance( aPoint );
-      if (curdist2 > MaxDist)
-        {
-          MaxDist = curdist2;
-          ResPnt = aPoint;
-        }
-    }
+  // Get intersect line.
+  Handle(Geom_Curve) anIntersectCurve = aPlaneIntersector.Line (1);
+
+  Handle(Geom_Line) anIntersectLine = Handle(Geom_Line)::DownCast (anIntersectCurve);
+
+  if (anIntersectLine.IsNull())
+  {
+    return Standard_False;
+  }
+
+  gp_Lin anIntersectLin = anIntersectLine->Lin();
+
+  gp_Pnt aFirstCenter, aSecondCenter;
+  Standard_Real anU1Min, anU1Max, aV1Min, aV1Max;
+  Standard_Real anU2Min, anU2Max, aV2Min, aV2Max;
 
-  if (MaxDist <= SquareTolerance)
+  BRepTools::UVBounds (theFirstFace, anU1Min, anU1Max, aV1Min, aV1Max);
+  BRepTools::UVBounds (theSecondFace, anU2Min, anU2Max, aV2Min, aV2Max);
+
+  // Get first and second attach.
+  if (theIsFirstPointSet)
+  {
+    GeomAPI_ProjectPointOnSurf aProjector (theFirstAttach, aFirstPlane);
+    if (!aProjector.IsDone())
     {
-      const Standard_Integer NodeNumber = 20;
-      Explo.Init( aFace, TopAbs_EDGE );
-      for (; Explo.More(); Explo.Next())
-        {
-         // CLE
-          // const TopoDS_Edge & anEdge = TopoDS::Edge( Explo.Current() );
-         TopoDS_Edge anEdge = TopoDS::Edge( Explo.Current() );
-         // ENDCLE
-          BRepAdaptor_Curve aCurve( anEdge );
-          Standard_Real FirstPar = aCurve.FirstParameter();
-          Standard_Real LastPar = aCurve.LastParameter();
-          Standard_Real Delta = (LastPar - FirstPar) / (NodeNumber - 1);
-          for (Standard_Integer i = 0; i < NodeNumber; i++)
-            {
-              gp_Pnt aPoint(0.0,0.0,0.0);
-              aCurve.D0( FirstPar, aPoint );
-              curdist2 = Line.SquareDistance( aPoint );
-              if (curdist2 > MaxDist)
-                {
-                  MaxDist = curdist2;
-                  ResPnt = aPoint;
-                }
-              FirstPar += Delta;
-            }
-          if (MaxDist > SquareTolerance) break;
-        }
+      return Standard_False;
     }
-  if (MaxDist <= SquareTolerance)
-    Standard_ConstructionError::Raise("AIS:: problem attach point") ;
-  return ResPnt;
-}
 
-void AIS::ComputeAngleBetweenPlanarFaces( const TopoDS_Face &      FirstFace,
-                                          const TopoDS_Face &      SecondFace,
-                                          const Handle( Geom_Surface )& Surf2,
-                                          const gp_Ax1 &           Axis,
-                                          const Standard_Real      Value,
-                                          const Standard_Boolean   AutomaticPos,
-                                          gp_Pnt &                 Position,
-                                          gp_Pnt &                 Center,
-                                          gp_Pnt &                 FirstAttach,
-                                          gp_Pnt &                 SecondAttach,
-                                          gp_Dir &                 FirstDir,
-                                          gp_Dir &                 SecondDir )
-{
-  FirstAttach = FindFarPoint( Axis, FirstFace );
-  Center = AIS::ProjectPointOnLine( FirstAttach, gp_Lin( Axis ) );
-  gp_Dir aDir1( gp_Vec( Center, FirstAttach ) );
-  FirstDir = aDir1;
-  SecondAttach = FirstAttach.Rotated( Axis, Value );
-  gp_Dir aDir2( gp_Vec( Center, SecondAttach ) );
-  SecondDir = aDir2;
-
-  GeomAPI_ProjectPointOnSurf   aProjPnt( SecondAttach,
-                                         Surf2 ) ;
-  //SecondAttach = aProjPnt.Point(1) ;
-  Quantity_Parameter U,V ;
-  aProjPnt.Parameters(1,U,V) ;
-  BRepTopAdaptor_FClass2d aClassifier(SecondFace,
-                                      Precision::Confusion());
-  if (aClassifier.Perform(gp_Pnt2d(U,V),Standard_False) == TopAbs_OUT ||
-      aClassifier.Perform(gp_Pnt2d(U,V),Standard_False) == TopAbs_UNKNOWN)
-    SecondAttach = FindFarPoint( Axis, SecondFace );
-
-  if (AutomaticPos)
-    Position = FirstAttach.Rotated( Axis, Value*0.5 );
+    aFirstCenter = aProjector.Point (1);
+  }
   else
-    {
-      gp_Pln PlaneOfDim( Center, Axis.Direction() );
-      Position = AIS::ProjectPointOnPlane( Position, PlaneOfDim );
-    }
+  {
+    aFirstCenter = aFirstPlane->Value ((anU1Min + anU1Max) * 0.5, (aV1Min + aV1Max) * 0.5);
+  }
+
+  aSecondCenter = aSecondPlane->Value ((anU2Min + anU2Max) * 0.5, (aV2Min + aV2Max) * 0.5);
+
+  GeomAPI_ProjectPointOnCurve aProj (aFirstCenter, anIntersectCurve);
+  theCenter = aProj.NearestPoint();
+
+  gp_Vec aFirstNormal = anIntersectLin.Direction() ^ aFirstPlane->Pln().Axis().Direction();
+  if (aFirstNormal * gp_Vec (theCenter, aFirstCenter) < 0.0)
+  {
+    aFirstNormal.Reverse();
+  }
+  theFirstAttach = theCenter.Translated (aFirstNormal);
+
+  gp_Vec aSecondNormal = anIntersectLin.Direction() ^ aSecondPlane->Pln().Axis().Direction();
+  if (aSecondNormal * gp_Vec (theCenter, aSecondCenter) < 0.0)
+  {
+    aSecondNormal.Reverse();
+  }
+  theSecondAttach = theCenter.Translated (aSecondNormal);
+
+  return Standard_True;
 }
-                                     
-                                     
-void AIS::ComputeAngleBetweenCurvilinearFaces( const TopoDS_Face &      FirstFace,
-                                               const TopoDS_Face &      SecondFace,
-                                               const Handle( Geom_Surface )& FirstSurf,
-                                               const Handle( Geom_Surface )& SecondSurf,
-                                               const AIS_KindOfSurface  FirstSurfType,
-                                               const AIS_KindOfSurface  SecondSurfType,
-                                               const gp_Ax1 &           Axis,
-                                               const Standard_Real      Value,
-                                               const Standard_Boolean   AutomaticPos,
-                                               gp_Pnt &                 Position,
-                                               gp_Pnt &                 Center,
-                                               gp_Pnt &                 FirstAttach,
-                                               gp_Pnt &                 SecondAttach,
-                                               gp_Dir &                 FirstDir,
-                                               gp_Dir &                 SecondDir,
-                                               Handle( Geom_Plane ) &   Plane )
+
+//=======================================================================
+//function : InitAngleBetweenCurvilinearFaces
+//purpose  :
+//=======================================================================
+Standard_Boolean AIS::InitAngleBetweenCurvilinearFaces (const TopoDS_Face&          theFirstFace,
+                                                        const TopoDS_Face&          theSecondFace,
+                                                        const AIS_KindOfSurface     theFirstSurfType,
+                                                        const AIS_KindOfSurface     theSecondSurfType,
+                                                        gp_Pnt&                     theCenter,
+                                                        gp_Pnt&                     theFirstAttach,
+                                                        gp_Pnt&                     theSecondAttach,
+                                                        const Standard_Boolean      theIsFirstPointSet)
 {
-  //
-  // even if it is not AutomaticPosition do not assume the Automatic
-  // case has saved the values in the AIS_AngleDimension class : this
-  // is not always the case
-  //
-  gp_Pnt SavedPosition = Position ;
-  FirstAttach = FindFarPoint( Axis, FirstFace );
-  Plane = new Geom_Plane( Axis.Location(),
-                          gp_Dir( gp_Vec( Axis.Location(), FirstAttach ) ^
-                                  gp_Vec( Axis.Direction() ) ) );
-  
-  Handle( Geom_Line ) FirstLine, SecondLine;
-  Standard_Real FirstU, FirstV;
-  if (FirstSurfType == AIS_KOS_Cylinder)
-    ElSLib::Parameters( Handle( Geom_CylindricalSurface )::DownCast( FirstSurf )->Cylinder(),
-                        FirstAttach,
-                        FirstU, FirstV );
-  else // it is Cone
-    ElSLib::Parameters( Handle( Geom_ConicalSurface )::DownCast( FirstSurf )->Cone(),
-                        FirstAttach,
-                        FirstU, FirstV );
-  FirstLine = Handle( Geom_Line )::DownCast( FirstSurf->UIso( FirstU ) );
-  
-  if (SecondSurfType == AIS_KOS_Cylinder)
-    {
-      Handle( Geom_CylindricalSurface ) Cylinder2 =
-        Handle( Geom_CylindricalSurface )::DownCast( SecondSurf );
-      Standard_Real SecondU = Cylinder2->Cylinder().XAxis().Direction().Angle(
-                                                                              gp_Dir( gp_Vec( ProjectPointOnLine( FirstAttach, gp_Lin( Cylinder2->Cylinder().Axis() ) ),
-                                                                                              FirstAttach ) ) );
-      
-      SecondLine = Handle( Geom_Line )::DownCast( Cylinder2->UIso( SecondU ) );
-    }
-  
-  else // it is Cone
+  Handle(Geom_Surface) aFirstSurf = BRep_Tool::Surface (theFirstFace);
+  Handle(Geom_Surface) aSecondSurf = BRep_Tool::Surface (theSecondFace);
+
+  // Find intersection curve between two surfaces.
+  GeomAPI_IntSS aSurfaceIntersector (aFirstSurf, aSecondSurf, Precision::Confusion());
+
+  // Fails if two planes haven't only one intersection line.
+  if (!aSurfaceIntersector.IsDone())
+  {
+    return Standard_False;
+  }
+
+  if (aSurfaceIntersector.NbLines() != 1)
+  {
+    return Standard_False;
+  }
+
+  // Get intersect line.
+  Handle(Geom_Curve) anIntersectCurve = aSurfaceIntersector.Line (1);
+
+  Handle(Geom_Line) aFirstLine, aSecondLine;
+  Standard_Real aFirstU = 0.0;
+  Standard_Real aFirstV = 0.0;
+
+  if (theIsFirstPointSet)
+  {
+    GeomAPI_ProjectPointOnSurf aProjector (theFirstAttach, aFirstSurf);
+    if (!aProjector.IsDone())
     {
-      Handle( Geom_ConicalSurface ) Cone2 = Handle( Geom_ConicalSurface )::DownCast( SecondSurf );
-      gp_Dir Xdirection = Cone2->Cone().XAxis().Direction() ;
-      gp_Dir ToFirstAttach = gp_Dir( gp_Vec(
-                                            ProjectPointOnLine( FirstAttach, gp_Lin( Cone2->Cone().Axis() )),
-                                            FirstAttach ) );
-      
-      Standard_Real SecondU = Xdirection.Angle( ToFirstAttach );
-      // check sign
-      if (! Xdirection.IsEqual( ToFirstAttach, Precision::Angular() ) &&
-          ! Xdirection.IsOpposite( ToFirstAttach, Precision::Angular() ) &&
-          (Xdirection ^ ToFirstAttach) * Cone2->Cone().Axis().Direction() < 0.0e0)
-        SecondU = 2*M_PI - SecondU ;
-      
-      SecondLine = Handle( Geom_Line )::DownCast( Cone2->UIso( SecondU ) );
-      
+      return Standard_False;
     }
-  if (! (FirstLine->Lin().Direction().IsEqual( SecondLine->Lin().Direction(), Precision::Angular() )) &&
-      ! (FirstLine->Lin().Direction().IsOpposite( SecondLine->Lin().Direction(), Precision::Angular() )))
-    {
-      GeomAPI_ExtremaCurveCurve Intersection( FirstLine, SecondLine );
-      Intersection.Points( 1, Center, Center );
-      
-      if (Center.SquareDistance( FirstAttach ) <= SquareTolerance)
-        {
-          FirstAttach = AIS::Farest( FirstFace, Center );
-          Standard_Real U, V;
-          if (FirstSurfType == AIS_KOS_Cylinder)
-            {
-              ElSLib::Parameters ( (Handle( Geom_CylindricalSurface )::DownCast( FirstSurf ))->Cylinder(),
-                                   FirstAttach,
-                                   U, V );
-              FirstAttach = ElSLib::Value( FirstU, V,
-                                           (Handle( Geom_CylindricalSurface )::DownCast( FirstSurf ))
-                                           ->Cylinder() );
-            }
-          else // it is Cone
-            {
-              ElSLib::Parameters ( (Handle( Geom_ConicalSurface )::DownCast( FirstSurf ))->Cone(),
-                                   FirstAttach,
-                                   U, V );
-              FirstAttach = ElSLib::Value( FirstU, V,
-                                           (Handle( Geom_ConicalSurface )::DownCast( FirstSurf ))
-                                           ->Cone() );
-            }
-        }
-      gp_Vec FirstVec( Center, FirstAttach );
-      FirstDir = gp_Dir( FirstVec );
-      
-      gp_Ax1 AxisOfRotation( Center, Plane->Pln().Axis().Direction() );
-      SecondAttach = FirstAttach.Rotated( AxisOfRotation, Value );
-      if (! SecondLine->Lin().Contains( SecondAttach, Precision::Confusion() ))
-        {
-          AxisOfRotation.Reverse();
-          SecondAttach = FirstAttach.Rotated( AxisOfRotation, Value );
-        }
-      
-      Position = FirstAttach.Rotated( AxisOfRotation, Value/2 );
 
-      gp_Vec SecondVec( Center, SecondAttach );
-      SecondDir = gp_Dir( SecondVec );
-      
-    }
-  else // FirstLine and SecondLine are coincident
+    theFirstAttach = aProjector.Point (1);
+  }
+  else
+  {
+    theFirstAttach = aFirstSurf->Value (aFirstU, aFirstV);
+  }
+
+  aFirstLine = Handle(Geom_Line)::DownCast (aFirstSurf->UIso (aFirstU));
+
+  if (theSecondSurfType == AIS_KOS_Cylinder)
+  {
+    Handle(Geom_CylindricalSurface) aCylinder = Handle(Geom_CylindricalSurface)::DownCast (aSecondSurf);
+
+    Standard_Real aSecondU = aCylinder->Cylinder().XAxis().Direction().Angle(
+                               gce_MakeDir (ProjectPointOnLine (theFirstAttach,
+                                                                gp_Lin (aCylinder->Cylinder().Axis())),
+                                            theFirstAttach));
+
+    aSecondLine = Handle(Geom_Line)::DownCast (aCylinder->UIso (aSecondU));
+  }
+  else if (theSecondSurfType == AIS_KOS_Cone)
+  {
+    Handle(Geom_ConicalSurface) aCone = Handle(Geom_ConicalSurface)::DownCast (aSecondSurf);
+
+    gp_Dir anXdirection = aCone->Cone().XAxis().Direction();
+
+    gp_Dir aToFirstAttach = gce_MakeDir (ProjectPointOnLine (theFirstAttach,
+                                                             gp_Lin (aCone->Cone().Axis())),
+                                         theFirstAttach);
+
+    Standard_Real aSecondU = anXdirection.Angle (aToFirstAttach);
+
+    // Check sign
+    if (!anXdirection.IsEqual (aToFirstAttach, Precision::Angular()) &&
+        !anXdirection.IsOpposite (aToFirstAttach, Precision::Angular()) &&
+        (anXdirection ^ aToFirstAttach) * aCone->Cone().Axis().Direction() < 0.0)
     {
-      Position = SecondAttach = FirstAttach;
-      FirstDir = FirstLine->Lin().Direction();
-      SecondDir = FirstDir;
-      Center = Position.Translated( gp_Vec( -FirstDir ) );
-      //Position.Translate( gp_Vec( FirstDir ) );
+      aSecondU = 2*M_PI - aSecondU;
     }
-  
-  GeomAPI_ProjectPointOnSurf   aProjPnt( SecondAttach, SecondSurf ) ;
-  Quantity_Parameter U, V;
-  aProjPnt.LowerDistanceParameters( U, V ) ;
-  BRepTopAdaptor_FClass2d aClassifier2( SecondFace, Precision::Confusion());
-  TopAbs_State State = aClassifier2.Perform( gp_Pnt2d( U, V ), Standard_True );
-  if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
+    aSecondLine = Handle( Geom_Line )::DownCast (aCone->UIso(aSecondU));
+  }
+  else
+  {
+    return Standard_False;
+  }
+
+  // If angle can be computed between two lines.
+  if (!(aFirstLine->Lin().Direction().IsEqual (aSecondLine->Lin().Direction(), Precision::Angular() )) &&
+      !(aFirstLine->Lin().Direction().IsOpposite (aSecondLine->Lin().Direction(), Precision::Angular())))
+  {
+    GeomAPI_ExtremaCurveCurve anIntersector (aFirstLine, aSecondLine);
+    anIntersector.Points (1, theCenter, theCenter);
+
+    // Move theFirstAttach on aFirstLine if it is on theCenter.
+    if (theCenter.SquareDistance(theFirstAttach ) <= SquareTolerance)
     {
-      Standard_Real MinDist2 = RealLast();
-      Standard_Real curdist2;
-      gp_Pnt curpnt(0.0,0.0,0.0);
-      gp_Pnt Result(0.0,0.0,0.0);
-      TopExp_Explorer Explo( SecondFace, TopAbs_VERTEX );
-      for (; Explo.More(); Explo.Next())
-        {
-          curpnt = BRep_Tool::Pnt( TopoDS::Vertex( Explo.Current() ) );
-          curdist2 = SecondAttach.SquareDistance( curpnt ) ;
-          if (curpnt.SquareDistance( Center ) > SquareTolerance && curdist2 < MinDist2)
-            {
-              Result = curpnt;
-              MinDist2 = curdist2;
-            }
-        }
-      SecondAttach = Result;
+      gp_Vec aDir (aFirstLine->Lin().Direction());
+      theFirstAttach = theCenter.Translated (aDir);
+
+      // theFirstAttach should be on theFirstSurf.
+      Standard_Real anU, aV;
+      if (theFirstSurfType == AIS_KOS_Cylinder)
+      {
+        ElSLib::Parameters ((Handle(Geom_CylindricalSurface)::DownCast (aFirstSurf))->Cylinder(),
+                            theFirstAttach, anU, aV);
+
+        theFirstAttach = ElSLib::Value (aFirstU, aV,
+                                        (Handle( Geom_CylindricalSurface )::DownCast (aFirstSurf))->Cylinder() );
+      }
+      else if (theFirstSurfType == AIS_KOS_Cone)
+      {
+        ElSLib::Parameters ((Handle(Geom_ConicalSurface)::DownCast (aFirstSurf))->Cone(),
+                             theFirstAttach, anU, aV);
+        theFirstAttach = ElSLib::Value (aFirstU, aV,
+                                       (Handle(Geom_ConicalSurface)::DownCast (aFirstSurf))->Cone());
+      }
+      else
+      {
+        return Standard_False;
+      }
     }
 
-  if (! AutomaticPos)
-    {  // protection in case this is created using the manual position
-      
-      
-      Position = AIS::ProjectPointOnPlane( SavedPosition, Plane->Pln() );
+    // Find theSecondAttach
+    GeomAPI_ProjectPointOnSurf aProjector (theFirstAttach, aSecondSurf);
+    if (!aProjector.IsDone())
+    {
+      return Standard_False;
     }
+    Quantity_Parameter anU, aV;
+    aProjector.LowerDistanceParameters (anU, aV);
+    theSecondAttach = aSecondSurf->Value (anU, aV);
+  }
+  else // aFirstLine and aSecondLine are coincident
+  {
+      gp_Vec aDir (aFirstLine->Lin().Direction());
+      theFirstAttach = theCenter.Translated (aDir);
+      theSecondAttach = theCenter.Translated (-aDir);
+  }
+  return Standard_True;
 }
 
-
-void AIS::ComputeLengthBetweenCurvilinearFaces( const TopoDS_Face &      FirstFace,
-                                                const TopoDS_Face &      SecondFace,
-                                                Handle( Geom_Surface )&  FirstSurf,
-                                                Handle( Geom_Surface )&  SecondSurf,
-                                                const Standard_Boolean   AutomaticPos,
-                                                Standard_Real &          Value,
-                                                gp_Pnt &                 Position,
-                                                gp_Pnt &                 FirstAttach,
-                                                gp_Pnt &                 SecondAttach,
-                                                gp_Dir &                 DirAttach )
+//=======================================================================
+//function : ComputeLengthBetweenCurvilinearFaces
+//purpose  : 
+//=======================================================================
+void AIS::InitLengthBetweenCurvilinearFaces (const TopoDS_Face&    theFirstFace,
+                                             const TopoDS_Face&    theSecondFace,
+                                             Handle(Geom_Surface)& theFirstSurf,
+                                             Handle(Geom_Surface)& theSecondSurf,
+                                             gp_Pnt&               theFirstAttach,
+                                             gp_Pnt&               theSecondAttach,
+                                             gp_Dir&               theDirOnPlane)
 {
   GeomAPI_ProjectPointOnSurf aProjector;
-  Quantity_Parameter U, V;
-  TopAbs_State State = TopAbs_UNKNOWN;
-  if (AutomaticPos)
-    {
-      TopExp_Explorer Explo( FirstFace, TopAbs_VERTEX );
-      FirstAttach = BRep_Tool::Pnt( TopoDS::Vertex( Explo.Current() ) );
-      aProjector.Init(FirstAttach , FirstSurf );
-      FirstAttach = aProjector.NearestPoint();
-      aProjector.LowerDistanceParameters( U, V );
-    }
-  else // posiiton is given
-    {
-      aProjector.Init( Position, FirstSurf );
-      FirstAttach = aProjector.NearestPoint();
-
-      aProjector.LowerDistanceParameters( U, V );
-      BRepTopAdaptor_FClass2d aClassifier( FirstFace, Precision::Confusion() );
-      State = aClassifier.Perform( gp_Pnt2d( U, V ), ( (FirstSurf->IsUPeriodic() || FirstSurf->IsVPeriodic())?
-                                                       Standard_True
-                                                       : Standard_False ) );
-      if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
-        {
-          FirstAttach = AIS::Nearest( FirstFace, Position );
-          aProjector.Init( FirstAttach, FirstSurf );
-          aProjector.LowerDistanceParameters( U, V );
-        }
-    }
+  Quantity_Parameter aPU, aPV;
+
+  TopExp_Explorer anExplorer (theFirstFace, TopAbs_VERTEX);
+
+  theFirstAttach = BRep_Tool::Pnt (TopoDS::Vertex (anExplorer.Current()));
+  aProjector.Init (theFirstAttach, theFirstSurf);
+
+  theFirstAttach = aProjector.NearestPoint();
+  aProjector.LowerDistanceParameters (aPU, aPV);
+
+  gp_Vec aD1U, aD1V;
+  theFirstSurf->D1 (aPU, aPV, theFirstAttach, aD1U, aD1V);
 
-  gp_Vec D1U, D1V;
-  FirstSurf->D1( U, V, FirstAttach, D1U, D1V );
-  if (D1U.SquareMagnitude() <= SquareTolerance || D1V.SquareMagnitude() <= SquareTolerance)
+  if (aD1U.SquareMagnitude() <= SquareTolerance || aD1V.SquareMagnitude() <= SquareTolerance)
+  {
+    theFirstAttach = AIS::Farest (theFirstFace, theFirstAttach);
+    aProjector.Init (theFirstAttach, theFirstSurf);
+    aProjector.LowerDistanceParameters (aPU, aPV);
+    theFirstSurf->D1 (aPU, aPV, theFirstAttach, aD1U, aD1V);
+  }
+
+  aD1U.Normalize();
+  aD1V.Normalize();
+
+  theDirOnPlane = gp_Dir (aD1U);
+
+  gp_Dir aFirstSurfN = gp_Dir (aD1U ^ aD1V);
+
+  aProjector.Init (theFirstAttach, theSecondSurf);
+
+  Standard_Integer aBestPointIndex = 0;
+  Quantity_Length aMinDist = RealLast();
+  gp_Dir aLocalDir;
+
+  for (Standard_Integer aPointIt = 1; aPointIt <= aProjector.NbPoints(); aPointIt++)
+  {
+    aProjector.Parameters (aPointIt, aPU, aPV);
+
+    theSecondSurf->D1 (aPU, aPV, theSecondAttach, aD1U, aD1V);
+
+    aLocalDir = aD1U.SquareMagnitude() <= SquareTolerance || aD1V.SquareMagnitude() <= SquareTolerance
+              ? gp_Dir (gp_Vec (theFirstAttach, aProjector.Point (aPointIt)))
+              : gp_Dir (aD1U ^ aD1V);
+
+    if (aFirstSurfN.IsParallel (aLocalDir, Precision::Angular()) && aProjector.Distance (aPointIt) < aMinDist)
     {
-      FirstAttach = AIS::Farest( FirstFace, FirstAttach );
-      aProjector.Init( FirstAttach, FirstSurf );
-      aProjector.LowerDistanceParameters( U, V );
-      FirstSurf->D1( U, V, FirstAttach, D1U, D1V );
+      aBestPointIndex = aPointIt;
+      aMinDist = aProjector.Distance (aPointIt);
     }
-  D1U.Normalize();
-  D1V.Normalize();
-  DirAttach = gp_Dir( D1U ^ D1V );
-
-  aProjector.Init( FirstAttach, SecondSurf );
-  Standard_Integer Index = 0;
-  Quantity_Length MinDist = RealLast();
-  gp_Dir LocalDir;
-  for (Standard_Integer i = 1; i <= aProjector.NbPoints(); i++)
-    {
-      aProjector.Parameters( i, U, V );
+  }
 
-      SecondSurf->D1( U, V, SecondAttach, D1U, D1V );
-      if (D1U.SquareMagnitude() <= SquareTolerance || D1V.SquareMagnitude() <= SquareTolerance)
-        LocalDir = gp_Dir( gp_Vec( FirstAttach, aProjector.Point( i ) ) );
-      else
-        LocalDir = gp_Dir( D1U ^ D1V );
-      if (DirAttach.IsParallel( LocalDir, Precision::Angular() ) && aProjector.Distance( i ) < MinDist)
-        {
-          Index = i;
-          MinDist = aProjector.Distance( i );
-        }
+  if (aBestPointIndex == 0)
+  {
+    theSecondAttach = theFirstAttach;
+  }
+  else
+  {
+    theSecondAttach = aProjector.Point (aBestPointIndex);
+    aProjector.Parameters (aBestPointIndex, aPU, aPV);
+
+    // Now there is projection of FirstAttach onto SecondSurf in aProjector
+    BRepTopAdaptor_FClass2d aClassifier (theSecondFace, Precision::Confusion());
+
+    TopAbs_State aState = 
+      aClassifier.Perform (gp_Pnt2d (aPU, aPV), theSecondSurf->IsUPeriodic() || theSecondSurf->IsVPeriodic());
+
+    if (aState == TopAbs_OUT || aState == TopAbs_UNKNOWN)
+    {
+      theSecondAttach = AIS::Nearest (theSecondFace, theSecondAttach);
     }
-if (Index == 0)  { 
-  SecondAttach = FirstAttach;
-} else {
-  SecondAttach = aProjector.Point( Index );
-  aProjector.Parameters( Index, U, V );
-
-  Value = FirstAttach.Distance( SecondAttach );
-  if (Value > Precision::Confusion())
-    DirAttach = gp_Dir( gp_Vec( FirstAttach, SecondAttach ) );
-
-  if (AutomaticPos)
-    Position.SetXYZ( (FirstAttach.XYZ() + SecondAttach.XYZ()) / 2 );
-  else if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
-    Position = AIS::ProjectPointOnLine( Position, gp_Lin( FirstAttach, DirAttach ) );
-
-  // Now there is projection of FirstAttach onto SecondSurf in aProjector
-  BRepTopAdaptor_FClass2d aClassifier( SecondFace, Precision::Confusion() );
-  State = aClassifier.Perform( gp_Pnt2d( U, V ), ( (SecondSurf->IsUPeriodic() || SecondSurf->IsVPeriodic())?
-                                                   Standard_True
-                                                   : Standard_False ) );
-  if (State == TopAbs_OUT || State == TopAbs_UNKNOWN)
-    SecondAttach = AIS::Nearest( SecondFace, SecondAttach );
-}
+  }
 }
+
 gp_Pnt AIS::TranslatePointToBound( const gp_Pnt & aPoint, const gp_Dir & aDir, const Bnd_Box & aBndBox )
 {
   if (aBndBox.IsOut( aPoint ))
index c18b5f4..a274ef4 100755 (executable)
 #include <BRepBuilderAPI_MakeFace.hxx>
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Surface.hxx>
+#include <BRepLib_MakeVertex.hxx>
+#include <BRep_Tool.hxx>
 #include <ElCLib.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_MakeCirc.hxx>
 #include <gce_MakeDir.hxx>
-#include <GC_MakeArcOfCircle.hxx>
-#include <GCPnts_UniformAbscissa.hxx>
-#include <Geom_TrimmedCurve.hxx>
 #include <Geom_Circle.hxx>
+#include <Geom_TrimmedCurve.hxx>
 #include <Geom_ConicalSurface.hxx>
 #include <Geom_SurfaceOfRevolution.hxx>
 #include <Geom_OffsetSurface.hxx>
 #include <Graphic3d_Group.hxx>
 #include <Graphic3d_ArrayOfPolylines.hxx>
 #include <IntAna2d_AnaIntersection.hxx>
-#include <IntAna2d_IntPoint.hxx>
-#include <IntAna_ResultType.hxx>
 #include <ProjLib.hxx>
 #include <Prs3d_Root.hxx>
 #include <Prs3d_ShadingAspect.hxx>
 #include <PrsMgr_PresentationManager3d.hxx>
-#include <Select3D_SensitiveCurve.hxx>
 #include <Select3D_SensitiveGroup.hxx>
 #include <Select3D_SensitiveSegment.hxx>
 #include <SelectMgr_Selection.hxx>
@@ -66,538 +66,382 @@ namespace
 };
 
 //=======================================================================
-//function : init
-//purpose  : Private constructor for default initialization
-//=======================================================================
-void AIS_AngleDimension::init()
-{
-  // Default values of units
-  UnitsAPI::SetLocalSystem (UnitsAPI_SI);
-  SetUnitsQuantity ("PLANE ANGLE");
-  SetModelUnits ("rad");
-  SetDisplayUnits ("deg");
-  SetSpecialSymbol (THE_DEGREE_SYMBOL);
-  SetDisplaySpecialSymbol (AIS_DSS_After);
-  SetFlyout (15.0);
-  SetKindOfDimension (AIS_KOD_PLANEANGLE);
-  MakeUnitsDisplayed (Standard_False);
-}
-
-//=======================================================================
 //function : Constructor
-//purpose  : Two edges dimension
+//purpose  : 
 //=======================================================================
 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
                                         const TopoDS_Edge& theSecondEdge)
-: AIS_Dimension(),
-  myIsFlyoutLines (Standard_True)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-  init();
-  myShapesNumber = 2;
-  myFirstShape   = theFirstEdge;
-  mySecondShape  = theSecondEdge;
+  Init();
+  SetMeasuredGeometry (theFirstEdge, theSecondEdge);
 }
 
 //=======================================================================
 //function : Constructor
-//purpose  : Two edges dimension
-//           <thePlane> is used in case of Angle=PI
+//purpose  : 
 //=======================================================================
-AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
-                                        const TopoDS_Edge& theSecondEdge,
-                                        const gp_Pln& thePlane)
-: AIS_Dimension(),
-  myIsFlyoutLines (Standard_True)
+AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
+                                        const gp_Pnt& theSecondPoint,
+                                        const gp_Pnt& theThirdPoint)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-  init();
-  myShapesNumber = 2;
-  myFirstShape   = theFirstEdge;
-  mySecondShape  = theSecondEdge;
-  SetWorkingPlane (thePlane);
+  Init();
+  SetMeasuredGeometry (theFirstPoint, theSecondPoint, theThirdPoint);
 }
 
 //=======================================================================
 //function : Constructor
-//purpose  : Three points dimension
+//purpose  : 
 //=======================================================================
-AIS_AngleDimension::AIS_AngleDimension (const gp_Pnt& theFirstPoint,
-                                        const gp_Pnt& theSecondPoint,
-                                        const gp_Pnt& theThirdPoint)
-: AIS_Dimension(),
-  myIsFlyoutLines (Standard_True)
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Vertex& theFirstVertex,
+                                        const TopoDS_Vertex& theSecondVertex,
+                                        const TopoDS_Vertex& theThirdVertex)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-  init();
-  myIsInitialized = Standard_True;
-  myFirstPoint    = theFirstPoint;
-  myCenter        = theSecondPoint;
-  mySecondPoint   = theThirdPoint;
-  myShapesNumber  = 3;
+  Init();
+  SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex);
 }
 
 //=======================================================================
 //function : Constructor
-//purpose  : Cone dimension
+//purpose  : 
 //=======================================================================
 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theCone)
-: AIS_Dimension(),
-  myIsFlyoutLines (Standard_True)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-  init();
-  myIsInitialized = Standard_False;
-  myFirstShape    = theCone;
-  myShapesNumber  = 1;
+  Init();
+  SetMeasuredGeometry (theCone);
 }
 
 //=======================================================================
 //function : Constructor
-//purpose  : Two faces dimension
+//purpose  : 
 //=======================================================================
 AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
-                                        const TopoDS_Face& theSecondFace,
-                                        const gp_Ax1& theAxis)
-: AIS_Dimension(),
-  myIsFlyoutLines (Standard_True)
+                                        const TopoDS_Face& theSecondFace)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-  init();
-  myIsInitialized = Standard_False;
-  myFirstShape    = theFirstFace;
-  mySecondShape   = theSecondFace;
-  myShapesNumber  = 2;
-  gp_Pln aPlane;
-  aPlane.SetAxis (theAxis);
-  SetWorkingPlane (aPlane);
+  Init();
+  SetMeasuredGeometry (theFirstFace, theSecondFace);
 }
 
 //=======================================================================
-//function : SetFirstShape
+//function : Constructor
 //purpose  : 
 //=======================================================================
-void AIS_AngleDimension::SetFirstShape (const TopoDS_Shape& theShape,
-                                        const Standard_Boolean isSingleShape /*= Standard_False*/)
+AIS_AngleDimension::AIS_AngleDimension (const TopoDS_Face& theFirstFace,
+                                        const TopoDS_Face& theSecondFace,
+                                        const gp_Pnt& thePoint)
+: AIS_Dimension (AIS_KOD_PLANEANGLE)
 {
-  AIS_Dimension::SetFirstShape (theShape);
-  if (isSingleShape)
-    myShapesNumber = 1;
+  Init();
+  SetMeasuredGeometry (theFirstFace, theSecondFace, thePoint);
 }
 
 //=======================================================================
-//function : aboveInBelowCone
-//purpose  : Returns 1 if <theC> center is above of <theCMin> center;
-//                   0 if <theC> center is between <theCMin> and
-//                        <theCMax> centers;
-//                  -1 if <theC> center is below <theCMax> center.
+//function : SetMeasuredGeometry
+//purpose  : 
 //=======================================================================
-Standard_Integer AIS_AngleDimension::aboveInBelowCone (const gp_Circ &theCMax,
-                                                       const gp_Circ &theCMin,
-                                                       const gp_Circ &theC)
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
+                                              const TopoDS_Edge& theSecondEdge)
 {
-  const Standard_Real aD  = theCMax.Location().Distance (theCMin.Location());
-  const Standard_Real aD1 = theCMax.Location().Distance (theC.Location());
-  const Standard_Real aD2 = theCMin.Location().Distance (theC.Location());
-
-  if (aD >= aD1 && aD >= aD2) return  0;
-  if (aD  < aD2 && aD1 < aD2) return -1;
-  if (aD  < aD1 && aD2 < aD1) return  1;
-  return 0;
+  gp_Pln aComputedPlane;
+
+  myFirstShape   = theFirstEdge;
+  mySecondShape  = theSecondEdge;
+  myThirdShape   = TopoDS_Shape();
+  myGeometryType = GeometryType_Edges;
+  myIsValid      = InitTwoEdgesAngle (aComputedPlane);
+
+  if (myIsValid && !myIsPlaneCustom)
+  {
+    myPlane = aComputedPlane;
+  }
+
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : initConeAngle
-//purpose  : initialization of the cone angle
+//function : SetMeasuredGeometry
+//purpose  : 
 //=======================================================================
-Standard_Boolean AIS_AngleDimension::initConeAngle (const TopoDS_Face& theCone)
+void AIS_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
+                                              const gp_Pnt& theSecondPoint,
+                                              const gp_Pnt& theThirdPoint)
 {
-  if (theCone.IsNull ())
-    return Standard_False;
-
-  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 (theCone);
-  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(theCone, aPln, aSurf, aSurfType, anOffset);
+  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 (aSurfType == AIS_KOS_Revolution)
+  if (myIsValid && !myIsPlaneCustom)
   {
-    // 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);
+    ComputePlane();
+  }
 
-    gp_Vec aVec2 (aFirst2, aLast2);
+  myIsValid &= CheckPlane (myPlane);
 
-    // 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;
+  SetToUpdate();
+}
 
-    gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1);
-    aCone =  aMkCone.Value();
-    myCenter = aCone.Apex();
-  }
-  else
+//=======================================================================
+//function : SetMeasuredGeometry
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
+                                              const TopoDS_Vertex& theSecondVertex,
+                                              const TopoDS_Vertex& theThirdVertex)
+{
+  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)
   {
-    aType = aSurf->DynamicType();
-    if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01)
-    {
-      // 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);
-    myCenter =  aConicalSurf->Apex();
+    ComputePlane();
   }
 
-  // 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();
+  myIsValid &= CheckPlane (myPlane);
 
-  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();
+  SetToUpdate();
+}
 
+//=======================================================================
+//function : SetMeasuredGeometry
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone)
+{
+  myFirstShape   = theCone;
+  mySecondShape  = TopoDS_Shape();
+  myThirdShape   = TopoDS_Shape();
+  myGeometryType = GeometryType_Face;
+  myIsValid      = InitConeAngle();
 
-  if (aCircVmax.Radius() < aCircVmin.Radius())
+  if (myIsValid && !myIsPlaneCustom)
   {
-   gp_Circ aTmpCirc = aCircVmax;
-   aCircVmax = aCircVmin;
-   aCircVmin = aTmpCirc;
+    ComputePlane();
   }
 
-  myFirstPoint  = ElCLib::Value (0, aCircle);
-  mySecondPoint = ElCLib::Value (M_PI, aCircle);
-  return Standard_True;
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : initTwoFacesAngle
-//purpose  : initialization of angle dimension between two faces
+//function : SetMeasuredGeometry
+//purpose  : 
 //=======================================================================
-Standard_Boolean AIS_AngleDimension::initTwoFacesAngle ()
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
+                                              const TopoDS_Face& theSecondFace)
 {
-  TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
-  TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
-  gp_Dir aFirstDir, aSecondDir;
-  gp_Pln aFirstPlane, aSecondPlane;
-  gp_Pnt aTextPos;
-  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);
+  myFirstShape   = theFirstFace;
+  mySecondShape  = theSecondFace;
+  myThirdShape   = TopoDS_Shape();
+  myGeometryType = GeometryType_Faces;
+  myIsValid      = InitTwoFacesAngle();
 
-  if (aFirstSurfType == AIS_KOS_Plane)
+  if (myIsValid && !myIsPlaneCustom)
   {
-    //Planar faces angle
-    AIS::ComputeAngleBetweenPlanarFaces (aFirstFace,
-                                        aSecondFace,
-                                        aSecondBasisSurf,
-                                        GetWorkingPlane().Axis(),
-                                        myValue,
-                                        Standard_True,
-                                        aTextPos,
-                                        myCenter,
-                                        myFirstPoint,
-                                        mySecondPoint,
-                                        aFirstDir,
-                                        aSecondDir);
-  }
-  else
-  {
-        // Curvilinear faces angle
-    Handle(Geom_Plane) aPlane = new Geom_Plane (GetWorkingPlane());
-    AIS::ComputeAngleBetweenCurvilinearFaces (aFirstFace,
-                                             aSecondFace,
-                                             aFirstBasisSurf,
-                                             aSecondBasisSurf,
-                                             aFirstSurfType,
-                                             aSecondSurfType,
-                                             GetWorkingPlane().Axis(),
-                                             myValue,
-                                             Standard_True,
-                                             aTextPos,
-                                             myCenter,
-                                             myFirstPoint,
-                                             mySecondPoint,
-                                             aFirstDir,
-                                             aSecondDir,
-                                             aPlane);
-    SetWorkingPlane (aPlane->Pln());
+    ComputePlane();
   }
-  return Standard_True;
+
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : countDefaultPlane
+//function : SetMeasuredGeometry
 //purpose  : 
 //=======================================================================
-void AIS_AngleDimension::countDefaultPlane ()
+void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
+                                              const TopoDS_Face& theSecondFace,
+                                              const gp_Pnt& thePoint)
 {
-  if (!myIsInitialized)
-    return;
-  // Compute normal of the default plane.
-  gp_Vec aVec1(myCenter, myFirstPoint),
-         aVec2(myCenter, mySecondPoint);
-  myDefaultPlane = gp_Pln(myCenter, aVec1^aVec2);
-  // Set computed value to <myWorkingPlane>
-  ResetWorkingPlane ();
+  myFirstShape   = theFirstFace;
+  mySecondShape  = theSecondFace;
+  myThirdShape   = TopoDS_Shape();
+  myGeometryType = GeometryType_Faces;
+  myIsValid      = InitTwoFacesAngle (thePoint);
+
+  if (myIsValid && !myIsPlaneCustom)
+  {
+    ComputePlane();
+  }
+
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : computeValue
+//function : Init
 //purpose  : 
 //=======================================================================
-void AIS_AngleDimension::computeValue ()
+void AIS_AngleDimension::Init()
 {
-  gp_Vec aVec1 (myCenter, myFirstPoint),
-         aVec2 (myCenter, mySecondPoint);
-  myValue = aVec1.Angle (aVec2);
-  // To model units
-  AIS_Dimension::computeValue();
+  SetSpecialSymbol (THE_DEGREE_SYMBOL);
+  SetDisplaySpecialSymbol (AIS_DSS_After);
+  SetFlyout (15.0);
 }
 
 //=======================================================================
-//function : initTwoEdgesAngle
-//purpose  : Fill gp_Pnt fields for further presentation computation
-//           If intersection between two edges doesn't exist
-//           <myIsInitialized> is set to false
+//function: GetCenterOnArc
+//purpose :
 //=======================================================================
-Standard_Boolean AIS_AngleDimension::initTwoEdgesAngle ()
+gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
+                                           const gp_Pnt& theSecondAttach,
+                                           const gp_Pnt& theCenter)
 {
-  // Data initialization
-  TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape);
-  TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
-  BRepAdaptor_Curve aMakeFirstLine (aFirstEdge);
-  BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
-
-  if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
+  // construct plane where the circle and the arc are located
+  gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
+  if (!aConstructPlane.IsDone())
   {
-    return  Standard_False;
+    return gp::Origin();
   }
+  
+  gp_Pln aPlane = aConstructPlane.Value();
 
-  Handle(Geom_Line) aFirstLine  = new Geom_Line (aMakeFirstLine.Line());
-  Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
+  Standard_Real aRadius = theFirstAttach.Distance (theCenter);
 
-  gp_Lin aFirstLin  = aFirstLine->Lin ();
-  gp_Lin aSecondLin = aSecondLine->Lin ();
-  gp_Lin2d aFirstLin2d, aSecondLin2d;
-  Standard_Boolean isParallelLines = aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular());
-  Standard_Boolean isSameLines = isParallelLines && aFirstLin.Distance (aSecondLin.Location()) <= Precision::Confusion();
-  // In case where we can't compute plane automatically
-  if ((isParallelLines || isSameLines) && !myIsWorkingPlaneCustom)
+  // construct circle forming the arc
+  gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
+  if (!aConstructCircle.IsDone())
   {
-    return Standard_False;
+    return gp::Origin();
   }
 
-  gp_Pln aPlane;
+  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);
 
-  /// PART 1 is for automatic plane computation from two edges if it is possible
-  // Build plane
-  if (!myIsWorkingPlaneCustom)
+  return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle);
+}
+
+//=======================================================================
+//function : DrawArc
+//purpose  : draws the arc between two attach points
+//=======================================================================
+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())
   {
-    gp_Pnt aPoint = aFirstLine->Value (0.);
-    gp_Dir aNormal = isParallelLines
-                     ? gp_Vec(aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
-                     : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
-    aPlane = gp_Pln (aPoint, aNormal);
-    resetWorkingPlane (aPlane);
+    return;
   }
-  else
+
+  gp_Pln aPlane = aConstructPlane.Value();
+
+  // construct circle forming the arc
+  gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
+  if (!aConstructCircle.IsDone())
   {
-    aPlane = GetWorkingPlane();
+    return;
   }
 
-  // Compute geometry for this plane and edges
-  Standard_Boolean isInfinite1,isInfinite2;
-  gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2;
-  Standard_Integer anExtIndex = -1;
-  Handle(Geom_Curve) anExtCurve;
-  Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
-  if (!AIS::ComputeGeometry (aFirstEdge, aSecondEdge,
-                             anExtIndex,
-                             aFirstLine, aSecondLine,
-                             aFirstPoint1, aLastPoint1,
-                             aFirstPoint2, aLastPoint2,
-                             anExtCurve,
-                             isInfinite1, isInfinite2,
-                             aGeomPlane))
+  gp_Circ aCircle = aConstructCircle.Value();
+
+  // construct the arc
+  GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True);
+  if (!aConstructArc.IsDone())
   {
-    return Standard_False;
+    return;
   }
 
-  // Check if both edges are on this plane
-  if (!anExtCurve.IsNull())
-  {
-    if (anExtIndex == 1) // First curve is out of the plane
-    {
-      // Project curve on the plane
-      if (myIsWorkingPlaneCustom)
-      {
-        aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
-        aFirstLin = ElCLib::To3d (aPlane.Position().Ax2(), aFirstLin2d);
-      }
-      else
-      {
-        aFirstLin.Translate (gp_Vec (aFirstLin.Location(), aSecondLin.Location()));
-      }
+  // generate points with specified deflection
+  const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value();
+  
+  GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter());
 
-      aFirstLine = new Geom_Line (aFirstLin);
-    }
-    else if (anExtIndex == 2) // Second curve is out of the plane
-    {
-      if (myIsWorkingPlaneCustom)
-      {
-        aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
-        aSecondLin = ElCLib::To3d (aPlane.Position().Ax2(), aSecondLin2d);
-      }
-      else
-      {
-        aSecondLin.Translate (gp_Vec (aSecondLin.Location(), aFirstLin.Location()));
-      }
+  // 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));
 
-      aSecondLine = new Geom_Line (aSecondLin);
-    }
+  GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
+  if (!aMakePnts.IsDone())
+  {
+    return;
   }
 
-  /// PART 2 is for dimension computation using the working plane
+  // init data arrays for graphical and selection primitives
+  Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
 
-  if (aFirstLin.Direction ().IsParallel (aSecondLin.Direction (), Precision::Angular ()))
-  {
-    // Parallel lines
-    isSameLines = aFirstLin.Distance(aSecondLin.Location()) <= Precision::Confusion();
-    if (!isSameLines)
-      return Standard_False;
+  SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
 
-     myFirstPoint = aFirstLin.Location();
-     mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
-     if (mySecondPoint.Distance (mySecondPoint) <= Precision::Confusion ())
-       mySecondPoint.Translate (gp_Vec (aSecondLin.Direction ())*Abs(GetFlyout()));
-     myCenter.SetXYZ( (myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2. );
-  }
-  else
+  // load data into arrays
+  for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
   {
-    // Find intersection
-    aFirstLin2d = ProjLib::Project (aPlane, aFirstLin);
-    aSecondLin2d = ProjLib::Project (aPlane, aSecondLin);
-
-    IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d);
-    gp_Pnt2d anIntersectPoint;
-    if (!anInt2d.IsDone() || anInt2d.IsEmpty())
-    {
-      return Standard_False;
-    }
-
-    anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value());
-    myCenter = ElCLib::To3d(aPlane.Position().Ax2(), anIntersectPoint);
+    gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
 
-    if (isInfinite1 || isInfinite2)
-    {
-      myFirstPoint  = myCenter.Translated (gp_Vec (aFirstLin.Direction())*Abs (GetFlyout()));
-      mySecondPoint = myCenter.Translated (gp_Vec (aSecondLin.Direction())*Abs (GetFlyout()));
-      return Standard_True;
-    }
+    aPrimSegments->AddVertex (aPnt);
 
-    // |
-    // | <- dimension should be here
-    // *----
-    myFirstPoint  = myCenter.Distance (aFirstPoint1) > myCenter.Distance (aLastPoint1) ? aFirstPoint1 : aLastPoint1;
-    mySecondPoint = myCenter.Distance (aFirstPoint2) > myCenter.Distance (aLastPoint2) ? aFirstPoint2 : aLastPoint2;
+    aSensitiveCurve.Append (aPnt);
   }
-  return Standard_True;
-}
 
-//=======================================================================
-//function: getCenterOnArc
-//purpose :
-//=======================================================================
-gp_Pnt AIS_AngleDimension::getCenterOnArc (const gp_Pnt& theFirstAttach,
-                                           const gp_Pnt& theSecondAttach)
-{
-  gp_Pnt2d aCenter2d       = ProjLib::Project (GetWorkingPlane(), myCenter),
-           aFirstAttach2d  = ProjLib::Project (GetWorkingPlane(), theFirstAttach),
-           aSecondAttach2d = ProjLib::Project (GetWorkingPlane(), theSecondAttach);
-  gp_Lin2d anAttachLine2d = gce_MakeLin2d (aFirstAttach2d, aSecondAttach2d);
-
-  // Getting text center
-  gp_Pnt2d aTextCenterPnt = ElCLib::Value ((ElCLib::Parameter (anAttachLine2d, aFirstAttach2d) + ElCLib::Parameter (anAttachLine2d, aSecondAttach2d)) / 2., anAttachLine2d);
-  gp_Lin2d aCenterToTextCenterLin = gce_MakeLin2d (aCenter2d, aTextCenterPnt);
-
-  // Drawing circle
-  Standard_Real aRadius = theFirstAttach.Distance (myCenter);
-  gp_Circ2d aCircle (gp_Ax22d (aCenter2d, gp_Dir2d (1, 0)), aRadius);
-
-  // Getting text position in the center of arc
-  IntAna2d_AnaIntersection anInt2d (aCenterToTextCenterLin, aCircle);
-  gp_Pnt2d aTextCenterOnArc2d;
-  if (anInt2d.IsDone())
-    if (!anInt2d.IsEmpty())
-      aTextCenterOnArc2d = gp_Pnt2d (anInt2d.Point (1).Value());
-  gp_Pnt aCenterOnArc = ElCLib::To3d (GetWorkingPlane().Position().Ax2(), aTextCenterOnArc2d);
-  return aCenterOnArc;
+  // 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: drawArcWithText
+//function: DrawArcWithText
 //purpose :
 //=======================================================================
-void AIS_AngleDimension::drawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
+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)
 {
   // construct plane where the circle and the arc are located
-  gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, myCenter);
+  gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
   if (!aConstructPlane.IsDone())
   {
     return;
   }
-  
+
   gp_Pln aPlane = aConstructPlane.Value();
 
-  Standard_Real aRadius = theFirstAttach.Distance (myCenter);
+  Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint);
 
   // construct circle forming the arc
-  gce_MakeCirc aConstructCircle (myCenter, aPlane, aRadius);
+  gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius);
   if (!aConstructCircle.IsDone())
   {
     return;
@@ -608,9 +452,7 @@ void AIS_AngleDimension::drawArcWithText (const Handle(Prs3d_Presentation)& theP
   // 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 (aParamBeg, aParamEnd,
-                          Precision::PConfusion(),
-                          aParamBeg, aParamEnd);
+  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;
@@ -619,12 +461,10 @@ void AIS_AngleDimension::drawArcWithText (const Handle(Prs3d_Presentation)& theP
   if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
   {
     gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle);
-    gp_Dir aTextDir = IsTextReversed()
-      ? gce_MakeDir (theSecondAttach, theFirstAttach)
-      : gce_MakeDir (theFirstAttach, theSecondAttach);
+    gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach);
 
     // Drawing text
-    drawText (thePresentation,
+    DrawText (thePresentation,
               aTextPos,
               aTextDir,
               theText,
@@ -650,95 +490,104 @@ void AIS_AngleDimension::drawArcWithText (const Handle(Prs3d_Presentation)& theP
     gp_Pnt aTextPntEnd = ElCLib::Value (aParamMid + aSectorOnCircle * 0.5, aCircle);
 
     // Drawing arcs
-    drawArc (thePresentation, theFirstAttach, aTextPntBeg, myCenter, aRadius, theMode);
-    drawArc (thePresentation, theSecondAttach, aTextPntEnd, myCenter, aRadius, theMode);
+    DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode);
+    DrawArc (thePresentation, theSecondAttach, aTextPntEnd, theCenter, aRadius, theMode);
   }
   else
   {
-    drawArc (thePresentation, theFirstAttach, theSecondAttach, myCenter, aRadius, theMode);
+    DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode);
   }
 }
 
 //=======================================================================
-//function : drawArc
-//purpose  : draws the arc between two attach points
+//function : CheckPlane
+//purpose  : 
 //=======================================================================
-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)
+Standard_Boolean AIS_AngleDimension::CheckPlane (const gp_Pln& thePlane)const
 {
-  // construct plane where the circle and the arc are located
-  gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
-  if (!aConstructPlane.IsDone())
+  if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
+      !thePlane.Contains (mySecondPoint, Precision::Confusion()) &&
+      !thePlane.Contains (myCenterPoint, Precision::Confusion()))
   {
-    return;
-  }
-
-  gp_Pln aPlane = aConstructPlane.Value();
-
-  // construct circle forming the arc
-  gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius);
-  if (!aConstructCircle.IsDone())
-  {
-    return;
-  }
-
-  gp_Circ aCircle = aConstructCircle.Value();
-
-  // construct the arc
-  GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True);
-  if (!aConstructArc.IsDone())
-  {
-    return;
+    return Standard_False;
   }
 
-  // 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));
+  return Standard_True;
+}
 
-  GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints);
-  if (!aMakePnts.IsDone())
+//=======================================================================
+//function : ComputePlane
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::ComputePlane()
+{
+  if (!IsValid())
   {
     return;
   }
 
-  // init data arrays for graphical and selection primitives
-  Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints);
+  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();
 
-  SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
+  myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX)));
+}
 
-  // load data into arrays
-  for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt)
-  {
-    gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt));
+//=======================================================================
+//function : GetModelUnits
+//purpose  :
+//=======================================================================
+const TCollection_AsciiString& AIS_AngleDimension::GetModelUnits() const
+{
+  return myDrawer->DimAngleModelUnits();
+}
 
-    aPrimSegments->AddVertex (aPnt);
+//=======================================================================
+//function : GetDisplayUnits
+//purpose  :
+//=======================================================================
+const TCollection_AsciiString& AIS_AngleDimension::GetDisplayUnits() const
+{
+  return myDrawer->DimAngleDisplayUnits();
+}
 
-    aSensitiveCurve.Append (aPnt);
-  }
+//=======================================================================
+//function : SetModelUnits
+//purpose  :
+//=======================================================================
+void AIS_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
+{
+  myDrawer->SetDimAngleModelUnits (theUnits);
+}
 
-  // 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)
+//=======================================================================
+//function : SetDisplayUnits
+//purpose  :
+//=======================================================================
+void AIS_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
+{
+  myDrawer->SetDimAngleDisplayUnits (theUnits);
+}
+
+//=======================================================================
+//function : ComputeValue
+//purpose  : 
+//=======================================================================
+Standard_Real AIS_AngleDimension::ComputeValue() const
+{
+  if (!IsValid())
   {
-    Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False);
+    return 0.0;
   }
+
+  gp_Vec aVec1 (myCenterPoint, myFirstPoint);
+  gp_Vec aVec2 (myCenterPoint, mySecondPoint);
+
+  Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction());
+
+  return anAngle > 0.0 ? anAngle : (2.0 * M_PI - anAngle);
 }
 
 //=======================================================================
@@ -751,69 +600,31 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
 {
   thePresentation->Clear();
   mySelectionGeom.Clear (theMode);
-  Handle(SelectMgr_EntityOwner) anEmptyOwner;
 
-  if (!myIsInitialized)
+  if (!IsValid())
   {
-    if (myShapesNumber == 1)
-    {
-      myIsInitialized = initConeAngle (TopoDS::Face (myFirstShape));
-    }
-    else if (myShapesNumber == 2)
-    {
-      switch (myFirstShape.ShapeType())
-      {
-      case TopAbs_FACE:
-        {
-          myIsInitialized = initTwoFacesAngle ();
-        }
-        break;
-      case TopAbs_EDGE:
-        {
-          myIsInitialized = initTwoEdgesAngle ();
-        }
-        break;
-      default:
-        return;
-      }
-    }
-    else
-      return;
-  }
-
-  // If initialization failed
-  if (!myIsInitialized)
     return;
+  }
 
   // Parameters for presentation
   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
 
-  Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect(aDimensionAspect->LineAspect()->Aspect());
+  Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
 
   Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
 
-  if (!myIsValueCustom)
-  {
-    computeValue();
-  }
-
-  TCollection_ExtendedString aValueString;
-  Standard_Real aTextLength;
-  getTextWidthAndString (aTextLength, aValueString);
+  // prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
 
   // add margins to label width
   if (aDimensionAspect->IsText3d())
   {
-    aTextLength += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
-  }
-
-  if (!myIsWorkingPlaneCustom)
-  {
-    countDefaultPlane();
+    aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
   }
 
-  gp_Pnt aFirstAttach = myCenter.Translated (gp_Vec(myCenter, myFirstPoint).Normalized() * GetFlyout());
-  gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec(myCenter, mySecondPoint).Normalized() * GetFlyout());
+  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
   bool isArrowsExternal = false;
@@ -833,16 +644,16 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
 
       Standard_Real anArrowsWidth   = (anArrowLength + anArrowMargin) * 2.0;
 
-      isArrowsExternal = aDimensionWidth < aTextLength + anArrowsWidth;
+      isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
       break;
     }
   }
 
   //Arrows positions and directions
-  gp_Vec aWPDir = gp_Vec (GetWorkingPlane().Axis().Direction());
+  gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
 
-  gp_Dir aFirstExtensionDir  = gp_Vec (myCenter, aFirstAttach) ^ aWPDir;
-  gp_Dir aSecondExtensionDir = gp_Vec (myCenter, aSecondAttach)^ aWPDir.Reversed();
+  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;
@@ -876,7 +687,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
       gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
       Standard_Real aDimensionWidth = anAttachVector.Magnitude();
       Standard_Real anArrowsWidth   = anArrowLength * 2.0;
-      Standard_Real aContentWidth   = isArrowsExternal ? aTextLength : aTextLength + anArrowsWidth;
+      Standard_Real aContentWidth   = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
 
       aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
       break;
@@ -907,11 +718,12 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
 
       if (isLineBreak)
       {
-        drawArcWithText (thePresentation,
+        DrawArcWithText (thePresentation,
                          aFirstAttach,
                          aSecondAttach,
-                         aValueString,
-                         aTextLength,
+                         myCenterPoint,
+                         aLabelString,
+                         aLabelWidth,
                          theMode,
                          aLabelPosition);
         break;
@@ -920,23 +732,23 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
       // compute text primitives
       if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
       {
-        gp_Vec aDimensionDir (aFirstArrowEnd, aSecondArrowBegin);
-        gp_Pnt aTextPos = getCenterOnArc (aFirstArrowEnd, aSecondArrowBegin);
-        gp_Dir aTextDir = myIsTextReversed ? aDimensionDir.Reversed() : aDimensionDir;
+        gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
+        gp_Pnt aTextPos = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+        gp_Dir aTextDir = aDimensionDir;
 
-        drawText (thePresentation,
+        DrawText (thePresentation,
                   aTextPos,
                   aTextDir,
-                  aValueString,
+                  aLabelString,
                   aLabelPosition);
       }
 
       if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
       {
-        drawArc (thePresentation,
+        DrawArc (thePresentation,
                  isArrowsExternal ? aFirstAttach : aFirstArrowEnd,
                  isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
-                 myCenter,
+                 myCenterPoint,
                  Abs (GetFlyout()),
                  theMode);
       }
@@ -945,12 +757,12 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
 
     case LabelPosition_Left :
     {
-      drawExtension (thePresentation,
+      DrawExtension (thePresentation,
                      anExtensionSize,
                      isArrowsExternal ? aFirstArrowEnd : aFirstAttach,
                      aFirstExtensionDir,
-                     aValueString,
-                     aTextLength,
+                     aLabelString,
+                     aLabelWidth,
                      theMode,
                      aLabelPosition);
     }
@@ -958,12 +770,12 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
 
     case LabelPosition_Right :
     {
-      drawExtension (thePresentation,
+      DrawExtension (thePresentation,
                      anExtensionSize,
                      isArrowsExternal ? aSecondArrowEnd : aSecondAttach,
                      aSecondExtensionDir,
-                     aValueString,
-                     aTextLength,
+                     aLabelString,
+                     aLabelWidth,
                      theMode,
                      aLabelPosition);
     }
@@ -975,10 +787,10 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
   {
     Prs3d_Root::NewGroup (thePresentation);
 
-    drawArc (thePresentation,
+    DrawArc (thePresentation,
              isArrowsExternal ? aFirstAttach  : aFirstArrowEnd,
              isArrowsExternal ? aSecondAttach : aSecondArrowEnd,
-             myCenter,
+             myCenterPoint,
              Abs(GetFlyout ()),
              theMode);
   }
@@ -988,8 +800,8 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
   {
     Prs3d_Root::NewGroup (thePresentation);
 
-    drawArrow (thePresentation, aFirstArrowBegin,  gp_Dir (aFirstArrowVec));
-    drawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
+    DrawArrow (thePresentation, aFirstArrowBegin,  gp_Dir (aFirstArrowVec));
+    DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec));
   }
 
   if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal)
@@ -998,7 +810,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
 
     if (aHPosition != LabelPosition_Left)
     {
-      drawExtension (thePresentation,
+      DrawExtension (thePresentation,
                      anExtensionSize,
                      aFirstArrowEnd,
                      aFirstExtensionDir,
@@ -1010,7 +822,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
 
     if (aHPosition != LabelPosition_Right)
     {
-      drawExtension (thePresentation,
+      DrawExtension (thePresentation,
                      anExtensionSize,
                      aSecondArrowEnd,
                      aSecondExtensionDir,
@@ -1022,14 +834,14 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
   }
 
   // flyouts
-  if (theMode == ComputeMode_All && myIsFlyoutLines)
+  if (theMode == ComputeMode_All)
   {
     Prs3d_Root::NewGroup (thePresentation);
 
     Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4);
-    aPrimSegments->AddVertex (myCenter);
+    aPrimSegments->AddVertex (myCenterPoint);
     aPrimSegments->AddVertex (aFirstAttach);
-    aPrimSegments->AddVertex (myCenter);
+    aPrimSegments->AddVertex (myCenterPoint);
     aPrimSegments->AddVertex (aSecondAttach);
 
     Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect();
@@ -1037,27 +849,342 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
   }
 
-  setComputed (Standard_True);
+  myIsComputed = Standard_True;
 }
 
 //=======================================================================
-//function : computeFlyoutSelection
+//function : ComputeFlyoutSelection
 //purpose  : computes selection for flyouts
 //=======================================================================
-void AIS_AngleDimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
+void AIS_AngleDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
                                                  const Handle(SelectMgr_EntityOwner)& theOwner)
 {
-  if (!myIsFlyoutLines)
+  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);
+}
+
+//=======================================================================
+//function : InitTwoEdgesAngle
+//purpose  : 
+//=======================================================================
+Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane)
+{
+  TopoDS_Edge aFirstEdge  = TopoDS::Edge (myFirstShape);
+  TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape);
+
+  BRepAdaptor_Curve aMakeFirstLine  (aFirstEdge);
+  BRepAdaptor_Curve aMakeSecondLine (aSecondEdge);
+
+  if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line)
   {
-    return;
+    return  Standard_False;
   }
 
-  gp_Pnt aFirstAttach  = myCenter.Translated (gp_Vec (myCenter, myFirstPoint).Normalized()  * GetFlyout());
-  gp_Pnt aSecondAttach = myCenter.Translated (gp_Vec (myCenter, mySecondPoint).Normalized() * GetFlyout());
+  Handle(Geom_Line) aFirstLine  = new Geom_Line (aMakeFirstLine.Line());
+  Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line());
 
-  Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
-  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aFirstAttach));
-  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenter, aSecondAttach));
+  gp_Lin aFirstLin  = aFirstLine->Lin();
+  gp_Lin aSecondLin = aSecondLine->Lin();
 
-  theSelection->Add (aSensitiveEntity);
+  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;
+  }
+
+  if (aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular()))
+  {
+    myFirstPoint  = aFirstLin.Location();
+    mySecondPoint = ElCLib::Value (ElCLib::Parameter (aFirstLin, myFirstPoint), aSecondLin);
+
+    if (mySecondPoint.Distance (myFirstPoint) <= Precision::Confusion())
+    {
+      mySecondPoint.Translate (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout()));
+    }
+
+    myCenterPoint.SetXYZ ((myFirstPoint.XYZ() + mySecondPoint.XYZ()) / 2.0);
+  }
+  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;
+    }
+
+    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;
+  }
+
+  return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint);
+}
+
+//=======================================================================
+//function : InitTwoFacesAngle
+//purpose  : initialization of angle dimension between two faces
+//=======================================================================
+Standard_Boolean AIS_AngleDimension::InitTwoFacesAngle()
+{
+  TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape);
+  TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape);
+
+  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);
+
+  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 : 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);
+
+  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()
+{
+  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)
+    {
+      // 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();
+  }
+
+  // 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 : 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();
 }
index 3c9d702..7b77c5b 100644 (file)
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-//! A framework to define display of angles. <br>
-//! These displays are particularly useful in viewing draft prisms. <br>
-//! The angle displayed may define an intersection <br>
-//! can be between two edges or two faces of a shape <br>
-//! or a plane. The display consists of arrows and text. <br>
-
 #ifndef _AIS_AngleDimension_HeaderFile
 #define _AIS_AngleDimension_HeaderFile
 
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Face.hxx>
+#include <TopoDS_Vertex.hxx>
 
 DEFINE_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
 
+//! Angle dimension. Can be constructed:
+//! - on two intersected edges.
+//! - on three points or vertices.
+//! - on conical face.
+//! - between two intersected faces.
+//!
+//! In case of three points or two intersected edges the dimension plane
+//! (on which dimension presentation is built) can be computed uniquely
+//! as through three defined points can be built only one plane.
+//! Therefore, if user-defined plane differs from this one, the dimension can't be built.
+//!
+//! In cases of two planes automatical plane by default is built on point of the
+//! origin of parametrical space of the first face (the basis surface) so, that
+//! the working plane and two faces intersection forms minimal angle between the faces.
+//! User can define the other point which the dimension plane should pass through
+//! using the appropriate constructor. This point can lay on the one of the faces or not.
+//! Also user can define his own plane but it should pass through the three points
+//! computed on the geometry initialization step (when the constructor or SetMeasuredGeometry() method
+//! is called). 
+//!
+//! In case of the conical face the center point of the angle is the apex of the conical surface.
+//! The attachment points are points of the first and the last parameter of the basis circle of the cone.
+//!
 class AIS_AngleDimension : public AIS_Dimension
 {
 public:
 
-  //! Constructs angle dimension between two edges
-  //! with automatic working plane computing
-  //! if it is possible. In case of PI angle please
-  //! set custom working plane or use constructor with 3 parameters.
-  Standard_EXPORT  AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
-                                       const TopoDS_Edge& theSecondEdge);
-  //!  Constructs the angle display object defined by the <br>
-  //! two edges and custom working plane.
-  //! ATTENTION :In case if the working plane is custom and one edge is out of the
-  //!            working plane it tries to project this edge line on the plane.
-  //!            To avoid this case you can reset the working plane
-  //!            using <ResetWorkingPlane ()> method.
-  Standard_EXPORT  AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
-                                       const TopoDS_Edge& theSecondEdge,
-                                       const gp_Pln& thePlane);
+  //! Constructs minimum angle dimension between two linear edges (where possible).
+  //! These two edges should be intersected by each other. Otherwise the geometry is not valid.
+  //! @param theFirstEdge [in] the first edge.
+  //! @param theSecondEdge [in] the second edge.
+  Standard_EXPORT AIS_AngleDimension (const TopoDS_Edge& theFirstEdge,
+                                      const TopoDS_Edge& theSecondEdge);
 
   //! Constructs the angle display object defined by three points.
-  Standard_EXPORT  AIS_AngleDimension (const gp_Pnt& theFirstPoint,
-                                       const gp_Pnt& theSecondPoint,
-                                       const gp_Pnt& theThirdPoint);
+  //! @param theFirstPoint [in] the first point (point on first angle flyout).
+  //! @param theSecondPoint [in] the center point of angle dimension.
+  //! @param theThirdPoint [in] the second point (point on second angle flyout).
+  Standard_EXPORT AIS_AngleDimension (const gp_Pnt& theFirstPoint,
+                                      const gp_Pnt& theSecondPoint,
+                                      const gp_Pnt& theThirdPoint);
+
+  //! Constructs the angle display object defined by three vertices.
+  //! @param theFirstVertex [in] the first vertex (vertex for first angle flyout).
+  //! @param theSecondVertex [in] the center vertex of angle dimension.
+  //! @param theThirdPoint [in] the second vertex (vertex for second angle flyout).
+  Standard_EXPORT AIS_AngleDimension (const TopoDS_Vertex& theFirstVertex,
+                                      const TopoDS_Vertex& theSecondVertex,
+                                      const TopoDS_Vertex& theThirdVertex);
+
+  //! Constructs angle dimension for the cone face.
+  //! @param theCone [in] the conical face.
+  Standard_EXPORT AIS_AngleDimension (const TopoDS_Face& theCone);
+
+  //! Constructs angle dimension between two planar faces.
+  //! @param theFirstFace [in] the first face.
+  //! @param theSecondFace [in] the second face.
+  Standard_EXPORT AIS_AngleDimension (const TopoDS_Face& theFirstFace,
+                                      const TopoDS_Face& theSecondFace);
+
+  //! Constructs angle dimension between two planar faces.
+  //! @param theFirstFace [in] the first face.
+  //! @param theSecondFace [in] the second face.
+  //! @param thePoint [in] the point which the dimension plane should pass through.
+  //! This point can lay on the one of the faces or not.
+  Standard_EXPORT AIS_AngleDimension (const TopoDS_Face& theFirstFace,
+                                      const TopoDS_Face& theSecondFace,
+                                      const gp_Pnt& thePoint);
+
+public:
+
+  //! @return first point forming the angle.
+  const gp_Pnt& FirstPoint() const
+  {
+    return myFirstPoint;
+  }
+
+  //! @return second point forming the angle.
+  const gp_Pnt& SecondPoint() const
+  {
+    return mySecondPoint;
+  }
+
+  //! @return center point forming the angle.
+  const gp_Pnt& CenterPoint() const
+  {
+    return myCenterPoint;
+  }
+
+  //! @return first argument shape.
+  const TopoDS_Shape& FirstShape() const
+  {
+    return myFirstShape;
+  }
+
+  //! @return second argument shape.
+  const TopoDS_Shape& SecondShape() const
+  {
+    return mySecondShape;
+  }
+
+  //! @return third argument shape.
+  const TopoDS_Shape& ThirdShape() const
+  {
+    return myThirdShape;
+  }
+
+public:
+
+  //! Measures minimum angle dimension between two linear edges.
+  //! These two edges should be intersected by each other. Otherwise the geometry is not valid.
+  //! @param theFirstEdge [in] the first edge.
+  //! @param theSecondEdge [in] the second edge.
+  Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
+                                            const TopoDS_Edge& theSecondEdge);
 
-  //! Angle of cone
-  Standard_EXPORT  AIS_AngleDimension (const TopoDS_Face& theCone);
+  //! Measures angle defined by three points.
+  //! @param theFirstPoint [in] the first point (point on first angle flyout).
+  //! @param theSecondPoint [in] the center point of angle dimension.
+  //! @param theThirdPoint [in] the second point (point on second angle flyout).
+  Standard_EXPORT void SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
+                                            const gp_Pnt& theSecondPoint,
+                                            const gp_Pnt& theThridPoint);
 
-  //! TwoPlanarFaceAngle dimension
-  Standard_EXPORT  AIS_AngleDimension (const TopoDS_Face& theFirstFace,
-                                       const TopoDS_Face& theSecondFace,
-                                       const gp_Ax1& theAxis);
+  //! Measures angle defined by three vertices.
+  //! @param theFirstVertex [in] the first vertex (vertex for first angle flyout).
+  //! @param theSecondVertex [in] the center vertex of angle dimension.
+  //! @param theThirdPoint [in] the second vertex (vertex for second angle flyout).
+  Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex,
+                                            const TopoDS_Vertex& theSecondVertex,
+                                            const TopoDS_Vertex& theThirdVertex);
 
-  //! Sets first shape
-  Standard_EXPORT  void SetFirstShape (const TopoDS_Shape& theShape,
-                                       const Standard_Boolean isSingleShape = Standard_False);
+  //! Measures angle of conical face.
+  //! @param theCone [in] the shape to measure.
+  Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Face& theCone);
+
+  //! Measures angle between two planar faces.
+  //! @param theFirstFace [in] the first face.
+  //! @param theSecondFace [in] the second face..
+  Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
+                                            const TopoDS_Face& theSecondFace);
+
+  //! Measures angle between two planar faces.
+  //! @param theFirstFace [in] the first face.
+  //! @param theSecondFace [in] the second face.
+  //! @param thePoint [in] the point which the dimension plane should pass through.
+  //! This point can lay on the one of the faces or not.
+  Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
+                                            const TopoDS_Face& theSecondFace,
+                                            const gp_Pnt& thePoint);
+
+  //! @return the display units string.
+  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const;
+  
+  //! @return the model units string.
+  Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const;
+
+  Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& theUnits);
+
+  Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits);
 
 public:
 
@@ -88,63 +207,111 @@ public:
 
 protected:
 
-  //! Computes dimension value in display units
-  Standard_EXPORT virtual void computeValue();
+  //! Initialization of fields that is common to all constructors. 
+  Standard_EXPORT void Init();
 
-  Standard_EXPORT  void init();
+  //! @param theFirstAttach [in] the first attachment point.
+  //! @param theSecondAttach [in] the second attachment point.
+  //! @param theCenter [in] the center point (center point of the angle).  
+  //! @return the center of the dimension arc (the main dimension line in case of angle). 
+  Standard_EXPORT gp_Pnt GetCenterOnArc (const gp_Pnt& theFirstAttach,
+                                         const gp_Pnt& theSecondAttach,
+                                         const gp_Pnt& theCenter);
 
-  Standard_EXPORT  gp_Pnt getCenterOnArc (const gp_Pnt& theFirstAttach,
-                                          const gp_Pnt& theSecondAttach);
+  //! Draws main dimension line (arc).
+  //! @param thePresentation [in] the dimension presentation.
+  //! @param theFirstAttach [in] the first attachment point.
+  //! @param theSecondAttach [in] the second attachment point.
+  //! @param theCenter [in] the center point (center point of the angle).
+  //! @param theRadius [in] the radius of the dimension arc.
+  //! @param theMode [in] the display mode.
+  Standard_EXPORT void 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);
 
-  Standard_EXPORT  void 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);
+  //! Draws main dimension line (arc) with text.
+  //! @param thePresentation [in] the dimension presentation.
+  //! @param theFirstAttach [in] the first attachment point.
+  //! @param theSecondAttach [in] the second attachment point.
+  //! @param theCenter [in] the center point (center point of the angle).
+  //! @param theText [in] the text label string.
+  //! @param theTextWidth [in] the text label width. 
+  //! @param theMode [in] the display mode.
+  //! @param theLabelPosition [in] the text label vertical and horizontal positioning option
+  //! respectively to the main dimension line. 
+  Standard_EXPORT void 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);
 
-  Standard_EXPORT  void drawArcWithText (const Handle(Prs3d_Presentation)& thePresentation,
-                                         const gp_Pnt& theFirstAttach,
-                                         const gp_Pnt& theSecondAttach,
-                                         const TCollection_ExtendedString& theText,
-                                         const Standard_Real theTextWidth,
-                                         const Standard_Integer theMode,
-                                         const Standard_Integer theLabelPosition);
+protected:
+
+  Standard_EXPORT virtual void ComputePlane();
+
+  //! Checks if the plane includes three angle points to build dimension.
+  Standard_EXPORT virtual Standard_Boolean CheckPlane (const gp_Pln& thePlane) const;
+
+  Standard_EXPORT virtual Standard_Real ComputeValue() const;
 
   Standard_EXPORT  virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePM,
                                          const Handle(Prs3d_Presentation)& thePresentation,
                                          const Standard_Integer theMode = 0);
 
-  Standard_EXPORT  Standard_Boolean initConeAngle (const TopoDS_Face& theCone);
+  Standard_EXPORT virtual void ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
+                                                       const Handle(SelectMgr_EntityOwner)& theOwner);
 
-  Standard_EXPORT  Standard_Boolean initTwoFacesAngle();
+protected:
 
-  Standard_EXPORT  Standard_Boolean initTwoEdgesAngle();
+  //! Init angular dimension to measure angle between two linear edges.
+  //! @return TRUE if the angular dimension can be constructured
+  //!         for the passed edges.
+  Standard_EXPORT Standard_Boolean InitTwoEdgesAngle (gp_Pln& theComputedPlane);
 
-  //! Auxiliary method to get position of the angle dimension
-  //! if the cone is trimmed
-  //! Returns 1 if <theC> center is above of <theCMin> center;
-  //!         0 if <theC> center is between <theCMin> and <theCMax> centers;
-  //!        -1 if <theC> center is below <theCMax> center.
-  Standard_EXPORT Standard_Integer aboveInBelowCone (const gp_Circ &theCMax,
-                                                     const gp_Circ &theCMin,
-                                                     const gp_Circ &theC);
+  //! Init angular dimension to measure angle between two planar faces.
+  //! there is no user-defined poisitoning. So attach points are set
+  //! according to faces geometry (in origin of the first face basis surface).
+  //! @return TRUE if the angular dimension can be constructed
+  //!         for the passed faces.
+  Standard_EXPORT Standard_Boolean InitTwoFacesAngle();
 
-  //! Fills default plane object if it is possible to count plane automatically.
-  Standard_EXPORT virtual void countDefaultPlane ();
-  
- //! Fills sensitive entity for flyouts and adds it to the selection
- Standard_EXPORT virtual void computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
-                                                      const Handle(SelectMgr_EntityOwner)& theOwner);
+  //! Init angular dimension to measure angle between two planar faces.
+  //! @param thePointOnFirstFace [in] the point which the dimension plane should pass through.
+  //! This point can lay on the one of the faces or not.
+  //! It will be projected on the first face and this point will be set
+  //! as the first point attach point.
+  //! It defines some kind of dimension positioning over the faces.
+  //! @return TRUE if the angular dimension can be constructed
+  //!         for the passed faces.
+  Standard_EXPORT Standard_Boolean InitTwoFacesAngle (const gp_Pnt thePointOnFirstFace);
 
-protected:
+  //! Init angular dimension to measure cone face.
+  //! @return TRUE if the angular dimension can be constructed
+  //!              for the passed cone.
+  Standard_EXPORT Standard_Boolean InitConeAngle();
+
+  //! Check that the points forming angle are valid.
+  //! @return TRUE if the points met the following requirements:
+  //!         The (P1, Center), (P2, Center) can be built.
+  //!         The angle between the vectors > Precision::Angular().
+  Standard_EXPORT Standard_Boolean IsValidPoints (const gp_Pnt& theFirstPoint,
+                                                  const gp_Pnt& theCenterPoint,
+                                                  const gp_Pnt& theSecondPoint) const;
 
-  //! Shows if there is necessarily to draw extensions on angle dimension
-  //! It is set to the true value if the attachment point are out of the edges.
-  Standard_Boolean myIsFlyoutLines;
+private:
 
-  //! The center of dimension arc
-  gp_Pnt myCenter;
+  gp_Pnt myFirstPoint;
+  gp_Pnt mySecondPoint;
+  gp_Pnt myCenterPoint;
+  TopoDS_Shape myFirstShape;
+  TopoDS_Shape mySecondShape;
+  TopoDS_Shape myThirdShape;
 };
 
-#endif
+#endif // _AIS_AngleDimension_HeaderFile
index e420737..8330025 100755 (executable)
 // and conditions governing the rights and limitations under the License.
 
 #include <AIS_DiameterDimension.hxx>
+
 #include <AIS.hxx>
-#include <AIS_Drawer.hxx>
+#include <BRepLib_MakeEdge.hxx>
 #include <ElCLib.hxx>
+#include <GeomAPI_IntCS.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_Plane.hxx>
 #include <gce_MakeDir.hxx>
-#include <Graphic3d_ArrayOfSegments.hxx>
-#include <Graphic3d_Group.hxx>
-#include <PrsMgr_PresentationManager3d.hxx>
-#include <Prs3d_Root.hxx>
+#include <Standard_ProgramError.hxx>
 
-IMPLEMENT_STANDARD_HANDLE(AIS_DiameterDimension, AIS_Dimension)
-IMPLEMENT_STANDARD_RTTIEXT(AIS_DiameterDimension, AIS_Dimension)
+IMPLEMENT_STANDARD_HANDLE (AIS_DiameterDimension, AIS_Dimension)
+IMPLEMENT_STANDARD_RTTIEXT (AIS_DiameterDimension, AIS_Dimension)
 
 namespace
 {
@@ -40,69 +41,251 @@ namespace
 //function : Constructor
 //purpose  : 
 //=======================================================================
+AIS_DiameterDimension::AIS_DiameterDimension (const gp_Circ& theCircle)
+: AIS_Dimension (AIS_KOD_DIAMETER)
+{
+  SetMeasuredGeometry (theCircle);
+  SetSpecialSymbol (THE_DIAMETER_SYMBOL);
+  SetDisplaySpecialSymbol (AIS_DSS_Before);
+  SetFlyout (0.0);
+}
 
-AIS_DiameterDimension::AIS_DiameterDimension(const gp_Circ& theCircle)
-: AIS_Dimension(),
-  myCircle (theCircle)
+//=======================================================================
+//function : Constructor
+//purpose  : 
+//=======================================================================
+AIS_DiameterDimension::AIS_DiameterDimension (const gp_Circ& theCircle,
+                                              const gp_Pln& thePlane)
+: AIS_Dimension (AIS_KOD_DIAMETER)
 {
-  SetKindOfDimension(AIS_KOD_DIAMETER);
-  myIsInitialized = Standard_True;
+  SetCustomPlane (thePlane);
+  SetMeasuredGeometry (theCircle);
   SetSpecialSymbol (THE_DIAMETER_SYMBOL);
   SetDisplaySpecialSymbol (AIS_DSS_Before);
   SetFlyout (0.0);
-  // Count attach points
-  myFirstPoint = ElCLib::Value (0, myCircle);
-  mySecondPoint = myFirstPoint.Translated (gp_Vec(myFirstPoint, theCircle.Location())*2);
 }
 
 //=======================================================================
 //function : Constructor
 //purpose  : 
 //=======================================================================
+AIS_DiameterDimension::AIS_DiameterDimension (const TopoDS_Shape& theShape)
+: AIS_Dimension (AIS_KOD_DIAMETER)
+{
+  SetMeasuredGeometry (theShape);
+  SetSpecialSymbol (THE_DIAMETER_SYMBOL);
+  SetDisplaySpecialSymbol (AIS_DSS_Before);
+  SetFlyout (0.0);
+}
 
-AIS_DiameterDimension::AIS_DiameterDimension(const gp_Circ& theCircle, const gp_Pnt& theAttachPoint)
-: AIS_Dimension(),
-  myCircle (theCircle)
+//=======================================================================
+//function : Constructor
+//purpose  : 
+//=======================================================================
+AIS_DiameterDimension::AIS_DiameterDimension (const TopoDS_Shape& theShape,
+                                              const gp_Pln& thePlane)
+: AIS_Dimension (AIS_KOD_DIAMETER)
 {
-  SetKindOfDimension (AIS_KOD_DIAMETER);
+  SetCustomPlane (thePlane);
+  SetMeasuredGeometry (theShape);
   SetSpecialSymbol (THE_DIAMETER_SYMBOL);
   SetDisplaySpecialSymbol (AIS_DSS_Before);
   SetFlyout (0.0);
-  myFirstPoint = theAttachPoint;
-  // Count the second point
-  if (Abs(myFirstPoint.Distance (theCircle.Location()) - theCircle.Radius()) < Precision::Confusion())
+}
+
+//=======================================================================
+//function : AnchorPoint
+//purpose  : 
+//=======================================================================
+gp_Pnt AIS_DiameterDimension::AnchorPoint()
+{
+  if (!IsValid())
   {
-    mySecondPoint = myFirstPoint.Translated(gp_Vec(myFirstPoint, theCircle.Location())*2);
+    return gp::Origin();
   }
-  else
+
+  return myAnchorPoint;
+}
+
+//=======================================================================
+//function : SetMeasuredGeometry
+//purpose  : 
+//=======================================================================
+void AIS_DiameterDimension::SetMeasuredGeometry (const gp_Circ& theCircle)
+{
+  myCircle       = theCircle;
+  myGeometryType = GeometryType_Edge;
+  myShape        = BRepLib_MakeEdge (theCircle);
+  myAnchorPoint  = gp::Origin();
+  myIsValid      = IsValidCircle (myCircle);
+
+  if (myIsValid && myIsPlaneCustom)
+  {
+    ComputeAnchorPoint();
+  }
+  else if (!myIsPlaneCustom)
   {
-    myFirstPoint = ElCLib::Value(0, myCircle);
-    mySecondPoint = myFirstPoint.Translated(gp_Vec(myFirstPoint, theCircle.Location())*2);
+    ComputePlane();
+    myAnchorPoint = ElCLib::Value (0.0, myCircle);
   }
-  myIsInitialized = Standard_True;
+
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : Constructor
-//purpose  : Universal constructor for diameter dimension of shape
+//function : SetMeasuredGeometry
+//purpose  : 
 //=======================================================================
+void AIS_DiameterDimension::SetMeasuredGeometry (const TopoDS_Shape& theShape)
+{
+  gp_Pnt aDummyPnt (gp::Origin());
+  Standard_Boolean isClosed = Standard_False;
 
-AIS_DiameterDimension::AIS_DiameterDimension (const TopoDS_Shape& theShape)
-: AIS_Dimension ()
+  myGeometryType = GeometryType_UndefShapes;
+  myShape        = theShape;
+  myAnchorPoint  = gp::Origin();
+  myIsValid      = InitCircularDimension (theShape, myCircle, aDummyPnt, isClosed)
+                 && IsValidCircle (myCircle)
+                 && isClosed;
+
+  if (myIsValid && myIsPlaneCustom)
+  {
+    ComputeAnchorPoint();
+  }
+  else if (!myIsPlaneCustom)
+  {
+    ComputePlane();
+    myAnchorPoint = ElCLib::Value (0.0, myCircle);
+  }
+
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
+}
+
+//=======================================================================
+//function : CheckPlane
+//purpose  : 
+//=======================================================================
+Standard_Boolean AIS_DiameterDimension::CheckPlane (const gp_Pln& thePlane) const
 {
-  SetKindOfDimension (AIS_KOD_DIAMETER);
-  SetSpecialSymbol (THE_DIAMETER_SYMBOL);
-  SetDisplaySpecialSymbol (AIS_DSS_Before);
-  SetFlyout (0.0);
-  myFirstShape = theShape;
-  myIsInitialized = Standard_False;
+  // Check if the circle center point belongs to plane.
+  if (!thePlane.Contains (myCircle.Location(), Precision::Confusion()))
+  {
+    return Standard_False;
+  }
+
+  return Standard_True;
 }
 
 //=======================================================================
-//function : Compute
+//function : ComputePlane
+//purpose  : 
+//=======================================================================
+void AIS_DiameterDimension::ComputePlane()
+{
+  if (!IsValid())
+  {
+    return;
+  }
+
+  myPlane = gp_Pln (gp_Ax3 (myCircle.Position()));
+}
+
+//=======================================================================
+//function : ComputeAnchorPoint
 //purpose  : 
 //=======================================================================
+void AIS_DiameterDimension::ComputeAnchorPoint()
+{
+  // Anchor point is an intersection of dimension plane and circle.
+  Handle(Geom_Circle) aCircle = new Geom_Circle (myCircle);
+  Handle(Geom_Plane) aPlane = new Geom_Plane (myPlane);
+  GeomAPI_IntCS anIntersector (aCircle, aPlane);
+  if (!anIntersector.IsDone())
+  {
+    myIsValid = Standard_False;
+    return;
+  }
 
+  // The circle lays on the plane.
+  if (anIntersector.NbPoints() != 2)
+  {
+    myAnchorPoint = ElCLib::Value (0.0, myCircle);
+    myIsValid = Standard_True;
+    return;
+  }
+
+  gp_Pnt aFirstPoint = anIntersector.Point (1);
+  gp_Pnt aSecondPoint = anIntersector.Point (2);
+
+  // Choose one of two intersection points that stands with
+  // positive direction of flyout.
+  // An anchor point is supposed to be the left attachment point.
+  gp_Dir aFirstDir = gce_MakeDir (aFirstPoint, myCircle.Location());
+  gp_Dir aDir = myPlane.Axis().Direction() ^ aFirstDir;
+  myAnchorPoint = (gp_Vec (aDir) * gp_Vec(myCircle.Position().Direction()) > 0.0)
+                  ? aFirstPoint
+                  : aSecondPoint;
+
+}
+
+//=======================================================================
+//function : GetModelUnits
+//purpose  :
+//=======================================================================
+const TCollection_AsciiString& AIS_DiameterDimension::GetModelUnits() const
+{
+  return myDrawer->DimLengthModelUnits();
+}
+
+//=======================================================================
+//function : GetDisplayUnits
+//purpose  :
+//=======================================================================
+const TCollection_AsciiString& AIS_DiameterDimension::GetDisplayUnits() const
+{
+  return myDrawer->DimLengthDisplayUnits();
+}
+
+//=======================================================================
+//function : SetModelUnits
+//purpose  :
+//=======================================================================
+void AIS_DiameterDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
+{
+  myDrawer->SetDimLengthModelUnits (theUnits);
+}
+
+//=======================================================================
+//function : SetDisplayUnits
+//purpose  :
+//=======================================================================
+void AIS_DiameterDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
+{
+  myDrawer->SetDimLengthDisplayUnits (theUnits);
+}
+
+//=======================================================================
+//function : ComputeValue
+//purpose  : 
+//=======================================================================
+Standard_Real AIS_DiameterDimension::ComputeValue() const
+{
+  if (!IsValid())
+  {
+    return 0.0;
+  }
+
+  return myCircle.Radius() * 2.0;
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
 void AIS_DiameterDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
                                      const Handle(Prs3d_Presentation)& thePresentation, 
                                      const Standard_Integer theMode)
@@ -110,48 +293,72 @@ void AIS_DiameterDimension::Compute (const Handle(PrsMgr_PresentationManager3d)&
   thePresentation->Clear();
   mySelectionGeom.Clear (theMode);
 
-  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
-  Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
-
-  if (!myIsInitialized)
+  if (!IsValid())
   {
-    if (!initCircularDimension (myFirstShape, myCircle,
-                               myFirstPoint, mySecondPoint))
-      return;
-    else
-      myIsInitialized = Standard_True;
+    return;
   }
 
-  if (!myIsWorkingPlaneCustom)
+  gp_Pnt aFirstPnt (gp::Origin());
+  gp_Pnt aSecondPnt (gp::Origin());
+  ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt);
+
+  DrawLinearDimension (thePresentation, theMode, aFirstPnt, aSecondPnt);
+}
+
+//=======================================================================
+//function : ComputeFlyoutSelection
+//purpose  : 
+//=======================================================================
+void AIS_DiameterDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
+                                                    const Handle(SelectMgr_EntityOwner)& theEntityOwner)
+{
+  if (!IsValid())
   {
-   countDefaultPlane();
+    return;
   }
 
-  drawLinearDimension (thePresentation, theMode);
+  gp_Pnt aFirstPnt (gp::Origin());
+  gp_Pnt aSecondPnt (gp::Origin());
+  ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt);
+
+  ComputeLinearFlyouts (theSelection, theEntityOwner, aFirstPnt, aSecondPnt);
 }
 
 //=======================================================================
-//function : computeValue
+//function : ComputeSidePoints
 //purpose  : 
 //=======================================================================
-
-void AIS_DiameterDimension::computeValue ()
+void AIS_DiameterDimension::ComputeSidePoints (const gp_Circ& /*theCircle*/,
+                                               const gp_Pln& /*thePlane*/,
+                                               gp_Pnt& theFirstPnt,
+                                               gp_Pnt& theSecondPnt)
 {
-  myValue = myFirstPoint.Distance (mySecondPoint);
-  AIS_Dimension::computeValue();
+  theFirstPnt = AnchorPoint();
+
+  gp_Vec aRadiusVector (myCircle.Location(), theFirstPnt);
+  theSecondPnt = myCircle.Location().Translated (-aRadiusVector);
 }
 
 //=======================================================================
-//function : countDefaultPlane
+//function : IsValidCircle
 //purpose  : 
 //=======================================================================
+Standard_Boolean AIS_DiameterDimension::IsValidCircle (const gp_Circ& theCircle) const
+{
+  return (theCircle.Radius() * 2.0) > Precision::Confusion();
+}
 
-void AIS_DiameterDimension::countDefaultPlane ()
+//=======================================================================
+//function : IsValidAnchor
+//purpose  : 
+//=======================================================================
+Standard_Boolean AIS_DiameterDimension::IsValidAnchor (const gp_Circ& theCircle,
+                                                       const gp_Pnt& theAnchor) const
 {
-  // Compute normal of the default plane.
-  //gp_Vec aVec1(mySecondPoint, myFirstPoint),
-  //       aVec2(mySecondPoint, ElCLib::Value(M_PI_2, myCircle));
-  myDefaultPlane = gp_Pln(gp_Ax3(myCircle.Position()));
-  // Set computed value to <myWorkingPlane>
-  ResetWorkingPlane ();
+  gp_Pln aCirclePlane (theCircle.Location(), theCircle.Axis().Direction());
+  Standard_Real anAnchorDist = theAnchor.Distance (theCircle.Location());
+  Standard_Real aRadius      = myCircle.Radius();
+
+  return Abs (anAnchorDist - aRadius) > Precision::Confusion()
+      && aCirclePlane.Contains (theAnchor, Precision::Confusion());
 }
index efc186a..dad8dc4 100644 (file)
@@ -15,6 +15,7 @@
 // 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.
+
 #ifndef _AIS_DiameterDimension_HeaderFile
 #define _AIS_DiameterDimension_HeaderFile
 
 #include <Standard_Macro.hxx>
 #include <Standard_DefineHandle.hxx>
 
-DEFINE_STANDARD_HANDLE(AIS_DiameterDimension,AIS_Dimension)
+DEFINE_STANDARD_HANDLE (AIS_DiameterDimension, AIS_Dimension)
 
-//! A framework to display diameter dimensions. <br>
-//! A diameter is displayed with arrows and text. The <br>
-//! text gives the length of the diameter. <br>
-//! The algorithm takes a length along a face and <br>
-//! analyzes it as an arc. It then reconstructs the circle <br>
-//! corresponding to the arc and calculates the <br>
-//! diameter of this circle. This diameter serves as a <br>
-//! relational reference in 3d presentations of the surface. <br>
+//! Diameter dimension. Can be constructued:
+//! - On generic circle.
+//! - On generic circle with user-defined anchor point on that circle
+//!   (dimension plane is oriented to follow the anchor point).
+//! - On generic circle in the specified plane.
+//! - On generic shape containing geometry that can be measured
+//!   by diameter dimension: circle wire, circular face, etc.
+//! The anchor point is the location of the left attachement point of
+//! dimension on the circle.
+//! The anchor point computation is processed after dimension plane setting
+//! so that positive flyout direction stands with normal of the circle and
+//! the normal of the plane.
+//! If the plane is user-defined the anchor point was computed as intersection
+//! of the plane and the basis circle. Among two intersection points
+//! the one is selected so that positive flyout direction vector and
+//! the circle normal on the one side form the circle plane.
+//! (corner between positive flyout directio nand the circle normal is acute.)
+//! If the plane is computed automatically (by default it is the circle plane),
+//! the anchor point is the zero parameter point of the circle.
+//!
+//! The dimension is considered as invalid if the user-defined plane
+//! does not include th enachor point and th ecircle center,
+//! if the diameter of the circle is less than Precision::Confusion().
+//! In case if the dimension is built on the arbitrary shape, it can be considered
+//! as invalid if the shape does not contain circle geometry.
+//!
 class AIS_DiameterDimension : public AIS_Dimension
 {
 public:
-  //! Constructs a diameter display object defined by the <br>
-  //! circle <theCircle>
-  Standard_EXPORT  AIS_DiameterDimension(const gp_Circ& theCircle);
 
-  //! Constructor that allows to set a attach point <br>
-  //! on the circle <theCircle> where to attach dimension
-  Standard_EXPORT  AIS_DiameterDimension (const gp_Circ& theCircle,
-                                          const gp_Pnt& theAttachPoint);
+  //! Construct diameter dimension for the circle.
+  //! @param theCircle [in] the circle to measure.
+  Standard_EXPORT AIS_DiameterDimension (const gp_Circ& theCircle);
+
+  //! Construct diameter dimension for the circle and orient it correspondingly
+  //! to the passed plane.
+  //! @param theCircle [in] the circle to measure.
+  //! @param thePlane [in] the plane defining preferred orientation
+  //!        for dimension.
+  Standard_EXPORT AIS_DiameterDimension (const gp_Circ& theCircle,
+                                         const gp_Pln& thePlane);
+
+  //! Construct diameter on the passed shape, if applicable.
+  //! @param theShape [in] the shape to measure.
+  Standard_EXPORT AIS_DiameterDimension (const TopoDS_Shape& theShape);
+
+  //! Construct diameter on the passed shape, if applicable - and
+  //! define the preferred plane to orient the dimension.
+  //! @param theShape [in] the shape to measure.
+  //! @param thePlane [in] the plane defining preferred orientation
+  //!        for dimension.
+  Standard_EXPORT AIS_DiameterDimension (const TopoDS_Shape& theShape,
+                                         const gp_Pln& thePlane);
+
+public:
+
+  //! @return measured geometry circle.
+  const gp_Circ& Circle() const
+  {
+    return myCircle;
+  }
+
+  //! @return anchor point on circle for diameter dimension.
+  Standard_EXPORT gp_Pnt AnchorPoint();
+
+  //! @return the measured shape.
+  const TopoDS_Shape& Shape() const
+  {
+    return myShape;
+  }
+
+public:
+
+  //! Measure diameter of the circle.
+  //! The actual dimension plane is used for determining anchor points
+  //! on the circle to attach the dimension lines to.
+  //! The dimension will become invalid if the diameter of the circle
+  //! is less than Precision::Confusion().
+  //! @param theCircle [in] the circle to measure.
+  Standard_EXPORT void SetMeasuredGeometry (const gp_Circ& theCircle);
+
+  //! Measure diameter on the passed shape, if applicable.
+  //! The dimension will become invalid if the passed shape is not
+  //! measurable or if measured diameter value is less than Precision::Confusion().
+  //! @param theShape [in] the shape to measure.
+  Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Shape& theShape);
 
-  Standard_EXPORT  AIS_DiameterDimension (const TopoDS_Shape& theShape);
+  //! @return the display units string.
+  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const;
+  
+  //! @return the model units string.
+  Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const;
+
+  Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& theUnits);
+
+  Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits);
+
+public:
 
   DEFINE_STANDARD_RTTI(AIS_DiameterDimension)
 
 protected:
 
-  Standard_EXPORT  virtual void computeValue();
+  //! Override this method to change logic of anchor point computation.
+  //! Computes anchor point. Its computation is based on the current
+  //! dimension plane. Therfore, anchor point is an intersection of plane
+  //! and circle.
+  //! ATTENTION!
+  //! 1) The plane should be set or computed before.
+  //! 2) The plane should inclide th ecircle center to be valid.
+  Standard_EXPORT virtual void ComputeAnchorPoint();
+
+  Standard_EXPORT virtual void ComputePlane();
+
+  //! Checks if the center of the circle is on the plane.
+  Standard_EXPORT virtual Standard_Boolean CheckPlane (const gp_Pln& thePlane) const;
 
-    //! Fills default plane object if it is possible to count plane automatically.
-  Standard_EXPORT  virtual void countDefaultPlane();
+  Standard_EXPORT virtual Standard_Real ComputeValue() const;
 
-private: 
+  Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
+                                        const Handle(Prs3d_Presentation)& thePresentation,
+                                        const Standard_Integer theMode = 0);
 
-  virtual  void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
-                         const Handle(Prs3d_Presentation)& thePresentation,
-                         const Standard_Integer theMode = 0);
+  Standard_EXPORT virtual void ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
+                                                       const Handle(SelectMgr_EntityOwner)& theEntityOwner);
+
+protected:
+
+  //! Compute points on the circle sides for the specified dimension plane.
+  //! Program error exception is raised if the dimension plane "x" direction 
+  //! is orthogonal to plane (the "impossible" case). The passed dimension plane
+  //! is the one specially computed to locate dimension presentation in circle.
+  //! @param theCircle [in] the circle.
+  //! @param thePlane [in] the dimension presentation plane computed.
+  //! @param theFirstPnt [out] the first point.
+  //! @param theSecondPnt [out] the second point.
+  Standard_EXPORT void ComputeSidePoints (const gp_Circ& theCircle,
+                                          const gp_Pln& thePlane,
+                                          gp_Pnt& theFirstPnt,
+                                          gp_Pnt& theSecondPnt);
+
+  Standard_EXPORT Standard_Boolean IsValidCircle (const gp_Circ& theCircle) const;
+
+  Standard_EXPORT Standard_Boolean IsValidAnchor (const gp_Circ& theCircle,
+                                                  const gp_Pnt& thePnt) const;
 
-// Fields
 private:
 
-  gp_Circ myCircle;
+  gp_Circ          myCircle;
+  gp_Pnt           myAnchorPoint;
+  TopoDS_Shape     myShape;
 };
-#endif
+
+#endif // _AIS_DiameterDimension_HeaderFile
index c0639ee..ec5c3a8 100644 (file)
@@ -1,4 +1,6 @@
-// Copyright (c) 1999-2013 OPEN CASCADE SAS
+// Created on: 2013-11-11
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2013 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
 
 #include <AIS.hxx>
 #include <AIS_DimensionOwner.hxx>
-#include <AIS_Drawer.hxx>
 #include <Adaptor3d_HCurve.hxx>
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Surface.hxx>
 #include <BRepBndLib.hxx>
+#include <Bnd_Box.hxx>
 #include <ElCLib.hxx>
 #include <Font_BRepFont.hxx>
 #include <GC_MakeCircle.hxx>
@@ -70,6 +72,7 @@
 #include <Units_UnitsDictionary.hxx>
 #include <UnitsAPI.hxx>
 #include <UnitsAPI_SystemUnits.hxx>
+#include <Standard_ProgramError.hxx>
 
 IMPLEMENT_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject)
@@ -79,6 +82,7 @@ namespace
   // default text strings
   static const Standard_Utf32Char THE_FILL_CHARACTER ('0');
   static const TCollection_ExtendedString THE_EMPTY_LABEL;
+  static const TCollection_AsciiString    THE_UNDEFINED_UNITS;
 
   // default text margin and resolution
   static const Standard_Real THE_3D_TEXT_MARGIN    = 0.1;
@@ -93,190 +97,202 @@ namespace
 //function : Constructor
 //purpose  : 
 //=======================================================================
-AIS_Dimension::AIS_Dimension()
+AIS_Dimension::AIS_Dimension (const AIS_KindOfDimension theType)
 : AIS_InteractiveObject(),
-  myDefaultPlane (gp_Pln (gp::XOY())),
-  myIsWorkingPlaneCustom (Standard_False),
-  myValue (0.0),
+  myCustomValue (0.0),
   myIsValueCustom (Standard_False),
-  myUnitsQuantity (TCollection_AsciiString("LENGTH")),
-  myToDisplayUnits (Standard_False),
   mySpecialSymbol (' '),
   myDisplaySpecialSymbol (AIS_DSS_No),
-  myIsTextReversed (Standard_False),
-  myIsInitialized (Standard_False),
+  myGeometryType (GeometryType_UndefShapes),
+  myIsPlaneCustom (Standard_False),
   myFlyout (0.0),
-  myKindOfDimension (AIS_KOD_NONE)
+  myIsValid (Standard_False),
+  myKindOfDimension (theType)
 {
-  ResetWorkingPlane();
-  // Units default settings
-  UnitsAPI::SetLocalSystem (UnitsAPI_SI);
-  myModelUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
-  myDisplayUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString());
 }
 
 //=======================================================================
-//function : AcceptDisplayMode
-//purpose  : Checks if display mode <theMode> is allowed to display object.
+//function : SetCustomValue
+//purpose  : 
 //=======================================================================
-Standard_Boolean AIS_Dimension::AcceptDisplayMode (const Standard_Integer theMode) const
+void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
 {
-  return theMode == ComputeMode_All;
-}
+  if (myIsValueCustom && myCustomValue == theValue)
+  {
+    return;
+  }
 
-//=======================================================================
-//function : computeValue
-//purpose  : Computes dimension value in display units.
-//=======================================================================
-void AIS_Dimension::computeValue()
-{
-  UnitsAPI::SetCurrentUnit (myUnitsQuantity.ToCString(), myModelUnits.ToCString());
-  myValue = UnitsAPI::CurrentFromLS (myValue, myUnitsQuantity.ToCString());
-  myValue = valueToDisplayUnits();
+  myIsValueCustom = Standard_True;
+
+  myCustomValue = theValue;
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : countDefaultPlane
+//function : GetPlane
 //purpose  : 
 //=======================================================================
-void AIS_Dimension::countDefaultPlane()
+const gp_Pln& AIS_Dimension::GetPlane() const
 {
+  return myPlane;
 }
 
 //=======================================================================
-//function : GetWorkingPlane
+//function : GetGeometryType
 //purpose  : 
 //=======================================================================
-const gp_Pln& AIS_Dimension::GetWorkingPlane() const
+const Standard_Integer AIS_Dimension::GetGeometryType () const
 {
-  return myWorkingPlane;
+  return myGeometryType;
 }
 
 //=======================================================================
-//function : SetWorkingPlane
+//function : SetUserPlane
 //purpose  : 
 //=======================================================================
-void AIS_Dimension::SetWorkingPlane (const gp_Pln& thePlane)
+void AIS_Dimension::SetCustomPlane (const gp_Pln& thePlane)
 {
-  myWorkingPlane = thePlane;
-  myIsWorkingPlaneCustom = Standard_True;
+  myPlane = thePlane;
+  myIsPlaneCustom = Standard_True;
+
+  // Check validity if geometry has been set already.
+  if (myIsValid)
+  {
+    myIsValid &= CheckPlane (myPlane);
+    SetToUpdate();
+  }
 }
 
 //=======================================================================
-//function : ResetWorkingPlane
-//purpose  : Set default value of working plane
+//function : SetDimensionAspect
+//purpose  :
 //=======================================================================
-void AIS_Dimension::ResetWorkingPlane()
+void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
 {
-  myWorkingPlane = myDefaultPlane;
-  myIsWorkingPlaneCustom = Standard_False;
+  myDrawer->SetDimensionAspect (theDimensionAspect);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : resetWorkingPlane
-//purpose  : Set default value of working plane
-//           Only for internal use.
+//function : SetDisplaySpecialSymbol
+//purpose  :
 //=======================================================================
-void AIS_Dimension::resetWorkingPlane (const gp_Pln& theNewDefaultPlane)
+void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
 {
-  myDefaultPlane = theNewDefaultPlane;
-  ResetWorkingPlane();
+  if (myDisplaySpecialSymbol == theDisplaySpecSymbol)
+  {
+    return;
+  }
+
+  myDisplaySpecialSymbol = theDisplaySpecSymbol;
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : valueInDisplayUnits
+//function : SetSpecialSymbol
 //purpose  :
 //=======================================================================
-Standard_Real AIS_Dimension::valueToDisplayUnits()
+void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
 {
-  return  UnitsAPI::AnyToAny (myValue,
-                              myModelUnits.ToCString(),
-                              myDisplayUnits.ToCString());
+  if (mySpecialSymbol == theSpecialSymbol)
+  {
+    return;
+  }
+
+  mySpecialSymbol = theSpecialSymbol;
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : KindOfDimension
-//purpose  : 
+//function : SetSelToleranceForText2d
+//purpose  :
 //=======================================================================
-AIS_KindOfDimension AIS_Dimension::KindOfDimension() const 
+void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
 {
-  return myKindOfDimension;
+  if (mySelToleranceForText2d == theTol)
+  {
+    return;
+  }
+
+  mySelToleranceForText2d = theTol;
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : SetKindOfDimension
-//purpose  : 
+//function : SetFlyout
+//purpose  :
 //=======================================================================
-void AIS_Dimension::SetKindOfDimension (const AIS_KindOfDimension theKindOfDimension)
+void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
 {
-  myKindOfDimension = theKindOfDimension;
-}
+  if (myFlyout == theFlyout)
+  {
+    return;
+  }
 
-//=======================================================================
-//function : GetValue
-//purpose  : 
-//=======================================================================
-Standard_Real AIS_Dimension::GetValue() const
- {
-  return myValue;
- }
+  myFlyout = theFlyout;
+
+  SetToUpdate();
+}
 
 //=======================================================================
-//function : SetCustomValue
-//purpose  : 
+//function : GetDisplayUnits
+//purpose  :
 //=======================================================================
-void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
+const TCollection_AsciiString& AIS_Dimension::GetDisplayUnits() const
 {
-  myValue = theValue;
-  myIsValueCustom = Standard_True;
+  return THE_UNDEFINED_UNITS;
 }
 
 //=======================================================================
-//function : SetFirstShape
-//purpose  : 
+//function : GetModelUnits
+//purpose  :
 //=======================================================================
-void AIS_Dimension::SetFirstShape (const TopoDS_Shape& theShape)
+const TCollection_AsciiString& AIS_Dimension::GetModelUnits() const
 {
-  myFirstShape = theShape;
-  myIsInitialized = Standard_False;
-  resetGeom();
+  return THE_UNDEFINED_UNITS;
 }
 
 //=======================================================================
-//function : SetSecondShape
-//purpose  : 
+//function : ValueToDisplayUnits
+//purpose  :
 //=======================================================================
-void AIS_Dimension::SetSecondShape (const TopoDS_Shape& theShape)
+Standard_Real AIS_Dimension::ValueToDisplayUnits() const
 {
-  mySecondShape = theShape;
-  myIsInitialized = Standard_False;
-  resetGeom();
+  return UnitsAPI::AnyToAny (GetValue(),
+                             GetModelUnits().ToCString(),
+                             GetDisplayUnits().ToCString());
 }
 
 //=======================================================================
-//function : getTextWidthAndString
+//function : GetValueString
 //purpose  : 
 //=======================================================================
-void AIS_Dimension::getTextWidthAndString (Quantity_Length& theWidth,
-                                           TCollection_ExtendedString& theString) const
+TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidth) const
 {
-  char aValueSimpleStr[25];
-  sprintf (aValueSimpleStr, "%g", GetValue());
-  theString = TCollection_ExtendedString (aValueSimpleStr);
+  // format value string using "sprintf"
+  TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
 
-  if (IsUnitsDisplayed())
-  {
-    theString += " ";
-    theString += TCollection_ExtendedString (myDisplayUnits);
-  }
+  char aFmtBuffer[256];
+  sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
+  TCollection_ExtendedString aValueStr = TCollection_ExtendedString (aFmtBuffer);
 
-  if (myDisplaySpecialSymbol == AIS_DSS_Before)
+  // add units to values string
+  if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
   {
-    theString = TCollection_ExtendedString (mySpecialSymbol) + theString;
+    aValueStr += " ";
+    aValueStr += TCollection_ExtendedString (GetDisplayUnits());
   }
-  else if (myDisplaySpecialSymbol == AIS_DSS_After)
+
+  switch (myDisplaySpecialSymbol)
   {
-    theString += TCollection_ExtendedString (mySpecialSymbol);
+    case AIS_DSS_Before : aValueStr.Insert (1, mySpecialSymbol); break;
+    case AIS_DSS_After  : aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
+    case AIS_DSS_No     : break;
   }
 
   // Get text style parameters
@@ -288,7 +304,7 @@ void AIS_Dimension::getTextWidthAndString (Quantity_Length& theWidth,
   Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
   Standard_Real   aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
 
-  NCollection_Utf8String anUTFString = (Standard_Utf16Char* )theString.ToExtString();
+  NCollection_Utf8String anUTFString = (Standard_Utf16Char* )aValueStr.ToExtString();
 
   theWidth = 0.0;
 
@@ -307,7 +323,7 @@ void AIS_Dimension::getTextWidthAndString (Quantity_Length& theWidth,
   else
   {
     // Text width for 1:1 scale 2D case
-    Handle(Font_FTFont) aFont = new Font_FTFont ();
+    Handle(Font_FTFont) aFont = new Font_FTFont();
     aFont->Init (aFontName, aFontAspect, (const unsigned int)aFontHeight, THE_2D_TEXT_RESOLUTION);
 
     for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
@@ -317,13 +333,15 @@ void AIS_Dimension::getTextWidthAndString (Quantity_Length& theWidth,
       theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
     }
   }
+
+  return aValueStr;
 }
 
 //=======================================================================
-//function : drawArrow
+//function : DrawArrow
 //purpose  : 
 //=======================================================================
-void AIS_Dimension::drawArrow (const Handle(Prs3d_Presentation)& thePresentation,
+void AIS_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
                                const gp_Pnt& theLocation,
                                const gp_Dir& theDirection)
 {
@@ -344,7 +362,7 @@ void AIS_Dimension::drawArrow (const Handle(Prs3d_Presentation)& thePresentation
   {
     gp_Pnt aLeftPoint (gp::Origin());
     gp_Pnt aRightPoint (gp::Origin());
-    const gp_Dir& aPlane = myWorkingPlane.Axis().Direction();
+    const gp_Dir& aPlane = GetPlane().Axis().Direction();
 
     PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint);
 
@@ -378,10 +396,10 @@ void AIS_Dimension::drawArrow (const Handle(Prs3d_Presentation)& thePresentation
 }
 
 //=======================================================================
-//function : drawText
+//function : DrawText
 //purpose  : 
 //=======================================================================
-void AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
+void AIS_Dimension::DrawText (const Handle(Prs3d_Presentation)& thePresentation,
                               const gp_Pnt& theTextPos,
                               const gp_Dir& theTextDir,
                               const TCollection_ExtendedString& theText,
@@ -458,7 +476,7 @@ void AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
     aTextShape.Move (anOffsetTrsf);
 
     // transform text to myWorkingPlane coordinate system
-    gp_Ax3 aTextCoordSystem (theTextPos, myWorkingPlane.Axis().Direction(), aTextDir);
+    gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
     gp_Trsf aTextPlaneTrsf;
     aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
     aTextShape.Move (aTextPlaneTrsf);
@@ -472,7 +490,7 @@ void AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
     aCenterOfLabel.Transform (aCenterOffsetTrsf);
     aCenterOfLabel.Transform (aTextPlaneTrsf);
 
-    gp_Ax2 aFlippingAxes (aCenterOfLabel, myWorkingPlane.Axis().Direction(), aTextDir);
+    gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
     Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes);
 
     // draw text
@@ -522,10 +540,10 @@ void AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation,
 }
 
 //=======================================================================
-//function : drawExtension
+//function : DrawExtension
 //purpose  : 
 //=======================================================================
-void AIS_Dimension::drawExtension (const Handle(Prs3d_Presentation)& thePresentation,
+void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
                                    const Standard_Real theExtensionSize,
                                    const gp_Pnt& theExtensionStart,
                                    const gp_Dir& theExtensionDir,
@@ -538,14 +556,13 @@ void AIS_Dimension::drawExtension (const Handle(Prs3d_Presentation)& thePresenta
   gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
 
   Standard_Boolean hasLabel = theLabelString.Length() > 0;
-
   if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
   {
     // compute text primitives; get its model width
     gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
-    gp_Dir aTextDir = myIsTextReversed ? -theExtensionDir : theExtensionDir;
+    gp_Dir aTextDir = theExtensionDir;
 
-    drawText (thePresentation,
+    DrawText (thePresentation,
               aTextPos,
               aTextDir,
               theLabelString,
@@ -590,71 +607,46 @@ void AIS_Dimension::drawExtension (const Handle(Prs3d_Presentation)& thePresenta
 }
 
 //=======================================================================
-//function : SetDimensionAspect
-//purpose  : 
-//=======================================================================
-void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
-{
-  myDrawer->SetDimensionAspect (theDimensionAspect);
-}
-
-//=======================================================================
-//function : DimensionAspect
+//function : DrawLinearDimension
 //purpose  : 
 //=======================================================================
-Handle(Prs3d_DimensionAspect) AIS_Dimension::DimensionAspect() const
-{
-  return myDrawer->DimensionAspect();
-}
-
-//=======================================================================
-//function : drawLinearDimension
-//purpose  : 
-//=======================================================================
-void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
+void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
                                          const Standard_Integer theMode,
-                                         const Standard_Boolean isOneSideDimension/* = Standard_False*/)
+                                         const gp_Pnt& theFirstPoint,
+                                         const gp_Pnt& theSecondPoint,
+                                         const Standard_Boolean theIsOneSide)
 {
-  // don not build any dimension for equal points
-  if (myFirstPoint.IsEqual (mySecondPoint, Precision::Confusion()))
+  // do not build any dimension for equal points
+  if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
   {
-    setComputed (Standard_False);
-    return;
+    Standard_ProgramError::Raise ("Can not build presentation for equal points.");
   }
 
   // compute dimension line points
-  gp_Ax1 aWorkingPlaneNormal = GetWorkingPlane().Axis();
-  gp_Dir aTargetPointsVector = gce_MakeDir (myFirstPoint, mySecondPoint);
+  gp_Ax1 aPlaneNormal = GetPlane().Axis();
+  gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
 
   // compute flyout direction vector
-  gp_Dir aFlyoutVector = aWorkingPlaneNormal.Direction() ^ aTargetPointsVector;
+  gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
 
   // create lines for layouts
-  gp_Lin aLine1 (myFirstPoint, aFlyoutVector);
-  gp_Lin aLine2 (mySecondPoint, aFlyoutVector);
+  gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+  gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
 
   // Get flyout end points
-  gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, myFirstPoint)  + GetFlyout(), aLine1);
-  gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, mySecondPoint) + GetFlyout(), aLine2);
+  gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint)  + GetFlyout(), aLine1);
+  gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
 
   Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
-  Handle(SelectMgr_EntityOwner) anEmptyOwner;
 
   gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
 
   // For extensions we need to know arrow size, text size and extension size: get it from aspect
   Quantity_Length anArrowLength   = aDimensionAspect->ArrowAspect()->Length();
   Standard_Real   anExtensionSize = aDimensionAspect->ExtensionSize();
-
-  if (!myIsValueCustom)
-  {
-   computeValue();
-  }
-
   // prepare label string and compute its geometrical width
   Standard_Real aLabelWidth;
-  TCollection_ExtendedString aLabelString;
-  getTextWidthAndString (aLabelWidth, aLabelString);
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
 
   // add margins to cut dimension lines for 3d text
   if (aDimensionAspect->IsText3d())
@@ -676,7 +668,7 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
                                     : 0.0;
 
       Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
-      Standard_Real anArrowsWidth   = isOneSideDimension 
+      Standard_Real anArrowsWidth   = theIsOneSide 
                                     ?  anArrowLength + anArrowMargin
                                     : (anArrowLength + anArrowMargin) * 2.0;
 
@@ -708,9 +700,9 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
   aSecondArrowEnd   = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength));
 
   gp_Pnt aCenterLineBegin = isArrowsExternal 
-    ? aLineBegPoint  : aFirstArrowEnd;
+    ? aLineBegPoint : aFirstArrowEnd;
 
-  gp_Pnt aCenterLineEnd   = isArrowsExternal || isOneSideDimension
+  gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
     ? aLineEndPoint : aSecondArrowEnd;
 
   Standard_Integer aLabelPosition = LabelPosition_None;
@@ -724,7 +716,7 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
     case Prs3d_DTHP_Fit:
     {
       Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
-      Standard_Real anArrowsWidth   = isOneSideDimension ? anArrowLength : 2.0 * anArrowLength;
+      Standard_Real anArrowsWidth   = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
       Standard_Real aContentWidth   = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
 
       aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
@@ -751,14 +743,12 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
       Prs3d_Root::NewGroup (thePresentation);
 
       gp_Pnt aTextPos = (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
-      gp_Dir aTextDir = myIsTextReversed 
-                      ? -aDimensionLine.Direction()
-                      :  aDimensionLine.Direction();
+      gp_Dir aTextDir = aDimensionLine.Direction();
 
       // add text primitives
       if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
       {
-        drawText (thePresentation,
+        DrawText (thePresentation,
                   aTextPos,
                   aTextDir,
                   aLabelString,
@@ -829,10 +819,10 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
         // add arrows to presentation
         Prs3d_Root::NewGroup (thePresentation);
 
-        drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
-        if (!isOneSideDimension)
+        DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
+        if (!theIsOneSide)
         {
-          drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
+          DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
         }
 
         if (!isArrowsExternal)
@@ -843,12 +833,12 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
         // add arrow extension lines to presentation
         Prs3d_Root::NewGroup (thePresentation);
 
-        drawExtension (thePresentation, anExtensionSize,
+        DrawExtension (thePresentation, anExtensionSize,
                        aFirstArrowEnd, aFirstExtensionDir,
                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
-        if (!isOneSideDimension)
+        if (!theIsOneSide)
         {
-          drawExtension (thePresentation, anExtensionSize,
+          DrawExtension (thePresentation, anExtensionSize,
                          aSecondArrowEnd, aSecondExtensionDir,
                          THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
         }
@@ -866,8 +856,10 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
       Prs3d_Root::NewGroup (thePresentation);
 
       // Left extension with the text
-      drawExtension (thePresentation, anExtensionSize,
-                     isArrowsExternal ? aFirstArrowEnd : aFirstArrowBegin,
+      DrawExtension (thePresentation, anExtensionSize,
+                     isArrowsExternal
+                       ? aFirstArrowEnd
+                       : aFirstArrowBegin,
                      aFirstExtensionDir,
                      aLabelString,
                      aLabelWidth,
@@ -896,13 +888,13 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
         // add arrows to presentation
         Prs3d_Root::NewGroup (thePresentation);
 
-        drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
-        if (!isOneSideDimension)
+        DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
+        if (!theIsOneSide)
         {
-          drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
+          DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
         }
 
-        if (!isArrowsExternal || isOneSideDimension)
+        if (!isArrowsExternal || theIsOneSide)
         {
           break;
         }
@@ -910,7 +902,7 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
         // add extension lines for external arrows
         Prs3d_Root::NewGroup (thePresentation);
 
-        drawExtension (thePresentation, anExtensionSize,
+        DrawExtension (thePresentation, anExtensionSize,
                        aSecondArrowEnd, aSecondExtensionDir,
                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
       }
@@ -927,8 +919,10 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
       Prs3d_Root::NewGroup (thePresentation);
 
       // Right extension with text
-      drawExtension (thePresentation, anExtensionSize,
-                     isArrowsExternal ? aSecondArrowEnd : aSecondArrowBegin,
+      DrawExtension (thePresentation, anExtensionSize,
+                     isArrowsExternal
+                       ? aSecondArrowEnd
+                       : aSecondArrowBegin,
                      aSecondExtensionDir,
                      aLabelString, aLabelWidth,
                      theMode,
@@ -954,13 +948,13 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
         // add arrows to presentation
         Prs3d_Root::NewGroup (thePresentation);
 
-        drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
-        if (!isOneSideDimension)
+        DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
+        if (!theIsOneSide)
         {
-          drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
+          DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
         }
 
-        if (!isArrowsExternal || isOneSideDimension)
+        if (!isArrowsExternal || theIsOneSide)
         {
           break;
         }
@@ -968,7 +962,7 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
         // add extension lines for external arrows
         Prs3d_Root::NewGroup (thePresentation);
 
-        drawExtension (thePresentation, anExtensionSize,
+        DrawExtension (thePresentation, anExtensionSize,
                        aFirstArrowEnd, aFirstExtensionDir,
                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
       }
@@ -983,10 +977,10 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
     Prs3d_Root::NewGroup (thePresentation);
 
     Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4);
-    aPrimSegments->AddVertex (myFirstPoint);
+    aPrimSegments->AddVertex (theFirstPoint);
     aPrimSegments->AddVertex (aLineBegPoint);
 
-    aPrimSegments->AddVertex (mySecondPoint);
+    aPrimSegments->AddVertex (theSecondPoint);
     aPrimSegments->AddVertex (aLineEndPoint);
 
     Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
@@ -994,44 +988,48 @@ void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePr
     Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
   }
 
-  setComputed (Standard_True);
+  myIsComputed = Standard_True;
 }
 
 //=======================================================================
-//function : SetFirstPoint
-//purpose  : 
+//function : ComputeLinearFlyouts
+//purpose  :
 //=======================================================================
-void AIS_Dimension::SetFirstPoint (const gp_Pnt& thePoint)
+void AIS_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
+                                          const Handle(SelectMgr_EntityOwner)& theOwner,
+                                          const gp_Pnt& theFirstPoint,
+                                          const gp_Pnt& theSecondPoint)
 {
-  myFirstPoint = thePoint;
-}
+  // count flyout direction
+  gp_Ax1 aPlaneNormal = GetPlane().Axis();
+  gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
 
-//=======================================================================
-//function : SetSecondPoint
-//purpose  : 
-//=======================================================================
-void AIS_Dimension::SetSecondPoint (const gp_Pnt& thePoint)
-{
-  mySecondPoint = thePoint;
-}
+  // count a flyout direction vector.
+  gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
 
-//=======================================================================
-//function : Type
-//purpose  :
-//=======================================================================
-AIS_KindOfInteractive AIS_Dimension::Type() const
-{
-  return AIS_KOI_Relation;
+  // create lines for layouts
+  gp_Lin aLine1 (theFirstPoint,  aFlyoutVector);
+  gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+
+  // get flyout end points
+  gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1);
+  gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
+
+  // fill sensitive entity for flyouts
+  Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
+  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1));
+  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2));
+  theSelection->Add (aSensitiveEntity);
 }
 
 //=======================================================================
-//function : circleFromPlanarFace
+//function : CircleFromPlanarFace
 //purpose  : if possible computes circle from planar face
 //=======================================================================
-Standard_Boolean AIS_Dimension::circleFromPlanarFace (const TopoDS_Face& theFace,
+Standard_Boolean AIS_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace,
                                                       Handle(Geom_Curve)& theCurve,
-                                                      gp_Pnt & theFirstPoint,
-                                                      gp_Pnt & theLastPoint)
+                                                      gp_Pnt& theFirstPoint,
+                                                      gp_Pnt& theLastPoint)
 {
   TopExp_Explorer anIt (theFace, TopAbs_EDGE);
   for ( ; anIt.More(); anIt.Next())
@@ -1049,13 +1047,13 @@ Standard_Boolean AIS_Dimension::circleFromPlanarFace (const TopoDS_Face& theFace
 }
 
 //=======================================================================
-//function : initCircularDimension
-//purpose  : if it's possible computes circle from planar face
+//function : InitCircularDimension
+//purpose  : 
 //=======================================================================
-Standard_Boolean AIS_Dimension::initCircularDimension (const TopoDS_Shape& theShape,
+Standard_Boolean AIS_Dimension::InitCircularDimension (const TopoDS_Shape& theShape,
                                                        gp_Circ& theCircle,
                                                        gp_Pnt& theMiddleArcPoint,
-                                                       gp_Pnt& theOppositeDiameterPoint)
+                                                       Standard_Boolean& theIsClosed)
 {
   gp_Pln aPln;
   Handle(Geom_Surface) aBasisSurf;
@@ -1064,8 +1062,8 @@ Standard_Boolean AIS_Dimension::initCircularDimension (const TopoDS_Shape& theSh
   Standard_Real anOffset    = 0.0;
   Standard_Real aFirstParam = 0.0;
   Standard_Real aLastParam  = 0.0;
-  Standard_Boolean isAnArc  = Standard_False;
 
+  // discover circular geometry
   if (theShape.ShapeType() == TopAbs_FACE)
   {
     AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset);
@@ -1073,14 +1071,12 @@ Standard_Boolean AIS_Dimension::initCircularDimension (const TopoDS_Shape& theSh
     if (aSurfType == AIS_KOS_Plane)
     {
       Handle(Geom_Curve) aCurve;
-      if (!circleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
+      if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint))
       {
-        Standard_ConstructionError::Raise ("AIS_Dimension:: Curve is not a circle or is Null") ;
         return Standard_False;
       }
 
       theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ();
-      isAnArc = !(aFirstPoint.IsEqual (aLastPoint, Precision::Confusion()));
     }
     else
     {
@@ -1092,7 +1088,7 @@ Standard_Boolean AIS_Dimension::initCircularDimension (const TopoDS_Shape& theSh
       Standard_Real aLastV  = aSurf1.LastVParameter();
       Standard_Real aMidU   = (aFirstU + aLastU) * 0.5;
       Standard_Real aMidV   = (aFirstV + aLastV) * 0.5;
-      aSurf1.D0(aMidU, aMidV, aCurPos);
+      aSurf1.D0 (aMidU, aMidV, aCurPos);
       Handle (Adaptor3d_HCurve) aBasisCurve;
       Standard_Boolean isExpectedType = Standard_False;
       if (aSurfType == AIS_KOS_Cylinder)
@@ -1121,9 +1117,9 @@ Standard_Boolean AIS_Dimension::initCircularDimension (const TopoDS_Shape& theSh
 
       if (!isExpectedType)
       {
-        Standard_ConstructionError::Raise ("AIS_Dimension:: Unexpected type of surface") ;
         return Standard_False;
       }
+
       Handle(Geom_Curve) aCurve;
       aCurve = aBasisSurf->VIso(aMidV);
       if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle))
@@ -1172,269 +1168,54 @@ Standard_Boolean AIS_Dimension::initCircularDimension (const TopoDS_Shape& theSh
     }
     else // Unexpected type of shape
     {
-      Standard_ConstructionError::Raise ("AIS_Dimension:: Unexpected type of shape");
       return Standard_False;
     }
+
     BRepAdaptor_Curve anAdaptedCurve (anEdge);
     if (!anAdaptedCurve.GetType() == GeomAbs_Circle)
     {
       return Standard_False;
     }
-    theCircle = anAdaptedCurve.Circle();
+
+    theCircle   = anAdaptedCurve.Circle();
     aFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter());
-    aLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
+    aLastPoint  = anAdaptedCurve.Value (anAdaptedCurve.LastParameter());
   }
-  // Get <theMiddleArcPoint> and <theOppositeDiameterPoint> values from <theCircle>
-  isAnArc = !(aFirstPoint.IsEqual (aLastPoint, Precision::Confusion()));
+
+  theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion());
+
   gp_Pnt aCenter = theCircle.Location();
-  if (!isAnArc)
+
+  if (theIsClosed) // Circle
   {
-    // Circle
     gp_Dir anXDir = theCircle.XAxis().Direction();
     theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius());
-    theOppositeDiameterPoint = aCenter.Translated (-gp_Vec (anXDir) * theCircle.Radius());
   }
-  else
+  else // Arc
   {
-    // Arc
     aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint);
     aLastParam  = ElCLib::Parameter (theCircle, aLastPoint);
     if (aFirstParam > aLastParam)
     {
       aFirstParam -= 2.0 * M_PI;
     }
+
     Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5;
     gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius ();
     theMiddleArcPoint = aCenter.Translated (aVec);
-    theOppositeDiameterPoint = aCenter.Translated (-aVec);
   }
 
   return Standard_True;
 }
 
 //=======================================================================
-//function : SetDisplaySpecialSymbol
-//purpose  : specifies dimension special symbol display options
-//=======================================================================
-void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol)
-{
-  myDisplaySpecialSymbol = theDisplaySpecSymbol;
-}
-
-//=======================================================================
-//function : DisplaySpecialSymbol
-//purpose  : shows dimension special symbol display options
-//=======================================================================
-AIS_DisplaySpecialSymbol AIS_Dimension::DisplaySpecialSymbol() const
-{
-  return myDisplaySpecialSymbol;
-}
-
-//=======================================================================
-//function : SetSpecialSymbol
-//purpose  : specifies special symbol
-//=======================================================================
-void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
-{
-  mySpecialSymbol = theSpecialSymbol;
-}
-
-//=======================================================================
-//function : SpecialSymbol
-//purpose  : returns special symbol
-//=======================================================================
-Standard_ExtCharacter AIS_Dimension::SpecialSymbol() const
-{
-  return mySpecialSymbol;
-}
-
-//=======================================================================
-//function : IsUnitsDisplayed
-//purpose  : shows if Units are to be displayed along with dimension value
-//=======================================================================
-Standard_Boolean AIS_Dimension::IsUnitsDisplayed() const
-{
-  return myToDisplayUnits;
-}
-
-//=======================================================================
-//function : MakeUnitsDisplayed
-//purpose  : sets to display units along with the dimension value or no
-//=======================================================================
-void AIS_Dimension::MakeUnitsDisplayed (const Standard_Boolean toDisplayUnits)
-{
-  myToDisplayUnits = toDisplayUnits;
-}
-
-//=======================================================================
-//function : MakeUnitsDisplayed
-//purpose  : returns the current type of units
-//=======================================================================
-TCollection_AsciiString AIS_Dimension::UnitsQuantity() const
-{
-  return myUnitsQuantity;
-}
-
-//=======================================================================
-//function : SetUnitsQuantity
-//purpose  : sets the current type of units
-//=======================================================================
-void AIS_Dimension::SetUnitsQuantity (const TCollection_AsciiString& theUnitsQuantity)
-{
-  myUnitsQuantity = theUnitsQuantity;
-}
-
-//=======================================================================
-//function : ModelUnits
-//purpose  : returns the current model units
-//=======================================================================
-TCollection_AsciiString AIS_Dimension::ModelUnits() const
-{
-  return myModelUnits;
-}
-
-//=======================================================================
-//function : SetModelUnits
-//purpose  : sets the current model units
-//=======================================================================
-void AIS_Dimension::SetModelUnits (const TCollection_AsciiString& theUnits)
-{
-  myModelUnits = theUnits;
-}
-
-//=======================================================================
-//function : DisplayUnits
-//purpose  : returns the current display units
-//=======================================================================
-TCollection_AsciiString AIS_Dimension::DisplayUnits() const
-{
-  return myDisplayUnits;
-}
-
-//=======================================================================
-//function : SetDisplayUnits
-//purpose  : sets the current display units
-//=======================================================================
-void AIS_Dimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
-{
-  myDisplayUnits = theUnits;
-}
-
-//=======================================================================
-//function : isComputed
-//purpose  :
-//=======================================================================
-Standard_Boolean AIS_Dimension::isComputed() const
-{
-  return myIsComputed;
-}
-
-//=======================================================================
-//function : setComputed
-//purpose  :
-//=======================================================================
-void AIS_Dimension::setComputed (Standard_Boolean isComputed)
-{
-  myIsComputed = isComputed;
-}
-
-//=======================================================================
-//function : resetGeom
-//purpose  :
-//=======================================================================
-void AIS_Dimension::resetGeom()
-{
-  mySelectionGeom.Clear (ComputeMode_All);
-}
-
-//=======================================================================
-//function : IsTextReversed
-//purpose  :
-//=======================================================================
-Standard_Boolean AIS_Dimension::IsTextReversed() const
-{
-  return myIsTextReversed;
-}
-
-//=======================================================================
-//function : MakeTextReversed
-//purpose  :
-//=======================================================================
-void AIS_Dimension::MakeTextReversed (const Standard_Boolean isTextReversed)
-{
-  myIsTextReversed = isTextReversed;
-}
-
-//=======================================================================
-//function : SetSelToleranceForText2d
-//purpose  :
-//=======================================================================
-void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
-{
-  mySelToleranceForText2d = theTol;
-}
-
-//=======================================================================
-//function : SelToleranceForText2d
-//purpose  :
-//=======================================================================
-Standard_Real AIS_Dimension::SelToleranceForText2d() const
-{
-  return mySelToleranceForText2d;
-}
-
-//=======================================================================
-//function : SetFlyout
-//purpose  :
-//=======================================================================
-void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
-{
-  if (myFlyout == theFlyout)
-  {
-    return;
-  }
-
-  myFlyout = theFlyout;
-  SetToUpdate();
-}
-
-//=======================================================================
-//function : computeFlyoutSelection
-//purpose  : computes selection for flyouts
-//=======================================================================
-void AIS_Dimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
-                                            const Handle(SelectMgr_EntityOwner)& theOwner)
-{
-  //Count flyout direction
-  gp_Ax1 aWorkingPlaneNormal = GetWorkingPlane().Axis();
-  gp_Dir aTargetPointsVector = gce_MakeDir (myFirstPoint, mySecondPoint);
-
-  // Count a flyout direction vector.
-  gp_Dir aFlyoutVector = aWorkingPlaneNormal.Direction() ^ aTargetPointsVector;
-
-  // Create lines for layouts
-  gp_Lin aLine1 (myFirstPoint, aFlyoutVector);
-  gp_Lin aLine2 (mySecondPoint, aFlyoutVector);
-
-  // Get flyout end points
-  gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, myFirstPoint) + GetFlyout(), aLine1);
-  gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, mySecondPoint) + GetFlyout(), aLine2);
-
-  // Fill sensitive entity for flyouts
-  Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner);
-  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myFirstPoint, aFlyoutEnd1));
-  aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, mySecondPoint, aFlyoutEnd2));
-  theSelection->Add (aSensitiveEntity);
-}
-
-//=======================================================================
 //function : ComputeSelection
 //purpose  : 
 //=======================================================================
 void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
                                       const Standard_Integer theMode)
 {
-  if (!isComputed())
+  if (!myIsComputed)
   {
     return;
   }
@@ -1488,7 +1269,7 @@ void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSele
 
       gp_Pnt aSidePnt1 (gp::Origin());
       gp_Pnt aSidePnt2 (gp::Origin());
-      const gp_Dir& aPlane = myWorkingPlane.Axis().Direction();
+      const gp_Dir& aPlane = GetPlane().Axis().Direction();
       const gp_Pnt& aPeak  = anArrow->Position;
       const gp_Dir& aDir   = anArrow->Direction;
 
@@ -1519,7 +1300,7 @@ void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSele
     Handle(Select3D_SensitiveEntity) aTextSensitive;
 
     gp_Ax2 aTextAxes (mySelectionGeom.TextPos,
-                      myWorkingPlane.Axis().Direction(),
+                      GetPlane().Axis().Direction(),
                       mySelectionGeom.TextDir);
 
     if (myDrawer->DimensionAspect()->IsText3d())
@@ -1555,7 +1336,7 @@ void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSele
   // callback for flyout sensitive calculation
   if (aSelectionMode == AIS_DSM_All)
   {
-    computeFlyoutSelection (theSelection, aSensitiveOwner);
+    ComputeFlyoutSelection (theSelection, aSensitiveOwner);
   }
 }
 
index 361814e..6eacf5e 100644 (file)
@@ -1,5 +1,6 @@
-// Copyright (c) 1998-1999 Matra Datavision
-// Copyright (c) 1999-2013 OPEN CASCADE SAS
+// Created on: 2013-11-11
+// Created by: Anastasia BORISOVA
+// Copyright (c) 2013 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
@@ -16,8 +17,8 @@
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-#ifndef _AIS_Dimension_Headerfile
-#define _AIS_Dimension_Headerfile
+#ifndef _AIS_Dimension_HeaderFile
+#define _AIS_Dimension_HeaderFile
 
 #include <AIS_DimensionSelectionMode.hxx>
 #include <AIS_DimensionOwner.hxx>
 #include <AIS_KindOfInteractive.hxx>
 #include <AIS_KindOfDimension.hxx>
 #include <AIS_KindOfSurface.hxx>
-#include <Bnd_Box.hxx>
+#include <AIS_Drawer.hxx>
 #include <Geom_Curve.hxx>
 #include <gp_Pln.hxx>
 #include <Prs3d_ArrowAspect.hxx>
 #include <Prs3d_DimensionAspect.hxx>
+#include <Prs3d_DimensionUnits.hxx>
 #include <Prs3d_LineAspect.hxx>
 #include <Prs3d_Presentation.hxx>
 #include <Prs3d_TextAspect.hxx>
 
 DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 
+//! AIS_Dimension is a base class for 2D presentations of linear (length, diameter, radius)
+//! and angular dimensions.
+//!
+//! The dimensions provide measurement of quantities, such as lengths or plane angles.
+//! The measurement of dimension "value" is done in model space "as is".
+//! These "value" are said to be represented in "model units", which can be specified by user.
+//! During the display the measured value converted from "model units" to "display units".
+//! The display and model units are stored in common Prs3d_Drawer (drawer of the context)
+//! to share it between all dimensions.
+//! The specified by user units are stored in the dimension's drawer.
+//!
+//! As a drawing, the dimension is composed from the following components:
+//! - Attachement (binding) points. The points where the dimension lines attaches to, for
+//!   length dimensions the distances are measured between these points.
+//! - Main dimension line. The which extends from the attachement points in "up" direction,
+//!   and which contains text label on it with value string.
+//! - Flyouts. The lines connecting the attachement points with main dimension line.
+//! - Extension. The lines used to extend the main dimension line in the cases when text
+//!   or arrows do not fit into the main dimension line due to their size.
+//! - Arrows.
+//!
+//! <pre>
+//!  Linear dimensions:
+//!
+//!  extension
+//!   line                                     arrow
+//!       -->|------- main dimension line -------|<--
+//!          |                                   |
+//!          |flyout                       flyout|
+//!          |                                   |
+//!          +-----------------------------------+
+//! attachement                                attachement
+//!  point                                       point
+//!
+//!  Angular dimensions:
+//!
+//!                  extension
+//!                     line
+//!                        -->|+++++
+//!                     arrow |     +++
+//!                           |        90(deg) - main dimension line
+//!                    flyout |         +++
+//!                           |           +
+//!                           o---flyout---
+//!                         center         ^ 
+//!                         point          | extension
+//!                                          line
+//! </pre>
+//!
+//! Being a 2D drawings, the dimensions are created on imaginary plane, called "dimension plane",
+//! which can be thought of as reference system of axes (X,Y,N) for constructing the presentation.
+//!
+//! The role of axes of the dimension plane is to guide you through the encapsualted automations
+//! of presentation building to help you understand how is the presentation will look and how it
+//! will be oriented in model space during construction.
+//! 
+//! Orientation of dimension line in model space relatively to the base shapes is defined 
+//! with the flyouts. Flyouts specify length of flyout lines and their orientation relatively
+//! to the attachment points on the working plane.
+//! For linear dimensions: 
+//!   Direction of flyouts is specified with direction of main dimension line
+//!   (vector from the first attachment to the second attachment) and the normal of the dimension plane.
+//!   Positive direction of flyouts is defined by vector multiplication: AttachVector * PlaneNormal.
+//! For angular dimensions:
+//!   Flyouts are defined by vectors from the center point to the attachment points.
+//!   These vectors directions are supposed to be the positive directions of flyouts.
+//!   Negative flyouts directions means that these vectors should be reversed
+//!   (and dimension will be built out of the angle constructed with center and two attach points).
+//!
+//! The dimension plane can be constructed automatically by application (where possible,
+//! it depends on the measured geometry).
+//! It can be also set by user. However, if the user-defined plane does not fit the
+//! geometry of the dimension (attach points do not belong to it), the dimension could not
+//! be built.
+//! If it is not possible to compute automatic plane (for example, in case of length between 
+//! two points) the user is supposed to specify the custom plane.
+//!
+//! Since the dimensions feature automated construction procedures from an arbitrary shapes,
+//! the interfaces to check the validness are also implemented. Once the measured geometry is
+//! specified, the one can inquire the validness status by calling "IsValid()" method. If the result
+//! is TRUE, then all of public parameters should be pre-computed and ready. The presentation
+//! should be also computable. Otherwise, the parameters may return invalid values. In this case,
+//! the presentation will not be computed and displayed.
+//! 
+//! The dimension support two local selection modes: main dimension line selection and text label
+//! selection. These modes can be used to develop interactive modification of dimension presentations.
+//! The component hilighting in these selection modes is provided by AIS_DimensionOwner class.
+//! Please note that selection is unavailable until the presentation is computed.
+//! 
+//! The specific drawing attributes are controlled through Prs3d_DimensionAspect. The one can change
+//! color, arrows, text and arrow style and specify positioning of value label by setting corresponding
+//! values to the aspect.
+//!
 class AIS_Dimension : public AIS_InteractiveObject
 {
 protected:
 
-  // Specifies supported at base level horizontal and vertical
-  // label positions for drawing extension lines and centered text.
+  //! Geometry type defines type of shapes on which the dimension is to be built.
+  //! Some type of geometry allows automatical plane computing and
+  //! can be built without user-defined plane
+  //! Another types can't be built without user-defined plane.
+  enum GeometryType
+  {
+    GeometryType_UndefShapes,
+    GeometryType_Edge,
+    GeometryType_Face,
+    GeometryType_Points,
+    GeometryType_Edges,
+    GeometryType_Faces,
+    GeometryType_EdgeFace,
+    GeometryType_EdgeVertex
+  };
+
+  //! Specifies supported at base level horizontal and vertical
+  //! label positions for drawing extension lines and centered text.
   enum LabelPosition
   {
     LabelPosition_None    = 0x00,
@@ -59,12 +170,12 @@ protected:
     LabelPosition_Left    = 0x01,
     LabelPosition_Right   = 0x02,
     LabelPosition_HCenter = 0x04,
-    LabelPosition_HMask  = LabelPosition_Left | LabelPosition_Right | LabelPosition_HCenter,
+    LabelPosition_HMask   = LabelPosition_Left | LabelPosition_Right | LabelPosition_HCenter,
 
     LabelPosition_Above   = 0x10,
     LabelPosition_Below   = 0x20,
     LabelPosition_VCenter = 0x40,
-    LabelPosition_VMask  = LabelPosition_Above | LabelPosition_Below | LabelPosition_VCenter
+    LabelPosition_VMask   = LabelPosition_Above | LabelPosition_Below | LabelPosition_VCenter
   };
 
 public:
@@ -81,128 +192,144 @@ public:
 
 public:
 
-  //! Constructor with default parameters values
-  Standard_EXPORT  AIS_Dimension();
-
-  //! Gets dimension value
-  Standard_EXPORT  Standard_Real GetValue() const;
-
-  //! Sets dimension value
-  //! Attention! This method is used ONLY to set custom value.
-  //! To set value internally, use <myValue>.
-  Standard_EXPORT  void SetCustomValue (const Standard_Real theValue);
+  //! Constructor with default parameters values.
+  //! @param theType [in] the type of dimension.
+  Standard_EXPORT AIS_Dimension (const AIS_KindOfDimension theType);
 
-  //! Gets working plane.
-  Standard_EXPORT  const gp_Pln& GetWorkingPlane() const;
-
-  //! Sets working plane.
-  Standard_EXPORT  void SetWorkingPlane (const gp_Pln& thePlane);
-
-  Standard_EXPORT  void SetFirstPoint (const gp_Pnt& thePoint);
-
-  Standard_EXPORT  void SetSecondPoint (const gp_Pnt& thePoint);
+  //! Gets dimension measurement value. If the value to display is not
+  //! specified by user, then the dimension object is responsible to
+  //! compute it on its own in model space coordinates.
+  //! @return the dimension value (in model units) which is used
+  //! during display of the presentation.
+  Standard_Real GetValue() const
+  {
+    return myIsValueCustom ? myCustomValue : ComputeValue();
+  }
 
-  Standard_EXPORT  void SetFirstShape (const TopoDS_Shape& theFirstShape);
+  //! Sets user-defined dimension value.
+  //! The user-defined dimension value is specified in model space,
+  //! and affect by unit conversion during the display.
+  //! @param theValue [in] the user-defined value to display.
+  Standard_EXPORT void SetCustomValue (const Standard_Real theValue);
+
+  //! Get the dimension plane in which the 2D dimension presentation is computed.
+  //! By default, if plane is not defined by user, it is computed automatically
+  //! after dimension geometry is computed.
+  //! If computed dimension geometry (points) can't be placed on the user-defined
+  //! plane, dimension geometry was set as unvalid (validity flag is set to false)
+  //! and dimension presentation wil not be computed.
+  //! If user-defined plane allow geometry placement on it, it will be used for
+  //! computing of the dimension presentation.
+  //! @return dimension plane used for presentation computing.
+  Standard_EXPORT const gp_Pln& GetPlane() const;
+
+  //! Geometry type defines type of shapes on which the dimension is to be built. 
+  //! @return type of geometry on which the dimension will be built.
+  Standard_EXPORT const Standard_Integer GetGeometryType () const;
+
+  //! Sets user-defined plane where the 2D dimension presentation will be placed.
+  //! Checks validity of this plane if geometry has been set already.
+  //! Validity of the plane is checked according to the geometry set
+  //! and has different criteria for different kinds of dimensions.
+  Standard_EXPORT virtual void SetCustomPlane (const gp_Pln& thePlane);
+
+  //! Unsets user-defined plane. Therefore the plane for dimension will be
+  //! computed automatically.
+  Standard_EXPORT void UnsetCustomPlane() { myIsPlaneCustom = Standard_False; }
 
-  Standard_EXPORT  void SetSecondShape (const TopoDS_Shape& theSecondShape);
+public:
 
   //! Gets the dimension aspect from AIS object drawer.
   //! Dimension aspect contains aspects of line, text and arrows for dimension presentation.
-  Standard_EXPORT   Handle(Prs3d_DimensionAspect) DimensionAspect() const;
-
-  //! Sets new length aspect in the interactive object drawer.
-  Standard_EXPORT   void SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect);
+  Handle(Prs3d_DimensionAspect) DimensionAspect() const
+  {
+    return myDrawer->DimensionAspect();
+  }
 
-  //! Returns the kind of dimension
-  Standard_EXPORT  AIS_KindOfDimension KindOfDimension() const;
+  //! Sets new dimension aspect for the interactive object drawer.
+  //! The dimension aspect provides dynamic properties which are generally
+  //! used during computation of dimension presentations.
+  Standard_EXPORT void SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect);
 
-  //! Returns the kind of interactive
-  Standard_EXPORT  virtual  AIS_KindOfInteractive Type() const;
+  //! @return the kind of dimension.
+  AIS_KindOfDimension KindOfDimension() const
+  {
+    return myKindOfDimension;
+  }
 
-  //! Sets the kind of dimension
-  Standard_EXPORT  virtual void SetKindOfDimension (const AIS_KindOfDimension theKindOfDimension);
+  //! @return the kind of interactive.
+  virtual AIS_KindOfInteractive Type() const
+  {
+    return AIS_KOI_Relation;
+  }
 
   //! Returns true if the class of objects accepts the display mode theMode.
-  //! The interactive context can have a default mode of
-  //! representation for the set of Interactive Objects. This
-  //! mode may not be accepted by object
-  Standard_EXPORT   virtual  Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const;
-
-  // Selection computing if it is needed here
-  Standard_EXPORT   virtual  void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
-                                                    const Standard_Integer theMode);
-
-  //! Reset working plane to default.
-  Standard_EXPORT  void ResetWorkingPlane();
-
-  //! specifies dimension special symbol display options
-  Standard_EXPORT  void SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol);
-
-  //! shows dimension special symbol display options
-  Standard_EXPORT  AIS_DisplaySpecialSymbol DisplaySpecialSymbol() const;
-
-  //! specifies special symbol
-  Standard_EXPORT  void SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol);
+  //! The interactive context can have a default mode of representation for
+  //! the set of Interactive Objects. This mode may not be accepted by object.
+  virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const
+  {
+    return theMode == ComputeMode_All;
+  }
 
-  //! returns special symbol
-  Standard_EXPORT  Standard_ExtCharacter SpecialSymbol() const;
+public:
 
-  //! shows if Units are to be displayed along with dimension value
-  Standard_EXPORT  Standard_Boolean IsUnitsDisplayed() const;
+  //! @return dimension special symbol display options.
+  AIS_DisplaySpecialSymbol DisplaySpecialSymbol() const
+  {
+    return myDisplaySpecialSymbol;
+  }
 
-  //! sets to display units along with the dimension value or no
-  Standard_EXPORT  void MakeUnitsDisplayed (const Standard_Boolean toDisplayUnits);
+  //! Specifies whether to display special symbol or not.
+  Standard_EXPORT void SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol);
 
-  //! returns the current type of units
-  Standard_EXPORT  TCollection_AsciiString UnitsQuantity() const;
+  //! @return special symbol.
+  Standard_ExtCharacter SpecialSymbol() const
+  {
+    return mySpecialSymbol;
+  }
 
-  //! sets the current type of units
-  Standard_EXPORT  void SetUnitsQuantity (const TCollection_AsciiString& theUnitsQuantity);
+  //! Specifies special symbol.
+  Standard_EXPORT void SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol);
 
-  //! returns the current model units
-  Standard_EXPORT  TCollection_AsciiString ModelUnits() const;
+  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const;
 
-  //! sets the current model units
-  Standard_EXPORT  void SetModelUnits (const TCollection_AsciiString& theUnits);
+  Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits() const;
 
-  //! returns the current display units
-  Standard_EXPORT  TCollection_AsciiString DisplayUnits() const;
+  Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& /*theUnits*/) { }
 
-  //! sets the current display units
-  Standard_EXPORT  void SetDisplayUnits (const TCollection_AsciiString& theUnits);
+  Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& /*theUnits*/) { }
 
-  //! Important! Only for 3d text </br>
-  //! 3d text is oriented relative to the attachment points order </br>
-  //! By default, text direction vector is oriented from the first attachment point </br>
-  //! to the second one. This method checks if text direction is to be default or </br>
-  //! should be reversed.
-  Standard_EXPORT  Standard_Boolean IsTextReversed() const;
+public:
 
-  //! Important! Only for 3d text
-  //! 3d text is oriented relative to the attachment points order </br>
-  //! By default, text direction vector is oriented from the first attachment point </br>
-  //! to the second one. This method sets value that shows if text direction </br>
-  //! should be reversed or not.
-  Standard_EXPORT  void MakeTextReversed (const Standard_Boolean isTextReversed);
+  //! Returns selection tolerance for text2d:
+  //! For 2d text selection detection sensitive point with tolerance is used
+  //! Important! Only for 2d text.
+  Standard_Real SelToleranceForText2d() const
+  {
+    return mySelToleranceForText2d;
+  }
 
   //! Sets selection tolerance for text2d:
   //! For 2d text selection detection sensitive point with tolerance is used
   //! to change this tolerance use this method
-  //! Important! Only for 2d text
-  Standard_EXPORT  void SetSelToleranceForText2d (const Standard_Real theTol);
+  //! Important! Only for 2d text.
+  Standard_EXPORT void SetSelToleranceForText2d (const Standard_Real theTol);
 
-  //! Returns selection tolerance for text2d:
-  //! For 2d text selection detection sensitive point with tolerance is used
-  //! Important! Only for 2d text
-  Standard_EXPORT  Standard_Real SelToleranceForText2d() const;
+  //! @return flyout value for dimension.
+  Standard_Real GetFlyout() const
+  {
+    return myFlyout;
+  }
 
-  //! Sets flyout size for dimension.
+  //! Sets flyout value for dimension.
   Standard_EXPORT void SetFlyout (const Standard_Real theFlyout);
 
-  //! @return flyout size for dimension.
-  Standard_Real GetFlyout() const
+  //! Check that the input geometry for dimension is valid and the
+  //! presentation can be succesfully computed.
+  //! @return TRUE if dimension geometry is ok.
+  Standard_Boolean IsValid() const
   {
-    return myFlyout;
+    return myIsValid;
   }
 
 public:
@@ -211,28 +338,28 @@ public:
 
 protected:
 
-  Standard_EXPORT void getTextWidthAndString (Quantity_Length& theWidth,
-                                              TCollection_ExtendedString& theString) const;
-
-  Standard_EXPORT Standard_Real valueToDisplayUnits();
-
-  //! Reset working plane to default.
-  Standard_EXPORT void resetWorkingPlane (const gp_Pln& theNewDefaultPlane);
+  Standard_EXPORT Standard_Real ValueToDisplayUnits() const;
 
-  //! Count default plane 
-  Standard_EXPORT virtual void countDefaultPlane();
-
-  //! Computes dimension value in display units
-  Standard_EXPORT virtual void computeValue();
+  //! Get formatted value string and its model space width.
+  //! @param theWidth [out] the model space with of the string.
+  //! @return formatted dimension value string.
+  Standard_EXPORT TCollection_ExtendedString GetValueString (Standard_Real& theWidth) const;
 
   //! Performs drawing of 2d or 3d arrows on the working plane
-  Standard_EXPORT void drawArrow (const Handle(Prs3d_Presentation)& thePresentation,
+  //! @param theLocation [in] the location of the arrow tip.
+  //! @param theDirection [in] the direction from the tip to the bottom of the arrow.
+  Standard_EXPORT void DrawArrow (const Handle(Prs3d_Presentation)& thePresentation,
                                   const gp_Pnt& theLocation,
                                   const gp_Dir& theDirection);
 
   //! Performs drawing of 2d or 3d text on the working plane
+  //! @param theTextPos [in] the position of the text label.
+  //! @param theTestDir [in] the direction of the text label.
+  //! @param theText [in] the text label string.
+  //! @param theLabelPosition [in] the text label vertical and horizontal positioning option
+  //! respectively to the main dimension line. 
   //! @return text width relative to the dimension working plane. For 2d text this value will be zero.
-  Standard_EXPORT void drawText (const Handle(Prs3d_Presentation)& thePresentation,
+  Standard_EXPORT void DrawText (const Handle(Prs3d_Presentation)& thePresentation,
                                  const gp_Pnt& theTextPos,
                                  const gp_Dir& theTextDir,
                                  const TCollection_ExtendedString& theText,
@@ -247,7 +374,7 @@ protected:
   //! @param theLabelWidth [in] the geometrical width computed for value string.
   //! @param theMode [in] the display mode.
   //! @param theLabelPosition [in] position flags for the text label.
-  Standard_EXPORT void drawExtension (const Handle(Prs3d_Presentation)& thePresentation,
+  Standard_EXPORT void DrawExtension (const Handle(Prs3d_Presentation)& thePresentation,
                                       const Standard_Real theExtensionSize,
                                       const gp_Pnt& theExtensionStart,
                                       const gp_Dir& theExtensionDir,
@@ -256,32 +383,81 @@ protected:
                                       const Standard_Integer theMode,
                                       const Standard_Integer theLabelPosition);
 
-  //! Performs computing of linear dimension (for length, diameter, radius and so on)
-  Standard_EXPORT void drawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
+  //! Performs computing of linear dimension (for length, diameter, radius and so on).
+  //! Please note that this method uses base dimension properties, like working plane
+  //! flyout length, drawer attributes.
+  //! @param thePresentation [in] the presentation to fill with primitives.
+  //! @param theMode [in] the presentation compute mode.
+  //! @param theFirstPoint [in] the first attach point of linear dimension.
+  //! @param theSecondPoint [in] the second attach point of linear dimension.
+  //! @param theIsOneSide [in] specifies whether the dimension has only one flyout line.
+  Standard_EXPORT void DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
                                             const Standard_Integer theMode,
-                                            const Standard_Boolean isOneSideDimension = Standard_False);
-
-  //! If it's possible computes circle from planar face
-  Standard_EXPORT  Standard_Boolean circleFromPlanarFace (const TopoDS_Face& theFace,
+                                            const gp_Pnt& theFirstPoint,
+                                            const gp_Pnt& theSecondPoint,
+                                            const Standard_Boolean theIsOneSide = Standard_False);
+
+  //! Compute selection sensitives for linear dimension flyout lines (length, diameter, radius).
+  //! Please note that this method uses base dimension properties: working plane and flyout length.
+  //! @param theSelection [in] the selection structure to fill with selection primitives.
+  //! @param theOwner [in] the selection entity owner.
+  //! @param theFirstPoint [in] the first attach point of linear dimension.
+  //! @param theSecondPoint [in] the second attach point of linear dimension.
+  Standard_EXPORT void ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection,
+                                             const Handle(SelectMgr_EntityOwner)& theOwner,
+                                             const gp_Pnt& theFirstPoint,
+                                             const gp_Pnt& theSecondPoint);
+
+  //! If it is possible extracts circle from planar face.
+  //! @param theFace [in] the planar face.
+  //! @param theCurve [out] the circular curve.
+  //! @param theFirstPoint [out] the point of the first parameter of the circlular curve.
+  //! @param theSecondPoint [out] the point of the last parameter of the circlular curve.
+  //! @return TRUE in case of successful circle extraction.
+  Standard_EXPORT  Standard_Boolean CircleFromPlanarFace (const TopoDS_Face& theFace,
                                                           Handle(Geom_Curve)& theCurve,
-                                                          gp_Pnt & theFirstPoint,
-                                                          gp_Pnt & theLastPoint);
-
-  //! Performs initialization of circle and points from given shape
-  //! (for radius, diameter and so on)
-  Standard_EXPORT  Standard_Boolean initCircularDimension (const TopoDS_Shape& theShape,
-                                                           gp_Circ& theCircle,
-                                                           gp_Pnt& theMiddleArcPoint,
-                                                           gp_Pnt& theOppositeDiameterPoint);
-  Standard_EXPORT Standard_Boolean isComputed() const;
-
-  Standard_EXPORT void setComputed (Standard_Boolean isComputed);
-
-  Standard_EXPORT void resetGeom();
+                                                          gp_Pnt& theFirstPoint,
+                                                          gp_Pnt& theLastPoint);
+
+  //! Performs initialization of circle and middle arc point from the passed
+  //! shape which is assumed to contain circular geometry.
+  //! @param theShape [in] the shape to explore.
+  //! @param theCircle [out] the circle geometry.
+  //! @param theMiddleArcPoint [out] the middle point of the arc.
+  //! @param theIsClosed [out] returns TRUE if the geometry is closed circle.
+  //! @return TRUE if the the circle is successfully got from the input shape.
+  Standard_EXPORT Standard_Boolean InitCircularDimension (const TopoDS_Shape& theShape,
+                                                          gp_Circ& theCircle,
+                                                          gp_Pnt& theMiddleArcPoint,
+                                                          Standard_Boolean& theIsClosed);
+
+protected: //! @name Behavior to implement
+
+  //! Override this method to compute automatically dimension plane
+  //! in which the dimension presentation is built.
+  virtual void ComputePlane() { }
+
+  //! Override this method to check if user-defined plane
+  //! is valid for the dimension geometry.
+  //! @param thePlane [in] the working plane for positioning every
+  //! dimension in the application.
+  //! @return true is the plane is suitable for building dimension
+  //! with computed dimension geometry.
+  virtual Standard_Boolean CheckPlane (const gp_Pln& /*thePlane*/) const { return Standard_True; }
+
+  //! Override this method to computed value of dimension.
+  //! @return value from the measured geometry.
+  virtual Standard_Real ComputeValue() const 
+  {
+    return 0.0;
+  }
 
-  //! Fills sensitive entity for flyouts and adds it to the selection.
-  Standard_EXPORT virtual void computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
-                                                       const Handle(SelectMgr_EntityOwner)& theOwner);
+  //! Override this method to compute selection primitives for
+  //! flyout lines (if the dimension provides it).
+  //! This callback is a only a part of base selection
+  //! computation routine.
+  virtual void ComputeFlyoutSelection (const Handle(SelectMgr_Selection)&,
+                                       const Handle(SelectMgr_EntityOwner)&) {}
 
   //! Produce points for triangular arrow face.
   //! @param thePeakPnt [in] the arrow peak position.
@@ -300,41 +476,11 @@ protected:
                                        gp_Pnt& theSidePnt1,
                                        gp_Pnt& theSidePnt2);
 
-protected: //! @name Working plane properties
-
-  //! Dimension default plane
-  gp_Pln myDefaultPlane;
-
-  //! Shows if working plane is set custom
-  Standard_Boolean myIsWorkingPlaneCustom;
-
-protected: //! @name Value properties
-
-  //! Dimension value which is displayed with dimension lines
-  Standard_Real myValue;
-
-  //! Shows if the value is set by user and is no need to count it automatically
-  Standard_Boolean myIsValueCustom;
-
-protected: // !@name Units properties
-
-  //! The quantity of units for the value computation
-  TCollection_AsciiString myUnitsQuantity;
-
-  //! Units of the model
-  TCollection_AsciiString myModelUnits;
-
-  //! Units in which the displayed value will be converted
-  TCollection_AsciiString myDisplayUnits;
-
-  //! Determines if units is to be displayed along with the value
-  Standard_Boolean myToDisplayUnits;
-
-  //! Special symbol for some kind of dimensions (for diameter, radius and so on)
-  Standard_ExtCharacter mySpecialSymbol;
-
-  //! Special symbol display options
-  AIS_DisplaySpecialSymbol myDisplaySpecialSymbol;
+  //! Base procedure of computing selection (based on selection geometry data).
+  //! @param theSelection [in] the selection structure to will with primitives.
+  //! @param theMode [in] the selection mode.
+  Standard_EXPORT virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
+                                                 const Standard_Integer theMode);
 
 protected: //! @name Selection geometry
 
@@ -403,43 +549,28 @@ protected: //! @name Selection geometry
   Standard_Real mySelToleranceForText2d; //!< Sensitive point tolerance for 2d text selection.
   Standard_Boolean myIsComputed;         //!< Shows if the presentation and selection was computed.
 
-protected:
-
-  //! Shows if text is inverted
-  Standard_Boolean myIsTextReversed;
-
-  //! Points that are base for dimension.
-  //! My first point of dimension attach (belongs to shape for which dimension is computed)
-  gp_Pnt myFirstPoint;
+protected: //! @name Value properties
 
-  //! My second point of dimension attach (belongs to shape for which dimension is computed)
-  gp_Pnt mySecondPoint;
+  Standard_Real    myCustomValue;   //!< Value of the dimension (computed or user-defined).
+  Standard_Boolean myIsValueCustom; //!< Is user-defined value.
 
-  //! Shows if attach points are initialized correctly
-  Standard_Boolean myIsInitialized;
+protected: //! @name Units properties
 
-  //! First shape (can be vertex, edge or face)
-  TopoDS_Shape myFirstShape;
+  Standard_ExtCharacter    mySpecialSymbol;        //!< Special symbol.
+  AIS_DisplaySpecialSymbol myDisplaySpecialSymbol; //!< Special symbol display options.
 
-  //! Second shape (can be vertex, edge or face)
-  TopoDS_Shape mySecondShape;
+protected: //! @name Geometrical properties
 
-  //! Number of shapes
-  Standard_Integer myShapesNumber;
+  GeometryType myGeometryType;  //!< defines type of shapes on which the dimension is to be built. 
 
-  //! Defines flyout lines and direction
-  //! Flyout direction in the working plane.
-  //! Can be negative, or positive and is defined by the sign of myFlyout value.
-  //! The direction vector is counting using the working plane.
-  //! myFlyout value defined the size of flyout.
-  Standard_Real myFlyout;
+  gp_Pln           myPlane;       //!< Plane where dimension will be built (computed or user defined).
+  Standard_Boolean myIsPlaneCustom; //!< Is plane defined by user (otherwise it will be computed automatically).
+  Standard_Real    myFlyout;      //!< Flyout distance.
+  Standard_Boolean myIsValid;     //!< Is dimension geometry properly defined.
 
 private:
 
-  //! Type of dimension
   AIS_KindOfDimension myKindOfDimension;
-
-  //! Dimension working plane, is equal to <myDefaultPlane> if it can be computed automatically.
-  gp_Pln myWorkingPlane;
 };
-#endif
+
+#endif // _AIS_Dimension_HeaderFile
index 0a947c4..2a85663 100755 (executable)
@@ -64,7 +64,10 @@ uses
     NameOfColor from Quantity,
     PlaneAngle from Quantity,
     Length from Quantity,
-    TypeOfHLR from Prs3d
+    DimensionUnits from Prs3d,
+    AsciiString from TCollection,
+    TypeOfHLR from Prs3d,
+    Ax2 from gp
 
 is
     Create returns mutable Drawer from AIS;
@@ -542,16 +545,42 @@ is
 --  Attributes for the presentation of a dimensions.
 --  
 
-    DimensionAspect(me:mutable) returns mutable DimensionAspect from Prs3d
+    DimensionAspect (me : mutable) returns mutable DimensionAspect from Prs3d is redefined static;
     ---Purpose: Returns a link with Prs3d_Drawer_DimensionAspect,
--- which provides settings for the appearance of dimensions.
-    is redefined static;
+    -- which provides settings for the appearance of dimensions.
+
+    HasDimensionAspect (me) returns Boolean from Standard is static;
+    ---C++: inline
+    -- Purpose: Returns true if the Drawer has a dimension aspect setting active.
+
+    SetDimLengthModelUnits (me: mutable; theUnits : AsciiString from TCollection) is redefined static;
+    ---Purpose: Sets dimension length model units for computing of dimension presentation.
+
+    SetDimAngleModelUnits (me: mutable; theUnits : AsciiString from TCollection) is redefined static;
+    ---Purpose: Sets dimension angle model units for computing of dimension presentation.
+
+    DimAngleModelUnits (me) returns AsciiString from TCollection is redefined static;
+    ---Purpose: Returns angle model units for the dimension presentation.
+    ---C++: return const &
+
+    DimLengthModelUnits (me) returns AsciiString from TCollection is redefined static;
+    ---Purpose: Returns length model units for the dimension presentation.
+    ---C++: return const &
+
+    SetDimLengthDisplayUnits (me: mutable; theUnits : AsciiString from TCollection) is redefined static;
+    ---Purpose: Sets length units in which value for dimension presentation is displayed.
+
+    SetDimAngleDisplayUnits (me: mutable; theUnits : AsciiString from TCollection) is redefined static;
+    ---Purpose: Sets angle units in which value for dimension presentation is displayed.
+
+    DimLengthDisplayUnits (me) returns AsciiString from TCollection is redefined static;
+    ---Purpose: Returns length units in which dimension presentation is displayed.
+    ---C++: return const &
+
+    DimAngleDisplayUnits (me) returns AsciiString from TCollection is redefined static;
+    ---Purpose: Returns angle units in which dimension presentation is displayed.
+    ---C++: return const &
 
-    HasDimensionAspect (me) returns Boolean from Standard
-        ---C++: inline 
-       ---Purpose: Returns true if the Drawer has a dimension aspect setting active.
-    is static;      
-     
 -- Attributes for the sections
 
     SectionAspect (me:mutable) returns mutable LineAspect from Prs3d
@@ -593,25 +622,32 @@ is
        -- for Interactive Objects.
 
 fields
+
     myLink                           : Drawer from Prs3d;
     hasLocalAttributes               : Boolean from Standard;          
-    
+
     myhasOwnDeviationCoefficient     : Boolean from Standard;
     myOwnDeviationCoefficient        : Real from Standard;
     myPreviousDeviationCoefficient   : Real from Standard;
-    
+
     myhasOwnHLRDeviationCoefficient  : Boolean from Standard;
     myOwnHLRDeviationCoefficient     : Real from Standard;
     myPreviousHLRDeviationCoefficient: Real from Standard;
-    
+
     myhasOwnDeviationAngle           : Boolean from Standard;
     myOwnDeviationAngle              : Real from Standard;
     myPreviousDeviationAngle         : Real from Standard;
-    
+
     myhasOwnHLRDeviationAngle        : Boolean from Standard;
     myOwnHLRDeviationAngle           : Real from Standard; 
     myPreviousHLRDeviationAngle      : Real from Standard;
     myHasOwnFaceBoundaryDraw         : Boolean from Standard;
+
+    myHasOwnDimLengthModelUnits      : Boolean from Standard;
+    myHasOwnDimLengthDisplayUnits    : Boolean from Standard;
+    myHasOwnDimAngleModelUnits      : Boolean from Standard;
+    myHasOwnDimAngleDisplayUnits    : Boolean from Standard;
+
 end Drawer;
  
 
index 6404e50..709f996 100755 (executable)
 #include <AIS_Drawer.ixx>
 #include <Standard_ProgramError.hxx>
 
-AIS_Drawer::AIS_Drawer(): 
-myLink(new Prs3d_Drawer()),
-hasLocalAttributes(Standard_False),
-myhasOwnDeviationCoefficient(Standard_False),
-myPreviousDeviationCoefficient(0.1),
-myhasOwnHLRDeviationCoefficient (Standard_False),
-myhasOwnDeviationAngle (Standard_False),
-myhasOwnHLRDeviationAngle (Standard_False),
-myHasOwnFaceBoundaryDraw (Standard_False)
+// =======================================================================
+// function : AIS_Drawer
+// purpose  :
+// =======================================================================
+AIS_Drawer::AIS_Drawer()
+: myLink (new Prs3d_Drawer()),
+  hasLocalAttributes (Standard_False),
+  myhasOwnDeviationCoefficient (Standard_False),
+  myPreviousDeviationCoefficient (0.1),
+  myhasOwnHLRDeviationCoefficient (Standard_False),
+  myhasOwnDeviationAngle (Standard_False),
+  myhasOwnHLRDeviationAngle (Standard_False),
+  myHasOwnFaceBoundaryDraw (Standard_False)
 {
-  SetMaximalParameterValue(500000.);
-  myLink->SetMaximalParameterValue(500000.);
+  SetMaximalParameterValue (500000.0);
+  myLink->SetMaximalParameterValue (500000.0);
   SetTypeOfHLR (Prs3d_TOH_NotSet);
-} 
-
+}
 
 Aspect_TypeOfDeflection AIS_Drawer::TypeOfDeflection () const 
 {
@@ -216,8 +219,97 @@ Handle (Prs3d_DatumAspect) AIS_Drawer::DatumAspect ()
 Handle (Prs3d_PlaneAspect) AIS_Drawer::PlaneAspect () 
 {return myPlaneAspect.IsNull() ? myLink->PlaneAspect (): myPlaneAspect;}
 
-Handle (Prs3d_DimensionAspect) AIS_Drawer::DimensionAspect ()  
-{return myDimensionAspect.IsNull()? myLink->DimensionAspect () : myDimensionAspect ;}
+// =======================================================================
+// function : DimensionAspect
+// purpose  :
+// =======================================================================
+Handle (Prs3d_DimensionAspect) AIS_Drawer::DimensionAspect()
+{
+  return myDimensionAspect.IsNull()? myLink->DimensionAspect () : myDimensionAspect;
+}
+
+// =======================================================================
+// function : DimAngleModelUnits
+// purpose  :
+// =======================================================================
+const TCollection_AsciiString& AIS_Drawer::DimAngleModelUnits() const
+{
+  return myHasOwnDimAngleModelUnits
+    ? Prs3d_Drawer::DimAngleModelUnits()
+    : myLink->DimAngleModelUnits();
+}
+
+// =======================================================================
+// function : DimensionModelUnits
+// purpose  :
+// =======================================================================
+const TCollection_AsciiString& AIS_Drawer::DimLengthModelUnits() const
+{
+  return myHasOwnDimLengthModelUnits
+    ? Prs3d_Drawer::DimLengthModelUnits()
+    : myLink->DimLengthModelUnits();
+}
+// =======================================================================
+// function : SetDimLengthModelUnits
+// purpose  :
+// =======================================================================
+void AIS_Drawer::SetDimLengthModelUnits (const TCollection_AsciiString& theUnits)
+{
+  myHasOwnDimLengthModelUnits = Standard_True;
+  Prs3d_Drawer::SetDimLengthDisplayUnits (theUnits);
+}
+
+// =======================================================================
+// function : SetDimAngleModelUnits
+// purpose  :
+// =======================================================================
+void AIS_Drawer::SetDimAngleModelUnits (const TCollection_AsciiString& theUnits)
+{
+  myHasOwnDimAngleModelUnits = Standard_True;
+  Prs3d_Drawer::SetDimAngleDisplayUnits (theUnits);
+}
+
+// =======================================================================
+// function : DimAngleDisplayUnits
+// purpose  :
+// =======================================================================
+const TCollection_AsciiString& AIS_Drawer::DimAngleDisplayUnits() const
+{
+  return myHasOwnDimAngleDisplayUnits
+    ? Prs3d_Drawer::DimAngleDisplayUnits()
+    : myLink->DimAngleDisplayUnits();
+}
+
+// =======================================================================
+// function : DimLengthDisplayUnits
+// purpose  :
+// =======================================================================
+const TCollection_AsciiString& AIS_Drawer::DimLengthDisplayUnits() const
+{
+  return myHasOwnDimLengthDisplayUnits
+    ? Prs3d_Drawer::DimLengthDisplayUnits()
+    : myLink->DimLengthDisplayUnits();
+}
+
+// =======================================================================
+// function : SetDimLengthDisplayUnits
+// purpose  :
+// =======================================================================
+void AIS_Drawer::SetDimLengthDisplayUnits (const TCollection_AsciiString& theUnits)
+{
+  myHasOwnDimLengthDisplayUnits = Standard_True;
+  Prs3d_Drawer::SetDimLengthDisplayUnits (theUnits);
+}
+
+// =======================================================================
+// function : SetDimAngleDisplayUnits
+// purpose  :
+// =======================================================================
+void AIS_Drawer::SetDimAngleDisplayUnits (const TCollection_AsciiString& theUnits)
+{
+  myHasOwnDimAngleDisplayUnits = Standard_True;
+  Prs3d_Drawer::SetDimAngleDisplayUnits (theUnits);
+}
 
 Handle (Prs3d_LineAspect) AIS_Drawer::SectionAspect ()
 {return mySectionAspect.IsNull()? myLink->SectionAspect (): mySectionAspect;}
@@ -256,6 +348,10 @@ void AIS_Drawer::ClearLocalAttributes()
   if (!myFaceBoundaryAspect.IsNull()) myFaceBoundaryAspect.Nullify();
   
   myHasOwnFaceBoundaryDraw = Standard_False;
+  myHasOwnDimLengthModelUnits = Standard_False;
+  myHasOwnDimLengthDisplayUnits = Standard_False;
+  myHasOwnDimAngleModelUnits = Standard_False;
+  myHasOwnDimAngleDisplayUnits = Standard_False;
 
   hasLocalAttributes = Standard_False;
 
index e488ce2..445d081 100755 (executable)
@@ -104,5 +104,7 @@ inline Prs3d_TypeOfHLR AIS_Drawer::TypeOfHLR ( ) const
   return (myTypeOfHLR == Prs3d_TOH_NotSet) ? myLink->TypeOfHLR() : myTypeOfHLR;
 }
 
-inline Standard_Boolean AIS_Drawer::HasDimensionAspect ()  const 
-{ return !myDimensionAspect.IsNull();}
+inline Standard_Boolean AIS_Drawer::HasDimensionAspect() const
+{
+  return !myDimensionAspect.IsNull();
+}
index 5705829..6bb7a9a 100755 (executable)
 #include <AIS.hxx>
 #include <BRep_Tool.hxx>
 #include <BRepAdaptor_Curve.hxx>
-#include <BRepGProp_Face.hxx>
 #include <BRepLib_MakeVertex.hxx>
 #include <BRepTopAdaptor_FClass2d.hxx>
+#include <BRepTools.hxx>
 #include <ElCLib.hxx>
 #include <ElSLib.hxx>
-#include <Geom_Line.hxx>
 #include <gce_MakeDir.hxx>
-#include <Graphic3d_Group.hxx>
-#include <Graphic3d_ArrayOfSegments.hxx>
-#include <PrsMgr_PresentationManager.hxx>
-#include <Prs3d_Root.hxx>
+#include <gce_MakePln.hxx>
+#include <GeomAPI_ExtremaCurveCurve.hxx>
+#include <GeomAPI_ExtremaCurveSurface.hxx>
+#include <GeomAPI_ExtremaSurfaceSurface.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_Line.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 
@@ -42,22 +43,38 @@ IMPLEMENT_STANDARD_RTTIEXT(AIS_LengthDimension, AIS_Dimension)
 
 //=======================================================================
 //function : Constructor
-//purpose  : Dimension between two points
+//purpose  : Dimension between two faces
+//=======================================================================
+AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFirstFace,
+                                          const TopoDS_Face& theSecondFace)
+: AIS_Dimension (AIS_KOD_LENGTH)
+{
+  SetMeasuredGeometry (theFirstFace, theSecondFace);
+  SetFlyout (15.0);
+}
+
+//=======================================================================
+//function : Constructor
+//purpose  : Dimension between two shape
 //=======================================================================
+AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFace,
+                                          const TopoDS_Edge& theEdge)
+: AIS_Dimension (AIS_KOD_LENGTH)
+{
+  SetMeasuredGeometry (theFace, theEdge);
+  SetFlyout (15.0);
+}
 
+//=======================================================================
+//function : Constructor
+//purpose  : Dimension between two points
+//=======================================================================
 AIS_LengthDimension::AIS_LengthDimension (const gp_Pnt& theFirstPoint,
                                           const gp_Pnt& theSecondPoint,
-                                          const gp_Pln& theDimensionPlane)
-: AIS_Dimension()
+                                          const gp_Pln& thePlane)
+: AIS_Dimension (AIS_KOD_LENGTH)
 {
-  myIsInitialized = Standard_True;
-  myFirstPoint = theFirstPoint;
-  mySecondPoint = theSecondPoint;
-  myFirstShape = BRepLib_MakeVertex (myFirstPoint);
-  mySecondShape = BRepLib_MakeVertex (mySecondPoint);
-  myShapesNumber = 2;
-  SetKindOfDimension (AIS_KOD_LENGTH);
-  SetWorkingPlane (theDimensionPlane);
+  SetMeasuredGeometry (theFirstPoint, theSecondPoint, thePlane);
   SetFlyout (15.0);
 }
 
@@ -65,18 +82,13 @@ AIS_LengthDimension::AIS_LengthDimension (const gp_Pnt& theFirstPoint,
 //function : Constructor
 //purpose  : Dimension between two shape
 //=======================================================================
-
 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Shape& theFirstShape,
                                           const TopoDS_Shape& theSecondShape,
-                                          const gp_Pln& theWorkingPlane)
-: AIS_Dimension()
+                                          const gp_Pln& thePlane)
+: AIS_Dimension (AIS_KOD_LENGTH)
 {
-  myIsInitialized = Standard_False;
-  myFirstShape = theFirstShape;
-  mySecondShape = theSecondShape;
-  myShapesNumber = 2;
-  SetKindOfDimension (AIS_KOD_LENGTH);
-  SetWorkingPlane (theWorkingPlane);
+  SetCustomPlane (thePlane);
+  SetMeasuredShapes (theFirstShape, theSecondShape);
   SetFlyout (15.0);
 }
 
@@ -84,452 +96,619 @@ AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Shape& theFirstShape,
 //function : Constructor
 //purpose  : Dimension of one edge
 //=======================================================================
-
 AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Edge& theEdge,
-                                          const gp_Pln& theWorkingPlane)
-: AIS_Dimension()
+                                          const gp_Pln& thePlane)
+: AIS_Dimension (AIS_KOD_LENGTH)
 {
-  myIsInitialized = Standard_False;
-  myFirstShape = theEdge;
-  myShapesNumber = 1;
-  SetKindOfDimension (AIS_KOD_LENGTH);
-  SetWorkingPlane (theWorkingPlane);
+  SetMeasuredGeometry (theEdge, thePlane);
   SetFlyout (15.0);
 }
 
 //=======================================================================
-//function : Constructor
-//purpose  : Dimension between two faces
+//function : SetMeasuredGeometry
+//purpose  : 
 //=======================================================================
+void AIS_LengthDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint,
+                                               const gp_Pnt& theSecondPoint,
+                                               const gp_Pln& thePlane)
+{
+  myFirstPoint   = theFirstPoint;
+  mySecondPoint  = theSecondPoint;
+  myFirstShape   = BRepLib_MakeVertex (myFirstPoint);
+  mySecondShape  = BRepLib_MakeVertex (mySecondPoint);
+  myGeometryType = GeometryType_Points;
+  SetCustomPlane (thePlane);
+  myIsValid      = IsValidPoints (theFirstPoint, theSecondPoint) && CheckPlane (myPlane);
+
+  SetToUpdate();
+}
 
-AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFirstFace,
-                                          const TopoDS_Face& theSecondFace)
-: AIS_Dimension()
+//=======================================================================
+//function : SetMeasuredGeometry
+//purpose  : 
+//=======================================================================
+void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Edge& theEdge,
+                                               const gp_Pln& thePlane)
 {
-  myIsInitialized = Standard_False;
-  myFirstShape = theFirstFace;
-  mySecondShape = theSecondFace;
-  myShapesNumber = 2;
-  SetKindOfDimension (AIS_KOD_LENGTH);
-  SetFlyout (15.0);
+  myFirstShape  = theEdge;
+  mySecondShape = TopoDS_Shape();
+  myGeometryType = GeometryType_Edge;
+  SetCustomPlane (thePlane);
+  myIsValid     = InitOneShapePoints (myFirstShape) && CheckPlane (myPlane);
+
+  SetToUpdate();
 }
 
 //=======================================================================
-//function : Constructor
-//purpose  : Dimension between two shape
+//function : SetMeasuredGeometry
+//purpose  : 
 //=======================================================================
+void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace,
+                                               const TopoDS_Face& theSecondFace)
+{
+  SetMeasuredShapes (theFirstFace, theSecondFace);
+}
 
-AIS_LengthDimension::AIS_LengthDimension (const TopoDS_Face& theFace,
-                                          const TopoDS_Edge& theEdge)
-: AIS_Dimension()
+//=======================================================================
+//function : SetMeasuredGeometry
+//purpose  : 
+//=======================================================================
+void AIS_LengthDimension::SetMeasuredGeometry (const TopoDS_Face& theFace,
+                                               const TopoDS_Edge& theEdge)
 {
-  myIsInitialized = Standard_False;
-  myFirstShape = theFace;
-  mySecondShape = theEdge;
-  myShapesNumber = 2;
-  SetKindOfDimension (AIS_KOD_LENGTH);
-  SetFlyout (15.0);
+  SetMeasuredShapes (theFace, theEdge);
+}
+
+//=======================================================================
+//function : SetMeasuredShapes
+//purpose  : 
+//=======================================================================
+void AIS_LengthDimension::SetMeasuredShapes (const TopoDS_Shape& theFirstShape,
+                                             const TopoDS_Shape& theSecondShape)
+{
+  gp_Pln aComputedPlane;
+  Standard_Boolean isPlaneReturned = Standard_False;
+  myFirstShape   = theFirstShape;
+  mySecondShape  = theSecondShape;
+  myIsValid      = InitTwoShapesPoints (myFirstShape, mySecondShape, aComputedPlane, isPlaneReturned);
+
+  if (myIsValid && !myIsPlaneCustom)
+  {
+    if (isPlaneReturned)
+    {
+      myPlane = aComputedPlane;
+    }
+    else
+    {
+      myIsValid = Standard_False;
+    }
+  }
+
+  myIsValid &= CheckPlane (myPlane);
+
+  SetToUpdate();
+}
+
+//=======================================================================
+//function : CheckPlane
+//purpose  : 
+//=======================================================================
+Standard_Boolean AIS_LengthDimension::CheckPlane (const gp_Pln& thePlane) const
+{
+  if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) &&
+      !thePlane.Contains (mySecondPoint, Precision::Confusion()))
+  {
+    return Standard_False;
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : ComputePlane
+//purpose  : 
+//=======================================================================
+gp_Pln AIS_LengthDimension::ComputePlane (const gp_Dir& theAttachDir) const
+{
+  if (!IsValidPoints (myFirstPoint, mySecondPoint))
+  {
+    return gp_Pln();
+  }
+
+  gp_Pnt aThirdPoint (myFirstPoint.Translated (gp_Vec(theAttachDir)));
+  gce_MakePln aPlaneConstrustor (myFirstPoint, mySecondPoint, aThirdPoint);
+  return aPlaneConstrustor.Value();
+}
+
+//=======================================================================
+//function : GetModelUnits
+//purpose  :
+//=======================================================================
+const TCollection_AsciiString& AIS_LengthDimension::GetModelUnits() const
+{
+  return myDrawer->DimLengthModelUnits();
 }
 
 //=======================================================================
-//function : initTwoEdgesLength
-//purpose  : Initialization of dimanesion between two linear edges
+//function : GetDisplayUnits
+//purpose  :
 //=======================================================================
+const TCollection_AsciiString& AIS_LengthDimension::GetDisplayUnits() const
+{
+  return myDrawer->DimLengthDisplayUnits();
+}
+
+//=======================================================================
+//function : SetModelUnits
+//purpose  :
+//=======================================================================
+void AIS_LengthDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
+{
+  myDrawer->SetDimLengthModelUnits (theUnits);
+}
+
+//=======================================================================
+//function : SetDisplayUnits
+//purpose  :
+//=======================================================================
+void AIS_LengthDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
+{
+  myDrawer->SetDimLengthDisplayUnits (theUnits);
+}
 
-Standard_Boolean AIS_LengthDimension::initTwoEdgesLength (const TopoDS_Edge & theFirstEdge,
+//=======================================================================
+//function : ComputeValue
+//purpose  : 
+//=======================================================================
+Standard_Real AIS_LengthDimension::ComputeValue() const
+{
+  return IsValid() ? myFirstPoint.Distance (mySecondPoint) : 0.0;
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+void AIS_LengthDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
+                                   const Handle(Prs3d_Presentation)& thePresentation,
+                                   const Standard_Integer theMode)
+{
+  thePresentation->Clear();
+  mySelectionGeom.Clear (theMode);
+
+  if (!IsValid())
+  {
+    return;
+  }
+
+  DrawLinearDimension (thePresentation, theMode, myFirstPoint, mySecondPoint);
+}
+
+//=======================================================================
+//function : ComputeFlyoutSelection
+//purpose  : 
+//=======================================================================
+void AIS_LengthDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
+                                                  const Handle(SelectMgr_EntityOwner)& theEntityOwner)
+{
+  if (!IsValid())
+  {
+    return;
+  }
+
+  ComputeLinearFlyouts (theSelection, theEntityOwner, myFirstPoint, mySecondPoint);
+}
+
+//=======================================================================
+//function : IsValidPoints
+//purpose  :
+//=======================================================================
+Standard_Boolean AIS_LengthDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
+                                                     const gp_Pnt& theSecondPoint) const
+{
+  return theFirstPoint.Distance (theSecondPoint) > Precision::Confusion();
+}
+
+//=======================================================================
+//function : InitTwoEdgesLength
+//purpose  : Initialization of dimension between two linear edges
+//=======================================================================
+Standard_Boolean AIS_LengthDimension::InitTwoEdgesLength (const TopoDS_Edge& theFirstEdge,
                                                           const TopoDS_Edge& theSecondEdge,
                                                           gp_Dir& theDirAttach)
 {
-  Standard_Integer anExtShapeIndex = 0;
   BRepAdaptor_Curve aFirstCurveAdapt (theFirstEdge);
   if (aFirstCurveAdapt.GetType() != GeomAbs_Line)
+  {
     return Standard_False;
+  }
+
   BRepAdaptor_Curve aSecondCurveAdapt (theSecondEdge);
   if (aSecondCurveAdapt.GetType() != GeomAbs_Line)
+  {
     return Standard_False;
-  Handle(Geom_Curve) aFirstCurve, aSecondCurve;
-  gp_Pnt aPoint11,aPoint12,aPoint21,aPoint22;
-  Standard_Boolean isFirstInfinite (Standard_False),
-                   isSecondInfinite (Standard_False);
-  Handle(Geom_Curve) anExtCurve;
-
-  if (!AIS::ComputeGeometry (theFirstEdge, theSecondEdge,anExtShapeIndex,
-                            aFirstCurve, aSecondCurve, aPoint11, aPoint12,
-                            aPoint21, aPoint22, anExtCurve, isFirstInfinite,
-                            isSecondInfinite, new Geom_Plane(GetWorkingPlane())))
-    return Standard_False;
-
-  const Handle(Geom_Line)& aGeomLine1 = (Handle(Geom_Line)&) aFirstCurve;
-  const Handle(Geom_Line)& aGeomLine2 = (Handle(Geom_Line)&) aSecondCurve;
-  const gp_Lin& aLin1 = aGeomLine1->Lin();
-  const gp_Lin& aLin2 = aGeomLine2->Lin();
-
-  myValue = aLin1.Distance (aLin2);
-  theDirAttach = aLin1.Direction();
+  }
 
-  gp_Pnt aCurPos;
-  if (!isFirstInfinite)
+  Handle(Geom_Curve) aFirstCurve;
+  Handle(Geom_Curve) aSecondCurve;
+
+  gp_Pnt aPoint11 (gp::Origin());
+  gp_Pnt aPoint12 (gp::Origin());
+  gp_Pnt aPoint21 (gp::Origin());
+  gp_Pnt aPoint22 (gp::Origin());
+  Standard_Boolean isFirstInfinite  = Standard_False;
+  Standard_Boolean isSecondInfinite = Standard_False;
+
+  if (!AIS::ComputeGeometry (theFirstEdge, theSecondEdge,
+                             aFirstCurve, aSecondCurve,
+                             aPoint11, aPoint12,
+                             aPoint21, aPoint22,
+                             isFirstInfinite,
+                             isSecondInfinite))
   {
-    gp_Pnt aPoint2 = ElCLib::Value(ElCLib::Parameter (aLin2, aPoint11), aLin2);
-    aCurPos.SetXYZ((aPoint11.XYZ() + aPoint2.XYZ()) / 2.);
+    return Standard_False;
   }
-  else if (!isSecondInfinite)
+
+  const Handle(Geom_Line) aFirstLine = Handle(Geom_Line)::DownCast (aFirstCurve);
+  const Handle(Geom_Line) aSecondLine = Handle(Geom_Line)::DownCast (aSecondCurve);
+
+  if (!aFirstLine->Lin().Direction().IsParallel (aSecondLine->Lin().Direction(),Precision::Angular()))
   {
-    gp_Pnt aPoint2 = ElCLib::Value (ElCLib::Parameter (aLin1, aPoint21), aLin1);
-    aCurPos.SetXYZ ((aPoint21.XYZ() + aPoint2.XYZ()) / 2.);
+    return Standard_False;
   }
-  else
-    aCurPos.SetXYZ((aLin1.Location().XYZ() + aLin2.Location().XYZ()) / 2.);
-  
-  // Offset to avoid confusion Edge and Dimension
-  gp_Vec anOffset(theDirAttach);
-  anOffset = anOffset * myDrawer->DimensionAspect()->ArrowAspect()->Length()*(-10.);
-  aCurPos.Translate (anOffset);
-
-  // Find attachment points
+
+  theDirAttach = aFirstLine->Lin().Direction();
+
+  gp_Pnt aPoint;
+
   if (!isFirstInfinite)
   {
-    if (aCurPos.Distance (aPoint11) > aCurPos.Distance (aPoint12))
-      myFirstPoint = aPoint12;
-    else
+    if (AIS::Nearest (aSecondCurve, aPoint11, aPoint21, aPoint22, aPoint))
+    {
       myFirstPoint = aPoint11;
+      mySecondPoint = aPoint;
+      return IsValidPoints (myFirstPoint, mySecondPoint);
+    }
+    else if (AIS::Nearest (aSecondCurve, aPoint12, aPoint21, aPoint22, aPoint))
+    {
+      myFirstPoint = aPoint12;
+      mySecondPoint = aPoint;
+      return IsValidPoints (myFirstPoint, mySecondPoint);
+    }
   }
-  else
-    myFirstPoint = ElCLib::Value (ElCLib::Parameter (aLin1, aCurPos), aLin1);
 
   if (!isSecondInfinite)
   {
-    if (aCurPos.Distance (aPoint21) > aCurPos.Distance (aPoint22))
-      mySecondPoint = aPoint22;
-    else
+    if (AIS::Nearest (aFirstCurve, aPoint21, aPoint11, aPoint12, aPoint))
+    {
+      myFirstPoint = aPoint;
       mySecondPoint = aPoint21;
+      return IsValidPoints (myFirstPoint, mySecondPoint);
+    }
+    if (AIS::Nearest (aFirstCurve, aPoint22, aPoint11, aPoint12, aPoint))
+    {
+      myFirstPoint = aPoint;
+      mySecondPoint = aPoint22;
+      return IsValidPoints (myFirstPoint, mySecondPoint);
+    }
   }
-  else
-    mySecondPoint = ElCLib::Value (ElCLib::Parameter (aLin2, aCurPos), aLin2);
 
-  return Standard_True;
+  GeomAPI_ExtremaCurveCurve anExtrema (aFirstCurve, aSecondCurve);
+  anExtrema.NearestPoints (myFirstPoint, mySecondPoint);
+  return IsValidPoints (myFirstPoint, mySecondPoint);
 }
 
 //=======================================================================
-//function : initEdgeVertexLength
+//function : InitEdgeVertexLength
 //purpose  : for first edge and second vertex shapes
 //=======================================================================
-
-Standard_Boolean AIS_LengthDimension::initEdgeVertexLength (const TopoDS_Edge & theEdge,
-                                                            const TopoDS_Vertex & theVertex,
-                                                            gp_Dir & theDirAttach,
+Standard_Boolean AIS_LengthDimension::InitEdgeVertexLength (const TopoDS_Edge& theEdge,
+                                                            const TopoDS_Vertex& theVertex,
+                                                            gp_Dir& theEdgeDir,
                                                             Standard_Boolean isInfinite)
 {
-  gp_Pnt anEdgePoint1,anEdgePoint2;
+  gp_Pnt anEdgePoint1 (gp::Origin());
+  gp_Pnt anEdgePoint2 (gp::Origin());
   Handle(Geom_Curve) aCurve;
-  Handle(Geom_Curve) anExtCurve;
-  Standard_Boolean isEdgeOnPlane, isVertexOnPlane;
-  if (!AIS::ComputeGeometry(theEdge,aCurve,anEdgePoint1,anEdgePoint2,
-                            anExtCurve,isInfinite,isEdgeOnPlane, new Geom_Plane (GetWorkingPlane())))
+
+  if (!AIS::ComputeGeometry (theEdge, aCurve, anEdgePoint1, anEdgePoint2, isInfinite))
+  {
     return Standard_False;
-  AIS::ComputeGeometry (theVertex, myFirstPoint, new Geom_Plane(GetWorkingPlane()), isVertexOnPlane);
+  }
+
+  myFirstPoint = BRep_Tool::Pnt (theVertex);
 
   const Handle(Geom_Line)& aGeomLine = (Handle(Geom_Line)&) aCurve;
   const gp_Lin& aLin = aGeomLine->Lin();
 
-  myValue = aLin.Distance( myFirstPoint);
-  theDirAttach = aLin.Direction();
+  // Get direction of edge to build plane automatically.
+  theEdgeDir = aLin.Direction();
 
-  gp_Pnt aPoint = ElCLib::Value(ElCLib::Parameter(aLin,myFirstPoint),aLin);
-  gp_Pnt aCurPos((myFirstPoint.XYZ() + aPoint.XYZ())/2.);
+  mySecondPoint = AIS::Nearest (aLin, myFirstPoint);
 
-  if (!isInfinite)
-  {
-    if (aCurPos.Distance (anEdgePoint1) > aCurPos.Distance (anEdgePoint2))
-      mySecondPoint = anEdgePoint2;
-    else
-      mySecondPoint = anEdgePoint1;
-  }
-  else
-    mySecondPoint = ElCLib::Value (ElCLib::Parameter (aLin, aCurPos), aLin);
-  return Standard_True;
+  return IsValidPoints (myFirstPoint, mySecondPoint);
 }
 
 //=======================================================================
-//function : initEdgeVertexLength
+//function : InitEdgeFaceLength
 //purpose  : 
 //=======================================================================
-
-Standard_Boolean AIS_LengthDimension::initEdgeFaceLength (const TopoDS_Edge& theEdge,
+Standard_Boolean AIS_LengthDimension::InitEdgeFaceLength (const TopoDS_Edge& theEdge,
                                                           const TopoDS_Face& theFace,
-                                                          gp_Dir& theDirAttach)
+                                                          gp_Dir& theEdgeDir)
 {
-  // The first attachment point is <aPoint1> from the reference <anEdge>.