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