0026159: Visualization - revise tolerance implementation for selection
[occt.git] / src / ViewerTest / ViewerTest.cxx
1 // Created on: 1997-07-23
2 // Created by: Henri JEANNIN
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified by  Eric Gouthiere [sep-oct 98] -> add commands for display...
18 // Modified by  Robert Coublanc [nov 16-17-18 1998]
19 //             -split ViewerTest.cxx into 3 files : ViewerTest.cxx,
20 //                                                  ViewerTest_ObjectCommands.cxx
21 //                                                  ViewerTest_RelationCommands.cxx
22 //             -add Functions and commands for interactive selection of shapes and objects
23 //              in AIS Viewers. (PickShape(s), PickObject(s),
24
25 #include <Standard_Stream.hxx>
26
27 #include <ViewerTest.hxx>
28
29 #include <TopLoc_Location.hxx>
30 #include <TopTools_HArray1OfShape.hxx>
31 #include <TColStd_HArray1OfTransient.hxx>
32 #include <TColStd_SequenceOfAsciiString.hxx>
33 #include <TColStd_HSequenceOfAsciiString.hxx>
34 #include <TColStd_MapOfTransient.hxx>
35 #include <OSD_Timer.hxx>
36 #include <Geom_Axis2Placement.hxx>
37 #include <Geom_Axis1Placement.hxx>
38 #include <gp_Trsf.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <BRepAdaptor_Curve.hxx>
41 #include <StdSelect_ShapeTypeFilter.hxx>
42 #include <AIS.hxx>
43 #include <AIS_ColoredShape.hxx>
44 #include <AIS_InteractiveObject.hxx>
45 #include <AIS_Trihedron.hxx>
46 #include <AIS_Axis.hxx>
47 #include <AIS_Relation.hxx>
48 #include <AIS_TypeFilter.hxx>
49 #include <AIS_SignatureFilter.hxx>
50 #include <AIS_LocalContext.hxx>
51 #include <AIS_ListOfInteractive.hxx>
52 #include <AIS_ListIteratorOfListOfInteractive.hxx>
53 #include <Aspect_InteriorStyle.hxx>
54 #include <Aspect_Window.hxx>
55 #include <Graphic3d_AspectFillArea3d.hxx>
56 #include <Graphic3d_AspectLine3d.hxx>
57 #include <Graphic3d_CStructure.hxx>
58 #include <Graphic3d_TextureRoot.hxx>
59 #include <Image_AlienPixMap.hxx>
60 #include <Prs3d_Drawer.hxx>
61 #include <Prs3d_ShadingAspect.hxx>
62 #include <Prs3d_IsoAspect.hxx>
63 #include <Prs3d_PointAspect.hxx>
64 #include <Select3D_SensitiveWire.hxx>
65 #include <SelectMgr_EntityOwner.hxx>
66 #include <StdSelect_BRepOwner.hxx>
67 #include <StdSelect_ViewerSelector3d.hxx>
68 #include <TopTools_MapOfShape.hxx>
69 #include <ViewerTest_AutoUpdater.hxx>
70
71 #include <stdio.h>
72
73 #include <Draw_Interpretor.hxx>
74 #include <TCollection_AsciiString.hxx>
75 #include <Draw_PluginMacro.hxx>
76
77 // avoid warnings on 'extern "C"' functions returning C++ classes
78 #ifdef WNT
79 #define _CRT_SECURE_NO_DEPRECATE
80 #pragma warning(4:4190)
81 #pragma warning (disable:4996)
82 #endif
83
84 #include <NIS_InteractiveContext.hxx>
85 #include <NIS_Triangulated.hxx>
86 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
87
88 #include <Quantity_Color.hxx>
89 #include <Quantity_NameOfColor.hxx>
90
91 #include <Graphic3d_NameOfMaterial.hxx>
92
93 #define DEFAULT_COLOR              Quantity_NOC_GOLDENROD
94 #define DEFAULT_FREEBOUNDARY_COLOR Quantity_NOC_GREEN
95 #define DEFAULT_MATERIAL           Graphic3d_NOM_BRASS
96
97 //=======================================================================
98 //function : GetColorFromName
99 //purpose  : get the Quantity_NameOfColor from a string
100 //=======================================================================
101
102 Quantity_NameOfColor ViewerTest::GetColorFromName (const Standard_CString theName)
103 {
104   Quantity_NameOfColor aColor = DEFAULT_COLOR;
105   Quantity_Color::ColorFromName (theName, aColor);
106   return aColor;
107 }
108
109 //=======================================================================
110 //function : ParseColor
111 //purpose  :
112 //=======================================================================
113
114 Standard_Integer ViewerTest::ParseColor (Standard_Integer  theArgNb,
115                                          const char**      theArgVec,
116                                          Quantity_Color&   theColor)
117 {
118   Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
119   if (theArgNb >= 1
120    && Quantity_Color::ColorFromName (theArgVec[0], aColor))
121   {
122     theColor = aColor;
123     return 1;
124   }
125   else if (theArgNb >= 3)
126   {
127     const TCollection_AsciiString anRgbStr[3] =
128     {
129       theArgVec[0],
130       theArgVec[1],
131       theArgVec[2]
132     };
133     if (!anRgbStr[0].IsRealValue()
134      || !anRgbStr[1].IsRealValue()
135      || !anRgbStr[2].IsRealValue())
136     {
137       return 0;
138     }
139
140     Graphic3d_Vec4d anRgb;
141     anRgb.x() = anRgbStr[0].RealValue();
142     anRgb.y() = anRgbStr[1].RealValue();
143     anRgb.z() = anRgbStr[2].RealValue();
144     if (anRgb.x() < 0.0 || anRgb.x() > 1.0
145      || anRgb.y() < 0.0 || anRgb.y() > 1.0
146      || anRgb.z() < 0.0 || anRgb.z() > 1.0)
147     {
148       std::cout << "Error: RGB color values should be within range 0..1!\n";
149       return 0;
150     }
151
152     theColor.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
153     return 3;
154   }
155
156   return 0;
157 }
158
159 //=======================================================================
160 //function : GetTypeNames
161 //purpose  :
162 //=======================================================================
163 static const char** GetTypeNames()
164 {
165   static const char* names[14] = {"Point","Axis","Trihedron","PlaneTrihedron", "Line","Circle","Plane",
166                           "Shape","ConnectedShape","MultiConn.Shape",
167                           "ConnectedInter.","MultiConn.",
168                           "Constraint","Dimension"};
169   static const char** ThePointer = names;
170   return ThePointer;
171 }
172
173 //=======================================================================
174 //function : GetTypeAndSignfromString
175 //purpose  :
176 //=======================================================================
177 void GetTypeAndSignfromString (const char* name,AIS_KindOfInteractive& TheType,Standard_Integer& TheSign)
178 {
179   const char ** thefullnames = GetTypeNames();
180   Standard_Integer index(-1);
181
182   for(Standard_Integer i=0;i<=13 && index==-1;i++)
183     if(!strcasecmp(name,thefullnames[i]))
184       index = i;
185
186   if(index ==-1){
187     TheType = AIS_KOI_None;
188     TheSign = -1;
189     return;
190   }
191
192   if(index<=6){
193     TheType = AIS_KOI_Datum;
194     TheSign = index+1;
195   }
196   else if (index <=9){
197     TheType = AIS_KOI_Shape;
198     TheSign = index-7;
199   }
200   else if(index<=11){
201     TheType = AIS_KOI_Object;
202     TheSign = index-10;
203   }
204   else{
205     TheType = AIS_KOI_Relation;
206     TheSign = index-12;
207   }
208
209 }
210
211
212
213 #include <string.h>
214 #include <Draw_Interpretor.hxx>
215 #include <Draw.hxx>
216 #include <Draw_Appli.hxx>
217 #include <DBRep.hxx>
218
219
220 #include <TCollection_AsciiString.hxx>
221 #include <V3d_Viewer.hxx>
222 #include <V3d_View.hxx>
223 #include <V3d.hxx>
224
225 #include <AIS_InteractiveContext.hxx>
226 #include <AIS_Shape.hxx>
227 #include <AIS_TexturedShape.hxx>
228 #include <AIS_DisplayMode.hxx>
229 #include <TColStd_MapOfInteger.hxx>
230 #include <AIS_MapOfInteractive.hxx>
231 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
232 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
233 #include <ViewerTest_EventManager.hxx>
234
235 #include <TopoDS_Solid.hxx>
236 #include <BRepTools.hxx>
237 #include <BRep_Builder.hxx>
238 #include <TopAbs_ShapeEnum.hxx>
239
240 #include <TopoDS.hxx>
241 #include <BRep_Tool.hxx>
242
243
244 #include <Draw_Window.hxx>
245 #include <AIS_ListIteratorOfListOfInteractive.hxx>
246 #include <AIS_ListOfInteractive.hxx>
247 #include <AIS_DisplayMode.hxx>
248 #include <TopTools_ListOfShape.hxx>
249 #include <BRepOffsetAPI_MakeThickSolid.hxx>
250 #include <BRepOffset.hxx>
251
252 //==============================================================================
253 //  VIEWER OBJECT MANAGEMENT GLOBAL VARIABLES
254 //==============================================================================
255 Standard_EXPORT ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(){
256   static ViewerTest_DoubleMapOfInteractiveAndName TheMap;
257   return TheMap;
258 }
259
260 //=======================================================================
261 //function : Display
262 //purpose  :
263 //=======================================================================
264 Standard_Boolean ViewerTest::Display (const TCollection_AsciiString&       theName,
265                                       const Handle(AIS_InteractiveObject)& theObject,
266                                       const Standard_Boolean               theToUpdate,
267                                       const Standard_Boolean               theReplaceIfExists)
268 {
269   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
270   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
271   if (aCtx.IsNull())
272   {
273     std::cout << "Error: AIS context is not available.\n";
274     return Standard_False;
275   }
276
277   if (aMap.IsBound2 (theName))
278   {
279     if (!theReplaceIfExists)
280     {
281       std::cout << "Error: other interactive object has been already registered with name: " << theName << ".\n"
282                 << "Please use another name.\n";
283       return Standard_False;
284     }
285
286     Handle(AIS_InteractiveObject) anOldObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (theName));
287     if (!anOldObj.IsNull())
288     {
289       aCtx->Remove (anOldObj, Standard_True);
290     }
291     aMap.UnBind2 (theName);
292   }
293
294   if (theObject.IsNull())
295   {
296     // object with specified name has been already unbound
297     return Standard_True;
298   }
299
300   // unbind AIS object if it was bound with another name
301   aMap.UnBind1 (theObject);
302
303   // can be registered without rebinding
304   aMap.Bind (theObject, theName);
305   aCtx->Display (theObject, theToUpdate);
306   return Standard_True;
307 }
308
309 //! Alias for ViewerTest::Display(), compatibility with old code.
310 Standard_EXPORT Standard_Boolean VDisplayAISObject (const TCollection_AsciiString&       theName,
311                                                     const Handle(AIS_InteractiveObject)& theObject,
312                                                     Standard_Boolean theReplaceIfExists = Standard_True)
313 {
314   return ViewerTest::Display (theName, theObject, Standard_True, theReplaceIfExists);
315 }
316
317 static TColStd_MapOfInteger theactivatedmodes(8);
318 static TColStd_ListOfTransient theEventMgrs;
319
320 static void VwrTst_InitEventMgr(const Handle(NIS_View)& aView,
321                                 const Handle(AIS_InteractiveContext)& Ctx)
322 {
323   theEventMgrs.Clear();
324   theEventMgrs.Prepend(new ViewerTest_EventManager(aView, Ctx));
325 }
326
327 static Handle(V3d_View)&  a3DView()
328 {
329   static Handle(V3d_View) Viou;
330   return Viou;
331 }
332
333
334 Standard_EXPORT Handle(AIS_InteractiveContext)& TheAISContext(){
335   static Handle(AIS_InteractiveContext) aContext;
336   return aContext;
337 }
338
339 const Handle(V3d_View)& ViewerTest::CurrentView()
340 {
341   return a3DView();
342 }
343 void ViewerTest::CurrentView(const Handle(V3d_View)& V)
344 {
345   a3DView() = V;
346 }
347
348 Standard_EXPORT const Handle(NIS_InteractiveContext)& TheNISContext()
349 {
350   static Handle(NIS_InteractiveContext) aContext;
351   if (aContext.IsNull()) {
352     aContext = new NIS_InteractiveContext;
353     aContext->SetSelectionMode (NIS_InteractiveContext::Mode_Normal);
354   }
355   return aContext;
356 }
357
358 const Handle(AIS_InteractiveContext)& ViewerTest::GetAISContext()
359 {
360   return TheAISContext();
361 }
362
363 void ViewerTest::SetAISContext (const Handle(AIS_InteractiveContext)& aCtx)
364 {
365   TheAISContext() = aCtx;
366   ViewerTest::ResetEventManager();
367 }
368
369 Handle(V3d_Viewer) ViewerTest::GetViewerFromContext()
370 {
371   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
372 }
373
374 Handle(V3d_Viewer) ViewerTest::GetCollectorFromContext()
375 {
376   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
377 }
378
379
380 void ViewerTest::SetEventManager(const Handle(ViewerTest_EventManager)& EM){
381   theEventMgrs.Prepend(EM);
382 }
383
384 void ViewerTest::UnsetEventManager()
385 {
386   theEventMgrs.RemoveFirst();
387 }
388
389
390 void ViewerTest::ResetEventManager()
391 {
392   const Handle(NIS_View) aView =
393     Handle(NIS_View)::DownCast(ViewerTest::CurrentView());
394   VwrTst_InitEventMgr(aView, ViewerTest::GetAISContext());
395 }
396
397 Handle(ViewerTest_EventManager) ViewerTest::CurrentEventManager()
398 {
399   Handle(ViewerTest_EventManager) EM;
400   if(theEventMgrs.IsEmpty()) return EM;
401   Handle(Standard_Transient) Tr =  theEventMgrs.First();
402   EM = *((Handle(ViewerTest_EventManager)*)&Tr);
403   return EM;
404 }
405
406 //=======================================================================
407 //function : Get Context and active view
408 //purpose  :
409 //=======================================================================
410 static Standard_Boolean getCtxAndView (Handle(AIS_InteractiveContext)& theCtx,
411                                        Handle(V3d_View)&               theView)
412 {
413   theCtx  = ViewerTest::GetAISContext();
414   theView = ViewerTest::CurrentView();
415   if (theCtx.IsNull()
416    || theView.IsNull())
417   {
418     std::cout << "Error: cannot find an active view!\n";
419     return Standard_False;
420   }
421   return Standard_True;
422 }
423
424 //==============================================================================
425 //function : GetShapeFromName
426 //purpose  : Compute an Shape from a draw variable or a file name
427 //==============================================================================
428
429 static TopoDS_Shape GetShapeFromName(const char* name)
430 {
431   TopoDS_Shape S = DBRep::Get(name);
432
433   if ( S.IsNull() ) {
434         BRep_Builder aBuilder;
435         BRepTools::Read( S, name, aBuilder);
436   }
437
438   return S;
439 }
440
441 //==============================================================================
442 //function : GetAISShapeFromName
443 //purpose  : Compute an AIS_Shape from a draw variable or a file name
444 //==============================================================================
445 Handle(AIS_Shape) GetAISShapeFromName(const char* name)
446 {
447   Handle(AIS_Shape) retsh;
448
449   if(GetMapOfAIS().IsBound2(name)){
450     const Handle(AIS_InteractiveObject) IO =
451       Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(name));
452     if (!IO.IsNull()) {
453       if(IO->Type()==AIS_KOI_Shape) {
454         if(IO->Signature()==0){
455           retsh = *((Handle(AIS_Shape)*)&IO);
456         }
457         else
458           cout << "an Object which is not an AIS_Shape "
459             "already has this name!!!"<<endl;
460       }
461     }
462     return retsh;
463   }
464
465
466   TopoDS_Shape S = GetShapeFromName(name);
467   if ( !S.IsNull() ) {
468     retsh = new AIS_Shape(S);
469   }
470   return retsh;
471 }
472
473
474 //==============================================================================
475 //function : Clear
476 //purpose  : Remove all the object from the viewer
477 //==============================================================================
478 void ViewerTest::Clear()
479 {
480   if ( !a3DView().IsNull() ) {
481     if (TheAISContext()->HasOpenedContext())
482       TheAISContext()->CloseLocalContext();
483     ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName it(GetMapOfAIS());
484     while ( it.More() ) {
485       cout << "Remove " << it.Key2() << endl;
486       if (it.Key1()->IsKind(STANDARD_TYPE(AIS_InteractiveObject))) {
487         const Handle(AIS_InteractiveObject) anObj =
488           Handle(AIS_InteractiveObject)::DownCast (it.Key1());
489         TheAISContext()->Remove(anObj,Standard_False);
490       } else if (it.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) {
491         const Handle(NIS_InteractiveObject) anObj =
492           Handle(NIS_InteractiveObject)::DownCast (it.Key1());
493         TheNISContext()->Remove(anObj);
494       }
495       it.Next();
496     }
497     TheAISContext()->RebuildSelectionStructs();
498     TheAISContext()->UpdateCurrentViewer();
499 //    TheNISContext()->UpdateViews();
500     GetMapOfAIS().Clear();
501   }
502 }
503
504 //==============================================================================
505 //function : StandardModesActivation
506 //purpose  : Activate a selection mode, vertex, edge, wire ..., in a local
507 //           Context
508 //==============================================================================
509 void ViewerTest::StandardModeActivation(const Standard_Integer mode )
510 {
511   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
512   if(mode==0) {
513     if (TheAISContext()->HasOpenedContext())
514       aContext->CloseLocalContext();
515   } else {
516
517     if(!aContext->HasOpenedContext()) {
518       // To unhilight the preselected object
519       aContext->UnhilightCurrents(Standard_False);
520       // Open a local Context in order to be able to select subshape from
521       // the selected shape if any or for all if there is no selection
522       if (!aContext->FirstCurrentObject().IsNull()){
523         aContext->OpenLocalContext(Standard_False);
524
525         for(aContext->InitCurrent();aContext->MoreCurrent();aContext->NextCurrent()){
526           aContext->Load(       aContext->Current(),-1,Standard_True);
527         }
528       }
529       else
530         aContext->OpenLocalContext();
531     }
532
533     const char *cmode="???";
534
535     switch (mode) {
536     case 0: cmode = "Shape"; break;
537     case 1: cmode = "Vertex"; break;
538     case 2: cmode = "Edge"; break;
539     case 3: cmode = "Wire"; break;
540     case 4: cmode = "Face"; break;
541     case 5: cmode = "Shell"; break;
542     case 6: cmode = "Solid"; break;
543     case 7: cmode = "Compsolid"; break;
544     case 8: cmode = "Compound"; break;
545     }
546
547     if(theactivatedmodes.Contains(mode))
548       { // Desactivate
549         aContext->DeactivateStandardMode(AIS_Shape::SelectionType(mode));
550         theactivatedmodes.Remove(mode);
551         cout<<"Mode "<< cmode <<" OFF"<<endl;
552       }
553     else
554       { // Activate
555         aContext->ActivateStandardMode(AIS_Shape::SelectionType(mode));
556         theactivatedmodes.Add(mode);
557         cout<<"Mode "<< cmode << " ON" << endl;
558       }
559   }
560 }
561
562 //==============================================================================
563 //function : CopyIsoAspect
564 //purpose  : Returns copy Prs3d_IsoAspect with new number of isolines.
565 //==============================================================================
566 static Handle(Prs3d_IsoAspect) CopyIsoAspect
567       (const Handle(Prs3d_IsoAspect) &theIsoAspect,
568        const Standard_Integer theNbIsos)
569 {
570   Quantity_Color    aColor;
571   Aspect_TypeOfLine aType;
572   Standard_Real     aWidth;
573
574   theIsoAspect->Aspect()->Values(aColor, aType, aWidth);
575
576   Handle(Prs3d_IsoAspect) aResult =
577     new Prs3d_IsoAspect(aColor, aType, aWidth, theNbIsos);
578
579   return aResult;
580 }
581
582 //==============================================================================
583 //function : visos
584 //purpose  : Returns or sets the number of U- and V- isos and isIsoOnPlane flag
585 //Draw arg : [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]
586 //==============================================================================
587 static int visos (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
588 {
589   if (TheAISContext().IsNull()) {
590     di << argv[0] << " Call 'vinit' before!\n";
591     return 1;
592   }
593
594   if (argc <= 1) {
595     di << "Current number of isos : " <<
596       TheAISContext()->IsoNumber(AIS_TOI_IsoU) << " " <<
597       TheAISContext()->IsoNumber(AIS_TOI_IsoV) << "\n";
598     di << "IsoOnPlane mode is " <<
599       (TheAISContext()->IsoOnPlane() ? "ON" : "OFF") << "\n";
600
601     return 0;
602   }
603
604   Standard_Integer aLastInd = argc - 1;
605   Standard_Boolean isChanged = Standard_False;
606   Standard_Integer aNbUIsos = 0;
607   Standard_Integer aNbVIsos = 0;
608
609   if (aLastInd >= 3) {
610     Standard_Boolean isIsoOnPlane = Standard_False;
611
612     if (strcmp(argv[aLastInd], "1") == 0) {
613       isIsoOnPlane = Standard_True;
614       isChanged    = Standard_True;
615     } else if (strcmp(argv[aLastInd], "0") == 0) {
616       isIsoOnPlane = Standard_False;
617       isChanged    = Standard_True;
618     }
619
620     if (isChanged) {
621       aNbVIsos = Draw::Atoi(argv[aLastInd - 1]);
622       aNbUIsos = Draw::Atoi(argv[aLastInd - 2]);
623       aLastInd -= 3;
624
625       di << "New number of isos : " << aNbUIsos << " " << aNbVIsos << "\n";
626       di << "New IsoOnPlane mode is " << (isIsoOnPlane ? "ON" : "OFF") << "\n";
627
628       TheAISContext()->IsoOnPlane(isIsoOnPlane);
629
630       if (aLastInd == 0) {
631         // If there are no shapes provided set the default numbers.
632         TheAISContext()->SetIsoNumber(aNbUIsos, AIS_TOI_IsoU);
633         TheAISContext()->SetIsoNumber(aNbVIsos, AIS_TOI_IsoV);
634       }
635     }
636   }
637
638   Standard_Integer i;
639
640   for (i = 1; i <= aLastInd; i++) {
641     TCollection_AsciiString name(argv[i]);
642     Standard_Boolean IsBound = GetMapOfAIS().IsBound2(name);
643
644     if (IsBound) {
645       const Handle(Standard_Transient) anObj = GetMapOfAIS().Find2(name);
646       if (anObj->IsKind(STANDARD_TYPE(AIS_InteractiveObject))) {
647         const Handle(AIS_InteractiveObject) aShape =
648         Handle(AIS_InteractiveObject)::DownCast (anObj);
649         Handle(Prs3d_Drawer) CurDrawer = aShape->Attributes();
650         Handle(Prs3d_IsoAspect) aUIso = CurDrawer->UIsoAspect();
651         Handle(Prs3d_IsoAspect) aVIso = CurDrawer->VIsoAspect();
652
653         if (isChanged) {
654           CurDrawer->SetUIsoAspect(CopyIsoAspect(aUIso, aNbUIsos));
655           CurDrawer->SetVIsoAspect(CopyIsoAspect(aVIso, aNbVIsos));
656           TheAISContext()->SetLocalAttributes
657                   (aShape, CurDrawer, Standard_False);
658           TheAISContext()->Redisplay(aShape);
659         } else {
660           di << "Number of isos for " << argv[i] << " : "
661              << aUIso->Number() << " " << aVIso->Number() << "\n";
662         }
663       } else {
664         di << argv[i] << ": Not an AIS interactive object!\n";
665       }
666     } else {
667       di << argv[i] << ": Use 'vdisplay' before\n";
668     }
669   }
670
671   if (isChanged) {
672     TheAISContext()->UpdateCurrentViewer();
673   }
674
675   return 0;
676 }
677
678 static Standard_Integer VDispSensi (Draw_Interpretor& ,
679                                     Standard_Integer  theArgNb,
680                                     Standard_CString* )
681 {
682   if (theArgNb > 1)
683   {
684     std::cout << "Error: wrong syntax!\n";
685     return 1;
686   }
687
688   Handle(AIS_InteractiveContext) aCtx;
689   Handle(V3d_View)               aView;
690   if (!getCtxAndView (aCtx, aView))
691   {
692     return 1;
693   }
694
695   aCtx->DisplayActiveSensitive (aView);
696   return 0;
697
698 }
699
700 static Standard_Integer VClearSensi (Draw_Interpretor& ,
701                                      Standard_Integer  theArgNb,
702                                      Standard_CString* )
703 {
704   if (theArgNb > 1)
705   {
706     std::cout << "Error: wrong syntax!\n";
707     return 1;
708   }
709
710   Handle(AIS_InteractiveContext) aCtx;
711   Handle(V3d_View)               aView;
712   if (!getCtxAndView (aCtx, aView))
713   {
714     return 1;
715   }
716   aCtx->ClearActiveSensitive (aView);
717   return 0;
718 }
719
720 //==============================================================================
721 //function : VDir
722 //purpose  : To list the displayed object with their attributes
723 //==============================================================================
724 static int VDir (Draw_Interpretor& theDI,
725                  Standard_Integer ,
726                  const char** )
727 {
728   if (!a3DView().IsNull())
729   {
730     return 0;
731   }
732
733   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
734        anIter.More(); anIter.Next())
735   {
736     theDI << "\t" << anIter.Key2().ToCString() << "\n";
737   }
738   return 0;
739 }
740
741 //==============================================================================
742 //function : VSelPrecision
743 //purpose  : To set the selection tolerance value
744 //Draw arg : Selection tolerance value (real value determining the width and
745 //           height of selecting frustum bases). Without arguments the function
746 //           just prints current tolerance.
747 //==============================================================================
748 static int VSelPrecision(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
749 {
750   if( argc > 2 )
751   {
752     di << "Wrong parameters! Must be: " << argv[0] << " [-unset] [tolerance]\n";
753     return 1;
754   }
755
756   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
757   if( aContext.IsNull() )
758     return 1;
759
760   if( argc == 1 )
761   {
762     Standard_Real aPixelTolerance = aContext->PixelTolerance();
763     di << "Pixel tolerance : " << aPixelTolerance << "\n";
764   }
765   else if (argc == 2)
766   {
767     TCollection_AsciiString anArg = TCollection_AsciiString (argv[1]);
768     anArg.LowerCase();
769     if (anArg == "-unset")
770     {
771       aContext->SetPixelTolerance (-1.0);
772     }
773     else
774     {
775       aContext->SetPixelTolerance (anArg.RealValue());
776     }
777   }
778
779   return 0;
780 }
781
782 //==============================================================================
783 //function : VDump
784 //purpose  : To dump the active view snapshot to image file
785 //==============================================================================
786 static Standard_Integer VDump (Draw_Interpretor& theDI,
787                                Standard_Integer  theArgNb,
788                                Standard_CString* theArgVec)
789 {
790   if (theArgNb < 2)
791   {
792     std::cout << "Error: wrong number of arguments! Image file name should be specified at least.\n";
793     return 1;
794   }
795
796   Standard_Integer      anArgIter   = 1;
797   Standard_CString      aFilePath   = theArgVec[anArgIter++];
798   Graphic3d_BufferType  aBufferType = Graphic3d_BT_RGB;
799   V3d_StereoDumpOptions aStereoOpts = V3d_SDO_MONO;
800   Standard_Integer      aWidth      = 0;
801   Standard_Integer      aHeight     = 0;
802   for (; anArgIter < theArgNb; ++anArgIter)
803   {
804     TCollection_AsciiString anArg (theArgVec[anArgIter]);
805     anArg.LowerCase();
806     if (anArg == "rgba")
807     {
808       aBufferType = Graphic3d_BT_RGBA;
809     }
810     else if (anArg == "rgb")
811     {
812       aBufferType = Graphic3d_BT_RGB;
813     }
814     else if (anArg == "depth")
815     {
816       aBufferType = Graphic3d_BT_Depth;
817     }
818     else if (anArg == "l"
819           || anArg == "left")
820     {
821       aStereoOpts = V3d_SDO_LEFT_EYE;
822     }
823     else if (anArg == "r"
824           || anArg == "right")
825     {
826       aStereoOpts = V3d_SDO_RIGHT_EYE;
827     }
828     else if (anArg == "mono")
829     {
830       aStereoOpts = V3d_SDO_MONO;
831     }
832     else if (anArg == "w"
833           || anArg == "width")
834     {
835       if (aWidth  != 0)
836       {
837         std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n";
838         return 1;
839       }
840       else if (++anArgIter >= theArgNb)
841       {
842         std::cout << "Error: integer value is expected right after 'width'\n";
843         return 1;
844       }
845       aWidth = Draw::Atoi (theArgVec[anArgIter]);
846     }
847     else if (anArg == "h"
848           || anArg == "height")
849     {
850       if (aHeight != 0)
851       {
852         std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n";
853         return 1;
854       }
855       if (++anArgIter >= theArgNb)
856       {
857         std::cout << "Error: integer value is expected right after 'height'\n";
858         return 1;
859       }
860       aHeight = Draw::Atoi (theArgVec[anArgIter]);
861     }
862     else if (anArg.IsIntegerValue())
863     {
864       // compatibility with old syntax
865       if (aWidth  != 0
866        || aHeight != 0)
867       {
868         std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n";
869         return 1;
870       }
871       else if (++anArgIter >= theArgNb)
872       {
873         std::cout << "Error: height value is expected right after width\n";
874         return 1;
875       }
876       aWidth  = Draw::Atoi (theArgVec[anArgIter - 1]);
877       aHeight = Draw::Atoi (theArgVec[anArgIter]);
878     }
879     else
880     {
881       std::cout << "Error: unknown argument '" << theArgVec[anArgIter] << "'\n";
882       return 1;
883     }
884   }
885   if ((aWidth <= 0 && aHeight >  0)
886    || (aWidth >  0 && aHeight <= 0))
887   {
888     std::cout << "Error: dimensions " << aWidth << "x" << aHeight << " are incorrect\n";
889     return 1;
890   }
891
892   Handle(V3d_View) aView = ViewerTest::CurrentView();
893   if (aView.IsNull())
894   {
895     std::cout << "Error: cannot find an active view!\n";
896     return 1;
897   }
898
899   if (aWidth <= 0 || aHeight <= 0)
900   {
901     if (aStereoOpts != V3d_SDO_MONO)
902     {
903       aView->Window()->Size (aWidth, aHeight);
904     }
905     else
906     {
907       if (!aView->Dump (aFilePath, aBufferType))
908       {
909         theDI << "Fail: view dump failed!\n";
910       }
911       return 0;
912     }
913   }
914
915   Image_AlienPixMap aPixMap;
916   if (!aView->ToPixMap (aPixMap, aWidth, aHeight, aBufferType, Standard_True, aStereoOpts))
917   {
918     theDI << "Fail: view dump failed!\n";
919     return 0;
920   }
921
922   if (aPixMap.SizeX() != Standard_Size(aWidth)
923    || aPixMap.SizeY() != Standard_Size(aHeight))
924   {
925     theDI << "Fail: dumped dimensions "    << (Standard_Integer )aPixMap.SizeX() << "x" << (Standard_Integer )aPixMap.SizeY()
926           << " are lesser than requested " << aWidth << "x" << aHeight << "\n";
927   }
928   if (!aPixMap.Save (aFilePath))
929   {
930     theDI << "Fail: image can not be saved!\n";
931   }
932   return 0;
933 }
934
935
936 //==============================================================================
937 //function : Displays,Erase...
938 //purpose  :
939 //Draw arg :
940 //==============================================================================
941 static int VwrTst_DispErase(const Handle(AIS_InteractiveObject)& IO,
942                             const Standard_Integer Mode,
943                             const Standard_Integer TypeOfOperation,
944                             const Standard_Boolean Upd)
945 {
946   Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
947
948   switch(TypeOfOperation){
949   case 1:
950     Ctx->Display(IO,Mode,Upd);
951     break;
952   case 2:{
953     Ctx->Erase(IO,Upd);
954     break;
955   }
956   case 3:{
957     if(IO.IsNull())
958       Ctx->SetDisplayMode((AIS_DisplayMode)Mode,Upd);
959     else
960       Ctx->SetDisplayMode(IO,Mode,Upd);
961     break;
962   }
963   case 4:{
964     if(IO.IsNull())
965       Ctx->SetDisplayMode(0,Upd);
966     else
967       Ctx->UnsetDisplayMode(IO,Upd);
968     break;
969   }
970   }
971   return 0;
972 }
973
974 //=======================================================================
975 //function :
976 //purpose  :
977 //=======================================================================
978 static int VDispMode (Draw_Interpretor& , Standard_Integer argc, const char** argv)
979 {
980
981   TCollection_AsciiString name;
982   if(argc>3)
983     return 1;
984   // display others presentations
985   Standard_Integer TypeOfOperation = (strcasecmp(argv[0],"vdispmode")==0)? 1:
986     (strcasecmp(argv[0],"verasemode")==0) ? 2 :
987       (strcasecmp(argv[0],"vsetdispmode")==0) ? 3 :
988         (strcasecmp(argv[0],"vunsetdispmode")==0) ? 4 : -1;
989
990   Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
991
992   //unset displaymode.. comportement particulier...
993   if(TypeOfOperation==4){
994     if(argc==1){
995       if(Ctx->NbCurrents()==0 ||
996          Ctx->NbSelected()==0){
997         Handle(AIS_InteractiveObject) IO;
998         VwrTst_DispErase(IO,-1,4,Standard_False);
999       }
1000       else if(!Ctx->HasOpenedContext()){
1001         for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent())
1002           VwrTst_DispErase(Ctx->Current(),-1,4,Standard_False);
1003       }
1004       else{
1005         for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1006           VwrTst_DispErase(Ctx->Interactive(),-1,4,Standard_False);}
1007       Ctx->UpdateCurrentViewer();
1008     }
1009     else{
1010       Handle(AIS_InteractiveObject) IO;
1011       name = argv[1];
1012       if(GetMapOfAIS().IsBound2(name)){
1013         IO = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(name));
1014         if (!IO.IsNull())
1015           VwrTst_DispErase(IO,-1,4,Standard_True);
1016       }
1017     }
1018   }
1019   else if(argc==2){
1020     Standard_Integer Dmode = Draw::Atoi(argv[1]);
1021     if(Ctx->NbCurrents()==0 && TypeOfOperation==3){
1022       Handle(AIS_InteractiveObject) IO;
1023       VwrTst_DispErase(IO,Dmode,TypeOfOperation,Standard_True);
1024     }
1025     if(!Ctx->HasOpenedContext()){
1026       // set/unset display mode sur le Contexte...
1027       for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent()){
1028         VwrTst_DispErase(Ctx->Current(),Dmode,TypeOfOperation,Standard_False);
1029       }
1030       Ctx->UpdateCurrentViewer();
1031     }
1032     else{
1033       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1034         Ctx->Display(Ctx->Interactive(),Dmode);
1035     }
1036   }
1037   else{
1038     Handle(AIS_InteractiveObject) IO;
1039     name = argv[1];
1040     if(GetMapOfAIS().IsBound2(name))
1041       IO = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(name));
1042     if (!IO.IsNull())
1043       VwrTst_DispErase(IO,Draw::Atoi(argv[2]),TypeOfOperation,Standard_True);
1044   }
1045   return 0;
1046 }
1047
1048
1049 //=======================================================================
1050 //function :
1051 //purpose  :
1052 //=======================================================================
1053 static int VSubInt(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1054 {
1055   if(argc==1) return 1;
1056   Standard_Integer On = Draw::Atoi(argv[1]);
1057   const Handle(AIS_InteractiveContext)& Ctx = ViewerTest::GetAISContext();
1058
1059   if(argc==2){
1060
1061     if(!Ctx->HasOpenedContext()){
1062       di<<"sub intensite ";
1063       if(On==1) di<<"On";
1064       else di<<"Off";
1065       di<<" pour "<<Ctx->NbCurrents()<<"  objets"<<"\n";
1066       for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent()){
1067         if(On==1){
1068           Ctx->SubIntensityOn(Ctx->Current(),Standard_False);}
1069         else{
1070           di <<"passage dans off"<<"\n";
1071           Ctx->SubIntensityOff(Ctx->Current(),Standard_False);
1072         }
1073       }
1074     }
1075     else{
1076       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected()){
1077         if(On==1){
1078           Ctx->SubIntensityOn(Ctx->Interactive(),Standard_False);}
1079         else{
1080           Ctx->SubIntensityOff(Ctx->Interactive(),Standard_False);}
1081       }
1082     }
1083     Ctx->UpdateCurrentViewer();
1084   }
1085   else {
1086     Handle(AIS_InteractiveObject) IO;
1087     TCollection_AsciiString name = argv[2];
1088     if(GetMapOfAIS().IsBound2(name)){
1089       IO = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(name));
1090       if (!IO.IsNull()) {
1091         if(On==1)
1092           Ctx->SubIntensityOn(IO);
1093         else
1094           Ctx->SubIntensityOff(IO);
1095       }
1096     }
1097     else return 1;
1098   }
1099   return 0;
1100 }
1101
1102 //! Auxiliary class to iterate presentations from different collections.
1103 class ViewTest_PrsIter
1104 {
1105 public:
1106
1107   //! Create and initialize iterator object.
1108   ViewTest_PrsIter (const TCollection_AsciiString& theName)
1109   : mySource (IterSource_All)
1110   {
1111     NCollection_Sequence<TCollection_AsciiString> aNames;
1112     if (!theName.IsEmpty())
1113     aNames.Append (theName);
1114     Init (aNames);
1115   }
1116
1117   //! Create and initialize iterator object.
1118   ViewTest_PrsIter (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1119   : mySource (IterSource_All)
1120   {
1121     Init (theNames);
1122   }
1123
1124   //! Initialize the iterator.
1125   void Init (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1126   {
1127     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1128     mySeq = theNames;
1129     mySelIter.Nullify();
1130     myCurrent.Nullify();
1131     myCurrentTrs.Nullify();
1132     if (!mySeq.IsEmpty())
1133     {
1134       mySource = IterSource_List;
1135       mySeqIter = NCollection_Sequence<TCollection_AsciiString>::Iterator (mySeq);
1136     }
1137     else if (aCtx->NbCurrents() > 0)
1138     {
1139       mySource  = IterSource_Selected;
1140       mySelIter = aCtx;
1141       mySelIter->InitCurrent();
1142     }
1143     else
1144     {
1145       mySource = IterSource_All;
1146       myMapIter.Initialize (GetMapOfAIS());
1147     }
1148     initCurrent();
1149   }
1150
1151   const TCollection_AsciiString& CurrentName() const
1152   {
1153     return myCurrentName;
1154   }
1155
1156   const Handle(AIS_InteractiveObject)& Current() const
1157   {
1158     return myCurrent;
1159   }
1160
1161   const Handle(Standard_Transient)& CurrentTrs() const
1162   {
1163     return myCurrentTrs;
1164   }
1165
1166   //! @return true if iterator points to valid object within collection
1167   Standard_Boolean More() const
1168   {
1169     switch (mySource)
1170     {
1171       case IterSource_All:      return myMapIter.More();
1172       case IterSource_List:     return mySeqIter.More();
1173       case IterSource_Selected: return mySelIter->MoreCurrent();
1174     }
1175     return Standard_False;
1176   }
1177
1178   //! Go to the next item.
1179   void Next()
1180   {
1181     myCurrentName.Clear();
1182     myCurrentTrs.Nullify();
1183     myCurrent.Nullify();
1184     switch (mySource)
1185     {
1186       case IterSource_All:
1187       {
1188         myMapIter.Next();
1189         break;
1190       }
1191       case IterSource_List:
1192       {
1193         mySeqIter.Next();
1194         break;
1195       }
1196       case IterSource_Selected:
1197       {
1198         mySelIter->NextCurrent();
1199         break;
1200       }
1201     }
1202     initCurrent();
1203   }
1204
1205 private:
1206
1207   void initCurrent()
1208   {
1209     switch (mySource)
1210     {
1211       case IterSource_All:
1212       {
1213         if (myMapIter.More())
1214         {
1215           myCurrentName = myMapIter.Key2();
1216           myCurrentTrs  = myMapIter.Key1();
1217           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1218         }
1219         break;
1220       }
1221       case IterSource_List:
1222       {
1223         if (mySeqIter.More())
1224         {
1225           if (!GetMapOfAIS().IsBound2 (mySeqIter.Value()))
1226           {
1227             std::cout << "Error: object " << mySeqIter.Value() << " is not displayed!\n";
1228             return;
1229           }
1230           myCurrentName = mySeqIter.Value();
1231           myCurrentTrs  = GetMapOfAIS().Find2 (mySeqIter.Value());
1232           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1233         }
1234         break;
1235       }
1236       case IterSource_Selected:
1237       {
1238         if (mySelIter->MoreCurrent())
1239         {
1240           myCurrentName = GetMapOfAIS().Find1 (mySelIter->Current());
1241           myCurrent     = mySelIter->Current();
1242         }
1243         break;
1244       }
1245     }
1246   }
1247
1248 private:
1249
1250   enum IterSource
1251   {
1252     IterSource_All,
1253     IterSource_List,
1254     IterSource_Selected
1255   };
1256
1257 private:
1258
1259   Handle(AIS_InteractiveContext) mySelIter;    //!< iterator for current (selected) objects (IterSource_Selected)
1260   ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName myMapIter; //!< iterator for map of all objects (IterSource_All)
1261   NCollection_Sequence<TCollection_AsciiString>           mySeq;
1262   NCollection_Sequence<TCollection_AsciiString>::Iterator mySeqIter;
1263
1264   TCollection_AsciiString        myCurrentName;//!< current item name
1265   Handle(Standard_Transient)     myCurrentTrs; //!< current item (as transient object)
1266   Handle(AIS_InteractiveObject)  myCurrent;    //!< current item
1267
1268   IterSource                     mySource;     //!< iterated collection
1269
1270 };
1271
1272 //==============================================================================
1273 //function : VInteriorStyle
1274 //purpose  : sets interior style of the a selected or named or displayed shape
1275 //==============================================================================
1276 static int VSetInteriorStyle (Draw_Interpretor& theDI,
1277                               Standard_Integer  theArgNb,
1278                               const char**      theArgVec)
1279 {
1280   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
1281   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
1282   if (aCtx.IsNull())
1283   {
1284     std::cerr << "Error: no active view!\n";
1285     return 1;
1286   }
1287
1288   Standard_Integer anArgIter = 1;
1289   for (; anArgIter < theArgNb; ++anArgIter)
1290   {
1291     if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
1292     {
1293       break;
1294     }
1295   }
1296   TCollection_AsciiString aName;
1297   if (theArgNb - anArgIter == 2)
1298   {
1299     aName = theArgVec[anArgIter++];
1300   }
1301   else if (theArgNb - anArgIter != 1)
1302   {
1303     std::cout << "Error: wrong number of arguments! See usage:\n";
1304     theDI.PrintHelp (theArgVec[0]);
1305     return 1;
1306   }
1307   Standard_Integer        anInterStyle = Aspect_IS_SOLID;
1308   TCollection_AsciiString aStyleArg (theArgVec[anArgIter++]);
1309   aStyleArg.LowerCase();
1310   if (aStyleArg == "empty")
1311   {
1312     anInterStyle = 0;
1313   }
1314   else if (aStyleArg == "hollow")
1315   {
1316     anInterStyle = 1;
1317   }
1318   else if (aStyleArg == "hatch")
1319   {
1320     anInterStyle = 2;
1321   }
1322   else if (aStyleArg == "solid")
1323   {
1324     anInterStyle = 3;
1325   }
1326   else if (aStyleArg == "hiddenline")
1327   {
1328     anInterStyle = 4;
1329   }
1330   else
1331   {
1332     anInterStyle = aStyleArg.IntegerValue();
1333   }
1334   if (anInterStyle < Aspect_IS_EMPTY
1335    || anInterStyle > Aspect_IS_HIDDENLINE)
1336   {
1337     std::cout << "Error: style must be within a range [0 (Aspect_IS_EMPTY), "
1338               << Aspect_IS_HIDDENLINE << " (Aspect_IS_HIDDENLINE)]\n";
1339     return 1;
1340   }
1341
1342   if (!aName.IsEmpty()
1343    && !GetMapOfAIS().IsBound2 (aName))
1344   {
1345     std::cout << "Error: object " << aName << " is not displayed!\n";
1346     return 1;
1347   }
1348
1349   if (aCtx->HasOpenedContext())
1350   {
1351     aCtx->CloseLocalContext();
1352   }
1353   for (ViewTest_PrsIter anIter (aName); anIter.More(); anIter.Next())
1354   {
1355     const Handle(AIS_InteractiveObject)& anIO = anIter.Current();
1356     if (!anIO.IsNull())
1357     {
1358       const Handle(Prs3d_Drawer)& aDrawer        = anIO->Attributes();
1359       Handle(Prs3d_ShadingAspect) aShadingAspect = aDrawer->ShadingAspect();
1360       Handle(Graphic3d_AspectFillArea3d) aFillAspect = aShadingAspect->Aspect();
1361       aFillAspect->SetInteriorStyle ((Aspect_InteriorStyle )anInterStyle);
1362       aCtx->RecomputePrsOnly (anIO, Standard_False, Standard_True);
1363     }
1364   }
1365   return 0;
1366 }
1367
1368 //! Auxiliary structure for VAspects
1369 struct ViewerTest_AspectsChangeSet
1370 {
1371   Standard_Integer         ToSetVisibility;
1372   Standard_Integer         Visibility;
1373
1374   Standard_Integer         ToSetColor;
1375   Quantity_Color           Color;
1376
1377   Standard_Integer         ToSetLineWidth;
1378   Standard_Real            LineWidth;
1379
1380   Standard_Integer         ToSetTransparency;
1381   Standard_Real            Transparency;
1382
1383   Standard_Integer         ToSetMaterial;
1384   Graphic3d_NameOfMaterial Material;
1385   TCollection_AsciiString  MatName;
1386
1387   NCollection_Sequence<TopoDS_Shape> SubShapes;
1388
1389   Standard_Integer         ToSetShowFreeBoundary;
1390   Standard_Integer         ToSetFreeBoundaryWidth;
1391   Standard_Real            FreeBoundaryWidth;
1392   Standard_Integer         ToSetFreeBoundaryColor;
1393   Quantity_Color           FreeBoundaryColor;
1394
1395   //! Empty constructor
1396   ViewerTest_AspectsChangeSet()
1397   : ToSetVisibility   (0),
1398     Visibility        (1),
1399     ToSetColor        (0),
1400     Color             (DEFAULT_COLOR),
1401     ToSetLineWidth    (0),
1402     LineWidth         (1.0),
1403     ToSetTransparency (0),
1404     Transparency      (0.0),
1405     ToSetMaterial     (0),
1406     Material          (Graphic3d_NOM_DEFAULT),
1407     ToSetShowFreeBoundary  (0),
1408     ToSetFreeBoundaryWidth (0),
1409     FreeBoundaryWidth      (1.0),
1410     ToSetFreeBoundaryColor (0),
1411     FreeBoundaryColor      (DEFAULT_FREEBOUNDARY_COLOR) {}
1412
1413   //! @return true if no changes have been requested
1414   Standard_Boolean IsEmpty() const
1415   {
1416     return ToSetVisibility        == 0
1417         && ToSetLineWidth         == 0
1418         && ToSetTransparency      == 0
1419         && ToSetColor             == 0
1420         && ToSetMaterial          == 0
1421         && ToSetShowFreeBoundary  == 0
1422         && ToSetFreeBoundaryColor == 0
1423         && ToSetFreeBoundaryWidth == 0;
1424   }
1425
1426   //! @return true if properties are valid
1427   Standard_Boolean Validate (const Standard_Boolean theIsSubPart) const
1428   {
1429     Standard_Boolean isOk = Standard_True;
1430     if (Visibility != 0 && Visibility != 1)
1431     {
1432       std::cout << "Error: the visibility should be equal to 0 or 1 (0 - invisible; 1 - visible) (specified " << Visibility << ")\n";
1433       isOk = Standard_False;
1434     }
1435     if (LineWidth <= 0.0
1436      || LineWidth >  10.0)
1437     {
1438       std::cout << "Error: the width should be within [1; 10] range (specified " << LineWidth << ")\n";
1439       isOk = Standard_False;
1440     }
1441     if (Transparency < 0.0
1442      || Transparency > 1.0)
1443     {
1444       std::cout << "Error: the transparency should be within [0; 1] range (specified " << Transparency << ")\n";
1445       isOk = Standard_False;
1446     }
1447     if (theIsSubPart
1448      && ToSetTransparency)
1449     {
1450       std::cout << "Error: the transparency can not be defined for sub-part of object!\n";
1451       isOk = Standard_False;
1452     }
1453     if (ToSetMaterial == 1
1454      && Material == Graphic3d_NOM_DEFAULT)
1455     {
1456       std::cout << "Error: unknown material " << MatName << ".\n";
1457       isOk = Standard_False;
1458     }
1459     if (FreeBoundaryWidth <= 0.0
1460      || FreeBoundaryWidth >  10.0)
1461     {
1462       std::cout << "Error: the free boundary width should be within [1; 10] range (specified " << FreeBoundaryWidth << ")\n";
1463       isOk = Standard_False;
1464     }
1465     return isOk;
1466   }
1467
1468 };
1469
1470 //==============================================================================
1471 //function : VAspects
1472 //purpose  :
1473 //==============================================================================
1474 static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
1475                                   Standard_Integer  theArgNb,
1476                                   const char**      theArgVec)
1477 {
1478   TCollection_AsciiString aCmdName (theArgVec[0]);
1479   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
1480   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
1481   if (aCtx.IsNull())
1482   {
1483     std::cerr << "Error: no active view!\n";
1484     return 1;
1485   }
1486
1487   Standard_Integer anArgIter = 1;
1488   Standard_Boolean isDefaults = Standard_False;
1489   NCollection_Sequence<TCollection_AsciiString> aNames;
1490   for (; anArgIter < theArgNb; ++anArgIter)
1491   {
1492     TCollection_AsciiString anArg = theArgVec[anArgIter];
1493     if (anUpdateTool.parseRedrawMode (anArg))
1494     {
1495       continue;
1496     }
1497     else if (!anArg.IsEmpty()
1498            && anArg.Value (1) != '-')
1499     {
1500       aNames.Append (anArg);
1501     }
1502     else
1503     {
1504       if (anArg == "-defaults")
1505       {
1506         isDefaults = Standard_True;
1507         ++anArgIter;
1508       }
1509       break;
1510     }
1511   }
1512
1513   if (!aNames.IsEmpty() && isDefaults)
1514   {
1515     std::cout << "Error: wrong syntax. If -defaults is used there should not be any objects' names!\n";
1516     return 1;
1517   }
1518
1519   NCollection_Sequence<ViewerTest_AspectsChangeSet> aChanges;
1520   aChanges.Append (ViewerTest_AspectsChangeSet());
1521   ViewerTest_AspectsChangeSet* aChangeSet = &aChanges.ChangeLast();
1522
1523   // parse syntax of legacy commands
1524   if (aCmdName == "vsetwidth")
1525   {
1526     if (aNames.IsEmpty()
1527     || !aNames.Last().IsRealValue())
1528     {
1529       std::cout << "Error: not enough arguments!\n";
1530       return 1;
1531     }
1532     aChangeSet->ToSetLineWidth = 1;
1533     aChangeSet->LineWidth = aNames.Last().RealValue();
1534     aNames.Remove (aNames.Length());
1535   }
1536   else if (aCmdName == "vunsetwidth")
1537   {
1538     aChangeSet->ToSetLineWidth = -1;
1539   }
1540   else if (aCmdName == "vsetcolor")
1541   {
1542     if (aNames.IsEmpty())
1543     {
1544       std::cout << "Error: not enough arguments!\n";
1545       return 1;
1546     }
1547     aChangeSet->ToSetColor = 1;
1548
1549     Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
1550     Standard_Boolean     isOk   = Standard_False;
1551     if (Quantity_Color::ColorFromName (aNames.Last().ToCString(), aColor))
1552     {
1553       aChangeSet->Color = aColor;
1554       aNames.Remove (aNames.Length());
1555       isOk = Standard_True;
1556     }
1557     else if (aNames.Length() >= 3)
1558     {
1559       const TCollection_AsciiString anRgbStr[3] =
1560       {
1561         aNames.Value (aNames.Upper() - 2),
1562         aNames.Value (aNames.Upper() - 1),
1563         aNames.Value (aNames.Upper() - 0)
1564       };
1565       isOk = anRgbStr[0].IsRealValue()
1566           && anRgbStr[1].IsRealValue()
1567           && anRgbStr[2].IsRealValue();
1568       if (isOk)
1569       {
1570         Graphic3d_Vec4d anRgb;
1571         anRgb.x() = anRgbStr[0].RealValue();
1572         anRgb.y() = anRgbStr[1].RealValue();
1573         anRgb.z() = anRgbStr[2].RealValue();
1574         if (anRgb.x() < 0.0 || anRgb.x() > 1.0
1575          || anRgb.y() < 0.0 || anRgb.y() > 1.0
1576          || anRgb.z() < 0.0 || anRgb.z() > 1.0)
1577         {
1578           std::cout << "Error: RGB color values should be within range 0..1!\n";
1579           return 1;
1580         }
1581         aChangeSet->Color.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
1582         aNames.Remove (aNames.Length());
1583         aNames.Remove (aNames.Length());
1584         aNames.Remove (aNames.Length());
1585       }
1586     }
1587     if (!isOk)
1588     {
1589       std::cout << "Error: not enough arguments!\n";
1590       return 1;
1591     }
1592   }
1593   else if (aCmdName == "vunsetcolor")
1594   {
1595     aChangeSet->ToSetColor = -1;
1596   }
1597   else if (aCmdName == "vsettransparency")
1598   {
1599     if (aNames.IsEmpty()
1600     || !aNames.Last().IsRealValue())
1601     {
1602       std::cout << "Error: not enough arguments!\n";
1603       return 1;
1604     }
1605     aChangeSet->ToSetTransparency = 1;
1606     aChangeSet->Transparency  = aNames.Last().RealValue();
1607     aNames.Remove (aNames.Length());
1608   }
1609   else if (aCmdName == "vunsettransparency")
1610   {
1611     aChangeSet->ToSetTransparency = -1;
1612   }
1613   else if (aCmdName == "vsetmaterial")
1614   {
1615     if (aNames.IsEmpty())
1616     {
1617       std::cout << "Error: not enough arguments!\n";
1618       return 1;
1619     }
1620     aChangeSet->ToSetMaterial = 1;
1621     aChangeSet->MatName  = aNames.Last();
1622     aChangeSet->Material = Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString());
1623     aNames.Remove (aNames.Length());
1624   }
1625   else if (aCmdName == "vunsetmaterial")
1626   {
1627     aChangeSet->ToSetMaterial = -1;
1628   }
1629   else if (anArgIter >= theArgNb)
1630   {
1631     std::cout << "Error: not enough arguments!\n";
1632     return 1;
1633   }
1634
1635   if (!aChangeSet->IsEmpty())
1636   {
1637     anArgIter = theArgNb;
1638   }
1639   for (; anArgIter < theArgNb; ++anArgIter)
1640   {
1641     TCollection_AsciiString anArg = theArgVec[anArgIter];
1642     anArg.LowerCase();
1643     if (anArg == "-setwidth"
1644      || anArg == "-setlinewidth")
1645     {
1646       if (++anArgIter >= theArgNb)
1647       {
1648         std::cout << "Error: wrong syntax at " << anArg << "\n";
1649         return 1;
1650       }
1651       aChangeSet->ToSetLineWidth = 1;
1652       aChangeSet->LineWidth = Draw::Atof (theArgVec[anArgIter]);
1653     }
1654     else if (anArg == "-unsetwidth"
1655           || anArg == "-unsetlinewidth")
1656     {
1657       aChangeSet->ToSetLineWidth = -1;
1658       aChangeSet->LineWidth = 1.0;
1659     }
1660     else if (anArg == "-settransp"
1661           || anArg == "-settransparency")
1662     {
1663       if (++anArgIter >= theArgNb)
1664       {
1665         std::cout << "Error: wrong syntax at " << anArg << "\n";
1666         return 1;
1667       }
1668       aChangeSet->ToSetTransparency = 1;
1669       aChangeSet->Transparency = Draw::Atof (theArgVec[anArgIter]);
1670       if (aChangeSet->Transparency >= 0.0
1671        && aChangeSet->Transparency <= Precision::Confusion())
1672       {
1673         aChangeSet->ToSetTransparency = -1;
1674         aChangeSet->Transparency = 0.0;
1675       }
1676     }
1677     else if (anArg == "-setvis"
1678           || anArg == "-setvisibility")
1679     {
1680       if (++anArgIter >= theArgNb)
1681       {
1682         std::cout << "Error: wrong syntax at " << anArg << "\n";
1683         return 1;
1684       }
1685
1686       aChangeSet->ToSetVisibility = 1;
1687       aChangeSet->Visibility = Draw::Atoi (theArgVec[anArgIter]);
1688     }
1689     else if (anArg == "-setalpha")
1690     {
1691       if (++anArgIter >= theArgNb)
1692       {
1693         std::cout << "Error: wrong syntax at " << anArg << "\n";
1694         return 1;
1695       }
1696       aChangeSet->ToSetTransparency = 1;
1697       aChangeSet->Transparency  = Draw::Atof (theArgVec[anArgIter]);
1698       if (aChangeSet->Transparency < 0.0
1699        || aChangeSet->Transparency > 1.0)
1700       {
1701         std::cout << "Error: the transparency should be within [0; 1] range (specified " << aChangeSet->Transparency << ")\n";
1702         return 1;
1703       }
1704       aChangeSet->Transparency = 1.0 - aChangeSet->Transparency;
1705       if (aChangeSet->Transparency >= 0.0
1706        && aChangeSet->Transparency <= Precision::Confusion())
1707       {
1708         aChangeSet->ToSetTransparency = -1;
1709         aChangeSet->Transparency = 0.0;
1710       }
1711     }
1712     else if (anArg == "-unsettransp"
1713           || anArg == "-unsettransparency"
1714           || anArg == "-unsetalpha"
1715           || anArg == "-opaque")
1716     {
1717       aChangeSet->ToSetTransparency = -1;
1718       aChangeSet->Transparency = 0.0;
1719     }
1720     else if (anArg == "-setcolor")
1721     {
1722       Standard_Integer aNbComps  = 0;
1723       Standard_Integer aCompIter = anArgIter + 1;
1724       for (; aCompIter < theArgNb; ++aCompIter, ++aNbComps)
1725       {
1726         if (theArgVec[aCompIter][0] == '-')
1727         {
1728           break;
1729         }
1730       }
1731       switch (aNbComps)
1732       {
1733         case 1:
1734         {
1735           Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
1736           Standard_CString     aName  = theArgVec[anArgIter + 1];
1737           if (!Quantity_Color::ColorFromName (aName, aColor))
1738           {
1739             std::cout << "Error: unknown color name '" << aName << "'\n";
1740             return 1;
1741           }
1742           aChangeSet->Color = aColor;
1743           break;
1744         }
1745         case 3:
1746         {
1747           Graphic3d_Vec3d anRgb;
1748           anRgb.x() = Draw::Atof (theArgVec[anArgIter + 1]);
1749           anRgb.y() = Draw::Atof (theArgVec[anArgIter + 2]);
1750           anRgb.z() = Draw::Atof (theArgVec[anArgIter + 3]);
1751           if (anRgb.x() < 0.0 || anRgb.x() > 1.0
1752            || anRgb.y() < 0.0 || anRgb.y() > 1.0
1753            || anRgb.z() < 0.0 || anRgb.z() > 1.0)
1754           {
1755             std::cout << "Error: RGB color values should be within range 0..1!\n";
1756             return 1;
1757           }
1758           aChangeSet->Color.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
1759           break;
1760         }
1761         default:
1762         {
1763           std::cout << "Error: wrong syntax at " << anArg << "\n";
1764           return 1;
1765         }
1766       }
1767       aChangeSet->ToSetColor = 1;
1768       anArgIter += aNbComps;
1769     }
1770     else if (anArg == "-unsetcolor")
1771     {
1772       aChangeSet->ToSetColor = -1;
1773       aChangeSet->Color = DEFAULT_COLOR;
1774     }
1775     else if (anArg == "-setmat"
1776           || anArg == "-setmaterial")
1777     {
1778       if (++anArgIter >= theArgNb)
1779       {
1780         std::cout << "Error: wrong syntax at " << anArg << "\n";
1781         return 1;
1782       }
1783       aChangeSet->ToSetMaterial = 1;
1784       aChangeSet->MatName  = theArgVec[anArgIter];
1785       aChangeSet->Material = Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString());
1786     }
1787     else if (anArg == "-unsetmat"
1788           || anArg == "-unsetmaterial")
1789     {
1790       aChangeSet->ToSetMaterial = -1;
1791       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
1792     }
1793     else if (anArg == "-subshape"
1794           || anArg == "-subshapes")
1795     {
1796       if (isDefaults)
1797       {
1798         std::cout << "Error: wrong syntax. -subshapes can not be used together with -defaults call!\n";
1799         return 1;
1800       }
1801
1802       if (aNames.IsEmpty())
1803       {
1804         std::cout << "Error: main objects should specified explicitly when -subshapes is used!\n";
1805         return 1;
1806       }
1807
1808       aChanges.Append (ViewerTest_AspectsChangeSet());
1809       aChangeSet = &aChanges.ChangeLast();
1810
1811       for (++anArgIter; anArgIter < theArgNb; ++anArgIter)
1812       {
1813         Standard_CString aSubShapeName = theArgVec[anArgIter];
1814         if (*aSubShapeName == '-')
1815         {
1816           --anArgIter;
1817           break;
1818         }
1819
1820         TopoDS_Shape aSubShape = DBRep::Get (aSubShapeName);
1821         if (aSubShape.IsNull())
1822         {
1823           std::cerr << "Error: shape " << aSubShapeName << " doesn't found!\n";
1824           return 1;
1825         }
1826         aChangeSet->SubShapes.Append (aSubShape);
1827       }
1828
1829       if (aChangeSet->SubShapes.IsEmpty())
1830       {
1831         std::cerr << "Error: empty list is specified after -subshapes!\n";
1832         return 1;
1833       }
1834     }
1835     else if (anArg == "-freeboundary"
1836           || anArg == "-fb")
1837     {
1838       if (++anArgIter >= theArgNb)
1839       {
1840         std::cout << "Error: wrong syntax at " << anArg << "\n";
1841         return 1;
1842       }
1843       TCollection_AsciiString aValue (theArgVec[anArgIter]);
1844       aValue.LowerCase();
1845       if (aValue == "on"
1846        || aValue == "1")
1847       {
1848         aChangeSet->ToSetShowFreeBoundary = 1;
1849       }
1850       else if (aValue == "off"
1851             || aValue == "0")
1852       {
1853         aChangeSet->ToSetShowFreeBoundary = -1;
1854       }
1855       else
1856       {
1857         std::cout << "Error: wrong syntax at " << anArg << "\n";
1858         return 1;
1859       }
1860     }
1861     else if (anArg == "-setfreeboundarywidth"
1862           || anArg == "-setfbwidth")
1863     {
1864       if (++anArgIter >= theArgNb)
1865       {
1866         std::cout << "Error: wrong syntax at " << anArg << "\n";
1867         return 1;
1868       }
1869       aChangeSet->ToSetFreeBoundaryWidth = 1;
1870       aChangeSet->FreeBoundaryWidth = Draw::Atof (theArgVec[anArgIter]);
1871     }
1872     else if (anArg == "-unsetfreeboundarywidth"
1873           || anArg == "-unsetfbwidth")
1874     {
1875       aChangeSet->ToSetFreeBoundaryWidth = -1;
1876       aChangeSet->FreeBoundaryWidth = 1.0;
1877     }
1878     else if (anArg == "-setfreeboundarycolor"
1879           || anArg == "-setfbcolor")
1880     {
1881       Standard_Integer aNbComps  = 0;
1882       Standard_Integer aCompIter = anArgIter + 1;
1883       for (; aCompIter < theArgNb; ++aCompIter, ++aNbComps)
1884       {
1885         if (theArgVec[aCompIter][0] == '-')
1886         {
1887           break;
1888         }
1889       }
1890       switch (aNbComps)
1891       {
1892         case 1:
1893         {
1894           Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
1895           Standard_CString     aName  = theArgVec[anArgIter + 1];
1896           if (!Quantity_Color::ColorFromName (aName, aColor))
1897           {
1898             std::cout << "Error: unknown free boundary color name '" << aName << "'\n";
1899             return 1;
1900           }
1901           aChangeSet->FreeBoundaryColor = aColor;
1902           break;
1903         }
1904         case 3:
1905         {
1906           Graphic3d_Vec3d anRgb;
1907           anRgb.x() = Draw::Atof (theArgVec[anArgIter + 1]);
1908           anRgb.y() = Draw::Atof (theArgVec[anArgIter + 2]);
1909           anRgb.z() = Draw::Atof (theArgVec[anArgIter + 3]);
1910           if (anRgb.x() < 0.0 || anRgb.x() > 1.0
1911            || anRgb.y() < 0.0 || anRgb.y() > 1.0
1912            || anRgb.z() < 0.0 || anRgb.z() > 1.0)
1913           {
1914             std::cout << "Error: free boundary RGB color values should be within range 0..1!\n";
1915             return 1;
1916           }
1917           aChangeSet->FreeBoundaryColor.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
1918           break;
1919         }
1920         default:
1921         {
1922           std::cout << "Error: wrong syntax at " << anArg << "\n";
1923           return 1;
1924         }
1925       }
1926       aChangeSet->ToSetFreeBoundaryColor = 1;
1927       anArgIter += aNbComps;
1928     }
1929     else if (anArg == "-unsetfreeboundarycolor"
1930           || anArg == "-unsetfbcolor")
1931     {
1932       aChangeSet->ToSetFreeBoundaryColor = -1;
1933       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
1934     }
1935     else if (anArg == "-unset")
1936     {
1937       aChangeSet->ToSetVisibility = 1;
1938       aChangeSet->Visibility = 1;
1939       aChangeSet->ToSetLineWidth = -1;
1940       aChangeSet->LineWidth = 1.0;
1941       aChangeSet->ToSetTransparency = -1;
1942       aChangeSet->Transparency = 0.0;
1943       aChangeSet->ToSetColor = -1;
1944       aChangeSet->Color = DEFAULT_COLOR;
1945       aChangeSet->ToSetMaterial = -1;
1946       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
1947       aChangeSet->ToSetShowFreeBoundary = -1;
1948       aChangeSet->ToSetFreeBoundaryColor = -1;
1949       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
1950       aChangeSet->ToSetFreeBoundaryWidth = -1;
1951       aChangeSet->FreeBoundaryWidth = 1.0;
1952     }
1953     else
1954     {
1955       std::cout << "Error: wrong syntax at " << anArg << "\n";
1956       return 1;
1957     }
1958   }
1959
1960   Standard_Boolean isFirst = Standard_True;
1961   for (NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
1962        aChangesIter.More(); aChangesIter.Next())
1963   {
1964     if (!aChangesIter.Value().Validate (!isFirst))
1965     {
1966       return 1;
1967     }
1968     isFirst = Standard_False;
1969   }
1970
1971   if (aCtx->HasOpenedContext())
1972   {
1973     aCtx->CloseLocalContext();
1974   }
1975
1976   // special case for -defaults parameter.
1977   // all changed values will be set to DefaultDrawer.
1978   if (isDefaults)
1979   {
1980     const Handle(Prs3d_Drawer)& aDrawer = aCtx->DefaultDrawer();
1981
1982     if (aChangeSet->ToSetLineWidth != 0)
1983     {
1984       aDrawer->LineAspect()->SetWidth (aChangeSet->LineWidth);
1985       aDrawer->WireAspect()->SetWidth (aChangeSet->LineWidth);
1986       aDrawer->UnFreeBoundaryAspect()->SetWidth (aChangeSet->LineWidth);
1987       aDrawer->SeenLineAspect()->SetWidth (aChangeSet->LineWidth);
1988     }
1989     if (aChangeSet->ToSetColor != 0)
1990     {
1991       aDrawer->ShadingAspect()->SetColor        (aChangeSet->Color);
1992       aDrawer->LineAspect()->SetColor           (aChangeSet->Color);
1993       aDrawer->UnFreeBoundaryAspect()->SetColor (aChangeSet->Color);
1994       aDrawer->SeenLineAspect()->SetColor       (aChangeSet->Color);
1995       aDrawer->WireAspect()->SetColor           (aChangeSet->Color);
1996       aDrawer->PointAspect()->SetColor          (aChangeSet->Color);
1997     }
1998     if (aChangeSet->ToSetTransparency != 0)
1999     {
2000       aDrawer->ShadingAspect()->SetTransparency (aChangeSet->Transparency);
2001     }
2002     if (aChangeSet->ToSetMaterial != 0)
2003     {
2004       aDrawer->ShadingAspect()->SetMaterial (aChangeSet->Material);
2005     }
2006     if (aChangeSet->ToSetShowFreeBoundary == 1)
2007     {
2008       aDrawer->SetFreeBoundaryDraw (Standard_True);
2009     }
2010     else if (aChangeSet->ToSetShowFreeBoundary == -1)
2011     {
2012       aDrawer->SetFreeBoundaryDraw (Standard_False);
2013     }
2014     if (aChangeSet->ToSetFreeBoundaryWidth != 0)
2015     {
2016       aDrawer->FreeBoundaryAspect()->SetWidth (aChangeSet->FreeBoundaryWidth);
2017     }
2018     if (aChangeSet->ToSetFreeBoundaryColor != 0)
2019     {
2020       aDrawer->FreeBoundaryAspect()->SetColor (aChangeSet->FreeBoundaryColor);
2021     }
2022
2023     // redisplay all objects in context
2024     for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
2025     {
2026       Handle(AIS_InteractiveObject)  aPrs = aPrsIter.Current();
2027       if (!aPrs.IsNull())
2028       {
2029         aCtx->Redisplay (aPrs, Standard_False);
2030       }
2031     }
2032     return 0;
2033   }
2034
2035   for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
2036   {
2037     const TCollection_AsciiString& aName   = aPrsIter.CurrentName();
2038     Handle(AIS_InteractiveObject)  aPrs    = aPrsIter.Current();
2039     Handle(Prs3d_Drawer)           aDrawer = aPrs->Attributes();
2040     Handle(AIS_ColoredShape) aColoredPrs;
2041     Standard_Boolean toDisplay = Standard_False;
2042     Standard_Boolean toRedisplay = Standard_False;
2043     if (aChanges.Length() > 1 || aChangeSet->ToSetVisibility == 1)
2044     {
2045       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aPrs);
2046       if (aShapePrs.IsNull())
2047       {
2048         std::cout << "Error: an object " << aName << " is not an AIS_Shape presentation!\n";
2049         return 1;
2050       }
2051       aColoredPrs = Handle(AIS_ColoredShape)::DownCast (aShapePrs);
2052       if (aColoredPrs.IsNull())
2053       {
2054         aColoredPrs = new AIS_ColoredShape (aShapePrs);
2055         aCtx->Remove (aShapePrs, Standard_False);
2056         GetMapOfAIS().UnBind2 (aName);
2057         GetMapOfAIS().Bind (aColoredPrs, aName);
2058         toDisplay = Standard_True;
2059         aShapePrs = aColoredPrs;
2060         aPrs      = aColoredPrs;
2061       }
2062     }
2063
2064     if (!aPrs.IsNull())
2065     {
2066       NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
2067       aChangeSet = &aChangesIter.ChangeValue();
2068       if (aChangeSet->ToSetVisibility == 1)
2069       {
2070         Handle(AIS_ColoredDrawer) aColDrawer = aColoredPrs->CustomAspects (aColoredPrs->Shape());
2071         aColDrawer->SetHidden (aChangeSet->Visibility == 0);
2072       }
2073       else if (aChangeSet->ToSetMaterial == 1)
2074       {
2075         aCtx->SetMaterial (aPrs, aChangeSet->Material, Standard_False);
2076       }
2077       else if (aChangeSet->ToSetMaterial == -1)
2078       {
2079         aCtx->UnsetMaterial (aPrs, Standard_False);
2080       }
2081       if (aChangeSet->ToSetColor == 1)
2082       {
2083         aCtx->SetColor (aPrs, aChangeSet->Color, Standard_False);
2084       }
2085       else if (aChangeSet->ToSetColor == -1)
2086       {
2087         aCtx->UnsetColor (aPrs, Standard_False);
2088       }
2089       if (aChangeSet->ToSetTransparency == 1)
2090       {
2091         aCtx->SetTransparency (aPrs, aChangeSet->Transparency, Standard_False);
2092       }
2093       else if (aChangeSet->ToSetTransparency == -1)
2094       {
2095         aCtx->UnsetTransparency (aPrs, Standard_False);
2096       }
2097       if (aChangeSet->ToSetLineWidth == 1)
2098       {
2099         aCtx->SetWidth (aPrs, aChangeSet->LineWidth, Standard_False);
2100       }
2101       else if (aChangeSet->ToSetLineWidth == -1)
2102       {
2103         aCtx->UnsetWidth (aPrs, Standard_False);
2104       }
2105       if (!aDrawer.IsNull())
2106       {
2107         if (aChangeSet->ToSetShowFreeBoundary == 1)
2108         {
2109           aDrawer->SetFreeBoundaryDraw (Standard_True);
2110           toRedisplay = Standard_True;
2111         }
2112         else if (aChangeSet->ToSetShowFreeBoundary == -1)
2113         {
2114           aDrawer->SetFreeBoundaryDraw (Standard_False);
2115           toRedisplay = Standard_True;
2116         }
2117         if (aChangeSet->ToSetFreeBoundaryWidth != 0)
2118         {
2119           Handle(Prs3d_LineAspect) aBoundaryAspect =
2120               new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2121           *aBoundaryAspect->Aspect() = *aDrawer->FreeBoundaryAspect()->Aspect();
2122           aBoundaryAspect->SetWidth (aChangeSet->FreeBoundaryWidth);
2123           aDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2124           toRedisplay = Standard_True;
2125         }
2126         if (aChangeSet->ToSetFreeBoundaryColor != 0)
2127         {
2128           Handle(Prs3d_LineAspect) aBoundaryAspect =
2129               new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2130           *aBoundaryAspect->Aspect() = *aDrawer->FreeBoundaryAspect()->Aspect();
2131           aBoundaryAspect->SetColor (aChangeSet->FreeBoundaryColor);
2132           aDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2133           toRedisplay = Standard_True;
2134         }
2135       }
2136
2137       for (aChangesIter.Next(); aChangesIter.More(); aChangesIter.Next())
2138       {
2139         aChangeSet = &aChangesIter.ChangeValue();
2140         for (NCollection_Sequence<TopoDS_Shape>::Iterator aSubShapeIter (aChangeSet->SubShapes);
2141              aSubShapeIter.More(); aSubShapeIter.Next())
2142         {
2143           const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
2144           if (aChangeSet->ToSetVisibility == 1)
2145           {
2146             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
2147             aCurColDrawer->SetHidden (aChangeSet->Visibility == 0);
2148           }
2149           if (aChangeSet->ToSetColor == 1)
2150           {
2151             aColoredPrs->SetCustomColor (aSubShape, aChangeSet->Color);
2152           }
2153           if (aChangeSet->ToSetLineWidth == 1)
2154           {
2155             aColoredPrs->SetCustomWidth (aSubShape, aChangeSet->LineWidth);
2156           }
2157           if (aChangeSet->ToSetColor     == -1
2158            || aChangeSet->ToSetLineWidth == -1)
2159           {
2160             aColoredPrs->UnsetCustomAspects (aSubShape, Standard_True);
2161           }
2162         }
2163       }
2164       if (toDisplay)
2165       {
2166         aCtx->Display (aPrs, Standard_False);
2167       }
2168       if (toRedisplay)
2169       {
2170         aCtx->Redisplay (aPrs, Standard_False);
2171       }
2172       else if (!aColoredPrs.IsNull())
2173       {
2174         aCtx->Redisplay (aColoredPrs, Standard_False);
2175       }
2176     }
2177     else
2178     {
2179       Handle(NIS_InteractiveObject) aNisObj = Handle(NIS_InteractiveObject)::DownCast (aPrsIter.CurrentTrs());
2180       Handle(NIS_Triangulated)      aNisTri = Handle(NIS_Triangulated)::DownCast (aNisObj);
2181       if (!aNisObj.IsNull())
2182       {
2183         if (aChangeSet->ToSetTransparency != 0)
2184         {
2185           aNisObj->SetTransparency (aChangeSet->Transparency);
2186         }
2187       }
2188       if (!aNisTri.IsNull())
2189       {
2190         if (aChangeSet->ToSetColor != 0)
2191         {
2192           aNisTri->SetColor (aChangeSet->Color);
2193         }
2194         if (aChangeSet->ToSetLineWidth != 0)
2195         {
2196           aNisTri->SetLineWidth (aChangeSet->LineWidth);
2197         }
2198       }
2199     }
2200   }
2201   return 0;
2202 }
2203
2204 //==============================================================================
2205 //function : VDonly2
2206 //author   : ege
2207 //purpose  : Display only a selected or named  object
2208 //           if there is no selected or named object s, nothing is done
2209 //==============================================================================
2210 static int VDonly2 (Draw_Interpretor& ,
2211                     Standard_Integer  theArgNb,
2212                     const char**      theArgVec)
2213 {
2214   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2215   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2216   if (aCtx.IsNull())
2217   {
2218     std::cerr << "Error: no active view!\n";
2219     return 1;
2220   }
2221
2222   if (aCtx->HasOpenedContext())
2223   {
2224     aCtx->CloseLocalContext();
2225   }
2226
2227   Standard_Integer anArgIter = 1;
2228   for (; anArgIter < theArgNb; ++anArgIter)
2229   {
2230     if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
2231     {
2232       break;
2233     }
2234   }
2235
2236   NCollection_Map<Handle(Standard_Transient)> aDispSet;
2237   if (anArgIter >= theArgNb)
2238   {
2239     // display only selected objects
2240     if (aCtx->NbCurrents() < 1)
2241     {
2242       return 0;
2243     }
2244
2245     for (aCtx->InitCurrent(); aCtx->MoreCurrent(); aCtx->NextCurrent())
2246     {
2247       aDispSet.Add (aCtx->Current());
2248     }
2249   }
2250   else
2251   {
2252     // display only specified objects
2253     for (; anArgIter < theArgNb; ++anArgIter)
2254     {
2255       TCollection_AsciiString aName = theArgVec[anArgIter];
2256       if (GetMapOfAIS().IsBound2 (aName))
2257       {
2258         const Handle(Standard_Transient) anObj = GetMapOfAIS().Find2 (aName);
2259         if (anObj->IsKind (STANDARD_TYPE(AIS_InteractiveObject)))
2260         {
2261           const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anObj);
2262           aCtx->Display (aShape, Standard_False);
2263         }
2264         else if (anObj->IsKind (STANDARD_TYPE(NIS_InteractiveObject)))
2265         {
2266           Handle(NIS_InteractiveObject) aShape = Handle(NIS_InteractiveObject)::DownCast (anObj);
2267           TheNISContext()->Display (aShape);
2268         }
2269         aDispSet.Add (anObj);
2270       }
2271     }
2272   }
2273
2274   // weed out other objects
2275   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); anIter.More(); anIter.Next())
2276   {
2277     if (aDispSet.Contains (anIter.Key1()))
2278     {
2279       continue;
2280     }
2281
2282     if (anIter.Key1()->IsKind (STANDARD_TYPE(AIS_InteractiveObject)))
2283     {
2284       const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2285       aCtx->Erase (aShape, Standard_False);
2286     }
2287     else if (anIter.Key1()->IsKind (STANDARD_TYPE(NIS_InteractiveObject)))
2288     {
2289       const Handle(NIS_InteractiveObject) aShape = Handle(NIS_InteractiveObject)::DownCast (anIter.Key1());
2290       TheNISContext()->Erase (aShape);
2291     }
2292   }
2293   return 0;
2294 }
2295
2296 //==============================================================================
2297 //function : VRemove
2298 //purpose  : Removes selected or named objects.
2299 //           If there is no selected or named objects,
2300 //           all objects in the viewer can be removed with argument -all.
2301 //           If -context is in arguments, the object is not deleted from the map of
2302 //           objects (deleted only from the current context).
2303 //==============================================================================
2304 int VRemove (Draw_Interpretor& theDI,
2305              Standard_Integer  theArgNb,
2306              const char**      theArgVec)
2307 {
2308   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2309   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2310   if (aCtx.IsNull())
2311   {
2312     std::cerr << "Error: no active view!\n";
2313     return 1;
2314   }
2315
2316   Standard_Boolean isContextOnly = Standard_False;
2317   Standard_Boolean toRemoveAll   = Standard_False;
2318   Standard_Boolean toPrintInfo   = Standard_True;
2319   Standard_Boolean toRemoveLocal = Standard_False;
2320
2321   Standard_Integer anArgIter = 1;
2322   for (; anArgIter < theArgNb; ++anArgIter)
2323   {
2324     TCollection_AsciiString anArg = theArgVec[anArgIter];
2325     anArg.LowerCase();
2326     if (anArg == "-context")
2327     {
2328       isContextOnly = Standard_True;
2329     }
2330     else if (anArg == "-all")
2331     {
2332       toRemoveAll = Standard_True;
2333     }
2334     else if (anArg == "-noinfo")
2335     {
2336       toPrintInfo = Standard_False;
2337     }
2338     else if (anArg == "-local")
2339     {
2340       toRemoveLocal = Standard_True;
2341     }
2342     else if (anUpdateTool.parseRedrawMode (anArg))
2343     {
2344       continue;
2345     }
2346     else
2347     {
2348       break;
2349     }
2350   }
2351   if (toRemoveAll
2352    && anArgIter < theArgNb)
2353   {
2354     std::cerr << "Error: wrong syntax!\n";
2355     return 1;
2356   }
2357
2358   if (toRemoveLocal && !aCtx->HasOpenedContext())
2359   {
2360     std::cerr << "Error: local selection context is not open.\n";
2361     return 1;
2362   }
2363   else if (!toRemoveLocal && aCtx->HasOpenedContext())
2364   {
2365     aCtx->CloseAllContexts (Standard_False);
2366   }
2367
2368   NCollection_List<TCollection_AsciiString> anIONameList;
2369   if (toRemoveAll)
2370   {
2371     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2372          anIter.More(); anIter.Next())
2373     {
2374       anIONameList.Append (anIter.Key2());
2375     }
2376   }
2377   else if (anArgIter < theArgNb) // removed objects names are in argument list
2378   {
2379     for (; anArgIter < theArgNb; ++anArgIter)
2380     {
2381       TCollection_AsciiString aName = theArgVec[anArgIter];
2382       if (!GetMapOfAIS().IsBound2 (aName))
2383       {
2384         theDI << aName.ToCString() << " was not bound to some object.\n";
2385         continue;
2386       }
2387
2388       const Handle(Standard_Transient)& aTransientObj = GetMapOfAIS().Find2 (aName);
2389
2390       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (aTransientObj);
2391       if (!anIO.IsNull())
2392       {
2393         if (anIO->GetContext() != aCtx)
2394         {
2395           theDI << aName.ToCString() << " was not displayed in current context.\n";
2396           theDI << "Please activate view with this object displayed and try again.\n";
2397           continue;
2398         }
2399
2400         anIONameList.Append (aName);
2401         continue;
2402       }
2403
2404       const Handle(NIS_InteractiveObject) aNisIO = Handle(NIS_InteractiveObject)::DownCast (aTransientObj);
2405       if (!aNisIO.IsNull())
2406       {
2407         anIONameList.Append (aName);
2408       }
2409     }
2410   }
2411   else if (aCtx->NbCurrents() > 0
2412         || TheNISContext()->GetSelected().Extent() > 0)
2413   {
2414     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2415          anIter.More(); anIter.Next())
2416     {
2417       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2418       if (!anIO.IsNull())
2419       {
2420         if (!aCtx->IsCurrent (anIO))
2421         {
2422           continue;
2423         }
2424
2425         anIONameList.Append (anIter.Key2());
2426         continue;
2427       }
2428
2429       const Handle(NIS_InteractiveObject) aNisIO = Handle(NIS_InteractiveObject)::DownCast (anIter.Key1());
2430       if (!aNisIO.IsNull())
2431       {
2432         if (!TheNISContext()->IsSelected (aNisIO))
2433         {
2434           continue;
2435         }
2436
2437         anIONameList.Append (anIter.Key2());
2438       }
2439     }
2440   }
2441
2442   // Unbind all removed objects from the map of displayed IO.
2443   for (NCollection_List<TCollection_AsciiString>::Iterator anIter (anIONameList);
2444        anIter.More(); anIter.Next())
2445   {
2446     const Handle(AIS_InteractiveObject) anIO  = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anIter.Value()));
2447     if (!anIO.IsNull())
2448     {
2449       aCtx->Remove (anIO, Standard_False);
2450       if (toPrintInfo)
2451       {
2452         theDI << anIter.Value().ToCString() << " was removed\n";
2453       }
2454     }
2455     else
2456     {
2457       const Handle(NIS_InteractiveObject) aNisIO = Handle(NIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anIter.Value()));
2458       if (!aNisIO.IsNull())
2459       {
2460         TheNISContext()->Remove (aNisIO);
2461         if (toPrintInfo)
2462         {
2463           theDI << anIter.Value().ToCString() << " was removed\n";
2464         }
2465       }
2466     }
2467     if (!isContextOnly)
2468     {
2469       GetMapOfAIS().UnBind2 (anIter.Value());
2470     }
2471   }
2472
2473   // Close local context if it is empty
2474   TColStd_MapOfTransient aLocalIO;
2475   if (aCtx->HasOpenedContext()
2476    && !aCtx->LocalContext()->DisplayedObjects (aLocalIO))
2477   {
2478     aCtx->CloseAllContexts (Standard_False);
2479   }
2480
2481   return 0;
2482 }
2483
2484 //==============================================================================
2485 //function : VErase
2486 //purpose  : Erase some selected or named objects
2487 //           if there is no selected or named objects, the whole viewer is erased
2488 //==============================================================================
2489 int VErase (Draw_Interpretor& theDI,
2490             Standard_Integer  theArgNb,
2491             const char**      theArgVec)
2492 {
2493   const Handle(AIS_InteractiveContext)& aCtx  = ViewerTest::GetAISContext();
2494   const Handle(V3d_View)&               aView = ViewerTest::CurrentView();
2495   ViewerTest_AutoUpdater anUpdateTool (aCtx, aView);
2496   if (aCtx.IsNull())
2497   {
2498     std::cerr << "Error: no active view!\n";
2499     return 1;
2500   }
2501
2502   const Standard_Boolean toEraseAll = TCollection_AsciiString (theArgNb > 0 ? theArgVec[0] : "") == "veraseall";
2503
2504   Standard_Integer anArgIter = 1;
2505   Standard_Boolean toEraseLocal  = Standard_False;
2506   Standard_Boolean toEraseInView = Standard_False;
2507   TColStd_SequenceOfAsciiString aNamesOfEraseIO;
2508   for (; anArgIter < theArgNb; ++anArgIter)
2509   {
2510     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2511     anArgCase.LowerCase();
2512     if (anUpdateTool.parseRedrawMode (anArgCase))
2513     {
2514       continue;
2515     }
2516     else if (anArgCase == "-local")
2517     {
2518       toEraseLocal = Standard_True;
2519     }
2520     else if (anArgCase == "-view"
2521           || anArgCase == "-inview")
2522     {
2523       toEraseInView = Standard_True;
2524     }
2525     else
2526     {
2527       aNamesOfEraseIO.Append (theArgVec[anArgIter]);
2528     }
2529   }
2530
2531   if (!aNamesOfEraseIO.IsEmpty() && toEraseAll)
2532   {
2533     std::cerr << "Error: wrong syntax, " << theArgVec[0] << " too much arguments.\n";
2534     return 1;
2535   }
2536
2537   if (toEraseLocal && !aCtx->HasOpenedContext())
2538   {
2539     std::cerr << "Error: local selection context is not open.\n";
2540     return 1;
2541   }
2542   else if (!toEraseLocal && aCtx->HasOpenedContext())
2543   {
2544     aCtx->CloseAllContexts (Standard_False);
2545   }
2546
2547   if (!aNamesOfEraseIO.IsEmpty())
2548   {
2549     // Erase named objects
2550     for (Standard_Integer anIter = 1; anIter <= aNamesOfEraseIO.Length(); ++anIter)
2551     {
2552       TCollection_AsciiString aName = aNamesOfEraseIO.Value (anIter);
2553       if (!GetMapOfAIS().IsBound2 (aName))
2554       {
2555         continue;
2556       }
2557
2558       const Handle(Standard_Transient)    anObj = GetMapOfAIS().Find2 (aName);
2559       const Handle(AIS_InteractiveObject) anIO  = Handle(AIS_InteractiveObject)::DownCast (anObj);
2560       theDI << aName.ToCString() << " ";
2561       if (!anIO.IsNull())
2562       {
2563         if (toEraseInView)
2564         {
2565           aCtx->SetViewAffinity (anIO, aView, Standard_False);
2566         }
2567         else
2568         {
2569           aCtx->Erase (anIO, Standard_False);
2570         }
2571       }
2572       else
2573       {
2574         const Handle(NIS_InteractiveObject) aNisIO = Handle(NIS_InteractiveObject)::DownCast (anObj);
2575         if (!aNisIO.IsNull())
2576         {
2577           TheNISContext()->Erase (aNisIO);
2578         }
2579       }
2580     }
2581   }
2582   else if (!toEraseAll && aCtx->NbCurrents() > 0)
2583   {
2584     // Erase selected objects
2585     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2586          anIter.More(); anIter.Next())
2587     {
2588       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2589       if (!anIO.IsNull()
2590        && aCtx->IsCurrent (anIO))
2591       {
2592         theDI << anIter.Key2().ToCString() << " ";
2593         if (toEraseInView)
2594         {
2595           aCtx->SetViewAffinity (anIO, aView, Standard_False);
2596         }
2597         else
2598         {
2599           aCtx->Erase (anIO, Standard_False);
2600         }
2601       }
2602     }
2603   }
2604   else
2605   {
2606     // Erase all objects
2607     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2608          anIter.More(); anIter.Next())
2609     {
2610       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2611       if (!anIO.IsNull())
2612       {
2613         if (toEraseInView)
2614         {
2615           aCtx->SetViewAffinity (anIO, aView, Standard_False);
2616         }
2617         else
2618         {
2619           aCtx->Erase (anIO, Standard_False);
2620         }
2621       }
2622       else
2623       {
2624         const Handle(NIS_InteractiveObject) aNisIO = Handle(NIS_InteractiveObject)::DownCast (anIter.Key1());
2625         if (!aNisIO.IsNull())
2626         {
2627           TheNISContext()->Erase (aNisIO);
2628         }
2629       }
2630     }
2631   }
2632
2633   return 0;
2634 }
2635
2636 //==============================================================================
2637 //function : VDisplayAll
2638 //author   : ege
2639 //purpose  : Display all the objects of the Map
2640 //==============================================================================
2641 static int VDisplayAll (Draw_Interpretor& ,
2642                         Standard_Integer  theArgNb,
2643                         const char**      theArgVec)
2644
2645 {
2646   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2647   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2648   if (aCtx.IsNull())
2649   {
2650     std::cerr << "Error: no active view!\n";
2651     return 1;
2652   }
2653
2654   Standard_Integer anArgIter = 1;
2655   Standard_Boolean toDisplayLocal = Standard_False;
2656   for (; anArgIter < theArgNb; ++anArgIter)
2657   {
2658     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2659     anArgCase.LowerCase();
2660     if (anArgCase == "-local")
2661     {
2662       toDisplayLocal = Standard_True;
2663     }
2664     else if (anUpdateTool.parseRedrawMode (anArgCase))
2665     {
2666       continue;
2667     }
2668     else
2669     {
2670       break;
2671     }
2672   }
2673   if (anArgIter < theArgNb)
2674   {
2675     std::cout << theArgVec[0] << "Error: wrong syntax\n";
2676     return 1;
2677   }
2678
2679   if (toDisplayLocal && !aCtx->HasOpenedContext())
2680   {
2681     std::cerr << "Error: local selection context is not open.\n";
2682     return 1;
2683   }
2684   else if (!toDisplayLocal && aCtx->HasOpenedContext())
2685   {
2686     aCtx->CloseLocalContext (Standard_False);
2687   }
2688
2689   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2690        anIter.More(); anIter.Next())
2691   {
2692     if (anIter.Key1()->IsKind (STANDARD_TYPE(AIS_InteractiveObject)))
2693     {
2694       const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2695       aCtx->Erase (aShape, Standard_False);
2696     }
2697     else if (anIter.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject)))
2698     {
2699       const Handle(NIS_InteractiveObject) aShape = Handle(NIS_InteractiveObject)::DownCast (anIter.Key1());
2700       TheNISContext()->Erase (aShape);
2701     }
2702   }
2703
2704   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2705        anIter.More(); anIter.Next())
2706   {
2707     if (anIter.Key1()->IsKind (STANDARD_TYPE(AIS_InteractiveObject)))
2708     {
2709       const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2710       aCtx->Display (aShape, Standard_False);
2711     }
2712     else if (anIter.Key1()->IsKind (STANDARD_TYPE(NIS_InteractiveObject)))
2713     {
2714       Handle(NIS_InteractiveObject) aShape = Handle(NIS_InteractiveObject)::DownCast (anIter.Key1());
2715       TheNISContext()->Display (aShape);
2716     }
2717   }
2718   return 0;
2719 }
2720
2721 //! Auxiliary method to find presentation
2722 inline Handle(PrsMgr_Presentation) findPresentation (const Handle(AIS_InteractiveContext)& theCtx,
2723                                                      const Handle(AIS_InteractiveObject)&  theIO,
2724                                                      const Standard_Integer                theMode)
2725 {
2726   if (theIO.IsNull())
2727   {
2728     return Handle(PrsMgr_Presentation)();
2729   }
2730
2731   if (theMode != -1)
2732   {
2733     if (theCtx->MainPrsMgr()->HasPresentation (theIO, theMode))
2734     {
2735       return theCtx->MainPrsMgr()->Presentation (theIO, theMode);
2736     }
2737   }
2738   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theIO->DisplayMode()))
2739   {
2740     return theCtx->MainPrsMgr()->Presentation (theIO, theIO->DisplayMode());
2741   }
2742   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theCtx->DisplayMode()))
2743   {
2744     return theCtx->MainPrsMgr()->Presentation (theIO, theCtx->DisplayMode());
2745   }
2746   return Handle(PrsMgr_Presentation)();
2747 }
2748
2749 enum ViewerTest_BndAction
2750 {
2751   BndAction_Hide,
2752   BndAction_Show,
2753   BndAction_Print
2754 };
2755
2756 //! Auxiliary method to print bounding box of presentation
2757 inline void bndPresentation (Draw_Interpretor&                  theDI,
2758                              const Handle(PrsMgr_Presentation)& thePrs,
2759                              const TCollection_AsciiString&     theName,
2760                              const ViewerTest_BndAction         theAction)
2761 {
2762   switch (theAction)
2763   {
2764     case BndAction_Hide:
2765     {
2766       thePrs->Presentation()->GraphicUnHighlight();
2767       break;
2768     }
2769     case BndAction_Show:
2770     {
2771       Handle(Graphic3d_Structure) aPrs = thePrs->Presentation();
2772       aPrs->CStructure()->HighlightColor.r = 0.988235f;
2773       aPrs->CStructure()->HighlightColor.g = 0.988235f;
2774       aPrs->CStructure()->HighlightColor.b = 0.988235f;
2775       aPrs->CStructure()->HighlightWithBndBox (aPrs, Standard_True);
2776       break;
2777     }
2778     case BndAction_Print:
2779     {
2780       Bnd_Box aBox = thePrs->Presentation()->MinMaxValues();
2781       gp_Pnt aMin = aBox.CornerMin();
2782       gp_Pnt aMax = aBox.CornerMax();
2783       theDI << theName  << "\n"
2784             << aMin.X() << " " << aMin.Y() << " " << aMin.Z() << " "
2785             << aMax.X() << " " << aMax.Y() << " " << aMax.Z() << "\n";
2786       break;
2787     }
2788   }
2789 }
2790
2791 //==============================================================================
2792 //function : VBounding
2793 //purpose  :
2794 //==============================================================================
2795 int VBounding (Draw_Interpretor& theDI,
2796                Standard_Integer  theArgNb,
2797                const char**      theArgVec)
2798 {
2799   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2800   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2801   if (aCtx.IsNull())
2802   {
2803     std::cout << "Error: no active view!\n";
2804     return 1;
2805   }
2806
2807   ViewerTest_BndAction anAction = BndAction_Show;
2808   Standard_Integer     aMode    = -1;
2809
2810   Standard_Integer anArgIter = 1;
2811   for (; anArgIter < theArgNb; ++anArgIter)
2812   {
2813     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2814     anArg.LowerCase();
2815     if (anArg == "-print")
2816     {
2817       anAction = BndAction_Print;
2818     }
2819     else if (anArg == "-show")
2820     {
2821       anAction = BndAction_Show;
2822     }
2823     else if (anArg == "-hide")
2824     {
2825       anAction = BndAction_Hide;
2826     }
2827     else if (anArg == "-mode")
2828     {
2829       if (++anArgIter >= theArgNb)
2830       {
2831         std::cout << "Error: wrong syntax at " << anArg << "\n";
2832         return 1;
2833       }
2834       aMode = Draw::Atoi (theArgVec[anArgIter]);
2835     }
2836     else if (!anUpdateTool.parseRedrawMode (anArg))
2837     {
2838       break;
2839     }
2840   }
2841
2842   if (anArgIter < theArgNb)
2843   {
2844     // has a list of names
2845     for (; anArgIter < theArgNb; ++anArgIter)
2846     {
2847       TCollection_AsciiString aName = theArgVec[anArgIter];
2848       if (!GetMapOfAIS().IsBound2 (aName))
2849       {
2850         std::cout << "Error: presentation " << aName << " does not exist\n";
2851         return 1;
2852       }
2853
2854       Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
2855       Handle(PrsMgr_Presentation)   aPrs = findPresentation (aCtx, anIO, aMode);
2856       if (aPrs.IsNull())
2857       {
2858         std::cout << "Error: presentation " << aName << " does not exist\n";
2859         return 1;
2860       }
2861       bndPresentation (theDI, aPrs, aName, anAction);
2862     }
2863   }
2864   else if (aCtx->NbCurrents() > 0)
2865   {
2866     // remove all currently selected objects
2867     for (aCtx->InitCurrent(); aCtx->MoreCurrent(); aCtx->NextCurrent())
2868     {
2869       Handle(AIS_InteractiveObject) anIO = aCtx->Current();
2870       Handle(PrsMgr_Presentation)   aPrs = findPresentation (aCtx, anIO, aMode);
2871       if (!aPrs.IsNull())
2872       {
2873         bndPresentation (theDI, aPrs, GetMapOfAIS().IsBound1 (anIO) ? GetMapOfAIS().Find1 (anIO) : "", anAction);
2874       }
2875     }
2876   }
2877   else
2878   {
2879     // all objects
2880     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2881          anIter.More(); anIter.Next())
2882     {
2883       Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2884       Handle(PrsMgr_Presentation)   aPrs = findPresentation (aCtx, anIO, aMode);
2885       if (!aPrs.IsNull())
2886       {
2887         bndPresentation (theDI, aPrs, anIter.Key2(), anAction);
2888       }
2889     }
2890   }
2891   return 0;
2892 }
2893
2894 //==============================================================================
2895 //function : VTexture
2896 //purpose  :
2897 //==============================================================================
2898 Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgv)
2899 {
2900   TCollection_AsciiString aCommandName (theArgv[0]);
2901
2902   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
2903   if (aCommandName == "vtexture")
2904   {
2905     if (theArgsNb < 2)
2906     {
2907       std::cout << theArgv[0] << ": " << " invalid arguments.\n";
2908       std::cout << "Type help for more information.\n";
2909       return 1;
2910     }
2911
2912     // look for options of vtexture command
2913     TCollection_AsciiString aParseKey;
2914     for (Standard_Integer anArgIt = 2; anArgIt < theArgsNb; ++anArgIt)
2915     {
2916       TCollection_AsciiString anArg (theArgv [anArgIt]);
2917
2918       anArg.UpperCase();
2919       if (anArg.Value (1) == '-' && !anArg.IsRealValue())
2920       {
2921         aParseKey = anArg;
2922         aParseKey.Remove (1);
2923         aParseKey.UpperCase();
2924         aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
2925         continue;
2926       }
2927
2928       if (aParseKey.IsEmpty())
2929       {
2930         continue;
2931       }
2932
2933       aMapOfArgs(aParseKey)->Append (anArg);
2934     }
2935   }
2936   else if (aCommandName == "vtexscale"
2937         || aCommandName == "vtexorigin"
2938         || aCommandName == "vtexrepeat")
2939   {
2940     // scan for parameters of vtexscale, vtexorigin, vtexrepeat commands
2941     // equal to -scale, -origin, -repeat options of vtexture command
2942     if (theArgsNb < 2 || theArgsNb > 4)
2943     {
2944       std::cout << theArgv[0] << ": " << " invalid arguments.\n";
2945       std::cout << "Type help for more information.\n";
2946       return 1;
2947     }
2948
2949     Handle(TColStd_HSequenceOfAsciiString) anArgs = new TColStd_HSequenceOfAsciiString;
2950     if (theArgsNb == 2)
2951     {
2952       anArgs->Append ("OFF");
2953     }
2954     else if (theArgsNb == 4)
2955     {
2956       anArgs->Append (TCollection_AsciiString (theArgv[2]));
2957       anArgs->Append (TCollection_AsciiString (theArgv[3]));
2958     }
2959
2960     TCollection_AsciiString anArgKey;
2961     if (aCommandName == "vtexscale")
2962     {
2963       anArgKey = "SCALE";
2964     }
2965     else if (aCommandName == "vtexorigin")
2966     {
2967       anArgKey = "ORIGIN";
2968     }
2969     else
2970     {
2971       anArgKey = "REPEAT";
2972     }
2973
2974     aMapOfArgs.Bind (anArgKey, anArgs);
2975   }
2976   else if (aCommandName == "vtexdefault")
2977   {
2978     // scan for parameters of vtexdefault command
2979     // equal to -default option of vtexture command
2980     aMapOfArgs.Bind ("DEFAULT", new TColStd_HSequenceOfAsciiString);
2981   }
2982
2983   // Check arguments for validity
2984   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
2985   for (; aMapIt.More(); aMapIt.Next())
2986   {
2987     const TCollection_AsciiString& aKey = aMapIt.Key();
2988     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
2989
2990     // -scale, -origin, -repeat: one argument "off", or two real values
2991     if ((aKey.IsEqual ("SCALE") || aKey.IsEqual ("ORIGIN") || aKey.IsEqual ("REPEAT"))
2992       && ((anArgs->Length() == 1 && anArgs->Value(1) == "OFF")
2993        || (anArgs->Length() == 2 && anArgs->Value(1).IsRealValue() && anArgs->Value(2).IsRealValue())))
2994     {
2995       continue;
2996     }
2997
2998     // -modulate: single argument "on" / "off"
2999     if (aKey.IsEqual ("MODULATE") && anArgs->Length() == 1 && (anArgs->Value(1) == "OFF" || anArgs->Value(1) == "ON"))
3000     {
3001       continue;
3002     }
3003
3004     // -default: no arguments
3005     if (aKey.IsEqual ("DEFAULT") && anArgs->IsEmpty())
3006     {
3007       continue;
3008     }
3009
3010     TCollection_AsciiString aLowerKey;
3011     aLowerKey  = "-";
3012     aLowerKey += aKey;
3013     aLowerKey.LowerCase();
3014     std::cout << theArgv[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
3015     std::cout << "Type help for more information.\n";
3016     return 1;
3017   }
3018
3019   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
3020   if (anAISContext.IsNull())
3021   {
3022     std::cout << aCommandName << ": " << " please use 'vinit' command to initialize view.\n";
3023     return 1;
3024   }
3025
3026   Standard_Integer aPreviousMode = 0;
3027
3028   ViewerTest::CurrentView()->SetSurfaceDetail (V3d_TEX_ALL);
3029
3030   TCollection_AsciiString aShapeName (theArgv[1]);
3031   Handle(AIS_InteractiveObject) anIO;
3032
3033   const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfIO = GetMapOfAIS();
3034   if (aMapOfIO.IsBound2 (aShapeName))
3035   {
3036     anIO = Handle(AIS_InteractiveObject)::DownCast (aMapOfIO.Find2 (aShapeName));
3037   }
3038
3039   if (anIO.IsNull())
3040   {
3041     std::cout << aCommandName << ": shape " << aShapeName << " does not exists.\n";
3042     return 1;
3043   }
3044
3045   Handle(AIS_TexturedShape) aTexturedIO;
3046   if (anIO->IsKind (STANDARD_TYPE (AIS_TexturedShape)))
3047   {
3048     aTexturedIO = Handle(AIS_TexturedShape)::DownCast (anIO);
3049     aPreviousMode = aTexturedIO->DisplayMode();
3050   }
3051   else
3052   {
3053     anAISContext->Remove (anIO, Standard_False);
3054     aTexturedIO = new AIS_TexturedShape (DBRep::Get (theArgv[1]));
3055     GetMapOfAIS().UnBind1 (anIO);
3056     GetMapOfAIS().UnBind2 (aShapeName);
3057     GetMapOfAIS().Bind (aTexturedIO, aShapeName);
3058   }
3059
3060   // -------------------------------------------
3061   //  Turn texturing on/off - only for vtexture
3062   // -------------------------------------------
3063
3064   if (aCommandName == "vtexture")
3065   {
3066     TCollection_AsciiString aTextureArg (theArgsNb > 2 ? theArgv[2] : "");
3067
3068     if (aTextureArg.IsEmpty())
3069     {
3070       std::cout << aCommandName << ": " << " Texture mapping disabled.\n";
3071       std::cout << "To enable it, use 'vtexture NameOfShape NameOfTexture'\n" << "\n";
3072
3073       anAISContext->SetDisplayMode (aTexturedIO, AIS_Shaded, Standard_False);
3074       if (aPreviousMode == 3)
3075       {
3076         anAISContext->RecomputePrsOnly (aTexturedIO);
3077       }
3078
3079       anAISContext->Display (aTexturedIO, Standard_True);
3080       return 0;
3081     }
3082     else if (aTextureArg.Value(1) != '-') // "-option" on place of texture argument
3083     {
3084       if (aTextureArg == "?")
3085       {
3086         TCollection_AsciiString aTextureFolder = Graphic3d_TextureRoot::TexturesFolder();
3087
3088         theDi << "\n Files in current directory : \n" << "\n";
3089         theDi.Eval ("glob -nocomplain *");
3090
3091         TCollection_AsciiString aCmnd ("glob -nocomplain ");
3092         aCmnd += aTextureFolder;
3093         aCmnd += "/* ";
3094
3095         theDi << "Files in " << aTextureFolder.ToCString() << " : \n" << "\n";
3096         theDi.Eval (aCmnd.ToCString());
3097         return 0;
3098       }
3099       else
3100       {
3101         aTexturedIO->SetTextureFileName (aTextureArg);
3102       }
3103     }
3104   }
3105
3106   // ------------------------------------
3107   //  Process other options and commands
3108   // ------------------------------------
3109
3110   Handle(TColStd_HSequenceOfAsciiString) aValues;
3111   if (aMapOfArgs.Find ("DEFAULT", aValues))
3112   {
3113     aTexturedIO->SetTextureRepeat (Standard_False);
3114     aTexturedIO->SetTextureOrigin (Standard_False);
3115     aTexturedIO->SetTextureScale  (Standard_False);
3116     aTexturedIO->EnableTextureModulate();
3117   }
3118   else
3119   {
3120     if (aMapOfArgs.Find ("SCALE", aValues))
3121     {
3122       if (aValues->Value(1) != "OFF")
3123       {
3124         aTexturedIO->SetTextureScale (Standard_True, aValues->Value(1).RealValue(), aValues->Value(2).RealValue());
3125       }
3126       else
3127       {
3128         aTexturedIO->SetTextureScale (Standard_False);
3129       }
3130     }
3131
3132     if (aMapOfArgs.Find ("ORIGIN", aValues))
3133     {
3134       if (aValues->Value(1) != "OFF")
3135       {
3136         aTexturedIO->SetTextureOrigin (Standard_True, aValues->Value(1).RealValue(), aValues->Value(2).RealValue());
3137       }
3138       else
3139       {
3140         aTexturedIO->SetTextureOrigin (Standard_False);
3141       }
3142     }
3143
3144     if (aMapOfArgs.Find ("REPEAT", aValues))
3145     {
3146       if (aValues->Value(1) != "OFF")
3147       {
3148         aTexturedIO->SetTextureRepeat (Standard_True, aValues->Value(1).RealValue(), aValues->Value(2).RealValue());
3149       }
3150       else
3151       {
3152         aTexturedIO->SetTextureRepeat (Standard_False);
3153       }
3154     }
3155
3156     if (aMapOfArgs.Find ("MODULATE", aValues))
3157     {
3158       if (aValues->Value(1) == "ON")
3159       {
3160         aTexturedIO->EnableTextureModulate();
3161       }
3162       else
3163       {
3164         aTexturedIO->DisableTextureModulate();
3165       }
3166     }
3167   }
3168
3169   if (aTexturedIO->DisplayMode() == 3 || aPreviousMode == 3)
3170   {
3171     anAISContext->RecomputePrsOnly (aTexturedIO);
3172   }
3173   else
3174   {
3175     anAISContext->SetDisplayMode (aTexturedIO, 3, Standard_False);
3176     anAISContext->Display (aTexturedIO, Standard_True);
3177     anAISContext->Update (aTexturedIO,Standard_True);
3178   }
3179
3180   return 0;
3181 }
3182
3183 //! Auxiliary method to parse transformation persistence flags
3184 inline Standard_Boolean parseTrsfPersFlag (const TCollection_AsciiString& theFlagString,
3185                                            Standard_Integer&              theFlags)
3186 {
3187   if (theFlagString == "pan")
3188   {
3189     theFlags |= Graphic3d_TMF_PanPers;
3190   }
3191   else if (theFlagString == "zoom")
3192   {
3193     theFlags |= Graphic3d_TMF_ZoomPers;
3194   }
3195   else if (theFlagString == "rotate")
3196   {
3197     theFlags |= Graphic3d_TMF_RotatePers;
3198   }
3199   else if (theFlagString == "trihedron")
3200   {
3201     theFlags = Graphic3d_TMF_TriedronPers;
3202   }
3203   else if (theFlagString == "full")
3204   {
3205     theFlags = Graphic3d_TMF_FullPers;
3206   }
3207   else if (theFlagString == "none")
3208   {
3209     theFlags = Graphic3d_TMF_None;
3210   }
3211   else
3212   {
3213     return Standard_False;
3214   }
3215
3216   return Standard_True;
3217 }
3218
3219 //==============================================================================
3220 //function : VDisplay2
3221 //author   : ege
3222 //purpose  : Display an object from its name
3223 //==============================================================================
3224 static int VDisplay2 (Draw_Interpretor& theDI,
3225                       Standard_Integer  theArgNb,
3226                       const char**      theArgVec)
3227 {
3228   if (theArgNb < 2)
3229   {
3230     std::cerr << theArgVec[0] << "Error: wrong number of arguments.\n";
3231     return 1;
3232   }
3233
3234   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
3235   if (aCtx.IsNull())
3236   {
3237     ViewerTest::ViewerInit();
3238     aCtx = ViewerTest::GetAISContext();
3239   }
3240
3241   // Parse input arguments
3242   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
3243   Standard_Integer   isMutable      = -1;
3244   Graphic3d_ZLayerId aZLayer        = Graphic3d_ZLayerId_UNKNOWN;
3245   Standard_Boolean   toDisplayLocal = Standard_False;
3246   Standard_Boolean   toReDisplay    = Standard_False;
3247   Standard_Integer   isSelectable   = -1;
3248   Standard_Integer   anObjDispMode  = -2;
3249   Standard_Integer   anObjHighMode  = -2;
3250   Standard_Boolean   toSetTrsfPers  = Standard_False;
3251   Graphic3d_TransModeFlags aTrsfPersFlags = Graphic3d_TMF_None;
3252   gp_Pnt aTPPosition;
3253   TColStd_SequenceOfAsciiString aNamesOfDisplayIO;
3254   AIS_DisplayStatus aDispStatus = AIS_DS_None;
3255   Standard_Integer toDisplayInView = Standard_False;
3256   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3257   {
3258     const TCollection_AsciiString aName     = theArgVec[anArgIter];
3259     TCollection_AsciiString       aNameCase = aName;
3260     aNameCase.LowerCase();
3261     if (anUpdateTool.parseRedrawMode (aName))
3262     {
3263       continue;
3264     }
3265     else if (aNameCase == "-mutable")
3266     {
3267       isMutable = 1;
3268     }
3269     else if (aNameCase == "-neutral")
3270     {
3271       aDispStatus = AIS_DS_Displayed;
3272     }
3273     else if (aNameCase == "-immediate"
3274           || aNameCase == "-top")
3275     {
3276       aZLayer = Graphic3d_ZLayerId_Top;
3277     }
3278     else if (aNameCase == "-topmost")
3279     {
3280       aZLayer = Graphic3d_ZLayerId_Topmost;
3281     }
3282     else if (aNameCase == "-osd"
3283           || aNameCase == "-toposd"
3284           || aNameCase == "-overlay")
3285     {
3286       aZLayer = Graphic3d_ZLayerId_TopOSD;
3287     }
3288     else if (aNameCase == "-botosd"
3289           || aNameCase == "-underlay")
3290     {
3291       aZLayer = Graphic3d_ZLayerId_BotOSD;
3292     }
3293     else if (aNameCase == "-select"
3294           || aNameCase == "-selectable")
3295     {
3296       isSelectable = 1;
3297     }
3298     else if (aNameCase == "-noselect"
3299           || aNameCase == "-noselection")
3300     {
3301       isSelectable = 0;
3302     }
3303     else if (aNameCase == "-dispmode"
3304           || aNameCase == "-displaymode")
3305     {
3306       if (++anArgIter >= theArgNb)
3307       {
3308         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3309         return 1;
3310       }
3311
3312       anObjDispMode = Draw::Atoi (theArgVec [anArgIter]);
3313     }
3314     else if (aNameCase == "-highmode"
3315           || aNameCase == "-highlightmode")
3316     {
3317       if (++anArgIter >= theArgNb)
3318       {
3319         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3320         return 1;
3321       }
3322
3323       anObjHighMode = Draw::Atoi (theArgVec [anArgIter]);
3324     }
3325     else if (aNameCase == "-3d")
3326     {
3327       toSetTrsfPers  = Standard_True;
3328       aTrsfPersFlags = Graphic3d_TMF_None;
3329     }
3330     else if (aNameCase == "-2d")
3331     {
3332       toSetTrsfPers  = Standard_True;
3333       aTrsfPersFlags = Graphic3d_TMF_2d;
3334     }
3335     else if (aNameCase == "-2dtopdown")
3336     {
3337       toSetTrsfPers  = Standard_True;
3338       aTrsfPersFlags = Graphic3d_TMF_2d | Graphic3d_TMF_2d_IsTopDown;
3339     }
3340     else if (aNameCase == "-trsfpers"
3341           || aNameCase == "-pers")
3342     {
3343       if (++anArgIter >= theArgNb)
3344       {
3345         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3346         return 1;
3347       }
3348
3349       toSetTrsfPers  = Standard_True;
3350       aTrsfPersFlags = Graphic3d_TMF_None;
3351       TCollection_AsciiString aPersFlags (theArgVec [anArgIter]);
3352       aPersFlags.LowerCase();
3353       for (Standard_Integer aParserPos = aPersFlags.Search ("|");; aParserPos = aPersFlags.Search ("|"))
3354       {
3355         if (aParserPos == -1)
3356         {
3357           if (!parseTrsfPersFlag (aPersFlags, aTrsfPersFlags))
3358           {
3359             std::cerr << "Error: wrong transform persistence flags " << theArgVec [anArgIter] << ".\n";
3360             return 1;
3361           }
3362           break;
3363         }
3364
3365         TCollection_AsciiString anOtherFlags = aPersFlags.Split (aParserPos - 1);
3366         if (!parseTrsfPersFlag (aPersFlags, aTrsfPersFlags))
3367         {
3368           std::cerr << "Error: wrong transform persistence flags " << theArgVec [anArgIter] << ".\n";
3369           return 1;
3370         }
3371         aPersFlags = anOtherFlags;
3372       }
3373     }
3374     else if (aNameCase == "-trsfperspos"
3375           || aNameCase == "-perspos")
3376     {
3377       if (anArgIter + 2 >= theArgNb)
3378       {
3379         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3380         return 1;
3381       }
3382
3383       TCollection_AsciiString aX (theArgVec[++anArgIter]);
3384       TCollection_AsciiString aY (theArgVec[++anArgIter]);
3385       TCollection_AsciiString aZ = "0";
3386       if (!aX.IsIntegerValue()
3387        || !aY.IsIntegerValue())
3388       {
3389         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3390         return 1;
3391       }
3392       if (anArgIter + 1 < theArgNb)
3393       {
3394         TCollection_AsciiString aTemp = theArgVec[anArgIter + 1];
3395         if (aTemp.IsIntegerValue())
3396         {
3397           aZ = aTemp;
3398           ++anArgIter;
3399         }
3400       }
3401       aTPPosition.SetCoord (aX.IntegerValue(), aY.IntegerValue(), aZ.IntegerValue());
3402     }
3403     else if (aNameCase == "-layer")
3404     {
3405       if (++anArgIter >= theArgNb)
3406       {
3407         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3408         return 1;
3409       }
3410
3411       TCollection_AsciiString aValue (theArgVec[anArgIter]);
3412       if (!aValue.IsIntegerValue())
3413       {
3414         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3415         return 1;
3416       }
3417
3418       aZLayer = aValue.IntegerValue();
3419     }
3420     else if (aNameCase == "-view"
3421           || aNameCase == "-inview")
3422     {
3423       toDisplayInView = Standard_True;
3424     }
3425     else if (aNameCase == "-local")
3426     {
3427       aDispStatus = AIS_DS_Temporary;
3428       toDisplayLocal = Standard_True;
3429     }
3430     else if (aNameCase == "-redisplay")
3431     {
3432       toReDisplay = Standard_True;
3433     }
3434     else
3435     {
3436       aNamesOfDisplayIO.Append (aName);
3437     }
3438   }
3439
3440   if (aNamesOfDisplayIO.IsEmpty())
3441   {
3442     std::cerr << theArgVec[0] << "Error: wrong number of arguments.\n";
3443     return 1;
3444   }
3445
3446   // Prepare context for display
3447   if (toDisplayLocal && !aCtx->HasOpenedContext())
3448   {
3449     aCtx->OpenLocalContext (Standard_False);
3450   }
3451   else if (!toDisplayLocal && aCtx->HasOpenedContext())
3452   {
3453     aCtx->CloseAllContexts (Standard_False);
3454   }
3455
3456   // Display interactive objects
3457   for (Standard_Integer anIter = 1; anIter <= aNamesOfDisplayIO.Length(); ++anIter)
3458   {
3459     const TCollection_AsciiString& aName = aNamesOfDisplayIO.Value(anIter);
3460
3461     if (!GetMapOfAIS().IsBound2 (aName))
3462     {
3463       // create the AIS_Shape from a name
3464       const Handle(AIS_InteractiveObject) aShape = GetAISShapeFromName (aName.ToCString());
3465       if (!aShape.IsNull())
3466       {
3467         if (isMutable != -1)
3468         {
3469           aShape->SetMutable (isMutable == 1);
3470         }
3471         if (aZLayer != Graphic3d_ZLayerId_UNKNOWN)
3472         {
3473           aShape->SetZLayer (aZLayer);
3474         }
3475         if (toSetTrsfPers)
3476         {
3477           aShape->SetTransformPersistence (aTrsfPersFlags, aTPPosition);
3478         }
3479         if (anObjDispMode != -2)
3480         {
3481           aShape->SetDisplayMode (anObjDispMode);
3482         }
3483         if (anObjHighMode != -2)
3484         {
3485           aShape->SetHilightMode (anObjHighMode);
3486         }
3487         if (!toDisplayLocal)
3488           GetMapOfAIS().Bind (aShape, aName);
3489
3490         Standard_Integer aDispMode = aShape->HasDisplayMode()
3491                                    ? aShape->DisplayMode()
3492                                    : (aShape->AcceptDisplayMode (aCtx->DisplayMode())
3493                                     ? aCtx->DisplayMode()
3494                                     : 0);
3495         Standard_Integer aSelMode = -1;
3496         if ( isSelectable ==  1
3497          || (isSelectable == -1
3498           && aCtx->GetAutoActivateSelection()
3499           && aShape->GetTransformPersistenceMode() == 0))
3500         {
3501           aSelMode = aShape->HasSelectionMode() ? aShape->SelectionMode() : -1;
3502         }
3503
3504         aCtx->Display (aShape, aDispMode, aSelMode,
3505                        Standard_False, aShape->AcceptShapeDecomposition(),
3506                        aDispStatus);
3507         if (toDisplayInView)
3508         {
3509           for (aCtx->CurrentViewer()->InitDefinedViews(); aCtx->CurrentViewer()->MoreDefinedViews(); aCtx->CurrentViewer()->NextDefinedViews())
3510           {
3511             aCtx->SetViewAffinity (aShape, aCtx->CurrentViewer()->DefinedView(), Standard_False);
3512           }
3513           aCtx->SetViewAffinity (aShape, ViewerTest::CurrentView(), Standard_True);
3514         }
3515       }
3516       else
3517       {
3518         std::cerr << "Error: object with name '" << aName << "' does not exist!\n";
3519       }
3520       continue;
3521     }
3522
3523     Handle(Standard_Transient) anObj = GetMapOfAIS().Find2 (aName);
3524     if (anObj->IsKind (STANDARD_TYPE (AIS_InteractiveObject)))
3525     {
3526       Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anObj);
3527       if (isMutable != -1)
3528       {
3529         aShape->SetMutable (isMutable == 1);
3530       }
3531       if (aZLayer != Graphic3d_ZLayerId_UNKNOWN)
3532       {
3533         aShape->SetZLayer (aZLayer);
3534       }
3535       if (toSetTrsfPers)
3536       {
3537         aShape->SetTransformPersistence (aTrsfPersFlags, aTPPosition);
3538       }
3539       if (anObjDispMode != -2)
3540       {
3541         aShape->SetDisplayMode (anObjDispMode);
3542       }
3543       if (anObjHighMode != -2)
3544       {
3545         aShape->SetHilightMode (anObjHighMode);
3546       }
3547       Standard_Integer aDispMode = aShape->HasDisplayMode()
3548                                   ? aShape->DisplayMode()
3549                                   : (aShape->AcceptDisplayMode (aCtx->DisplayMode())
3550                                   ? aCtx->DisplayMode()
3551                                   : 0);
3552       Standard_Integer aSelMode = -1;
3553       if ( isSelectable ==  1
3554        || (isSelectable == -1
3555         && aCtx->GetAutoActivateSelection()
3556         && aShape->GetTransformPersistenceMode() == 0))
3557       {
3558         aSelMode = aShape->HasSelectionMode() ? aShape->SelectionMode() : -1;
3559       }
3560
3561       if (aShape->Type() == AIS_KOI_Datum)
3562       {
3563         aCtx->Display (aShape, Standard_False);
3564       }
3565       else
3566       {
3567         theDI << "Display " << aName.ToCString() << "\n";
3568
3569         // update the Shape in the AIS_Shape
3570         TopoDS_Shape      aNewShape = GetShapeFromName (aName.ToCString());
3571         Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(aShape);
3572         if (!aShapePrs.IsNull())
3573         {
3574           if (!aShapePrs->Shape().IsEqual (aNewShape))
3575           {
3576             toReDisplay = Standard_True;
3577           }
3578           aShapePrs->Set (aNewShape);
3579         }
3580         if (toReDisplay)
3581         {
3582           aCtx->Redisplay (aShape, Standard_False);
3583         }
3584
3585         if (aSelMode == -1)
3586         {
3587           aCtx->Erase (aShape);
3588         }
3589         aCtx->Display (aShape, aDispMode, aSelMode,
3590                        Standard_False, aShape->AcceptShapeDecomposition(),
3591                        aDispStatus);
3592         if (toDisplayInView)
3593         {
3594           aCtx->SetViewAffinity (aShape, ViewerTest::CurrentView(), Standard_True);
3595         }
3596       }
3597     }
3598     else if (anObj->IsKind (STANDARD_TYPE (NIS_InteractiveObject)))
3599     {
3600       Handle(NIS_InteractiveObject) aShape = Handle(NIS_InteractiveObject)::DownCast (anObj);
3601       TheNISContext()->Display (aShape);
3602     }
3603   }
3604
3605   return 0;
3606 }
3607
3608 //===============================================================================================
3609 //function : VUpdate
3610 //purpose  :
3611 //===============================================================================================
3612 static int VUpdate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
3613 {
3614   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
3615   if (aContextAIS.IsNull())
3616   {
3617     std::cout << theArgVec[0] << "AIS context is not available.\n";
3618     return 1;
3619   }
3620
3621   if (theArgsNb < 2)
3622   {
3623     std::cout << theArgVec[0] << ": insufficient arguments. Type help for more information.\n";
3624     return 1;
3625   }
3626
3627   const ViewerTest_DoubleMapOfInteractiveAndName& anAISMap = GetMapOfAIS();
3628
3629   AIS_ListOfInteractive aListOfIO;
3630
3631   for (int anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
3632   {
3633     TCollection_AsciiString aName = TCollection_AsciiString (theArgVec[anArgIt]);
3634
3635     Handle(AIS_InteractiveObject) anAISObj;
3636     if (anAISMap.IsBound2 (aName))
3637     {
3638       anAISObj = Handle(AIS_InteractiveObject)::DownCast (anAISMap.Find2 (aName));
3639     }
3640
3641     if (anAISObj.IsNull())
3642     {
3643       std::cout << theArgVec[0] << ": no AIS interactive object named \"" << aName << "\".\n";
3644       return 1;
3645     }
3646
3647     aListOfIO.Append (anAISObj);
3648   }
3649
3650   AIS_ListIteratorOfListOfInteractive anIOIt (aListOfIO);
3651   for (; anIOIt.More(); anIOIt.Next())
3652   {
3653     aContextAIS->Update (anIOIt.Value(), Standard_False);
3654   }
3655
3656   aContextAIS->UpdateCurrentViewer();
3657
3658   return 0;
3659 }
3660
3661 //==============================================================================
3662 //function : VPerf
3663 //purpose  : Test the annimation of an object along a
3664 //           predifined trajectory
3665 //Draw arg : vperf ShapeName 1/0(Transfo/Location) 1/0(Primitives sensibles ON/OFF)
3666 //==============================================================================
3667
3668 static int VPerf(Draw_Interpretor& di, Standard_Integer , const char** argv) {
3669
3670   OSD_Timer myTimer;
3671   if (TheAISContext()->HasOpenedContext())
3672     TheAISContext()->CloseLocalContext();
3673
3674   Standard_Real Step=4*M_PI/180;
3675   Standard_Real Angle=0;