0023432: Connected Interactive Objects computed without Interactive Context
authorkgv <kgv@opencascade.com>
Thu, 15 Nov 2012 09:27:18 +0000 (13:27 +0400)
committerkgv <kgv@opencascade.com>
Thu, 15 Nov 2012 09:27:18 +0000 (13:27 +0400)
Setup interactive context for reference(s) in Compute() method of classes AIS_ConnectedInteractive and AIS_MultipleConnectedInteractive
Extend vconnectsh and vconnect to process several input objects, added displaying color for result object
Fixed errors in QAGetPixelColor DRAW command
Edit QAGetPixelColor command and test case
ViewerTest::GetColorFromName() - fixed iteration bounds
QAAISGetPixelColor() - removed redundant conversions
Turn back QAGetPixelColor output syntax in case of 3 arguments
Integration of test script to new test system

src/AIS/AIS_ConnectedInteractive.cxx
src/AIS/AIS_MultipleConnectedInteractive.cdl
src/AIS/AIS_MultipleConnectedInteractive.cxx
src/AIS/AIS_MultipleConnectedShape.cxx
src/QADraw/QADraw.cxx
src/ViewerTest/ViewerTest.cdl
src/ViewerTest/ViewerTest.cxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx

index c38c8d2..72a3a31 100755 (executable)
@@ -105,30 +105,39 @@ void AIS_ConnectedInteractive::Disconnect()
 }
 //=======================================================================
 //function : Compute
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-void AIS_ConnectedInteractive::
-Compute(const Handle(PrsMgr_PresentationManager3d)& aPresentationManager,
-       const Handle(Prs3d_Presentation)& aPresentation, 
-       const Standard_Integer aMode)
+void AIS_ConnectedInteractive::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+                                        const Handle(Prs3d_Presentation)&           thePrs,
+                                        const Standard_Integer                      theMode)
 {
-  static Handle(Geom_Transformation) myPrsTrans ;
+  if (!(HasLocation() || HasConnection()))
+  {
+    return;
+  }
 
-  if(!(HasLocation() ||HasConnection())) return;
-  
-  if(HasConnection()){
-    aPresentation->Clear(Standard_False);
-    aPresentation->RemoveAll();
-    aPresentationManager->Connect( this,myReference, aMode, aMode);
-    if(aPresentationManager->Presentation(myReference,aMode)->MustBeUpdated())
-      aPresentationManager->Update(myReference,aMode);
-    
+  if (HasConnection())
+  {
+    thePrs->Clear (Standard_False);
+    thePrs->RemoveAll();
+
+    if (!myReference->HasInteractiveContext())
+    {
+      myReference->SetContext (GetContext());
+    }
+    thePrsMgr->Connect (this, myReference, theMode, theMode);
+    if (thePrsMgr->Presentation (myReference, theMode)->MustBeUpdated())
+    {
+      thePrsMgr->Update (myReference, theMode);
+    }
+  }
+
+  if (HasLocation())
+  {
+    Handle(Geom_Transformation) aPrsTrans = new Geom_Transformation (myLocation.Transformation());
+    thePrsMgr->Transform (this, aPrsTrans, theMode);
   }
-  if(HasLocation()){
-    myPrsTrans = new Geom_Transformation(myLocation.Transformation());
-    aPresentationManager->Transform(this, myPrsTrans, aMode);  }
-  aPresentation->ReCompute();
+  thePrs->ReCompute();
 }
 
 void AIS_ConnectedInteractive::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
index 01c1ea6..19081b8 100755 (executable)
@@ -95,7 +95,7 @@ is
     --          compute anything, but just uses the 
     --          presentation of this last object, with
     --          a transformation if there's one stored. 
-    is redefined virtual private;
+    is redefined virtual protected; 
 
     Compute(me:mutable;
            aPresentationManager: PresentationManager2d from PrsMgr;
index 8847316..03efed5 100755 (executable)
@@ -130,32 +130,35 @@ void AIS_MultipleConnectedInteractive::DisconnectAll ()
 
 //=======================================================================
 //function : Compute
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-void AIS_MultipleConnectedInteractive::Compute
-(const Handle(PrsMgr_PresentationManager3d)& aPresentationManager, 
- const Handle(Prs3d_Presentation)& aPresentation, 
- const Standard_Integer aMode)
-
+void AIS_MultipleConnectedInteractive::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+                                                const Handle(Prs3d_Presentation)&           thePrs,
+                                                const Standard_Integer                      theMode)
 {
-  //cout<<"AIS_MultipleConnectedInteractive::Compute"<<endl;
-
-  aPresentation->Clear(Standard_False);
-  aPresentation->RemoveAll();
-  if(HasConnection()) {
-    for (Standard_Integer I=1 ; I<= myReferences.Length(); I++) {
-      const Handle (AIS_InteractiveObject)& aReference = myReferences.Value (I);
-      aPresentationManager->Connect( this, aReference, aMode, aMode);
-      if(aPresentationManager->Presentation(aReference,aMode)->MustBeUpdated())
-       aPresentationManager->Update(aReference,aMode);
+  thePrs->Clear (Standard_False);
+  thePrs->RemoveAll();
+  if (HasConnection())
+  {
+    for (Standard_Integer aRefIter = 1; aRefIter <= myReferences.Length(); ++aRefIter)
+    {
+      const Handle (AIS_InteractiveObject)& aRef = myReferences.Value (aRefIter);
+      if (!aRef->HasInteractiveContext())
+      {
+        aRef->SetContext (GetContext());
+      }
+
+      thePrsMgr->Connect (this, aRef, theMode, theMode);
+      if (thePrsMgr->Presentation (aRef, theMode)->MustBeUpdated())
+      {
+        thePrsMgr->Update (aRef, theMode);
+      }
     }
   }
 
-  aPresentation->ReCompute();
-
+  thePrs->ReCompute();
 }
-   
+
 //=======================================================================
 //function : Compute
 //purpose  : 
index c961760..b0a24b7 100755 (executable)
@@ -164,12 +164,11 @@ void AIS_MultipleConnectedShape::Compute(const Handle(Prs3d_Projector)& aProject
 //purpose  : 
 //=======================================================================
 
-void AIS_MultipleConnectedShape::Compute(const Handle_PrsMgr_PresentationManager3d& /*aPresentationManager3d*/,
-                                         const Handle_Prs3d_Presentation& /*aPresentation*/,
-                                         const int /*anint*/)
+void AIS_MultipleConnectedShape::Compute(const Handle_PrsMgr_PresentationManager3d& aPresentationManager3d,
+                                         const Handle_Prs3d_Presentation& aPresentation,
+                                         const int anint)
 {
- Standard_NotImplemented::Raise("AIS_MultipleConnectedShape::Compute(const Handle_PrsMgr_PresentationManager3d&, const Handle_Prs3d_Presentation&, const int)");
-// AIS_MultipleConnectedInteractive::Compute( aPresentationManager3d , aPresentation , anint ) ; Not accessible
+  AIS_MultipleConnectedInteractive::Compute( aPresentationManager3d , aPresentation , anint ) ;
 }
 
 //=======================================================================
index a9279bc..dd2f4c5 100755 (executable)
@@ -464,79 +464,80 @@ Handle(TColStd_HSequenceOfReal) GetColorOfPixel (const Image_PixMap&    theImage
   return aSeq;
 }
 
-static Standard_Integer QAAISGetPixelColor (Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
+static Standard_Integer QAAISGetPixelColor (Draw_Interpretor& theDi,
+                                            Standard_Integer  theArgsNb,
+                                            const char**      theArgs)
 {
-  if ( argc != 3 ) {
-    if ( argc != 6 ) {
-      di << "Usage : " << argv[0] << " coordinate_X coordinate_Y [color_R color_G color_B]" << "\n";
-      return 1;
-    }
-  }
-  Handle (V3d_View) QAAISView = ViewerTest::CurrentView ();
-  if ( QAAISView.IsNull () ) {
-    di << "You must initialize AISViewer before this command." << "\n";
-    return 1;
+  if (theArgsNb != 3 && theArgsNb != 6)
+  {
+    theDi << "Usage : " << theArgs[0] << " coordinate_X coordinate_Y [color_R color_G color_B]" << "\n";
+    return 1; // TCL_ERROR
   }
-  Handle (Aspect_Window) QAAISWindow = QAAISView->Window ();
-  Standard_Integer QAAISXWindowSize_X = 0;
-  Standard_Integer QAAISXWindowSize_Y = 0;
-  QAAISWindow->Size(QAAISXWindowSize_X, QAAISXWindowSize_Y);
-  Standard_Integer QAAISCoordinateX = atoi (argv [1]);
-  Standard_Integer QAAISCoordinateY = atoi (argv [2]);
 
-  Standard_Real QAAISColorRED_V = 0;
-  Standard_Real QAAISColorGRN_V = 0;
-  Standard_Real QAAISColorBLU_V = 0;
+  Handle(V3d_View) aView3d = ViewerTest::CurrentView();
+  if (aView3d.IsNull())
+  {
+    theDi << "You must initialize AISViewer before this command.\n";
+    return 1; // TCL_ERROR
+  }
 
-  if ( argc == 6 ) {
-    QAAISColorRED_V = atof (argv [3]);
-    QAAISColorGRN_V = atof (argv [4]);
-    QAAISColorBLU_V = atof (argv [5]);
+  const Handle(Aspect_Window) anAISWindow = aView3d->Window();
+  Standard_Integer aWindowSizeX = 0;
+  Standard_Integer aWindowSizeY = 0;
+  anAISWindow->Size (aWindowSizeX, aWindowSizeY);
 
-    di << "Begin aColorRED_User = " << QAAISColorRED_V << "\n";
-    di << "Begin aColorGRN_User = " << QAAISColorRED_V << "\n";
-    di << "Begin aColorBLU_User = " << QAAISColorRED_V << "\n";
-  }
+  Standard_Integer anArgIter = 1;
+  const Standard_Integer aPickCoordX = atoi (theArgs[anArgIter++]);
+  const Standard_Integer aPickCoordY = atoi (theArgs[anArgIter++]);
+  const Standard_Integer aRadius = (theArgsNb == 3) ? 0 : 1;
 
-  Standard_Integer aRadius = 1;
-  if ( argc == 3 ) {
-    aRadius=0;
+  Image_ColorRGBF aColorInput = {{ 0.0f, 0.0f, 0.0f }};
+  if (theArgsNb == 6)
+  {
+    aColorInput.r() = (Standard_ShortReal )atof (theArgs[anArgIter++]);
+    aColorInput.g() = (Standard_ShortReal )atof (theArgs[anArgIter++]);
+    aColorInput.b() = (Standard_ShortReal )atof (theArgs[anArgIter++]);
   }
 
   Image_PixMap anImage;
-  QAAISView->ToPixMap (anImage, QAAISXWindowSize_X, QAAISXWindowSize_Y);
-  Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (anImage, QAAISCoordinateX, QAAISCoordinateY, aRadius);
+  aView3d->ToPixMap (anImage, aWindowSizeX, aWindowSizeY);
+  const Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (anImage, aPickCoordX, aPickCoordY, aRadius);
   cout << "Length = " << aSeq->Length() << endl;
 
-  Standard_Boolean IsNotEqual = Standard_True;
-  Standard_Integer i;
-  for(i=1; i<=aSeq->Length();i+=3) {
-    // mkv 29.04.03
-    Standard_Real QAAISColorRED_R = (Floor(aSeq->Value(i+0) * 1000000.)) / 1000000.;
-    Standard_Real QAAISColorGRN_R = (Floor(aSeq->Value(i+1) * 1000000.)) / 1000000.;
-    Standard_Real QAAISColorBLU_R = (Floor(aSeq->Value(i+2) * 1000000.)) / 1000000.;
-    // mkv 29.04.03
-
-    if ( argc == 3 ) {
-      di << "RED : "    << QAAISColorRED_R
-       << " GREEN : " << QAAISColorGRN_R
-         << " BLUE : "  << QAAISColorBLU_R
-           << "\n";
-      IsNotEqual = Standard_False;
+  Image_ColorRGBF aColorPicked = {{ 0.0f, 0.0f, 0.0f }};
+  Standard_Boolean isNotEqual = Standard_True;
+  for (Standard_Integer i = 1; i <= aSeq->Length(); i += 3)
+  {
+    aColorPicked.r() = (Standard_ShortReal )aSeq->Value (i + 0);
+    aColorPicked.g() = (Standard_ShortReal )aSeq->Value (i + 1);
+    aColorPicked.b() = (Standard_ShortReal )aSeq->Value (i + 2);
+
+    if (theArgsNb == 3 ||
+        ((Abs (aColorPicked.r() - aColorInput.r()) <= Precision::Confusion())
+      && (Abs (aColorPicked.g() - aColorInput.g()) <= Precision::Confusion())
+      && (Abs (aColorPicked.b() - aColorInput.b()) <= Precision::Confusion())))
+    {
+      isNotEqual = Standard_False;
       break;
     }
+  }
 
-    if (   QAAISColorRED_R == QAAISColorRED_V
-       && QAAISColorGRN_R == QAAISColorGRN_V
-       && QAAISColorBLU_R == QAAISColorBLU_V
-       ) {
-      IsNotEqual = Standard_False;
-      break;
-    }
+  theDi << "RED :   " << aColorPicked.r() << " "
+        << "GREEN : " << aColorPicked.g() << " "
+        << "BLUE :  " << aColorPicked.b() << "\n";
+
+  if (theArgsNb == 6)
+  {
+    theDi << "User color: \n"
+          << "RED :   " << aColorInput.r() << " "
+          << "GREEN : " << aColorInput.g() << " "
+          << "BLUE :  " << aColorInput.b() << "\n";
   }
-  if (IsNotEqual) {
-    di << "Faulty : colors are not equal." << "\n";
-    return 1;
+
+  if (isNotEqual)
+  {
+    theDi << "Faulty : colors are not equal.\n";
+    return 1; // TCL_ERROR
   }
   return 0;
 }
index 27dcf35..8ee7d9f 100755 (executable)
@@ -35,7 +35,8 @@ uses
     V3d,
     AIS,
     NIS,
-    MMgt
+    MMgt,
+    Quantity
 
 is
 
@@ -171,6 +172,9 @@ is
 
     StandardModeActivation(Mode  : Integer from Standard);
 
+    GetColorFromName(name: CString from Standard)
+    returns NameOfColor from Quantity;
+
 
 
 end;
index d017497..d062cb5 100755 (executable)
 #include <NIS_Triangulated.hxx>
 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
 
-//=======================================================================
-//function : GetColorFromName
-//purpose  : get the Quantity_NameOfColor from a string
-//=======================================================================
-
-#include <Quantity_NameOfColor.hxx>
 #include <Quantity_Color.hxx>
 #include <Quantity_NameOfColor.hxx>
 
@@ -96,22 +90,23 @@ extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
 #define DEFAULT_COLOR    Quantity_NOC_GOLDENROD
 #define DEFAULT_MATERIAL Graphic3d_NOM_BRASS
 
-static Quantity_NameOfColor GetColorFromName( const char *name )
-{
-  Quantity_NameOfColor ret = DEFAULT_COLOR;
+//=======================================================================
+//function : GetColorFromName
+//purpose  : get the Quantity_NameOfColor from a string
+//=======================================================================
 
-  Standard_Boolean Found = Standard_False;
-  Standard_CString colstring;
-  for(Standard_Integer i=0;i<=514 && !Found;i++)
+Quantity_NameOfColor ViewerTest::GetColorFromName (const Standard_CString theName)
+{
+  for (Standard_Integer anIter = Quantity_NOC_BLACK; anIter <= Quantity_NOC_WHITE; ++anIter)
+  {
+    Standard_CString aColorName = Quantity_Color::StringName (Quantity_NameOfColor (anIter));
+    if (strcasecmp (theName, aColorName) == 0)
     {
-      colstring = Quantity_Color::StringName(Quantity_NameOfColor(i));
-      if (!strcasecmp(name,colstring)) {
-       ret = (Quantity_NameOfColor)i;
-       Found = Standard_True;
-      }
+      return Quantity_NameOfColor (anIter);
     }
+  }
 
-  return ret;
+  return DEFAULT_COLOR;
 }
 
 //=======================================================================
@@ -1107,20 +1102,20 @@ static int VColor2 (Draw_Interpretor& di, Standard_Integer argc, const char** ar
           Handle(AIS_InteractiveObject)::DownCast (anObj);
 #ifdef DEB
           if (HaveToSet)
-            di  << "HaveToSet "<< "1" <<" Color Given "<< argv[2] << " Color returned "<< GetColorFromName(argv[2]) << "\n";
+            di  << "HaveToSet "<< "1" <<" Color Given "<< argv[2] << " Color returned "<< ViewerTest::GetColorFromName(argv[2]) << "\n";
           else
             di  << "HaveToSet 0\n";
 #endif
 
         if(HaveToSet)
-          TheAISContext()->SetColor(ashape,GetColorFromName(argv[2]) );
+          TheAISContext()->SetColor(ashape,ViewerTest::GetColorFromName(argv[2]) );
         else
           TheAISContext()->UnsetColor(ashape);
       } else if (anObj->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
         Handle(NIS_Triangulated) ashape =
           Handle(NIS_Triangulated)::DownCast (anObj);
         if (!ashape.IsNull())
-          ashape->SetColor (GetColorFromName(argv[2]));
+          ashape->SetColor (ViewerTest::GetColorFromName(argv[2]));
       }
     }
 
@@ -1139,12 +1134,12 @@ static int VColor2 (Draw_Interpretor& di, Standard_Integer argc, const char** ar
           continue;
 #ifdef DEB
         if (HaveToSet)
-          di  << "HaveToSet "<< "1" <<" Color Given "<< argv[2] << " Color returned "<< GetColorFromName(argv[2]) << "\n";
+          di  << "HaveToSet "<< "1" <<" Color Given "<< argv[2] << " Color returned "<< ViewerTest::GetColorFromName(argv[2]) << "\n";
         else
           di  << "HaveToSet 0\n";
 #endif
         if(HaveToSet)
-          TheAISContext()->SetColor(ashape,GetColorFromName(argv[1]),Standard_False);
+          TheAISContext()->SetColor(ashape,ViewerTest::GetColorFromName(argv[1]),Standard_False);
         else
           TheAISContext()->UnsetColor(ashape,Standard_False);
       }
@@ -1163,7 +1158,7 @@ static int VColor2 (Draw_Interpretor& di, Standard_Integer argc, const char** ar
           Handle(AIS_InteractiveObject)::DownCast(it.Key1());
         if (!ashape.IsNull())
           if(HaveToSet)
-            TheAISContext()->SetColor(ashape,GetColorFromName(argv[1]),Standard_False);
+            TheAISContext()->SetColor(ashape,ViewerTest::GetColorFromName(argv[1]),Standard_False);
           else
             TheAISContext()->UnsetColor(ashape,Standard_False);
         it.Next();
index a6fc1dc..ceea781 100755 (executable)
 #include <TopoDS_Wire.hxx>
 
 #include <AIS_ConnectedShape.hxx>
+#include <AIS_MultipleConnectedInteractive.hxx>
+#include <AIS_MultipleConnectedShape.hxx>
 #include <TopLoc_Location.hxx>
 #include <TColStd_ListOfInteger.hxx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
@@ -3504,50 +3506,138 @@ static Standard_Integer VSetLocation (Draw_Interpretor& di,
 //===============================================================================================
 //function : VConnect
 //purpose  : Creates and displays AIS_ConnectedInteractive object from input object and location 
-//Draw arg : vconnect name object Xo Yo Zo Xu Xv Xw Zu Zv Zw
+//Draw arg : vconnect name Xo Yo Zo Xu Xv Xw Zu Zv Zw object1 object2 ... [color=NAME]
 //===============================================================================================
 
 static Standard_Integer VConnect(Draw_Interpretor& di, 
                                  Standard_Integer argc, 
                                  const char ** argv) 
 {
-  // Check argumnets 
-  if(argc != 12)
+  // Check the viewer
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if (aContext.IsNull())
   {
-    std::cout << "vconnect error: expect 11 argumnets\n"; 
+    std::cout << "vconnect error : call vinit before\n";
     return 1; // TCL_ERROR
   }
-  // Get values 
-  TCollection_AsciiString aName(argv[1]); 
-  TCollection_AsciiString anOriginObjectName(argv[2]); 
-  if(aName.IsEqual(anOriginObjectName))
+  // Check argumnets 
+  if (argc < 12)
   {
-    std::cout << "vconnect error: equal names for connected objects\n"; 
+    std::cout << "vconnect error: expect at least 11 arguments\n";
     return 1; // TCL_ERROR
   }
-  // Check if the origin shape is not null
+
+  // Get values
+  Standard_Integer anArgIter = 1;
+  TCollection_AsciiString aName (argv[anArgIter++]);
   Handle(AIS_InteractiveObject) anOriginObject;
-  if(GetMapOfAIS().IsBound2(anOriginObjectName))
+  TCollection_AsciiString aColorString (argv[argc-1]);
+  Standard_CString aColorName;
+  Standard_Boolean hasColor = Standard_False;
+  if (aColorString.Search ("color=") != -1)
   {
-    Handle(Standard_Transient) anObj = GetMapOfAIS().Find2(anOriginObjectName);
-    anOriginObject = Handle(AIS_InteractiveObject)::DownCast(anObj);
-    if(anOriginObject.IsNull())
+    hasColor = Standard_True;
+    aColorString.Remove (1, 6);
+    aColorName = aColorString.ToCString();
+  }
+  Handle(AIS_InteractiveObject) anObject;
+
+  // AIS_ConnectedInteractive
+  if (argc == 12 || (argc == 13 && hasColor))
+  {
+    TCollection_AsciiString anOriginObjectName(argv[11]);
+    if (aName.IsEqual (anOriginObjectName))
     {
-      std::cout << "Object " << anOriginObjectName << " is used for non AIS viewer\n!";
+      std::cout << "vconnect error: equal names for connected objects\n"; 
       return 1; // TCL_ERROR
     }
+    if (GetMapOfAIS().IsBound2 (anOriginObjectName))
+    {
+      Handle(Standard_Transient) anObj = GetMapOfAIS().Find2 (anOriginObjectName);
+      anOriginObject = Handle(AIS_InteractiveObject)::DownCast(anObj);
+      if (anOriginObject.IsNull())
+      {
+        std::cout << "Object " << anOriginObjectName << " is used for non AIS viewer\n";
+        return 1; // TCL_ERROR
+      }
+    }
+    else
+    {
+      Standard_CString aName = anOriginObjectName.ToCString();
+      TopoDS_Shape aTDShape = DBRep::Get (aName);
+      if (aTDShape.IsNull())
+      {
+        std::cout << "vconnect error: object " << anOriginObjectName << " doesn't exist\n";
+        return 1; // TCL_ERROR
+      }
+      anOriginObject = new AIS_Shape (aTDShape);
+      if (hasColor)
+      {
+        anOriginObject->SetColor (ViewerTest::GetColorFromName (aColorName));
+      }
+    }
   }
-  
+  // AIS_MultipleConnectedInteractive
+  else
+  {
+    const Standard_Integer aNbShapes = hasColor ? (argc - 1) : argc;
+    for (Standard_Integer i = 11; i < aNbShapes; ++i)
+    {
+      TCollection_AsciiString anOriginObjectName (argv[i]);
+      if (aName.IsEqual (anOriginObjectName))
+      {
+        std::cout << "vconnect error: equal names for connected objects\n";
+        continue;
+      }
+      if (GetMapOfAIS().IsBound2 (anOriginObjectName))
+      {
+        Handle(Standard_Transient) anObj = GetMapOfAIS().Find2 (anOriginObjectName);
+        anObject = Handle(AIS_InteractiveObject)::DownCast(anObj);
+        if (anObject.IsNull())
+        {
+          std::cout << "Object " << anOriginObjectName << " is used for non AIS viewer\n";
+          continue;
+        }
+      }
+      else
+      {
+        Standard_CString aName = anOriginObjectName.ToCString();
+        TopoDS_Shape aTDShape = DBRep::Get (aName);
+        if (aTDShape.IsNull())
+        {
+          std::cout << "vconnect error: object " << anOriginObjectName << " doesn't exist\n";
+          continue;
+        }
+        anObject = new AIS_Shape (aTDShape);
+        anObject->SetColor (ViewerTest::GetColorFromName (aColorName));
+      }
+      if (anOriginObject.IsNull())
+      {
+        anOriginObject = new AIS_MultipleConnectedInteractive();
+        Handle(AIS_MultipleConnectedInteractive)::DownCast(anOriginObject)->Connect (anObject);
+      }
+      else
+      {
+        Handle(AIS_MultipleConnectedInteractive)::DownCast(anOriginObject)->Connect (anObject);
+      }
+    }
+    if (anOriginObject.IsNull())
+    {
+      std::cout << "vconect error : can't connect input objects\n";
+      return 1; // TCL_ERROR
+    }
+  }
+
   // Get location data
-  Standard_Real aXo = atof(argv[3]);
-  Standard_Real aYo = atof(argv[4]);
-  Standard_Real aZo = atof(argv[5]);
-  Standard_Real aXu = atof(argv[6]);
-  Standard_Real aXv = atof(argv[7]);
-  Standard_Real aXw = atof(argv[8]);
-  Standard_Real aZu = atof(argv[9]);
-  Standard_Real aZv = atof(argv[10]);
-  Standard_Real aZw = atof(argv[11]);
+  Standard_Real aXo = atof (argv[anArgIter++]);
+  Standard_Real aYo = atof (argv[anArgIter++]);
+  Standard_Real aZo = atof (argv[anArgIter++]);
+  Standard_Real aXu = atof (argv[anArgIter++]);
+  Standard_Real aXv = atof (argv[anArgIter++]);
+  Standard_Real aXw = atof (argv[anArgIter++]);
+  Standard_Real aZu = atof (argv[anArgIter++]);
+  Standard_Real aZv = atof (argv[anArgIter++]);
+  Standard_Real aZw = atof (argv[anArgIter++]);
 
   // Create transformation
   gp_Pnt aPoint(aXo, aYo, aZo);
@@ -3563,8 +3653,16 @@ static Standard_Integer VConnect(Draw_Interpretor& di,
   TopLoc_Location aLocation(aTrsf);
 
   // Create connected object
-  Handle(AIS_ConnectedInteractive) aConnectedObject = new AIS_ConnectedInteractive();
-  aConnectedObject->Connect(anOriginObject, aLocation);
+  Handle(AIS_ConnectedInteractive) aConnected = new AIS_ConnectedInteractive();
+  Handle(AIS_MultipleConnectedInteractive) anOrigin = Handle(AIS_MultipleConnectedInteractive)::DownCast(anOriginObject);
+  if (anOrigin.IsNull())
+  {
+    aConnected->Connect (anOriginObject, aLocation);
+  }
+  else
+  {
+    aConnected->Connect (anOrigin, aLocation);
+  }
 
   // Check if there is another object with given name
   // and remove it from context
@@ -3576,11 +3674,11 @@ static Standard_Integer VConnect(Draw_Interpretor& di,
     GetMapOfAIS().UnBind2(aName);
   }
 
-  // Bind connected object to its name 
-  GetMapOfAIS().Bind(aConnectedObject, aName); 
+  // Bind connected object to its name
+  GetMapOfAIS().Bind (aConnected, aName);
 
   // Display connected object
-  TheAISContext()->Display(aConnectedObject);
+  TheAISContext()->Display (aConnected);
 
   return 0;
 }
@@ -3588,50 +3686,141 @@ static Standard_Integer VConnect(Draw_Interpretor& di,
 //===============================================================================================
 //function : VConnectShape
 //purpose  : Creates and displays AIS_ConnectedShape from input shape and location 
-//Draw arg : vconnectsh name shape Xo Yo Zo Xu Xv Xw Zu Zv Zw
+//Draw arg : vconnectsh name Xo Yo Zo Xu Xv Xw Zu Zv Zw shape1 shape2 ... [color=NAME]
 //===============================================================================================
 
 static Standard_Integer VConnectShape(Draw_Interpretor& di, 
                                       Standard_Integer argc, 
                                       const char ** argv) 
 {
-  // Check argumnets 
-  if(argc != 12)
+  // Check the viewer
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if (aContext.IsNull())
   {
-    std::cout << "vconnectsh error: expect 11 argumnets\n"; 
+    std::cout << "vconnectsh error : call vinit before\n";
     return 1; // TCL_ERROR
   }
-  // Get values 
-  TCollection_AsciiString aName(argv[1]); 
-  TCollection_AsciiString anOriginShapeName(argv[2]); 
-  if(aName.IsEqual(anOriginShapeName))
+  // Check argumnets
+  if (argc < 12)
   {
-    std::cout << "vconnectsh error: equal names for connected shapes\n"; 
+    std::cout << "vconnectsh error: expect at least 11 arguments\n";
     return 1; // TCL_ERROR
   }
-  // Check if the origin shape is not null
+
+  // Get values
+  Standard_Integer anArgIter = 1;
+  TCollection_AsciiString aName (argv[anArgIter++]);
   Handle(AIS_InteractiveObject) anOriginShape;
-  if(GetMapOfAIS().IsBound2(anOriginShapeName))
+  TCollection_AsciiString aColorString(argv[argc-1]);
+  Standard_CString aColorName;
+  Standard_Boolean hasColor = Standard_False;
+  if (aColorString.Search ("color=") != -1)
+  {
+    hasColor = Standard_True;
+    aColorString.Remove (1, 6);
+    aColorName = aColorString.ToCString();
+  }
+  Handle(AIS_Shape) aShape;
+
+  // AIS_ConnectedShape
+  if (argc == 12 || (argc == 13 && hasColor))
   {
-    Handle(Standard_Transient) anObj = GetMapOfAIS().Find2(anOriginShapeName);
-    anOriginShape = Handle(AIS_InteractiveObject)::DownCast(anObj);
-    if(anOriginShape.IsNull())
+    TCollection_AsciiString anOriginShapeName (argv[11]);
+    if (aName.IsEqual (anOriginShapeName))
     {
-      std::cout << "Shape " << anOriginShapeName << " is used for non AIS viewer\n!";
+      std::cout << "vconnectsh error: equal names for connected shapes\n";
+      return 1; // TCL_ERROR
+    }
+    if (GetMapOfAIS().IsBound2 (anOriginShapeName))
+    {
+      Handle(Standard_Transient) anObj = GetMapOfAIS().Find2 (anOriginShapeName);
+      anOriginShape = Handle(AIS_Shape)::DownCast(anObj);
+      if (anOriginShape.IsNull())
+      {
+        std::cout << "Shape " << anOriginShapeName << " is used for non AIS viewer\n!";
+        return 1; // TCL_ERROR
+      }
+    }
+    else
+    {
+      Standard_CString aName = anOriginShapeName.ToCString();
+      TopoDS_Shape aTDShape = DBRep::Get (aName);
+      if (aTDShape.IsNull())
+      {
+        std::cout << "vconnectsh error: object " << anOriginShapeName << " doesn't exist\n";
+        return 1; // TCL_ERROR
+      }
+      anOriginShape = new AIS_Shape (aTDShape);
+      if (hasColor)
+      {
+        anOriginShape->SetColor (ViewerTest::GetColorFromName (aColorName));
+      }
+    }
+  }
+  // AIS_MultipleConnectedShape
+  else
+  {
+    const Standard_Integer aNbShapes = hasColor ? (argc - 1) : argc;
+    for (Standard_Integer i = 11; i < aNbShapes; ++i)
+    {
+      TCollection_AsciiString anOriginShapeName (argv[i]);
+      if (aName.IsEqual (anOriginShapeName))
+      {
+        std::cout << "vconnectsh error: equal names for connected shapes\n";
+        continue;
+      }
+      if (GetMapOfAIS().IsBound2 (anOriginShapeName))
+      {
+        Handle(Standard_Transient) anObj = GetMapOfAIS().Find2 (anOriginShapeName);
+        aShape = Handle(AIS_Shape)::DownCast(anObj);
+        if (aShape.IsNull())
+        {
+          std::cout << "Shape " << anOriginShapeName << " is used for non AIS viewer\n";
+          continue;
+        }
+      }
+      else
+      {
+        Standard_CString aName = anOriginShapeName.ToCString();
+        TopoDS_Shape aTDShape = DBRep::Get (aName);
+        if (aTDShape.IsNull())
+        {
+          std::cout << "vconnectsh error: object " << anOriginShapeName << " doesn't exist\n";
+          continue;
+        }
+        aShape = new AIS_Shape (aTDShape);
+        if (hasColor)
+        {
+          aShape->SetColor (ViewerTest::GetColorFromName (aColorName));
+        }
+      }
+      if (anOriginShape.IsNull())
+      {
+        anOriginShape = new AIS_MultipleConnectedShape (aShape->Shape());
+        Handle(AIS_MultipleConnectedShape)::DownCast(anOriginShape)->Connect (aShape);
+      }
+      else
+      {
+        Handle(AIS_MultipleConnectedShape)::DownCast(anOriginShape)->Connect (aShape);
+      }
+    }
+    if (anOriginShape.IsNull())
+    {
+      std::cout << "vconectsh error : can't connect input objects\n";
       return 1; // TCL_ERROR
     }
   }
 
   // Get location data  
-  Standard_Real aXo = atof(argv[3]);
-  Standard_Real aYo = atof(argv[4]);
-  Standard_Real aZo = atof(argv[5]);
-  Standard_Real aXu = atof(argv[6]);
-  Standard_Real aXv = atof(argv[7]);
-  Standard_Real aXw = atof(argv[8]);
-  Standard_Real aZu = atof(argv[9]);
-  Standard_Real aZv = atof(argv[10]);
-  Standard_Real aZw = atof(argv[11]);
+  Standard_Real aXo = atof (argv[anArgIter++]);
+  Standard_Real aYo = atof (argv[anArgIter++]);
+  Standard_Real aZo = atof (argv[anArgIter++]);
+  Standard_Real aXu = atof (argv[anArgIter++]);
+  Standard_Real aXv = atof (argv[anArgIter++]);
+  Standard_Real aXw = atof (argv[anArgIter++]);
+  Standard_Real aZu = atof (argv[anArgIter++]);
+  Standard_Real aZv = atof (argv[anArgIter++]);
+  Standard_Real aZw = atof (argv[anArgIter++]);
 
   // Create transformation
   gp_Pnt aPoint(aXo, aYo, aZo);
@@ -3647,9 +3836,18 @@ static Standard_Integer VConnectShape(Draw_Interpretor& di,
   TopLoc_Location aLocation(aTrsf);
 
   // Create connected shape
-  Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anOriginShape);
-  Handle(AIS_ConnectedShape) aConnectedShape = new AIS_ConnectedShape(aShape);
-  aConnectedShape->Connect(anOriginShape, aLocation);
+  Handle(AIS_ConnectedInteractive) aConnected;
+  Handle(AIS_Shape) anOrigin = Handle(AIS_Shape)::DownCast(anOriginShape);
+  if (!anOrigin.IsNull())
+  {
+    aConnected = new AIS_ConnectedShape (anOrigin);
+    aConnected->Connect (anOrigin, aLocation);
+  }
+  else
+  {
+    aConnected = new AIS_ConnectedInteractive();
+    aConnected->Connect (anOriginShape, aLocation);
+  }
 
   // Check if there is another object with given name
   // and remove it from context
@@ -3661,11 +3859,11 @@ static Standard_Integer VConnectShape(Draw_Interpretor& di,
     GetMapOfAIS().UnBind2(aName);
   }
 
-  // Bind connected shape to its name 
-  GetMapOfAIS().Bind(aConnectedShape, aName); 
+  // Bind connected shape to its name
+  GetMapOfAIS().Bind (aConnected, aName);
 
   // Display connected shape
-  TheAISContext()->Display(aConnectedShape);
+  TheAISContext()->Display (aConnected);
 
   return 0;
 }
@@ -4487,11 +4685,11 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
     __FILE__,VDrawPArray,group);
 
   theCommands.Add("vconnect", 
-    "vconnect : name object Xo Yo Zo Xu Xv Xw Zu Zv Zw", 
+    "vconnect : name Xo Yo Zo Xu Xv Xw Zu Zv Zw object1 object2 ... [color=NAME]", 
     __FILE__, VConnect, group);
 
   theCommands.Add("vconnectsh", 
-    "vconnectsh : name shape Xo Yo Zo Xu Xv Xw Zu Zv Zw", 
+    "vconnectsh : name Xo Yo Zo Xu Xv Xw Zu Zv Zw shape1 shape2 ... [color=NAME]", 
     __FILE__, VConnectShape, group);
 
   theCommands.Add("vselmode",