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