0031189: Draw Harness, ViewerTest - send messages to Message::DefaultMessenger()
[occt.git] / src / ViewerTest / ViewerTest_RelationCommands.cxx
index befd5d8..44b8c8c 100644 (file)
 
 #include <ViewerTest.hxx>
 
-#include <AIS_AngleDimension.hxx>
 #include <AIS_Circle.hxx>
-#include <AIS_DiameterDimension.hxx>
 #include <AIS_DisplayMode.hxx>
 #include <AIS_InteractiveContext.hxx>
-#include <AIS_LengthDimension.hxx>
 #include <AIS_ListIteratorOfListOfInteractive.hxx>
 #include <AIS_ListOfInteractive.hxx>
 #include <AIS_MapOfInteractive.hxx>
 #include <AIS_Point.hxx>
-#include <AIS_RadiusDimension.hxx>
-#include <AIS_Relation.hxx>
 #include <AIS_Shape.hxx>
-#include <BRepAdaptor_Curve.hxx>
+#include <PrsDim_AngleDimension.hxx>
+#include <PrsDim_ConcentricRelation.hxx>
+#include <PrsDim_DiameterDimension.hxx>
+#include <PrsDim_EqualDistanceRelation.hxx>
+#include <PrsDim_EqualRadiusRelation.hxx>
+#include <PrsDim_FixRelation.hxx>
+#include <PrsDim_IdenticRelation.hxx>
+#include <PrsDim_KindOfRelation.hxx>
+#include <PrsDim_LengthDimension.hxx>
+#include <PrsDim_OffsetDimension.hxx>
+#include <PrsDim_ParallelRelation.hxx>
+#include <PrsDim_PerpendicularRelation.hxx>
+#include <PrsDim_RadiusDimension.hxx>
+#include <PrsDim_Relation.hxx>
+#include <PrsDim_SymmetricRelation.hxx>
+#include <PrsDim_TangentRelation.hxx>
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <BRepExtrema_ExtCC.hxx>
+#include <BRepExtrema_ExtPC.hxx>
+#include <BRepExtrema_ExtCF.hxx>
+#include <BRepExtrema_ExtPF.hxx>
+#include <BRepExtrema_ExtFF.hxx>
 #include <BRepTools.hxx>
 #include <Draw_Interpretor.hxx>
 #include <Draw.hxx>
@@ -39,6 +56,7 @@
 #include <Draw_Window.hxx>
 #include <DBRep.hxx>
 #include <ElSLib.hxx>
+#include <Font_FontMgr.hxx>
 #include <GC_MakePlane.hxx>
 #include <Geom_CartesianPoint.hxx>
 #include <Geom_Circle.hxx>
 #include <gp_Pln.hxx>
 #include <IntAna_IntConicQuad.hxx>
 #include <IntAna_Quadric.hxx>
+#include <Message.hxx>
 #include <Precision.hxx>
 #include <StdSelect.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <TCollection_ExtendedString.hxx>
 #include <TColStd_MapOfInteger.hxx>
+#include <TColStd_SequenceOfReal.hxx>
 #include <TopAbs.hxx>
 #include <TopAbs_ShapeEnum.hxx>
 #include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Solid.hxx>
@@ -173,7 +194,9 @@ static Standard_Boolean Get3DPointAtMousePosition (const gp_Pnt& theFirstPoint,
 //           -arrowangle ArrowAngle(degrees)
 //           -plane xoy|yoz|zox
 //           -flyout FloatValue -extension FloatValue
-//           -value CustomNumberValue
+//           -autovalue
+//           -value CustomRealValue
+//           -textvalue CustomTextValue
 //           -dispunits DisplayUnitsString
 //           -modelunits ModelUnitsString
 //           -showunits
@@ -209,6 +232,12 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
     }
 
     // Boolean flags
+    if (aParam.IsEqual ("-autovalue"))
+    {
+      theRealParams.Bind ("autovalue", 1);
+      continue;
+    }
+
     if (aParam.IsEqual ("-showunits"))
     {
       theAspect->MakeUnitsDisplayed (Standard_True);
@@ -219,11 +248,29 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
       theAspect->MakeUnitsDisplayed (Standard_False);
       continue;
     }
+    else if (aParam.IsEqual ("-selected"))
+    {
+      if (!theShapeList)
+      {
+        Message::SendFail() << "Error: unknown parameter '" << aParam << "'";
+        return 1;
+      }
+
+      for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
+      {
+        TopoDS_Shape aShape = TheAISContext()->SelectedShape();
+        if (!aShape.IsNull())
+        {
+          theShapeList->Append (new AIS_Shape (aShape));
+        }
+      }
+      continue;
+    }
 
     // Before all non-boolean flags parsing check if a flag have at least one value.
     if (anIt + 1 >= theArgNum)
     {
-      std::cerr << "Error: "<< aParam <<" flag should have value.\n";
+      Message::SendFail() << "Error: "<< aParam <<" flag should have value.";
       return 1;
     }
 
@@ -233,7 +280,7 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
     {
       if (!theShapeList)
       {
-        std::cerr << "Error: unknown parameter '" << aParam << "'\n";
+        Message::SendFail() << "Error: unknown parameter '" << aParam << "'";
         return 1;
       }
 
@@ -248,20 +295,11 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
         {
           anAISObject = new AIS_Shape (aShape);
         }
-        else
+        else if (!GetMapOfAIS().Find2 (anArgString, anAISObject)
+               || anAISObject.IsNull())
         {
-          if (!GetMapOfAIS().IsBound2 (anArgString))
-          {
-            std::cerr << "Error: shape with name '" << aStr << "' is not found.\n";
-            return 1;
-          }
-
-          anAISObject = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anArgString));
-          if (anAISObject.IsNull())
-          {
-            std::cerr << "Error: " << aStr <<" is not a shape.\n";
-            return 1;
-          }
+          Message::SendFail() << "Error: shape with name '" << aStr << "' is not found.";
+          return 1;
         }
         theShapeList->Append (anAISObject);
       }
@@ -297,6 +335,16 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
       }
       while (anIt + 1 < theArgNum && theArgVec[anIt + 1][0] != '-');
     }
+    else if (aParam.IsEqual ("-font"))
+    {
+      if (anIt + 1 >= theArgNum)
+      {
+        Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
+        return 1;
+      }
+
+      theAspect->TextAspect()->SetFont (theArgVec[++anIt]);
+    }
     else if (aParam.IsEqual ("-label"))
     {
       do
@@ -314,7 +362,7 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
         else if (aParamValue == "vcenter") { theAspect->SetTextVerticalPosition   (Prs3d_DTVP_Center);}
         else
         {
-          std::cerr << "Error: invalid label position: '" << aParamValue << "'.\n";
+          Message::SendFail() << "Error: invalid label position: '" << aParamValue << "'.";
           return 1;
         }
       }
@@ -322,19 +370,19 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
     }
     else if (aParam.IsEqual ("-arrow"))
     {
-      TCollection_AsciiString aParam (theArgVec[++anIt]);
-      aParam.LowerCase();
+      TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
+      aLocalParam.LowerCase();
 
-      if (aParam == "external") { theAspect->SetArrowOrientation (Prs3d_DAO_External); }
-      if (aParam == "internal") { theAspect->SetArrowOrientation (Prs3d_DAO_Internal); }
-      if (aParam == "fit")      { theAspect->SetArrowOrientation (Prs3d_DAO_Fit); }
+      if (aLocalParam == "external") { theAspect->SetArrowOrientation (Prs3d_DAO_External); }
+      if (aLocalParam == "internal") { theAspect->SetArrowOrientation (Prs3d_DAO_Internal); }
+      if (aLocalParam == "fit")      { theAspect->SetArrowOrientation (Prs3d_DAO_Fit); }
     }
     else if (aParam.IsEqual ("-arrowlength") || aParam.IsEqual ("-arlen"))
     {
       TCollection_AsciiString aValue (theArgVec[++anIt]);
       if (!aValue.IsRealValue())
       {
-        std::cerr << "Error: arrow lenght should be float degree value.\n";
+        Message::SendFail() << "Error: arrow lenght should be float degree value.";
         return 1;
       }
       theAspect->ArrowAspect()->SetLength (Draw::Atof (aValue.ToCString()));
@@ -344,7 +392,7 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
       TCollection_AsciiString aValue (theArgVec[++anIt]);
       if (!aValue.IsRealValue())
       {
-        std::cerr << "Error: arrow angle should be float degree value.\n";
+        Message::SendFail ("Error: arrow angle should be float degree value.");
         return 1;
       }
       theAspect->ArrowAspect()->SetAngle (Draw::Atof (aValue.ToCString()));
@@ -355,13 +403,13 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
     }
     else if (aParam.IsEqual ("-extension"))
     {
-      TCollection_AsciiString aParam (theArgVec[++anIt]);
-      if (!aParam.IsRealValue())
+      TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
+      if (!aLocalParam.IsRealValue())
       {
-        std::cerr << "Error: extension size for dimension should be real value.\n";
+        Message::SendFail ("Error: extension size for dimension should be real value.");
         return 1;
       }
-      theAspect->SetExtensionSize (Draw::Atof (aParam.ToCString()));
+      theAspect->SetExtensionSize (Draw::Atof (aLocalParam.ToCString()));
     }
     else if (aParam.IsEqual ("-plane"))
     {
@@ -384,47 +432,53 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
       }
       else
       {
-        std::cerr << "Error: wrong plane '" << aValue << "'.\n";
+        Message::SendFail() << "Error: wrong plane '" << aValue << "'";
         return 1;
       }
     }
     else if (aParam.IsEqual ("-flyout"))
     {
-      TCollection_AsciiString aParam (theArgVec[++anIt]);
-      if (!aParam.IsRealValue())
+      TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
+      if (!aLocalParam.IsRealValue())
       {
-        std::cerr << "Error: flyout for dimension should be real value.\n";
+        Message::SendFail ("Error: flyout for dimension should be real value.");
         return 1;
       }
 
-      theRealParams.Bind ("flyout", Draw::Atof (aParam.ToCString()));
+      theRealParams.Bind ("flyout", Draw::Atof (aLocalParam.ToCString()));
     }
     else if (aParam.IsEqual ("-value"))
     {
-      TCollection_AsciiString aParam (theArgVec[++anIt]);
-      if (!aParam.IsRealValue())
+      TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
+      if (!aLocalParam.IsRealValue())
       {
-        std::cerr << "Error: dimension value for dimension should be real value.\n";
+        Message::SendFail ("Error: dimension value for dimension should be real value");
         return 1;
       }
 
-      theRealParams.Bind ("value", Draw::Atof (aParam.ToCString()));
+      theRealParams.Bind ("value", Draw::Atof (aLocalParam.ToCString()));
+    }
+    else if (aParam.IsEqual ("-textvalue"))
+    {
+      TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
+
+      theStringParams.Bind ("textvalue", aLocalParam);
     }
     else if (aParam.IsEqual ("-modelunits"))
     {
-      TCollection_AsciiString aParam (theArgVec[++anIt]);
+      TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
 
-      theStringParams.Bind ("modelunits", aParam);
+      theStringParams.Bind ("modelunits", aLocalParam);
     }
     else if (aParam.IsEqual ("-dispunits"))
     {
-      TCollection_AsciiString aParam (theArgVec[++anIt]);
+      TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
 
-      theStringParams.Bind ("dispunits", aParam);
+      theStringParams.Bind ("dispunits", aLocalParam);
     }
     else
     {
-      std::cerr << "Error: unknown parameter '" << aParam << "'.\n";
+      Message::SendFail() << "Error: unknown parameter '" << aParam << "'";
       return 1;
     }
   }
@@ -436,7 +490,7 @@ static int ParseDimensionParams (Standard_Integer  theArgNum,
 //function : SetDimensionParams
 //purpose  : Sets parameters for dimension
 //=======================================================================
-static void SetDimensionParams (const Handle(AIS_Dimension)& theDim,
+static void SetDimensionParams (const Handle(PrsDim_Dimension)& theDim,
                                 const NCollection_DataMap<TCollection_AsciiString, Standard_Real>& theRealParams,
                                 const NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams)
 {
@@ -445,11 +499,21 @@ static void SetDimensionParams (const Handle(AIS_Dimension)& theDim,
     theDim->SetFlyout (theRealParams.Find ("flyout"));
   }
 
+  if (theRealParams.IsBound ("autovalue"))
+  {
+    theDim->SetComputedValue();
+  }
+
   if (theRealParams.IsBound ("value"))
   {
     theDim->SetCustomValue (theRealParams.Find ("value"));
   }
 
+  if (theStringParams.IsBound ("textvalue"))
+  {
+    theDim->SetCustomValue (theStringParams.Find ("textvalue"));
+  }
+
   if (theStringParams.IsBound ("modelunits"))
   {
     theDim->SetModelUnits (theStringParams.Find ("modelunits"));
@@ -461,6 +525,122 @@ static void SetDimensionParams (const Handle(AIS_Dimension)& theDim,
   }
 }
 
+//=======================================================================
+//function : ParseAngleDimensionParams
+//purpose  : Auxilliary function: sets custom parameters for angle dimension.
+//
+//draw args: -type [interior|exterior]
+//           -showarrow [first|second|both|none]
+//=======================================================================
+static int ParseAngleDimensionParams (Standard_Integer  theArgNum,
+                               const char**      theArgVec,
+                               Standard_Integer  theStartIndex,
+                               NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams)
+{
+  theStringParams.Clear();
+
+  // Begin from the second parameter: the first one is dimension name
+  for (Standard_Integer anIt = theStartIndex; anIt < theArgNum; ++anIt)
+  {
+    TCollection_AsciiString aParam (theArgVec[anIt]);
+    aParam.LowerCase();
+
+    if (aParam.Search ("-") == -1)
+    {
+      Message::SendFail() << "Error: wrong parameter '" << aParam << "'.";
+      return 1;
+    }
+
+    // Before all non-boolean flags parsing check if a flag have at least one value.
+    if (anIt + 1 >= theArgNum)
+    {
+      Message::SendFail() << "Error: "<< aParam <<" flag should have value.";
+      return 1;
+    }
+
+    if (aParam.IsEqual ("-type"))
+    {
+      TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
+
+      theStringParams.Bind ("type", aLocalParam);
+    }
+    else if (aParam.IsEqual ("-showarrow"))
+    {
+      TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
+
+      theStringParams.Bind ("showarrow", aLocalParam);
+    }
+    else
+    {
+      Message::SendFail() << "Error: unknown parameter '" << aParam << "'.";
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+//=======================================================================
+//function : SetAngleDimensionParams
+//purpose  : Sets parameters for angle dimension
+//=======================================================================
+static void SetAngleDimensionParams (const Handle(PrsDim_Dimension)& theDim,
+                                     const NCollection_DataMap<TCollection_AsciiString,
+                                     TCollection_AsciiString>& theStringParams)
+{
+  Handle(PrsDim_AngleDimension) anAngleDim = Handle(PrsDim_AngleDimension)::DownCast (theDim);
+  if (anAngleDim.IsNull())
+  {
+    return;
+  }
+
+  if (theStringParams.IsBound ("type"))
+  {
+    PrsDim_TypeOfAngle anAngleType = PrsDim_TypeOfAngle_Interior;
+    TCollection_AsciiString anAngleTypeStr = theStringParams.Find ("type");
+    if (anAngleTypeStr.IsEqual("interior"))
+    {
+      anAngleType = PrsDim_TypeOfAngle_Interior;
+    }
+    else if (anAngleTypeStr.IsEqual("exterior"))
+    {
+      anAngleType = PrsDim_TypeOfAngle_Exterior;
+    }
+    else
+    {
+      Message::SendFail() << "Error: wrong angle type.";
+    }
+    anAngleDim->SetType(anAngleType);
+  }
+
+  if (theStringParams.IsBound ("showarrow"))
+  {
+    PrsDim_TypeOfAngleArrowVisibility anArrowType = PrsDim_TypeOfAngleArrowVisibility_Both;
+    TCollection_AsciiString anArrowTypeStr = theStringParams.Find ("showarrow");
+    if (anArrowTypeStr.IsEqual("both"))
+    {
+      anArrowType = PrsDim_TypeOfAngleArrowVisibility_Both;
+    }
+    else if (anArrowTypeStr.IsEqual("first"))
+    {
+      anArrowType = PrsDim_TypeOfAngleArrowVisibility_First;
+    }
+    else if (anArrowTypeStr.IsEqual("second"))
+    {
+      anArrowType = PrsDim_TypeOfAngleArrowVisibility_Second;
+    }
+    else if (anArrowTypeStr.IsEqual("none"))
+    {
+      anArrowType = PrsDim_TypeOfAngleArrowVisibility_None;
+    }
+    else
+    {
+      Message::SendFail() << "Error: wrong showarrow type.";
+    }
+    anAngleDim->SetArrowsVisibility(anArrowType);
+  }
+}
+
 //=======================================================================
 //function : VDimBuilder
 //purpose  : Command for building dimension presentations: angle,
@@ -472,7 +652,7 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
 {
   if (theArgsNb < 2)
   {
-    std::cerr << "Error: wrong number of arguments.\n";
+    Message::SendFail ("Syntax error: wrong number of arguments");
     return 1;
   }
 
@@ -489,26 +669,26 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
 
   TCollection_AsciiString aDimType(theArgs[2]);
   aDimType.LowerCase();
-  AIS_KindOfDimension aKindOfDimension;
+  PrsDim_KindOfDimension aKindOfDimension;
   if (aDimType == "-length")
   {
-    aKindOfDimension = AIS_KOD_LENGTH;
+    aKindOfDimension = PrsDim_KOD_LENGTH;
   }
   else if (aDimType == "-angle")
   {
-    aKindOfDimension = AIS_KOD_PLANEANGLE;
+    aKindOfDimension = PrsDim_KOD_PLANEANGLE;
   }
   else if (aDimType == "-radius")
   {
-    aKindOfDimension = AIS_KOD_RADIUS;
+    aKindOfDimension = PrsDim_KOD_RADIUS;
   }
   else if (aDimType == "-diameter" || aDimType == "-diam")
   {
-    aKindOfDimension = AIS_KOD_DIAMETER;
+    aKindOfDimension = PrsDim_KOD_DIAMETER;
   }
   else
   {
-    std::cerr << "Error: wrong type of dimension.\n";
+    Message::SendFail ("Error: wrong type of dimension");
     return 1;
   }
 
@@ -521,65 +701,111 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
   }
 
   // Build dimension
-  Handle(AIS_Dimension) aDim;
+  Handle(PrsDim_Dimension) aDim;
   switch (aKindOfDimension)
   {
-    case AIS_KOD_LENGTH:
+    case PrsDim_KOD_LENGTH:
     {
-      if (!isPlaneCustom)
-      {
-        std::cerr << theArgs[0] << ": can not build dimension without working plane.\n";
-        return 1;
-      }
       if (aShapes.Extent() == 1)
       {
         if (aShapes.First()->Type() == AIS_KOI_Shape
           && (Handle(AIS_Shape)::DownCast(aShapes.First()))->Shape().ShapeType() != TopAbs_EDGE)
         {
-          std::cerr << theArgs[0] << ": wrong shape type.\n";
+          Message::SendFail ("Error: wrong shape type");
+          return 1;
+        }
+        if (!isPlaneCustom)
+        {
+          Message::SendFail ("Error: can not build dimension without working plane");
           return 1;
         }
+
         // Adjust working plane
         TopoDS_Edge anEdge = TopoDS::Edge ((Handle(AIS_Shape)::DownCast(aShapes.First()))->Shape());
         TopoDS_Vertex aFirst, aSecond;
         TopExp::Vertices (anEdge, aFirst, aSecond);
-        aDim = new AIS_LengthDimension (anEdge, aWorkingPlane);
+        aDim = new PrsDim_LengthDimension (anEdge, aWorkingPlane);
 
         // Move standard plane (XOY, YOZ or ZOX) to the first point to make it working for dimension
-        aWorkingPlane.SetLocation (Handle(AIS_LengthDimension)::DownCast (aDim)->FirstPoint());
+        aWorkingPlane.SetLocation (Handle(PrsDim_LengthDimension)::DownCast (aDim)->FirstPoint());
       }
       else if (aShapes.Extent() == 2)
       {
-        if (aShapes.First()->Type() == AIS_KOI_Shape && aShapes.Last()->Type() == AIS_KOI_Shape)
-          aDim = new AIS_LengthDimension ((Handle(AIS_Shape)::DownCast(aShapes.First ()))->Shape(),
-          (Handle(AIS_Shape)::DownCast(aShapes.Last ()))->Shape(),
-          aWorkingPlane);
-        else// AIS_Point
+        TopoDS_Shape aShape1, aShape2;
+
+        // Getting shapes
+        if (aShapes.First()->DynamicType() == STANDARD_TYPE (AIS_Point))
         {
-          Handle(AIS_Point) aPoint1 = Handle(AIS_Point)::DownCast(aShapes.First ());
-          Handle(AIS_Point) aPoint2 = Handle(AIS_Point)::DownCast(aShapes.Last ());
-          // Adjust working plane
-          aWorkingPlane.SetLocation (BRep_Tool::Pnt(aPoint1->Vertex()));
-          aDim = new AIS_LengthDimension (aPoint1->Component()->Pnt(),
-            aPoint2->Component()->Pnt(),
-            aWorkingPlane);
+          aShape1 = Handle(AIS_Point)::DownCast (aShapes.First ())->Vertex();
+        }
+        else if (aShapes.First()->Type() == AIS_KOI_Shape)
+        {
+          aShape1 = (Handle(AIS_Shape)::DownCast (aShapes.First()))->Shape();
+        }
+
+        if (aShapes.Last()->DynamicType() == STANDARD_TYPE (AIS_Point))
+        {
+          aShape2 = Handle(AIS_Point)::DownCast (aShapes.Last ())->Vertex();
+        }
+        else if (aShapes.Last()->Type() == AIS_KOI_Shape)
+        {
+          aShape2 = (Handle(AIS_Shape)::DownCast (aShapes.Last()))->Shape();
+        }
+
+        if (aShape1.IsNull() || aShape2.IsNull())
+        {
+          Message::SendFail ("Error: wrong shape type.");
+          return 1;
+        }
+
+        // Face-Face case
+        if (aShape1.ShapeType() == TopAbs_FACE && aShape2.ShapeType() == TopAbs_FACE)
+        {
+          aDim = new PrsDim_LengthDimension (TopoDS::Face (aShape1), TopoDS::Face (aShape2));
+        }
+        else if (aShape1.ShapeType() == TopAbs_FACE && aShape2.ShapeType() == TopAbs_EDGE)
+        {
+          aDim = new PrsDim_LengthDimension (TopoDS::Face (aShape1), TopoDS::Edge (aShape2));
+        }
+        else if (aShape1.ShapeType() == TopAbs_EDGE && aShape2.ShapeType() == TopAbs_FACE)
+        {
+          aDim = new PrsDim_LengthDimension (TopoDS::Face (aShape2), TopoDS::Edge (aShape1));
+        }
+        else
+        {
+          if (!isPlaneCustom)
+          {
+            Message::SendFail ("Error: can not build dimension without working plane.");
+            return 1;
+          }
+          // Vertex-Vertex case
+          if (aShape1.ShapeType() == TopAbs_VERTEX)
+          {
+            aWorkingPlane.SetLocation (BRep_Tool::Pnt (TopoDS::Vertex (aShape1)));
+          }
+          else if (aShape2.ShapeType() == TopAbs_VERTEX)
+          {
+            aWorkingPlane.SetLocation (BRep_Tool::Pnt (TopoDS::Vertex (aShape2)));
+          }
+
+          aDim = new PrsDim_LengthDimension (aShape1, aShape2, aWorkingPlane);
         }
       }
       else
       {
-        std::cerr << theArgs[0] << ": wrong number of shapes to build dimension.\n";
+        Message::SendFail ("Error: wrong number of shapes to build dimension");
         return 1;
       }
 
       break;
     }
-    case AIS_KOD_PLANEANGLE:
+    case PrsDim_KOD_PLANEANGLE:
     {
       if (aShapes.Extent() == 1 && aShapes.First()->Type()==AIS_KOI_Shape)
       {
         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aShapes.First());
         if (aShape->Shape().ShapeType() == TopAbs_FACE)
-          aDim = new AIS_AngleDimension (TopoDS::Face(aShape->Shape()));
+          aDim = new PrsDim_AngleDimension (TopoDS::Face(aShape->Shape()));
       }
       if (aShapes.Extent() == 2)
       {
@@ -588,10 +814,10 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
         if (!aShape1.IsNull() && !aShape2.IsNull()
           && aShape1->Shape().ShapeType() == TopAbs_EDGE
           && aShape2->Shape().ShapeType() == TopAbs_EDGE)
-          aDim = new AIS_AngleDimension (TopoDS::Edge(aShape1->Shape()),TopoDS::Edge(aShape2->Shape()));
+          aDim = new PrsDim_AngleDimension (TopoDS::Edge(aShape1->Shape()),TopoDS::Edge(aShape2->Shape()));
         else
         {
-          std::cerr << theArgs[0] << ": wrong shapes for angle dimension.\n";
+          Message::SendFail ("Error: wrong shapes for angle dimension");
           return 1;
         }
       }
@@ -612,46 +838,65 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
         if (aPoint.IsNull())
           return 1;
         aP3 = aPoint->Component()->Pnt();
-        aDim = new AIS_AngleDimension (aP1, aP2, aP3);
+        aDim = new PrsDim_AngleDimension (aP1, aP2, aP3);
       }
       else
       {
-        std::cerr << theArgs[0] << ": wrong number of shapes to build dimension.\n";
+        Message::SendFail ("Error: wrong number of shapes to build dimension");
         return 1;
       }
 
       break;
     }
-    case AIS_KOD_RADIUS: // radius of the circle
+    case PrsDim_KOD_RADIUS: // radius of the circle
     {
-      if (aShapes.Extent() == 1)
+      gp_Pnt anAnchor;
+      bool hasAnchor = false;
+      for (NCollection_List<Handle(AIS_InteractiveObject)>::Iterator aShapeIter (aShapes); aShapeIter.More(); aShapeIter.Next())
       {
-        if (aShapes.First()->DynamicType() == STANDARD_TYPE(AIS_Circle))
+        if (Handle(AIS_Point) aPoint = Handle(AIS_Point)::DownCast(aShapeIter.Value()))
         {
-          Handle(AIS_Circle) aShape = Handle(AIS_Circle)::DownCast (aShapes.First());
-          gp_Circ aCircle = aShape->Circle()->Circ();
-          aDim = new AIS_RadiusDimension (aCircle);
+          hasAnchor = true;
+          anAnchor = aPoint->Component()->Pnt();
+          aShapes.Remove (aShapeIter);
+          break;
+        }
+      }
+      if (aShapes.Extent() != 1)
+      {
+        Message::SendFail ("Syntax error: wrong number of shapes to build dimension");
+        return 1;
+      }
+
+      if (Handle(AIS_Circle) aShapeCirc = Handle(AIS_Circle)::DownCast(aShapes.First()))
+      {
+        gp_Circ aCircle = aShapeCirc->Circle()->Circ();
+        if (hasAnchor)
+        {
+          aDim = new PrsDim_RadiusDimension (aCircle, anAnchor);
         }
         else
         {
-          Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aShapes.First());
-          if (aShape.IsNull())
-          {
-            std::cerr << "Error: shape for radius is of wrong type.\n";
-            return 1;
-          }
-          aDim = new AIS_RadiusDimension (aShape->Shape());
+          aDim = new PrsDim_RadiusDimension (aCircle);
+        }
+      }
+      else if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aShapes.First()))
+      {
+        Handle(PrsDim_RadiusDimension) aRadDim = new PrsDim_RadiusDimension (aShape->Shape());
+        if (hasAnchor)
+        {
+          aRadDim->SetMeasuredGeometry (aShape->Shape(), anAnchor);
         }
+        aDim = aRadDim;
       }
       else
       {
-        std::cerr << theArgs[0] << ": wrong number of shapes to build dimension.\n";
+        Message::SendFail ("Error: shape for radius has wrong type");
         return 1;
       }
-
       break;
     }
-    case AIS_KOD_DIAMETER:
+    case PrsDim_KOD_DIAMETER:
     {
       if (aShapes.Extent() == 1)
       {
@@ -659,22 +904,22 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
         {
           Handle(AIS_Circle) aShape = Handle(AIS_Circle)::DownCast (aShapes.First());
           gp_Circ aCircle = aShape->Circle()->Circ();
-          aDim = new AIS_DiameterDimension (aCircle);
+          aDim = new PrsDim_DiameterDimension (aCircle);
         }
         else
         {
           Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aShapes.First());
           if (aShape.IsNull())
           {
-            std::cerr << "Error: shape for radius is of wrong type.\n";
+            Message::SendFail ("Error: shape for radius is of wrong type");
             return 1;
           }
-          aDim = new AIS_DiameterDimension (aShape->Shape());
+          aDim = new PrsDim_DiameterDimension (aShape->Shape());
         }
       }
       else
       {
-        std::cerr << theArgs[0] << ": wrong number of shapes to build dimension.\n";
+        Message::SendFail ("Error: wrong number of shapes to build dimension");
         return 1;
       }
 
@@ -682,7 +927,7 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
     }
     default:
     {
-      std::cerr << theArgs[0] << ": wrong type of dimension. Type help for more information.\n";
+      Message::SendFail ("Error: wrong type of dimension. Type help for more information");
       return 1;
     }
   }
@@ -690,8 +935,8 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
   // Check dimension geometry
   if (!aDim->IsValid())
   {
-    std::cerr << theArgs[0] << ":dimension geometry is invalid, " << aDimType.ToCString()
-      << " dimension can't be built on input shapes.\n";
+    Message::SendFail() << "Error: dimension geometry is invalid, " << aDimType
+                        << " dimension can't be built on input shapes.";
     return 1;
   }
 
@@ -704,1802 +949,586 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
   return 0;
 }
 
+namespace
+{
+  //! If the given shapes are edges then check whether they are parallel else return true.
+  Standard_Boolean IsParallel (const TopoDS_Shape& theShape1,
+                               const TopoDS_Shape& theShape2)
+  {
+    if (theShape1.ShapeType() == TopAbs_EDGE
+     && theShape2.ShapeType() == TopAbs_EDGE)
+    {
+      BRepExtrema_ExtCC aDelta (TopoDS::Edge (theShape1),
+                                TopoDS::Edge (theShape2));
+      return aDelta.IsParallel();
+    }
+
+    return Standard_True;
+  }
+}
 //=======================================================================
-//function : VAngleDimBuilder
-//purpose  : 
+//function : VRelationBuilder
+//purpose  : Command for building realation presentation
 //=======================================================================
-
-static int VAngleDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
+static int VRelationBuilder (Draw_Interpretor& /*theDi*/,
+                             Standard_Integer  theArgsNb,
+                             const char**      theArgs)
 {
-  Standard_Integer aCurrentIndex;
-  if (argc!=2)
+  if (theArgsNb < 2)
   {
-    di << argv[0] << " error : wrong number of parameters.\n";
+    Message::SendFail ("Error: wrong number of arguments");
     return 1;
   }
 
-  TheAISContext()->CloseAllContexts();
-  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)) { }
+  TCollection_AsciiString aName (theArgs[1]);
+  TCollection_AsciiString aType (theArgs[2]);
 
-  TopoDS_Shape aFirstShape;
-  for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
+  PrsDim_KindOfRelation aKindOfRelation = PrsDim_KOR_NONE;
+  if (aType == "-concentric")
   {
-    aFirstShape = TheAISContext()->SelectedShape();
+    aKindOfRelation = PrsDim_KOR_CONCENTRIC;
   }
-
-  if (aFirstShape.IsNull())
+  else if (aType == "-equaldistance")
   {
-    di << argv[0] << " error : no picked shape.\n";
-    return 1;
+    aKindOfRelation = PrsDim_KOR_EQUALDISTANCE;
   }
-
-  if (aFirstShape.ShapeType()== TopAbs_EDGE)
+  else if (aType == "-equalradius")
   {
-    while (ViewerMainLoop (anArgsNum, anArgsVec)) { }
-
-    TopoDS_Shape aSecondShape;
-    for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
-    {
-      aSecondShape = TheAISContext()->SelectedShape();
-    }
-
-    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;
-    }
-
-    // Close local context to draw dimension in the neutral point.
-    TheAISContext()->CloseLocalContext (aCurrentIndex);
-
-    // Construct the dimension.
-    Handle (AIS_AngleDimension) aDim= new AIS_AngleDimension (TopoDS::Edge(aFirstShape) ,TopoDS::Edge(aSecondShape));
-    VDisplayAISObject (argv[1], aDim);
+    aKindOfRelation = PrsDim_KOR_EQUALRADIUS;
   }
-  else
+  else if (aType == "-fix")
   {
-    di << argv[0] << " error: you must select 2 edges.\n";
-    return 1;
+    aKindOfRelation = PrsDim_KOR_FIX;
   }
-
-  return 0;
-}
-
-//==============================================================================
-//function : VDiameterDim
-//purpose  : Display the diameter dimension of a face or an edge.
-//Draw arg : vdiameterdim Name 
-//==============================================================================
-
-static int VDiameterDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer aCurrentIndex;
-  Standard_Real aRadius;
-
-  // Verification
-  if (argc != 2)
+  else if (aType == "-identic")
   {
-    di<<" vdiameterdim error"<<"\n";
-    return 1;
+    aKindOfRelation = PrsDim_KOR_IDENTIC;
   }
-
-  // Close all local contexts
-  TheAISContext()->CloseAllContexts();
-  // Open local context and get its index for recovery
-  TheAISContext()->OpenLocalContext();
-  aCurrentIndex = TheAISContext()->IndexOfCurrentLocal();
-  
-  // Activate 'edge' selection mode
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  di<<" Select an circled edge."<<"\n";
-  
-  // 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) ) { }
-  // end of the loop.
-  
-  TopoDS_Shape aShape;
-  for(TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
+  else if (aType == "-offset")
   {
-    aShape = TheAISContext()->SelectedShape();
+    aKindOfRelation = PrsDim_KOR_OFFSET;
   }
-
-  if (aShape.IsNull())
+  else if (aType == "-parallel")
   {
-    di << argv[0] << ": no shape is selected." << "\n";
-    return 1;
+    aKindOfRelation = PrsDim_KOR_PARALLEL;
   }
-
-  if (aShape.ShapeType() != TopAbs_EDGE)
+  else if (aType == "-perpendicular")
   {
-    di << " vdiameterdim error: the selection of a face or an edge was expected." << "\n";
-    return 1;
+    aKindOfRelation = PrsDim_KOR_PERPENDICULAR;
+  }
+  else if (aType == "-tangent")
+  {
+    aKindOfRelation = PrsDim_KOR_TANGENT;
+  }
+  else if (aType == "-symmetric")
+  {
+    aKindOfRelation = PrsDim_KOR_SYMMETRIC;
   }
 
-  // Compute the radius
-  BRepAdaptor_Curve aCurve (TopoDS::Edge (aShape));
+  TopTools_ListOfShape aShapes;
+  ViewerTest::GetSelectedShapes (aShapes);
 
-  if (aCurve.GetType() != GeomAbs_Circle)
+  // Build relation.
+  Handle(PrsDim_Relation) aRelation;
+  switch (aKindOfRelation)
   {
-    di << "vdiameterdim error: the edge is not a circular one." << "\n";
-    return 1;
-  }
+    case PrsDim_KOR_CONCENTRIC:
+    {
+      if (aShapes.Extent() != 2)
+      {
+        Message::SendFail ("Error: Wrong number of selected shapes");
+        return 1;
+      }
 
-  gp_Circ aCircle = aCurve.Circle();
-  aRadius = 2.0 * aCircle.Radius();
+      const TopoDS_Shape& aShape1 = aShapes.First();
+      const TopoDS_Shape& aShape2 = aShapes.Last();
 
-  // Construction of the diameter dimension.
-  TheAISContext()->CloseLocalContext (aCurrentIndex);
-  Handle (AIS_DiameterDimension) aDiamDim= new AIS_DiameterDimension (aShape);
-  VDisplayAISObject (argv[1], aDiamDim);
+      if (!(aShape1.ShapeType() == TopAbs_EDGE
+         && aShape2.ShapeType() == TopAbs_EDGE))
+      {
+        Message::SendFail ("Syntax error: selected shapes are not edges");
+        return 1;
+      }
 
-  return 0;
-}
+      BRepAdaptor_Curve aCurve1 (TopoDS::Edge (aShape1));
+      gp_Circ           aCircle1 = aCurve1.Circle();
+      gp_Pnt            aCenter1 = aCircle1.Location();
+      gp_Pnt            B = aCurve1.Value (0.25);
+      gp_Pnt            C = aCurve1.Value (0.75);
+      GC_MakePlane      aMkPlane (aCenter1, B, C);
 
+      aRelation = new PrsDim_ConcentricRelation (aShape1, aShape2, aMkPlane.Value());
 
-//==============================================================================
-// Fonction  vconcentric
-// -----------------  Uniquement par selection dans le viewer.
-//==============================================================================
+      break;
+    }
+    case PrsDim_KOR_EQUALDISTANCE:
+    {
+      if (aShapes.Extent() != 4)
+      {
+        Message::SendFail ("Error: Wrong number of selected shapes");
+        return 1;
+      }
 
-//==============================================================================
-//function : VConcentric
-//purpose  : Display the concentric relation between two surfaces.
-//Draw arg : vconcentric Name
-//==============================================================================
-#include <AIS_ConcentricRelation.hxx>
-#include <Geom_Plane.hxx>
-#include <gp_Pln.hxx>
-#include <GC_MakePlane.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <TopExp_Explorer.hxx>
+      TopoDS_Shape aSelectedShapes[4];
 
+      Standard_Integer anIdx = 0;
+      TopTools_ListOfShape::Iterator anIter (aShapes);
+      for (; anIter.More(); anIter.Next(), ++anIdx)
+      {
+        aSelectedShapes[anIdx] = anIter.Value();
+      }
 
-static int VConcentricBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  
-  // Verification
-  if (argc!=2) {di<<"vconcentric  error."<<"\n";return 1;}
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections Edges et Faces.
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  di<<" Select a circled edge."<<"\n";
-  
-  // Boucle d'attente waitpick.
-  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();
-  }
-  // ShapeA est un edge
-  // ==================
-  if (ShapeA.ShapeType()==TopAbs_EDGE  ) {
-    TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
-    di<<" Select an edge."<<"\n";
-    
-    // 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 (ShapeB.ShapeType()!=TopAbs_EDGE  ) {
-      di<<" vconcentric error: select an edge."<<"\n";return 1;
-    }
-     
-    // Construction du plane.
-    // On recupere le centre du cercle A.
-    BRepAdaptor_Curve theCurveA(TopoDS::Edge(ShapeA) );
-    gp_Circ theCircleA=theCurveA.Circle();
-    gp_Pnt theCenterA=theCircleA.Location();
-    // On recupere deux points sur le cercle A
-    gp_Pnt B= theCurveA.Value(0.25);
-    gp_Pnt C= theCurveA.Value(0.75);
-    // Construction du plane.
-    GC_MakePlane MkPlane(theCenterA ,B ,C );
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    
-    // Fermeture du context local
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    
-    Handle (AIS_ConcentricRelation) myConcentry= new AIS_ConcentricRelation(ShapeA, ShapeB, theGeomPlane );
-    TheAISContext()->Display(myConcentry );
-    GetMapOfAIS().Bind (myConcentry,argv[1]);
-  }
-  
-  
-  else {
-    di<<" vconcentric  error: the selection of a face or an edge was expected."<<"\n";return 1;
-  }
-  
-  return 0;
-  
-  
-  
-  
-}
-
-//==============================================================================
-//function : VEqualDistRelation
-//purpose  : 
-//Draw arg : vdiameterdim Name DiameterValue
-//==============================================================================
-#include <AIS_EqualDistanceRelation.hxx>
-#include <BRepExtrema_ExtCC.hxx>
-#include <GC_MakePlane.hxx>
-
-
-static int VEqualDistRelation(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  
-  // Verification
-  if (argc!=2) {di<<" vequaldistrelation error: no arguments allowed."<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections Edges et Vertexes.
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1) );
-  di<<" Select an edge or a vertex"<<"\n";
-  
-  // Boucle d'attente waitpick.
-  Standard_Integer argc1 = 5;
-  const char *buf1[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-  const char **argv1 = (const char **) buf1;
-  while (ViewerMainLoop( argc1, argv1) ) { }
-  // fin de la boucle
-  
-  TopoDS_Shape ShapeA;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeA = TheAISContext()->SelectedShape();
-  }
-  
-  di<<" Select an edge or a vertex"<<"\n";
-  // Boucle d'attente waitpick.
-  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();
-  }
-  
-  // Verification des resultats.
-  if (ShapeA.ShapeType()==TopAbs_EDGE && ShapeB.ShapeType()==TopAbs_EDGE  ) {
-    // A et B sont des edges ils doivent etre paralleles
-    BRepExtrema_ExtCC myDeltaEdge (TopoDS::Edge(ShapeA) ,TopoDS::Edge(ShapeB)  );
-    // on verifie qu'ils sont pas paralleles.
-    if (!myDeltaEdge.IsParallel() ) {di<<"vequaldist error: non parallel edges."<<"\n";return 1; }
-    
-  }
-  
-  
-  di<<" Select an edge or a vertex"<<"\n";
-  // Boucle d'attente waitpick.
-  Standard_Integer argc3 = 5;
-  const char *buf3[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-  const char **argv3 = (const char **) buf3;
-  while (ViewerMainLoop( argc3, argv3) ) { }
-  // fin de la boucle
-  
-  TopoDS_Shape ShapeC;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeC = TheAISContext()->SelectedShape();
-  }
-  
-  di<<" Select an edge or a vertex"<<"\n";
-  // Boucle d'attente waitpick.
-  Standard_Integer argc4 = 5;
-  const char *buf4[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-  const char **argv4 = (const char **) buf4;
-  while (ViewerMainLoop( argc4, argv4) ) { }
-  // fin de la boucle
-  
-  TopoDS_Shape ShapeD;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeD = TheAISContext()->SelectedShape();
-  }
-  // Verification des resultats.
-  if (ShapeC.ShapeType()==TopAbs_EDGE && ShapeD.ShapeType()==TopAbs_EDGE  ) {
-    // C et D sont des edges ils doivent etre paralleles
-    BRepExtrema_ExtCC myDeltaEdge2 (TopoDS::Edge(ShapeC) ,TopoDS::Edge(ShapeD)  );
-    // on verifie qu'ils sont pas paralleles.
-    if (!myDeltaEdge2.IsParallel() ) {di<<"vequaldist error: non parallel edges."<<"\n";return 1; }
-    
-  }
-  
-  // Creation du plan porteur de la contrainte.Methode lourde!
-  gp_Pnt A,B,C;
-  if (ShapeA.ShapeType()==TopAbs_EDGE) {
-    // A est un edge
-    TopoDS_Vertex Va,Vb;
-    TopExp::Vertices (TopoDS::Edge(ShapeA) ,Va ,Vb );
-    A=BRep_Tool::Pnt(Va);
-    B=BRep_Tool::Pnt(Vb);
-    
-    if (ShapeB.ShapeType()==TopAbs_EDGE) {
-      // B est un edge aussi
-      TopoDS_Vertex Vc,Vd;
-      TopExp::Vertices (TopoDS::Edge(ShapeB) ,Vc ,Vd );
-      // besoin que de 1 point.
-      C=BRep_Tool::Pnt(Vc);
-      
-    }
-    else {
-      // B est un vertex
-      C=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB) );
-    }
-  }
-  else {
-    // A est un vertex
-    A=BRep_Tool::Pnt(TopoDS::Vertex(ShapeA) );
-    
-    if (ShapeB.ShapeType()==TopAbs_EDGE ) {
-      // B est un edge 
-      TopoDS_Vertex Vb,Vc;
-      TopExp::Vertices (TopoDS::Edge(ShapeB) ,Vb ,Vc );
-      // besoin que de 2 points.
-      B=BRep_Tool::Pnt(Vb);
-      C=BRep_Tool::Pnt(Vc);
-      
-    }
-    else {
-      // B est un vertex
-      B=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB) );
-      C.SetX(B.X()+5.);
-      C.SetY(B.Y()+5.);
-      C.SetZ(B.Z()+5.);
-      
-    }
-  }
-  
-  // Fermeture du context local.
-  TheAISContext()->CloseLocalContext(myCurrentIndex);
-  
-  // construction du plane 
-  GC_MakePlane MkPlane(A ,B ,C );
-  Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-  
-  // Construction de l'AIS_EqualDistanceRelation
-  Handle (AIS_EqualDistanceRelation ) myRelation= new AIS_EqualDistanceRelation (ShapeA, ShapeB, ShapeC ,ShapeD , theGeomPlane );
-  TheAISContext()->Display(myRelation );
-  GetMapOfAIS().Bind (myRelation,argv[1]);
-  
-
-  
-  return 0;
-  
-}
-
-//==============================================================================
-//function : VEqualRadiusRelation
-//purpose  : 
-//Draw arg : vdiameterdim Name DiameterValue
-//==============================================================================
-#include <AIS_EqualRadiusRelation.hxx>
-#include <GC_MakePlane.hxx>
-#include <BRepAdaptor_Curve.hxx>
-
+      if (!IsParallel (aSelectedShapes[0], aSelectedShapes[1])
+       || !IsParallel (aSelectedShapes[2], aSelectedShapes[3]))
+      {
+        Message::SendFail ("Syntax error: non parallel edges");
+        return 1;
+      }
 
-static int VEqualRadiusRelation(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  
-  // Verification
-  if (argc!=2) {di<<" vequalrad error: no arguments allowed."<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections Edges.
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  di<<" Select an circled edge "<<"\n";
-  
-  // Boucle d'attente waitpick.
-  Standard_Integer argc1 = 5;
-  const char *buf1[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-  const char **argv1 = (const char **) buf1;
-  while (ViewerMainLoop( argc1, argv1) ) { }
-  // fin de la boucle
-  
-  TopoDS_Shape ShapeA;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeA = TheAISContext()->SelectedShape();
-  }
-  
-  di<<" Select the last circled edge."<<"\n";
-  // Boucle d'attente waitpick.
-  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();
-  }
-  // creation du plan qui contient la contrainte.
-  TopoDS_Edge EdgeA=TopoDS::Edge(ShapeA);
-  TopoDS_Edge EdgeB=TopoDS::Edge(ShapeB);
-  BRepAdaptor_Curve theCurveA(EdgeA);
-  // On recupere 3 points A,B,C de la curve.
-  gp_Pnt A=theCurveA.Value(0.1);
-  gp_Pnt B=theCurveA.Value(0.5);
-  gp_Pnt C=theCurveA.Value(0.9);
-  
-  // fermeture du contexte local.
-  TheAISContext()->CloseLocalContext(myCurrentIndex);
-  
-  // Creation du plane.
-  GC_MakePlane MkPlane (A ,B ,C );
-  Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-  // Construction de l'AIS_EqualRadiusRelation
-  Handle (AIS_EqualRadiusRelation ) myRelation= new AIS_EqualRadiusRelation (EdgeA,EdgeB, theGeomPlane );
-  TheAISContext()->Display(myRelation );
-  GetMapOfAIS().Bind (myRelation,argv[1]);
-  
-  return 0;
-  
-}
+      gp_Pnt A, B, C;
+      if (aSelectedShapes[0].ShapeType() == TopAbs_EDGE)
+      {
+        TopoDS_Vertex Va, Vb;
+        TopExp::Vertices (TopoDS::Edge (aSelectedShapes[0]), Va, Vb);
+        A = BRep_Tool::Pnt (Va);
+        B = BRep_Tool::Pnt (Vb);
 
+        if (aSelectedShapes[1].ShapeType() == TopAbs_EDGE)
+        {
+          TopoDS_Vertex Vc, Vd;
+          TopExp::Vertices (TopoDS::Edge (aSelectedShapes[1]), Vc, Vd);
+          C = BRep_Tool::Pnt (Vc);
+        }
+        else
+        {
+          C = BRep_Tool::Pnt (TopoDS::Vertex (aSelectedShapes[1]));
+        }
+      }
+      else
+      {
+        A = BRep_Tool::Pnt (TopoDS::Vertex (aSelectedShapes[0]));
 
-//==============================================================================
-//function : VFixRelation
-//purpose  : 
-//Draw arg : vdiameterdim Name DiameterValue
-//==============================================================================
-#include <AIS_FixRelation.hxx>
-#include <GC_MakePlane.hxx>
-#include <BRepAdaptor_Curve.hxx>
+        if (aSelectedShapes[1].ShapeType() == TopAbs_EDGE)
+        {
+          TopoDS_Vertex Vb, Vc;
+          TopExp::Vertices (TopoDS::Edge (aSelectedShapes[1]), Vb, Vc);
+          B = BRep_Tool::Pnt (Vb);
+          C = BRep_Tool::Pnt (Vc);
 
-static int VFixRelation(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  
-  // Verification
-  if (argc!=2) {di<<" vfix  error: no arguments allowed."<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections edge.
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  di<<" Select an edge. "<<"\n";
-  
-  // Boucle d'attente waitpick.
-  Standard_Integer argc1 = 5;
-  const char *buf1[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-  const char **argv1 = (const char **) buf1;
-  while (ViewerMainLoop( argc1, argv1) ) { }
-  // fin de la boucle
-  
-  TopoDS_Shape ShapeA;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeA = TheAISContext()->SelectedShape();
-  }
-  
-  // creation du plan qui contient la contrainte.
-  TopoDS_Edge EdgeA=TopoDS::Edge(ShapeA);
-  BRepAdaptor_Curve theCurveA(EdgeA);
-  // On recupere 3 points A,B,C de la curve.
-  gp_Pnt A=theCurveA.Value(0.1);
-  gp_Pnt B=theCurveA.Value(0.5);
-  gp_Pnt D=theCurveA.Value(0.9);
-  gp_Pnt C(B.X()+5,B.Y()+5,B.Z()+5);
-  
-  // fermeture du contexte local.
-  TheAISContext()->CloseLocalContext(myCurrentIndex);
-  
-  // Creation du plane.
-  GC_MakePlane MkPlane (A ,D ,C );
-  Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-  // Construction de l'AIS_EqualRadiusRelation
-  Handle (AIS_FixRelation) myRelation= new AIS_FixRelation (EdgeA,theGeomPlane );
-  TheAISContext()->Display(myRelation );
-  GetMapOfAIS().Bind (myRelation,argv[1]);
-  
-  
-  return 0;
-  
-}
+        }
+        else
+        {
+          B = BRep_Tool::Pnt (TopoDS::Vertex (aSelectedShapes[1]));
+          C.SetX (B.X() + 5.0);
+          C.SetY (B.Y() + 5.0);
+          C.SetZ (B.Z() + 5.0);
 
-//==============================================================================
-//function : VIdenticRelation
-//purpose  : 
-//Draw arg : vdiameterdim Name DiameterValue
-//==============================================================================
-#include <AIS_IdenticRelation.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <TopExp_Explorer.hxx>
+        }
+      }
 
+      GC_MakePlane aMkPlane (A, B, C);
+      aRelation = new PrsDim_EqualDistanceRelation (aSelectedShapes[0], aSelectedShapes[1], aSelectedShapes[2], aSelectedShapes[3], aMkPlane.Value());
 
-static int VIdenticRelation(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  
-  // Verification
-  if (argc!=2) {di<<" videntity error: no arguments allowed."<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections  vertex et face.
-  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.
-  Standard_Integer argc1 = 5;
-  const char *buf1[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-  const char **argv1 = (const char **) buf1;
-  while (ViewerMainLoop( argc1, argv1) ) { }
-  // fin de la boucle
-  
-  TopoDS_Shape ShapeA;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeA = TheAISContext()->SelectedShape();
-  }
-  
-  di<<" Select an edge, a face or a vertex. "<<"\n";
-  // Boucle d'attente waitpick.
-  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();
-  }
-  
-  // Recuperation de points pour construir le Geom_Plnae.
-  gp_Pnt A,B,C;
-  if (ShapeA.ShapeType()==TopAbs_EDGE) {
-    // A est un edge; on peut supposer qu'il sera element d'une face ou possesseur d'un vertex ou identic a un autre edge.
-    // on recupere deux points sur l'edge (il peut etre rectiligne)
-    TopoDS_Edge EdgeA=TopoDS::Edge(ShapeA);
-    BRepAdaptor_Curve theCurveA(EdgeA);
-    // Creation des 3 points.
-    A=theCurveA.Value(0.1);
-    B=theCurveA.Value(0.9);
-    C.SetX(B.X()+5.);
-    C.SetY(B.Y()+5.);
-    C.SetZ(B.Z()+5.);
-  }
-  else if (ShapeA.ShapeType()==TopAbs_VERTEX ) {
-    // SahpeA est un Vertex
-    // On va utiliser ShapeB
-    if (ShapeB.ShapeType()==TopAbs_EDGE) {
-      // B est un edge 
-      TopoDS_Edge EdgeB=TopoDS::Edge(ShapeB);
-      BRepAdaptor_Curve theCurveB(EdgeB);
-      // Creation des 3 points.
-      A=theCurveB.Value(0.1);
-      B=theCurveB.Value(0.9);
-      C.SetX(B.X()+5.);
-      C.SetY(B.Y()+5.);
-      C.SetZ(B.Z()+5.);
-      
-    }
-    else if (ShapeB.ShapeType()==TopAbs_FACE ) {
-      // Shape B est une face
-      TopoDS_Face  FaceB=TopoDS::Face(ShapeB);
-      // On recupere 1 edge de FaceB(la face n'a pas forcement de vertex) (l'element A est forcement dans B).
-      TopExp_Explorer FaceExp(FaceB,TopAbs_EDGE);
-      TopoDS_Edge EdgeFromB=TopoDS::Edge(FaceExp.Current() );
-      // On recupere les 3 points de l'edge de face B
-      BRepAdaptor_Curve theCurveB(EdgeFromB);
-      // On recupere 3 points A,B,C de la curve.
-      A=theCurveB.Value(0.1);
-      B=theCurveB.Value(0.5);
-      C=theCurveB.Value(0.9);
-      
-    }
-    else {
-      // B ets un vetex aussi
-      A=BRep_Tool::Pnt(TopoDS::Vertex(ShapeA) );
-      B=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB) );
-      C.SetX(B.X()+5.);
-      C.SetY(B.Y()+5.);
-      C.SetZ(B.Z()+5.);
-      
+      break;
     }
-    
-  }
-  else {
-    // A est une face.
-    TopoDS_Face  FaceA=TopoDS::Face(ShapeA);
-    // On recupere 1 edge de FaceA
-    TopExp_Explorer FaceExp(FaceA,TopAbs_EDGE);
-    TopoDS_Edge EdgeFromA=TopoDS::Edge(FaceExp.Current() );
-    // On recupere les 3 points de l'edge
-    BRepAdaptor_Curve theCurveA(EdgeFromA);
-    // On recupere 3 points A,B,C de la curve.
-    A=theCurveA.Value(0.1);
-    B=theCurveA.Value(0.5);
-    C=theCurveA.Value(0.9);
-    
-  }
-  
-  // Fermeture du context local.
-  TheAISContext()->CloseLocalContext(myCurrentIndex);
-  // On construit le plane 
-  GC_MakePlane MkPlane (A ,B ,C );
-  Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-  
-  // Construction de l'AIS_IdenticRelation
-  Handle ( AIS_IdenticRelation ) myRelation= new AIS_IdenticRelation  (ShapeA ,ShapeB, theGeomPlane );
-  TheAISContext()->Display(myRelation );
-  GetMapOfAIS().Bind (myRelation,argv[1]);
-  
-
-  
-  return 0;
-  
-}
-//==============================================================================
-//function : VLengthDimension
-//purpose  : Display the diameter dimension of a face or an edge.
-//Draw arg : vdiameterdim Name DiameterValue
-//==============================================================================
-#include <AIS_LengthDimension.hxx>
-#include <BRepExtrema_ExtCC.hxx>
-#include <BRepExtrema_ExtPC.hxx>
-#include <BRepExtrema_ExtCF.hxx>
-#include <BRepExtrema_ExtPF.hxx>
-#include <BRepExtrema_ExtFF.hxx>
-#include <TCollection_ExtendedString.hxx>
-#include <BRepExtrema_DistShapeShape.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 aCurrentIndex;
-  // Verification
-  if (argc != 2)
-  {
-    di << argv[0] << " error: wrong number of arguments.\n";
-    return 1;
-  }
-
-  // Close all local contexts
-  TheAISContext()->CloseAllContexts();
-
-  // 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.
-
-  TopoDS_Shape aFirstShape;
-  for(TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
-  {
-    aFirstShape = TheAISContext()->SelectedShape();
-  }
-
-  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) ) { }
-
-  TopoDS_Shape aSecondShape;
-  for(TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
-  {
-    aSecondShape = TheAISContext()->SelectedShape();
-  }
-
-  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)
+    case PrsDim_KOR_EQUALRADIUS:
     {
-      TopoDS_Edge EdgeB = TopoDS::Edge (aSecondShape);
-      BRepExtrema_ExtCC myDeltaEdge (EdgeA ,EdgeB);
-
-      if (!myDeltaEdge.IsParallel())
+      if (aShapes.Extent() != 2 && aShapes.Extent() != 1)
       {
-        di << argv[0] << " error: non parallel edges." << "\n";
+        Message::SendFail ("Error: Wrong number of selected shapes");
         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]);
-    }
-
-    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]);
-    }
-
-    // Second shape is a face
-    else
-    {
-      TopoDS_Face FaceB = TopoDS::Face (aSecondShape);
-      BRepExtrema_ExtCF aDeltaEdgeFace (EdgeA,FaceB);
-
-      if (!aDeltaEdgeFace.IsParallel())
+      const TopoDS_Shape& aShape1 = aShapes.First();
+      const TopoDS_Shape& aShape2 = (aShapes.Extent() == 2) ? aShapes.Last() : aShape1;
+      if (!(aShape1.ShapeType() == TopAbs_EDGE
+         && aShape2.ShapeType() == TopAbs_EDGE))
       {
-        di << argv[0] << "error: the edge isn't parallel to the face;can't compute the distance." << "\n";
+        Message::SendFail ("Syntax error: selected shapes are not edges");
         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);
-
-      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);
+      TopoDS_Edge       anEdge1 = TopoDS::Edge (aShape1);
+      TopoDS_Edge       anEdge2 = TopoDS::Edge (aShape2);
+      BRepAdaptor_Curve aCurve1 (anEdge1);
+      gp_Pnt            A = aCurve1.Value (0.1);
+      gp_Pnt            B = aCurve1.Value (0.5);
+      gp_Pnt            C = aCurve1.Value (0.9);
+      GC_MakePlane      aMkPlane (A, B, C);
 
-      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]);
+      aRelation = new PrsDim_EqualRadiusRelation (anEdge1, anEdge2, aMkPlane.Value());
+      break;
     }
-
-    else if (aSecondShape.ShapeType() == TopAbs_VERTEX)
+    case PrsDim_KOR_FIX:
     {
-      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);
+      if (aShapes.Extent() != 1)
+      {
+        Message::SendFail ("Error: Wrong number of selected shapes");
+        return 1;
+      }
 
-      gce_MakePln aMakePlane (A,B,C);
-      gp_Pln aPlane= aMakePlane.Value();
+      const TopoDS_Shape& aShape = aShapes.First();
+      if (aShape.ShapeType() != TopAbs_EDGE)
+      {
+        Message::SendFail ("Syntax error: selected shapes are not edges");
+        return 1;
+      }
 
-      TheAISContext()->CloseLocalContext (aCurrentIndex);
+      TopoDS_Edge anEdge = TopoDS::Edge (aShape);
+      BRepAdaptor_Curve aCurve (anEdge);
+      gp_Pnt A = aCurve.Value(0.1);
+      gp_Pnt B = aCurve.Value(0.5);
+      gp_Pnt D = aCurve.Value(0.9);
+      gp_Pnt C (B.X() + 5.0, B.Y() + 5.0, B.Z() + 5.0);
+      GC_MakePlane aMkPlane (A, D, C);
 
-      Handle(AIS_LengthDimension ) aLenghtDim = new AIS_LengthDimension (VertexA, VertexB, aPlane);
-      TheAISContext()->Display (aLenghtDim);
-      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
+      aRelation = new PrsDim_FixRelation (anEdge, aMkPlane.Value());
+      break;
     }
-    // The second shape is face
-    else
+    case PrsDim_KOR_IDENTIC:
     {
-      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();
+      if (aShapes.Extent() != 2)
+      {
+        Message::SendFail ("Error: Wrong number of selected shapes");
+        return 1;
+      }
 
-      // Create working plane for the dimension.
-      gce_MakePln aMakePlane (A, aProjA, C);
-      gp_Pln aPlane = aMakePlane.Value();
+      const TopoDS_Shape& aShapeA = aShapes.First();
+      const TopoDS_Shape& aShapeB = aShapes.Last();
 
-      TheAISContext()->CloseLocalContext (aCurrentIndex);
+      gp_Pnt A,B,C;
+      if (aShapeA.ShapeType() == TopAbs_EDGE)
+      {
+        TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
+        BRepAdaptor_Curve aCurveA (anEdgeA);
+
+        A = aCurveA.Value (0.1);
+        B = aCurveA.Value (0.9);
+        C.SetX (B.X() + 5.0);
+        C.SetY (B.Y() + 5.0);
+        C.SetZ (B.Z() + 5.0);
+      }
+      else if (aShapeA.ShapeType() == TopAbs_VERTEX)
+      {
+        if (aShapeB.ShapeType() == TopAbs_EDGE)
+        {
+          TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
+          BRepAdaptor_Curve aCurveB (anEdgeB);
+
+          A = aCurveB.Value (0.1);
+          B = aCurveB.Value (0.9);
+          C.SetX (B.X() + 5.0);
+          C.SetY (B.Y() + 5.0);
+          C.SetZ (B.Z() + 5.0);
+        }
+        else if (aShapeB.ShapeType() == TopAbs_FACE)
+        {
+          TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
+          TopExp_Explorer aFaceExp (aFaceB, TopAbs_EDGE);
+          TopoDS_Edge anEdgeFromB = TopoDS::Edge (aFaceExp.Current());
+          BRepAdaptor_Curve aCurveB (anEdgeFromB);
+          A = aCurveB.Value (0.1);
+          B = aCurveB.Value (0.5);
+          C = aCurveB.Value (0.9);
+        }
+        else
+        {
+          A = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
+          B = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
+          C.SetX (B.X() + 5.0);
+          C.SetY (B.Y() + 5.0);
+          C.SetZ (B.Z() + 5.0);
+        }
+      }
+      else
+      {
+        TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
+        TopExp_Explorer aFaceExp (aFaceA, TopAbs_EDGE);
+        TopoDS_Edge anEdgeFromA = TopoDS::Edge (aFaceExp.Current());
+        BRepAdaptor_Curve aCurveA (anEdgeFromA);
+        A = aCurveA.Value (0.1);
+        B = aCurveA.Value (0.5);
+        C = aCurveA.Value (0.9);
+      }
 
-      // Construct the dimension.
-      Handle(AIS_LengthDimension ) aLenghtDim = new AIS_LengthDimension (VertexA, aVertexAProj, aPlane);
-      TheAISContext()->Display (aLenghtDim);
-      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
+      GC_MakePlane aMkPlane (A ,B ,C);
+      aRelation = new PrsDim_IdenticRelation (aShapeA, aShapeB, aMkPlane.Value());
+      break;
     }
-  }
-
-  // The first shape is a face.
-  else
-  {
-    TopoDS_Face FaceA = TopoDS::Face (aFirstShape);
-
-    if (aSecondShape.ShapeType() == TopAbs_EDGE)
+    case PrsDim_KOR_OFFSET:
     {
-      TopoDS_Edge EdgeB = TopoDS::Edge (aSecondShape);
-      BRepExtrema_ExtCF aDeltaEdgeFace (EdgeB,FaceA );
-
-      if (!aDeltaEdgeFace.IsParallel())
+      if (aShapes.Extent() != 2)
       {
-        di << argv[0] << " error: the edge isn't parallel to the face;can't compute the distance. " << "\n";
+        Message::SendFail ("Error: Wrong number of selected shapes");
         return 1;
       }
 
-      Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (FaceA, EdgeB);
-      TheAISContext()->Display (aLenghtDim);
-      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
-    }
-
-    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 OCCT_DEBUG
-      gp_Pnt C = BRep_Tool::Pnt(aVertex2);
-#endif
+      const TopoDS_Shape& aShape1 = aShapes.First();
+      const TopoDS_Shape& aShape2 = aShapes.Last();
+      if (!(aShape1.ShapeType() == TopAbs_FACE
+         && aShape2.ShapeType() == TopAbs_FACE))
+      {
+        Message::SendFail ("Syntax error: selected shapes are not faces");
+        return 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();
+      TopoDS_Face aFace1 = TopoDS::Face (aShape1);
+      TopoDS_Face aFace2 = TopoDS::Face (aShape2);
 
-      TheAISContext()->CloseLocalContext(aCurrentIndex);
+      BRepExtrema_ExtFF aDelta (aFace1, aFace2);
+      if (!aDelta.IsParallel())
+      {
+        Message::SendFail ("Syntax error: the faces are not parallel");
+        return 1;
+      }
 
-      Handle(AIS_LengthDimension) aLenghtDim  =new AIS_LengthDimension (VertexB, aVertexBProj, aPlane);
-      TheAISContext()->Display (aLenghtDim);
-      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
+      Standard_Real aDist = Round (sqrt (aDelta.SquareDistance (1)) * 10.0) / 10.0;
+      TCollection_ExtendedString aMessage (TCollection_ExtendedString ("offset=") + TCollection_ExtendedString (aDist));
+      aRelation = new PrsDim_OffsetDimension (aFace1, aFace2, aDist, aMessage);
+      break;
     }
-    // the second shape is face.
-    else
+    case PrsDim_KOR_PARALLEL:
     {
-      TopoDS_Face FaceB = TopoDS::Face (aSecondShape);
-      BRepExtrema_ExtFF aDeltaFaceFace (FaceA, FaceB);
-
-      if (!aDeltaFaceFace.IsParallel())
+      if (aShapes.Extent() != 2)
       {
-        di << argv[0] << " error: the faces are not parallel. "<<"\n";
+        Message::SendFail ("Error: wrong number of selected shapes");
         return 1;
       }
 
-      TheAISContext()->CloseLocalContext (aCurrentIndex);
-
-      Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (FaceA,FaceB);
-      TheAISContext()->Display (aLenghtDim);
-      GetMapOfAIS().Bind (aLenghtDim, argv[1]);
-    }
-  }
-
-  return 0;
-}
-
+      const TopoDS_Shape& aShapeA = aShapes.First();
+      const TopoDS_Shape& aShapeB = aShapes.Last();
+      if (aShapeA.ShapeType() == TopAbs_EDGE)
+      {
+        TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
+        TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
+        BRepExtrema_ExtCC aDeltaEdge (anEdgeA, anEdgeB);
 
-//==============================================================================
-//function : VRadiusDim
-//purpose  : Display the radius dimension of a face or an edge.
-//Draw arg : vradiusdim Name 
-//==============================================================================
-#include <AIS_RadiusDimension.hxx>
-#include <TCollection_ExtendedString.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <gp_Circ.hxx>
+        if (!aDeltaEdge.IsParallel())
+        {
+          Message::SendFail ("Error: the edges are not parallel");
+          return 1;
+        }
 
+        BRepAdaptor_Curve aCurveA (anEdgeA);
+        BRepAdaptor_Curve aCurveB (anEdgeB);
 
-static int VRadiusDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer aCurrentIndex;
-  Standard_Real aRadius;
-  TopoDS_Edge anEdge;
-  // Verification
-  if (argc != 2)
-  {
-    di << argv[0] << " error: wrong number of parameters." << "\n";
-    return 1;
-  }
+        gp_Pnt A = aCurveA.Value (0.1);
+        gp_Pnt B = aCurveA.Value (0.9);
+        gp_Pnt C = aCurveB.Value (0.5);
 
-  // Close all local contexts
-  TheAISContext()->CloseAllContexts();
+        GC_MakePlane aMkPlane (A, B, C);
 
-  // Open local context and get its index for recovery.
-  TheAISContext()->OpenLocalContext();
-  aCurrentIndex = TheAISContext()->IndexOfCurrentLocal();
+        aRelation = new PrsDim_ParallelRelation (anEdgeA, anEdgeB, aMkPlane.Value());
+      }
+      else
+      {
+        TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
+        TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
 
-  // 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";
+        BRepExtrema_ExtFF aDeltaFace (aFaceA, aFaceB);
+        if (!aDeltaFace.IsParallel())
+        {
+          Message::SendFail ("Error: the faces are not parallel");
+          return 1;
+        }
 
-  // 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)) { }
-  // end of the loop
+        TopExp_Explorer aFaceExpA (aFaceA, TopAbs_EDGE);
+        TopExp_Explorer aFaceExpB (aFaceB, TopAbs_EDGE);
 
-  TopoDS_Shape aShape;
+        TopoDS_Edge anEdgeA = TopoDS::Edge (aFaceExpA.Current());
+        TopoDS_Edge anEdgeB = TopoDS::Edge (aFaceExpB.Current());
 
-  for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected() )
-  {
-    aShape = TheAISContext()->SelectedShape();
-  }
+        BRepAdaptor_Curve aCurveA (anEdgeA);
+        BRepAdaptor_Curve aCurveB (anEdgeB);
+        gp_Pnt A = aCurveA.Value (0.1);
+        gp_Pnt B = aCurveA.Value (0.9);
+        gp_Pnt C = aCurveB.Value (0.5);
 
-  if (aShape.IsNull())
-  {
-    di << argv[0] << ": no shape is selected." << "\n";
-    return 1;
-  }
+        GC_MakePlane aMkPlane (A, B, C);
 
-  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;
-  }
+        aRelation = new PrsDim_ParallelRelation (aFaceA, aFaceB, aMkPlane.Value());
+      }
+      break;
+    }
+    case PrsDim_KOR_PERPENDICULAR:
+    {
+      if (aShapes.Extent() != 2)
+      {
+        Message::SendFail ("Error: Wrong number of selected shapes");
+        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);
+      const TopoDS_Shape& aShapeA = aShapes.First();
+      const TopoDS_Shape& aShapeB = aShapes.Last();
 
-    TopExp_Explorer aFaceExp (aFace,TopAbs_EDGE);
-    anEdge = TopoDS::Edge (aFaceExp.Current());
-  }
+      if (aShapeA.ShapeType() == TopAbs_EDGE)
+      {
+        TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
+        TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
 
-  // 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);
+        BRepAdaptor_Curve aCurveA (anEdgeA);
+        BRepAdaptor_Curve aCurveB (anEdgeB);
 
-  // Construct radius dimension
-  Handle (AIS_RadiusDimension) aRadDim= new AIS_RadiusDimension (aShape);
-  VDisplayAISObject (argv[1], aRadDim);
+        gp_Pnt A = aCurveA.Value (0.1);
+        gp_Pnt B = aCurveA.Value (0.9);
+        gp_Pnt C = aCurveB.Value (0.5);
 
-  return 0;
-}
+        GC_MakePlane aMkPlane (A, B, C);
 
+        aRelation = new PrsDim_PerpendicularRelation (anEdgeA, anEdgeB, aMkPlane.Value());
+      }
+      else
+      {
+        TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
+        TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
 
+        TopExp_Explorer aFaceExpA (aFaceA, TopAbs_EDGE);
+        TopExp_Explorer aFaceExpB (aFaceB, TopAbs_EDGE);
 
-//==============================================================================
-//function : VOffsetDim
-//purpose  : Display the offset dimension
-//Draw arg : voffsetdim Name 
-//==============================================================================
-#include <AIS_OffsetDimension.hxx>
-#include <TCollection_ExtendedString.hxx>
-#include <BRepExtrema_ExtFF.hxx>
+        TopoDS_Edge anEdgeA = TopoDS::Edge (aFaceExpA.Current());
+        TopoDS_Edge anEdgeB = TopoDS::Edge (aFaceExpB.Current());
 
+        BRepAdaptor_Curve aCurveA (anEdgeA);
+        BRepAdaptor_Curve aCurveB (anEdgeB);
 
-static int VOffsetDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  Standard_Real    theDist;
-  
-  // Verification
-  if (argc!=2) {di<<" voffsetdim error"<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections Faces.
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
-  di<<" Select a face."<<"\n";
-  
-  // Boucle d'attente waitpick.
-  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();
-  }
-  
-  di<<" Select a face."<<"\n";
-  // 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();
-  }
-  
-  
-  // Shape A et B est une face
-  if (ShapeA.ShapeType()==TopAbs_FACE && ShapeB.ShapeType()==TopAbs_FACE ) {
-    
-    TopoDS_Face  FaceA=TopoDS::Face(ShapeA);
-    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("offset=")+TCollection_ExtendedString(theDist ) );
-    
-    // on construit l'AIS_OffsetDimension
-    Handle(AIS_OffsetDimension) myOffsetDim=new AIS_OffsetDimension (FaceA,FaceB,theDist,TheMessage_Str );
-    TheAISContext()->Display(myOffsetDim );
-    GetMapOfAIS().Bind (myOffsetDim ,argv[1]);
-    
-    
-    
-  }
-  
-  else {
-    di<<" voffsetdim error: the selection of a face was expected."<<"\n";return 1;
-  }
-  
-  return 0;
-  
-}
+        gp_Pnt A = aCurveA.Value (0.1);
+        gp_Pnt B = aCurveA.Value (0.9);
+        gp_Pnt C = aCurveB.Value (0.5);
 
+        GC_MakePlane aMkPlane (A, B, C);
 
+        aRelation = new PrsDim_PerpendicularRelation (aFaceA, aFaceB);
+      }
 
+      break;
+    }
+    case PrsDim_KOR_TANGENT:
+    {
+      if (aShapes.Extent() != 2)
+      {
+        Message::SendFail ("Error: Wrong number of selected shapes");
+        return 1;
+      }
 
-//==============================================================================
-//function : VParallel
-//purpose  : Display the parallel relation 
-//Draw arg : vparallel Name 
-//==============================================================================
-#include <AIS_ParallelRelation.hxx>
-#include <TCollection_ExtendedString.hxx>
-#include <BRepExtrema_ExtFF.hxx>
-#include <BRepExtrema_ExtCC.hxx>
-#include <GC_MakePlane.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <TopExp_Explorer.hxx>
+      const TopoDS_Shape& aShapeA = aShapes.First();
+      const TopoDS_Shape& aShapeB = aShapes.Last();
 
+      if (aShapeA.ShapeType() == TopAbs_EDGE)
+      {
+        TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
+        TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
 
-static int VParallelBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  // Verification
-  if (argc!=2) {di<<" vparallel error"<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections Edges.
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
-  di<<" Select an edge or a face "<<"\n";
-  
-  // Boucle d'attente waitpick.
-  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();
-  }
-  
-  // SahpeA est un edge.
-  // ===================
-  if (ShapeA.ShapeType()==TopAbs_EDGE ) {
-    
-    // desactivation du mode face
-    TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
-    di<<" Select a second edge"<<"\n";
-    // 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();
-    }
-    
-    // recuperation des edges.
-    TopoDS_Edge  EdgeA=TopoDS::Edge(ShapeA);
-    TopoDS_Edge  EdgeB=TopoDS::Edge(ShapeB);
-    BRepExtrema_ExtCC myDeltaEdge (EdgeA ,EdgeB );
-    // on verifie qu'ils ne sont pas paralleles.
-    if (!myDeltaEdge.IsParallel() ) {di<<"vparallel error: non parallel edges."<<"\n";return 1; }
-    
-    
-    // On recupere les  vertexes extremites des edge A et B.
-    BRepAdaptor_Curve theCurveA(EdgeA);
-    BRepAdaptor_Curve theCurveB(EdgeB);
-    // On recupere 3 points A,B,C des  curves.
-    gp_Pnt A=theCurveA.Value(0.1);
-    gp_Pnt B=theCurveA.Value(0.9);
-    gp_Pnt C=theCurveB.Value(0.5);
-    
-    // Construction du Geom_Plane
-    GC_MakePlane MkPlane(A,B,C);
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    // Fermeture du contexte local.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    // Construction de l'AIS_ParallelRelation
-    Handle(AIS_ParallelRelation) myParaRelation= new AIS_ParallelRelation(EdgeA ,EdgeB ,theGeomPlane );
-    TheAISContext()->Display(myParaRelation );
-    GetMapOfAIS().Bind (myParaRelation ,argv[1]);
-    
-    
-  }
-  
-  // Shape A est une face
-  // ====================
-  else {
-    
-    // desactivation du mode edge
-    TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(2) );
-    di<<" Select a second edge"<<"\n";
-    // 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();
-    }
-    
-    TopoDS_Face  FaceA=TopoDS::Face(ShapeA);
-    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; }
-    
-    // recuperation des edges des faces.
-    TopExp_Explorer FaceExpA(FaceA,TopAbs_EDGE);
-    TopExp_Explorer FaceExpB(FaceB,TopAbs_EDGE);
-    
-    TopoDS_Edge EdgeA=TopoDS::Edge(FaceExpA.Current() );
-    TopoDS_Edge EdgeB=TopoDS::Edge(FaceExpB.Current() );
-    
-    // On recupere les  vertexes extremites des edge A et B.
-    BRepAdaptor_Curve theCurveA(EdgeA);
-    BRepAdaptor_Curve theCurveB(EdgeB);
-    // On recupere 3 points A,B,C des  curves.
-    gp_Pnt A=theCurveA.Value(0.1);
-    gp_Pnt B=theCurveA.Value(0.9);
-    gp_Pnt C=theCurveB.Value(0.5);
-    
-    // Construction du Geom_Plane
-    GC_MakePlane MkPlane(A,B,C);
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    // Fermeture du contexte local.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    // Construction de l'AIS_ParallelRelation
-    Handle(AIS_ParallelRelation) myParaRelation= new AIS_ParallelRelation(FaceA ,FaceB ,theGeomPlane );
-    TheAISContext()->Display(myParaRelation );
-    GetMapOfAIS().Bind (myParaRelation ,argv[1]);
-    
-    
+        BRepAdaptor_Curve aCurveA (anEdgeA);
+        BRepAdaptor_Curve aCurveB (anEdgeB);
     
-  }
-  
-  
-  return 0;
-  
-}
+        gp_Pnt A = aCurveA.Value (0.1);
+        gp_Pnt B = aCurveA.Value (0.9);
+        gp_Pnt C = aCurveB.Value (0.5);
 
+        GC_MakePlane aMkPlane (A,B,C);
 
+        aRelation = new PrsDim_TangentRelation (anEdgeA, anEdgeB, aMkPlane.Value());
+      }
+      else
+      {
+        TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
+        TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
 
+        TopExp_Explorer aFaceExpA (aFaceA, TopAbs_EDGE);
+        TopExp_Explorer aFaceExpB (aFaceB, TopAbs_EDGE);
+    
+        TopoDS_Edge anEdgeA = TopoDS::Edge (aFaceExpA.Current());
+        TopoDS_Edge anEdgeB = TopoDS::Edge (aFaceExpB.Current());
 
-//==============================================================================
-//function : VPerpendicularRelation
-//purpose  : Display the Perpendicular Relation
-//Draw arg : vperpendicular Name 
-//==============================================================================
-#include <AIS_PerpendicularRelation.hxx>
-#include <TCollection_ExtendedString.hxx>
-#include <GC_MakePlane.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <TopExp_Explorer.hxx>
+        BRepAdaptor_Curve aCurveA (anEdgeA);
+        BRepAdaptor_Curve aCurveB (anEdgeB);
 
+        gp_Pnt A = aCurveA.Value (0.1);
+        gp_Pnt B = aCurveA.Value (0.9);
+        gp_Pnt C = aCurveB.Value (0.5);
 
+        GC_MakePlane aMkPlane (A,B,C);
 
-static int VPerpendicularBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  // Verification
-  if (argc!=2) {di<<" vortho error"<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections Edges.
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
-  di<<" Select an edge or a face "<<"\n";
-  
-  // Boucle d'attente waitpick.
-  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();
-  }
-  
-  // ShapeA est un edge.
-  // ===================
-  if (ShapeA.ShapeType()==TopAbs_EDGE ) {
-    
-    // desactivation du mode face
-    TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
-    di<<" Select a second edge"<<"\n";
-    // 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();
-    }
-    
-    // recuperation des edges.
-    TopoDS_Edge  EdgeA=TopoDS::Edge(ShapeA);
-    TopoDS_Edge  EdgeB=TopoDS::Edge(ShapeB);
-    
-    // On recupere les  curves
-    BRepAdaptor_Curve theCurveA(EdgeA);
-    BRepAdaptor_Curve theCurveB(EdgeB);
-    // on verifie si les edges sont orthogonaux.
-    //gp_Lin theLineA=theCurveA.Line();
-    //gp_Lin theLineB=theCurveB.Line();
-    //if (abs(theLineA.Angle(theLineB) ) != M_PI/2 ) {cout<<"vperpendicular error: Edges are not  othogonals."<<endl;return 1;}
-    
-    // On recupere 3 points A,B,C des  curves.
-    gp_Pnt A=theCurveA.Value(0.1);
-    gp_Pnt B=theCurveA.Value(0.9);
-    gp_Pnt C=theCurveB.Value(0.5);
-    // Construction du Geom_Plane
-    GC_MakePlane MkPlane(A,B,C);
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    // Fermeture du contexte local.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    // Construction de l'AIS_ParallelRelation
-    Handle(AIS_PerpendicularRelation) myOrthoRelation= new AIS_PerpendicularRelation (EdgeA ,EdgeB ,theGeomPlane );
-    TheAISContext()->Display(myOrthoRelation );
-    GetMapOfAIS().Bind (myOrthoRelation ,argv[1]);
-    
-    
-  }
-  
-  // Shape A est une face
-  // ====================
-  else {
-    
-    // desactivation du mode edge
-    TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(2) );
-    di<<" Select a second edge"<<"\n";
-    // 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();
+        aRelation = new PrsDim_TangentRelation (aFaceA, aFaceB, aMkPlane.Value());
+      }
+      break;
     }
-    
-    // pas de verification d'orthogonalite.
-    TopoDS_Face  FaceA=TopoDS::Face(ShapeA);
-    TopoDS_Face  FaceB=TopoDS::Face(ShapeB);
-    
-    // recuperation des edges des faces.
-    TopExp_Explorer FaceExpA(FaceA,TopAbs_EDGE);
-    TopExp_Explorer FaceExpB(FaceB,TopAbs_EDGE);
-    
-    TopoDS_Edge EdgeA=TopoDS::Edge(FaceExpA.Current() );
-    TopoDS_Edge EdgeB=TopoDS::Edge(FaceExpB.Current() );
-    
-    // On recupere les  vertexes extremites des edge A et B.
-    BRepAdaptor_Curve theCurveA(EdgeA);
-    BRepAdaptor_Curve theCurveB(EdgeB);
-    // On recupere 3 points A,B,C des  curves.
-    gp_Pnt A=theCurveA.Value(0.1);
-    gp_Pnt B=theCurveA.Value(0.9);
-    gp_Pnt C=theCurveB.Value(0.5);
-    // Construction du Geom_Plane
-    GC_MakePlane MkPlane(A,B,C);
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    // Fermeture du contexte local.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    // Construction de l'AIS_PerpendicularRelation
-    Handle(AIS_PerpendicularRelation) myOrthoRelation= new AIS_PerpendicularRelation(FaceA ,FaceB );
-    TheAISContext()->Display(myOrthoRelation );
-    GetMapOfAIS().Bind (myOrthoRelation  ,argv[1]);
-    
-    
-    
-  }
-  
-  
-  return 0;
-  
-}
+    case PrsDim_KOR_SYMMETRIC:
+    {
+      if (aShapes.Extent() != 3)
+      {
+        Message::SendFail ("Error: Wrong number of selected shapes");
+        return 1;
+      }
 
+      TopoDS_Shape aSelectedShapes[3];
+      Standard_Integer anIdx = 0;
+      TopTools_ListOfShape::Iterator anIter (aShapes);
+      for (; anIter.More(); anIter.Next(), ++anIdx)
+      {
+        aSelectedShapes[anIdx] = anIter.Value();
+      }
 
-//==============================================================================
-//function : VTangentRelation
-//purpose  : Display the tangent Relation
-//Draw arg : vtangent Name 
-//==============================================================================
-#include <AIS_TangentRelation.hxx>
+      TopoDS_Edge anEdgeA = TopoDS::Edge (aSelectedShapes[0]);
+      if (aSelectedShapes[1].ShapeType() == TopAbs_EDGE)
+      {
+        // 1 - edge,  2 - edge, 3 - edge.
+        TopoDS_Edge anEdgeB = TopoDS::Edge (aSelectedShapes[1]);
+        TopoDS_Edge anEdgeC = TopoDS::Edge (aSelectedShapes[2]);
 
+        BRepExtrema_ExtCC aDeltaEdgeAB (anEdgeA, anEdgeB);
+        BRepExtrema_ExtCC aDeltaEdgeAC (anEdgeA, anEdgeC);
 
-static int VTangentBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  // Verification
-  if (argc!=2) {di<<" vtangent error"<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections Edges.
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
-  di<<" Select two coplanar edges(First the circular edge then the tangent edge) or two faces "<<"\n";
-  
-  // Boucle d'attente waitpick.
-  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();
-  }
-  
-  // ShapeA est un edge.
-  // ===================
-  if (ShapeA.ShapeType()==TopAbs_EDGE ) {
-    
-    // desactivation du mode face
-    TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
-    di<<" Select a second edge"<<"\n";
-    // 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();
-    }
-    
-    // recuperation des edges.
-    TopoDS_Edge  EdgeA=TopoDS::Edge(ShapeA);
-    TopoDS_Edge  EdgeB=TopoDS::Edge(ShapeB);
-    
-    // On recupere les  curves
-    BRepAdaptor_Curve theCurveA(EdgeA);
-    BRepAdaptor_Curve theCurveB(EdgeB);
-    
-    // On recupere 3 points A,B,C des  curves.
-    gp_Pnt A=theCurveA.Value(0.1);
-    gp_Pnt B=theCurveA.Value(0.9);
-    gp_Pnt C=theCurveB.Value(0.5);
-
-    // Construction du Geom_Plane
-    GC_MakePlane MkPlane(A,B,C);
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    // Fermeture du contexte local.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    // Construction de l'AIS_TangentRelation
-    Handle(AIS_TangentRelation) myTanRelation= new AIS_TangentRelation  (EdgeA ,EdgeB ,theGeomPlane );
-    TheAISContext()->Display(myTanRelation );
-    GetMapOfAIS().Bind (myTanRelation ,argv[1]);
-    
-    
-  }
-  
-  // Shape A est une face
-  // ====================
-  else {
-    
-    // desactivation du mode edge
-    TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(2) );
-    di<<" Select a second edge"<<"\n";
-    // 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();
-    }
-    
-    TopoDS_Face  FaceA=TopoDS::Face(ShapeA);
-    TopoDS_Face  FaceB=TopoDS::Face(ShapeB);
-    
-    // recuperation des edges des faces.
-    TopExp_Explorer FaceExpA(FaceA,TopAbs_EDGE);
-    TopExp_Explorer FaceExpB(FaceB,TopAbs_EDGE);
-    
-    TopoDS_Edge EdgeA=TopoDS::Edge(FaceExpA.Current() );
-    TopoDS_Edge EdgeB=TopoDS::Edge(FaceExpB.Current() );
-    
-    // On recupere les  vertexes extremites des edge A et B.
-    BRepAdaptor_Curve theCurveA(EdgeA);
-    BRepAdaptor_Curve theCurveB(EdgeB);
-    // On recupere 3 points A,B,C des  curves.
-    gp_Pnt A=theCurveA.Value(0.1);
-    gp_Pnt B=theCurveA.Value(0.9);
-    gp_Pnt C=theCurveB.Value(0.5);
-
-    // Construction du Geom_Plane
-    GC_MakePlane MkPlane(A,B,C);
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    // Fermeture du contexte local.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    // Construction de l'AIS_PerpendicularRelation
-    Handle(AIS_TangentRelation) myTanRelation= new AIS_TangentRelation(FaceA ,FaceB,theGeomPlane );
-    TheAISContext()->Display(myTanRelation );
-    GetMapOfAIS().Bind (myTanRelation  ,argv[1]);
-    
-    
-    
-  }
-  
-  
-  return 0;
-  
-}
+        if (!aDeltaEdgeAB.IsParallel())
+        {
+          Message::SendFail ("Syntax error: the edges are not parallel");
+          return 1;
+        }
+        if (!aDeltaEdgeAC.IsParallel())
+        {
+          Message::SendFail ("Syntax error: the edges are not parallel");
+          return 1;
+        }
 
-//==============================================================================
-//function : VSymetricalRelation
-//purpose  : Display the Symetrical Relation
-//Draw arg : vsymetric Name 
-//==============================================================================
-#include <AIS_SymmetricRelation.hxx>
+        TopoDS_Vertex Va, Vb, Vc, Vd;
+        TopExp::Vertices (anEdgeB, Va, Vb);
+        TopExp::Vertices (anEdgeC, Vc, Vd);
+        gp_Pnt A = BRep_Tool::Pnt (Va);
+        gp_Pnt B = BRep_Tool::Pnt (Vc);
+        gp_Pnt C = Get3DPointAtMousePosition();
 
+        GC_MakePlane aMkPlane (A, B, C);
 
-static int VSymmetricBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) 
-{
-  // Declarations
-  Standard_Integer myCurrentIndex;
-  // Verification
-  if (argc!=2) {di<<" vSymmetric error"<<"\n";return 1;}
-  
-  // Fermeture des contextes locaux
-  TheAISContext()->CloseAllContexts();
-  
-  // Ouverture d'un contexte local et recuperation de son index.
-  TheAISContext()->OpenLocalContext();
-  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
-  
-  // On active les modes de selections
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  di<<" Select an edge:the axis of symetry "<<"\n";
-  
-  // Boucle d'attente waitpick.
-  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();
-  }
-  // recuperation des edges.
-  TopoDS_Edge  EdgeA=TopoDS::Edge(ShapeA);
-  
-  // On active les modes de selections
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
-  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1) );
-  di<<" Select two edges or two vertices. "<<"\n";
-  
-  // Boucle d'attente waitpick.
-  Standard_Integer argcc2 = 5;
-//  const char *buff2[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
-  const char **argvv2 = (const char **) buff;
-  while (ViewerMainLoop( argcc2, argvv2) ) { }
-  // fin de la boucle
-  
-  TopoDS_Shape ShapeB;
-  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-    ShapeB = TheAISContext()->SelectedShape();
-  }
-  
-  
-  
-  
-  
-  // ShapeB est un edge.
-  // ===================
-  if (ShapeB.ShapeType()==TopAbs_EDGE ) {
-    
-    // desactivation du mode vertex
-    TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(1) );
-    di<<" Select a second edge"<<"\n";
-    // 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 ShapeC;
-    for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-      ShapeC = TheAISContext()->SelectedShape();
+        aRelation = new PrsDim_SymmetricRelation (anEdgeA, anEdgeB, anEdgeC, aMkPlane.Value());
+      }
+      else
+      {
+        // 1 - edge, 2 - vertex, 3 - vertex
+        TopoDS_Vertex aVertexB = TopoDS::Vertex (aSelectedShapes[1]);
+        TopoDS_Vertex aVertexC = TopoDS::Vertex (aSelectedShapes[2]);
+
+        gp_Pnt B = BRep_Tool::Pnt (aVertexB);
+        gp_Pnt C = BRep_Tool::Pnt (aVertexC);
+
+        TopoDS_Vertex Va, Vb;
+        TopExp::Vertices (anEdgeA, Va, Vb);
+        gp_Pnt A = BRep_Tool::Pnt (Va);
+
+        GC_MakePlane aMkPlane(A, B, C);
+        aRelation = new PrsDim_SymmetricRelation (anEdgeA, aVertexB, aVertexC, aMkPlane.Value());
+      }
+
+      break;
     }
-    
-    // recuperation des edges.
-    TopoDS_Edge  EdgeB=TopoDS::Edge(ShapeB);
-    TopoDS_Edge  EdgeC=TopoDS::Edge(ShapeC);
-    // on verifie que les edges sont paralleles
-    BRepExtrema_ExtCC myDeltaEdgeAB (EdgeA ,EdgeB );
-    BRepExtrema_ExtCC myDeltaEdgeAC (EdgeA ,EdgeC );
-    // on verifie qu'ils  sont paralleles.
-    if (!myDeltaEdgeAB.IsParallel() ) {di<<"vsymetric error: non parallel edges."<<"\n";return 1; }
-    if (!myDeltaEdgeAC.IsParallel() ) {di<<"vsymetric error: non parallel edges."<<"\n";return 1; }
-    // on recupere les vertexs
-    TopoDS_Vertex  Va,Vb,Vc,Vd;
-    TopExp::Vertices(EdgeB,Va,Vb );
-    TopExp::Vertices(EdgeC,Vc,Vd );
-    gp_Pnt A=BRep_Tool::Pnt(Va);
-    gp_Pnt B=BRep_Tool::Pnt(Vc);
-    gp_Pnt C = Get3DPointAtMousePosition();
-    
-    //    gp_Pnt C=BRep_Tool::Pnt(Vc);
-    // Construction du Geom_Plane
-    GC_MakePlane MkPlane(A,B,C);
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    // Fermeture du contexte local.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    // Construction de l'AIS_SymmetricRelation
-    Handle(AIS_SymmetricRelation) mySymRelation= new AIS_SymmetricRelation (EdgeA ,EdgeB ,EdgeC, theGeomPlane );
-    TheAISContext()->Display(mySymRelation );
-    GetMapOfAIS().Bind (mySymRelation ,argv[1]);
-    
-    
-  }
-  
-  // Shape B est un vertex
-  // =====================
-  else {
-    
-    // desactivation du mode edge
-    TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(2) );
-    di<<" Select a second edge"<<"\n";
-    // 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 ShapeC;
-    for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
-      ShapeC = TheAISContext()->SelectedShape();
+    case PrsDim_KOR_NONE:
+    {
+      Message::SendFail ("Error: Unknown type of relation!");
+      return 1;
     }
-    
-    // recuperation des Vertex
-    TopoDS_Vertex  VertexB=TopoDS::Vertex(ShapeB);
-    TopoDS_Vertex  VertexC=TopoDS::Vertex(ShapeC);
-    // transfo en gp_Pnt
-    gp_Pnt B=BRep_Tool::Pnt(VertexB);
-    gp_Pnt C=BRep_Tool::Pnt(VertexC);
-    
-    // on recupere les vertexes de l'axe de sym
-    TopoDS_Vertex  Va,Vb;
-    TopExp::Vertices(EdgeA,Va,Vb );
-    gp_Pnt A=BRep_Tool::Pnt(Va);
-    // Construction du Geom_Plane
-    GC_MakePlane MkPlane(A,B,C);
-    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
-    // Fermeture du contexte local.
-    TheAISContext()->CloseLocalContext(myCurrentIndex);
-    // Construction de l'AIS_SymmetricRelation
-    Handle(AIS_SymmetricRelation) mySymRelation= new AIS_SymmetricRelation (EdgeA ,VertexB ,VertexC, theGeomPlane );
-    TheAISContext()->Display(mySymRelation );
-    GetMapOfAIS().Bind (mySymRelation ,argv[1]);
-    
-    
-    
   }
-  
-  
+
+  VDisplayAISObject (aName, aRelation);
   return 0;
-  
 }
 
 //=======================================================================
@@ -2523,20 +1552,19 @@ static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
   NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
   NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
 
-  if (!GetMapOfAIS().IsBound2 (aName))
+  Handle(AIS_InteractiveObject) anObject;
+  if (!GetMapOfAIS().Find2 (aName, anObject))
   {
     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)
+  Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (anObject);
+  if (aDim.IsNull())
   {
     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();
 
   if (ParseDimensionParams (theArgNum, theArgVec, 2, anAspect,
@@ -2555,7 +1583,7 @@ static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
 
   if (!aDim->IsValid())
   {
-    std::cerr << "Error: Dimension geometry or plane is not valid.\n";
+    Message::SendFail ("Error: Dimension geometry or plane is not valid");
     return 1;
   }
 
@@ -2568,6 +1596,157 @@ static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
   return 0;
 }
 
+//=======================================================================
+//function : VLengthParam
+//purpose  : Sets parameters to length dimension.
+//=======================================================================
+static int VLengthParam (Draw_Interpretor&, Standard_Integer theArgNum, const char** theArgVec)
+{
+  if (theArgNum < 3)
+  {
+    Message::SendFail ("Syntax error: the wrong number of input parameters");
+    return 1;
+  }
+
+  TCollection_AsciiString aName (theArgVec[1]);
+  Handle(AIS_InteractiveObject) anObject;
+  if (!GetMapOfAIS().Find2 (aName, anObject))
+  {
+    Message::SendFail() << "Syntax error: no object with name '" << aName << "'";
+    return 1;
+  }
+
+  Handle(PrsDim_LengthDimension) aLengthDim = Handle(PrsDim_LengthDimension)::DownCast (anObject);
+  if (aLengthDim.IsNull())
+  {
+    Message::SendFail() << "Syntax error: no length dimension with name '" << aName << "'";
+    return 1;
+  }
+
+  // parse direction value
+  gp_Dir aDirection;
+  int anArgumentIt = 2;
+  TCollection_AsciiString aParam (theArgVec[anArgumentIt]);
+  aParam.LowerCase();
+
+  bool isCustomDirection = false;
+  if (aParam.IsEqual ("-direction"))
+  {
+    if (anArgumentIt + 1 >= theArgNum)
+    {
+      Message::SendFail() << "Error: "<< aParam <<" direction should have value";
+      return 1;
+    }
+    anArgumentIt++;
+    isCustomDirection = Standard_True;
+    TCollection_AsciiString aValue = theArgVec[anArgumentIt];
+    aValue.LowerCase();
+    if (aValue == "ox")
+      aDirection = gp::DX();
+    else if (aValue == "oy")
+      aDirection = gp::DY();
+    else if (aValue == "oz")
+      aDirection = gp::DZ();
+    else if (aValue == "autodirection")
+      isCustomDirection = false;
+    else
+    {
+      if (anArgumentIt + 2 >= theArgNum)
+      {
+        Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
+        return 1;
+      }
+      // access coordinate arguments
+      TColStd_SequenceOfReal aCoords;
+      for (; anArgumentIt < theArgNum; ++anArgumentIt)
+      {
+        TCollection_AsciiString anArg (theArgVec[anArgumentIt]);
+        if (!anArg.IsRealValue())
+        {
+          break;
+        }
+        aCoords.Append (anArg.RealValue());
+      }
+      // non-numeric argument too early
+      if (aCoords.IsEmpty() || aCoords.Size() != 3)
+      {
+        Message::SendFail ("Error: wrong number of direction arguments");
+        return 1;
+      }
+      aDirection = gp_Dir (aCoords.Value (1), aCoords.Value (2), aCoords.Value (3));
+    }
+  }
+
+  aLengthDim->SetDirection (aDirection, isCustomDirection);
+  if (!aLengthDim->IsValid())
+  {
+    Message::SendFail ("Error: Dimension geometry or plane is not valid");
+    return 1;
+  }
+
+  // Redisplay a dimension after parameter changing.
+  if (ViewerTest::GetAISContext()->IsDisplayed (aLengthDim))
+  {
+    ViewerTest::GetAISContext()->Redisplay (aLengthDim, true);
+  }
+
+  return 0;
+}
+
+//=======================================================================
+//function : VAngleParam
+//purpose  : Sets aspect parameters to angle dimension.
+//=======================================================================
+static int VAngleParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec)
+{
+  if (theArgNum < 3)
+  {
+    theDi << theArgVec[0] << " error: the wrong number of input parameters.\n";
+    return 1;
+  }
+
+
+  TCollection_AsciiString aName (theArgVec[1]);
+  gp_Pln aWorkingPlane;
+  Standard_Boolean toUpdate = Standard_True;
+
+  NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
+  Handle(AIS_InteractiveObject) anObject;
+  if (!GetMapOfAIS().Find2 (aName, anObject))
+  {
+    theDi << theArgVec[0] << "error: no object with this name.\n";
+    return 1;
+  }
+
+  Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (anObject);
+  if (aDim.IsNull())
+  {
+    theDi << theArgVec[0] << "error: no dimension with this name.\n";
+    return 1;
+  }
+
+  Handle(Prs3d_DimensionAspect) anAspect = aDim->DimensionAspect();
+  if (ParseAngleDimensionParams (theArgNum, theArgVec, 2, aStringParams))
+  {
+    return 1;
+  }
+
+  SetAngleDimensionParams (aDim, aStringParams);
+
+  if (!aDim->IsValid())
+  {
+    Message::SendFail ("Error: Dimension geometry or plane is not valid");
+    return 1;
+  }
+
+  // Redisplay a dimension after parameter changing.
+  if (ViewerTest::GetAISContext()->IsDisplayed (aDim))
+  {
+    ViewerTest::GetAISContext()->Redisplay (aDim, toUpdate);
+  }
+  return 0;
+}
+
 //=======================================================================
 //function : VMoveDim
 //purpose  : Moves dimension or relation text label to defined or picked
@@ -2588,27 +1767,19 @@ static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
 
   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))
+     if (!GetMapOfAIS().Find2 (aName, aPickedObj)
+       || aPickedObj.IsNull())
      {
        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";
@@ -2617,13 +1788,6 @@ static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
   }
   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();
-
     // Loop that will be handle picking.
     Standard_Integer anArgNum = 5;
     const char *aBuffer[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
@@ -2650,7 +1814,7 @@ static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
     }
     if (!isPicked)
     {
-      theDi << theArgVec[0] << ": no dimension or relation is selected." << "\n";
+      theDi << theArgVec[0] << ": no dimension or relation is selected.\n";
       return 1;
     }
   }
@@ -2672,36 +1836,36 @@ static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
     // Set text position, update relation or dimension.
     if (aPickedObj->Type() == AIS_KOI_Relation)
     {
-      Handle(AIS_Relation) aRelation = Handle(AIS_Relation)::DownCast (aPickedObj);
+      Handle(PrsDim_Relation) aRelation = Handle(PrsDim_Relation)::DownCast (aPickedObj);
       aPoint = Get3DPointAtMousePosition();
       aRelation->SetPosition (aPoint);
-      TheAISContext()->Redisplay (aRelation);
+      TheAISContext()->Redisplay (aRelation, Standard_True);
     }
     else
     {
-      Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast (aPickedObj);
+      Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (aPickedObj);
       gp_Pnt aFirstPoint, aSecondPoint;
-      if (aDim->KindOfDimension() == AIS_KOD_PLANEANGLE)
+      if (aDim->KindOfDimension() == PrsDim_KOD_PLANEANGLE)
       {
-        Handle(AIS_AngleDimension) anAngleDim = Handle(AIS_AngleDimension)::DownCast (aDim);
+        Handle(PrsDim_AngleDimension) anAngleDim = Handle(PrsDim_AngleDimension)::DownCast (aDim);
         aFirstPoint = anAngleDim->FirstPoint();
         aSecondPoint = anAngleDim->SecondPoint();
       }
-      else if (aDim->KindOfDimension() == AIS_KOD_LENGTH)
+      else if (aDim->KindOfDimension() == PrsDim_KOD_LENGTH)
       {
-        Handle(AIS_LengthDimension) aLengthDim = Handle(AIS_LengthDimension)::DownCast (aDim);
+        Handle(PrsDim_LengthDimension) aLengthDim = Handle(PrsDim_LengthDimension)::DownCast (aDim);
         aFirstPoint = aLengthDim->FirstPoint();
         aSecondPoint = aLengthDim->SecondPoint();
       }
-      else if (aDim->KindOfDimension() == AIS_KOD_RADIUS)
+      else if (aDim->KindOfDimension() == PrsDim_KOD_RADIUS)
       {
-        Handle(AIS_RadiusDimension) aRadiusDim = Handle(AIS_RadiusDimension)::DownCast (aDim);
+        Handle(PrsDim_RadiusDimension) aRadiusDim = Handle(PrsDim_RadiusDimension)::DownCast (aDim);
         aFirstPoint = aRadiusDim->AnchorPoint();
         aSecondPoint = aRadiusDim->Circle().Location();
       }
-      else if (aDim->KindOfDimension() == AIS_KOD_DIAMETER)
+      else if (aDim->KindOfDimension() == PrsDim_KOD_DIAMETER)
       {
-        Handle(AIS_DiameterDimension) aDiameterDim = Handle(AIS_DiameterDimension)::DownCast (aDim);
+        Handle(PrsDim_DiameterDimension) aDiameterDim = Handle(PrsDim_DiameterDimension)::DownCast (aDim);
         aFirstPoint = aDiameterDim->AnchorPoint();
         aSecondPoint = aDiameterDim->Circle().Location();
       }
@@ -2712,7 +1876,7 @@ static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
       }
 
       aDim->SetTextPosition (aPoint);
-      TheAISContext()->Redisplay (aDim);
+      TheAISContext()->Redisplay (aDim, Standard_True);
     }
 
   }
@@ -2720,15 +1884,15 @@ static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
   // Set text position, update relation or dimension.
   if (aPickedObj->Type() == AIS_KOI_Relation)
   {
-    Handle(AIS_Relation) aRelation = Handle(AIS_Relation)::DownCast (aPickedObj);
+    Handle(PrsDim_Relation) aRelation = Handle(PrsDim_Relation)::DownCast (aPickedObj);
     aRelation->SetPosition (aPoint);
-    TheAISContext()->Redisplay (aRelation);
+    TheAISContext()->Redisplay (aRelation, Standard_True);
   }
   else
   {
-    Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast (aPickedObj);
+    Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (aPickedObj);
     aDim->SetTextPosition (aPoint);
-    TheAISContext()->Redisplay (aDim);
+    TheAISContext()->Redisplay (aDim, Standard_True);
   }
 
   return 0;
@@ -2745,15 +1909,20 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands)
   const char *group = "AISRelations";
 
   theCommands.Add("vdimension",
-      "vdimension name {-angle|-length|-radius|-diameter} -shapes shape1 [shape2 [shape3]]\n"
+      "vdimension name {-angle|-length|-radius|-diameter}"
+      "[-shapes shape1 [shape2 [shape3]]\n"
+      "[-selected]\n"
       "[-text 3d|2d wf|sh|wireframe|shading IntegerSize]\n"
+      "[-font FontName]\n"
       "[-label left|right|hcenter|hfit top|bottom|vcenter|vfit]\n"
       "[-arrow external|internal|fit]\n"
       "[{-arrowlength|-arlen} RealArrowLength]\n"
       "[{-arrowangle|-arangle} ArrowAngle(degrees)]\n"
       "[-plane xoy|yoz|zox]\n"
       "[-flyout FloatValue -extension FloatValue]\n"
-      "[-value CustomNumberValue]\n"
+      "[-autovalue]\n"
+      "[-value CustomRealValue]\n"
+      "[-textvalue CustomTextValue]\n"
       "[-dispunits DisplayUnitsString]\n"
       "[-modelunits ModelUnitsString]\n"
       "[-showunits | -hideunits]\n"
@@ -2761,9 +1930,25 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands)
       " -See also: vdimparam, vmovedim.\n",
       __FILE__,VDimBuilder,group);
 
+  theCommands.Add ("vrelation",
+      "vrelation name {-concentric|-equaldistance|-equalradius|-fix|-identic|-offset|-parallel|-perpendicular|-tangent|-symmetric}"
+      "\n\t\t: concentric - 2 circled edges."
+      "\n\t\t: equaldistance - 4 vertex/edges."
+      "\n\t\t: equalradius - 1 or 2 circled edges."
+      "\n\t\t: fix - 1 edge."
+      "\n\t\t: identic - 2 faces, edges or vertices."
+      "\n\t\t: offset - 2 faces."
+      "\n\t\t: parallel - 2 faces or 2 edges."
+      "\n\t\t: perpendicular - 2 faces or 2 edges."
+      "\n\t\t: tangent - two coplanar edges (first the circular edge then the tangent edge) or two faces."
+      "\n\t\t: symmetric - 3 edges or 1 edge and 2 vertices."
+      "-Builds specific relation from selected objects.",
+      __FILE__, VRelationBuilder, group);
+
   theCommands.Add("vdimparam",
     "vdimparam name"
     "[-text 3d|2d wf|sh|wireframe|shading IntegerSize]\n"
+    "[-font FontName]\n"
     "[-label left|right|hcenter|hfit top|bottom|vcenter|vfit]\n"
     "[-arrow external|internal|fit]\n"
     "[{-arrowlength|-arlen} RealArrowLength]\n"
@@ -2771,6 +1956,7 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands)
     "[-plane xoy|yoz|zox]\n"
     "[-flyout FloatValue -extension FloatValue]\n"
     "[-value CustomNumberValue]\n"
+    "[-textvalue CustomTextValue]\n"
     "[-dispunits DisplayUnitsString]\n"
     "[-modelunits ModelUnitsString]\n"
     "[-showunits | -hideunits]\n"
@@ -2778,66 +1964,26 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands)
     " -See also: vmovedim, vdimension.\n",
     __FILE__,VDimParam,group);
 
-  theCommands.Add("vangledim",
-                 "vangledim Name:Selection in the viewer only ",
-                 __FILE__,VAngleDimBuilder,group);
-  
-  theCommands.Add("vdiameterdim",
-                 "vdiameterdim Name : Selection in the viewer only ",
-                 __FILE__,VDiameterDimBuilder,group);
-  
-  theCommands.Add("vconcentric",
-                 "vconcentric Name : Selection in the viewer only ",
-                 __FILE__,VConcentricBuilder,group);
-
-  theCommands.Add("vequaldist",
-                 "vequaldist Name Selection in the viewer only ",
-                 __FILE__,VEqualDistRelation ,group);
-  
-  theCommands.Add("vequalrad",
-                 "vequalrad Name Selection in the viewer only ",
-                 __FILE__,VEqualRadiusRelation  ,group);
-  
-  theCommands.Add("vfix",  
-                 "vfix Name Selection in the viewer only ",
-                 __FILE__,VFixRelation  ,group);
-  
-  theCommands.Add("videntity",
-                 "videntity Name Selection in the viewer only ",
-                 __FILE__,VIdenticRelation  ,group);
-  
-  theCommands.Add("vdistdim",
-                 "vdistdim Name Selection in the viewer only ",
-                 __FILE__,VLenghtDimension ,group);
-  
-  theCommands.Add("vradiusdim",
-                 "vradiusdim Name Selection in the viewer only ",
-                 __FILE__,VRadiusDimBuilder ,group);
-  
-  theCommands.Add("voffsetdim",
-                 "voffsetdim Name Selection in the viewer only ",
-                 __FILE__,VOffsetDimBuilder ,group);
-  
-  theCommands.Add("vparallel",
-                 "vparallel Name Selection in the viewer only ",
-                 __FILE__,VParallelBuilder ,group);
-  
-  theCommands.Add("vortho",
-                 "vortho Name Selection in the viewer only ",
-                 __FILE__,VPerpendicularBuilder ,group);
-  
-  theCommands.Add("vtangent",  
-                 "vtangent Name Selection in the viewer only ",
-                 __FILE__,VTangentBuilder ,group);
-  
-  
-  theCommands.Add("vsymetric",
-                 "vsymetric Name Selection in the viewer only ",
-                 __FILE__,VSymmetricBuilder ,group);
+  theCommands.Add("vlengthparam",
+    "vlengthparam name"
+    "[-direction {ox|oy|oz|x y z|autodirection}]\n"
+    " -Sets parameters for length dimension.\n"
+    " -See also: vdimparam, vdimension.\n",
+    __FILE__,VLengthParam,group);
+
+  theCommands.Add("vangleparam",
+    "vangleparam name"
+    "[-type interior|exterior]\n"
+    "[-showarrow first|second|both|none]\n"
+    " -Sets parameters for angle dimension.\n"
+    " -See also: vdimparam, vdimension.\n",
+    __FILE__,VAngleParam,group);
 
   theCommands.Add("vmovedim",
-                 "vmovedim [name] [x y z]: moves picked or named (if name defined) "
-          "dimension to picked mouse position or input point.",
+      "vmovedim : vmovedim [name] [x y z]"
+      "\n\t\t: Moves picked or named (if name defined)"
+      "\n\t\t: dimension to picked mouse position or input point."
+      "\n\t\t: Text label of dimension 'name' is moved to position, another parts of dimensionare adjusted.",
                  __FILE__,VMoveDim,group);
 
 }