d28ac98fa0fb9da668ba059ec2000e5fde55c617
[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 #include <Standard_Stream.hxx>
18
19 #include <ViewerTest.hxx>
20 #include <ViewerTest_CmdParser.hxx>
21
22 #include <Draw.hxx>
23 #include <TopLoc_Location.hxx>
24 #include <TopTools_HArray1OfShape.hxx>
25 #include <TColStd_HArray1OfTransient.hxx>
26 #include <TColStd_SequenceOfAsciiString.hxx>
27 #include <TColStd_HSequenceOfAsciiString.hxx>
28 #include <TColStd_MapOfTransient.hxx>
29 #include <OSD_Timer.hxx>
30 #include <Geom_Axis2Placement.hxx>
31 #include <Geom_Axis1Placement.hxx>
32 #include <gp_Trsf.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <BRepAdaptor_Curve.hxx>
35 #include <StdSelect_ShapeTypeFilter.hxx>
36 #include <AIS_ColoredShape.hxx>
37 #include <AIS_InteractiveObject.hxx>
38 #include <AIS_Trihedron.hxx>
39 #include <AIS_Axis.hxx>
40 #include <PrsDim.hxx>
41 #include <PrsDim_Relation.hxx>
42 #include <AIS_TypeFilter.hxx>
43 #include <AIS_SignatureFilter.hxx>
44 #include <AIS_ListOfInteractive.hxx>
45 #include <AIS_ListIteratorOfListOfInteractive.hxx>
46 #include <Aspect_InteriorStyle.hxx>
47 #include <Aspect_Window.hxx>
48 #include <Graphic3d_AspectFillArea3d.hxx>
49 #include <Graphic3d_AspectLine3d.hxx>
50 #include <Graphic3d_CStructure.hxx>
51 #include <Graphic3d_Texture2Dmanual.hxx>
52 #include <Graphic3d_GraphicDriver.hxx>
53 #include <Graphic3d_MediaTextureSet.hxx>
54 #include <Image_AlienPixMap.hxx>
55 #include <Message.hxx>
56 #include <OSD_File.hxx>
57 #include <Prs3d_Drawer.hxx>
58 #include <Prs3d_ShadingAspect.hxx>
59 #include <Prs3d_IsoAspect.hxx>
60 #include <Prs3d_PointAspect.hxx>
61 #include <Select3D_SensitiveWire.hxx>
62 #include <Select3D_SensitivePrimitiveArray.hxx>
63 #include <SelectMgr_EntityOwner.hxx>
64 #include <StdSelect_BRepOwner.hxx>
65 #include <StdSelect_ViewerSelector3d.hxx>
66 #include <TopTools_MapOfShape.hxx>
67 #include <ViewerTest_AutoUpdater.hxx>
68 #include <Aspect_XRSession.hxx>
69
70 #include <stdio.h>
71
72 #include <Draw_Interpretor.hxx>
73 #include <TCollection_AsciiString.hxx>
74 #include <Draw_PluginMacro.hxx>
75
76 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
77
78 #include <Quantity_Color.hxx>
79 #include <Quantity_NameOfColor.hxx>
80
81 #include <Graphic3d_NameOfMaterial.hxx>
82
83 #define DEFAULT_COLOR              Quantity_NOC_GOLDENROD
84 #define DEFAULT_FREEBOUNDARY_COLOR Quantity_NOC_GREEN
85 #define DEFAULT_MATERIAL           Graphic3d_NOM_BRASS
86
87 namespace
88 {
89
90   const Standard_Integer THE_MAX_INTEGER_COLOR_COMPONENT = 255;
91
92   const Standard_ShortReal THE_MAX_REAL_COLOR_COMPONENT = 1.0f;
93
94   //! Parses string and get an integer color component (only values within range 0 .. 255 are allowed)
95   //! @param theColorComponentString the string representing the color component
96   //! @param theIntegerColorComponent an integer color component that is a result of parsing
97   //! @return true if parsing was successful, or false otherwise
98   static bool parseNumericalColorComponent (const Standard_CString theColorComponentString,
99                                             Standard_Integer&      theIntegerColorComponent)
100   {
101     Standard_Integer anIntegerColorComponent;
102     if (!Draw::ParseInteger (theColorComponentString, anIntegerColorComponent))
103     {
104       return false;
105     }
106     if ((anIntegerColorComponent < 0) || (anIntegerColorComponent > THE_MAX_INTEGER_COLOR_COMPONENT))
107     {
108       return false;
109     }
110     theIntegerColorComponent = anIntegerColorComponent;
111     return true;
112   }
113
114   //! Parses the string and gets a real color component from it (only values within range 0.0 .. 1.0 are allowed)
115   //! @param theColorComponentString the string representing the color component
116   //! @param theRealColorComponent a real color component that is a result of parsing
117   //! @return true if parsing was successful, or false otherwise
118   static bool parseNumericalColorComponent (const Standard_CString theColorComponentString,
119                                             Standard_ShortReal&    theRealColorComponent)
120   {
121     Standard_Real aRealColorComponent;
122     if (!Draw::ParseReal (theColorComponentString, aRealColorComponent))
123     {
124       return false;
125     }
126     const Standard_ShortReal aShortRealColorComponent = static_cast<Standard_ShortReal> (aRealColorComponent);
127     if ((aShortRealColorComponent < 0.0f) || (aShortRealColorComponent > THE_MAX_REAL_COLOR_COMPONENT))
128     {
129       return false;
130     }
131     theRealColorComponent = aShortRealColorComponent;
132     return true;
133   }
134
135   //! Parses the string and gets a real color component from it (integer values 2 .. 255 are scaled to the 0.0 .. 1.0
136   //! range, values 0 and 1 are leaved as they are)
137   //! @param theColorComponentString the string representing the color component
138   //! @param theColorComponent a color component that is a result of parsing
139   //! @return true if parsing was successful, or false otherwise
140   static bool parseColorComponent (const Standard_CString theColorComponentString,
141                                    Standard_ShortReal&    theColorComponent)
142   {
143     Standard_Integer anIntegerColorComponent;
144     if (parseNumericalColorComponent (theColorComponentString, anIntegerColorComponent))
145     {
146       if (anIntegerColorComponent == 1)
147       {
148         theColorComponent = THE_MAX_REAL_COLOR_COMPONENT;
149       }
150       else
151       {
152         theColorComponent = anIntegerColorComponent * 1.0f / THE_MAX_INTEGER_COLOR_COMPONENT;
153       }
154       return true;
155     }
156     return parseNumericalColorComponent (theColorComponentString, theColorComponent);
157   }
158
159   //! Parses the array of strings and gets an integer color (only values within range 0 .. 255 are allowed and at least
160   //! one of components must be greater than 1)
161   //! @tparam TheNumber the type of resulting color vector elements
162   //! @param theNumberOfColorComponents the number of color components
163   //! @param theColorComponentStrings the array of strings representing color components
164   //! @param theNumericalColor a 4-component vector that is a result of parsing
165   //! @return true if parsing was successful, or false otherwise
166   template <typename TheNumber>
167   static bool parseNumericalColor (Standard_Integer&            theNumberOfColorComponents,
168                                    const char* const* const     theColorComponentStrings,
169                                    NCollection_Vec4<TheNumber>& theNumericalColor)
170   {
171     for (Standard_Integer aColorComponentIndex = 0; aColorComponentIndex < theNumberOfColorComponents;
172          ++aColorComponentIndex)
173     {
174       const char* const aColorComponentString = theColorComponentStrings[aColorComponentIndex];
175       TheNumber         aNumericalColorComponent;
176       if (parseNumericalColorComponent (aColorComponentString, aNumericalColorComponent))
177       {
178         theNumericalColor[aColorComponentIndex] = aNumericalColorComponent;
179       }
180       else
181       {
182         if (aColorComponentIndex == 3)
183         {
184           theNumberOfColorComponents = 3;
185         }
186         else
187         {
188           return false;
189         }
190       }
191     }
192     return true;
193   }
194
195   //! Parses an array of strings and get an integer color (only values within range 0 .. 255 are allowed and at least
196   //! one of components must be greater than 1)
197   //! @param theNumberOfColorComponents the number of color components
198   //! @param theColorComponentStrings the array of strings representing color components
199   //! @param theColor a color that is a result of parsing
200   //! @return true if parsing was successful, or false otherwise
201   static bool parseIntegerColor (Standard_Integer&        theNumberOfColorComponents,
202                                  const char* const* const theColorComponentStrings,
203                                  Quantity_ColorRGBA&      theColor)
204   {
205     const Standard_Integer THE_COLOR_COMPONENT_NOT_PARSED = -1;
206     Graphic3d_Vec4i        anIntegerColor (THE_COLOR_COMPONENT_NOT_PARSED);
207     if (!parseNumericalColor (theNumberOfColorComponents, theColorComponentStrings, anIntegerColor)
208       || anIntegerColor.maxComp() <= 1)
209     {
210       return false;
211     }
212     if (anIntegerColor.a() == THE_COLOR_COMPONENT_NOT_PARSED)
213     {
214       anIntegerColor.a() = THE_MAX_INTEGER_COLOR_COMPONENT;
215     }
216
217     const Graphic3d_Vec4 aRealColor = Graphic3d_Vec4 (anIntegerColor) / static_cast<Standard_ShortReal> (THE_MAX_INTEGER_COLOR_COMPONENT);
218     theColor = Quantity_ColorRGBA (Quantity_ColorRGBA::Convert_sRGB_To_LinearRGB (aRealColor));
219     return true;
220   }
221
222   //! Parses an array of strings and get a real color (only values within range 0.0 .. 1.0 are allowed)
223   //! @param theNumberOfColorComponents the number of color components
224   //! @param theColorComponentStrings the array of strings representing color components
225   //! @param theColor a color that is a result of parsing
226   //! @return true if parsing was successful, or false otherwise
227   static bool parseRealColor (Standard_Integer&        theNumberOfColorComponents,
228                               const char* const* const theColorComponentStrings,
229                               Quantity_ColorRGBA&      theColor)
230   {
231     Graphic3d_Vec4 aRealColor (THE_MAX_REAL_COLOR_COMPONENT);
232     if (!parseNumericalColor (theNumberOfColorComponents, theColorComponentStrings, aRealColor))
233     {
234       return false;
235     }
236     theColor = Quantity_ColorRGBA (aRealColor);
237     return true;
238   }
239
240 } // namespace
241
242 //=======================================================================
243 // function : GetColorFromName
244 // purpose  : get the Quantity_NameOfColor from a string
245 //=======================================================================
246
247 Quantity_NameOfColor ViewerTest::GetColorFromName (const Standard_CString theName)
248 {
249   Quantity_NameOfColor aColor = DEFAULT_COLOR;
250   Quantity_Color::ColorFromName (theName, aColor);
251   return aColor;
252 }
253
254 //=======================================================================
255 // function : parseColor
256 // purpose  :
257 //=======================================================================
258 Standard_Integer ViewerTest::parseColor (const Standard_Integer   theArgNb,
259                                          const char* const* const theArgVec,
260                                          Quantity_ColorRGBA&      theColor,
261                                          const bool               theToParseAlpha)
262 {
263   if ((theArgNb >= 1) && Quantity_ColorRGBA::ColorFromHex (theArgVec[0], theColor, !theToParseAlpha))
264   {
265     return 1;
266   }
267   if (theArgNb >= 1 && Quantity_ColorRGBA::ColorFromName (theArgVec[0], theColor))
268   {
269     if (theArgNb >= 2 && theToParseAlpha)
270     {
271       const Standard_CString anAlphaStr = theArgVec[1];
272       Standard_ShortReal     anAlphaComponent;
273       if (parseColorComponent (anAlphaStr, anAlphaComponent))
274       {
275         theColor.SetAlpha (anAlphaComponent);
276         return 2;
277       }
278     }
279     return 1;
280   }
281   if (theArgNb >= 3)
282   {
283     const Standard_Integer aNumberOfColorComponentsToParse = Min (theArgNb, theToParseAlpha ? 4 : 3);
284     Standard_Integer aNumberOfColorComponentsParsed = aNumberOfColorComponentsToParse;
285     if (parseIntegerColor (aNumberOfColorComponentsParsed, theArgVec, theColor))
286     {
287       return aNumberOfColorComponentsParsed;
288     }
289     aNumberOfColorComponentsParsed = aNumberOfColorComponentsToParse;
290     if (parseRealColor (aNumberOfColorComponentsParsed, theArgVec, theColor))
291     {
292       return aNumberOfColorComponentsParsed;
293     }
294     return 0;
295   }
296   return 0;
297 }
298
299 //=======================================================================
300 //function : ParseOnOff
301 //purpose  :
302 //=======================================================================
303 Standard_Boolean ViewerTest::ParseOnOff (Standard_CString  theArg,
304                                          Standard_Boolean& theIsOn)
305 {
306   TCollection_AsciiString aFlag(theArg);
307   aFlag.LowerCase();
308   if (aFlag == "on"
309    || aFlag == "1")
310   {
311     theIsOn = Standard_True;
312     return Standard_True;
313   }
314   else if (aFlag == "off"
315         || aFlag == "0")
316   {
317     theIsOn = Standard_False;
318     return Standard_True;
319   }
320   return Standard_False;
321 }
322
323 //=======================================================================
324 //function : GetSelectedShapes
325 //purpose  :
326 //=======================================================================
327 void ViewerTest::GetSelectedShapes (TopTools_ListOfShape& theSelectedShapes)
328 {
329   for (GetAISContext()->InitSelected(); GetAISContext()->MoreSelected(); GetAISContext()->NextSelected())
330   {
331     TopoDS_Shape aShape = GetAISContext()->SelectedShape();
332     if (!aShape.IsNull())
333     {
334       theSelectedShapes.Append (aShape);
335     }
336   }
337 }
338
339 //=======================================================================
340 //function : ParseLineType
341 //purpose  :
342 //=======================================================================
343 Standard_Boolean ViewerTest::ParseLineType (Standard_CString theArg,
344                                             Aspect_TypeOfLine& theType,
345                                             uint16_t& thePattern)
346 {
347   TCollection_AsciiString aTypeStr (theArg);
348   aTypeStr.LowerCase();
349   if (aTypeStr == "empty"
350    || aTypeStr == "-1")
351   {
352     theType = Aspect_TOL_EMPTY;
353     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
354   }
355   else if (aTypeStr == "solid"
356         || aTypeStr == "0")
357   {
358     theType = Aspect_TOL_SOLID;
359     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
360   }
361   else if (aTypeStr == "dot"
362         || aTypeStr == "2")
363   {
364     theType = Aspect_TOL_DOT;
365     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
366   }
367   else if (aTypeStr == "dash"
368         || aTypeStr == "1")
369   {
370     theType = Aspect_TOL_DASH;
371     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
372   }
373   else if (aTypeStr == "dotdash"
374         || aTypeStr == "3")
375   {
376     theType = Aspect_TOL_DOTDASH;
377     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
378   }
379   else
380   {
381     if (aTypeStr.StartsWith ("0x"))
382     {
383       aTypeStr = aTypeStr.SubString (3, aTypeStr.Length());
384     }
385
386     if (aTypeStr.Length() != 4
387     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (1)))
388     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (2)))
389     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (3)))
390     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (4))))
391     {
392       return Standard_False;
393     }
394
395     std::stringstream aStream;
396     aStream << std::setbase (16) << aTypeStr.ToCString();
397     if (aStream.fail())
398     {
399       return Standard_False;
400     }
401
402     Standard_Integer aNumber = -1;
403     aStream >> aNumber;
404     if (aStream.fail())
405     {
406       return Standard_False;
407     }
408
409     thePattern = (uint16_t )aNumber;
410     theType = Graphic3d_Aspects::DefaultLineTypeForPattern (thePattern);
411   }
412   return Standard_True;
413 }
414
415 //=======================================================================
416 //function : ParseMarkerType
417 //purpose  :
418 //=======================================================================
419 Standard_Boolean ViewerTest::ParseMarkerType (Standard_CString theArg,
420                                               Aspect_TypeOfMarker& theType,
421                                               Handle(Image_PixMap)& theImage)
422 {
423   theImage.Nullify();
424   TCollection_AsciiString aTypeStr (theArg);
425   aTypeStr.LowerCase();
426   if (aTypeStr == "empty")
427   {
428     theType = Aspect_TOM_EMPTY;
429   }
430   else if (aTypeStr == "point"
431         || aTypeStr == "dot"
432         || aTypeStr == ".")
433   {
434     theType = Aspect_TOM_POINT;
435   }
436   else if (aTypeStr == "plus"
437         || aTypeStr == "+")
438   {
439     theType = Aspect_TOM_PLUS;
440   }
441   else if (aTypeStr == "star"
442         || aTypeStr == "*")
443   {
444     theType = Aspect_TOM_STAR;
445   }
446   else if (aTypeStr == "cross"
447         || aTypeStr == "x")
448   {
449     theType = Aspect_TOM_X;
450   }
451   else if (aTypeStr == "circle"
452         || aTypeStr == "o")
453   {
454     theType = Aspect_TOM_O;
455   }
456   else if (aTypeStr == "pointincircle")
457   {
458     theType = Aspect_TOM_O_POINT;
459   }
460   else if (aTypeStr == "plusincircle")
461   {
462     theType = Aspect_TOM_O_PLUS;
463   }
464   else if (aTypeStr == "starincircle")
465   {
466     theType = Aspect_TOM_O_STAR;
467   }
468   else if (aTypeStr == "crossincircle"
469         || aTypeStr == "xcircle")
470   {
471     theType = Aspect_TOM_O_X;
472   }
473   else if (aTypeStr == "ring1")
474   {
475     theType = Aspect_TOM_RING1;
476   }
477   else if (aTypeStr == "ring2")
478   {
479     theType = Aspect_TOM_RING2;
480   }
481   else if (aTypeStr == "ring"
482         || aTypeStr == "ring3")
483   {
484     theType = Aspect_TOM_RING3;
485   }
486   else if (aTypeStr == "ball")
487   {
488     theType = Aspect_TOM_BALL;
489   }
490   else if (aTypeStr.IsIntegerValue())
491   {
492     const int aTypeInt = aTypeStr.IntegerValue();
493     if (aTypeInt < -1 || aTypeInt >= Aspect_TOM_USERDEFINED)
494     {
495       return Standard_False;
496     }
497     theType = (Aspect_TypeOfMarker )aTypeInt;
498   }
499   else
500   {
501     theType = Aspect_TOM_USERDEFINED;
502     Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
503     if (!anImage->Load (theArg))
504     {
505       return Standard_False;
506     }
507     if (anImage->Format() == Image_Format_Gray)
508     {
509       anImage->SetFormat (Image_Format_Alpha);
510     }
511     else if (anImage->Format() == Image_Format_GrayF)
512     {
513       anImage->SetFormat (Image_Format_AlphaF);
514     }
515     theImage = anImage;
516   }
517   return Standard_True;
518 }
519
520 //=======================================================================
521 //function : ParseShadingModel
522 //purpose  :
523 //=======================================================================
524 Standard_Boolean ViewerTest::ParseShadingModel (Standard_CString              theArg,
525                                                 Graphic3d_TypeOfShadingModel& theModel)
526 {
527   TCollection_AsciiString aTypeStr (theArg);
528   aTypeStr.LowerCase();
529   if (aTypeStr == "unlit"
530    || aTypeStr == "color"
531    || aTypeStr == "none")
532   {
533     theModel = Graphic3d_TOSM_UNLIT;
534   }
535   else if (aTypeStr == "flat"
536         || aTypeStr == "facet")
537   {
538     theModel = Graphic3d_TOSM_FACET;
539   }
540   else if (aTypeStr == "gouraud"
541         || aTypeStr == "vertex"
542         || aTypeStr == "vert")
543   {
544     theModel = Graphic3d_TOSM_VERTEX;
545   }
546   else if (aTypeStr == "phong"
547         || aTypeStr == "fragment"
548         || aTypeStr == "frag"
549         || aTypeStr == "pixel")
550   {
551     theModel = Graphic3d_TOSM_FRAGMENT;
552   }
553   else if (aTypeStr == "pbr")
554   {
555     theModel = Graphic3d_TOSM_PBR;
556   }
557   else if (aTypeStr == "pbr_facet")
558   {
559     theModel = Graphic3d_TOSM_PBR_FACET;
560   }
561   else if (aTypeStr == "default"
562         || aTypeStr == "def")
563   {
564     theModel = Graphic3d_TOSM_DEFAULT;
565   }
566   else if (aTypeStr.IsIntegerValue())
567   {
568     const int aTypeInt = aTypeStr.IntegerValue();
569     if (aTypeInt <= Graphic3d_TOSM_DEFAULT || aTypeInt >= Graphic3d_TypeOfShadingModel_NB)
570     {
571       return Standard_False;
572     }
573     theModel = (Graphic3d_TypeOfShadingModel)aTypeInt;
574   }
575   else
576   {
577     return Standard_False;
578   }
579   return Standard_True;
580 }
581
582 //=======================================================================
583 //function : parseZLayer
584 //purpose  :
585 //=======================================================================
586 Standard_Boolean ViewerTest::parseZLayer (Standard_CString theArg,
587                                           Standard_Boolean theToAllowInteger,
588                                           Graphic3d_ZLayerId& theLayer)
589 {
590   TCollection_AsciiString aName (theArg);
591   aName.LowerCase();
592   if (aName == "default"
593    || aName == "def")
594   {
595     theLayer = Graphic3d_ZLayerId_Default;
596   }
597   else if (aName == "top")
598   {
599     theLayer = Graphic3d_ZLayerId_Top;
600   }
601   else if (aName == "topmost")
602   {
603     theLayer = Graphic3d_ZLayerId_Topmost;
604   }
605   else if (aName == "overlay"
606         || aName == "toposd")
607   {
608     theLayer = Graphic3d_ZLayerId_TopOSD;
609   }
610   else if (aName == "underlay"
611         || aName == "botosd")
612   {
613     theLayer = Graphic3d_ZLayerId_BotOSD;
614   }
615   else if (aName == "undefined")
616   {
617     theLayer = Graphic3d_ZLayerId_UNKNOWN;
618   }
619   else if (!GetAISContext().IsNull())
620   {
621     const Handle(V3d_Viewer)& aViewer = ViewerTest::GetAISContext()->CurrentViewer();
622     TColStd_SequenceOfInteger aLayers;
623     aViewer->GetAllZLayers (aLayers);
624     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
625     {
626       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
627       if (TCollection_AsciiString::IsSameString (aSettings.Name(), aName, Standard_False))
628       {
629         theLayer = aLayeriter.Value();
630         return true;
631       }
632     }
633
634     if (!theToAllowInteger
635      || !aName.IsIntegerValue())
636     {
637       return false;
638     }
639     Graphic3d_ZLayerId aLayer = aName.IntegerValue();
640     if (aLayer == Graphic3d_ZLayerId_UNKNOWN
641      || std::find (aLayers.begin(), aLayers.end(), aLayer) != aLayers.end())
642     {
643       theLayer = aLayer;
644       return true;
645     }
646     return false;
647   }
648   return true;
649 }
650
651 //=======================================================================
652 //function : GetTypeNames
653 //purpose  :
654 //=======================================================================
655 static const char** GetTypeNames()
656 {
657   static const char* names[14] = {"Point","Axis","Trihedron","PlaneTrihedron", "Line","Circle","Plane",
658                           "Shape","ConnectedShape","MultiConn.Shape",
659                           "ConnectedInter.","MultiConn.",
660                           "Constraint","Dimension"};
661   static const char** ThePointer = names;
662   return ThePointer;
663 }
664
665 //=======================================================================
666 //function : GetTypeAndSignfromString
667 //purpose  :
668 //=======================================================================
669 void GetTypeAndSignfromString (const char* name,AIS_KindOfInteractive& TheType,Standard_Integer& TheSign)
670 {
671   const char ** thefullnames = GetTypeNames();
672   Standard_Integer index(-1);
673
674   for(Standard_Integer i=0;i<=13 && index==-1;i++)
675     if(!strcasecmp(name,thefullnames[i]))
676       index = i;
677
678   if(index ==-1){
679     TheType = AIS_KOI_None;
680     TheSign = -1;
681     return;
682   }
683
684   if(index<=6){
685     TheType = AIS_KOI_Datum;
686     TheSign = index+1;
687   }
688   else if (index <=9){
689     TheType = AIS_KOI_Shape;
690     TheSign = index-7;
691   }
692   else if(index<=11){
693     TheType = AIS_KOI_Object;
694     TheSign = index-10;
695   }
696   else{
697     TheType = AIS_KOI_Relation;
698     TheSign = index-12;
699   }
700
701 }
702
703
704
705 #include <string.h>
706 #include <Draw_Interpretor.hxx>
707 #include <Draw.hxx>
708 #include <Draw_Appli.hxx>
709 #include <DBRep.hxx>
710
711
712 #include <TCollection_AsciiString.hxx>
713 #include <V3d_Viewer.hxx>
714 #include <V3d_View.hxx>
715 #include <V3d.hxx>
716
717 #include <AIS_InteractiveContext.hxx>
718 #include <AIS_Shape.hxx>
719 #include <AIS_DisplayMode.hxx>
720 #include <TColStd_MapOfInteger.hxx>
721 #include <AIS_MapOfInteractive.hxx>
722 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
723 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
724 #include <ViewerTest_EventManager.hxx>
725
726 #include <TopoDS_Solid.hxx>
727 #include <BRepTools.hxx>
728 #include <BRep_Builder.hxx>
729 #include <TopAbs_ShapeEnum.hxx>
730
731 #include <TopoDS.hxx>
732 #include <BRep_Tool.hxx>
733
734
735 #include <Draw_Window.hxx>
736 #include <AIS_ListIteratorOfListOfInteractive.hxx>
737 #include <AIS_ListOfInteractive.hxx>
738 #include <AIS_DisplayMode.hxx>
739 #include <TopTools_ListOfShape.hxx>
740 #include <BRepOffsetAPI_MakeThickSolid.hxx>
741
742 //==============================================================================
743 //  VIEWER OBJECT MANAGEMENT GLOBAL VARIABLES
744 //==============================================================================
745 Standard_EXPORT ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(){
746   static ViewerTest_DoubleMapOfInteractiveAndName TheMap;
747   return TheMap;
748 }
749
750 //=======================================================================
751 //function : Display
752 //purpose  :
753 //=======================================================================
754 Standard_Boolean ViewerTest::Display (const TCollection_AsciiString&       theName,
755                                       const Handle(AIS_InteractiveObject)& theObject,
756                                       const Standard_Boolean               theToUpdate,
757                                       const Standard_Boolean               theReplaceIfExists)
758 {
759   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
760   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
761   if (aCtx.IsNull())
762   {
763     Message::SendFail ("Error: AIS context is not available.");
764     return Standard_False;
765   }
766
767   if (aMap.IsBound2 (theName))
768   {
769     if (!theReplaceIfExists)
770     {
771       Message::SendFail() << "Error: other interactive object has been already registered with name: " << theName << ".\n"
772                           << "Please use another name.";
773       return Standard_False;
774     }
775
776     if (Handle(AIS_InteractiveObject) anOldObj = aMap.Find2 (theName))
777     {
778       aCtx->Remove (anOldObj, theObject.IsNull() && theToUpdate);
779     }
780     aMap.UnBind2 (theName);
781   }
782
783   if (theObject.IsNull())
784   {
785     // object with specified name has been already unbound
786     return Standard_True;
787   }
788
789   // unbind AIS object if it was bound with another name
790   aMap.UnBind1 (theObject);
791
792   // can be registered without rebinding
793   aMap.Bind (theObject, theName);
794   aCtx->Display (theObject, theToUpdate);
795   return Standard_True;
796 }
797
798 //! Alias for ViewerTest::Display(), compatibility with old code.
799 Standard_EXPORT Standard_Boolean VDisplayAISObject (const TCollection_AsciiString&       theName,
800                                                     const Handle(AIS_InteractiveObject)& theObject,
801                                                     Standard_Boolean theReplaceIfExists = Standard_True)
802 {
803   return ViewerTest::Display (theName, theObject, Standard_True, theReplaceIfExists);
804 }
805
806 static NCollection_List<Handle(ViewerTest_EventManager)> theEventMgrs;
807
808 static Handle(V3d_View)&  a3DView()
809 {
810   static Handle(V3d_View) Viou;
811   return Viou;
812 }
813
814
815 Standard_EXPORT Handle(AIS_InteractiveContext)& TheAISContext(){
816   static Handle(AIS_InteractiveContext) aContext;
817   return aContext;
818 }
819
820 const Handle(V3d_View)& ViewerTest::CurrentView()
821 {
822   return a3DView();
823 }
824 void ViewerTest::CurrentView(const Handle(V3d_View)& V)
825 {
826   a3DView() = V;
827 }
828
829 const Handle(AIS_InteractiveContext)& ViewerTest::GetAISContext()
830 {
831   return TheAISContext();
832 }
833
834 void ViewerTest::SetAISContext (const Handle(AIS_InteractiveContext)& aCtx)
835 {
836   TheAISContext() = aCtx;
837   ViewerTest::ResetEventManager();
838 }
839
840 Handle(V3d_Viewer) ViewerTest::GetViewerFromContext()
841 {
842   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
843 }
844
845 Handle(V3d_Viewer) ViewerTest::GetCollectorFromContext()
846 {
847   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
848 }
849
850
851 void ViewerTest::SetEventManager(const Handle(ViewerTest_EventManager)& EM){
852   theEventMgrs.Prepend(EM);
853 }
854
855 void ViewerTest::UnsetEventManager()
856 {
857   theEventMgrs.RemoveFirst();
858 }
859
860
861 void ViewerTest::ResetEventManager()
862 {
863   theEventMgrs.Clear();
864   theEventMgrs.Prepend (new ViewerTest_EventManager (ViewerTest::CurrentView(), ViewerTest::GetAISContext()));
865 }
866
867 Handle(ViewerTest_EventManager) ViewerTest::CurrentEventManager()
868 {
869   return !theEventMgrs.IsEmpty()
870         ? theEventMgrs.First()
871         : Handle(ViewerTest_EventManager)();
872 }
873
874 //=======================================================================
875 //function : Get Context and active view
876 //purpose  :
877 //=======================================================================
878 static Standard_Boolean getCtxAndView (Handle(AIS_InteractiveContext)& theCtx,
879                                        Handle(V3d_View)&               theView)
880 {
881   theCtx  = ViewerTest::GetAISContext();
882   theView = ViewerTest::CurrentView();
883   if (theCtx.IsNull()
884    || theView.IsNull())
885   {
886     Message::SendFail ("Error: cannot find an active view!");
887     return Standard_False;
888   }
889   return Standard_True;
890 }
891
892 //==============================================================================
893 //function : Clear
894 //purpose  : Remove all the object from the viewer
895 //==============================================================================
896 void ViewerTest::Clear()
897 {
898   if (a3DView().IsNull())
899   {
900     return;
901   }
902
903   NCollection_Sequence<Handle(AIS_InteractiveObject)> aListRemoved;
904   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS()); anObjIter.More(); anObjIter.Next())
905   {
906     const Handle(AIS_InteractiveObject) anObj = anObjIter.Key1();
907     if (anObj->GetContext() != TheAISContext())
908     {
909       continue;
910     }
911
912     Message::SendInfo() << "Remove " << anObjIter.Key2();
913     TheAISContext()->Remove (anObj, Standard_False);
914     aListRemoved.Append (anObj);
915   }
916
917   TheAISContext()->RebuildSelectionStructs();
918   TheAISContext()->UpdateCurrentViewer();
919   if (aListRemoved.Size() == GetMapOfAIS().Extent())
920   {
921     GetMapOfAIS().Clear();
922   }
923   else
924   {
925     for (NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator anObjIter (aListRemoved); anObjIter.More(); anObjIter.Next())
926     {
927       GetMapOfAIS().UnBind1 (anObjIter.Value());
928     }
929   }
930 }
931
932 //==============================================================================
933 //function : CopyIsoAspect
934 //purpose  : Returns copy Prs3d_IsoAspect with new number of isolines.
935 //==============================================================================
936 static Handle(Prs3d_IsoAspect) CopyIsoAspect
937       (const Handle(Prs3d_IsoAspect) &theIsoAspect,
938        const Standard_Integer theNbIsos)
939 {
940   Quantity_Color    aColor = theIsoAspect->Aspect()->Color();
941   Aspect_TypeOfLine aType  = theIsoAspect->Aspect()->Type();
942   Standard_Real     aWidth = theIsoAspect->Aspect()->Width();
943
944   Handle(Prs3d_IsoAspect) aResult =
945     new Prs3d_IsoAspect(aColor, aType, aWidth, theNbIsos);
946
947   return aResult;
948 }
949
950 //==============================================================================
951 //function : visos
952 //purpose  : Returns or sets the number of U- and V- isos and isIsoOnPlane flag
953 //Draw arg : [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]
954 //==============================================================================
955 static int visos (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
956 {
957   if (TheAISContext().IsNull()) {
958     di << argv[0] << " Call 'vinit' before!\n";
959     return 1;
960   }
961
962   if (argc <= 1) {
963     di << "Current number of isos : " <<
964       TheAISContext()->IsoNumber(AIS_TOI_IsoU) << " " <<
965       TheAISContext()->IsoNumber(AIS_TOI_IsoV) << "\n";
966     di << "IsoOnPlane mode is " <<
967       (TheAISContext()->IsoOnPlane() ? "ON" : "OFF") << "\n";
968     di << "IsoOnTriangulation mode is " <<
969       (TheAISContext()->IsoOnTriangulation() ? "ON" : "OFF") << "\n";
970     return 0;
971   }
972
973   Standard_Integer aLastInd = argc - 1;
974   Standard_Boolean isChanged = Standard_False;
975   Standard_Integer aNbUIsos = 0;
976   Standard_Integer aNbVIsos = 0;
977
978   if (aLastInd >= 3) {
979     Standard_Boolean isIsoOnPlane = Standard_False;
980
981     if (strcmp(argv[aLastInd], "1") == 0) {
982       isIsoOnPlane = Standard_True;
983       isChanged    = Standard_True;
984     } else if (strcmp(argv[aLastInd], "0") == 0) {
985       isIsoOnPlane = Standard_False;
986       isChanged    = Standard_True;
987     }
988
989     if (isChanged) {
990       aNbVIsos = Draw::Atoi(argv[aLastInd - 1]);
991       aNbUIsos = Draw::Atoi(argv[aLastInd - 2]);
992       aLastInd -= 3;
993
994       di << "New number of isos : " << aNbUIsos << " " << aNbVIsos << "\n";
995       di << "New IsoOnPlane mode is " << (isIsoOnPlane ? "ON" : "OFF") << "\n";
996
997       TheAISContext()->IsoOnPlane(isIsoOnPlane);
998
999       if (aLastInd == 0) {
1000         // If there are no shapes provided set the default numbers.
1001         TheAISContext()->SetIsoNumber(aNbUIsos, AIS_TOI_IsoU);
1002         TheAISContext()->SetIsoNumber(aNbVIsos, AIS_TOI_IsoV);
1003       }
1004     }
1005   }
1006
1007   Standard_Integer i;
1008
1009   for (i = 1; i <= aLastInd; i++)
1010   {
1011     TCollection_AsciiString name(argv[i]);
1012     Handle(AIS_InteractiveObject) aShape;
1013     GetMapOfAIS().Find2(name, aShape);
1014     if (aShape.IsNull())
1015     {
1016       Message::SendFail() << "Syntax error: object '" << name << "' is not found";
1017       return 1;
1018     }
1019
1020     Handle(Prs3d_Drawer) CurDrawer = aShape->Attributes();
1021     Handle(Prs3d_IsoAspect) aUIso = CurDrawer->UIsoAspect();
1022     Handle(Prs3d_IsoAspect) aVIso = CurDrawer->VIsoAspect();
1023     if (isChanged)
1024     {
1025       CurDrawer->SetUIsoAspect(CopyIsoAspect(aUIso, aNbUIsos));
1026       CurDrawer->SetVIsoAspect(CopyIsoAspect(aVIso, aNbVIsos));
1027       TheAISContext()->SetLocalAttributes (aShape, CurDrawer, Standard_False);
1028       TheAISContext()->Redisplay (aShape, Standard_False);
1029     }
1030     else
1031     {
1032       di << "Number of isos for " << argv[i] << " : "
1033           << aUIso->Number() << " " << aVIso->Number() << "\n";
1034     }
1035   }
1036
1037   if (isChanged) {
1038     TheAISContext()->UpdateCurrentViewer();
1039   }
1040
1041   return 0;
1042 }
1043
1044 static Standard_Integer VDispSensi (Draw_Interpretor& ,
1045                                     Standard_Integer  theArgNb,
1046                                     Standard_CString* )
1047 {
1048   if (theArgNb > 1)
1049   {
1050     Message::SendFail ("Error: wrong syntax!");
1051     return 1;
1052   }
1053
1054   Handle(AIS_InteractiveContext) aCtx;
1055   Handle(V3d_View)               aView;
1056   if (!getCtxAndView (aCtx, aView))
1057   {
1058     return 1;
1059   }
1060
1061   aCtx->DisplayActiveSensitive (aView);
1062   return 0;
1063
1064 }
1065
1066 static Standard_Integer VClearSensi (Draw_Interpretor& ,
1067                                      Standard_Integer  theArgNb,
1068                                      Standard_CString* )
1069 {
1070   if (theArgNb > 1)
1071   {
1072     Message::SendFail ("Error: wrong syntax!");
1073     return 1;
1074   }
1075
1076   Handle(AIS_InteractiveContext) aCtx;
1077   Handle(V3d_View)               aView;
1078   if (!getCtxAndView (aCtx, aView))
1079   {
1080     return 1;
1081   }
1082   aCtx->ClearActiveSensitive (aView);
1083   return 0;
1084 }
1085
1086 //==============================================================================
1087 //function : VDir
1088 //purpose  : To list the displayed object with their attributes
1089 //==============================================================================
1090 static int VDir (Draw_Interpretor& theDI,
1091                  Standard_Integer theNbArgs,
1092                  const char** theArgVec)
1093 {
1094   TCollection_AsciiString aMatch;
1095   Standard_Boolean toFormat = Standard_False;
1096   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
1097   {
1098     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
1099     anArgCase.LowerCase();
1100     if (anArgCase == "-list"
1101      || anArgCase == "-format")
1102     {
1103       toFormat = Standard_True;
1104     }
1105     else if (aMatch.IsEmpty())
1106     {
1107       aMatch = theArgVec[anArgIter];
1108     }
1109     else
1110     {
1111       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
1112       return 1;
1113     }
1114   }
1115
1116   TCollection_AsciiString aRes;
1117   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); anIter.More(); anIter.Next())
1118   {
1119     if (!aMatch.IsEmpty())
1120     {
1121       const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aMatch + "' '" + anIter.Key2() + "'";
1122       if (theDI.Eval (aCheck.ToCString()) == 0
1123       && *theDI.Result() != '1')
1124       {
1125         continue;
1126       }
1127     }
1128
1129     if (toFormat)
1130     {
1131       aRes += TCollection_AsciiString("\t") + anIter.Key2() + "\n";
1132     }
1133     else
1134     {
1135       aRes += anIter.Key2() + " ";
1136     }
1137   }
1138   theDI.Reset();
1139   theDI << aRes;
1140   return 0;
1141 }
1142
1143 //! Auxiliary enumeration
1144 enum ViewerTest_StereoPair
1145 {
1146   ViewerTest_SP_Single,
1147   ViewerTest_SP_SideBySide,
1148   ViewerTest_SP_OverUnder
1149 };
1150
1151 //==============================================================================
1152 //function : VDump
1153 //purpose  : To dump the active view snapshot to image file
1154 //==============================================================================
1155 static Standard_Integer VDump (Draw_Interpretor& theDI,
1156                                Standard_Integer  theArgNb,
1157                                Standard_CString* theArgVec)
1158 {
1159   Handle(V3d_View) aView = ViewerTest::CurrentView();
1160   if (theArgNb < 2)
1161   {
1162     Message::SendFail ("Error: wrong number of arguments! Image file name should be specified at least.");
1163     return 1;
1164   }
1165   if (aView.IsNull())
1166   {
1167     Message::SendFail() << "Error: cannot find an active view!";
1168     return 1;
1169   }
1170
1171   Standard_Integer      anArgIter   = 1;
1172   Standard_CString      aFilePath   = theArgVec[anArgIter++];
1173   ViewerTest_StereoPair aStereoPair = ViewerTest_SP_Single;
1174   V3d_ImageDumpOptions  aParams;
1175   Handle(Graphic3d_Camera) aCustomCam;
1176   aParams.BufferType    = Graphic3d_BT_RGB;
1177   aParams.StereoOptions = V3d_SDO_MONO;
1178   for (; anArgIter < theArgNb; ++anArgIter)
1179   {
1180     TCollection_AsciiString anArg (theArgVec[anArgIter]);
1181     anArg.LowerCase();
1182     if (anArg == "-buffer")
1183     {
1184       if (++anArgIter >= theArgNb)
1185       {
1186         Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
1187         return 1;
1188       }
1189
1190       TCollection_AsciiString aBufArg (theArgVec[anArgIter]);
1191       aBufArg.LowerCase();
1192       if (aBufArg == "rgba")
1193       {
1194         aParams.BufferType = Graphic3d_BT_RGBA;
1195       }
1196       else if (aBufArg == "rgb")
1197       {
1198         aParams.BufferType = Graphic3d_BT_RGB;
1199       }
1200       else if (aBufArg == "red")
1201       {
1202         aParams.BufferType = Graphic3d_BT_Red;
1203       }
1204       else if (aBufArg == "depth")
1205       {
1206         aParams.BufferType = Graphic3d_BT_Depth;
1207       }
1208       else
1209       {
1210         Message::SendFail() << "Error: unknown buffer '" << aBufArg << "'";
1211         return 1;
1212       }
1213     }
1214     else if (anArgIter + 1 < theArgNb
1215           && anArg == "-xrpose")
1216     {
1217       TCollection_AsciiString anXRArg (theArgVec[++anArgIter]);
1218       anXRArg.LowerCase();
1219       if (anXRArg == "base")
1220       {
1221         aCustomCam = aView->View()->BaseXRCamera();
1222       }
1223       else if (anXRArg == "head")
1224       {
1225         aCustomCam = aView->View()->PosedXRCamera();
1226       }
1227       else if (anXRArg == "handleft"
1228             || anXRArg == "handright")
1229       {
1230         if (aView->View()->IsActiveXR())
1231         {
1232           aCustomCam = new Graphic3d_Camera();
1233           aView->View()->ComputeXRPosedCameraFromBase (*aCustomCam, anXRArg == "handleft"
1234                                                      ? aView->View()->XRSession()->LeftHandPose()
1235                                                      : aView->View()->XRSession()->RightHandPose());
1236         }
1237       }
1238       else
1239       {
1240         Message::SendFail() << "Syntax error: unknown XR pose '" << anXRArg << "'";
1241         return 1;
1242       }
1243       if (aCustomCam.IsNull())
1244       {
1245         Message::SendFail() << "Error: undefined XR pose";
1246         return 0;
1247       }
1248     }
1249     else if (anArg == "-stereo")
1250     {
1251       if (++anArgIter >= theArgNb)
1252       {
1253         Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
1254         return 1;
1255       }
1256
1257       TCollection_AsciiString aStereoArg (theArgVec[anArgIter]);
1258       aStereoArg.LowerCase();
1259       if (aStereoArg == "l"
1260        || aStereoArg == "left")
1261       {
1262         aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1263       }
1264       else if (aStereoArg == "r"
1265             || aStereoArg == "right")
1266       {
1267         aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1268       }
1269       else if (aStereoArg == "mono")
1270       {
1271         aParams.StereoOptions = V3d_SDO_MONO;
1272       }
1273       else if (aStereoArg == "blended"
1274             || aStereoArg == "blend"
1275             || aStereoArg == "stereo")
1276       {
1277         aParams.StereoOptions = V3d_SDO_BLENDED;
1278       }
1279       else if (aStereoArg == "sbs"
1280             || aStereoArg == "sidebyside")
1281       {
1282         aStereoPair = ViewerTest_SP_SideBySide;
1283       }
1284       else if (aStereoArg == "ou"
1285             || aStereoArg == "overunder")
1286       {
1287         aStereoPair = ViewerTest_SP_OverUnder;
1288       }
1289       else
1290       {
1291         Message::SendFail() << "Error: unknown stereo format '" << aStereoArg << "'";
1292         return 1;
1293       }
1294     }
1295     else if (anArg == "-rgba"
1296           || anArg ==  "rgba")
1297     {
1298       aParams.BufferType = Graphic3d_BT_RGBA;
1299     }
1300     else if (anArg == "-rgb"
1301           || anArg ==  "rgb")
1302     {
1303       aParams.BufferType = Graphic3d_BT_RGB;
1304     }
1305     else if (anArg == "-red"
1306           || anArg ==  "red")
1307     {
1308       aParams.BufferType = Graphic3d_BT_Red;
1309     }
1310     else if (anArg == "-depth"
1311           || anArg ==  "depth")
1312     {
1313       aParams.BufferType = Graphic3d_BT_Depth;
1314     }
1315     else if (anArg == "-width"
1316           || anArg ==  "width"
1317           || anArg ==  "sizex")
1318     {
1319       if (aParams.Width != 0)
1320       {
1321         Message::SendFail() << "Error: wrong syntax at " << theArgVec[anArgIter];
1322         return 1;
1323       }
1324       else if (++anArgIter >= theArgNb)
1325       {
1326         Message::SendFail() << "Error: integer value is expected right after 'width'";
1327         return 1;
1328       }
1329       aParams.Width = Draw::Atoi (theArgVec[anArgIter]);
1330     }
1331     else if (anArg == "-height"
1332           || anArg ==  "height"
1333           || anArg ==  "-sizey")
1334     {
1335       if (aParams.Height != 0)
1336       {
1337         Message::SendFail() << "Error: wrong syntax at " << theArgVec[anArgIter];
1338         return 1;
1339       }
1340       else if (++anArgIter >= theArgNb)
1341       {
1342         Message::SendFail() << "Error: integer value is expected right after 'height'";
1343         return 1;
1344       }
1345       aParams.Height = Draw::Atoi (theArgVec[anArgIter]);
1346     }
1347     else if (anArg == "-tile"
1348           || anArg == "-tilesize")
1349     {
1350       if (++anArgIter >= theArgNb)
1351       {
1352         Message::SendFail() << "Error: integer value is expected right after 'tileSize'";
1353         return 1;
1354       }
1355       aParams.TileSize = Draw::Atoi (theArgVec[anArgIter]);
1356     }
1357     else
1358     {
1359       Message::SendFail() << "Error: unknown argument '" << theArgVec[anArgIter] << "'";
1360       return 1;
1361     }
1362   }
1363   if ((aParams.Width <= 0 && aParams.Height >  0)
1364    || (aParams.Width >  0 && aParams.Height <= 0))
1365   {
1366     Message::SendFail() << "Error: dimensions " << aParams.Width << "x" << aParams.Height << " are incorrect";
1367     return 1;
1368   }
1369
1370   if (aParams.Width <= 0 || aParams.Height <= 0)
1371   {
1372     aView->Window()->Size (aParams.Width, aParams.Height);
1373   }
1374
1375   Image_AlienPixMap aPixMap;
1376   Image_Format aFormat = Image_Format_UNKNOWN;
1377   switch (aParams.BufferType)
1378   {
1379     case Graphic3d_BT_RGB:                 aFormat = Image_Format_RGB;   break;
1380     case Graphic3d_BT_RGBA:                aFormat = Image_Format_RGBA;  break;
1381     case Graphic3d_BT_Depth:               aFormat = Image_Format_GrayF; break;
1382     case Graphic3d_BT_RGB_RayTraceHdrLeft: aFormat = Image_Format_RGBF;  break;
1383     case Graphic3d_BT_Red:                 aFormat = Image_Format_Gray;  break;
1384   }
1385
1386   const bool wasImmUpdate = aView->SetImmediateUpdate (false);
1387   Handle(Graphic3d_Camera) aCamBack = aView->Camera();
1388   if (!aCustomCam.IsNull())
1389   {
1390     aView->SetCamera (aCustomCam);
1391   }
1392   switch (aStereoPair)
1393   {
1394     case ViewerTest_SP_Single:
1395     {
1396       if (!aView->ToPixMap (aPixMap, aParams))
1397       {
1398         theDI << "Fail: view dump failed!\n";
1399         return 0;
1400       }
1401       else if (aPixMap.SizeX() != Standard_Size(aParams.Width)
1402             || aPixMap.SizeY() != Standard_Size(aParams.Height))
1403       {
1404         theDI << "Fail: dumped dimensions "    << (Standard_Integer )aPixMap.SizeX() << "x" << (Standard_Integer )aPixMap.SizeY()
1405               << " are lesser than requested " << aParams.Width << "x" << aParams.Height << "\n";
1406       }
1407       break;
1408     }
1409     case ViewerTest_SP_SideBySide:
1410     {
1411       if (!aPixMap.InitZero (aFormat, aParams.Width * 2, aParams.Height))
1412       {
1413         theDI << "Fail: not enough memory for image allocation!\n";
1414         return 0;
1415       }
1416
1417       Image_PixMap aPixMapL, aPixMapR;
1418       aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
1419                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1420       aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizePixelBytes() * aParams.Width,
1421                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1422
1423       aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1424       Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams);
1425       aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1426       isOk          = isOk && aView->ToPixMap (aPixMapR, aParams);
1427       if (!isOk)
1428       {
1429         theDI << "Fail: view dump failed!\n";
1430         return 0;
1431       }
1432       break;
1433     }
1434     case ViewerTest_SP_OverUnder:
1435     {
1436       if (!aPixMap.InitZero (aFormat, aParams.Width, aParams.Height * 2))
1437       {
1438         theDI << "Fail: not enough memory for image allocation!\n";
1439         return 0;
1440       }
1441
1442       Image_PixMap aPixMapL, aPixMapR;
1443       aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
1444                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1445       aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizeRowBytes() * aParams.Height,
1446                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1447
1448       aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1449       Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams);
1450       aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1451       isOk          = isOk && aView->ToPixMap (aPixMapR, aParams);
1452       if (!isOk)
1453       {
1454         theDI << "Fail: view dump failed!\n";
1455         return 0;
1456       }
1457       break;
1458     }
1459   }
1460   if (!aCustomCam.IsNull())
1461   {
1462     aView->SetCamera (aCamBack);
1463   }
1464   aView->SetImmediateUpdate (wasImmUpdate);
1465
1466   if (!aPixMap.Save (aFilePath))
1467   {
1468     theDI << "Fail: image can not be saved!\n";
1469   }
1470   return 0;
1471 }
1472
1473 enum TypeOfDispOperation
1474 {
1475   TypeOfDispOperation_SetDispMode,
1476   TypeOfDispOperation_UnsetDispMode
1477 };
1478
1479 //! Displays,Erase...
1480 static void VwrTst_DispErase (const Handle(AIS_InteractiveObject)& thePrs,
1481                                                 const Standard_Integer theMode,
1482                                                 const TypeOfDispOperation theType,
1483                                                 const Standard_Boolean theToUpdate)
1484 {
1485   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1486   switch (theType)
1487   {
1488     case TypeOfDispOperation_SetDispMode:
1489     {
1490       if (!thePrs.IsNull())
1491       {
1492         aCtx->SetDisplayMode (thePrs, theMode, theToUpdate);
1493       }
1494       else
1495       {
1496         aCtx->SetDisplayMode ((AIS_DisplayMode )theMode, theToUpdate);
1497       }
1498       break;
1499     }
1500     case TypeOfDispOperation_UnsetDispMode:
1501     {
1502       if (!thePrs.IsNull())
1503       {
1504         aCtx->UnsetDisplayMode (thePrs, theToUpdate);
1505       }
1506       else
1507       {
1508         aCtx->SetDisplayMode (AIS_WireFrame, theToUpdate);
1509       }
1510       break;
1511     }
1512   }
1513 }
1514
1515 //=======================================================================
1516 //function :
1517 //purpose  :
1518 //=======================================================================
1519 static int VDispMode (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1520 {
1521   if (argc < 1
1522    || argc > 3)
1523   {
1524     Message::SendFail() << "Syntax error: wrong number of arguments";
1525     return 1;
1526   }
1527
1528   TypeOfDispOperation aType = TCollection_AsciiString (argv[0]) == "vunsetdispmode"
1529                             ? TypeOfDispOperation_UnsetDispMode
1530                             : TypeOfDispOperation_SetDispMode;
1531   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1532   if (aType == TypeOfDispOperation_UnsetDispMode)
1533   {
1534     if (argc == 1)
1535     {
1536       if (aCtx->NbSelected() == 0)
1537       {
1538         VwrTst_DispErase (Handle(AIS_InteractiveObject)(), -1, TypeOfDispOperation_UnsetDispMode, Standard_False);
1539       }
1540       else
1541       {
1542         for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
1543         {
1544           VwrTst_DispErase (aCtx->SelectedInteractive(), -1, TypeOfDispOperation_UnsetDispMode, Standard_False);
1545         }
1546       }
1547       aCtx->UpdateCurrentViewer();
1548     }
1549     else
1550     {
1551       TCollection_AsciiString aName = argv[1];
1552       Handle(AIS_InteractiveObject) aPrs;
1553       if (GetMapOfAIS().Find2 (aName, aPrs)
1554       && !aPrs.IsNull())
1555       {
1556         VwrTst_DispErase (aPrs, -1, TypeOfDispOperation_UnsetDispMode, Standard_True);
1557       }
1558     }
1559   }
1560   else if (argc == 2)
1561   {
1562     Standard_Integer aDispMode = Draw::Atoi (argv[1]);
1563     if (aCtx->NbSelected() == 0
1564      && aType == TypeOfDispOperation_SetDispMode)
1565     {
1566       VwrTst_DispErase (Handle(AIS_InteractiveObject)(), aDispMode, TypeOfDispOperation_SetDispMode, Standard_True);
1567     }
1568     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
1569     {
1570       VwrTst_DispErase (aCtx->SelectedInteractive(), aDispMode, aType, Standard_False);
1571     }
1572     aCtx->UpdateCurrentViewer();
1573   }
1574   else
1575   {
1576     Handle(AIS_InteractiveObject) aPrs;
1577     TCollection_AsciiString aName (argv[1]);
1578     if (GetMapOfAIS().Find2 (aName, aPrs)
1579      && !aPrs.IsNull())
1580     {
1581       VwrTst_DispErase (aPrs, Draw::Atoi(argv[2]), aType, Standard_True);
1582     }
1583   }
1584   return 0;
1585 }
1586
1587
1588 //=======================================================================
1589 //function :
1590 //purpose  :
1591 //=======================================================================
1592 static int VSubInt(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1593 {
1594   if(argc==1) return 1;
1595   Standard_Integer On = Draw::Atoi(argv[1]);
1596   const Handle(AIS_InteractiveContext)& Ctx = ViewerTest::GetAISContext();
1597
1598   if(argc==2)
1599   {
1600     TCollection_AsciiString isOnOff = On == 1 ? "on" : "off";
1601     di << "Sub intensite is turned " << isOnOff << " for " << Ctx->NbSelected() << "objects\n";
1602     for (Ctx->InitSelected(); Ctx->MoreSelected(); Ctx->NextSelected())
1603     {
1604       if(On==1)
1605       {
1606         Ctx->SubIntensityOn (Ctx->SelectedInteractive(), Standard_False);
1607       }
1608       else
1609       {
1610         Ctx->SubIntensityOff (Ctx->SelectedInteractive(), Standard_False);
1611       }
1612     }
1613
1614     Ctx->UpdateCurrentViewer();
1615   }
1616   else {
1617     Handle(AIS_InteractiveObject) IO;
1618     TCollection_AsciiString name = argv[2];
1619     if (GetMapOfAIS().Find2 (name, IO)
1620     && !IO.IsNull())
1621     {
1622       if(On==1)
1623         Ctx->SubIntensityOn(IO, Standard_True);
1624       else
1625         Ctx->SubIntensityOff(IO, Standard_True);
1626     }
1627     else return 1;
1628   }
1629   return 0;
1630 }
1631
1632 //! Auxiliary class to iterate presentations from different collections.
1633 class ViewTest_PrsIter
1634 {
1635 public:
1636
1637   //! Create and initialize iterator object.
1638   ViewTest_PrsIter (const TCollection_AsciiString& theName)
1639   : mySource (IterSource_All)
1640   {
1641     NCollection_Sequence<TCollection_AsciiString> aNames;
1642     if (!theName.IsEmpty())
1643     aNames.Append (theName);
1644     Init (aNames);
1645   }
1646
1647   //! Create and initialize iterator object.
1648   ViewTest_PrsIter (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1649   : mySource (IterSource_All)
1650   {
1651     Init (theNames);
1652   }
1653
1654   //! Initialize the iterator.
1655   void Init (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1656   {
1657     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1658     mySeq = theNames;
1659     mySelIter.Nullify();
1660     myCurrent.Nullify();
1661     myCurrentTrs.Nullify();
1662     if (!mySeq.IsEmpty())
1663     {
1664       mySource = IterSource_List;
1665       mySeqIter = NCollection_Sequence<TCollection_AsciiString>::Iterator (mySeq);
1666     }
1667     else if (aCtx->NbSelected() > 0)
1668     {
1669       mySource  = IterSource_Selected;
1670       mySelIter = aCtx;
1671       mySelIter->InitSelected();
1672     }
1673     else
1674     {
1675       mySource = IterSource_All;
1676       myMapIter.Initialize (GetMapOfAIS());
1677     }
1678     initCurrent();
1679   }
1680
1681   const TCollection_AsciiString& CurrentName() const
1682   {
1683     return myCurrentName;
1684   }
1685
1686   const Handle(AIS_InteractiveObject)& Current() const
1687   {
1688     return myCurrent;
1689   }
1690
1691   const Handle(Standard_Transient)& CurrentTrs() const
1692   {
1693     return myCurrentTrs;
1694   }
1695
1696   //! @return true if iterator points to valid object within collection
1697   Standard_Boolean More() const
1698   {
1699     switch (mySource)
1700     {
1701       case IterSource_All:      return myMapIter.More();
1702       case IterSource_List:     return mySeqIter.More();
1703       case IterSource_Selected: return mySelIter->MoreSelected();
1704     }
1705     return Standard_False;
1706   }
1707
1708   //! Go to the next item.
1709   void Next()
1710   {
1711     myCurrentName.Clear();
1712     myCurrentTrs.Nullify();
1713     myCurrent.Nullify();
1714     switch (mySource)
1715     {
1716       case IterSource_All:
1717       {
1718         myMapIter.Next();
1719         break;
1720       }
1721       case IterSource_List:
1722       {
1723         mySeqIter.Next();
1724         break;
1725       }
1726       case IterSource_Selected:
1727       {
1728         mySelIter->NextSelected();
1729         break;
1730       }
1731     }
1732     initCurrent();
1733   }
1734
1735 private:
1736
1737   void initCurrent()
1738   {
1739     switch (mySource)
1740     {
1741       case IterSource_All:
1742       {
1743         if (myMapIter.More())
1744         {
1745           myCurrentName = myMapIter.Key2();
1746           myCurrentTrs  = myMapIter.Key1();
1747           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1748         }
1749         break;
1750       }
1751       case IterSource_List:
1752       {
1753         if (mySeqIter.More())
1754         {
1755           if (!GetMapOfAIS().IsBound2 (mySeqIter.Value()))
1756           {
1757             Message::SendFail() << "Error: object " << mySeqIter.Value() << " is not displayed!";
1758             return;
1759           }
1760           myCurrentName = mySeqIter.Value();
1761           myCurrentTrs  = GetMapOfAIS().Find2 (mySeqIter.Value());
1762           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1763         }
1764         break;
1765       }
1766       case IterSource_Selected:
1767       {
1768         if (mySelIter->MoreSelected())
1769         {
1770           myCurrentName = GetMapOfAIS().Find1 (mySelIter->SelectedInteractive());
1771           myCurrent     = mySelIter->SelectedInteractive();
1772         }
1773         break;
1774       }
1775     }
1776   }
1777
1778 private:
1779
1780   enum IterSource
1781   {
1782     IterSource_All,
1783     IterSource_List,
1784     IterSource_Selected
1785   };
1786
1787 private:
1788
1789   Handle(AIS_InteractiveContext) mySelIter;    //!< iterator for current (selected) objects (IterSource_Selected)
1790   ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName myMapIter; //!< iterator for map of all objects (IterSource_All)
1791   NCollection_Sequence<TCollection_AsciiString>           mySeq;
1792   NCollection_Sequence<TCollection_AsciiString>::Iterator mySeqIter;
1793
1794   TCollection_AsciiString        myCurrentName;//!< current item name
1795   Handle(Standard_Transient)     myCurrentTrs; //!< current item (as transient object)
1796   Handle(AIS_InteractiveObject)  myCurrent;    //!< current item
1797
1798   IterSource                     mySource;     //!< iterated collection
1799
1800 };
1801
1802 //! Parse interior style name.
1803 static bool parseInteriorStyle (const TCollection_AsciiString& theArg,
1804                                 Aspect_InteriorStyle& theStyle)
1805 {
1806   TCollection_AsciiString anArg (theArg);
1807   anArg.LowerCase();
1808   if (anArg == "empty")
1809   {
1810     theStyle = Aspect_IS_EMPTY;
1811   }
1812   else if (anArg == "hollow")
1813   {
1814     theStyle = Aspect_IS_HOLLOW;
1815   }
1816   else if (anArg == "solid")
1817   {
1818     theStyle = Aspect_IS_SOLID;
1819   }
1820   else if (anArg == "hatch")
1821   {
1822     theStyle = Aspect_IS_HATCH;
1823   }
1824   else if (anArg == "hiddenline"
1825         || anArg == "hidden-line"
1826         || anArg == "hidden_line")
1827   {
1828     theStyle = Aspect_IS_HIDDENLINE;
1829   }
1830   else if (anArg == "point")
1831   {
1832     theStyle = Aspect_IS_POINT;
1833   }
1834   else if (theArg.IsIntegerValue())
1835   {
1836     const Standard_Integer anIntStyle = theArg.IntegerValue();
1837     if (anIntStyle < Aspect_IS_EMPTY || anIntStyle > Aspect_IS_POINT)
1838     {
1839       return false;
1840     }
1841     theStyle = (Aspect_InteriorStyle)anIntStyle;
1842   }
1843   else
1844   {
1845     return false;
1846   }
1847   return true;
1848 }
1849
1850 //! Auxiliary structure for VAspects
1851 struct ViewerTest_AspectsChangeSet
1852 {
1853   Standard_Integer             ToSetVisibility;
1854   Standard_Integer             Visibility;
1855
1856   Standard_Integer             ToSetColor;
1857   Quantity_Color               Color;
1858   Standard_Integer             ToSetBackFaceColor;
1859   Quantity_Color               BackFaceColor;
1860
1861   Standard_Integer             ToSetLineWidth;
1862   Standard_Real                LineWidth;
1863
1864   Standard_Integer             ToSetTypeOfLine;
1865   uint16_t                     StippleLinePattern;
1866   uint16_t                     StippleLineFactor;
1867
1868   Standard_Integer             ToSetTypeOfMarker;
1869   Aspect_TypeOfMarker          TypeOfMarker;
1870   Handle(Image_PixMap)         MarkerImage;
1871
1872   Standard_Integer             ToSetMarkerSize;
1873   Standard_Real                MarkerSize;
1874
1875   Standard_Integer             ToSetTransparency;
1876   Standard_Real                Transparency;
1877
1878   Standard_Integer             ToSetAlphaMode;
1879   Graphic3d_AlphaMode          AlphaMode;
1880   Standard_ShortReal           AlphaCutoff;
1881
1882   Standard_Integer             ToSetMaterial;
1883   Graphic3d_NameOfMaterial     Material;
1884   TCollection_AsciiString      MatName;
1885
1886   NCollection_Sequence<TopoDS_Shape> SubShapes;
1887
1888   Standard_Integer             ToSetShowFreeBoundary;
1889   Standard_Integer             ToSetFreeBoundaryWidth;
1890   Standard_Real                FreeBoundaryWidth;
1891   Standard_Integer             ToSetFreeBoundaryColor;
1892   Quantity_Color               FreeBoundaryColor;
1893
1894   Standard_Integer             ToEnableIsoOnTriangulation;
1895
1896   Standard_Integer             ToSetFaceBoundaryDraw;
1897   Standard_Integer             ToSetFaceBoundaryUpperContinuity;
1898   GeomAbs_Shape                FaceBoundaryUpperContinuity;
1899
1900   Standard_Integer             ToSetFaceBoundaryColor;
1901   Quantity_Color               FaceBoundaryColor;
1902
1903   Standard_Integer             ToSetFaceBoundaryWidth;
1904   Standard_Real                FaceBoundaryWidth;
1905
1906   Standard_Integer             ToSetTypeOfFaceBoundaryLine;
1907   Aspect_TypeOfLine            TypeOfFaceBoundaryLine;
1908
1909   Standard_Integer             ToSetMaxParamValue;
1910   Standard_Real                MaxParamValue;
1911
1912   Standard_Integer             ToSetSensitivity;
1913   Standard_Integer             SelectionMode;
1914   Standard_Integer             Sensitivity;
1915
1916   Standard_Integer             ToSetHatch;
1917   Standard_Integer             StdHatchStyle;
1918   TCollection_AsciiString      PathToHatchPattern;
1919
1920   Standard_Integer             ToSetShadingModel;
1921   Graphic3d_TypeOfShadingModel ShadingModel;
1922   TCollection_AsciiString      ShadingModelName;
1923
1924   Standard_Integer             ToSetInterior;
1925   Aspect_InteriorStyle         InteriorStyle;
1926
1927   Standard_Integer             ToSetDrawSilhouette;
1928
1929   Standard_Integer             ToSetDrawEdges;
1930   Standard_Integer             ToSetQuadEdges;
1931
1932   Standard_Integer             ToSetEdgeColor;
1933   Quantity_ColorRGBA           EdgeColor;
1934
1935   Standard_Integer             ToSetEdgeWidth;
1936   Standard_Real                EdgeWidth;
1937
1938   Standard_Integer             ToSetTypeOfEdge;
1939   Aspect_TypeOfLine            TypeOfEdge;
1940
1941   //! Empty constructor
1942   ViewerTest_AspectsChangeSet()
1943   : ToSetVisibility   (0),
1944     Visibility        (1),
1945     ToSetColor        (0),
1946     Color             (DEFAULT_COLOR),
1947     ToSetBackFaceColor(0),
1948     BackFaceColor     (DEFAULT_COLOR),
1949     ToSetLineWidth    (0),
1950     LineWidth         (1.0),
1951     ToSetTypeOfLine   (0),
1952     StippleLinePattern(0xFFFF),
1953     StippleLineFactor (1),
1954     ToSetTypeOfMarker (0),
1955     TypeOfMarker      (Aspect_TOM_PLUS),
1956     ToSetMarkerSize   (0),
1957     MarkerSize        (1.0),
1958     ToSetTransparency (0),
1959     Transparency      (0.0),
1960     ToSetAlphaMode    (0),
1961     AlphaMode         (Graphic3d_AlphaMode_BlendAuto),
1962     AlphaCutoff       (0.5f),
1963     ToSetMaterial     (0),
1964     Material          (Graphic3d_NOM_DEFAULT),
1965     ToSetShowFreeBoundary      (0),
1966     ToSetFreeBoundaryWidth     (0),
1967     FreeBoundaryWidth          (1.0),
1968     ToSetFreeBoundaryColor     (0),
1969     FreeBoundaryColor          (DEFAULT_FREEBOUNDARY_COLOR),
1970     ToEnableIsoOnTriangulation (0),
1971     //
1972     ToSetFaceBoundaryDraw      (0),
1973     ToSetFaceBoundaryUpperContinuity (0),
1974     FaceBoundaryUpperContinuity(GeomAbs_CN),
1975     ToSetFaceBoundaryColor     (0),
1976     FaceBoundaryColor          (Quantity_NOC_BLACK),
1977     ToSetFaceBoundaryWidth     (0),
1978     FaceBoundaryWidth          (1.0f),
1979     ToSetTypeOfFaceBoundaryLine(0),
1980     TypeOfFaceBoundaryLine     (Aspect_TOL_SOLID),
1981     //
1982     ToSetMaxParamValue         (0),
1983     MaxParamValue              (500000),
1984     ToSetSensitivity           (0),
1985     SelectionMode              (-1),
1986     Sensitivity                (-1),
1987     ToSetHatch                 (0),
1988     StdHatchStyle              (-1),
1989     ToSetShadingModel          (0),
1990     ShadingModel               (Graphic3d_TOSM_DEFAULT),
1991     ToSetInterior              (0),
1992     InteriorStyle              (Aspect_IS_SOLID),
1993     ToSetDrawSilhouette (0),
1994     ToSetDrawEdges    (0),
1995     ToSetQuadEdges    (0),
1996     ToSetEdgeColor    (0),
1997     ToSetEdgeWidth    (0),
1998     EdgeWidth         (1.0),
1999     ToSetTypeOfEdge   (0),
2000     TypeOfEdge        (Aspect_TOL_SOLID)
2001     {}
2002
2003   //! @return true if no changes have been requested
2004   Standard_Boolean IsEmpty() const
2005   {
2006     return ToSetVisibility        == 0
2007         && ToSetLineWidth         == 0
2008         && ToSetTransparency      == 0
2009         && ToSetAlphaMode         == 0
2010         && ToSetColor             == 0
2011         && ToSetBackFaceColor     == 0
2012         && ToSetMaterial          == 0
2013         && ToSetShowFreeBoundary  == 0
2014         && ToSetFreeBoundaryColor == 0
2015         && ToSetFreeBoundaryWidth == 0
2016         && ToEnableIsoOnTriangulation == 0
2017         && ToSetFaceBoundaryDraw == 0
2018         && ToSetFaceBoundaryUpperContinuity == 0
2019         && ToSetFaceBoundaryColor == 0
2020         && ToSetFaceBoundaryWidth == 0
2021         && ToSetTypeOfFaceBoundaryLine == 0
2022         && ToSetMaxParamValue     == 0
2023         && ToSetSensitivity       == 0
2024         && ToSetHatch             == 0
2025         && ToSetShadingModel      == 0
2026         && ToSetInterior          == 0
2027         && ToSetDrawSilhouette    == 0
2028         && ToSetDrawEdges         == 0
2029         && ToSetQuadEdges         == 0
2030         && ToSetEdgeColor         == 0
2031         && ToSetEdgeWidth         == 0
2032         && ToSetTypeOfEdge        == 0;
2033   }
2034
2035   //! @return true if properties are valid
2036   Standard_Boolean Validate() const
2037   {
2038     Standard_Boolean isOk = Standard_True;
2039     if (Visibility != 0 && Visibility != 1)
2040     {
2041       Message::SendFail() << "Error: the visibility should be equal to 0 or 1 (0 - invisible; 1 - visible) (specified " << Visibility << ")";
2042       isOk = Standard_False;
2043     }
2044     if (LineWidth <= 0.0
2045      || LineWidth >  10.0)
2046     {
2047       Message::SendFail() << "Error: the width should be within [1; 10] range (specified " << LineWidth << ")";
2048       isOk = Standard_False;
2049     }
2050     if (Transparency < 0.0
2051      || Transparency > 1.0)
2052     {
2053       Message::SendFail() << "Error: the transparency should be within [0; 1] range (specified " << Transparency << ")";
2054       isOk = Standard_False;
2055     }
2056     if (ToSetAlphaMode == 1
2057      && (AlphaCutoff <= 0.0f || AlphaCutoff >= 1.0f))
2058     {
2059       Message::SendFail() << "Error: alpha cutoff value should be within (0; 1) range (specified " << AlphaCutoff << ")";
2060       isOk = Standard_False;
2061     }
2062     if (FreeBoundaryWidth <= 0.0
2063      || FreeBoundaryWidth >  10.0)
2064     {
2065       Message::SendFail() << "Error: the free boundary width should be within [1; 10] range (specified " << FreeBoundaryWidth << ")";
2066       isOk = Standard_False;
2067     }
2068     if (MaxParamValue < 0.0)
2069     {
2070       Message::SendFail() << "Error: the max parameter value should be greater than zero (specified " << MaxParamValue << ")";
2071       isOk = Standard_False;
2072     }
2073     if (Sensitivity <= 0 && ToSetSensitivity)
2074     {
2075       Message::SendFail() << "Error: sensitivity parameter value should be positive (specified " << Sensitivity << ")";
2076       isOk = Standard_False;
2077     }
2078     if (ToSetHatch == 1 && StdHatchStyle < 0 && PathToHatchPattern == "")
2079     {
2080       Message::SendFail ("Error: hatch style must be specified");
2081       isOk = Standard_False;
2082     }
2083     if (ToSetShadingModel == 1
2084     && (ShadingModel < Graphic3d_TOSM_DEFAULT || ShadingModel > Graphic3d_TOSM_PBR_FACET))
2085     {
2086       Message::SendFail() << "Error: unknown shading model " << ShadingModelName << ".";
2087       isOk = Standard_False;
2088     }
2089     return isOk;
2090   }
2091
2092   //! Apply aspects to specified drawer.
2093   bool Apply (const Handle(Prs3d_Drawer)& theDrawer)
2094   {
2095     bool toRecompute = false;
2096     const Handle(Prs3d_Drawer)& aDefDrawer = ViewerTest::GetAISContext()->DefaultDrawer();
2097     if (ToSetShowFreeBoundary != 0)
2098     {
2099       theDrawer->SetFreeBoundaryDraw (ToSetShowFreeBoundary == 1);
2100       toRecompute = true;
2101     }
2102     if (ToSetFreeBoundaryWidth != 0)
2103     {
2104       if (ToSetFreeBoundaryWidth != -1
2105        || theDrawer->HasOwnFreeBoundaryAspect())
2106       {
2107         if (!theDrawer->HasOwnFreeBoundaryAspect())
2108         {
2109           Handle(Prs3d_LineAspect) aBoundaryAspect = new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2110           *aBoundaryAspect->Aspect() = *theDrawer->FreeBoundaryAspect()->Aspect();
2111           theDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2112           toRecompute = true;
2113         }
2114         theDrawer->FreeBoundaryAspect()->SetWidth (FreeBoundaryWidth);
2115       }
2116     }
2117     if (ToSetFreeBoundaryColor != 0)
2118     {
2119       Handle(Prs3d_LineAspect) aBoundaryAspect = new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2120       *aBoundaryAspect->Aspect() = *theDrawer->FreeBoundaryAspect()->Aspect();
2121       aBoundaryAspect->SetColor (FreeBoundaryColor);
2122       theDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2123       toRecompute = true;
2124     }
2125     if (ToSetTypeOfLine != 0)
2126     {
2127       if (ToSetTypeOfLine != -1
2128        || theDrawer->HasOwnLineAspect()
2129        || theDrawer->HasOwnWireAspect()
2130        || theDrawer->HasOwnFreeBoundaryAspect()
2131        || theDrawer->HasOwnUnFreeBoundaryAspect()
2132        || theDrawer->HasOwnSeenLineAspect())
2133       {
2134         toRecompute = theDrawer->SetOwnLineAspects() || toRecompute;
2135         theDrawer->LineAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2136         theDrawer->LineAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
2137         theDrawer->WireAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2138         theDrawer->WireAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
2139         theDrawer->FreeBoundaryAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2140         theDrawer->FreeBoundaryAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
2141         theDrawer->UnFreeBoundaryAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2142         theDrawer->UnFreeBoundaryAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
2143         theDrawer->SeenLineAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2144         theDrawer->SeenLineAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
2145       }
2146     }
2147     if (ToSetTypeOfMarker != 0)
2148     {
2149       if (ToSetTypeOfMarker != -1
2150        || theDrawer->HasOwnPointAspect())
2151       {
2152         toRecompute = theDrawer->SetupOwnPointAspect (aDefDrawer) || toRecompute;
2153         theDrawer->PointAspect()->SetTypeOfMarker (TypeOfMarker);
2154         theDrawer->PointAspect()->Aspect()->SetMarkerImage (MarkerImage.IsNull() ? Handle(Graphic3d_MarkerImage)() : new Graphic3d_MarkerImage (MarkerImage));
2155       }
2156     }
2157     if (ToSetMarkerSize != 0)
2158     {
2159       if (ToSetMarkerSize != -1
2160        || theDrawer->HasOwnPointAspect())
2161       {
2162         toRecompute = theDrawer->SetupOwnPointAspect (aDefDrawer) || toRecompute;
2163         theDrawer->PointAspect()->SetScale (MarkerSize);
2164         toRecompute = true;
2165       }
2166     }
2167     if (ToSetMaxParamValue != 0)
2168     {
2169       if (ToSetMaxParamValue != -1
2170        || theDrawer->HasOwnMaximalParameterValue())
2171       {
2172         theDrawer->SetMaximalParameterValue (MaxParamValue);
2173         toRecompute = true;
2174       }
2175     }
2176     if (ToSetFaceBoundaryDraw != 0)
2177     {
2178       if (ToSetFaceBoundaryDraw != -1
2179        || theDrawer->HasOwnFaceBoundaryDraw())
2180       {
2181         toRecompute = true;
2182         theDrawer->SetFaceBoundaryDraw (ToSetFaceBoundaryDraw == 1);
2183       }
2184     }
2185     if (ToSetFaceBoundaryUpperContinuity != 0)
2186     {
2187       if (ToSetFaceBoundaryUpperContinuity != -1
2188        || theDrawer->HasOwnFaceBoundaryUpperContinuity())
2189       {
2190         toRecompute = true;
2191         if (ToSetFaceBoundaryUpperContinuity == -1)
2192         {
2193           theDrawer->UnsetFaceBoundaryUpperContinuity();
2194         }
2195         else
2196         {
2197           theDrawer->SetFaceBoundaryUpperContinuity (FaceBoundaryUpperContinuity);
2198         }
2199       }
2200     }
2201     if (ToSetFaceBoundaryColor != 0)
2202     {
2203       if (ToSetFaceBoundaryColor != -1
2204        || theDrawer->HasOwnFaceBoundaryAspect())
2205       {
2206         if (ToSetFaceBoundaryColor == -1)
2207         {
2208           toRecompute = true;
2209           theDrawer->SetFaceBoundaryAspect (Handle(Prs3d_LineAspect)());
2210         }
2211         else
2212         {
2213           toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2214           theDrawer->FaceBoundaryAspect()->SetColor (FaceBoundaryColor);
2215         }
2216       }
2217     }
2218     if (ToSetFaceBoundaryWidth != 0)
2219     {
2220       if (ToSetFaceBoundaryWidth != -1
2221        || theDrawer->HasOwnFaceBoundaryAspect())
2222       {
2223         toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2224         theDrawer->FaceBoundaryAspect()->SetWidth (FaceBoundaryWidth);
2225       }
2226     }
2227     if (ToSetTypeOfFaceBoundaryLine != 0)
2228     {
2229       if (ToSetTypeOfFaceBoundaryLine != -1
2230        || theDrawer->HasOwnFaceBoundaryAspect())
2231       {
2232         toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2233         theDrawer->FaceBoundaryAspect()->SetTypeOfLine (TypeOfFaceBoundaryLine);
2234       }
2235     }
2236     if (ToSetShadingModel != 0)
2237     {
2238       if (ToSetShadingModel != -1
2239        || theDrawer->HasOwnShadingAspect())
2240       {
2241         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2242         theDrawer->ShadingAspect()->Aspect()->SetShadingModel (ShadingModel);
2243       }
2244     }
2245     if (ToSetBackFaceColor != 0)
2246     {
2247       if (ToSetBackFaceColor != -1
2248        || theDrawer->HasOwnShadingAspect())
2249       {
2250         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2251         theDrawer->ShadingAspect()->SetColor (BackFaceColor, Aspect_TOFM_BACK_SIDE);
2252       }
2253     }
2254     if (ToSetAlphaMode != 0)
2255     {
2256       if (ToSetAlphaMode != -1
2257        || theDrawer->HasOwnShadingAspect())
2258       {
2259         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2260         theDrawer->ShadingAspect()->Aspect()->SetAlphaMode (AlphaMode, AlphaCutoff);
2261       }
2262     }
2263     if (ToSetHatch != 0)
2264     {
2265       if (ToSetHatch != -1
2266       ||  theDrawer->HasOwnShadingAspect())
2267       {
2268         theDrawer->SetupOwnShadingAspect (aDefDrawer);
2269         Handle(Graphic3d_AspectFillArea3d) anAsp = theDrawer->ShadingAspect()->Aspect();
2270         if (ToSetHatch == -1)
2271         {
2272           anAsp->SetInteriorStyle (Aspect_IS_SOLID);
2273         }
2274         else
2275         {
2276           anAsp->SetInteriorStyle (Aspect_IS_HATCH);
2277           if (!PathToHatchPattern.IsEmpty())
2278           {
2279             Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
2280             if (anImage->Load (TCollection_AsciiString (PathToHatchPattern.ToCString())))
2281             {
2282               anAsp->SetHatchStyle (new Graphic3d_HatchStyle (anImage));
2283             }
2284             else
2285             {
2286               Message::SendFail() << "Error: cannot load the following image: " << PathToHatchPattern;
2287             }
2288           }
2289           else if (StdHatchStyle != -1)
2290           {
2291             anAsp->SetHatchStyle (new Graphic3d_HatchStyle ((Aspect_HatchStyle)StdHatchStyle));
2292           }
2293         }
2294         toRecompute = true;
2295       }
2296     }
2297     if (ToSetInterior != 0)
2298     {
2299       if (ToSetInterior != -1
2300        || theDrawer->HasOwnShadingAspect())
2301       {
2302         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2303         theDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (InteriorStyle);
2304         if (InteriorStyle == Aspect_IS_HATCH
2305          && theDrawer->ShadingAspect()->Aspect()->HatchStyle().IsNull())
2306         {
2307           theDrawer->ShadingAspect()->Aspect()->SetHatchStyle (Aspect_HS_VERTICAL);
2308         }
2309       }
2310     }
2311     if (ToSetDrawSilhouette != 0)
2312     {
2313       if (ToSetDrawSilhouette != -1
2314        || theDrawer->HasOwnShadingAspect())
2315       {
2316         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2317         theDrawer->ShadingAspect()->Aspect()->SetDrawSilhouette (ToSetDrawSilhouette == 1);
2318       }
2319     }
2320     if (ToSetDrawEdges != 0)
2321     {
2322       if (ToSetDrawEdges != -1
2323        || theDrawer->HasOwnShadingAspect())
2324       {
2325         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2326         theDrawer->ShadingAspect()->Aspect()->SetDrawEdges (ToSetDrawEdges == 1);
2327       }
2328     }
2329     if (ToSetQuadEdges != 0)
2330     {
2331       if (ToSetQuadEdges != -1
2332           || theDrawer->HasOwnShadingAspect())
2333       {
2334         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2335         theDrawer->ShadingAspect()->Aspect()->SetSkipFirstEdge (ToSetQuadEdges == 1);
2336       }
2337     }
2338     if (ToSetEdgeWidth != 0)
2339     {
2340       if (ToSetEdgeWidth != -1
2341        || theDrawer->HasOwnShadingAspect())
2342       {
2343         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2344         theDrawer->ShadingAspect()->Aspect()->SetEdgeWidth (EdgeWidth);
2345       }
2346     }
2347     if (ToSetTypeOfEdge != 0)
2348     {
2349       if (ToSetTypeOfEdge != -1
2350        || theDrawer->HasOwnShadingAspect())
2351       {
2352         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2353         theDrawer->ShadingAspect()->Aspect()->SetEdgeLineType (TypeOfEdge);
2354         if (ToSetInterior == 0)
2355         {
2356           theDrawer->ShadingAspect()->Aspect()->SetDrawEdges (ToSetTypeOfEdge == 1
2357                                                            && TypeOfEdge != Aspect_TOL_EMPTY);
2358         }
2359       }
2360     }
2361     if (ToSetEdgeColor != 0)
2362     {
2363       if (ToSetEdgeColor != -1
2364        || theDrawer->HasOwnShadingAspect())
2365       {
2366         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2367         if (ToSetEdgeColor == -1)
2368         {
2369           theDrawer->ShadingAspect()->Aspect()->SetEdgeColor (theDrawer->ShadingAspect()->Aspect()->InteriorColor());
2370         }
2371         else
2372         {
2373           theDrawer->ShadingAspect()->Aspect()->SetEdgeColor (EdgeColor);
2374         }
2375       }
2376     }
2377     return toRecompute;
2378   }
2379 };
2380
2381 //==============================================================================
2382 //function : VAspects
2383 //purpose  :
2384 //==============================================================================
2385 static Standard_Integer VAspects (Draw_Interpretor& theDI,
2386                                   Standard_Integer  theArgNb,
2387                                   const char**      theArgVec)
2388 {
2389   TCollection_AsciiString aCmdName (theArgVec[0]);
2390   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2391   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2392   if (aCtx.IsNull())
2393   {
2394     Message::SendFail ("Error: no active view!");
2395     return 1;
2396   }
2397
2398   Standard_Integer anArgIter = 1;
2399   Standard_Boolean isDefaults = Standard_False;
2400   NCollection_Sequence<TCollection_AsciiString> aNames;
2401   for (; anArgIter < theArgNb; ++anArgIter)
2402   {
2403     TCollection_AsciiString anArg = theArgVec[anArgIter];
2404     if (anUpdateTool.parseRedrawMode (anArg))
2405     {
2406       continue;
2407     }
2408     else if (!anArg.IsEmpty()
2409            && anArg.Value (1) != '-')
2410     {
2411       aNames.Append (anArg);
2412     }
2413     else
2414     {
2415       if (anArg == "-defaults")
2416       {
2417         isDefaults = Standard_True;
2418         ++anArgIter;
2419       }
2420       break;
2421     }
2422   }
2423
2424   if (!aNames.IsEmpty() && isDefaults)
2425   {
2426     Message::SendFail ("Error: wrong syntax. If -defaults is used there should not be any objects' names!");
2427     return 1;
2428   }
2429
2430   NCollection_Sequence<ViewerTest_AspectsChangeSet> aChanges;
2431   aChanges.Append (ViewerTest_AspectsChangeSet());
2432   ViewerTest_AspectsChangeSet* aChangeSet = &aChanges.ChangeLast();
2433
2434   // parse syntax of legacy commands
2435   bool toParseAliasArgs = false;
2436   Standard_Boolean toDump = 0;
2437   Standard_Boolean toCompactDump = 0;
2438   Standard_Integer aDumpDepth = -1;
2439   if (aCmdName == "vsetwidth")
2440   {
2441     if (aNames.IsEmpty()
2442     || !aNames.Last().IsRealValue())
2443     {
2444       Message::SendFail ("Error: not enough arguments!");
2445       return 1;
2446     }
2447     aChangeSet->ToSetLineWidth = 1;
2448     aChangeSet->LineWidth = aNames.Last().RealValue();
2449     aNames.Remove (aNames.Length());
2450   }
2451   else if (aCmdName == "vunsetwidth")
2452   {
2453     aChangeSet->ToSetLineWidth = -1;
2454   }
2455   else if (aCmdName == "vsetcolor")
2456   {
2457     if (aNames.IsEmpty())
2458     {
2459       Message::SendFail ("Error: not enough arguments!");
2460       return 1;
2461     }
2462     aChangeSet->ToSetColor = 1;
2463
2464     Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
2465     Standard_Boolean     isOk   = Standard_False;
2466     if (Quantity_Color::ColorFromName (aNames.Last().ToCString(), aColor))
2467     {
2468       aChangeSet->Color = aColor;
2469       aNames.Remove (aNames.Length());
2470       isOk = Standard_True;
2471     }
2472     else if (Quantity_Color::ColorFromHex (aNames.Last().ToCString(), aChangeSet->Color))
2473     {
2474       aNames.Remove (aNames.Length());
2475       isOk = Standard_True;
2476     }
2477     else if (aNames.Length() >= 3)
2478     {
2479       const char* anArgVec[3] =
2480       {
2481         aNames.Value (aNames.Upper() - 2).ToCString(),
2482         aNames.Value (aNames.Upper() - 1).ToCString(),
2483         aNames.Value (aNames.Upper() - 0).ToCString(),
2484       };
2485
2486       Standard_Integer aNbParsed = ViewerTest::ParseColor (3, anArgVec, aChangeSet->Color);
2487       isOk = aNbParsed == 3;
2488       aNames.Remove (aNames.Length());
2489       aNames.Remove (aNames.Length());
2490       aNames.Remove (aNames.Length());
2491     }
2492     if (!isOk)
2493     {
2494       Message::SendFail ("Error: not enough arguments!");
2495       return 1;
2496     }
2497   }
2498   else if (aCmdName == "vunsetcolor")
2499   {
2500     aChangeSet->ToSetColor = -1;
2501   }
2502   else if (aCmdName == "vsettransparency")
2503   {
2504     if (aNames.IsEmpty()
2505     || !aNames.Last().IsRealValue())
2506     {
2507       Message::SendFail ("Error: not enough arguments!");
2508       return 1;
2509     }
2510     aChangeSet->ToSetTransparency = 1;
2511     aChangeSet->Transparency  = aNames.Last().RealValue();
2512     aNames.Remove (aNames.Length());
2513   }
2514   else if (aCmdName == "vunsettransparency")
2515   {
2516     aChangeSet->ToSetTransparency = -1;
2517   }
2518   else if (aCmdName == "vsetmaterial")
2519   {
2520     if (aNames.IsEmpty())
2521     {
2522       Message::SendFail ("Error: not enough arguments!");
2523       return 1;
2524     }
2525     aChangeSet->ToSetMaterial = 1;
2526     aChangeSet->MatName = aNames.Last();
2527     aNames.Remove (aNames.Length());
2528     if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString(), aChangeSet->Material))
2529     {
2530       Message::SendFail() << "Syntax error: unknown material '" << aChangeSet->MatName << "'.";
2531       return 1;
2532     }
2533   }
2534   else if (aCmdName == "vunsetmaterial")
2535   {
2536     aChangeSet->ToSetMaterial = -1;
2537   }
2538   else if (aCmdName == "vsetinteriorstyle")
2539   {
2540     if (aNames.IsEmpty()
2541     || !aNames.Last().IsRealValue())
2542     {
2543       Message::SendFail ("Error: not enough arguments!");
2544       return 1;
2545     }
2546     aChangeSet->ToSetInterior = 1;
2547     if (!parseInteriorStyle (aNames.Last(), aChangeSet->InteriorStyle))
2548     {
2549       Message::SendFail() << "Error: wrong syntax at " << aNames.Last();
2550       return 1;
2551     }
2552     aNames.Remove (aNames.Length());
2553   }
2554   else if (aCmdName == "vsetedgetype")
2555   {
2556     aChangeSet->ToSetDrawEdges = 1;
2557     toParseAliasArgs = true;
2558   }
2559   else if (aCmdName == "vunsetedgetype")
2560   {
2561     aChangeSet->ToSetDrawEdges  = -1;
2562     aChangeSet->ToSetEdgeColor  = -1;
2563     aChangeSet->ToSetTypeOfEdge = -1;
2564     aChangeSet->TypeOfEdge = Aspect_TOL_SOLID;
2565   }
2566   else if (aCmdName == "vshowfaceboundary")
2567   {
2568     aChangeSet->ToSetFaceBoundaryDraw = 1;
2569     toParseAliasArgs = true;
2570     if (aNames.Size() >= 2
2571      && aNames.Value (2).IsIntegerValue())
2572     {
2573       if (aNames.Size() == 7)
2574       {
2575         if (ViewerTest::ParseLineType (aNames.Value (7).ToCString(), aChangeSet->TypeOfFaceBoundaryLine))
2576         {
2577           aChangeSet->ToSetTypeOfFaceBoundaryLine = 1;
2578           aNames.Remove (7);
2579         }
2580       }
2581       if (aNames.Size() == 6
2582        && aNames.Value (6).IsRealValue())
2583       {
2584         aChangeSet->ToSetFaceBoundaryWidth = 1;
2585         aChangeSet->FaceBoundaryWidth = aNames.Value (6).RealValue();
2586         aNames.Remove (6);
2587       }
2588       if (aNames.Size() == 5
2589        && aNames.Value (3).IsIntegerValue()
2590        && aNames.Value (4).IsIntegerValue()
2591        && aNames.Value (5).IsIntegerValue())
2592       {
2593         aChangeSet->ToSetFaceBoundaryColor = 1;
2594         aChangeSet->FaceBoundaryColor = Quantity_Color (aNames.Value (3).IntegerValue() / 255.0,
2595                                                         aNames.Value (4).IntegerValue() / 255.0,
2596                                                         aNames.Value (5).IntegerValue() / 255.0,
2597                                                         Quantity_TOC_sRGB);
2598         aNames.Remove (5);
2599         aNames.Remove (4);
2600         aNames.Remove (3);
2601       }
2602       if (aNames.Size() == 2)
2603       {
2604         toParseAliasArgs = false;
2605         aChangeSet->ToSetFaceBoundaryDraw = aNames.Value (2).IntegerValue() == 1 ? 1 : -1;
2606         aNames.Remove (2);
2607       }
2608     }
2609   }
2610   else if (anArgIter >= theArgNb)
2611   {
2612     Message::SendFail ("Error: not enough arguments!");
2613     return 1;
2614   }
2615
2616   if (!aChangeSet->IsEmpty()
2617    && !toParseAliasArgs)
2618   {
2619     anArgIter = theArgNb;
2620   }
2621   for (; anArgIter < theArgNb; ++anArgIter)
2622   {
2623     TCollection_AsciiString anArg = theArgVec[anArgIter];
2624     anArg.LowerCase();
2625     if (anArg == "-setwidth"
2626      || anArg == "-width"
2627      || anArg == "-setlinewidth"
2628      || anArg == "-linewidth"
2629      || anArg == "-setedgewidth"
2630      || anArg == "-setedgeswidth"
2631      || anArg == "-edgewidth"
2632      || anArg == "-edgeswidth"
2633      || anArg == "-setfaceboundarywidth"
2634      || anArg == "-setboundarywidth"
2635      || anArg == "-faceboundarywidth"
2636      || anArg == "-boundarywidth")
2637     {
2638       if (++anArgIter >= theArgNb)
2639       {
2640         Message::SendFail() << "Error: wrong syntax at " << anArg;
2641         return 1;
2642       }
2643
2644       const Standard_Real aWidth = Draw::Atof (theArgVec[anArgIter]);
2645       if (anArg == "-setedgewidth"
2646        || anArg == "-setedgeswidth"
2647        || anArg == "-edgewidth"
2648        || anArg == "-edgeswidth"
2649        || aCmdName == "vsetedgetype")
2650       {
2651         aChangeSet->ToSetEdgeWidth = 1;
2652         aChangeSet->EdgeWidth = aWidth;
2653       }
2654       else if (anArg == "-setfaceboundarywidth"
2655             || anArg == "-setboundarywidth"
2656             || anArg == "-faceboundarywidth"
2657             || anArg == "-boundarywidth"
2658             || aCmdName == "vshowfaceboundary")
2659       {
2660         aChangeSet->ToSetFaceBoundaryWidth = 1;
2661         aChangeSet->FaceBoundaryWidth = aWidth;
2662       }
2663       else
2664       {
2665         aChangeSet->ToSetLineWidth = 1;
2666         aChangeSet->LineWidth = aWidth;
2667       }
2668     }
2669     else if (anArg == "-unsetwidth"
2670           || anArg == "-unsetlinewidth"
2671           || anArg == "-unsetedgewidth")
2672     {
2673       if (anArg == "-unsetedgewidth")
2674       {
2675         aChangeSet->ToSetEdgeWidth = -1;
2676         aChangeSet->EdgeWidth = 1.0;
2677       }
2678       else
2679       {
2680         aChangeSet->ToSetLineWidth = -1;
2681         aChangeSet->LineWidth = 1.0;
2682       }
2683     }
2684     else if (anArg == "-settransp"
2685           || anArg == "-settransparency"
2686           || anArg == "-transparency"
2687           || anArg == "-transp")
2688     {
2689       if (++anArgIter >= theArgNb)
2690       {
2691         Message::SendFail() << "Error: wrong syntax at " << anArg;
2692         return 1;
2693       }
2694       aChangeSet->ToSetTransparency = 1;
2695       aChangeSet->Transparency = Draw::Atof (theArgVec[anArgIter]);
2696       if (aChangeSet->Transparency >= 0.0
2697        && aChangeSet->Transparency <= Precision::Confusion())
2698       {
2699         aChangeSet->ToSetTransparency = -1;
2700         aChangeSet->Transparency = 0.0;
2701       }
2702     }
2703     else if (anArg == "-setalphamode"
2704           || anArg == "-alphamode")
2705     {
2706       if (++anArgIter >= theArgNb)
2707       {
2708         Message::SendFail() << "Error: wrong syntax at " << anArg;
2709         return 1;
2710       }
2711       aChangeSet->ToSetAlphaMode = 1;
2712       aChangeSet->AlphaCutoff = 0.5f;
2713       {
2714         TCollection_AsciiString aParam (theArgVec[anArgIter]);
2715         aParam.LowerCase();
2716         if (aParam == "opaque")
2717         {
2718           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Opaque;
2719         }
2720         else if (aParam == "mask")
2721         {
2722           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Mask;
2723         }
2724         else if (aParam == "blend")
2725         {
2726           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Blend;
2727         }
2728         else if (aParam == "blendauto"
2729               || aParam == "auto")
2730         {
2731           aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto;
2732         }
2733         else
2734         {
2735           Message::SendFail() << "Error: wrong syntax at " << aParam;
2736           return 1;
2737         }
2738       }
2739
2740       if (anArgIter + 1 < theArgNb
2741        && theArgVec[anArgIter + 1][0] != '-')
2742       {
2743         TCollection_AsciiString aParam2 (theArgVec[anArgIter + 1]);
2744         if (aParam2.IsRealValue())
2745         {
2746           aChangeSet->AlphaCutoff = (float )aParam2.RealValue();
2747           ++anArgIter;
2748         }
2749       }
2750     }
2751     else if (anArg == "-setvis"
2752           || anArg == "-setvisibility"
2753           || anArg == "-visibility")
2754     {
2755       if (++anArgIter >= theArgNb)
2756       {
2757         Message::SendFail() << "Error: wrong syntax at " << anArg;
2758         return 1;
2759       }
2760
2761       aChangeSet->ToSetVisibility = 1;
2762       aChangeSet->Visibility = Draw::Atoi (theArgVec[anArgIter]);
2763     }
2764     else if (anArg == "-setalpha"
2765           || anArg == "-alpha")
2766     {
2767       if (++anArgIter >= theArgNb)
2768       {
2769         Message::SendFail() << "Error: wrong syntax at " << anArg;
2770         return 1;
2771       }
2772       aChangeSet->ToSetTransparency = 1;
2773       aChangeSet->Transparency  = Draw::Atof (theArgVec[anArgIter]);
2774       if (aChangeSet->Transparency < 0.0
2775        || aChangeSet->Transparency > 1.0)
2776       {
2777         Message::SendFail() << "Error: the transparency should be within [0; 1] range (specified " << aChangeSet->Transparency << ")";
2778         return 1;
2779       }
2780       aChangeSet->Transparency = 1.0 - aChangeSet->Transparency;
2781       if (aChangeSet->Transparency >= 0.0
2782        && aChangeSet->Transparency <= Precision::Confusion())
2783       {
2784         aChangeSet->ToSetTransparency = -1;
2785         aChangeSet->Transparency = 0.0;
2786       }
2787     }
2788     else if (anArg == "-unsettransp"
2789           || anArg == "-unsettransparency"
2790           || anArg == "-unsetalpha"
2791           || anArg == "-opaque")
2792     {
2793       aChangeSet->ToSetTransparency = -1;
2794       aChangeSet->Transparency = 0.0;
2795     }
2796     else if (anArg == "-setcolor"
2797           || anArg == "-color"
2798           || anArg == "-setbackfacecolor"
2799           || anArg == "-backfacecolor"
2800           || anArg == "-setbackcolor"
2801           || anArg == "-backcolor"
2802           || anArg == "-setfaceboundarycolor"
2803           || anArg == "-setboundarycolor"
2804           || anArg == "-faceboundarycolor"
2805           || anArg == "-boundarycolor")
2806     {
2807       Quantity_Color aColor;
2808       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
2809                                                            theArgVec + anArgIter + 1,
2810                                                            aColor);
2811       if (aNbParsed == 0)
2812       {
2813         Message::SendFail() << "Syntax error at '" << anArg << "'";
2814         return 1;
2815       }
2816       anArgIter += aNbParsed;
2817       if (aCmdName == "vsetedgetype")
2818       {
2819         aChangeSet->ToSetEdgeColor = 1;
2820         aChangeSet->EdgeColor = Quantity_ColorRGBA (aColor);
2821       }
2822       else if (aCmdName == "vshowfaceboundary"
2823             || anArg == "-setfaceboundarycolor"
2824             || anArg == "-setboundarycolor"
2825             || anArg == "-faceboundarycolor"
2826             || anArg == "-boundarycolor")
2827       {
2828         aChangeSet->ToSetFaceBoundaryColor = 1;
2829         aChangeSet->FaceBoundaryColor = aColor;
2830       }
2831       else if (anArg == "-setbackfacecolor"
2832             || anArg == "-backfacecolor"
2833             || anArg == "-setbackcolor"
2834             || anArg == "-backcolor")
2835       {
2836         aChangeSet->ToSetBackFaceColor = 1;
2837         aChangeSet->BackFaceColor = aColor;
2838       }
2839       else
2840       {
2841         aChangeSet->ToSetColor = 1;
2842         aChangeSet->Color = aColor;
2843       }
2844     }
2845     else if (anArg == "-setlinetype"
2846           || anArg == "-linetype"
2847           || anArg == "-setedgetype"
2848           || anArg == "-setedgestype"
2849           || anArg == "-edgetype"
2850           || anArg == "-edgestype"
2851           || anArg == "-setfaceboundarystyle"
2852           || anArg == "-faceboundarystyle"
2853           || anArg == "-boundarystyle"
2854           || anArg == "-setfaceboundarytype"
2855           || anArg == "-faceboundarytype"
2856           || anArg == "-setboundarytype"
2857           || anArg == "-boundarytype"
2858           || anArg == "-type")
2859     {
2860       if (++anArgIter >= theArgNb)
2861       {
2862         Message::SendFail() << "Error: wrong syntax at " << anArg;
2863         return 1;
2864       }
2865       Aspect_TypeOfLine aLineType = Aspect_TOL_EMPTY;
2866       uint16_t aLinePattern = 0xFFFF;
2867       if (!ViewerTest::ParseLineType (theArgVec[anArgIter], aLineType, aLinePattern))
2868       {
2869         Message::SendFail() << "Error: wrong syntax at " << anArg;
2870         return 1;
2871       }
2872
2873       if (anArg == "-setedgetype"
2874        || anArg == "-setedgestype"
2875        || anArg == "-edgetype"
2876        || anArg == "-edgestype"
2877        || aCmdName == "vsetedgetype")
2878       {
2879         aChangeSet->TypeOfEdge = Graphic3d_Aspects::DefaultLineTypeForPattern (aLinePattern);
2880         aChangeSet->ToSetTypeOfEdge = 1;
2881       }
2882       else if (anArg == "-setfaceboundarystyle"
2883             || anArg == "-faceboundarystyle"
2884             || anArg == "-boundarystyle"
2885             || anArg == "-setfaceboundarytype"
2886             || anArg == "-faceboundarytype"
2887             || anArg == "-setboundarytype"
2888             || anArg == "-boundarytype"
2889             || aCmdName == "vshowfaceboundary")
2890       {
2891         aChangeSet->TypeOfFaceBoundaryLine = Graphic3d_Aspects::DefaultLineTypeForPattern (aLinePattern);
2892         aChangeSet->ToSetTypeOfFaceBoundaryLine = 1;
2893       }
2894       else
2895       {
2896         aChangeSet->StippleLinePattern = aLinePattern;
2897         aChangeSet->ToSetTypeOfLine = 1;
2898       }
2899     }
2900     else if (anArg == "-unsetlinetype"
2901           || anArg == "-unsetedgetype"
2902           || anArg == "-unsetedgestype")
2903     {
2904       if (anArg == "-unsetedgetype"
2905        || anArg == "-unsetedgestype")
2906       {
2907         aChangeSet->ToSetTypeOfEdge = -1;
2908       }
2909       else
2910       {
2911         aChangeSet->ToSetTypeOfLine = -1;
2912       }
2913     }
2914     else if (anArg == "-setstipplelinefactor"
2915           || anArg == "-setstipplefactor"
2916           || anArg == "-setlinefactor"
2917           || anArg == "-stipplelinefactor"
2918           || anArg == "-stipplefactor"
2919           || anArg == "-linefactor")
2920     {
2921       if (aChangeSet->ToSetTypeOfLine == -1)
2922       {
2923         Message::SendFail() << "Error: -setStippleLineFactor requires -setLineType";
2924         return 1;
2925       }
2926       if (++anArgIter >= theArgNb)
2927       {
2928         Message::SendFail() << "Error: wrong syntax at " << anArg;
2929         return 1;
2930       }
2931       aChangeSet->StippleLineFactor = (uint16_t )Draw::Atoi (theArgVec[anArgIter]);
2932     }
2933     else if (anArg == "-setmarkertype"
2934           || anArg == "-markertype"
2935           || anArg == "-setpointtype"
2936           || anArg == "-pointtype")
2937     {
2938       if (++anArgIter >= theArgNb)
2939       {
2940         Message::SendFail() << "Error: wrong syntax at " << anArg;
2941         return 1;
2942       }
2943       if (!ViewerTest::ParseMarkerType (theArgVec[anArgIter], aChangeSet->TypeOfMarker, aChangeSet->MarkerImage))
2944       {
2945         Message::SendFail() << "Error: wrong syntax at " << anArg;
2946         return 1;
2947       }
2948
2949       aChangeSet->ToSetTypeOfMarker = 1;
2950     }
2951     else if (anArg == "-unsetmarkertype"
2952           || anArg == "-unsetpointtype")
2953     {
2954       aChangeSet->ToSetTypeOfMarker = -1;
2955     }
2956     else if (anArg == "-setmarkersize"
2957           || anArg == "-markersize"
2958           || anArg == "-setpointsize"
2959           || anArg == "-pointsize")
2960     {
2961       if (++anArgIter >= theArgNb)
2962       {
2963         Message::SendFail() << "Error: wrong syntax at " << anArg;
2964         return 1;
2965       }
2966       aChangeSet->ToSetMarkerSize = 1;
2967       aChangeSet->MarkerSize = Draw::Atof (theArgVec[anArgIter]);
2968     }
2969     else if (anArg == "-unsetmarkersize"
2970           || anArg == "-unsetpointsize")
2971     {
2972       aChangeSet->ToSetMarkerSize = -1;
2973       aChangeSet->MarkerSize = 1.0;
2974     }
2975     else if (anArg == "-unsetcolor")
2976     {
2977       aChangeSet->ToSetColor = -1;
2978       aChangeSet->Color = DEFAULT_COLOR;
2979     }
2980     else if (anArg == "-setmat"
2981           || anArg == "-mat"
2982           || anArg == "-setmaterial"
2983           || anArg == "-material")
2984     {
2985       if (++anArgIter >= theArgNb)
2986       {
2987         Message::SendFail() << "Error: wrong syntax at " << anArg;
2988         return 1;
2989       }
2990       aChangeSet->ToSetMaterial = 1;
2991       aChangeSet->MatName = theArgVec[anArgIter];
2992       if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString(), aChangeSet->Material))
2993       {
2994         Message::SendFail() << "Syntax error: unknown material '" << aChangeSet->MatName << "'.";
2995         return 1;
2996       }
2997     }
2998     else if (anArg == "-unsetmat"
2999           || anArg == "-unsetmaterial")
3000     {
3001       aChangeSet->ToSetMaterial = -1;
3002       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
3003     }
3004     else if (anArg == "-subshape"
3005           || anArg == "-subshapes")
3006     {
3007       if (isDefaults)
3008       {
3009         Message::SendFail() << "Error: wrong syntax. -subshapes can not be used together with -defaults call!";
3010         return 1;
3011       }
3012
3013       if (aNames.IsEmpty())
3014       {
3015         Message::SendFail() << "Error: main objects should specified explicitly when -subshapes is used!";
3016         return 1;
3017       }
3018
3019       aChanges.Append (ViewerTest_AspectsChangeSet());
3020       aChangeSet = &aChanges.ChangeLast();
3021
3022       for (++anArgIter; anArgIter < theArgNb; ++anArgIter)
3023       {
3024         Standard_CString aSubShapeName = theArgVec[anArgIter];
3025         if (*aSubShapeName == '-')
3026         {
3027           --anArgIter;
3028           break;
3029         }
3030
3031         TopoDS_Shape aSubShape = DBRep::Get (aSubShapeName);
3032         if (aSubShape.IsNull())
3033         {
3034           Message::SendFail() << "Error: shape " << aSubShapeName << " doesn't found!";
3035           return 1;
3036         }
3037         aChangeSet->SubShapes.Append (aSubShape);
3038       }
3039
3040       if (aChangeSet->SubShapes.IsEmpty())
3041       {
3042         Message::SendFail() << "Error: empty list is specified after -subshapes!";
3043         return 1;
3044       }
3045     }
3046     else if (anArg == "-setfreeboundary"
3047           || anArg == "-freeboundary"
3048           || anArg == "-setfb"
3049           || anArg == "-fb")
3050     {
3051       bool toEnable = true;
3052       if (!ViewerTest::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
3053       {
3054         Message::SendFail() << "Error: wrong syntax at " << anArg;
3055         return 1;
3056       }
3057       ++anArgIter;
3058       aChangeSet->ToSetShowFreeBoundary = toEnable ? 1 : -1;
3059     }
3060     else if (anArg == "-setfreeboundarywidth"
3061           || anArg == "-freeboundarywidth"
3062           || anArg == "-setfbwidth"
3063           || anArg == "-fbwidth")
3064     {
3065       if (++anArgIter >= theArgNb)
3066       {
3067         Message::SendFail() << "Error: wrong syntax at " << anArg;
3068         return 1;
3069       }
3070       aChangeSet->ToSetFreeBoundaryWidth = 1;
3071       aChangeSet->FreeBoundaryWidth = Draw::Atof (theArgVec[anArgIter]);
3072     }
3073     else if (anArg == "-unsetfreeboundarywidth"
3074           || anArg == "-unsetfbwidth")
3075     {
3076       aChangeSet->ToSetFreeBoundaryWidth = -1;
3077       aChangeSet->FreeBoundaryWidth = 1.0;
3078     }
3079     else if (anArg == "-setfreeboundarycolor"
3080           || anArg == "-freeboundarycolor"
3081           || anArg == "-setfbcolor"
3082           || anArg == "-fbcolor")
3083     {
3084       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3085                                                            theArgVec + anArgIter + 1,
3086                                                            aChangeSet->FreeBoundaryColor);
3087       if (aNbParsed == 0)
3088       {
3089         Message::SendFail() << "Syntax error at '" << anArg << "'";
3090         return 1;
3091       }
3092       anArgIter += aNbParsed;
3093       aChangeSet->ToSetFreeBoundaryColor = 1;
3094     }
3095     else if (anArg == "-unsetfreeboundarycolor"
3096           || anArg == "-unsetfbcolor")
3097     {
3098       aChangeSet->ToSetFreeBoundaryColor = -1;
3099       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
3100     }
3101     else if (anArg == "-setisoontriangulation"
3102           || anArg == "-isoontriangulation"
3103           || anArg == "-setisoontriang"
3104           || anArg == "-isoontriang")
3105     {
3106       bool toEnable = true;
3107       if (!ViewerTest::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
3108       {
3109         Message::SendFail() << "Error: wrong syntax at " << anArg;
3110         return 1;
3111       }
3112       ++anArgIter;
3113       aChangeSet->ToEnableIsoOnTriangulation = toEnable ? 1 : -1;
3114     }
3115     else if (anArg == "-setfaceboundarydraw"
3116           || anArg == "-setdrawfaceboundary"
3117           || anArg == "-setdrawfaceboundaries"
3118           || anArg == "-setshowfaceboundary"
3119           || anArg == "-setshowfaceboundaries"
3120           || anArg == "-setdrawfaceedges"
3121           || anArg == "-faceboundarydraw"
3122           || anArg == "-drawfaceboundary"
3123           || anArg == "-drawfaceboundaries"
3124           || anArg == "-showfaceboundary"
3125           || anArg == "-showfaceboundaries"
3126           || anArg == "-drawfaceedges"
3127           || anArg == "-faceboundary"
3128           || anArg == "-faceboundaries"
3129           || anArg == "-faceedges")
3130     {
3131       bool toEnable = true;
3132       if (!ViewerTest::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
3133       {
3134         Message::SendFail() << "Error: wrong syntax at " << anArg;
3135         return 1;
3136       }
3137       ++anArgIter;
3138       aChangeSet->ToSetFaceBoundaryDraw = toEnable ? 1 : -1;
3139     }
3140     else if (anArg == "-unsetfaceboundary"
3141           || anArg == "-unsetboundary")
3142     {
3143       aChangeSet->ToSetFaceBoundaryDraw  = -1;
3144       aChangeSet->ToSetFaceBoundaryColor = -1;
3145     }
3146     else if (anArg == "-setmostcontinuity"
3147           || anArg == "-mostcontinuity")
3148     {
3149       TCollection_AsciiString aClassArg (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "");
3150       aClassArg.LowerCase();
3151       GeomAbs_Shape aClass = GeomAbs_CN;
3152       if (aClassArg == "c0"
3153        || aClassArg == "0")
3154       {
3155         aClass = GeomAbs_C0;
3156       }
3157       else if (aClassArg == "c1"
3158             || aClassArg == "1")
3159       {
3160         aClass = GeomAbs_C1;
3161       }
3162       else if (aClassArg == "c2"
3163             || aClassArg == "2")
3164       {
3165         aClass = GeomAbs_C2;
3166       }
3167       else if (aClassArg == "c3"
3168             || aClassArg == "3")
3169       {
3170         aClass = GeomAbs_C3;
3171       }
3172       else if (aClassArg == "cn"
3173             || aClassArg == "n")
3174       {
3175         aClass = GeomAbs_CN;
3176       }
3177       else
3178       {
3179         Message::SendFail() << "Syntax error at '" << anArg << "'";
3180         return 1;
3181       }
3182
3183       ++anArgIter;
3184       aChangeSet->ToSetFaceBoundaryUpperContinuity = 1;
3185       aChangeSet->FaceBoundaryUpperContinuity = aClass;
3186     }
3187     else if (anArg == "-setmaxparamvalue"
3188           || anArg == "-maxparamvalue")
3189     {
3190       if (++anArgIter >= theArgNb)
3191       {
3192         Message::SendFail() << "Error: wrong syntax at " << anArg;
3193         return 1;
3194       }
3195       aChangeSet->ToSetMaxParamValue = 1;
3196       aChangeSet->MaxParamValue = Draw::Atof (theArgVec[anArgIter]);
3197     }
3198     else if (anArg == "-setsensitivity"
3199           || anArg == "-sensitivity")
3200     {
3201       if (isDefaults)
3202       {
3203         Message::SendFail() << "Error: wrong syntax. -setSensitivity can not be used together with -defaults call!";
3204         return 1;
3205       }
3206
3207       if (aNames.IsEmpty())
3208       {
3209         Message::SendFail() << "Error: object and selection mode should specified explicitly when -setSensitivity is used!";
3210         return 1;
3211       }
3212
3213       if (anArgIter + 2 >= theArgNb)
3214       {
3215         Message::SendFail() << "Error: wrong syntax at " << anArg;
3216         return 1;
3217       }
3218       aChangeSet->ToSetSensitivity = 1;
3219       aChangeSet->SelectionMode = Draw::Atoi (theArgVec[++anArgIter]);
3220       aChangeSet->Sensitivity = Draw::Atoi (theArgVec[++anArgIter]);
3221     }
3222     else if (anArg == "-sethatch"
3223           || anArg == "-hatch")
3224     {
3225       if (isDefaults)
3226       {
3227         Message::SendFail() << "Error: wrong syntax. -setHatch can not be used together with -defaults call!";
3228         return 1;
3229       }
3230
3231       if (aNames.IsEmpty())
3232       {
3233         Message::SendFail() << "Error: object should be specified explicitly when -setHatch is used!";
3234         return 1;
3235       }
3236
3237       aChangeSet->ToSetHatch = 1;
3238       TCollection_AsciiString anArgHatch (theArgVec[++anArgIter]);
3239       if (anArgHatch.Length() <= 2)
3240       {
3241         const Standard_Integer anIntStyle = Draw::Atoi (anArgHatch.ToCString());
3242         if (anIntStyle < 0
3243          || anIntStyle >= Aspect_HS_NB)
3244         {
3245           Message::SendFail() << "Error: hatch style is out of range [0, " << (Aspect_HS_NB - 1) << "]!";
3246           return 1;
3247         }
3248         aChangeSet->StdHatchStyle = anIntStyle;
3249       }
3250       else
3251       {
3252         aChangeSet->PathToHatchPattern = anArgHatch;
3253       }
3254     }
3255     else if (anArg == "-setshadingmodel"
3256           || anArg == "-setshading"
3257           || anArg == "-shadingmodel"
3258           || anArg == "-shading")
3259     {
3260       if (++anArgIter >= theArgNb)
3261       {
3262         Message::SendFail() << "Error: wrong syntax at " << anArg;
3263         return 1;
3264       }
3265       aChangeSet->ToSetShadingModel = 1;
3266       aChangeSet->ShadingModelName  = theArgVec[anArgIter];
3267       if (!ViewerTest::ParseShadingModel (theArgVec[anArgIter], aChangeSet->ShadingModel))
3268       {
3269         Message::SendFail() << "Error: wrong syntax at " << anArg;
3270         return 1;
3271       }
3272     }
3273     else if (anArg == "-unsetshadingmodel")
3274     {
3275       aChangeSet->ToSetShadingModel = -1;
3276       aChangeSet->ShadingModel = Graphic3d_TOSM_DEFAULT;
3277     }
3278     else if (anArg == "-setinterior"
3279           || anArg == "-setinteriorstyle"
3280           || anArg == "-interior"
3281           || anArg == "-interiorstyle")
3282     {
3283       if (++anArgIter >= theArgNb)
3284       {
3285         Message::SendFail() << "Error: wrong syntax at " << anArg;
3286         return 1;
3287       }
3288       aChangeSet->ToSetInterior = 1;
3289       if (!parseInteriorStyle (theArgVec[anArgIter], aChangeSet->InteriorStyle))
3290       {
3291         Message::SendFail() << "Error: wrong syntax at " << anArg;
3292         return 1;
3293       }
3294     }
3295     else if (anArg == "-unsetinterior")
3296     {
3297       aChangeSet->ToSetInterior = -1;
3298       aChangeSet->InteriorStyle = Aspect_IS_SOLID;
3299     }
3300     else if (anArg == "-setdrawoutline"
3301           || anArg == "-setdrawsilhouette"
3302           || anArg == "-setoutline"
3303           || anArg == "-setsilhouette"
3304           || anArg == "-outline"
3305           || anArg == "-outlined"
3306           || anArg == "-silhouette")
3307     {
3308       bool toDrawOutline = true;
3309       if (anArgIter + 1 < theArgNb
3310        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toDrawOutline))
3311       {
3312         ++anArgIter;
3313       }
3314       aChangeSet->ToSetDrawSilhouette = toDrawOutline ? 1 : -1;
3315     }
3316     else if (anArg == "-setdrawedges"
3317           || anArg == "-setdrawedge"
3318           || anArg == "-drawedges"
3319           || anArg == "-drawedge"
3320           || anArg == "-edges")
3321     {
3322       bool toDrawEdges = true;
3323       if (anArgIter + 1 < theArgNb
3324        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toDrawEdges))
3325       {
3326         ++anArgIter;
3327       }
3328       aChangeSet->ToSetDrawEdges = toDrawEdges ? 1 : -1;
3329     }
3330     else if (anArg == "-setquadedges"
3331           || anArg == "-setquads"
3332           || anArg == "-quads"
3333           || anArg == "-skipfirstedge")
3334     {
3335       bool isQuadMode = true;
3336       if (anArgIter + 1 < theArgNb
3337        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isQuadMode))
3338       {
3339         ++anArgIter;
3340       }
3341       aChangeSet->ToSetQuadEdges = isQuadMode ? 1 : -1;
3342     }
3343     else if (anArg == "-setedgecolor"
3344           || anArg == "-setedgescolor"
3345           || anArg == "-edgecolor"
3346           || anArg == "-edgescolor")
3347     {
3348       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3349                                                            theArgVec + anArgIter + 1,
3350                                                            aChangeSet->EdgeColor);
3351       if (aNbParsed == 0)
3352       {
3353         Message::SendFail() << "Syntax error at '" << anArg << "'";
3354         return 1;
3355       }
3356       anArgIter += aNbParsed;
3357       aChangeSet->ToSetEdgeColor = 1;
3358     }
3359     else if (anArg == "-unset")
3360     {
3361       aChangeSet->ToSetVisibility = 1;
3362       aChangeSet->Visibility = 1;
3363       aChangeSet->ToSetLineWidth = -1;
3364       aChangeSet->LineWidth = 1.0;
3365       aChangeSet->ToSetTypeOfLine = -1;
3366       aChangeSet->StippleLinePattern = 0xFFFF;
3367       aChangeSet->StippleLineFactor = 1;
3368       aChangeSet->ToSetTypeOfMarker = -1;
3369       aChangeSet->TypeOfMarker = Aspect_TOM_PLUS;
3370       aChangeSet->ToSetMarkerSize = -1;
3371       aChangeSet->MarkerSize = 1.0;
3372       aChangeSet->ToSetTransparency = -1;
3373       aChangeSet->Transparency = 0.0;
3374       aChangeSet->ToSetAlphaMode = -1;
3375       aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto;
3376       aChangeSet->AlphaCutoff = 0.5f;
3377       aChangeSet->ToSetColor = -1;
3378       aChangeSet->Color = DEFAULT_COLOR;
3379       //aChangeSet->ToSetBackFaceColor = -1; // should be reset by ToSetColor
3380       //aChangeSet->BackFaceColor = DEFAULT_COLOR;
3381       aChangeSet->ToSetMaterial = -1;
3382       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
3383       aChangeSet->ToSetShowFreeBoundary = -1;
3384       aChangeSet->ToSetFreeBoundaryColor = -1;
3385       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
3386       aChangeSet->ToSetFreeBoundaryWidth = -1;
3387       aChangeSet->FreeBoundaryWidth = 1.0;
3388       aChangeSet->ToEnableIsoOnTriangulation = -1;
3389       //
3390       aChangeSet->ToSetFaceBoundaryDraw = -1;
3391       aChangeSet->ToSetFaceBoundaryUpperContinuity = -1;
3392       aChangeSet->FaceBoundaryUpperContinuity = GeomAbs_CN;
3393       aChangeSet->ToSetFaceBoundaryColor = -1;
3394       aChangeSet->FaceBoundaryColor = Quantity_NOC_BLACK;
3395       aChangeSet->ToSetFaceBoundaryWidth = -1;
3396       aChangeSet->FaceBoundaryWidth = 1.0f;
3397       aChangeSet->ToSetTypeOfFaceBoundaryLine = -1;
3398       aChangeSet->TypeOfFaceBoundaryLine = Aspect_TOL_SOLID;
3399       //
3400       aChangeSet->ToSetHatch = -1;
3401       aChangeSet->StdHatchStyle = -1;
3402       aChangeSet->PathToHatchPattern.Clear();
3403       aChangeSet->ToSetShadingModel = -1;
3404       aChangeSet->ShadingModel = Graphic3d_TOSM_DEFAULT;
3405       aChangeSet->ToSetInterior = -1;
3406       aChangeSet->InteriorStyle = Aspect_IS_SOLID;
3407       aChangeSet->ToSetDrawSilhouette = -1;
3408       aChangeSet->ToSetDrawEdges = -1;
3409       aChangeSet->ToSetQuadEdges = -1;
3410       aChangeSet->ToSetEdgeColor = -1;
3411       aChangeSet->EdgeColor = Quantity_ColorRGBA (DEFAULT_COLOR);
3412       aChangeSet->ToSetEdgeWidth = -1;
3413       aChangeSet->EdgeWidth = 1.0;
3414       aChangeSet->ToSetTypeOfEdge = -1;
3415       aChangeSet->TypeOfEdge = Aspect_TOL_SOLID;
3416     }
3417     else if (anArg == "-dumpjson")
3418     {
3419       toDump = Standard_True;
3420     }
3421     else if (anArg == "-dumpcompact")
3422     {
3423       toCompactDump = Standard_False;
3424       if (++anArgIter >= theArgNb && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toCompactDump))
3425         ++anArgIter;
3426     }
3427     else if (anArg == "-dumpdepth")
3428     {
3429       if (++anArgIter >= theArgNb)
3430       {
3431         Message::SendFail() << "Error: wrong syntax at " << anArg;
3432         return 1;
3433       }
3434       aDumpDepth = Draw::Atoi (theArgVec[anArgIter]);
3435     }
3436     else
3437     {
3438       Message::SendFail() << "Error: wrong syntax at " << anArg;
3439       return 1;
3440     }
3441   }
3442
3443   for (NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
3444        aChangesIter.More(); aChangesIter.Next())
3445   {
3446     if (!aChangesIter.Value().Validate())
3447     {
3448       return 1;
3449     }
3450   }
3451
3452   // special case for -defaults parameter.
3453   // all changed values will be set to DefaultDrawer.
3454   if (isDefaults)
3455   {
3456     const Handle(Prs3d_Drawer)& aDrawer = aCtx->DefaultDrawer();
3457     aChangeSet->Apply (aDrawer);
3458     if (aChangeSet->ToSetLineWidth != 0)
3459     {
3460       aDrawer->LineAspect()->SetWidth (aChangeSet->LineWidth);
3461       aDrawer->WireAspect()->SetWidth (aChangeSet->LineWidth);
3462       aDrawer->UnFreeBoundaryAspect()->SetWidth (aChangeSet->LineWidth);
3463       aDrawer->SeenLineAspect()->SetWidth (aChangeSet->LineWidth);
3464     }
3465     if (aChangeSet->ToSetColor != 0)
3466     {
3467       aDrawer->ShadingAspect()->SetColor        (aChangeSet->Color);
3468       aDrawer->LineAspect()->SetColor           (aChangeSet->Color);
3469       aDrawer->UnFreeBoundaryAspect()->SetColor (aChangeSet->Color);
3470       aDrawer->SeenLineAspect()->SetColor       (aChangeSet->Color);
3471       aDrawer->WireAspect()->SetColor           (aChangeSet->Color);
3472       aDrawer->PointAspect()->SetColor          (aChangeSet->Color);
3473     }
3474     if (aChangeSet->ToSetTransparency != 0)
3475     {
3476       aDrawer->ShadingAspect()->SetTransparency (aChangeSet->Transparency);
3477     }
3478     if (aChangeSet->ToSetMaterial != 0)
3479     {
3480       aDrawer->ShadingAspect()->SetMaterial (aChangeSet->Material);
3481     }
3482     if (aChangeSet->ToEnableIsoOnTriangulation != 0)
3483     {
3484       aDrawer->SetIsoOnTriangulation (aChangeSet->ToEnableIsoOnTriangulation == 1);
3485     }
3486
3487     // redisplay all objects in context
3488     for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
3489     {
3490       Handle(AIS_InteractiveObject)  aPrs = aPrsIter.Current();
3491       if (!aPrs.IsNull())
3492       {
3493         aCtx->Redisplay (aPrs, Standard_False);
3494       }
3495     }
3496     if (toDump)
3497     {
3498       Standard_SStream aStream;
3499       aDrawer->DumpJson (aStream, aDumpDepth);
3500
3501       if (toCompactDump)
3502         theDI << Standard_Dump::Text (aStream);
3503       else
3504         theDI << Standard_Dump::FormatJson (aStream);
3505     }
3506     return 0;
3507   }
3508
3509   for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
3510   {
3511     const TCollection_AsciiString& aName = aPrsIter.CurrentName();
3512     Handle(AIS_InteractiveObject)  aPrs  = aPrsIter.Current();
3513     if (aPrs.IsNull())
3514     {
3515       return 1;
3516     }
3517
3518     Handle(Prs3d_Drawer)           aDrawer = aPrs->Attributes();
3519     Handle(AIS_ColoredShape) aColoredPrs;
3520     Standard_Boolean toDisplay = Standard_False;
3521     Standard_Boolean toRedisplay = Standard_False;
3522     if (aChanges.Length() > 1 || aChangeSet->ToSetVisibility == 1)
3523     {
3524       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aPrs);
3525       if (aShapePrs.IsNull())
3526       {
3527         Message::SendFail() << "Error: an object " << aName << " is not an AIS_Shape presentation!";
3528         return 1;
3529       }
3530       aColoredPrs = Handle(AIS_ColoredShape)::DownCast (aShapePrs);
3531       if (aColoredPrs.IsNull())
3532       {
3533         aColoredPrs = new AIS_ColoredShape (aShapePrs);
3534         if (aShapePrs->HasDisplayMode())
3535         {
3536           aColoredPrs->SetDisplayMode (aShapePrs->DisplayMode());
3537         }
3538         aColoredPrs->SetLocalTransformation (aShapePrs->LocalTransformation());
3539         aCtx->Remove (aShapePrs, Standard_False);
3540         GetMapOfAIS().UnBind2 (aName);
3541         GetMapOfAIS().Bind (aColoredPrs, aName);
3542         toDisplay = Standard_True;
3543         aShapePrs = aColoredPrs;
3544         aPrs      = aColoredPrs;
3545       }
3546     }
3547
3548     if (!aPrs.IsNull())
3549     {
3550       NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
3551       aChangeSet = &aChangesIter.ChangeValue();
3552       if (aChangeSet->ToSetVisibility == 1)
3553       {
3554         Handle(AIS_ColoredDrawer) aColDrawer = aColoredPrs->CustomAspects (aColoredPrs->Shape());
3555         aColDrawer->SetHidden (aChangeSet->Visibility == 0);
3556       }
3557       else if (aChangeSet->ToSetMaterial == 1)
3558       {
3559         aCtx->SetMaterial (aPrs, aChangeSet->Material, Standard_False);
3560       }
3561       else if (aChangeSet->ToSetMaterial == -1)
3562       {
3563         aCtx->UnsetMaterial (aPrs, Standard_False);
3564       }
3565       if (aChangeSet->ToSetColor == 1)
3566       {
3567         aCtx->SetColor (aPrs, aChangeSet->Color, Standard_False);
3568       }
3569       else if (aChangeSet->ToSetColor == -1)
3570       {
3571         aCtx->UnsetColor (aPrs, Standard_False);
3572       }
3573       if (aChangeSet->ToSetTransparency == 1)
3574       {
3575         aCtx->SetTransparency (aPrs, aChangeSet->Transparency, Standard_False);
3576       }
3577       else if (aChangeSet->ToSetTransparency == -1)
3578       {
3579         aCtx->UnsetTransparency (aPrs, Standard_False);
3580       }
3581       if (aChangeSet->ToSetLineWidth == 1)
3582       {
3583         aCtx->SetWidth (aPrs, aChangeSet->LineWidth, Standard_False);
3584       }
3585       else if (aChangeSet->ToSetLineWidth == -1)
3586       {
3587         aCtx->UnsetWidth (aPrs, Standard_False);
3588       }
3589       else if (aChangeSet->ToEnableIsoOnTriangulation != 0)
3590       {
3591         aCtx->IsoOnTriangulation (aChangeSet->ToEnableIsoOnTriangulation == 1, aPrs);
3592         toRedisplay = Standard_True;
3593       }
3594       else if (aChangeSet->ToSetSensitivity != 0)
3595       {
3596         aCtx->SetSelectionSensitivity (aPrs, aChangeSet->SelectionMode, aChangeSet->Sensitivity);
3597       }
3598       if (!aDrawer.IsNull())
3599       {
3600         toRedisplay = aChangeSet->Apply (aDrawer) || toRedisplay;
3601       }
3602
3603       for (aChangesIter.Next(); aChangesIter.More(); aChangesIter.Next())
3604       {
3605         aChangeSet = &aChangesIter.ChangeValue();
3606         for (NCollection_Sequence<TopoDS_Shape>::Iterator aSubShapeIter (aChangeSet->SubShapes);
3607              aSubShapeIter.More(); aSubShapeIter.Next())
3608         {
3609           const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
3610           if (!aChangeSet->IsEmpty())
3611           {
3612             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
3613             aChangeSet->Apply (aCurColDrawer);
3614           }
3615           if (aChangeSet->ToSetVisibility == 1)
3616           {
3617             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
3618             aCurColDrawer->SetHidden (aChangeSet->Visibility == 0);
3619           }
3620           if (aChangeSet->ToSetColor == 1)
3621           {
3622             aColoredPrs->SetCustomColor (aSubShape, aChangeSet->Color);
3623           }
3624           if (aChangeSet->ToSetTransparency == 1)
3625           {
3626             aColoredPrs->SetCustomTransparency (aSubShape, aChangeSet->Transparency);
3627           }
3628           if (aChangeSet->ToSetLineWidth == 1)
3629           {
3630             aColoredPrs->SetCustomWidth (aSubShape, aChangeSet->LineWidth);
3631           }
3632           if (aChangeSet->ToSetColor     == -1
3633            || aChangeSet->ToSetLineWidth == -1)
3634           {
3635             aColoredPrs->UnsetCustomAspects (aSubShape, Standard_True);
3636           }
3637           if (aChangeSet->ToSetSensitivity != 0)
3638           {
3639             aCtx->SetSelectionSensitivity (aPrs, aChangeSet->SelectionMode, aChangeSet->Sensitivity);
3640           }
3641         }
3642       }
3643       if (toDisplay)
3644       {
3645         aCtx->Display (aPrs, Standard_False);
3646       }
3647       if (toRedisplay)
3648       {
3649         aCtx->Redisplay (aPrs, Standard_False);
3650       }
3651       else if (!aColoredPrs.IsNull())
3652       {
3653         aCtx->Redisplay (aColoredPrs, Standard_False);
3654       }
3655       else
3656       {
3657         aPrs->SynchronizeAspects();
3658       }
3659
3660       if (toDump)
3661       {
3662         Standard_SStream aStream;
3663         aDrawer->DumpJson (aStream);
3664
3665         theDI << aName << ": \n";
3666         theDI << Standard_Dump::FormatJson (aStream);
3667         theDI << "\n";
3668       }
3669     }
3670   }
3671   return 0;
3672 }
3673
3674 //==============================================================================
3675 //function : VDonly2
3676 //author   : ege
3677 //purpose  : Display only a selected or named  object
3678 //           if there is no selected or named object s, nothing is done
3679 //==============================================================================
3680 static int VDonly2 (Draw_Interpretor& ,
3681                     Standard_Integer  theArgNb,
3682                     const char**      theArgVec)
3683 {
3684   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
3685   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
3686   if (aCtx.IsNull())
3687   {
3688     Message::SendFail ("Error: no active view!");
3689     return 1;
3690   }
3691
3692   Standard_Integer anArgIter = 1;
3693   for (; anArgIter < theArgNb; ++anArgIter)
3694   {
3695     if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
3696     {
3697       break;
3698     }
3699   }
3700
3701   NCollection_Map<Handle(Standard_Transient)> aDispSet;
3702   if (anArgIter >= theArgNb)
3703   {
3704     // display only selected objects
3705     if (aCtx->NbSelected() < 1)
3706     {
3707       return 0;
3708     }
3709
3710     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
3711     {
3712       aDispSet.Add (aCtx->SelectedInteractive());
3713     }
3714   }
3715   else
3716   {
3717     // display only specified objects
3718     for (; anArgIter < theArgNb; ++anArgIter)
3719     {
3720       TCollection_AsciiString aName = theArgVec[anArgIter];
3721       Handle(AIS_InteractiveObject) aShape;
3722       if (GetMapOfAIS().Find2 (aName, aShape)
3723       && !aShape.IsNull())
3724       {
3725         aCtx->Display (aShape, Standard_False);
3726         aDispSet.Add (aShape);
3727       }
3728     }
3729   }
3730
3731   // weed out other objects
3732   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); anIter.More(); anIter.Next())
3733   {
3734     if (aDispSet.Contains (anIter.Key1()))
3735     {
3736       continue;
3737     }
3738
3739     if (Handle(AIS_InteractiveObject) aShape = anIter.Key1())
3740     {
3741       aCtx->Erase (aShape, Standard_False);
3742     }
3743   }
3744   return 0;
3745 }
3746
3747 //==============================================================================
3748 //function : VRemove
3749 //purpose  : Removes selected or named objects.
3750 //           If there is no selected or named objects,
3751 //           all objects in the viewer can be removed with argument -all.
3752 //           If -context is in arguments, the object is not deleted from the map of
3753 //           objects (deleted only from the current context).
3754 //==============================================================================
3755 int VRemove (Draw_Interpretor& theDI,
3756              Standard_Integer  theArgNb,
3757              const char**      theArgVec)
3758 {
3759   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
3760   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
3761   if (aCtx.IsNull())
3762   {
3763     Message::SendFail ("Error: no active view!");
3764     return 1;
3765   }
3766
3767   Standard_Boolean isContextOnly = Standard_False;
3768   Standard_Boolean toRemoveAll   = Standard_False;
3769   Standard_Boolean toPrintInfo   = Standard_True;
3770   Standard_Boolean toFailOnError = Standard_True;
3771
3772   Standard_Integer anArgIter = 1;
3773   for (; anArgIter < theArgNb; ++anArgIter)
3774   {
3775     TCollection_AsciiString anArg = theArgVec[anArgIter];
3776     anArg.LowerCase();
3777     if (anArg == "-context")
3778     {
3779       isContextOnly = Standard_True;
3780     }
3781     else if (anArg == "-all")
3782     {
3783       toRemoveAll = Standard_True;
3784     }
3785     else if (anArg == "-noinfo")
3786     {
3787       toPrintInfo = Standard_False;
3788     }
3789     else if (anArg == "-noerror"
3790           || anArg == "-nofail")
3791     {
3792       toFailOnError = Standard_False;
3793     }
3794     else if (anUpdateTool.parseRedrawMode (anArg))
3795     {
3796       continue;
3797     }
3798     else
3799     {
3800       break;
3801     }
3802   }
3803   if (toRemoveAll
3804    && anArgIter < theArgNb)
3805   {
3806     Message::SendFail ("Error: wrong syntax!");
3807     return 1;
3808   }
3809
3810   NCollection_List<TCollection_AsciiString> anIONameList;
3811   if (toRemoveAll)
3812   {
3813     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3814          anIter.More(); anIter.Next())
3815     {
3816       anIONameList.Append (anIter.Key2());
3817     }
3818   }
3819   else if (anArgIter < theArgNb) // removed objects names are in argument list
3820   {
3821     for (; anArgIter < theArgNb; ++anArgIter)
3822     {
3823       const TCollection_AsciiString aName (theArgVec[anArgIter]);
3824       if (aName.Search ("*") != -1)
3825       {
3826         for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aPrsIter (GetMapOfAIS()); aPrsIter.More(); aPrsIter.Next())
3827         {
3828           if (aPrsIter.Key1()->GetContext() != aCtx)
3829           {
3830             continue;
3831           }
3832           const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aName + "' '" + aPrsIter.Key2() + "'";
3833           if (theDI.Eval (aCheck.ToCString()) == 0
3834           && *theDI.Result() == '1')
3835           {
3836             anIONameList.Append (aPrsIter.Key2());
3837           }
3838         }
3839         theDI.Reset();
3840         continue;
3841       }
3842
3843       Handle(AIS_InteractiveObject) anIO;
3844       if (!GetMapOfAIS().Find2 (aName, anIO))
3845       {
3846         if (toFailOnError)
3847         {
3848           Message::SendFail() << "Syntax error: '" << aName << "' was not bound to some object.";
3849           return 1;
3850         }
3851       }
3852       else if (anIO->GetContext() != aCtx)
3853       {
3854         if (toFailOnError)
3855         {
3856           Message::SendFail() << "Syntax error: '" << aName << "' was not displayed in current context.\n"
3857                               << "Please activate view with this object displayed and try again.";
3858           return 1;
3859         }
3860       }
3861       else
3862       {
3863         anIONameList.Append (aName);
3864       }
3865     }
3866   }
3867   else if (aCtx->NbSelected() > 0)
3868   {
3869     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3870          anIter.More(); anIter.Next())
3871     {
3872       if (!aCtx->IsSelected (anIter.Key1()))
3873       {
3874         continue;
3875       }
3876
3877       anIONameList.Append (anIter.Key2());
3878       continue;
3879     }
3880   }
3881
3882   // Unbind all removed objects from the map of displayed IO.
3883   for (NCollection_List<TCollection_AsciiString>::Iterator anIter (anIONameList);
3884        anIter.More(); anIter.Next())
3885   {
3886     const Handle(AIS_InteractiveObject) anIO = GetMapOfAIS().Find2 (anIter.Value());
3887     aCtx->Remove (anIO, Standard_False);
3888     if (toPrintInfo)
3889     {
3890       theDI << anIter.Value() << " ";
3891     }
3892     if (!isContextOnly)
3893     {
3894       GetMapOfAIS().UnBind2 (anIter.Value());
3895     }
3896   }
3897   return 0;
3898 }
3899
3900 //==============================================================================
3901 //function : VErase
3902 //purpose  : Erase some selected or named objects
3903 //           if there is no selected or named objects, the whole viewer is erased
3904 //==============================================================================
3905 int VErase (Draw_Interpretor& theDI,
3906             Standard_Integer  theArgNb,
3907             const char**      theArgVec)
3908 {
3909   const Handle(AIS_InteractiveContext)& aCtx  = ViewerTest::GetAISContext();
3910   const Handle(V3d_View)&               aView = ViewerTest::CurrentView();
3911   ViewerTest_AutoUpdater anUpdateTool (aCtx, aView);
3912   if (aCtx.IsNull())
3913   {
3914     Message::SendFail ("Error: no active view!");
3915     return 1;
3916   }
3917
3918   const Standard_Boolean toEraseAll = TCollection_AsciiString (theArgNb > 0 ? theArgVec[0] : "") == "veraseall";
3919
3920   Standard_Integer anArgIter = 1;
3921   Standard_Boolean toEraseInView = Standard_False;
3922   Standard_Boolean toFailOnError = Standard_True;
3923   TColStd_SequenceOfAsciiString aNamesOfEraseIO;
3924   for (; anArgIter < theArgNb; ++anArgIter)
3925   {
3926     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
3927     anArgCase.LowerCase();
3928     if (anUpdateTool.parseRedrawMode (anArgCase))
3929     {
3930       continue;
3931     }
3932     else if (anArgCase == "-view"
3933           || anArgCase == "-inview")
3934     {
3935       toEraseInView = Standard_True;
3936     }
3937     else if (anArgCase == "-noerror"
3938           || anArgCase == "-nofail")
3939     {
3940       toFailOnError = Standard_False;
3941     }
3942     else
3943     {
3944       aNamesOfEraseIO.Append (theArgVec[anArgIter]);
3945     }
3946   }
3947
3948   if (!aNamesOfEraseIO.IsEmpty() && toEraseAll)
3949   {
3950     Message::SendFail() << "Error: wrong syntax, " << theArgVec[0] << " too much arguments.";
3951     return 1;
3952   }
3953
3954   if (!aNamesOfEraseIO.IsEmpty())
3955   {
3956     // Erase named objects
3957     NCollection_IndexedDataMap<Handle(AIS_InteractiveObject), TCollection_AsciiString> aPrsList;
3958     for (TColStd_SequenceOfAsciiString::Iterator anIter (aNamesOfEraseIO); anIter.More(); anIter.Next())
3959     {
3960       const TCollection_AsciiString& aName = anIter.Value();
3961       if (aName.Search ("*") != -1)
3962       {
3963         for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aPrsIter (GetMapOfAIS()); aPrsIter.More(); aPrsIter.Next())
3964         {
3965           const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aName + "' '" + aPrsIter.Key2() + "'";
3966           if (theDI.Eval (aCheck.ToCString()) == 0
3967           && *theDI.Result() == '1')
3968           {
3969             aPrsList.Add (aPrsIter.Key1(), aPrsIter.Key2());
3970           }
3971         }
3972         theDI.Reset();
3973       }
3974       else
3975       {
3976         Handle(AIS_InteractiveObject) anIO;
3977         if (!GetMapOfAIS().Find2 (aName, anIO))
3978         {
3979           if (toFailOnError)
3980           {
3981             Message::SendFail() << "Syntax error: '" << aName << "' is not found";
3982             return 1;
3983           }
3984         }
3985         else
3986         {
3987           aPrsList.Add (anIO, aName);
3988         }
3989       }
3990     }
3991
3992     for (NCollection_IndexedDataMap<Handle(AIS_InteractiveObject), TCollection_AsciiString>::Iterator anIter (aPrsList); anIter.More(); anIter.Next())
3993     {
3994       theDI << anIter.Value() << " ";
3995       if (toEraseInView)
3996       {
3997         aCtx->SetViewAffinity (anIter.Key(), aView, Standard_False);
3998       }
3999       else
4000       {
4001         aCtx->Erase (anIter.Key(), Standard_False);
4002       }
4003     }
4004   }
4005   else if (!toEraseAll && aCtx->NbSelected() > 0)
4006   {
4007     // Erase selected objects
4008     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
4009          anIter.More(); anIter.Next())
4010     {
4011       const Handle(AIS_InteractiveObject) anIO = anIter.Key1();
4012       if (!anIO.IsNull()
4013        && aCtx->IsSelected (anIO))
4014       {
4015         theDI << anIter.Key2() << " ";
4016         if (toEraseInView)
4017         {
4018           aCtx->SetViewAffinity (anIO, aView, Standard_False);
4019         }
4020       }
4021     }
4022
4023     if (!toEraseInView)
4024     {
4025       aCtx->EraseSelected (Standard_False);
4026     }
4027   }
4028   else
4029   {
4030     // Erase all objects
4031     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
4032          anIter.More(); anIter.Next())
4033     {
4034       Handle(AIS_InteractiveObject) anIO = anIter.Key1();
4035       if (!anIO.IsNull())
4036       {
4037         if (toEraseInView)
4038         {
4039           aCtx->SetViewAffinity (anIO, aView, Standard_False);
4040         }
4041         else
4042         {
4043           aCtx->Erase (anIO, Standard_False);
4044         }
4045       }
4046     }
4047   }
4048
4049   return 0;
4050 }
4051
4052 //==============================================================================
4053 //function : VDisplayAll
4054 //purpose  : Display all the objects of the Map
4055 //==============================================================================
4056 static int VDisplayAll (Draw_Interpretor& ,
4057                         Standard_Integer  theArgNb,
4058                         const char**      theArgVec)
4059
4060 {
4061   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
4062   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
4063   if (aCtx.IsNull())
4064   {
4065     Message::SendFail ("Error: no active view!");
4066     return 1;
4067   }
4068
4069   Standard_Integer anArgIter = 1;
4070   for (; anArgIter < theArgNb; ++anArgIter)
4071   {
4072     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
4073     anArgCase.LowerCase();
4074     if (anUpdateTool.parseRedrawMode (anArgCase))
4075     {
4076       continue;
4077     }
4078     else
4079     {
4080       break;
4081     }
4082   }
4083   if (anArgIter < theArgNb)
4084   {
4085     Message::SendFail() << theArgVec[0] << "Error: wrong syntax";
4086     return 1;
4087   }
4088
4089   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
4090        anIter.More(); anIter.Next())
4091   {
4092     aCtx->Erase (anIter.Key1(), Standard_False);
4093   }
4094
4095   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
4096        anIter.More(); anIter.Next())
4097   {
4098     aCtx->Display (anIter.Key1(), Standard_False);
4099   }
4100   return 0;
4101 }
4102
4103 //! Auxiliary method to check if presentation exists
4104 inline Standard_Integer checkMode (const Handle(AIS_InteractiveContext)& theCtx,
4105                                    const Handle(AIS_InteractiveObject)&  theIO,
4106                                    const Standard_Integer                theMode)
4107 {
4108   if (theIO.IsNull() || theCtx.IsNull())
4109   {
4110     return -1;
4111   }
4112
4113   if (theMode != -1)
4114   {
4115     if (theCtx->MainPrsMgr()->HasPresentation (theIO, theMode))
4116     {
4117       return theMode;
4118     }
4119   }
4120   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theIO->DisplayMode()))
4121   {
4122     return theIO->DisplayMode();
4123   }
4124   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theCtx->DisplayMode()))
4125   {
4126     return theCtx->DisplayMode();
4127   }
4128
4129   return -1;
4130 }
4131
4132 enum ViewerTest_BndAction
4133 {
4134   BndAction_Hide,
4135   BndAction_Show,
4136   BndAction_Print
4137 };
4138
4139 //! Auxiliary method to print bounding box of presentation
4140 inline void bndPresentation (Draw_Interpretor&                         theDI,
4141                              const Handle(PrsMgr_PresentationManager)& theMgr,
4142                              const Handle(AIS_InteractiveObject)&      theObj,
4143                              const Standard_Integer                    theDispMode,
4144                              const TCollection_AsciiString&            theName,
4145                              const ViewerTest_BndAction                theAction,
4146                              const Handle(Prs3d_Drawer)&               theStyle)
4147 {
4148   switch (theAction)
4149   {
4150     case BndAction_Hide:
4151     {
4152       theMgr->Unhighlight (theObj);
4153       break;
4154     }
4155     case BndAction_Show:
4156     {
4157       theMgr->Color (theObj, theStyle, theDispMode);
4158       break;
4159     }
4160     case BndAction_Print:
4161     {
4162       Bnd_Box aBox;
4163       for (PrsMgr_Presentations::Iterator aPrsIter (theObj->Presentations()); aPrsIter.More(); aPrsIter.Next())
4164       {
4165         if (aPrsIter.Value()->Mode() != theDispMode)
4166           continue;
4167
4168         aBox = aPrsIter.Value()->MinMaxValues();
4169       }
4170       gp_Pnt aMin = aBox.CornerMin();
4171       gp_Pnt aMax = aBox.CornerMax();
4172       theDI << theName  << "\n"
4173             << aMin.X() << " " << aMin.Y() << " " << aMin.Z() << " "
4174             << aMax.X() << " " << aMax.Y() << " " << aMax.Z() << "\n";
4175       break;
4176     }
4177   }
4178 }
4179
4180 //==============================================================================
4181 //function : VBounding
4182 //purpose  :
4183 //==============================================================================
4184 int VBounding (Draw_Interpretor& theDI,
4185                Standard_Integer  theArgNb,
4186                const char**      theArgVec)
4187 {
4188   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
4189   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
4190   if (aCtx.IsNull())
4191   {
4192     Message::SendFail ("Error: no active view!");
4193     return 1;
4194   }
4195
4196   ViewerTest_BndAction anAction = BndAction_Show;
4197   Standard_Integer     aMode    = -1;
4198
4199   Handle(Prs3d_Drawer) aStyle;
4200
4201   Standard_Integer anArgIter = 1;
4202   for (; anArgIter < theArgNb; ++anArgIter)
4203   {
4204     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4205     anArg.LowerCase();
4206     if (anArg == "-print")
4207     {
4208       anAction = BndAction_Print;
4209     }
4210     else if (anArg == "-show")
4211     {
4212       anAction = BndAction_Show;
4213     }
4214     else if (anArg == "-hide")
4215     {
4216       anAction = BndAction_Hide;
4217     }
4218     else if (anArg == "-mode")
4219     {
4220       if (++anArgIter >= theArgNb)
4221       {
4222         Message::SendFail() << "Error: wrong syntax at " << anArg;
4223         return 1;
4224       }
4225       aMode = Draw::Atoi (theArgVec[anArgIter]);
4226     }
4227     else if (!anUpdateTool.parseRedrawMode (anArg))
4228     {
4229       break;
4230     }
4231   }
4232
4233   if (anAction == BndAction_Show)
4234   {
4235     aStyle = new Prs3d_Drawer();
4236     aStyle->SetMethod (Aspect_TOHM_BOUNDBOX);
4237     aStyle->SetColor  (Quantity_NOC_GRAY99);
4238   }
4239
4240   Standard_Integer aHighlightedMode = -1;
4241   if (anArgIter < theArgNb)
4242   {
4243     // has a list of names
4244     for (; anArgIter < theArgNb; ++anArgIter)
4245     {
4246       TCollection_AsciiString aName = theArgVec[anArgIter];
4247       Handle(AIS_InteractiveObject) anIO;
4248       if (!GetMapOfAIS().Find2 (aName, anIO))
4249       {
4250         Message::SendFail() << "Error: presentation " << aName << " does not exist";
4251         return 1;
4252       }
4253
4254       aHighlightedMode = checkMode (aCtx, anIO, aMode);
4255       if (aHighlightedMode == -1)
4256       {
4257         Message::SendFail() << "Error: object " << aName << " has no presentation with mode " << aMode;