0024412: TKV3d, Dimensions - Possibility to customize text position was lost:
authoraba <aba@opencascade.com>
Thu, 13 Feb 2014 08:43:56 +0000 (12:43 +0400)
committerapn <apn@opencascade.com>
Thu, 13 Feb 2014 10:04:32 +0000 (14:04 +0400)
AIS_Dimension::GetTextPosition() and AIS_Dimension::SetTextPosition() methods were added.
Added possibility to set and unset text label alignment respectively to the attach points after text position changed.
Added test cases to check text positioning with dimension parameters and with setting 3D point.
Corrected DRAW commands vmovedim, vangledim, vdistdim, vradiusdim.
Corrections of AIS_Dimension::SetTextPosition(): aspect parameters are not changed inside it.
Layout mode was removed; test cases and vdimparams, vdimension  commands were corrected.
remarks: coding style, removing redundant code of LayoutMode enumeration.

16 files changed:
src/AIS/AIS.cdl
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_LengthDimension.cxx
src/AIS/AIS_LengthDimension.hxx
src/AIS/AIS_RadiusDimension.cxx
src/AIS/AIS_RadiusDimension.hxx
src/Prs3d/Prs3d_DimensionAspect.cdl
src/Prs3d/Prs3d_DimensionAspect.cxx
src/ViewerTest/ViewerTest_RelationCommands.cxx
tests/bugs/vis/bug24412_1 [new file with mode: 0644]
tests/bugs/vis/bug24412_2 [new file with mode: 0644]

index f1f9c76..7909dad 100644 (file)
@@ -241,19 +241,23 @@ is
     KOI_Datum,
     KOI_Shape,
     KOI_Object,
-    KOI_Relation;
-        --- Purpose: Declares the type of Interactive Object. 
-        -- This is one of the following:
-        -- -   the Datum
-        -- -   the Object
-        -- -   the Relation
-        -- -   the None type.
-        --  The Datum is the construction element. These include
-        -- points, lines, axes and planes. The object brings
-        -- together topological shapes. The Relation includes
-        -- dimensions and constraints. When the object is of an
-        -- unknown type, the None type is declared.
-    
+    KOI_Relation,
+    KOI_Dimension;
+    --- Purpose: Declares the type of Interactive Object. 
+    -- This is one of the following:
+    -- -   the Datum
+    -- -   the Object
+    -- -   the Relation
+    -- -   the Dimension
+    -- -   the None type.
+    -- The Datum is the construction element. These include
+    -- points, lines, axes and planes. The object brings
+    -- together topological shapes. The Relation includes
+    -- dimensions and constraints. The Dimension includes
+    -- length, radius, diameter and angle dimensions.
+    -- When the object is of an unknown type, the None
+    -- type is declared.
+
     enumeration ClearMode is
     CM_All,
     CM_Interactive,
index 6b841c8..b31ed17 100644 (file)
@@ -48,6 +48,7 @@
 #include <Select3D_SensitiveGroup.hxx>
 #include <Select3D_SensitiveSegment.hxx>
 #include <SelectMgr_Selection.hxx>
+#include <Standard_ProgramError.hxx>
 #include <UnitsAPI.hxx>
 
 IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
@@ -152,7 +153,7 @@ void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge,
 
   if (myIsValid && !myIsPlaneCustom)
   {
-    myPlane = aComputedPlane;
+    ComputePlane();
   }
 
   myIsValid &= CheckPlane (myPlane);
@@ -300,7 +301,7 @@ void AIS_AngleDimension::Init()
 //=======================================================================
 gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
                                            const gp_Pnt& theSecondAttach,
-                                           const gp_Pnt& theCenter)
+                                           const gp_Pnt& theCenter) const
 {
   // construct plane where the circle and the arc are located
   gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
@@ -583,7 +584,7 @@ Standard_Real AIS_AngleDimension::ComputeValue() const
 
   Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction());
 
-  return anAngle > 0.0 ? anAngle : (2.0 * M_PI - anAngle);
+  return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle);
 }
 
 //=======================================================================
@@ -619,31 +620,23 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
   }
 
-  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
-  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+  // Get parameters from aspect or adjust it according with custom text position
+  Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+  Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
 
-  // Handle user-defined and automatic arrow placement
-  bool isArrowsExternal = false;
-  switch (aDimensionAspect->ArrowOrientation())
+  if (IsTextPositionCustom())
   {
-    case Prs3d_DAO_External: isArrowsExternal = true; break;
-    case Prs3d_DAO_Internal: isArrowsExternal = false; break;
-    case Prs3d_DAO_Fit:
-    {
-      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
-      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+    AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos);
+  }
 
-      // add margin to ensure a small tail between text and arrow
-      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
-                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
-                                    : 0.0;
+  // Handle user-defined and automatic arrow placement
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
 
-      Standard_Real anArrowsWidth   = (anArrowLength + anArrowMargin) * 2.0;
+  FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal);
 
-      isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
-      break;
-    }
-  }
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
 
   //Arrows positions and directions
   gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
@@ -670,38 +663,9 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
   aFirstArrowEnd    = aFirstAttach.Translated (-aFirstArrowVec);
   aSecondArrowEnd   = aSecondAttach.Translated (-aSecondArrowVec);
 
-  Standard_Integer aLabelPosition = LabelPosition_None;
-
-  // Handle user-defined and automatic text placement
-  switch (aDimensionAspect->TextHorizontalPosition())
-  {
-    case Prs3d_DTHP_Left  : aLabelPosition |= LabelPosition_Left; break;
-    case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break;
-    case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break;
-    case Prs3d_DTHP_Fit:
-    {
-      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
-      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
-      Standard_Real anArrowsWidth   = anArrowLength * 2.0;
-      Standard_Real aContentWidth   = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
-
-      aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
-      break;
-    }
-  }
-
-  switch (aDimensionAspect->TextVerticalPosition())
-  {
-    case Prs3d_DTVP_Above  : aLabelPosition |= LabelPosition_Above; break;
-    case Prs3d_DTVP_Below  : aLabelPosition |= LabelPosition_Below; break;
-    case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break;
-  }
-
   // Group1: stenciling text and the angle dimension arc
   Prs3d_Root::NewGroup (thePresentation);
 
-  Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
-
   Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask;
 
   // draw text label
@@ -729,7 +693,8 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
       if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
       {
         gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
-        gp_Pnt aTextPos = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+        gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
+                                                : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
         gp_Dir aTextDir = aDimensionDir;
 
         DrawText (thePresentation,
@@ -807,7 +772,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     if (aHPosition != LabelPosition_Left)
     {
       DrawExtension (thePresentation,
-                     anExtensionSize,
+                     aDimensionAspect->ArrowTailSize(),
                      aFirstArrowEnd,
                      aFirstExtensionDir,
                      THE_EMPTY_LABEL_STRING,
@@ -819,7 +784,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     if (aHPosition != LabelPosition_Right)
     {
       DrawExtension (thePresentation,
-                     anExtensionSize,
+                     aDimensionAspect->ArrowTailSize(),
                      aSecondArrowEnd,
                      aSecondExtensionDir,
                      THE_EMPTY_LABEL_STRING,
@@ -1184,3 +1149,272 @@ Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
       && gp_Vec (theCenterPoint, theFirstPoint).Angle (
            gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();
 }
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_AngleDimension::GetTextPosition() const
+{
+  if (!IsValid())
+  {
+    return gp::Origin();
+  }
+
+  if (IsTextPositionCustom())
+  {
+    return myFixedTextPosition;
+  }
+
+  // Counts text position according to the dimension parameters
+  gp_Pnt aTextPosition (gp::Origin());
+
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  // Prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
+
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+
+  // Handle user-defined and automatic arrow placement
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
+  FitTextAlignment (aDimensionAspect->TextHorizontalPosition(),
+                    aLabelPosition, isArrowsExternal);
+
+  // Get text position
+  switch (aLabelPosition & LabelPosition_HMask)
+  {
+  case LabelPosition_HCenter:
+    {
+      aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+    }
+    break;
+  case LabelPosition_Left:
+    {
+      gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
+      gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec (anExtensionDir) * -anOffset;
+      aTextPosition = aFirstAttach.Translated (anExtensionVec);
+    }
+    break;
+  case LabelPosition_Right:
+    {
+      gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
+      gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec (anExtensionDir) * anOffset;
+      aTextPosition = aSecondAttach.Translated (anExtensionVec);
+    }
+    break;
+  }
+
+  return aTextPosition;
+}
+
+//=======================================================================
+//function : SetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!IsValid())
+  {
+    return;
+  }
+
+  // The text position point for angle dimension should belong to the working plane.
+  if (!GetPlane().Contains (theTextPos, Precision::Confusion()))
+  {
+    Standard_ProgramError::Raise ("The text position point for angle dimension doesn't belong to the working plane.");
+  }
+
+  myIsTextPositionFixed = Standard_True;
+  myFixedTextPosition = theTextPos;
+}
+
+//=======================================================================
+//function : AdjustAspectParameters
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos,
+                                           Standard_Real& theExtensionSize,
+                                           Prs3d_DimensionTextHorizontalPosition& theAlignment)
+{
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+  Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+
+  // Compute flyout direction vector.
+  gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+  gp_Dir aTargetPointsDir = gce_MakeDir (myFirstPoint, mySecondPoint);
+
+  // Build circle with radius that is equal to distance from text position to the center point.
+  Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude();
+
+  // Set attach points in positive direction of the flyout.
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * aRadius);
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * aRadius);
+
+  gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius);
+  if (!aConstructCircle.IsDone())
+  {
+    return;
+  }
+  gp_Circ aCircle = aConstructCircle.Value();
+
+  // Default values
+  theExtensionSize = aDimensionAspect->ArrowAspect()->Length();
+  theAlignment = Prs3d_DTHP_Center;
+
+  Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach);
+  Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach);
+  if (aParamEnd < aParamBeg)
+  {
+    Standard_Real aParam = aParamEnd;
+    aParamEnd = aParamBeg;
+    aParamBeg = aParam;
+  }
+
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+  Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos);
+
+  // Horizontal center
+  if (aTextPar > aParamBeg && aTextPar < aParamEnd)
+  {
+    myFlyout = aRadius;
+
+    SetToUpdate();
+    return;
+  }
+
+  aParamBeg += M_PI;
+  aParamEnd += M_PI;
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+
+  if (aTextPar > aParamBeg  && aTextPar < aParamEnd)
+  {
+    myFlyout = -aRadius;
+
+    SetToUpdate();
+    return;
+  }
+
+  // Text on the extensions
+  gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint);
+  gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint);
+  gp_Pnt aFirstTextProj = AIS::Nearest (aFirstLine, theTextPos);
+  gp_Pnt aSecondTextProj = AIS::Nearest (aSecondLine, theTextPos);
+  Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos);
+  Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos);
+
+  if (aFirstDist <= aSecondDist)
+  {
+    aRadius = myCenterPoint.Distance (aFirstTextProj);
+    Standard_Real aNewExtensionSize = aFirstDist - anArrowLength;
+    theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
+
+    theAlignment = Prs3d_DTHP_Left;
+
+    gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius);
+
+    myFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
+                ? -aRadius : aRadius;
+  }
+  else
+  {
+    aRadius = myCenterPoint.Distance (aSecondTextProj);
+
+    Standard_Real aNewExtensionSize = aSecondDist - anArrowLength;
+
+    theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize;
+
+    theAlignment = Prs3d_DTHP_Right;
+
+    gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius);
+
+    myFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion()
+                ? -aRadius : aRadius;
+  }
+}
+
+//=======================================================================
+//function : FitTextAlignment
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
+                                           Standard_Integer& theLabelPosition,
+                                           Standard_Boolean& theIsArrowsExternal) const
+{
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+
+  // Prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
+
+  // add margins to label width
+  if (aDimensionAspect->IsText3d())
+  {
+    aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
+  }
+
+  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
+  switch (aDimensionAspect->ArrowOrientation())
+  {
+    case Prs3d_DAO_External: theIsArrowsExternal = true; break;
+    case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
+    case Prs3d_DAO_Fit:
+    {
+      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
+      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+
+      // Add margin to ensure a small tail between text and arrow
+      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
+                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
+                                    : 0.0;
+
+      Standard_Real anArrowsWidth   = (anArrowLength + anArrowMargin) * 2.0;
+
+      theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
+      break;
+    }
+  }
+
+  // Handle user-defined and automatic text placement
+  switch (theHorizontalTextPos)
+  {
+    case Prs3d_DTHP_Left  : theLabelPosition |= LabelPosition_Left; break;
+    case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
+    case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
+    case Prs3d_DTHP_Fit:
+    {
+      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
+      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+      Standard_Real anArrowsWidth   = anArrowLength * 2.0;
+      Standard_Real aContentWidth   = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
+
+      theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
+      break;
+    }
+  }
+
+  switch (aDimensionAspect->TextVerticalPosition())
+  {
+    case Prs3d_DTVP_Above  : theLabelPosition |= LabelPosition_Above; break;
+    case Prs3d_DTVP_Below  : theLabelPosition |= LabelPosition_Below; break;
+    case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
+  }
+}
index 31548dd..13c1fc0 100755 (executable)
@@ -47,8 +47,8 @@ DEFINE_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
 //! 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
+//! In cases of two planes automatic plane by default is built on point of the
+//! origin of parametric 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.
@@ -188,15 +188,25 @@ public:
                                             const gp_Pnt& thePoint);
 
   //! @return the display units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const;
+  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const;
   
   //! @return the model units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const;
+  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);
 
+  //! Principle of horizontal text alignment settings:
+  //! - divide circle into two halves according to attachment points
+  //! - if aTextPos is between attach points -> Center + positive flyout
+  //! - if aTextPos is not between attach points but in this half -> Left or Right + positive flyout
+  //! - if aTextPos is between reflections of attach points -> Center + negative flyout
+  //! - if aTextPos is not between reflections of attach points -> Left or Right + negative flyout
+  Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos);
+
+  Standard_EXPORT virtual const gp_Pnt GetTextPosition () const;
+
 public:
 
   DEFINE_STANDARD_RTTI (AIS_AngleDimension)
@@ -212,7 +222,7 @@ protected:
   //! @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);
+                                         const gp_Pnt& theCenter) const;
 
   //! Draws main dimension line (arc).
   //! @param thePresentation [in] the dimension presentation.
@@ -247,6 +257,29 @@ protected:
                                         const Standard_Integer theMode,
                                         const Standard_Integer theLabelPosition);
 
+  //! Fits text alignment relatively to the dimension line;
+  //! it computes the value of label position and arrow orientation
+  //! according set in the aspect and dimension properties.
+  //! @param theHorizontalTextPos [in] the horizontal alignment for text position.
+  //! @param theLabelPosition [out] the label position, contains bits that defines
+  //! vertical and horizontal alignment. (for internal usage in count text position).
+  //! @param theIsArrowExternal [out] is the arrows external,
+  //! if arrow orientation in the dimension aspect is Prs3d_DAO_Fit, it fits arrow
+  //! orientation automatically.
+  Standard_EXPORT void FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
+                                         Standard_Integer& theLabelPosition,
+                                         Standard_Boolean& theIsArrowsExternal) const;
+
+  //! Adjusts aspect parameters according the text position:
+  //! extension size, vertical text alignment and flyout.
+  //! It changes flyout of the dimension.
+  //! @param theTextPos [in] the user defined 3d point of text position.
+  //! @param theExtensionSize [out] the adjusted extension size.
+  //! @param theAlignment [out] the horizontal label alignment.
+  Standard_EXPORT void AdjustParameters (const gp_Pnt& theTextPos,
+                                         Standard_Real& theExtensionSize,
+                                         Prs3d_DimensionTextHorizontalPosition& theAlignment);
+
 protected:
 
   Standard_EXPORT virtual void ComputePlane();
index 761f701..c2679e3 100644 (file)
@@ -296,7 +296,7 @@ void AIS_DiameterDimension::Compute (const Handle(PrsMgr_PresentationManager3d)&
 
   gp_Pnt aFirstPnt (gp::Origin());
   gp_Pnt aSecondPnt (gp::Origin());
-  ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt);
+  ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt);
 
   DrawLinearDimension (thePresentation, theMode, aFirstPnt, aSecondPnt);
 }
@@ -315,7 +315,7 @@ void AIS_DiameterDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selec
 
   gp_Pnt aFirstPnt (gp::Origin());
   gp_Pnt aSecondPnt (gp::Origin());
-  ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt);
+  ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt);
 
   ComputeLinearFlyouts (theSelection, theEntityOwner, aFirstPnt, aSecondPnt);
 }
@@ -324,15 +324,14 @@ void AIS_DiameterDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selec
 //function : ComputeSidePoints
 //purpose  : 
 //=======================================================================
-void AIS_DiameterDimension::ComputeSidePoints (const gp_Circ& /*theCircle*/,
-                                               const gp_Pln& /*thePlane*/,
+void AIS_DiameterDimension::ComputeSidePoints (const gp_Circ& theCircle,
                                                gp_Pnt& theFirstPnt,
                                                gp_Pnt& theSecondPnt)
 {
   theFirstPnt = AnchorPoint();
 
-  gp_Vec aRadiusVector (myCircle.Location(), theFirstPnt);
-  theSecondPnt = myCircle.Location().Translated (-aRadiusVector);
+  gp_Vec aRadiusVector (theCircle.Location(), theFirstPnt);
+  theSecondPnt = theCircle.Location().Translated (-aRadiusVector);
 }
 
 //=======================================================================
@@ -358,3 +357,35 @@ Standard_Boolean AIS_DiameterDimension::IsValidAnchor (const gp_Circ& theCircle,
   return Abs (anAnchorDist - aRadius) > Precision::Confusion()
       && aCirclePlane.Contains (theAnchor, Precision::Confusion());
 }
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_DiameterDimension::GetTextPosition() const
+{
+  if (IsTextPositionCustom())
+  {
+    return myFixedTextPosition;
+  }
+  
+  // Counts text position according to the dimension parameters
+  return GetTextPositionForLinear (myAnchorPoint, myCircle.Location());
+}
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_DiameterDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!myIsValid)
+  {
+    return;
+  }
+
+  myIsTextPositionFixed = Standard_True;
+  myFixedTextPosition = theTextPos;
+
+  SetToUpdate();
+}
index 7783f8c..508b15c 100644 (file)
@@ -114,15 +114,19 @@ public:
   Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Shape& theShape);
 
   //! @return the display units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const;
+  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const;
   
   //! @return the model units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const;
+  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);
 
+  Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos);
+
+  Standard_EXPORT virtual const gp_Pnt GetTextPosition() const;
+
 public:
 
   DEFINE_STANDARD_RTTI(AIS_DiameterDimension)
@@ -154,16 +158,14 @@ protected:
 
 protected:
 
-  //! Compute points on the circle sides for the specified dimension plane.
+  //! Compute points on the circle sides for the 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);
 
index e11b3c4..0b549e1 100755 (executable)
 #include <ElCLib.hxx>
 #include <Font_BRepFont.hxx>
 #include <GC_MakeCircle.hxx>
+#include <Geom_Line.hxx>
 #include <GeomAdaptor_Curve.hxx>
 #include <Geom_Circle.hxx>
 #include <Geom_TrimmedCurve.hxx>
 #include <gce_MakeDir.hxx>
 #include <gce_MakeLin.hxx>
+#include <gce_MakePln.hxx>
 #include <Graphic3d_ArrayOfSegments.hxx>
 #include <Graphic3d_ArrayOfTriangles.hxx>
 #include <Graphic3d_AspectLine3d.hxx>
@@ -59,6 +61,7 @@
 #include <Poly_Array1OfTriangle.hxx>
 #include <Poly_Triangulation.hxx>
 #include <Standard_CString.hxx>
+#include <Standard_ProgramError.hxx>
 #include <StdPrs_ShadedShape.hxx>
 #include <StdPrs_WFShape.hxx>
 #include <TCollection_AsciiString.hxx>
@@ -70,7 +73,6 @@
 #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)
@@ -154,6 +156,9 @@ void AIS_Dimension::SetCustomPlane (const gp_Pln& thePlane)
   myPlane = thePlane;
   myIsPlaneCustom = Standard_True;
 
+  // Disable fixed text position
+  UnsetFixedTextPosition();
+
   // Check validity if geometry has been set already.
   if (myIsValid)
   {
@@ -234,6 +239,9 @@ void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
 
   myFlyout = theFlyout;
 
+  // Disable fixed text position
+  UnsetFixedTextPosition();
+
   SetToUpdate();
 }
 
@@ -620,25 +628,8 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
     Standard_ProgramError::Raise ("Can not build presentation for equal points.");
   }
 
-  // compute dimension line points
-  gp_Ax1 aPlaneNormal = GetPlane().Axis();
-  gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
-
-  // compute flyout direction vector
-  gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
-
-  // create lines for layouts
-  gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
-  gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
-
-  // Get flyout end points
-  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();
 
-  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();
@@ -653,28 +644,37 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
   }
 
   // handle user-defined and automatic arrow placement
-  bool isArrowsExternal = false;
-  switch (aDimensionAspect->ArrowOrientation())
-  {
-    case Prs3d_DAO_External: isArrowsExternal = true; break;
-    case Prs3d_DAO_Internal: isArrowsExternal = false; break;
-    case Prs3d_DAO_Fit:
-    {
-      // add margin to ensure a small tail between text and arrow
-      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
-                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
-                                    : 0.0;
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
 
-      Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
-      Standard_Real anArrowsWidth   = theIsOneSide 
-                                    ?  anArrowLength + anArrowMargin
-                                    : (anArrowLength + anArrowMargin) * 2.0;
+  Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition();
+  if (IsTextPositionCustom())
+  {
+    AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint,
+                               anExtensionSize, aHorisontalTextPos);
 
-      isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
-      break;
-    }
   }
 
+  FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
+                             aLabelPosition, isArrowsExternal);
+
+    // compute dimension line points
+  gp_Ax1 aPlaneNormal = GetPlane().Axis();
+  gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
+
+  // compute flyout direction vector
+  gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
+
+  // create lines for layouts
+  gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+  gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+
+  // Get flyout end points
+  gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint)  + GetFlyout(), aLine1);
+  gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
+
+  gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
+
   // compute arrows positions and directions
   gp_Dir aFirstArrowDir       = aDimensionLine.Direction().Reversed();
   gp_Dir aSecondArrowDir      = aDimensionLine.Direction();
@@ -703,32 +703,6 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
   gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
     ? aLineEndPoint : aSecondArrowEnd;
 
-  Standard_Integer aLabelPosition = LabelPosition_None;
-
-  // handle user-defined and automatic text placement
-  switch (aDimensionAspect->TextHorizontalPosition())
-  {
-    case Prs3d_DTHP_Left  : aLabelPosition |= LabelPosition_Left; break;
-    case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break;
-    case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break;
-    case Prs3d_DTHP_Fit:
-    {
-      Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
-      Standard_Real anArrowsWidth   = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
-      Standard_Real aContentWidth   = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
-
-      aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
-      break;
-    }
-  }
-
-  // handle vertical text placement options
-  switch (aDimensionAspect->TextVerticalPosition())
-  {
-    case Prs3d_DTVP_Above  : aLabelPosition |= LabelPosition_Above; break;
-    case Prs3d_DTVP_Below  : aLabelPosition |= LabelPosition_Below; break;
-    case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break;
-  }
 
   switch (aLabelPosition & LabelPosition_HMask)
   {
@@ -740,7 +714,8 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
       // add label on dimension or extension line to presentation
       Prs3d_Root::NewGroup (thePresentation);
 
-      gp_Pnt aTextPos = (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
+      gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
+                                              : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
       gp_Dir aTextDir = aDimensionLine.Direction();
 
       // add text primitives
@@ -831,12 +806,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, aDimensionAspect->ArrowTailSize(),
                        aFirstArrowEnd, aFirstExtensionDir,
                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
         if (!theIsOneSide)
         {
-          DrawExtension (thePresentation, anExtensionSize,
+          DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
                          aSecondArrowEnd, aSecondExtensionDir,
                          THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
         }
@@ -900,7 +875,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, aDimensionAspect->ArrowTailSize(),
                        aSecondArrowEnd, aSecondExtensionDir,
                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
       }
@@ -960,7 +935,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, aDimensionAspect->ArrowTailSize(),
                        aFirstArrowEnd, aFirstExtensionDir,
                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
       }
@@ -1366,3 +1341,247 @@ void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
   theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
   theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
 }
+
+//=======================================================================
+//function : GetTextPositionForLinear
+//purpose  : 
+//=======================================================================
+gp_Pnt AIS_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
+                                                const gp_Pnt& theSecondPoint,
+                                                const Standard_Boolean theIsOneSide) const
+{
+  if (!myIsValid)
+  {
+    return gp::Origin();
+  }
+
+  gp_Pnt aTextPosition (gp::Origin());
+
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  // Get label alignment and arrow orientation.
+  Standard_Integer aLabelPosition = 0;
+  Standard_Boolean isArrowsExternal = Standard_False;
+  FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
+                             aDimensionAspect->TextHorizontalPosition(),
+                             aLabelPosition, isArrowsExternal);
+
+  // Compute dimension line points.
+  gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+  gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
+
+  // Compute flyout direction vector
+  gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec);
+
+  // create lines for layouts
+  gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+  gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+  // Get flyout end points
+  gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint)  + GetFlyout(), aLine1);
+  gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
+
+  // Get text position.
+  switch (aLabelPosition & LabelPosition_HMask)
+  {
+  case LabelPosition_Left:
+    {
+      gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+
+      Standard_Real anOffset = isArrowsExternal
+                                 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+                                 : anExtensionSize;
+      gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset;
+      aTextPosition = aLineEndPoint.Translated (anExtensionVec);
+    }
+    break;
+  case LabelPosition_Right:
+    {
+      gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+
+      Standard_Real anOffset = isArrowsExternal
+                                 ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+                                 : anExtensionSize;
+      gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset;
+      aTextPosition = aLineBegPoint.Translated (anExtensionVec);
+    }
+    break;
+  case LabelPosition_HCenter:
+    {
+      aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
+    }
+    break;
+  }
+
+  return aTextPosition;
+}
+
+//=======================================================================
+//function : AdjustAspectParameters
+//purpose  : 
+//=======================================================================
+void AIS_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos,
+                                               const gp_Pnt& theFirstPoint,
+                                               const gp_Pnt& theSecondPoint,
+                                               Standard_Real& theExtensionSize,
+                                               Prs3d_DimensionTextHorizontalPosition& theAlignment)
+{
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+  Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+
+  //Set new automatic plane.
+  myPlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
+  myIsPlaneCustom = Standard_False;
+
+  // Compute dimension line points.
+  gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+  gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+  gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
+
+  // Compute flyout direction vector.
+  gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
+
+  // Set flyout.
+  gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
+
+  Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
+
+  gp_Pnt aTextPosProj = theFirstPoint.Translated
+    (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos);
+
+  // Compute flyout value and direction.
+  gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
+
+  myFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular())
+              ? -aFlyoutVector.Magnitude()
+              :  aFlyoutVector.Magnitude();
+
+  // Compute attach points (through which main dimension line passes).
+  gp_Pnt aFirstAttach  = theFirstPoint.Translated (aFlyoutVector);
+  gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector);
+
+  // Set horisontal text alignment.
+  if (aCos < 0.0)
+  {
+    theAlignment = Prs3d_DTHP_Left;
+
+    Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength;
+    theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
+  }
+  else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
+  {
+    theAlignment = Prs3d_DTHP_Right;
+
+    Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength;
+    theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize;
+  }
+  else
+  {
+    theAlignment = Prs3d_DTHP_Center;
+  }
+}
+
+//=======================================================================
+//function : FitTextAlignmentForLinear
+//purpose  : 
+//=======================================================================
+void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
+                                               const gp_Pnt& theSecondPoint,
+                                               const Standard_Boolean theIsOneSide,
+                                               const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
+                                               Standard_Integer& theLabelPosition,
+                                               Standard_Boolean& theIsArrowsExternal) const
+{
+  theLabelPosition = LabelPosition_None;
+  theIsArrowsExternal = Standard_False;
+
+  // Compute dimension line points
+  gp_Ax1 aPlaneNormal = GetPlane().Axis();
+  gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
+
+  // compute flyout direction vector
+  gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
+
+  // create lines for layouts
+  gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+  gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+
+  // Get flyout end points
+  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();
+
+  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();
+
+  // prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
+
+  // Add margins to cut dimension lines for 3d text
+  if (aDimensionAspect->IsText3d())
+  {
+    aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
+  }
+
+  // Handle user-defined and automatic arrow placement
+  switch (aDimensionAspect->ArrowOrientation())
+  {
+    case Prs3d_DAO_External: theIsArrowsExternal = true; break;
+    case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
+    case Prs3d_DAO_Fit:
+    {
+      // Add margin to ensure a small tail between text and arrow
+      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
+                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
+                                    : 0.0;
+
+      Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
+      Standard_Real anArrowsWidth   = theIsOneSide 
+                                      ?  anArrowLength + anArrowMargin
+                                      : (anArrowLength + anArrowMargin) * 2.0;
+
+      theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
+      break;
+    }
+  }
+
+  // Handle user-defined and automatic text placement
+  switch (theHorizontalTextPos)
+  {
+    case Prs3d_DTHP_Left  : theLabelPosition |= LabelPosition_Left; break;
+    case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
+    case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
+    case Prs3d_DTHP_Fit:
+    {
+      Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
+      Standard_Real anArrowsWidth   = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
+      Standard_Real aContentWidth   = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
+
+      theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
+      break;
+    }
+  }
+
+  // Handle vertical text placement options
+  switch (aDimensionAspect->TextVerticalPosition())
+  {
+    case Prs3d_DTVP_Above  : theLabelPosition |= LabelPosition_Above; break;
+    case Prs3d_DTVP_Below  : theLabelPosition |= LabelPosition_Below; break;
+    case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
+  }
+}
+
+//=======================================================================
+//function : UnsetFixedTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_Dimension::UnsetFixedTextPosition()
+{
+  myIsTextPositionFixed = Standard_False;
+  myFixedTextPosition = gp::Origin();
+}
index 39e28dc..1203a9b 100755 (executable)
@@ -56,11 +56,11 @@ DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 //! 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
+//! - Attachment (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,
+//! - Main dimension line. The which extends from the attachment 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.
+//! - Flyouts. The lines connecting the attachment 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.
@@ -75,7 +75,7 @@ DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 //!          |flyout                       flyout|
 //!          |                                   |
 //!          +-----------------------------------+
-//! attachement                                attachement
+//! attachment                                attachment
 //!  point                                       point
 //!
 //!  Angular dimensions:
@@ -130,19 +130,46 @@ DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 //! 
 //! 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.
+//! The component highlighting 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.
 //!
+//! Such set of parameters that consists of:
+//! - flyout size and direction,
+//! - user-defined  dimension plane,
+//! - horizontal and vertical text alignment
+//! can be uniquely replaced with text position in 3d space. Therefore, there are methods to convert
+//! this set of parameters to the text position and vice versa:
+//!
+//! - If the fixed text position is defined by user, called SetTextPosition (theTextPos) method converts
+//! this 3d point to the set of parameters including adjusting of the dimension plane (this plane will be
+//! automatic plane, NOT user-defined one).
+//! If the fixed text position is set, the flag myIsFixedTextPosition is set to TRUE.
+//! ATTENSION! myIsFixedTextPosition fixes all parameters of the set from recomputing inside
+//! SetMeasureGeometry() methods. Parameters in dimension aspect (they are horizontal text position
+//! and extension size) are adjusted on presentation computing step, user-defined values in
+//! dimension aspect are not changed.
+//! But plane and flyout as dimension position parameters are changed by SetTextPosition() method
+//! according with user-defined text position.
+//! If parameters from the set are changed by user with calls of setters, it leads to disabling of
+//! fixed text position (myIsFixedTextPosition is set to FALSE).
+//! If the fixed text position is set and geometry is changed by user (SetMeasureGeometry() method
+//! is called) and the geometry doesn't satisfy computed dimension plane, the dimension is not valid.
+//!
+//! - If the set of parameters was set by user (may be without the user-defined plane or with it),
+//! it can be converted to the text position by calling the method GetTextPosition(). In this case
+//! the text position is NOT fixed, and SetMeasureGeometry() without user-defined plane adjusts
+//! the automatic plane according input geometry (if it is possible).
+//!
 class AIS_Dimension : public AIS_InteractiveObject
 {
 protected:
 
   //! Geometry type defines type of shapes on which the dimension is to be built.
-  //! Some type of geometry allows automatical plane computing and
+  //! Some type of geometry allows automatic plane computing and
   //! can be built without user-defined plane
   //! Another types can't be built without user-defined plane.
   enum GeometryType
@@ -212,8 +239,8 @@ public:
   //! 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.
+  //! plane, dimension geometry was set as invalid (validity flag is set to false)
+  //! and dimension presentation will 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.
@@ -233,6 +260,22 @@ public:
   //! computed automatically.
   Standard_EXPORT void UnsetCustomPlane() { myIsPlaneCustom = Standard_False; }
 
+  //! @return TRUE if text position is set by user with method SetTextPosition().
+  Standard_Boolean IsTextPositionCustom() const
+  {
+    return myIsTextPositionFixed;
+  }
+
+  //! Fixes the absolute text position and adjusts flyout, plane and text alignment
+  //! according to it. Updates presentation if the text position is valid.
+  //! ATTENTION! It does not change vertical text alignment.
+  //! @param theTextPos [in] the point of text position.
+  virtual void SetTextPosition (const gp_Pnt& /*theTextPos*/) { }
+
+  //! Computes absolute text position from dimension parameters
+  //! (flyout, plane and text alignment).
+  virtual const gp_Pnt GetTextPosition () const { return gp_Pnt(); }
+
 public:
 
   //! Gets the dimension aspect from AIS object drawer.
@@ -256,7 +299,7 @@ public:
   //! @return the kind of interactive.
   virtual AIS_KindOfInteractive Type() const
   {
-    return AIS_KOI_Relation;
+    return AIS_KOI_Dimension;
   }
 
   //! Returns true if the class of objects accepts the display mode theMode.
@@ -295,6 +338,10 @@ public:
 
   Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& /*theUnits*/) { }
 
+  //! Unsets user defined text positioning and enables text positioning
+  //!  by other parameters: text alignment, extension size, flyout and custom plane.
+  Standard_EXPORT void UnsetFixedTextPosition();
+
 public:
 
   //! Returns selection tolerance for text2d:
@@ -321,7 +368,7 @@ public:
   Standard_EXPORT void SetFlyout (const Standard_Real theFlyout);
 
   //! Check that the input geometry for dimension is valid and the
-  //! presentation can be succesfully computed.
+  //! presentation can be successfully computed.
   //! @return TRUE if dimension geometry is ok.
   Standard_Boolean IsValid() const
   {
@@ -426,6 +473,59 @@ protected:
                                                           gp_Circ& theCircle,
                                                           gp_Pnt& theMiddleArcPoint,
                                                           Standard_Boolean& theIsClosed);
+  //! Produce points for triangular arrow face.
+  //! @param thePeakPnt [in] the arrow peak position.
+  //! @param theDirection [in] the arrow direction.
+  //! @param thePlane [in] the face plane.
+  //! @param theArrowLength [in] the length of arrow.
+  //! @param theArrowAngle [in] the angle of arrow.
+  //! @param theSidePnt1 [out] the first side point.
+  //! @param theSidePnt2 [out] the second side point.
+  Standard_EXPORT void PointsForArrow (const gp_Pnt& thePeakPnt,
+                                       const gp_Dir& theDirection,
+                                       const gp_Dir& thePlane,
+                                       const Standard_Real theArrowLength,
+                                       const Standard_Real theArrowAngle,
+                                       gp_Pnt& theSidePnt1,
+                                       gp_Pnt& theSidePnt2);
+
+  //! Compute point of text position for dimension parameters
+  //! for linear kinds of dimensions (length, radius, diameter).
+  Standard_EXPORT gp_Pnt GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
+                                                   const gp_Pnt& theSecondPoint,
+                                                   const Standard_Boolean theIsOneSide = Standard_False) const;
+
+  //! Fits text alignment relatively to the dimension line.
+  //! @param theFirstPoint [in] the first attachment point.
+  //! @param theSecondPoint [in] the second attachment point.
+  //! @param theIsOneSide [in] is the arrow displayed only on the one side of the dimension.
+  //! @param theHorizontalTextPos [in] the text horizontal position (alignment).
+  //! @param theLabelPosition [out] the label position, contains bits that defines
+  //! vertical and horizontal alignment. (for internal usage in count text position)
+  //! @param theIsArrowExternal [out] is the arrows external,
+  //! if arrow orientation in the dimension aspect is Prs3d_DAO_Fit, it fits arrow
+  //! orientation automatically.
+  void FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
+                                  const gp_Pnt& theSecondPoint,
+                                  const Standard_Boolean theIsOneSide,
+                                  const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos,
+                                  Standard_Integer& theLabelPosition,
+                                  Standard_Boolean& theIsArrowsExternal) const;
+
+  //! Adjusts aspect parameters according the text position:
+  //! extension size, vertical text alignment and flyout.
+  //! It changes working plane and flyout of linear dimension.
+  //! @param theTextPos [in] the user defined 3d point of text position
+  //! @param theFirstPoint [in] the first point of linear measurement.
+  //! @param theSecondPoint [in] the second point of linear measurement.
+  //! @param theExtensionSize [out] the adjusted extension size
+  //! @param theAlignment [out] the horizontal label alignment.
+  void AdjustParametersForLinear (const gp_Pnt& theTextPos,
+                                  const gp_Pnt& theFirstPoint,
+                                  const gp_Pnt& theSecondPoint,
+                                  Standard_Real& theExtensionSize,
+                                  Prs3d_DimensionTextHorizontalPosition& theAlignment);
 
 protected: //! @name Behavior to implement
 
@@ -455,22 +555,6 @@ protected: //! @name Behavior to implement
   virtual void ComputeFlyoutSelection (const Handle(SelectMgr_Selection)&,
                                        const Handle(SelectMgr_EntityOwner)&) {}
 
-  //! Produce points for triangular arrow face.
-  //! @param thePeakPnt [in] the arrow peak position.
-  //! @param theDirection [in] the arrow direction.
-  //! @param thePlane [in] the face plane.
-  //! @param theArrowLength [in] the length of arrow.
-  //! @param theArrowAngle [in] the angle of arrow.
-  //! @param thePeakPnt [in] the arrow peak point.
-  //! @param theSidePnt1 [in] the first side point.
-  //! @param theSidePnt2 [in] the second side point.
-  Standard_EXPORT void PointsForArrow (const gp_Pnt& thePeakPnt,
-                                       const gp_Dir& theDirection,
-                                       const gp_Dir& thePlane,
-                                       const Standard_Real theArrowLength,
-                                       const Standard_Real theArrowAngle,
-                                       gp_Pnt& theSidePnt1,
-                                       gp_Pnt& theSidePnt2);
 
   //! Base procedure of computing selection (based on selection geometry data).
   //! @param theSelection [in] the selection structure to will with primitives.
@@ -525,7 +609,7 @@ protected: //! @name Selection geometry
       }
     }
 
-    //! Add new curve entry and return the referenece to populate it.
+    //! Add new curve entry and return the reference to populate it.
     Curve& NewCurve()
     {
       DimensionLine.Append( new Curve );
@@ -533,7 +617,7 @@ protected: //! @name Selection geometry
       return *aLastCurve;
     }
 
-    //! Add new arrow entry and return the referenece to populate it.
+    //! Add new arrow entry and return the reference to populate it.
     Arrow& NewArrow()
     {
       Arrows.Append( new Arrow );
@@ -550,6 +634,11 @@ protected: //! @name Value properties
   Standard_Real    myCustomValue;   //!< Value of the dimension (computed or user-defined).
   Standard_Boolean myIsValueCustom; //!< Is user-defined value.
 
+protected: //! @name Fixed text position properties
+
+  gp_Pnt                  myFixedTextPosition;   //!< Stores text position fixed by user.
+  Standard_Boolean        myIsTextPositionFixed; //!< Is the text label position fixed by user.
+
 protected: //! @name Units properties
 
   Standard_ExtCharacter    mySpecialSymbol;        //!< Special symbol.
@@ -559,10 +648,10 @@ protected: //! @name Geometrical properties
 
   GeometryType myGeometryType;  //!< defines type of shapes on which the dimension is to be built. 
 
-  gp_Pln           myPlane;       //!< Plane where dimension will be built (computed or user defined).
+  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.
+  Standard_Real    myFlyout;        //!< Flyout distance.
+  Standard_Boolean myIsValid;       //!< Is dimension geometry properly defined.
 
 private:
 
index 86b0ff4..1256283 100755 (executable)
@@ -708,3 +708,35 @@ Standard_Boolean AIS_LengthDimension::InitOneShapePoints (const TopoDS_Shape& th
 
   return IsValidPoints (myFirstPoint, mySecondPoint);
 }
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_LengthDimension::GetTextPosition() const
+{
+  if (IsTextPositionCustom())
+  {
+    return myFixedTextPosition;
+  }
+
+  // Counts text position according to the dimension parameters
+  return GetTextPositionForLinear (myFirstPoint, mySecondPoint);
+}
+
+//=======================================================================
+//function : SetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_LengthDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!myIsValid)
+  {
+    return;
+  }
+
+  myIsTextPositionFixed = Standard_True;
+  myFixedTextPosition = theTextPos;
+
+  SetToUpdate();
+}
index cd23349..a9f7669 100755 (executable)
@@ -187,15 +187,19 @@ public:
                                           const TopoDS_Shape& theSecondShape);
 
   //! @return the display units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const;
-  
+  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const;
+
   //! @return the model units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const;
+  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);
 
+  Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos);
+
+  Standard_EXPORT virtual const gp_Pnt GetTextPosition() const;
+
 public:
 
   DEFINE_STANDARD_RTTI(AIS_LengthDimension)
index ab737d0..f6760a6 100644 (file)
@@ -262,3 +262,35 @@ Standard_Boolean AIS_RadiusDimension::IsValidAnchor (const gp_Circ& theCircle,
   return Abs (anAnchorDist - aRadius) > Precision::Confusion()
       && aCirclePlane.Contains (theAnchor, Precision::Confusion());
 }
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_RadiusDimension::GetTextPosition() const
+{
+  if (IsTextPositionCustom())
+  {
+    return myFixedTextPosition;
+  }
+
+  // Counts text position according to the dimension parameters
+  return GetTextPositionForLinear (myAnchorPoint, myCircle.Location(), Standard_True);
+}
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_RadiusDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!myIsValid)
+  {
+    return;
+  }
+
+  myIsTextPositionFixed = Standard_True;
+  myFixedTextPosition = theTextPos;
+
+  SetToUpdate();
+}
index f501b9b..c05b84b 100644 (file)
@@ -50,7 +50,7 @@ public:
   //! orientation by location of the first point on that circle.
   //! @param theCircle [in] the circle to measure.
   //! @param theAnchorPoint [in] the point to define the position
-  //!        of the dimension attachement on the circle.
+  //!        of the dimension attachment on the circle.
   Standard_EXPORT AIS_RadiusDimension (const gp_Circ& theCircle,
                                        const gp_Pnt& theAnchorPoint);
 
@@ -88,7 +88,7 @@ public:
 
   //! Measure radius of the circle and orient the dimension so
   //! the dimension lines attaches to anchor point on the circle.
-  //! The dimension will become invalid if the radiuss of the circle
+  //! The dimension will become invalid if the radius of the circle
   //! is less than Precision::Confusion().
   //! @param theCircle [in] the circle to measure.
   //! @param theAnchorPoint [in] the point to attach the dimension lines.
@@ -102,15 +102,19 @@ public:
   Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Shape& theShape);
 
   //! @return the display units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const;
+  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const;
   
   //! @return the model units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const;
+  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);
 
+  Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos);
+
+  Standard_EXPORT virtual const gp_Pnt GetTextPosition() const;
+
 public:
 
   DEFINE_STANDARD_RTTI (AIS_RadiusDimension)
index f967c4b..e2db8a3 100644 (file)
@@ -106,6 +106,12 @@ is
     ExtensionSize (me) returns Real from Standard;
     ---Purpose: Returns extension size.
 
+    SetArrowTailSize (me : mutable; theSize : Real from Standard);
+    ---Purpose: Set size for arrow tail (extension without text).
+
+    ArrowTailSize (me) returns Real from Standard;
+    ---Purpose: Returns arrow tail size.
+
     SetValueStringFormat (me : mutable; theFormat : AsciiString from TCollection);
     ---Purpose: Sets "sprintf"-syntax format for formatting dimension value labels.
 
@@ -138,7 +144,10 @@ fields
 
     myExtensionSize : Real from Standard;
     ---Purpose: Size of arrow extensions.
-    -- The length of arrow tails if arrows are located outside dimension line.
+    -- The length of arrow tail with text if arrows are located outside dimension line.
+
+    myArrowTailSize : Real from Standard;
+    ---Purpose: Size of arrow tail (extension without text).
 
     myValueStringFormat : AsciiString from TCollection;
     ---Purpose: "sprintf"-syntax format for formatting dimension value labels.
index 6ab0716..3d42ab8 100755 (executable)
@@ -46,9 +46,10 @@ Prs3d_DimensionAspect::Prs3d_DimensionAspect()
   myArrowAspect->SetColor (Quantity_NOC_LAWNGREEN);
   myArrowAspect->SetAngle (M_PI * 20.0 / 180.0);
   myArrowAspect->SetLength (6.0);
-  myExtensionSize     = 6.0;
-  myValueStringFormat = "%g";
-  myToDisplayUnits    = Standard_False;
+  myExtensionSize      = 6.0;
+  myArrowTailSize      = 6.0;
+  myValueStringFormat  = "%g";
+  myToDisplayUnits     = Standard_False;
 }
 
 //=======================================================================
@@ -262,6 +263,24 @@ Standard_Real Prs3d_DimensionAspect::ExtensionSize() const
 }
 
 //=======================================================================
+//function : SetShortExtensionSize
+//purpose  : 
+//=======================================================================
+void Prs3d_DimensionAspect::SetArrowTailSize (const Standard_Real theSize)
+{
+  myArrowTailSize = theSize;
+}
+
+//=======================================================================
+//function : ShortExtensionSize
+//purpose  : 
+//=======================================================================
+Standard_Real Prs3d_DimensionAspect::ArrowTailSize() const
+{
+  return myArrowTailSize;
+}
+
+//=======================================================================
 //function : SetValueStringFormat
 //purpose  : 
 //=======================================================================
index d68e76e..842ecaf 100644 (file)
 #include <GC_MakePlane.hxx>
 #include <Geom_CartesianPoint.hxx>
 #include <Geom_Circle.hxx>
+#include <Geom_Line.hxx>
 #include <Geom_Plane.hxx>
+#include <GeomAPI_IntCS.hxx>
+#include <gce_MakeLin.hxx>
+#include <gce_MakePln.hxx>
 #include <gp_Circ.hxx>
 #include <gp_Pln.hxx>
 #include <IntAna_IntConicQuad.hxx>
@@ -71,6 +75,9 @@
 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
 #include <ViewerTest_EventManager.hxx>
 
+extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
+                                           const Handle(AIS_InteractiveObject)& theAISObj,
+                                           Standard_Boolean theReplaceIfExists = Standard_True);
 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
 extern Handle(AIS_InteractiveContext)& TheAISContext ();
@@ -83,104 +90,87 @@ extern Handle(AIS_InteractiveContext)& TheAISContext ();
 #define EdgeMask 0x02
 #define FaceMask 0x04
 
-static Standard_Boolean ComputeIntersection(const gp_Lin& L,const gp_Pln& ThePl, gp_Pnt& TheInter)
-{
-  static IntAna_Quadric TheQuad;
-  TheQuad.SetQuadric(ThePl);
-  static IntAna_IntConicQuad QQ;
-   QQ.Perform(L,TheQuad);
-  if(QQ.IsDone()){
-    if(QQ.NbPoints()>0){
-      TheInter = QQ.Point(1);
-      return Standard_True;
-    }
-  }
-  return Standard_False;
-}
-
 //=======================================================================
 //function : Get3DPointAtMousePosition
-//purpose  : calcul du point 3D correspondant a la position souris dans le plan de 
-// la vue...
+//purpose  : Calculates the 3D points corresponding to the mouse position
+//           in the plane of the view
 //=======================================================================
-
-static gp_Pnt Get3DPointAtMousePosition ()
+static gp_Pnt Get3DPointAtMousePosition()
 {
-  Handle(V3d_View) aview = ViewerTest::CurrentView();
-  static Select3D_Projector prj;
-  prj.SetView(aview);
-  
-  // le plan de la vue...
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  static Select3D_Projector aProjector;
+  aProjector.SetView (aView);
+
   Standard_Real xv,yv,zv;
-  aview->Proj(xv,yv,zv);
+  aView->Proj (xv,yv,zv);
   Standard_Real xat,yat,zat;
-  aview->At(xat,yat,zat);
-  gp_Pln ThePl(gp_Pnt(xat,yat,zat),gp_Dir(xv,yv,zv));
-  Standard_Integer xpix,ypix;
-  Standard_Real x,y;
-  ViewerTest::GetMousePosition(xpix,ypix);
-  aview->Convert(xpix,ypix,x,y); // espace reel 2D de la vue...
-  gp_Lin L = prj.Shoot(x,y);
-  gp_Pnt P(0.,0.,0.);
-
-  ComputeIntersection(L,ThePl,P);
-  return P;
+  aView->At(xat,yat,zat);
+  gp_Pln aPlane (gp_Pnt(xat,yat,zat), gp_Dir(xv,yv,zv));
+  
+  Standard_Integer aPixX, aPixY;
+  Standard_Real aX, aY, aZ, aDX, aDY, aDZ;
+
+  ViewerTest::GetMousePosition (aPixX, aPixY);
+  aView->ConvertWithProj (aPixX, aPixY, aX, aY, aZ, aDX, aDY, aDZ);
+  gp_Lin aLine( gp_Pnt(aX, aY, aZ), gp_Dir(aDX, aDY, aDZ) );
+
+  // Compute intersection
+  Handle(Geom_Line) aGeomLine = new Geom_Line (aLine);
+  Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
+  GeomAPI_IntCS anIntersector (aGeomLine, aGeomPlane);
+  if (!anIntersector.IsDone() || anIntersector.NbPoints() == 0)
+  {
+    return gp::Origin();
+  }
+  return anIntersector.Point (1);
 }
 
 //=======================================================================
-//function : ComputeNewPlaneForDim
-//purpose  : 
+//function : Get3DPointAtMousePosition
+//purpose  : Calculates the 3D points corresponding to the mouse position
+//           in the plane of the view
 //=======================================================================
-
-static void ComputeNewPlaneForDim (const Handle(AIS_Relation)& R,
-                                   gp_Pln& ,
-                                   gp_Pnt&)
+static Standard_Boolean Get3DPointAtMousePosition (const gp_Pnt& theFirstPoint,
+                                                   const gp_Pnt& theSecondPoint,
+                                                   gp_Pnt& theOutputPoint)
 {
-// 0   COMPOUND,
-// 1   COMPSOLID,
-// 2   SOLID,
-// 3   SHELL,
-// 4   FACE,
-// 5           WIRE,
-// 6   EDGE,
-// 7   VERTEX,
-// 8   SHAPE
-  TopoDS_Shape S1 = R->FirstShape();
-  TopoDS_Shape S2 = R->SecondShape();
-  TopAbs_ShapeEnum Typ1 = S1.ShapeType();
-  TopAbs_ShapeEnum Typ2 = S2.ShapeType();
-  
-  gp_Pnt thepoint [3];
-  thepoint[0] = Get3DPointAtMousePosition();
-  
-  // on met l'objet le plus petit en 1...
-  if((Standard_Integer)Typ2>(Standard_Integer)Typ1){
-    
-    TopoDS_Shape tmpS = S1;
-    TopAbs_ShapeEnum tmpT = Typ1;
-    S1= S2;
-    Typ1 = Typ2;
-    S2= tmpS;
-    Typ2 = tmpT;
-  }
-/*  
-  switch (Typ1){
-  case TopAbs_VERTEX:{
-    thepoint[0]  = BRep_Tool::Pnt(S1);
-    if(Typ2==TopAbs_VERTEX)
-      thepoint[1] = BRep_Tool::Pnt(S2);
-    else if(Typ2==TopAbs_EDGE){
-      TopoDS_Vertex  Va,Vb;
-      TopExp::Vertices(S2,Va,Vb);
-      thepoint[1] = BRep_Tool::Pnt(Va);
-    }
-    else if(Typ2==TopAbs_FACE){
-    }
-    break;
+  theOutputPoint = gp::Origin();
+
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+
+  Standard_Integer aPixX, aPixY;
+  Standard_Real aX, aY, aZ, aDx, aDy, aDz, aUx, aUy, aUz;
+
+  // Get 3D point in view coordinates and projection vector from the pixel point.
+  ViewerTest::GetMousePosition (aPixX, aPixY);
+  aView->ConvertWithProj (aPixX, aPixY, aX, aY, aZ, aDx, aDy, aDz);
+  gp_Lin aProjLin (gp_Pnt(aX, aY, aZ), gp_Dir(aDx, aDy, aDz));
+
+  // Get plane
+  gp_Vec aDimVec (theFirstPoint, theSecondPoint);
+  aView->Up (aUx, aUy, aUz);
+  gp_Vec aViewUp (aUx, aUy, aUz);
+
+  if (aDimVec.IsParallel (aViewUp, Precision::Angular()))
+  {
+    theOutputPoint = Get3DPointAtMousePosition();
+    return Standard_True;
   }
-  case TopAbs_EDGE:
+
+  gp_Vec aDimNormal = aDimVec ^ aViewUp;
+  gp_Pln aViewPlane= gce_MakePln (theFirstPoint, aDimNormal);
+
+  // Get intersection of view plane and projection line
+  Handle(Geom_Plane) aPlane = new Geom_Plane (aViewPlane);
+  Handle(Geom_Line) aProjLine = new Geom_Line (aProjLin);
+  GeomAPI_IntCS anIntersector (aProjLine, aPlane);
+  if (!anIntersector.IsDone() || anIntersector.NbPoints() == 0)
+  {
+    return Standard_False;
   }
-*/
+
+  theOutputPoint = anIntersector.Point (1);
+  return Standard_True;
 }
 
 //=======================================================================
@@ -555,71 +545,70 @@ static int VDimBuilder(Draw_Interpretor& theDi, Standard_Integer theArgsNb, cons
 
 static int VAngleDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
 {
-  Standard_Integer myCurrentIndex;
-  if (argc!=2) {di<<" vangledim error."<<"\n";return 1;}
+  Standard_Integer aCurrentIndex;
+  if (argc!=2)
+  {
+    di << argv[0] << " error : wrong number of parameters.\n";
+    return 1;
+  }
+
   TheAISContext()->CloseAllContexts();
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  di<<" Select two  edges coplanar or not."<<"\n";
-  Standard_Integer argcc = 5;
-  const char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-  const char **argvv = (const char **) buff;
-  while (ViewerMainLoop( argcc, argvv) ) { }
-  
-  TopoDS_Shape ShapeA;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeA = TheAISContext()->SelectedShape();
+  aCurrentIndex =  TheAISContext()->OpenLocalContext();
+  // Set selection mode for edges.
+  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2));
+  di << "Select two edges coplanar or not.\n";
+
+  Standard_Integer anArgsNum = 5;
+  const char *aBuffer[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
+  const char **anArgsVec = (const char **) aBuffer;
+  while (ViewerMainLoop (anArgsNum, anArgsVec)) { }
+
+  TopoDS_Shape aFirstShape;
+  for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
+  {
+    aFirstShape = TheAISContext()->SelectedShape();
   }
-  // Si ShapeA est un Edge.
-  if (ShapeA.ShapeType()== TopAbs_EDGE ) {
-    
-    // Boucle d'attente waitpick.
-    Standard_Integer argccc = 5;
-    const char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-    const char **argvvv = (const char **) bufff;
-    while (ViewerMainLoop( argccc, argvvv) ) { }
-    // fin de la boucle
-    
-    TopoDS_Shape ShapeB;
-    for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-      ShapeB = TheAISContext()->SelectedShape();
+
+  if (aFirstShape.IsNull())
+  {
+    di << argv[0] << " error : no picked shape.\n";
+    return 1;
+  }
+
+  if (aFirstShape.ShapeType()== TopAbs_EDGE)
+  {
+    while (ViewerMainLoop (anArgsNum, anArgsVec)) { }
+
+    TopoDS_Shape aSecondShape;
+    for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
+    {
+      aSecondShape = TheAISContext()->SelectedShape();
     }
-    // ShapeB doit etre un Edge
-    if (ShapeB.ShapeType()!= TopAbs_EDGE ) {
-      di<<" vangledim error: you shoud have selected an edge."<<"\n";return 1;
+
+    if (aSecondShape.IsNull())
+    {
+      di << argv[0] << " error : no picked shape.\n";
+      return 1;
+    }
+
+    if (aSecondShape.ShapeType() != TopAbs_EDGE)
+    {
+      di << argv[0] <<" error: you should have selected an edge.\n"; return 1;
     }
-    
-    // on recupere les vertexes de edgeA
-    TopoDS_Vertex Va,Vb;
-    TopExp::Vertices(TopoDS::Edge(ShapeA),Va ,Vb );
-    // Recuperation des points.
-    gp_Pnt A=BRep_Tool::Pnt(Va);
-    gp_Pnt B=BRep_Tool::Pnt(Vb);
-    gp_Pnt C(A.X()+5 ,A.Y()+5 ,A.Z()+5 );
 
+    // Close local context to draw dimension in the neutral point.
+    TheAISContext()->CloseLocalContext (aCurrentIndex);
 
-    // Construction du plane. Methode pas orthodoxe!
-    GC_MakePlane MkPlane(A ,B ,C );
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    
-    // Construction du texte.
-    TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString( 90 ) );
-    
-    // Fermeture du context local.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    
-    // Construction de l'AIS dimension
-    Handle (AIS_AngleDimension) myAISDim= new AIS_AngleDimension (TopoDS::Edge(ShapeA) ,TopoDS::Edge(ShapeB));
-    GetMapOfAIS().Bind (myAISDim,argv[1]);
-    TheAISContext()->Display(myAISDim );
-    
+    // Construct the dimension.
+    Handle (AIS_AngleDimension) aDim= new AIS_AngleDimension (TopoDS::Edge(aFirstShape) ,TopoDS::Edge(aSecondShape));
+    VDisplayAISObject (argv[1], aDim);
   }
-else {
-  di<<" vangledim error: you must select 2 edges."<<"\n";return 1;
-}
-  
-  
+  else
+  {
+    di << argv[0] << " error: you must select 2 edges.\n";
+    return 1;
+  }
+
   return 0;
 }
 
@@ -632,59 +621,69 @@ else {
 static int VDiameterDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
 {
   // Declarations
-  Standard_Integer myCurrentIndex;
-  Standard_Real theRadius;
-    
+  Standard_Integer aCurrentIndex;
+  Standard_Real aRadius;
+
   // Verification
-  if (argc!=2) {di<<" vdiameterdim error"<<"\n";return 1;}
-  // Fermeture des contextes locaux
+  if (argc != 2)
+  {
+    di<<" vdiameterdim error"<<"\n";
+    return 1;
+  }
+
+  // Close all local contexts
   TheAISContext()->CloseAllContexts();
-  // Ouverture d'un contexte local et recuperation de son index.
+  // Open local context and get its index for recovery
   TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
+  aCurrentIndex = TheAISContext()->IndexOfCurrentLocal();
   
-  // On active les modes de selections Edges et Faces.
+  // Activate 'edge' selection mode
   TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
   di<<" Select an circled edge."<<"\n";
   
-  // Boucle d'attente waitpick.
+  // Loop that will handle the picking.
   Standard_Integer argcc = 5;
   const char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
   const char **argvv = (const char **) buff;
   while (ViewerMainLoop( argcc, argvv) ) { }
-  // fin de la boucle
+  // end of the loop.
   
-  TopoDS_Shape ShapeA;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeA = TheAISContext()->SelectedShape();
+  TopoDS_Shape aShape;
+  for(TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
+  {
+    aShape = TheAISContext()->SelectedShape();
   }
-  if (ShapeA.ShapeType()==TopAbs_EDGE  ) {
-    
-    // Recuperation du rayon 
-    BRepAdaptor_Curve theCurve(TopoDS::Edge(ShapeA));
-    if (theCurve.GetType()!=GeomAbs_Circle ) {di<<"vdiameterdim error: the edge is not a circular one."<<"\n";return 1;}
-    else {
-      gp_Circ theGpCircle=theCurve.Circle();
-      theRadius=2.*theGpCircle.Radius();
-    }
-    
-    // Construction du texte.
-    TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theRadius  ) );
-    // Construction de L'AIS_AngleDimension.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    
-    Handle (AIS_DiameterDimension) myDiamDim= new AIS_DiameterDimension(ShapeA);
-    GetMapOfAIS().Bind (myDiamDim,argv[1]);
-    TheAISContext()->Display(myDiamDim );
-    
+
+  if (aShape.IsNull())
+  {
+    di << argv[0] << ": no shape is selected." << "\n";
+    return 1;
   }
-  
-  else {
-    di<<" vdiameterdim error: the selection of a face or an edge was expected."<<"\n";return 1;
+
+  if (aShape.ShapeType() != TopAbs_EDGE)
+  {
+    di << " vdiameterdim error: the selection of a face or an edge was expected." << "\n";
+    return 1;
   }
-  
+
+  // Compute the radius
+  BRepAdaptor_Curve aCurve (TopoDS::Edge (aShape));
+
+  if (aCurve.GetType() != GeomAbs_Circle)
+  {
+    di << "vdiameterdim error: the edge is not a circular one." << "\n";
+    return 1;
+  }
+
+  gp_Circ aCircle = aCurve.Circle();
+  aRadius = 2.0 * aCircle.Radius();
+
+  // Construction of the diameter dimension.
+  TheAISContext()->CloseLocalContext (aCurrentIndex);
+  Handle (AIS_DiameterDimension) aDiamDim= new AIS_DiameterDimension (aShape);
+  VDisplayAISObject (argv[1], aDiamDim);
+
   return 0;
-  
 }
 
 
@@ -1246,339 +1245,292 @@ static int VIdenticRelation(Draw_Interpretor& di, Standard_Integer argc, const c
 #include <BRepExtrema_ExtFF.hxx>
 #include <TCollection_ExtendedString.hxx>
 #include <BRepExtrema_DistShapeShape.hxx>
-#include <GC_MakePlane.hxx>
+#include <gce_MakePln.hxx>
 #include <TopExp_Explorer.hxx>
 #include <BRepBuilderAPI_MakeVertex.hxx>
+
 static int VLenghtDimension(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
 {
   // Declarations
-  Standard_Integer myCurrentIndex;
-  Standard_Real theDist;
-  
+  Standard_Integer aCurrentIndex;
   // Verification
-  if (argc!=2) {di<<" videntity error: no arguments allowed."<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
+  if (argc != 2)
+  {
+    di << argv[0] << " error: wrong number of arguments.\n";
+    return 1;
+  }
+
+  // Close all local contexts
   TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  myCurrentIndex = TheAISContext()->OpenLocalContext();
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1) );
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
-  di<<" Select an edge, a face or a vertex. "<<"\n";
-  
-  // Boucle d'attente waitpick.
+
+  // Open local context
+  aCurrentIndex = TheAISContext()->OpenLocalContext();
+  // Activate 'edge', 'face' and 'vertex' selection modes.
+  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2));
+  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1));
+  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4));
+
+  // First shape picking
+  di << " Select an edge, a face or a vertex. " << "\n";
+  // Loop that will handle the picking.
   Standard_Integer argc1 = 5;
   const char *buf1[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
   const char **argv1 = (const char **) buf1;
   while (ViewerMainLoop( argc1, argv1) ) { }
+  // end of the loop.
 
-  // fin de la boucle
-  TopoDS_Shape ShapeA;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeA = TheAISContext()->SelectedShape();
+  TopoDS_Shape aFirstShape;
+  for(TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
+  {
+    aFirstShape = TheAISContext()->SelectedShape();
   }
-  di<<" Select an edge, a face or a vertex. "<<"\n";
-  // Boucle d'attente waitpick.
+
+  if (aFirstShape.IsNull())
+  {
+    di << argv[0] << "error: no first picked shape.\n";
+    return 1;
+  }
+
+  // Second shape picking
+  di << " Select an edge, a face or a vertex. " << "\n";
+  // Loop that will handle the picking.
   Standard_Integer argc2 = 5;
   const char *buf2[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
   const char **argv2 = (const char **) buf2;
   while (ViewerMainLoop( argc2, argv2) ) { }
-  // fin de la boucle
-  
-  TopoDS_Shape ShapeB;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeB = TheAISContext()->SelectedShape();
+
+  TopoDS_Shape aSecondShape;
+  for(TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
+  {
+    aSecondShape = TheAISContext()->SelectedShape();
   }
-  // ShapeA est un edge.
-  // ===================
-  if (ShapeA.ShapeType()==TopAbs_EDGE ) {
-    TopoDS_Edge  EdgeA=TopoDS::Edge(ShapeA);
-    
-    // Si ShapeB est un edge
-    if (ShapeB.ShapeType()==TopAbs_EDGE ) {
-      TopoDS_Edge  EdgeB=TopoDS::Edge(ShapeB);
-      BRepExtrema_ExtCC myDeltaEdge (EdgeA ,EdgeB );
-      // on verifie qu'ils ne sont pas paralleles.
-      if (!myDeltaEdge.IsParallel() ) {di<<"vlenghtdim error: non parallel edges."<<"\n";return 1; }
-      
-      // On saisit la distance et on l'arrondit!
-      theDist=Round (sqrt(myDeltaEdge.SquareDistance(1))*10. )/10.;
-      
-      // On recupere 3 Points des edges pour construire un plane.
-      TopoDS_Vertex  Va,Vb,Vc,Vd;
-      TopExp::Vertices(EdgeA,Va,Vb);
-      TopExp::Vertices(EdgeB,Vc,Vd);
-      gp_Pnt A=BRep_Tool::Pnt(Va);
-      gp_Pnt B=BRep_Tool::Pnt(Vb);
-      gp_Pnt C=BRep_Tool::Pnt(Vc);
-      
-      // Creation du Plane contenant la relation.
-      GC_MakePlane MkPlane(A,B,C);
-      Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-      
-      TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) );
-      
-      // On ferme le contexte local.
-      TheAISContext()->CloseLocalContext(myCurrentIndex);
-      
-      // on construit l'AISLenghtDimension.
-      Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (EdgeA,EdgeB,theGeomPlane->Pln());
-      TheAISContext()->Display(myLenghtDim );
-      GetMapOfAIS().Bind (myLenghtDim ,argv[1]);
+
+  if (aSecondShape.IsNull())
+  {
+    di << argv[0] << "error: no second picked shape.\n";
+    return 1;
+  }
+
+  if (aFirstShape.ShapeType() == TopAbs_EDGE)
+  {
+    TopoDS_Edge EdgeA = TopoDS::Edge (aFirstShape);
+
+    if (aSecondShape.ShapeType() == TopAbs_EDGE)
+    {
+      TopoDS_Edge EdgeB = TopoDS::Edge (aSecondShape);
+      BRepExtrema_ExtCC myDeltaEdge (EdgeA ,EdgeB);
+
+      if (!myDeltaEdge.IsParallel())
+      {
+        di << argv[0] << " error: non parallel edges." << "\n";
+        return 1;
+      }
+
+      // 3 points of edges is recovered to build a plane
+      TopoDS_Vertex aVertex1, aVertex2, aVertex3, aVertex4;
+      TopExp::Vertices (EdgeA, aVertex1, aVertex2);
+      TopExp::Vertices (EdgeB, aVertex3, aVertex4);
+      gp_Pnt A = BRep_Tool::Pnt (aVertex1);
+      gp_Pnt B = BRep_Tool::Pnt (aVertex2);
+      gp_Pnt C = BRep_Tool::Pnt (aVertex3);
+
+      gce_MakePln aMakePlane (A,B,C);
+      gp_Pln aPlane= aMakePlane.Value();
+
+      // Close local context
+      TheAISContext()->CloseLocalContext (aCurrentIndex);
+
+      // Construct the dimension
+      Handle(AIS_LengthDimension ) aLenghtDim = new AIS_LengthDimension (EdgeA, EdgeB, aPlane);
+      TheAISContext()->Display (aLenghtDim);
+      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
     }
-    
-    // Si ShapeB est un vertex.
-    else if (ShapeB.ShapeType()==TopAbs_VERTEX ) {
-      
-      TopoDS_Vertex  VertexB=TopoDS::Vertex(ShapeB);
-      BRepExtrema_ExtPC myDeltaEdgeVertex  (VertexB ,EdgeA );
-      
-      // On saisit la distance et on l'arrondit!
-      theDist=Round (sqrt (myDeltaEdgeVertex.SquareDistance(1))*10. )/10.;
-      
-      // On recupere 2 Points de EdgeA pour construire un plane.
-      TopoDS_Vertex  Va,Vb;
-      TopExp::Vertices(EdgeA,Va,Vb);
-      gp_Pnt A=BRep_Tool::Pnt(Va);
-      gp_Pnt B=BRep_Tool::Pnt(Vb);
-      gp_Pnt C=BRep_Tool::Pnt(VertexB);
-      
-      GC_MakePlane MkPlane(A,B,C);
-      Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-      
-      TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) );
-      TheAISContext()->CloseLocalContext(myCurrentIndex);
-      Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (EdgeA,VertexB,theGeomPlane->Pln());
-      TheAISContext()->Display(myLenghtDim );
-      GetMapOfAIS().Bind (myLenghtDim ,argv[1]);
-      
-      
+
+    else if (aSecondShape.ShapeType() == TopAbs_VERTEX)
+    {
+      TopoDS_Vertex aVertex = TopoDS::Vertex (aSecondShape);
+      BRepExtrema_ExtPC myDeltaEdgeVertex  (aVertex ,EdgeA);
+
+      TopoDS_Vertex aVertex1, aVertex2;
+      TopExp::Vertices (EdgeA, aVertex1, aVertex2);
+      gp_Pnt A=BRep_Tool::Pnt (aVertex1);
+      gp_Pnt B=BRep_Tool::Pnt (aVertex2);
+      gp_Pnt C=BRep_Tool::Pnt (aVertex);
+
+      gce_MakePln aMakePlane (A,B,C);
+      gp_Pln aPlane= aMakePlane.Value();
+
+      TheAISContext()->CloseLocalContext (aCurrentIndex);
+      Handle(AIS_LengthDimension) aLenghtDim=new AIS_LengthDimension (EdgeA, aVertex, aPlane);
+      TheAISContext()->Display (aLenghtDim);
+      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
     }
-    
-    // Si ShapeB est une Face
+
+    // Second shape is a face
     else
     {
-      TopoDS_Face FaceB=TopoDS::Face(ShapeB);
-      BRepExtrema_ExtCF myDeltaEdgeFace  (EdgeA,FaceB );
-      // On verifie que l'edge est bien parallele a la face.
-      if (!myDeltaEdgeFace.IsParallel() ) {di<<"vdistdim error: the edge isn't parallel to the face;can't compute the distance. "<<"\n";return 1; }
-
-      // on construit l'AISLenghtDimension.
-      Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (FaceB,EdgeA);
-      TheAISContext()->Display(myLenghtDim );
-      GetMapOfAIS().Bind (myLenghtDim ,argv[1]);
+      TopoDS_Face FaceB = TopoDS::Face (aSecondShape);
+      BRepExtrema_ExtCF aDeltaEdgeFace (EdgeA,FaceB);
+
+      if (!aDeltaEdgeFace.IsParallel())
+      {
+        di << argv[0] << "error: the edge isn't parallel to the face;can't compute the distance." << "\n";
+        return 1;
+      }
+
+      Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (FaceB, EdgeA);
+      TheAISContext()->Display (aLenghtDim);
+      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
     }
   }
+  else if (aFirstShape.ShapeType() == TopAbs_VERTEX)
+  {
+    TopoDS_Vertex  VertexA = TopoDS::Vertex (aFirstShape);
+    if (aSecondShape.ShapeType() == TopAbs_EDGE )
+    {
+      TopoDS_Edge  EdgeB=TopoDS::Edge (aSecondShape);
+      BRepExtrema_ExtPC aDeltaEdgeVertex (VertexA, EdgeB);
 
-  // ShapeA est un vertex
-  // ====================
-  if (ShapeA.ShapeType()==TopAbs_VERTEX ) {
-    TopoDS_Vertex  VertexA=TopoDS::Vertex(ShapeA);
-    
-    // Si ShapeB est un edge.
-    if (ShapeB.ShapeType()==TopAbs_EDGE ) {
-      TopoDS_Edge  EdgeB=TopoDS::Edge(ShapeB);
-      BRepExtrema_ExtPC myDeltaEdgeVertex  (VertexA ,EdgeB );
-      // On saisit la distance et on l'arrondit!
-      theDist=Round (sqrt (myDeltaEdgeVertex.SquareDistance(1))*10. )/10.;
-      
-      // On recupere 2 Points de EdgeB pour construire un plane.
-      TopoDS_Vertex  Va,Vb;
-      TopExp::Vertices(EdgeB,Va,Vb);
-      gp_Pnt A=BRep_Tool::Pnt(Va);
-      gp_Pnt B=BRep_Tool::Pnt(Vb);
-      gp_Pnt C=BRep_Tool::Pnt(VertexA);
-      
-      // Creation du Plane contenant la relation.
-      GC_MakePlane MkPlane(A,B,C);
-      Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-      
-      // Fermeture du contexte local.
-      TheAISContext()->CloseLocalContext(myCurrentIndex);
-      // Construction du texte.
-      TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) );
-      
-      // on construit l'AISLenghtDimension.
-      Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (EdgeB,VertexA,theGeomPlane->Pln());
-      TheAISContext()->Display(myLenghtDim );
-      GetMapOfAIS().Bind (myLenghtDim ,argv[1]);
-      
-    }
-    
-    // Si ShapeB est un vertex.
-    else if (ShapeB.ShapeType()==TopAbs_VERTEX ) {
-      TopoDS_Vertex  VertexB=TopoDS::Vertex(ShapeB);
-      BRepExtrema_DistShapeShape myDeltaVertexVertex  (VertexA ,VertexB );
-      // On saisit la distance et on l'arrondit!
-      theDist=Round (myDeltaVertexVertex.Value()*10. )/10.;
-      
-      // Les deux premiers points.
-      gp_Pnt A=BRep_Tool::Pnt(VertexA);
-      gp_Pnt B=BRep_Tool::Pnt(VertexB);
-      gp_Pnt C(B.X()+10,B.Y()+10,B.Z()+10);
+      TopoDS_Vertex aVertex1, aVertex2;
+      TopExp::Vertices(EdgeB, aVertex1, aVertex2);
+      gp_Pnt A = BRep_Tool::Pnt (aVertex1);
+      gp_Pnt B = BRep_Tool::Pnt (aVertex2);
+      gp_Pnt C = BRep_Tool::Pnt (VertexA);
 
-      GC_MakePlane MkPlane(A,B,C);
-      Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-      
-      // Fermeture du contexte local.
-      TheAISContext()->CloseLocalContext(myCurrentIndex);
-      // Construction du texte.
-      TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) );
-      
-      // on construit l'AISLenghtDimension.
-      Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (VertexA,VertexB,theGeomPlane->Pln());
-      TheAISContext()->Display(myLenghtDim );
-      GetMapOfAIS().Bind (myLenghtDim ,argv[1]);
-      
-      
-      
-      
+      gce_MakePln aMakePlane (A,B,C);
+      gp_Pln aPlane = aMakePlane.Value();
+
+      // Close local contex by its index.
+      TheAISContext()->CloseLocalContext (aCurrentIndex);
+
+      // Construct the dimension.
+      Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (EdgeB,VertexA, aPlane);
+      TheAISContext()->Display (aLenghtDim);
+      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
     }
-    
-    // Si ShapeB est une Face
-    else {
-      
-      TopoDS_Face  FaceB=TopoDS::Face(ShapeB);
-      BRepExtrema_ExtPF myDeltaVertexFace  (VertexA ,FaceB );
-      // On saisit la distance et on l'arrondit!
-      theDist=Round (sqrt (myDeltaVertexFace.SquareDistance(1))*10. )/10.;
-      
-      // Premier point.
-      gp_Pnt A=BRep_Tool::Pnt(VertexA);
-      
-      // On recupere 1 edge de FaceB.
-      TopExp_Explorer FaceExp(FaceB,TopAbs_EDGE);
-      TopoDS_Edge EdFromB=TopoDS::Edge(FaceExp.Current() );
-      // On recupere les deux vertexes extremites de l'edge de face B
-      TopoDS_Vertex  Vb,Vc;
-      TopExp::Vertices(EdFromB,Vb,Vc);
-      gp_Pnt C=BRep_Tool::Pnt(Vc);
-      
-      // On projette le point B sur la Face car il 
-      // n'existe pas de constructeurs AIS_LD PointFace
-      // on est donc oblige de creer un nouveau TopoDS_Vertex.
-      gp_Pnt theProjA=myDeltaVertexFace.Point(1);
-      BRepBuilderAPI_MakeVertex theVertexMaker(theProjA);
-      TopoDS_Vertex VertexAproj=theVertexMaker.Vertex();
-      // Creation du Plane contenant la relation.
-      GC_MakePlane MkPlane(A,theProjA,C);
-      Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-      
-      // Fermeture du contexte local.
-      TheAISContext()->CloseLocalContext(myCurrentIndex);
-      // Construction du texte.
-      TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) );
-      
-      // on construit l'AISLenghtDimension.
-      Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (VertexA,VertexAproj,theGeomPlane->Pln());
-      TheAISContext()->Display(myLenghtDim );
-      GetMapOfAIS().Bind (myLenghtDim ,argv[1]);
-      
+
+    else if (aSecondShape.ShapeType() == TopAbs_VERTEX)
+    {
+      TopoDS_Vertex  VertexB = TopoDS::Vertex (aSecondShape);
+
+      gp_Pnt A = BRep_Tool::Pnt (VertexA);
+      gp_Pnt B = BRep_Tool::Pnt (VertexB);
+      gp_Pnt C(B.X() + 10.0, B.Y() + 10.0, B.Z() + 10.0);
+
+      gce_MakePln aMakePlane (A,B,C);
+      gp_Pln aPlane= aMakePlane.Value();
+
+      TheAISContext()->CloseLocalContext (aCurrentIndex);
+
+      Handle(AIS_LengthDimension ) aLenghtDim = new AIS_LengthDimension (VertexA, VertexB, aPlane);
+      TheAISContext()->Display (aLenghtDim);
+      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
+    }
+    // The second shape is face
+    else
+    {
+      TopoDS_Face  FaceB = TopoDS::Face (aSecondShape);
+
+      BRepExtrema_ExtPF aDeltaVertexFace (VertexA, FaceB);
+
+      gp_Pnt A = BRep_Tool::Pnt (VertexA);
+
+      // Recover edge from face.
+      TopExp_Explorer aFaceExp (FaceB,TopAbs_EDGE);
+      TopoDS_Edge aSecondEdge = TopoDS::Edge (aFaceExp.Current());
+
+      TopoDS_Vertex aVertex1, aVertex2;
+      TopExp::Vertices (aSecondEdge, aVertex1, aVertex2);
+      gp_Pnt C = BRep_Tool::Pnt (aVertex2);
+
+      gp_Pnt aProjA = aDeltaVertexFace.Point(1);
+      BRepBuilderAPI_MakeVertex aVertexMaker (aProjA);
+      TopoDS_Vertex aVertexAProj = aVertexMaker.Vertex();
+
+      // Create working plane for the dimension.
+      gce_MakePln aMakePlane (A, aProjA, C);
+      gp_Pln aPlane = aMakePlane.Value();
+
+      TheAISContext()->CloseLocalContext (aCurrentIndex);
+
+      // Construct the dimension.
+      Handle(AIS_LengthDimension ) aLenghtDim = new AIS_LengthDimension (VertexA, aVertexAProj, aPlane);
+      TheAISContext()->Display (aLenghtDim);
+      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
     }
-    
-    
-    
   }
-  
-  // ShapeA est une Face
-  // ===================
-  else {
-    TopoDS_Face  FaceA=TopoDS::Face(ShapeA);
-    // Si ShapeB est un edge.
-    if (ShapeB.ShapeType()==TopAbs_EDGE ) {
-      TopoDS_Edge EdgeB=TopoDS::Edge(ShapeB);
-      BRepExtrema_ExtCF myDeltaEdgeFace  (EdgeB,FaceA );
-      // On verifie que l'edge est bien parallele a la face.
-      if (!myDeltaEdgeFace.IsParallel() ) {di<<"vdistdim error: the edge isn't parallel to the face;can't compute the distance. "<<"\n";return 1; }
-      
-      // On saisit la distance et on l'arrondit!
-      theDist=Round (sqrt (myDeltaEdgeFace.SquareDistance(1))*10. )/10.;
-      
-      // Construction du texte.
-      TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) );
-      
-      // on construit l'AISLenghtDimension.
-      Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (FaceA,EdgeB);
-      TheAISContext()->Display(myLenghtDim );
-      GetMapOfAIS().Bind (myLenghtDim ,argv[1]);
-      
+
+  // The first shape is a face.
+  else
+  {
+    TopoDS_Face FaceA = TopoDS::Face (aFirstShape);
+
+    if (aSecondShape.ShapeType() == TopAbs_EDGE)
+    {
+      TopoDS_Edge EdgeB = TopoDS::Edge (aSecondShape);
+      BRepExtrema_ExtCF aDeltaEdgeFace (EdgeB,FaceA );
+
+      if (!aDeltaEdgeFace.IsParallel())
+      {
+        di << argv[0] << " error: the edge isn't parallel to the face;can't compute the distance. " << "\n";
+        return 1;
+      }
+
+      Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (FaceA, EdgeB);
+      TheAISContext()->Display (aLenghtDim);
+      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
     }
-    
-    // Si ShapeB est un vertex.
-    else if (ShapeB.ShapeType()==TopAbs_VERTEX ) {
-      
-      TopoDS_Vertex  VertexB=TopoDS::Vertex(ShapeB);
-      BRepExtrema_ExtPF myDeltaVertexFace  (VertexB ,FaceA );
-      // On saisit la distance et on l'arrondit!
-      theDist=Round (sqrt (myDeltaVertexFace.SquareDistance(1))*10. )/10.;
-      
-      // Premier point.
-      gp_Pnt B=BRep_Tool::Pnt(VertexB);
-      
-      // On recupere 1 edge de FaceA.
-      TopExp_Explorer FaceExp(FaceA,TopAbs_EDGE);
-      TopoDS_Edge EdFromA=TopoDS::Edge(FaceExp.Current() );
-      // On recupere les deux vertexes extremites de l'edge de face A
-      TopoDS_Vertex  Va,Vc;
-      TopExp::Vertices(EdFromA,Va,Vc);
-      gp_Pnt A=BRep_Tool::Pnt(Va);
+
+    else if (aSecondShape.ShapeType() == TopAbs_VERTEX)
+    {
+      TopoDS_Vertex  VertexB = TopoDS::Vertex (aSecondShape);
+      BRepExtrema_ExtPF aDeltaVertexFace (VertexB, FaceA);
+
+      gp_Pnt B = BRep_Tool::Pnt (VertexB);
+
+      TopExp_Explorer aFaceExp (FaceA, TopAbs_EDGE);
+      TopoDS_Edge anEdgeFromA = TopoDS::Edge (aFaceExp.Current());
+      TopoDS_Vertex  aVertex1, aVertex2;
+      TopExp::Vertices(anEdgeFromA, aVertex1, aVertex2);
+      gp_Pnt A=BRep_Tool::Pnt(aVertex1);
 
 #ifdef DEB
-      gp_Pnt C = BRep_Tool::Pnt(Vc);
+      gp_Pnt C = BRep_Tool::Pnt(aVertex2);
 #endif
 
-      // On projette le point B sur la Face car il 
-      // n'existe pas de constructeurs AIS_LD PointFace
-      // on est donc oblige de creer un nouveau TopoDS_Vertex.
-      gp_Pnt theProjB=myDeltaVertexFace.Point(1);
-      BRepBuilderAPI_MakeVertex theVertexMaker(theProjB);
-      TopoDS_Vertex VertexBproj=theVertexMaker.Vertex();
-      // Creation du Plane contenant la relation.
-      GC_MakePlane MkPlane(A,B,theProjB);
-      Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-      
-      // Fermeture du contexte local.
-      TheAISContext()->CloseLocalContext(myCurrentIndex);
-      // Construction du texte.
-      TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) );
-      
-      // on construit l'AISLenghtDimension mais en utilisant le constructeur Vertex Vertex.
-      Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (VertexB,VertexBproj,theGeomPlane->Pln());
-      TheAISContext()->Display(myLenghtDim );
-      GetMapOfAIS().Bind (myLenghtDim ,argv[1]);
-      
+      gp_Pnt aProjB = aDeltaVertexFace.Point(1);
+      BRepBuilderAPI_MakeVertex aVertexMaker (aProjB);
+      TopoDS_Vertex aVertexBProj = aVertexMaker.Vertex();
+      gce_MakePln aMakePlane (A, B, aProjB);
+      gp_Pln aPlane= aMakePlane.Value();
+
+      TheAISContext()->CloseLocalContext(aCurrentIndex);
+
+      Handle(AIS_LengthDimension) aLenghtDim  =new AIS_LengthDimension (VertexB, aVertexBProj, aPlane);
+      TheAISContext()->Display (aLenghtDim);
+      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
     }
-    
-    // Si ShapeB est une Face
-    else {
-      
-      TopoDS_Face  FaceB=TopoDS::Face(ShapeB);
-      BRepExtrema_ExtFF myDeltaFaceFace  (FaceA ,FaceB );
-      // On verifie que les deux faces sont bien parelles.
-      if (!myDeltaFaceFace.IsParallel() ) {di<<"vdistdim error: the faces are not parallel. "<<"\n";return 1; }
-      
-      // On saisit la distance et on l'arrondit!
-      theDist=Round (sqrt (myDeltaFaceFace.SquareDistance(1))*10. )/10.;
-      // Fermeture du contexte local.
-      TheAISContext()->CloseLocalContext(myCurrentIndex);
-      // Construction du texte.
-      TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) );
-      
-      // on construit l'AISLenghtDimension.
-      Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (FaceA,FaceB);
-      TheAISContext()->Display(myLenghtDim );
-      GetMapOfAIS().Bind (myLenghtDim ,argv[1]);
-      
+    // the second shape is face.
+    else
+    {
+      TopoDS_Face FaceB = TopoDS::Face (aSecondShape);
+      BRepExtrema_ExtFF aDeltaFaceFace (FaceA, FaceB);
+
+      if (!aDeltaFaceFace.IsParallel())
+      {
+        di << argv[0] << " error: the faces are not parallel. "<<"\n";
+        return 1;
+      }
+
+      TheAISContext()->CloseLocalContext (aCurrentIndex);
+
+      Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (FaceA,FaceB);
+      TheAISContext()->Display (aLenghtDim);
+      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
     }
-    
   }
-  
-  
-  
+
   return 0;
-  
 }
 
 
@@ -1596,103 +1548,88 @@ static int VLenghtDimension(Draw_Interpretor& di, Standard_Integer argc, const c
 static int VRadiusDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
 {
   // Declarations
-  Standard_Integer myCurrentIndex;
-  Standard_Real theRadius;
-    
+  Standard_Integer aCurrentIndex;
+  Standard_Real aRadius;
+  TopoDS_Edge anEdge;
   // Verification
-  if (argc!=2) {di<<" vradiusdim error"<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
+  if (argc != 2)
+  {
+    di << argv[0] << " error: wrong number of parameters." << "\n";
+    return 1;
+  }
+
+  // Close all local contexts
   TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
+
+  // Open local context and get its index for recovery.
   TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections Edges et Faces.
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
-  di<<" Select an circled edge or face."<<"\n";
-  
-  // Boucle d'attente waitpick.
+  aCurrentIndex = TheAISContext()->IndexOfCurrentLocal();
+
+  // Current selection modes - faces and edges
+  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2));
+  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4));
+  di << " Select a circled edge or face." << "\n";
+
+  // Loop that will be handle picking.
   Standard_Integer argcc = 5;
   const char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
   const char **argvv = (const char **) buff;
-  while (ViewerMainLoop( argcc, argvv) ) { }
-  // fin de la boucle
-  
-  TopoDS_Shape ShapeA;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeA = TheAISContext()->SelectedShape();
+  while (ViewerMainLoop (argcc, argvv)) { }
+  // end of the loop
+
+  TopoDS_Shape aShape;
+
+  for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected() )
+  {
+    aShape = TheAISContext()->SelectedShape();
   }
-  
-  // Shape A est un edge.
-  if (ShapeA.ShapeType()==TopAbs_EDGE  ) {
-    
-    TopoDS_Edge  EdgeA=TopoDS::Edge(ShapeA);
-    // Recuperation du rayon
-    BRepAdaptor_Curve theCurve(TopoDS::Edge(ShapeA));
-    if (theCurve.GetType()!=GeomAbs_Circle ) {di<<"vradiusdim error: the edge is not a circular one."<<"\n";return 1;}
-    else {
-      gp_Circ theGpCircle=theCurve.Circle();
-      theRadius=theGpCircle.Radius();
-      // On arrondit le rayon
-      theRadius=Round (theRadius*10. )/10.;
-    }
-    
-    // Construction du texte.
-    TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("r=")+TCollection_ExtendedString(theRadius  ) );
-    
-    // Fermeture du contexte.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    
-    // Construction de L'AIS_RadiusDimension.
-    Handle (AIS_RadiusDimension) myRadDim= new AIS_RadiusDimension(ShapeA);
-    GetMapOfAIS().Bind (myRadDim,argv[1]);
-    TheAISContext()->Display(myRadDim );
-    
-    
+
+  if (aShape.IsNull())
+  {
+    di << argv[0] << ": no shape is selected." << "\n";
+    return 1;
   }
-  
-  // Shape A est une face
-  else if (ShapeA.ShapeType()==TopAbs_FACE ) {
-    
-    // on recupere un edge de la face.
-    TopoDS_Face  FaceA=TopoDS::Face(ShapeA);
-    // on explore.
-    TopExp_Explorer FaceExp(FaceA,TopAbs_EDGE);
-    TopoDS_Edge EdgeFromA=TopoDS::Edge(FaceExp.Current() );
-    
-    // Recuperation du rayon
-    BRepAdaptor_Curve theCurve(EdgeFromA );
-    if (theCurve.GetType()!=GeomAbs_Circle ) {di<<"vradiusdim error: the face is not a circular one."<<"\n";return 1;}
-    else {
-      gp_Circ theGpCircle=theCurve.Circle();
-      theRadius=theGpCircle.Radius();
-      // On arrondit le rayon
-      theRadius=Round (theRadius*10. )/10.;
-    }
-    
-    // Construction du texte.
-    TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("r=")+TCollection_ExtendedString(theRadius  ) );
-    
-    // Fermeture du contexte.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    
-    // Construction de L'AIS_RadiusDimension.
-    Handle (AIS_RadiusDimension) myRadDim= new AIS_RadiusDimension(ShapeA);
-    GetMapOfAIS().Bind (myRadDim,argv[1]);
-    TheAISContext()->Display(myRadDim );
-    
-    
+
+  if (aShape.ShapeType() != TopAbs_EDGE && aShape.ShapeType() != TopAbs_FACE)
+  {
+    di << argv[0] << " error: the selection of a face or an edge was expected." << "\n";
+    return 1;
   }
-  
-  else {
-    di<<" vradiusdim error: the selection of a face or an edge was expected."<<"\n";return 1;
+
+  if (aShape.ShapeType() == TopAbs_EDGE)
+  {
+    anEdge = TopoDS::Edge (aShape);
   }
-  
+  else // Face
+  {
+    // Recover an edge of the face.
+    TopoDS_Face aFace = TopoDS::Face (aShape);
+
+    TopExp_Explorer aFaceExp (aFace,TopAbs_EDGE);
+    anEdge = TopoDS::Edge (aFaceExp.Current());
+  }
+
+  // Compute the radius
+  BRepAdaptor_Curve aCurve (anEdge);
+  if (aCurve.GetType() != GeomAbs_Circle)
+  {
+    di << argv[0] << " error: the edge is not a circular one." << "\n";
+    return 1;
+  }
+  else
+  {
+    gp_Circ aCircle = aCurve.Circle();
+    aRadius = aCircle.Radius();
+    aRadius = Round (aRadius * 10.0) / 10.0;
+  }
+  // Close the context
+  TheAISContext()->CloseLocalContext (aCurrentIndex);
+
+  // Construct radius dimension
+  Handle (AIS_RadiusDimension) aRadDim= new AIS_RadiusDimension (aShape);
+  VDisplayAISObject (argv[1], aRadDim);
+
   return 0;
-  
 }
 
 
@@ -2398,94 +2335,346 @@ static int VSymmetricBuilder(Draw_Interpretor& di, Standard_Integer argc, const
   return 0;
   
 }
+
 //=======================================================================
-//function : VMoveDim
-//purpose  : 
+//function : VDimParam
+//purpose  : Moves dimension or relation text label to defined or picked
+//           position and updates the object.
 //=======================================================================
-static int VMoveDim(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
+static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec) 
 {
-  if(argc>2) return 1;
-  
-  const Handle(V3d_View) aview = ViewerTest::CurrentView();
-  Handle(AIS_InteractiveObject) pickedobj;
-  if(argc==1){
-    pickedobj = TheAISContext()->FirstCurrentObject();
-    if(pickedobj.IsNull() || pickedobj->Type()!=AIS_KOI_Relation)
-      pickedobj = ViewerTest::PickObject(AIS_KOI_Relation);
-  }
-  else{
-    // reperage dans le viewer...
-    if(!strcasecmp(argv[1],".")){
-      pickedobj = ViewerTest::PickObject(AIS_KOI_Relation);
-      
+  if (theArgNum < 3)
+  {
+    theDi << theArgVec[0] << " error: the wrong number of input parameters.\n";
+    return 1;
+  }
+
+  // Get dimension name
+  TCollection_AsciiString aName (theArgVec[1]);
+  if (!GetMapOfAIS().IsBound2 (aName))
+  {
+    theDi << theArgVec[0] << "error: no object with this name.\n";
+    return 1;
+  }
+
+  Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2 (aName));
+  if (anObject->Type() != AIS_KOI_Dimension)
+  {
+    theDi << theArgVec[0] << "error: no dimension with this name.\n";
+    return 1;
+  }
+  Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast (anObject);
+  Handle(Prs3d_DimensionAspect) anAspect = aDim->DimensionAspect();
+
+  // Parse parameters
+  gp_Pln aWorkingPlane;
+  Standard_Real aCustomFlyout = 0.0;
+
+  for (Standard_Integer anIt = 2; anIt < theArgNum; ++anIt)
+  {
+    TCollection_AsciiString anArgString = theArgVec[anIt];
+    TCollection_AsciiString aParamName;
+    TCollection_AsciiString aParamValue;
+    if (ViewerTest::SplitParameter (anArgString, aParamName, aParamValue))
+    {
+      aParamName.LowerCase();
+      aParamValue.LowerCase();
+
+      if (aParamName == "text")
+      {
+        anAspect->MakeText3d (aParamValue == "3d");
+      }
+      else if (aParamName == "name")
+      {
+        if (aParamValue.IsEmpty())
+        {
+          std::cerr << theArgVec[0] << ": no name for dimension.\n";
+          return 1;
+        }
+
+        aName = aParamValue;
+      }
+      else if (aParamName == "plane")
+      {
+        if (aParamValue == "xoy")
+        {
+          aWorkingPlane = gp_Pln (gp_Ax3 (gp::XOY()));
+        }
+        else if (aParamValue == "zox")
+        {
+          aWorkingPlane = gp_Pln (gp_Ax3 (gp::ZOX()));
+        }
+        else if (aParamValue == "yoz")
+        {
+          aWorkingPlane = gp_Pln (gp_Ax3 (gp::YOZ()));
+        }
+        else
+        {
+          std::cerr << theArgVec[0] << ": wrong plane.\n";
+          return 1;
+        }
+      }
+      else if (aParamName == "label")
+      {
+        NCollection_List<TCollection_AsciiString> aListOfLabelVals;
+        while (aParamValue.Length() > 0)
+        {
+          TCollection_AsciiString aValue = aParamValue;
+
+          Standard_Integer aSeparatorPos = aParamValue.Search (",");
+          if (aSeparatorPos >= 0)
+          {
+            aValue.Trunc (aSeparatorPos - 1);
+            aParamValue.Remove (aSeparatorPos, 1);
+          }
+
+          aListOfLabelVals.Append (aValue);
+
+          aParamValue.Remove (1, aValue.Length());
+        }
+
+        NCollection_List<TCollection_AsciiString>::Iterator aLabelValueIt (aListOfLabelVals);
+        for ( ; aLabelValueIt.More(); aLabelValueIt.Next())
+        {
+          aParamValue = aLabelValueIt.Value();
+
+          if (aParamValue == "left")
+          {
+            anAspect->SetTextHorizontalPosition (Prs3d_DTHP_Left);
+          }
+          else if (aParamValue == "right")
+          {
+            anAspect->SetTextHorizontalPosition (Prs3d_DTHP_Right);
+          }
+          else if (aParamValue == "hcenter")
+          {
+            anAspect->SetTextHorizontalPosition (Prs3d_DTHP_Center);
+          }
+          else if (aParamValue == "hfit")
+          {
+            anAspect->SetTextHorizontalPosition (Prs3d_DTHP_Fit);
+          }
+          else if (aParamValue == "above")
+          {
+            anAspect->SetTextVerticalPosition (Prs3d_DTVP_Above);
+          }
+          else if (aParamValue == "below")
+          {
+            anAspect->SetTextVerticalPosition (Prs3d_DTVP_Below);
+          }
+          else if (aParamValue == "vcenter")
+          {
+            anAspect->SetTextVerticalPosition (Prs3d_DTVP_Center);
+          }
+          else
+          {
+            std::cerr << theArgVec[0] << ": invalid label position: \"" << aParamValue << "\".\n";
+            return 1;
+          }
+        }
+      }
+      else if (aParamName == "flyout")
+      {
+        if (!aParamValue.IsRealValue())
+        {
+          std::cerr << theArgVec[0] << ": numeric value expected for flyout.\n";
+          return 1;
+        }
+
+        aCustomFlyout = aParamValue.RealValue();
+        aDim->SetFlyout (aCustomFlyout);
+      }
+      else if (aParamName == "arrows")
+      {
+        if (aParamValue == "external")
+        {
+          anAspect->SetArrowOrientation (Prs3d_DAO_External);
+        }
+        else if (aParamValue == "internal")
+        {
+          anAspect->SetArrowOrientation (Prs3d_DAO_Internal);
+        }
+        else if (aParamValue == "fit")
+        {
+          anAspect->SetArrowOrientation (Prs3d_DAO_Fit);
+        }
+      }
+      else
+      {
+        std::cerr << theArgVec[0] << ": unknow parameter: \"" << aParamName << "\".\n";
+        return 1;
+      }
     }
-    else if(GetMapOfAIS().IsBound2(argv[1]))
-      pickedobj = Handle(AIS_InteractiveObject)::DownCast
-        (GetMapOfAIS().Find2(argv[1]));
   }
-  
-  if(pickedobj.IsNull()){
-    di<<"Bad Type Object"<<"\n";
-    return 1 ;}
-  
-  if(pickedobj->Type() != AIS_KOI_Relation)
+
+  // Redisplay a dimension after parameter changing.
+  ViewerTest::GetAISContext()->Redisplay (aDim);
+  return 0;
+}
+
+//=======================================================================
+//function : VMoveDim
+//purpose  : Moves dimension or relation text label to defined or picked
+//           position and updates the object.
+//draw args: vmovedim [name] [x y z]
+//=======================================================================
+static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec) 
+{
+  if (theArgNum > 5)
+  {
+    theDi << theArgVec[0] << " error: the wrong number of parameters.\n";
     return 1;
-  Standard_Integer argccc = 5;
-  
-  const char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-  const char **argvvv = (const char **) bufff;
+  }
+
+  // Parameters parsing
+  Standard_Boolean isNameSet = (theArgNum ==2 || theArgNum == 5);
+  Standard_Boolean isPointSet = (theArgNum == 4 || theArgNum == 5);
+
+  Handle(AIS_InteractiveObject) aPickedObj;
+  gp_Pnt aPoint (gp::Origin());
+  Standard_Integer aCurrentIndex = 0;
+  Standard_Integer aMaxPickNum = 5;
+
+  // Find object
+  if (isNameSet)
+  {
+     TCollection_AsciiString aName (theArgVec[1]);
+     if (!GetMapOfAIS().IsBound2 (aName))
+     {
+       theDi << theArgVec[0] << " error: no object with this name.\n";
+       return 1;
+     }
+
+     aPickedObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
+     
+     if (aPickedObj.IsNull())
+     {
+       theDi << theArgVec[0] << " error: the object with this name is not valid.\n";
+       return 1;
+     }
+
+     if (aPickedObj->Type() != AIS_KOI_Dimension && aPickedObj->Type() != AIS_KOI_Relation)
+     {
+       theDi << theArgVec[0] << " error: no dimension or relation with this name.\n";
+       return 1;
+     }
+  }
+  else // Pick dimension or relation
+  {
+    // Close all local contexts
+    TheAISContext()->CloseAllContexts();
+
+    // Open local context and get its index for recovery.
+    TheAISContext()->OpenLocalContext();
+    aCurrentIndex = TheAISContext()->IndexOfCurrentLocal();
 
-  Handle(AIS_Relation) R = *((Handle(AIS_Relation)*)&pickedobj);
-  Handle(Geom_Plane) ThePl;
-//  Standard_Real x,y,z,xv,yv,zv;
-  Standard_Real x,y,xv,yv,zv;
-  static Standard_Real last_xv(0),last_yv(0),last_zv(0);
-  Standard_Integer xpix,ypix;
-//  Standard_Boolean SameAsLast(Standard_False);
-  Select3D_Projector prj(aview);
-  
-  
-  while (ViewerMainLoop( argccc, argvvv) ) {
-    //....... la ligne de tir
-    ViewerTest::GetMousePosition(xpix,ypix);
-    aview->Convert(xpix,ypix,x,y); // espace reel 2D de la vue...
-    gp_Lin L = prj.Shoot(x,y);
-
-    
-    
-    // ....... le plan de la vue...
-    aview->Proj(xv,yv,zv);
-    static Standard_Boolean haschanged(Standard_False);
-    if(Abs(last_xv-xv)>Precision::Confusion() ||
-       Abs(last_yv-yv)>Precision::Confusion() ||
-       Abs(last_zv-zv)>Precision::Confusion() ){
-      last_xv = xv;
-      last_yv = yv;
-      last_zv = zv;
-      Standard_Real xat,yat,zat;
-      aview->At(xat,yat,zat);
-      ThePl = new Geom_Plane(gp_Pnt(xat,yat,zat),gp_Dir(xv,yv,zv));
-      haschanged = Standard_True;
-      di <<"changement de plan"<<"\n";
+    // Loop that will be handle picking.
+    Standard_Integer anArgNum = 5;
+    const char *aBuffer[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
+    const char **anArgVec = (const char **) aBuffer;
+
+    Standard_Boolean isPicked = Standard_False;
+    Standard_Integer aPickNum = 0;
+    while (!isPicked && aPickNum < aMaxPickNum)
+    {
+      while (ViewerMainLoop (anArgNum, anArgVec)) { }
+
+      for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
+      {
+        aPickedObj = TheAISContext()->SelectedInteractive();
+      }
+
+      isPicked = (!aPickedObj.IsNull() && (aPickedObj->Type() == AIS_KOI_Dimension || aPickedObj->Type() == AIS_KOI_Relation));
+
+      if (isPicked)
+      {
+        break;
+      }
+      aPickNum++;
     }
-    
-    //  
-//    Standard_Integer xpix,ypix;
-//    Standard_Real x,y;
-    gp_Pnt GoodPoint;
-    if(haschanged){
-      gp_Pln NewPlane;;
-      ComputeNewPlaneForDim(R,NewPlane,GoodPoint);
-      haschanged = Standard_False;
+    if (!isPicked)
+    {
+      theDi << theArgVec[0] << ": no dimension or relation is selected." << "\n";
+      return 1;
     }
-    else{
-      if(ComputeIntersection(L,ThePl->Pln(),GoodPoint)){
-       R->SetPosition(GoodPoint);
+  }
+
+  // Find point
+  if (isPointSet)
+  {
+    aPoint = theArgNum == 4 ? gp_Pnt (atoi (theArgVec[1]), atoi (theArgVec[2]), atoi (theArgVec[3]))
+                            : gp_Pnt (atoi (theArgVec[2]), atoi (theArgVec[3]), atoi (theArgVec[4]));
+  }
+  else // Pick the point
+  {
+    Standard_Integer aPickArgNum = 5;
+    const char *aPickBuff[] = {"VPick", "X", "VPickY", "VPickZ", "VPickShape"};
+    const char **aPickArgVec = (const char **) aPickBuff;
+
+    while (ViewerMainLoop (aPickArgNum, aPickArgVec)) { }
+
+    // Set text position, update relation or dimension.
+    if (aPickedObj->Type() == AIS_KOI_Relation)
+    {
+      Handle(AIS_Relation) aRelation = Handle(AIS_Relation)::DownCast (aPickedObj);
+      aPoint = Get3DPointAtMousePosition();
+      aRelation->SetPosition (aPoint);
+      TheAISContext()->Redisplay (aRelation);
+    }
+    else
+    {
+      Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast (aPickedObj);
+      gp_Pnt aFirstPoint, aSecondPoint;
+      if (aDim->KindOfDimension() == AIS_KOD_PLANEANGLE)
+      {
+        Handle(AIS_AngleDimension) anAngleDim = Handle(AIS_AngleDimension)::DownCast (aDim);
+        aFirstPoint = anAngleDim->FirstPoint();
+        aSecondPoint = anAngleDim->SecondPoint();
+      }
+      else if (aDim->KindOfDimension() == AIS_KOD_LENGTH)
+      {
+        Handle(AIS_LengthDimension) aLengthDim = Handle(AIS_LengthDimension)::DownCast (aDim);
+        aFirstPoint = aLengthDim->FirstPoint();
+        aSecondPoint = aLengthDim->SecondPoint();
+      }
+      else if (aDim->KindOfDimension() == AIS_KOD_RADIUS)
+      {
+        Handle(AIS_RadiusDimension) aRadiusDim = Handle(AIS_RadiusDimension)::DownCast (aDim);
+        aFirstPoint = aRadiusDim->AnchorPoint();
+        aSecondPoint = aRadiusDim->Circle().Location();
+      }
+      else if (aDim->KindOfDimension() == AIS_KOD_DIAMETER)
+      {
+        Handle(AIS_DiameterDimension) aDiameterDim = Handle(AIS_DiameterDimension)::DownCast (aDim);
+        aFirstPoint = aDiameterDim->AnchorPoint();
+        aSecondPoint = aDiameterDim->Circle().Location();
+      }
+
+      if (!Get3DPointAtMousePosition (aFirstPoint, aSecondPoint, aPoint))
+      {
+        return 1;
       }
-      TheAISContext()->Redisplay(R);
+
+      aDim->SetTextPosition (aPoint);
+      TheAISContext()->Redisplay (aDim);
     }
+
   }
-  
+
+  // Set text position, update relation or dimension.
+  if (aPickedObj->Type() == AIS_KOI_Relation)
+  {
+    Handle(AIS_Relation) aRelation = Handle(AIS_Relation)::DownCast (aPickedObj);
+    aRelation->SetPosition (aPoint);
+    TheAISContext()->Redisplay (aRelation);
+  }
+  else
+  {
+    Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast (aPickedObj);
+    aDim->SetTextPosition (aPoint);
+    TheAISContext()->Redisplay (aDim);
+  }
+
   return 0;
 }
 
@@ -2504,9 +2693,17 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands)
       " [text={2d|3d}] [plane={xoy|yoz|zox}]\n"
       " [label={left|right|hcenter|hfit},{above|below|vcenter}]\n"
       " [flyout=value] [arrows={external|internal|fit}]\n"
-      " -Builds angle, length, radius and diameter dimensions.\n"
+      " -Builds angle, length, radius and diameter dimensions.\n",
       __FILE__,VDimBuilder,group);
 
+  theCommands.Add("vdimparam",
+    "vdimparam Dim_Name"
+    " [text={2d|3d}] [plane={xoy|yoz|zox}]\n"
+    " [label={left|right|hcenter|hfit},{above|below|vcenter}]\n"
+    " [flyout=value] [arrows={external|internal|fit}]\n"
+    " -Sets parameters for angle, length, radius and diameter dimensions.\n",
+    __FILE__,VDimParam,group);
+
   theCommands.Add("vangledim",
                  "vangledim Name:Selection in the viewer only ",
                  __FILE__,VAngleDimBuilder,group);
diff --git a/tests/bugs/vis/bug24412_1 b/tests/bugs/vis/bug24412_1
new file mode 100644 (file)
index 0000000..d26de81
--- /dev/null
@@ -0,0 +1,48 @@
+puts "============"
+puts "CR24412"
+puts "============"
+puts ""
+#######################################################################
+#  TKV3d, Dimensions - Possibility to customize text position was lost
+#  Test position setting for linear dimension
+#######################################################################
+pload ALL
+
+set anImage1 $imagedir/${casename}_1.png
+set anImage2 $imagedir/${casename}_2.png
+
+vinit Viewer1/View1
+vpoint  circ_p1 0  10 30
+vpoint  circ_p2 30 10  0
+vpoint  circ_p3 60 10 30
+vcircle circ circ_p1 circ_p2 circ_p3 0
+vdisplay circ
+vdimension diameter name=diam circ
+vdisplay diam
+# Change text position
+vmovedim diam 15 15 15
+vfit
+
+# Check that text position was changed and the text is not aligned
+set x_coord 166
+set y_coord 226
+checkcolor $x_coord $y_coord 0.46 0.9 0
+if { $stat != 1 } {
+  puts "Error : Text position of dimension is incorrect."
+}
+
+vdump $anImage1
+
+# Update dimension parameters and set automatic text positioning
+vdimparam diam flyout=-5
+vfit
+
+# Check that text position was changed according to flyout
+set x_coord 213
+set y_coord 179
+checkcolor $x_coord $y_coord 0.46 0.9 0
+if { $stat != 1 } {
+  puts "Error : Text position of dimension after layout changing is incorrect."
+}
+
+vdump $anImage2
diff --git a/tests/bugs/vis/bug24412_2 b/tests/bugs/vis/bug24412_2
new file mode 100644 (file)
index 0000000..a51f3e2
--- /dev/null
@@ -0,0 +1,46 @@
+puts "============"
+puts "CR24412"
+puts "============"
+puts ""
+#######################################################################
+#  TKV3d, Dimensions - Possibility to customize text position was lost
+#  Test position setting for angular dimension
+#######################################################################
+pload ALL
+
+set anImage1 $imagedir/${casename}_1.png
+set anImage2 $imagedir/${casename}_2.png
+
+vinit Viewer1/View1
+vpoint  ang_p1 0  0 30
+vpoint  ang_p2 30 0  0
+vpoint  ang_p3 60 0 30
+vdimension angle name=ang ang_p1 ang_p2 ang_p3
+vdisplay ang
+vmovedim ang 5 0 5
+vfit
+
+# Check that text position was changed and the text is not aligned
+set x_coord 60
+set y_coord 189
+checkcolor $x_coord $y_coord 0.46 0.9 0
+if { $stat != 1 } {
+  puts "Error : Text position of dimension is incorrect."
+}
+
+vdump $anImage1
+
+
+# Update dimension parameters and set automatic text positioning
+vdimparam ang flyout=-5
+vfit
+
+# Check that text position was changed according to flyout
+set x_coord 206
+set y_coord 312
+checkcolor $x_coord $y_coord 0.46 0.9 0
+if { $stat != 1 } {
+  puts "Error : Text position of dimension after layout changing is incorrect."
+}
+
+vdump $anImage2