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