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