0028726: Quantity_NameOfColor should be replaced by Quantity_Color in function input...
[occt.git] / src / ViewerTest / ViewerTest_ObjectCommands.cxx
index 3ef8ae7..d0cdf88 100644 (file)
 
 #include <ViewerTest.hxx>
 
+#include <AIS_PlaneTrihedron.hxx>
+
 #include <Quantity_NameOfColor.hxx>
 #include <Draw_Interpretor.hxx>
 #include <Draw.hxx>
 #include <Draw_Appli.hxx>
 #include <DBRep.hxx>
+#include <DBRep_DrawableShape.hxx>
 
 #include <Font_BRepFont.hxx>
 #include <Font_BRepTextBuilder.hxx>
 #include <Font_FontMgr.hxx>
+
+#include <NCollection_List.hxx>
+
 #include <OSD_Chronometer.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <V3d_Viewer.hxx>
 #include <BRepBuilderAPI_MakeWire.hxx>
 #include <Geom_Circle.hxx>
 #include <GC_MakeCircle.hxx>
-#include <Prs3d_Presentation.hxx>
 #include <Select3D_SensitiveCircle.hxx>
 #include <SelectMgr_EntityOwner.hxx>
 #include <SelectMgr_Selection.hxx>
 #include <BRepExtrema_ExtPC.hxx>
 #include <BRepExtrema_ExtPF.hxx>
 
+#include <Prs3d_Arrow.hxx>
+#include <Prs3d_ArrowAspect.hxx>
+#include <Prs3d_DatumAttribute.hxx>
 #include <Prs3d_DatumAspect.hxx>
 #include <Prs3d_Drawer.hxx>
 #include <Prs3d_VertexDrawMode.hxx>
 #include <Prs3d_LineAspect.hxx>
 #include <Prs3d_PointAspect.hxx>
+#include <Prs3d_Presentation.hxx>
 #include <Prs3d_TextAspect.hxx>
 
 #include <Image_AlienPixMap.hxx>
@@ -147,12 +156,335 @@ extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theNam
 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
 extern Handle(AIS_InteractiveContext)& TheAISContext();
 
+namespace
+{
+  static bool convertToColor (const Handle(TColStd_HSequenceOfAsciiString)& theColorValues,
+                              Quantity_Color& theColor)
+  {
+    const char* anArgs[3] =
+    {
+      theColorValues->Size() >= 1 ? theColorValues->Value (1).ToCString() : "",
+      theColorValues->Size() >= 2 ? theColorValues->Value (2).ToCString() : "",
+      theColorValues->Size() >= 3 ? theColorValues->Value (3).ToCString() : ""
+    };
+    return ViewerTest::ParseColor (theColorValues->Size(), anArgs, theColor) != 0;
+  }
+
+  static bool convertToDatumPart (const TCollection_AsciiString& theValue,
+                                  Prs3d_DatumParts& theDatumPart)
+  {
+    TCollection_AsciiString aValue = theValue;
+    aValue.LowerCase();
+    if      (aValue == "origin")  theDatumPart = Prs3d_DP_Origin;
+    else if (aValue == "xaxis")   theDatumPart = Prs3d_DP_XAxis;
+    else if (aValue == "yaxis")   theDatumPart = Prs3d_DP_YAxis;
+    else if (aValue == "zaxis")   theDatumPart = Prs3d_DP_ZAxis;
+    else if (aValue == "xarrow")  theDatumPart = Prs3d_DP_XArrow;
+    else if (aValue == "yarrow")  theDatumPart = Prs3d_DP_YArrow;
+    else if (aValue == "zarrow")  theDatumPart = Prs3d_DP_ZArrow;
+    else if (aValue == "xoyaxis") theDatumPart = Prs3d_DP_XOYAxis;
+    else if (aValue == "yozaxis") theDatumPart = Prs3d_DP_YOZAxis;
+    else if (aValue == "xozaxis") theDatumPart = Prs3d_DP_XOZAxis;
+    else if (aValue == "whole")   theDatumPart = Prs3d_DP_None;
+    else
+    {
+      return false;
+    }
+    return true;
+  }
+
+  static void convertToDatumParts (const TCollection_AsciiString& theValue,
+                                   NCollection_List<Prs3d_DatumParts>& theParts)
+  {
+    TCollection_AsciiString aValue = theValue;
+    const Standard_Integer aSplitPos = theValue.Search ("|");
+    Prs3d_DatumParts aPart = Prs3d_DP_None;
+    if (aSplitPos > 0)
+    {
+      convertToDatumParts (theValue.SubString (aSplitPos + 1, theValue.Length()), theParts);
+      if (aSplitPos == 1) // first symbol
+      {
+        return;
+      }
+      aValue = theValue.SubString (1, aSplitPos - 1);
+    }
+    if (convertToDatumPart (aValue, aPart))
+    {
+      theParts.Append (aPart);
+    }
+  }
+
+  static bool convertToDatumAttribute (const TCollection_AsciiString& theValue,
+                                       Prs3d_DatumAttribute& theAttribute)
+  {
+    TCollection_AsciiString aValue = theValue;
+    aValue.LowerCase();
+    if      (aValue == "xaxislength")       theAttribute = Prs3d_DA_XAxisLength;
+    else if (aValue == "yaxislength")       theAttribute = Prs3d_DA_YAxisLength;
+    else if (aValue == "zaxislength")       theAttribute = Prs3d_DA_ZAxisLength;
+    else if (aValue == "tuberadiuspercent") theAttribute = Prs3d_DP_ShadingTubeRadiusPercent;
+    else if (aValue == "coneradiuspercent") theAttribute = Prs3d_DP_ShadingConeRadiusPercent;
+    else if (aValue == "conelengthpercent") theAttribute = Prs3d_DP_ShadingConeLengthPercent;
+    else if (aValue == "originradiuspercent") theAttribute = Prs3d_DP_ShadingOriginRadiusPercent;
+    else if (aValue == "shadingnumberoffacettes") theAttribute = Prs3d_DP_ShadingNumberOfFacettes;
+    else
+      return false;
+    return true;
+  }
+
+  static void convertToDatumAttributes (const TCollection_AsciiString& theValue,
+                                        NCollection_List<Prs3d_DatumAttribute>& theAttributes)
+  {
+    TCollection_AsciiString aValue = theValue;
+    const Standard_Integer aSplitPos = theValue.Search ("|");
+    Prs3d_DatumAttribute anAttribute = Prs3d_DA_XAxisLength;
+    if (aSplitPos > 0)
+    {
+      convertToDatumAttributes (theValue.SubString (aSplitPos + 1, theValue.Length()), theAttributes);
+      if (aSplitPos == 1) // first symbol
+      {
+        return;
+      }
+      aValue = theValue.SubString (1, aSplitPos - 1);
+    }
+    if (convertToDatumAttribute (aValue, anAttribute))
+    {
+      theAttributes.Append (anAttribute);
+    }
+  }
+
+  static bool convertToDatumAxes (const TCollection_AsciiString& theValue,
+                                  Prs3d_DatumAxes& theDatumAxes)
+  {
+    TCollection_AsciiString aValue = theValue;
+    aValue.LowerCase();
+    if      (aValue == "x")   theDatumAxes = Prs3d_DA_XAxis;
+    else if (aValue == "y")   theDatumAxes = Prs3d_DA_YAxis;
+    else if (aValue == "z")   theDatumAxes = Prs3d_DA_ZAxis;
+    else if (aValue == "xy")  theDatumAxes = Prs3d_DA_XYAxis;
+    else if (aValue == "zy")  theDatumAxes = Prs3d_DA_YZAxis;
+    else if (aValue == "xz")  theDatumAxes = Prs3d_DA_XZAxis;
+    else if (aValue == "xyz") theDatumAxes = Prs3d_DA_XYZAxis;
+    else
+    {
+      return false;
+    }
+    return true;
+  }
+
+  static Standard_Boolean setTrihedronParams (Standard_Integer  theArgsNb,
+                                              const char** theArgVec,
+                                              Handle(AIS_Trihedron) theTrihedron)
+  {
+    NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
+    TCollection_AsciiString aParseKey;
+    for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
+    {
+      TCollection_AsciiString anArg (theArgVec [anArgIt]);
+      if (anArg.Value (1) == '-'
+      && !anArg.IsRealValue())
+      {
+        aParseKey = anArg;
+        aParseKey.Remove (1);
+        aParseKey.LowerCase();
+        std::string aKey = aParseKey.ToCString();
+        aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString());
+        continue;
+      }
+
+      if (aParseKey.IsEmpty())
+      {
+        continue;
+      }
+
+      aMapOfArgs (aParseKey)->Append (anArg);
+    }
+
+    // Check parameters
+    if ((aMapOfArgs.IsBound ("xaxis") && !aMapOfArgs.IsBound ("zaxis"))
+    || (!aMapOfArgs.IsBound ("xaxis") &&  aMapOfArgs.IsBound ("zaxis")))
+    {
+      std::cout << "Syntax error: -xaxis and -zaxis parameters are to set together.\n";
+      return Standard_False;
+    }
+
+    Handle(TColStd_HSequenceOfAsciiString) aValues;
+    Handle(Geom_Axis2Placement) aComponent = theTrihedron->Component();
+    if (aMapOfArgs.Find ("origin", aValues))
+    {
+      aComponent->SetLocation (gp_Pnt (aValues->Value (1).RealValue(),
+                                       aValues->Value (2).RealValue(),
+                                       aValues->Value (3).RealValue()));
+    }
+    Handle(TColStd_HSequenceOfAsciiString) aXValues, aZValues;
+    if (aMapOfArgs.Find ("xaxis", aXValues) && aMapOfArgs.Find ("zaxis", aZValues))
+    {
+      gp_Dir aXDir (aXValues->Value (1).RealValue(),
+                    aXValues->Value (2).RealValue(),
+                    aXValues->Value (3).RealValue());
+
+      gp_Dir aZDir (aZValues->Value (1).RealValue(),
+                    aZValues->Value (2).RealValue(),
+                    aZValues->Value (3).RealValue());
+
+      if (!aZDir.IsNormal (aXDir, M_PI / 180.0))
+      {
+        std::cout << "Syntax error - parameters 'xaxis' and 'zaxis' are not applied as VectorX is not normal to VectorZ\n";
+        return Standard_False;
+      }
+
+      aComponent->SetXDirection(aXDir);
+      aComponent->SetDirection (aZDir);
+    }
+
+    if (aMapOfArgs.Find ("dispmode", aValues))
+    {
+      TCollection_AsciiString aValue (aValues->Value (1));
+      bool isWireframe = true;
+      if (aValue.IsEqual ("sh") || aValue.IsEqual ("shading"))
+        isWireframe = false;
+      theTrihedron->SetDatumDisplayMode (isWireframe ? Prs3d_DM_WireFrame
+                                                     : Prs3d_DM_Shaded);
+    }
+
+    if (aMapOfArgs.Find ("hidelabels", aValues))
+    {
+      if (aValues->Size() == 0)
+      {
+        std::cout << "Syntax error: -hidelabels expects parameter 'on' or 'off' after.\n";
+        return Standard_False;
+      }
+
+      Standard_Boolean toHideLabels = Standard_True;
+      ViewerTest::ParseOnOff (aValues->Value (1).ToCString(), toHideLabels);
+      if (!theTrihedron->Attributes()->HasOwnDatumAspect())
+        theTrihedron->Attributes()->SetDatumAspect(new Prs3d_DatumAspect());
+      theTrihedron->Attributes()->DatumAspect()->SetToDrawLabels (!toHideLabels);
+    }
+
+    if (aMapOfArgs.Find ("color", aValues))
+    {
+      NCollection_List<Prs3d_DatumParts> aParts;
+      if (aValues->Size() < 2)
+      {
+        std::cout << "Syntax error: -color wrong parameters.\n";
+        return Standard_False;
+      }
+
+      convertToDatumParts (aValues->Value(1), aParts);
+      aValues->Remove (1); // datum part is processed
+      Quantity_Color aColor;
+      if (!convertToColor (aValues, aColor))
+      {
+        std::cout << "Syntax error: -color wrong parameters.\n";
+        return Standard_False;
+      }
+
+      for (NCollection_List<Prs3d_DatumParts>::Iterator anIterator (aParts); anIterator.More(); anIterator.Next())
+      {
+        Prs3d_DatumParts aDatumPart = anIterator.Value();
+        if (aDatumPart == Prs3d_DP_None)
+        {
+          theTrihedron->SetColor (aColor);
+        }
+        else
+        {
+          theTrihedron->SetDatumPartColor (aDatumPart, aColor);
+        }
+      }
+    }
+
+    if (aMapOfArgs.Find ("textcolor", aValues))
+    {
+      Quantity_Color aColor;
+      if (!convertToColor (aValues, aColor))
+      {
+        std::cout << "Syntax error: -textcolor wrong parameters.\n";
+        return Standard_False;
+      }
+      theTrihedron->SetTextColor (aColor);
+    }
+
+    if (aMapOfArgs.Find ("arrowcolor", aValues))
+    {
+      Quantity_Color aColor;
+      if (!convertToColor (aValues, aColor))
+      {
+        std::cout << "Syntax error: -arrowcolor wrong parameters.\n";
+        return Standard_False;
+      }
+      theTrihedron->SetArrowColor (aColor);
+    }
+
+    if (aMapOfArgs.Find ("attribute", aValues))
+    {
+      NCollection_List<Prs3d_DatumAttribute> anAttributes;
+      if (aValues->Size() != 2)
+      {
+        std::cout << "Syntax error: -attribute wrong parameters.\n";
+        return Standard_False;
+      }
+
+      convertToDatumAttributes (aValues->Value (1), anAttributes);
+      if (!theTrihedron->Attributes()->HasOwnDatumAspect())
+        theTrihedron->Attributes()->SetDatumAspect(new Prs3d_DatumAspect());
+      for (NCollection_List<Prs3d_DatumAttribute>::Iterator anIterator (anAttributes); anIterator.More(); anIterator.Next())
+      {
+        theTrihedron->Attributes()->DatumAspect()->SetAttribute (anIterator.Value(), aValues->Value (2).RealValue());
+      }
+    }
+
+    if (aMapOfArgs.Find ("priority", aValues))
+    {
+      Prs3d_DatumParts aDatumPart;
+      if (aValues->Size() < 2
+      || !convertToDatumPart (aValues->Value (1), aDatumPart))
+      {
+        std::cout << "Syntax error: -priority wrong parameters.\n";
+        return Standard_False;
+      }
+      theTrihedron->SetSelectionPriority (aDatumPart, aValues->Value (2).IntegerValue());
+    }
+
+    if (aMapOfArgs.Find ("labels", aValues))
+    {
+      Prs3d_DatumParts aDatumPart = Prs3d_DP_None;
+      if (aValues->Size() > 2
+       && convertToDatumPart(aValues->Value(1), aDatumPart)
+       && aDatumPart >= Prs3d_DP_XAxis
+       && aDatumPart <= Prs3d_DP_ZAxis) // labels are set to axes only
+      {
+        theTrihedron->SetLabel (aDatumPart, aValues->Value (2));
+      }
+      else
+      {
+        std::cout << "Syntax error: -labels wrong parameters.\n";
+        return Standard_False;
+      }
+    }
+
+    if (aMapOfArgs.Find ("drawaxes", aValues))
+    {
+      Prs3d_DatumAxes aDatumAxes = Prs3d_DA_XAxis;
+      if (aValues->Size() < 1
+      || !convertToDatumAxes (aValues->Value (1), aDatumAxes))
+      {
+        std::cout << "Syntax error: -drawaxes wrong parameters.\n";
+        return Standard_False;
+      }
+      if (!theTrihedron->Attributes()->HasOwnDatumAspect())
+        theTrihedron->Attributes()->SetDatumAspect(new Prs3d_DatumAspect());
+      theTrihedron->Attributes()->DatumAspect()->SetDrawDatumAxes (aDatumAxes);
+    }
+    return Standard_True;
+  }
+}
+
 //==============================================================================
 //function : Vtrihedron 2d
 //purpose  : Create a plane with a 2D  trihedron from a faceselection
 //Draw arg : vtri2d  name
 //==============================================================================
-#include <AIS_PlaneTrihedron.hxx>
 static int VTrihedron2D (Draw_Interpretor& /*theDI*/,
                          Standard_Integer  theArgsNum,
                          const char**      theArgVec)
@@ -207,136 +539,60 @@ static int VTrihedron2D (Draw_Interpretor& /*theDI*/,
   return 0;
 }
 
-
-
-//==============================================================================
-//function : VTriherdron
-//purpose  : Create a trihedron. If no arguments are set, the default
-//           trihedron (Oxyz) is created.
-//Draw arg : vtrihedron  name  [Xo] [Yo] [Zo] [Zu] [Zv] [Zw] [Xu] [Xv] [Xw]
-//==============================================================================
-
-static int VTrihedron (Draw_Interpretor& /*theDi*/,
-                       Standard_Integer  theArgsNb,
-                       const char**      theArgVec)
+//=======================================================================
+//function : VTrihedron
+//purpose  :
+//=======================================================================
+static int VTrihedron (Draw_Interpretor& ,
+                       Standard_Integer theArgsNb,
+                       const char** theArgVec)
 {
-  if (theArgsNb < 2 || theArgsNb > 11)
+  if (theArgsNb < 2)
   {
-    std::cout << theArgVec[0] << " syntax error\n";
+    std::cout << "Syntax error: the wrong number of input parameters.\n";
     return 1;
   }
 
-  // Parse parameters
-  NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
-  TCollection_AsciiString aParseKey;
-  for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
-  {
-    TCollection_AsciiString anArg (theArgVec [anArgIt]);
-
-    if (anArg.Value (1) == '-' && !anArg.IsRealValue())
-    {
-      aParseKey = anArg;
-      aParseKey.Remove (1);
-      aParseKey.LowerCase();
-      aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
-      continue;
-    }
-
-    if (aParseKey.IsEmpty())
-    {
-      continue;
-    }
-
-    aMapOfArgs(aParseKey)->Append (anArg);
-  }
+  TCollection_AsciiString aName (theArgVec[1]);
+  gp_Pln aWorkingPlane;
+  Standard_Boolean toUpdate = Standard_True;
 
-  // Check parameters
-  if ( (aMapOfArgs.IsBound ("xaxis") && !aMapOfArgs.IsBound ("zaxis"))
-    || (!aMapOfArgs.IsBound ("xaxis") && aMapOfArgs.IsBound ("zaxis")) )
-  {
-    std::cout << theArgVec[0] << " error: -xaxis and -yaxis parameters are to set together.\n";
-    return 1;
-  }
+  NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
+  NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
 
-  for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
-       aMapIt.More(); aMapIt.Next())
+  Handle(AIS_Trihedron) aTrihedron;
+  if (GetMapOfAIS().IsBound2 (aName))
   {
-    const TCollection_AsciiString& aKey = aMapIt.Key();
-    const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
-
-    // Bool key, without arguments
-    if (aKey.IsEqual ("hidelabels") && anArgs->IsEmpty())
-    {
-      continue;
-    }
-
-    if ( (aKey.IsEqual ("xaxis") || aKey.IsEqual ("zaxis") || aKey.IsEqual ("origin")) && anArgs->Length() == 3
-      && anArgs->Value(1).IsRealValue() && anArgs->Value(2).IsRealValue() && anArgs->Value(3).IsRealValue() )
+    Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
+    aTrihedron = Handle(AIS_Trihedron)::DownCast (anObject);
+    if (aTrihedron.IsNull())
     {
-      continue;
+      std::cout << "Syntax error: no trihedron with this name.\n";
+      return 1;
     }
   }
-
-  // Process parameters
-  gp_Pnt anOrigin (0.0, 0.0, 0.0);
-  gp_Dir aDirZ = gp::DZ();
-  gp_Dir aDirX = gp::DX();
-
-  Handle(TColStd_HSequenceOfAsciiString) aValues;
-
-  if (aMapOfArgs.Find ("origin", aValues))
+  else
   {
-    anOrigin.SetX (aValues->Value(1).RealValue());
-    anOrigin.SetY (aValues->Value(2).RealValue());
-    anOrigin.SetZ (aValues->Value(3).RealValue());
+    Handle(Geom_Axis2Placement) aPlacement = new Geom_Axis2Placement (gp_Pnt (0.0, 0.0, 0.0),
+                                                                      gp::DZ(), gp::DX());
+    aTrihedron = new AIS_Trihedron (aPlacement);
   }
 
-  Handle(TColStd_HSequenceOfAsciiString) aValues2;
-  if (aMapOfArgs.Find ("xaxis", aValues) && aMapOfArgs.Find ("zaxis", aValues2))
+  if (!setTrihedronParams (theArgsNb, theArgVec, aTrihedron))
   {
-    Standard_Real aX = aValues->Value(1).RealValue();
-    Standard_Real aY = aValues->Value(2).RealValue();
-    Standard_Real aZ = aValues->Value(3).RealValue();
-    aDirX.SetCoord (aX, aY, aZ);
-
-    aX = aValues->Value(1).RealValue();
-    aY = aValues->Value(2).RealValue();
-    aZ = aValues->Value(3).RealValue();
-    aDirZ.SetCoord (aX, aY, aZ);
+    return 1;
   }
 
-  if (!aDirZ.IsNormal (aDirX, M_PI / 180.0))
+  // Redisplay a dimension after parameter changing.
+  if (ViewerTest::GetAISContext()->IsDisplayed (aTrihedron))
   {
-    std::cout << theArgVec[0] << " error - VectorX is not normal to VectorZ\n";
-    return 1;
+    ViewerTest::GetAISContext()->Redisplay (aTrihedron, toUpdate);
   }
-
-  Handle(Geom_Axis2Placement) aPlacement = new Geom_Axis2Placement (anOrigin, aDirZ, aDirX);
-  Handle(AIS_Trihedron) aShape = new AIS_Trihedron (aPlacement);
-
-  if (aMapOfArgs.Find ("hidelabels", aValues))
+  else
   {
-    const Handle(Prs3d_Drawer)& aDrawer = aShape->Attributes();
-
-    if(!aDrawer->HasOwnDatumAspect())
-    {
-      Handle(Prs3d_DatumAspect) aDefAspect = ViewerTest::GetAISContext()->DefaultDrawer()->DatumAspect();
-
-      Handle(Prs3d_DatumAspect) aDatumAspect = new Prs3d_DatumAspect();
-      aDatumAspect->FirstAxisAspect()->SetAspect (aDefAspect->FirstAxisAspect()->Aspect());
-      aDatumAspect->SecondAxisAspect()->SetAspect (aDefAspect->SecondAxisAspect()->Aspect());
-      aDatumAspect->ThirdAxisAspect()->SetAspect (aDefAspect->ThirdAxisAspect()->Aspect());
-      aDatumAspect->SetAxisLength (aDefAspect->FirstAxisLength(),
-                                   aDefAspect->SecondAxisLength(),
-                                   aDefAspect->ThirdAxisLength());
-
-      aDrawer->SetDatumAspect (aDatumAspect);
-    }
-
-    aDrawer->DatumAspect()->SetToDrawLabels (Standard_False);
+    VDisplayAISObject (theArgVec[1], aTrihedron);
   }
 
-  VDisplayAISObject (theArgVec[1], aShape);
   return 0;
 }
 
@@ -358,7 +614,7 @@ static int VSize (Draw_Interpretor& di, Standard_Integer argc, const char** argv
   Standard_Real                value;
   Standard_Boolean             hascol;
 
-  Quantity_NameOfColor         col = Quantity_NOC_BLACK ;
+  Quantity_Color col = Quantity_NOC_BLACK;
 
   // Verification des arguments
   if ( argc>3 ) {di<<argv[0]<<" Syntaxe error\n"; return 1;}
@@ -395,13 +651,17 @@ static int VSize (Draw_Interpretor& di, Standard_Integer argc, const char** argv
         // un AIS_Trihedron
         if (aShape->Type()==AIS_KOI_Datum && aShape->Signature()==3) {
 
-          if (aShape->HasColor()) {
-            hascol=Standard_True;
+          if (aShape->HasColor())
+          {
+            hascol = Standard_True;
 
             // On recupere la couleur de aShape
-            col=aShape->Color();}
-
-          else hascol=Standard_False;
+            aShape->Color (col);
+          }
+          else
+          {
+            hascol = Standard_False;
+          }
 
           // On downcast aShape  de AIS_InteractiveObject a AIS_Trihedron
           // pour lui appliquer la methode SetSize()
@@ -455,14 +715,17 @@ static int VSize (Draw_Interpretor& di, Standard_Integer argc, const char** argv
       if (!aShape.IsNull() &&
         aShape->Type()==AIS_KOI_Datum && aShape->Signature()==3)
       {
-
-        if (aShape->HasColor()) {
+        if (aShape->HasColor())
+        {
           hascol=Standard_True;
 
           // On recupere la couleur de aShape
-          col=aShape->Color();}
-
-        else hascol=Standard_False;
+          aShape->Color (col);
+        }
+        else
+        {
+          hascol = Standard_False;
+        }
 
         // On downcast aShape de AIS_InteractiveObject a AIS_Trihedron
         // pour lui appliquer la methode SetSize()
@@ -4108,8 +4371,31 @@ static Standard_Integer VSetSelectionMode (Draw_Interpretor& /*di*/,
     }
   }
 
-  const Standard_Integer aSelectionMode = Draw::Atoi (anArgNb == 3 ? theArgv[1] : theArgv[2]);
-  const Standard_Boolean toTurnOn       = Draw::Atoi (anArgNb == 3 ? theArgv[2] : theArgv[3]) != 0;
+  Standard_Integer aSelectionMode = -1;
+  Standard_Boolean toTurnOn = Standard_True;
+  {
+    const TCollection_AsciiString aSelModeString (theArgv[anArgNb == 3 ? 1 : 2]);
+    TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
+    if (aSelModeString.IsIntegerValue())
+    {
+      aSelectionMode = aSelModeString.IntegerValue();
+    }
+    else if (TopAbs::ShapeTypeFromString (aSelModeString.ToCString(), aShapeType))
+    {
+      aSelectionMode = AIS_Shape::SelectionMode (aShapeType);
+    }
+    else
+    {
+      std::cout << "Syntax error: unknown selection mode '" << aSelModeString  << "'\n";
+      return 1;
+    }
+  }
+  if (!ViewerTest::ParseOnOff (theArgv[anArgNb == 3 ? 2 : 3], toTurnOn))
+  {
+    std::cout << "Syntax error: on/off is expected by found '" << theArgv[anArgNb == 3 ? 2 : 3] << "'\n";
+    return 1;
+  }
+
   Standard_DISABLE_DEPRECATION_WARNINGS
   if (aSelectionMode == 0 && anAISContext->HasOpenedContext())
   {
@@ -4962,13 +5248,13 @@ static Standard_Integer VMarkersTest (Draw_Interpretor&,
       std::cerr << "Could not load image from file '" << aFileName << "'!\n";
       return 1;
     }
-    if (anImage->Format() == Image_PixMap::ImgGray)
+    if (anImage->Format() == Image_Format_Gray)
     {
-      anImage->SetFormat (Image_PixMap::ImgAlpha);
+      anImage->SetFormat (Image_Format_Alpha);
     }
-    else if (anImage->Format() == Image_PixMap::ImgGrayF)
+    else if (anImage->Format() == Image_Format_GrayF)
     {
-      anImage->SetFormat (Image_PixMap::ImgAlphaF);
+      anImage->SetFormat (Image_Format_AlphaF);
     }
     anAspect = new Graphic3d_AspectMarker3d (anImage);
   }
@@ -5934,6 +6220,217 @@ static int VPriority (Draw_Interpretor& theDI,
   return 0;
 }
 
+//! Auxiliary class for command vnormals.
+class MyShapeWithNormals : public AIS_Shape
+{
+  DEFINE_STANDARD_RTTI_INLINE(MyShapeWithNormals, AIS_Shape);
+public:
+
+  Standard_Real    NormalLength;
+  Standard_Integer NbAlongU;
+  Standard_Integer NbAlongV;
+  Standard_Boolean ToUseMesh;
+  Standard_Boolean ToOrient;
+
+public:
+
+  //! Main constructor.
+  MyShapeWithNormals (const TopoDS_Shape& theShape)
+  : AIS_Shape   (theShape),
+    NormalLength(10),
+    NbAlongU  (1),
+    NbAlongV  (1),
+    ToUseMesh (Standard_False),
+    ToOrient  (Standard_False) {}
+
+protected:
+
+  //! Comnpute presentation.
+  virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+                        const Handle(Prs3d_Presentation)&           thePrs,
+                        const Standard_Integer                      theMode) Standard_OVERRIDE
+  {
+    AIS_Shape::Compute (thePrsMgr, thePrs, theMode);
+
+    NCollection_DataMap<TopoDS_Face, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> > > aNormalMap;
+    if (ToUseMesh)
+    {
+      DBRep_DrawableShape::addMeshNormals (aNormalMap, myshape, NormalLength);
+    }
+    else
+    {
+      DBRep_DrawableShape::addSurfaceNormals (aNormalMap, myshape, NormalLength, NbAlongU, NbAlongV);
+    }
+
+    Handle(Graphic3d_Group) aPrsGroup = Prs3d_Root::NewGroup (thePrs);
+    aPrsGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
+
+    const Standard_Real aArrowAngle  = myDrawer->ArrowAspect()->Angle();
+    const Standard_Real aArrowLength = myDrawer->ArrowAspect()->Length();
+    for (NCollection_DataMap<TopoDS_Face, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> > >::Iterator aFaceIt (aNormalMap);
+         aFaceIt.More(); aFaceIt.Next())
+    {
+      const Standard_Boolean toReverse = ToOrient && aFaceIt.Key().Orientation() == TopAbs_REVERSED;
+      Handle(Graphic3d_ArrayOfSegments) aSegments = new Graphic3d_ArrayOfSegments (2 * aFaceIt.Value().Size());
+      for (NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >::Iterator aPntIt (aFaceIt.Value()); aPntIt.More(); aPntIt.Next())
+      {
+        std::pair<gp_Pnt, gp_Pnt> aPair = aPntIt.Value();
+        if (toReverse)
+        {
+          const gp_Vec aDir = aPair.first.XYZ() - aPair.second.XYZ();
+          aPair.second = aPair.first.XYZ() + aDir.XYZ();
+        }
+
+        aSegments->AddVertex (aPair.first);
+        aSegments->AddVertex (aPair.second);
+        Prs3d_Arrow::Draw (aPrsGroup, aPair.second, gp_Vec(aPair.first, aPair.second), aArrowAngle, aArrowLength);
+      }
+
+      aPrsGroup->AddPrimitiveArray (aSegments);
+    }
+  }
+
+};
+
+//=======================================================================
+//function : VNormals
+//purpose  : Displays/Hides normals calculated on shape geometry or retrieved from triangulation
+//=======================================================================
+static int VNormals (Draw_Interpretor& theDI,
+                     Standard_Integer  theArgNum,
+                     const char**      theArgs)
+{
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if (aContext.IsNull())
+  {
+    std::cout << "Error: no view available, call 'vinit' before!\n";
+    return 1;
+  }
+  else if (theArgNum < 2)
+  {
+    std::cout << "Error: wrong number of arguments! See usage:\n";
+    theDI.PrintHelp (theArgs[0]);
+    return 1;
+  }
+
+  Standard_Integer anArgIter = 1;
+  Standard_CString aShapeName = theArgs[anArgIter++];
+  TopoDS_Shape     aShape     = DBRep::Get (aShapeName);
+  Standard_Boolean isOn = Standard_True;
+  if (aShape.IsNull())
+  {
+    std::cout << "Error: shape with name '" << aShapeName << "' is not found\n";
+    return 1;
+  }
+
+  ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
+  Handle(MyShapeWithNormals) aShapePrs;
+  if (aMap.IsBound2 (aShapeName))
+  {
+    aShapePrs = Handle(MyShapeWithNormals)::DownCast (aMap.Find2 (aShapeName));
+  }
+
+  Standard_Boolean isUseMesh = Standard_False;
+  Standard_Real    aLength = 10.0;
+  Standard_Integer aNbAlongU = 1, aNbAlongV = 1;
+  Standard_Boolean isOriented = Standard_False;
+  for (; anArgIter < theArgNum; ++anArgIter)
+  {
+    TCollection_AsciiString aParam (theArgs[anArgIter]);
+    aParam.LowerCase();
+    if (anArgIter == 2
+     && ViewerTest::ParseOnOff (aParam.ToCString(), isOn))
+    {
+      continue;
+    }
+    else if (aParam == "-usemesh"
+          || aParam == "-mesh")
+    {
+      isUseMesh = Standard_True;
+    }
+    else if (aParam == "-length"
+          || aParam == "-len")
+    {
+      ++anArgIter;
+      aLength = anArgIter < theArgNum ? Draw::Atof (theArgs[anArgIter]) : 0.0;
+      if (Abs (aLength) <= gp::Resolution())
+      {
+        std::cout << "Syntax error: length should not be zero\n";
+        return 1;
+      }
+    }
+    else if (aParam == "-orient"
+          || aParam == "-oriented")
+    {
+      isOriented = Standard_True;
+      if (anArgIter + 1 < theArgNum
+        && ViewerTest::ParseOnOff (theArgs[anArgIter + 1], isOriented))
+      {
+        ++anArgIter;
+      }
+    }
+    else if (aParam == "-nbalongu"
+          || aParam == "-nbu")
+    {
+      ++anArgIter;
+      aNbAlongU = anArgIter < theArgNum ? Draw::Atoi (theArgs[anArgIter]) : 0;
+      if (aNbAlongU < 1)
+      {
+        std::cout << "Syntax error: NbAlongU should be >=1\n";
+        return 1;
+      }
+    }
+    else if (aParam == "-nbalongv"
+          || aParam == "-nbv")
+    {
+      ++anArgIter;
+      aNbAlongV = anArgIter < theArgNum ? Draw::Atoi (theArgs[anArgIter]) : 0;
+      if (aNbAlongV < 1)
+      {
+        std::cout << "Syntax error: NbAlongV should be >=1\n";
+        return 1;
+      }
+    }
+    else if (aParam == "-nbalong"
+          || aParam == "-nbuv")
+    {
+      ++anArgIter;
+      aNbAlongU = anArgIter < theArgNum ? Draw::Atoi (theArgs[anArgIter]) : 0;
+      aNbAlongV = aNbAlongU;
+      if (aNbAlongU < 1)
+      {
+        std::cout << "Syntax error: NbAlong should be >=1\n";
+        return 1;
+      }
+    }
+    else
+    {
+      std::cout << "Syntax error: unknwon argument '" << aParam << "'\n";
+      return 1;
+    }
+  }
+
+  if (isOn)
+  {
+    if (aShapePrs.IsNull())
+    {
+      aShapePrs = new MyShapeWithNormals (aShape);
+    }
+    aShapePrs->ToUseMesh    = isUseMesh;
+    aShapePrs->ToOrient     = isOriented;
+    aShapePrs->NormalLength = aLength;
+    aShapePrs->NbAlongU     = aNbAlongU;
+    aShapePrs->NbAlongV     = aNbAlongV;
+    VDisplayAISObject (aShapeName, aShapePrs);
+  }
+  else if (!aShapePrs.IsNull())
+  {
+    VDisplayAISObject (aShapeName, new AIS_Shape (aShape));
+  }
+
+  return 0;
+}
+
 //=======================================================================
 //function : ObjectsCommands
 //purpose  :
@@ -5942,11 +6439,48 @@ static int VPriority (Draw_Interpretor& theDI,
 void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
 {
   const char *group ="AISObjects";
-  theCommands.Add("vtrihedron",
-    "vtrihedron         : vtrihedron name [ -origin x y z ] [ -zaxis u v w -xaxis u v w ] [ -hidelabels ]"
-    "\n\t\t: Creates a new *AIS_Trihedron* object. If no argument is set, the default trihedron (0XYZ) is created."
-     "\n\t\t: -hidelabels allows to draw trihedron without axes labels. By default, they are displayed.",
-    __FILE__,VTrihedron,group);
+
+  theCommands.Add ("vtrihedron",
+                   "vtrihedron : vtrihedron name"
+                   "\n\t\t: [-dispMode {wireframe|shading} ]"
+                   "\n\t\t: [-origin x y z ]"
+                   "\n\t\t: [-zaxis u v w -xaxis u v w ]"
+                   "\n\t\t: [-drawaxes {X|Y|Z|XY|YZ|XZ|XYZ}]"
+                   "\n\t\t: [-hidelabels {on|off}]"
+                   "\n\t\t: [-label {XAxis|YAxis|ZAxis} value]"
+                   "\n\t\t: [-attribute {XAxisLength|YAxisLength|ZAxisLength"
+                   "\n\t\t:             |TubeRadiusPercent|ConeRadiusPercent"
+                   "\n\t\t:             |ConeLengthPercent|OriginRadiusPercent"
+                   "\n\t\t:             |ShadingNumberOfFacettes} value]"
+                   "\n\t\t: [-color {Origin|XAxis|YAxis|ZAxis|XOYAxis|YOZAxis"
+                   "\n\t\t:         |XOZAxis|Whole} {r g b | colorName}]"
+                   "\n\t\t: [-textcolor {r g b | colorName}]"
+                   "\n\t\t: [-arrowscolor {r g b | colorName}]"
+                   "\n\t\t: [-priority {Origin|XAxis|YAxis|ZAxis|XArrow"
+                   "\n\t\t:            |YArrow|ZArrow|XOYAxis|YOZAxis"
+                   "\n\t\t:            |XOZAxis|Whole} value]"
+                   "\n\t\t:"
+                   "\n\t\t: Creates a new *AIS_Trihedron* object or changes parameters of "
+                   "\n\t\t: existing trihedron. If no argument is set,"
+                   "\n\t\t: the default trihedron (0XYZ) is created."
+                   "\n\t\t: -dispMode mode of visualization: wf - wireframe,"
+                   "\n\t\t:                                  sh - shading."
+                   "\n\t\t:               Default value is wireframe."
+                   "\n\t\t: -origin allows to set trihedron location."
+                   "\n\t\t: -zaxis/-xaxis allows to set trihedron X and Z"
+                   "\n\t\t:               directions. The directions should"
+                   "\n\t\t:               be orthogonal. Y direction is calculated."
+                   "\n\t\t: -drawaxes allows to set what axes are drawn in the"
+                   "\n\t\t:           trihedron, default state is XYZ"
+                   "\n\t\t: -hidelabels allows to hide or show trihedron labels"
+                   "\n\t\t: -labels allows to change default X/Y/Z titles of axes"
+                   "\n\t\t: -attribute sets parameters of trihedron"
+                   "\n\t\t: -color sets color properties of parts of trihedron"
+                   "\n\t\t: -textcolor sets color properties of trihedron labels"
+                   "\n\t\t: -arrowscolor sets color properties of trihedron arrows"
+                   "\n\t\t: -priority allows to change default selection priority"
+                   "\n\t\t: of trihedron components",
+                   __FILE__,VTrihedron,group);
 
   theCommands.Add("vtri2d",
     "vtri2d Name"
@@ -6232,4 +6766,11 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
     "vpriority [-noupdate|-update] name [value]\n\t\t  prints or sets the display priority for an object",
     __FILE__,
     VPriority, group);
+
+  theCommands.Add ("vnormals",
+                   "vnormals usage:\n"
+                   "vnormals Shape [{on|off}=on] [-length {10}] [-nbAlongU {1}] [-nbAlongV {1}] [-nbAlong {1}]"
+                   "\n\t\t:        [-useMesh] [-oriented {0}1}=0]"
+                   "\n\t\t:  Displays/Hides normals calculated on shape geometry or retrieved from triangulation",
+                   __FILE__, VNormals, group);
 }