0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / ViewerTest / ViewerTest.cxx
1 // Created on: 1997-07-23
2 // Created by: Henri JEANNIN
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Standard_Stream.hxx>
18
19 #include <ViewerTest.hxx>
20 #include <ViewerTest_CmdParser.hxx>
21
22 #include <Draw.hxx>
23 #include <TopLoc_Location.hxx>
24 #include <TopTools_HArray1OfShape.hxx>
25 #include <TColStd_HArray1OfTransient.hxx>
26 #include <TColStd_SequenceOfAsciiString.hxx>
27 #include <TColStd_HSequenceOfAsciiString.hxx>
28 #include <TColStd_MapOfTransient.hxx>
29 #include <OSD_Timer.hxx>
30 #include <Geom_Axis2Placement.hxx>
31 #include <Geom_Axis1Placement.hxx>
32 #include <gp_Trsf.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <BRepAdaptor_Curve.hxx>
35 #include <StdSelect_ShapeTypeFilter.hxx>
36 #include <AIS_ColoredShape.hxx>
37 #include <AIS_InteractiveObject.hxx>
38 #include <AIS_Trihedron.hxx>
39 #include <AIS_Axis.hxx>
40 #include <PrsDim.hxx>
41 #include <PrsDim_Relation.hxx>
42 #include <AIS_TypeFilter.hxx>
43 #include <AIS_SignatureFilter.hxx>
44 #include <AIS_ListOfInteractive.hxx>
45 #include <AIS_ListIteratorOfListOfInteractive.hxx>
46 #include <Aspect_InteriorStyle.hxx>
47 #include <Aspect_Window.hxx>
48 #include <Graphic3d_AspectFillArea3d.hxx>
49 #include <Graphic3d_AspectLine3d.hxx>
50 #include <Graphic3d_CStructure.hxx>
51 #include <Graphic3d_Texture2Dmanual.hxx>
52 #include <Graphic3d_GraphicDriver.hxx>
53 #include <Graphic3d_MediaTextureSet.hxx>
54 #include <Image_AlienPixMap.hxx>
55 #include <Message.hxx>
56 #include <OSD_File.hxx>
57 #include <Prs3d_Drawer.hxx>
58 #include <Prs3d_ShadingAspect.hxx>
59 #include <Prs3d_IsoAspect.hxx>
60 #include <Prs3d_PointAspect.hxx>
61 #include <Select3D_SensitiveWire.hxx>
62 #include <Select3D_SensitivePrimitiveArray.hxx>
63 #include <SelectMgr_EntityOwner.hxx>
64 #include <StdSelect_BRepOwner.hxx>
65 #include <StdSelect_ViewerSelector3d.hxx>
66 #include <TopTools_MapOfShape.hxx>
67 #include <ViewerTest_AutoUpdater.hxx>
68 #include <Aspect_XRSession.hxx>
69
70 #include <stdio.h>
71
72 #include <Draw_Interpretor.hxx>
73 #include <TCollection_AsciiString.hxx>
74 #include <Draw_PluginMacro.hxx>
75
76 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
77
78 #include <Quantity_Color.hxx>
79 #include <Quantity_NameOfColor.hxx>
80
81 #include <Graphic3d_NameOfMaterial.hxx>
82
83 #define DEFAULT_COLOR              Quantity_NOC_GOLDENROD
84 #define DEFAULT_FREEBOUNDARY_COLOR Quantity_NOC_GREEN
85 #define DEFAULT_MATERIAL           Graphic3d_NOM_BRASS
86
87 namespace
88 {
89
90   const Standard_Integer THE_MAX_INTEGER_COLOR_COMPONENT = 255;
91
92   const Standard_ShortReal THE_MAX_REAL_COLOR_COMPONENT = 1.0f;
93
94   //! Parses string and get an integer color component (only values within range 0 .. 255 are allowed)
95   //! @param theColorComponentString the string representing the color component
96   //! @param theIntegerColorComponent an integer color component that is a result of parsing
97   //! @return true if parsing was successful, or false otherwise
98   static bool parseNumericalColorComponent (const Standard_CString theColorComponentString,
99                                             Standard_Integer&      theIntegerColorComponent)
100   {
101     Standard_Integer anIntegerColorComponent;
102     if (!Draw::ParseInteger (theColorComponentString, anIntegerColorComponent))
103     {
104       return false;
105     }
106     if ((anIntegerColorComponent < 0) || (anIntegerColorComponent > THE_MAX_INTEGER_COLOR_COMPONENT))
107     {
108       return false;
109     }
110     theIntegerColorComponent = anIntegerColorComponent;
111     return true;
112   }
113
114   //! Parses the string and gets a real color component from it (only values within range 0.0 .. 1.0 are allowed)
115   //! @param theColorComponentString the string representing the color component
116   //! @param theRealColorComponent a real color component that is a result of parsing
117   //! @return true if parsing was successful, or false otherwise
118   static bool parseNumericalColorComponent (const Standard_CString theColorComponentString,
119                                             Standard_ShortReal&    theRealColorComponent)
120   {
121     Standard_Real aRealColorComponent;
122     if (!Draw::ParseReal (theColorComponentString, aRealColorComponent))
123     {
124       return false;
125     }
126     const Standard_ShortReal aShortRealColorComponent = static_cast<Standard_ShortReal> (aRealColorComponent);
127     if ((aShortRealColorComponent < 0.0f) || (aShortRealColorComponent > THE_MAX_REAL_COLOR_COMPONENT))
128     {
129       return false;
130     }
131     theRealColorComponent = aShortRealColorComponent;
132     return true;
133   }
134
135   //! Parses the string and gets a real color component from it (integer values 2 .. 255 are scaled to the 0.0 .. 1.0
136   //! range, values 0 and 1 are leaved as they are)
137   //! @param theColorComponentString the string representing the color component
138   //! @param theColorComponent a color component that is a result of parsing
139   //! @return true if parsing was successful, or false otherwise
140   static bool parseColorComponent (const Standard_CString theColorComponentString,
141                                    Standard_ShortReal&    theColorComponent)
142   {
143     Standard_Integer anIntegerColorComponent;
144     if (parseNumericalColorComponent (theColorComponentString, anIntegerColorComponent))
145     {
146       if (anIntegerColorComponent == 1)
147       {
148         theColorComponent = THE_MAX_REAL_COLOR_COMPONENT;
149       }
150       else
151       {
152         theColorComponent = anIntegerColorComponent * 1.0f / THE_MAX_INTEGER_COLOR_COMPONENT;
153       }
154       return true;
155     }
156     return parseNumericalColorComponent (theColorComponentString, theColorComponent);
157   }
158
159   //! Parses the array of strings and gets an integer color (only values within range 0 .. 255 are allowed and at least
160   //! one of components must be greater than 1)
161   //! @tparam TheNumber the type of resulting color vector elements
162   //! @param theNumberOfColorComponents the number of color components
163   //! @param theColorComponentStrings the array of strings representing color components
164   //! @param theNumericalColor a 4-component vector that is a result of parsing
165   //! @return true if parsing was successful, or false otherwise
166   template <typename TheNumber>
167   static bool parseNumericalColor (Standard_Integer&            theNumberOfColorComponents,
168                                    const char* const* const     theColorComponentStrings,
169                                    NCollection_Vec4<TheNumber>& theNumericalColor)
170   {
171     for (Standard_Integer aColorComponentIndex = 0; aColorComponentIndex < theNumberOfColorComponents;
172          ++aColorComponentIndex)
173     {
174       const char* const aColorComponentString = theColorComponentStrings[aColorComponentIndex];
175       TheNumber         aNumericalColorComponent;
176       if (parseNumericalColorComponent (aColorComponentString, aNumericalColorComponent))
177       {
178         theNumericalColor[aColorComponentIndex] = aNumericalColorComponent;
179       }
180       else
181       {
182         if (aColorComponentIndex == 3)
183         {
184           theNumberOfColorComponents = 3;
185         }
186         else
187         {
188           return false;
189         }
190       }
191     }
192     return true;
193   }
194
195   //! Parses an array of strings and get an integer color (only values within range 0 .. 255 are allowed and at least
196   //! one of components must be greater than 1)
197   //! @param theNumberOfColorComponents the number of color components
198   //! @param theColorComponentStrings the array of strings representing color components
199   //! @param theColor a color that is a result of parsing
200   //! @return true if parsing was successful, or false otherwise
201   static bool parseIntegerColor (Standard_Integer&        theNumberOfColorComponents,
202                                  const char* const* const theColorComponentStrings,
203                                  Quantity_ColorRGBA&      theColor)
204   {
205     const Standard_Integer THE_COLOR_COMPONENT_NOT_PARSED = -1;
206     Graphic3d_Vec4i        anIntegerColor (THE_COLOR_COMPONENT_NOT_PARSED);
207     if (!parseNumericalColor (theNumberOfColorComponents, theColorComponentStrings, anIntegerColor)
208       || anIntegerColor.maxComp() <= 1)
209     {
210       return false;
211     }
212     if (anIntegerColor.a() == THE_COLOR_COMPONENT_NOT_PARSED)
213     {
214       anIntegerColor.a() = THE_MAX_INTEGER_COLOR_COMPONENT;
215     }
216
217     const Graphic3d_Vec4 aRealColor = Graphic3d_Vec4 (anIntegerColor) / static_cast<Standard_ShortReal> (THE_MAX_INTEGER_COLOR_COMPONENT);
218     theColor = Quantity_ColorRGBA (Quantity_ColorRGBA::Convert_sRGB_To_LinearRGB (aRealColor));
219     return true;
220   }
221
222   //! Parses an array of strings and get a real color (only values within range 0.0 .. 1.0 are allowed)
223   //! @param theNumberOfColorComponents the number of color components
224   //! @param theColorComponentStrings the array of strings representing color components
225   //! @param theColor a color that is a result of parsing
226   //! @return true if parsing was successful, or false otherwise
227   static bool parseRealColor (Standard_Integer&        theNumberOfColorComponents,
228                               const char* const* const theColorComponentStrings,
229                               Quantity_ColorRGBA&      theColor)
230   {
231     Graphic3d_Vec4 aRealColor (THE_MAX_REAL_COLOR_COMPONENT);
232     if (!parseNumericalColor (theNumberOfColorComponents, theColorComponentStrings, aRealColor))
233     {
234       return false;
235     }
236     theColor = Quantity_ColorRGBA (aRealColor);
237     return true;
238   }
239
240 } // namespace
241
242 //=======================================================================
243 // function : GetColorFromName
244 // purpose  : get the Quantity_NameOfColor from a string
245 //=======================================================================
246
247 Quantity_NameOfColor ViewerTest::GetColorFromName (const Standard_CString theName)
248 {
249   Quantity_NameOfColor aColor = DEFAULT_COLOR;
250   Quantity_Color::ColorFromName (theName, aColor);
251   return aColor;
252 }
253
254 //=======================================================================
255 // function : parseColor
256 // purpose  :
257 //=======================================================================
258 Standard_Integer ViewerTest::parseColor (const Standard_Integer   theArgNb,
259                                          const char* const* const theArgVec,
260                                          Quantity_ColorRGBA&      theColor,
261                                          const bool               theToParseAlpha)
262 {
263   if ((theArgNb >= 1) && Quantity_ColorRGBA::ColorFromHex (theArgVec[0], theColor, !theToParseAlpha))
264   {
265     return 1;
266   }
267   if (theArgNb >= 1 && Quantity_ColorRGBA::ColorFromName (theArgVec[0], theColor))
268   {
269     if (theArgNb >= 2 && theToParseAlpha)
270     {
271       const Standard_CString anAlphaStr = theArgVec[1];
272       Standard_ShortReal     anAlphaComponent;
273       if (parseColorComponent (anAlphaStr, anAlphaComponent))
274       {
275         theColor.SetAlpha (anAlphaComponent);
276         return 2;
277       }
278     }
279     return 1;
280   }
281   if (theArgNb >= 3)
282   {
283     const Standard_Integer aNumberOfColorComponentsToParse = Min (theArgNb, theToParseAlpha ? 4 : 3);
284     Standard_Integer aNumberOfColorComponentsParsed = aNumberOfColorComponentsToParse;
285     if (parseIntegerColor (aNumberOfColorComponentsParsed, theArgVec, theColor))
286     {
287       return aNumberOfColorComponentsParsed;
288     }
289     aNumberOfColorComponentsParsed = aNumberOfColorComponentsToParse;
290     if (parseRealColor (aNumberOfColorComponentsParsed, theArgVec, theColor))
291     {
292       return aNumberOfColorComponentsParsed;
293     }
294     return 0;
295   }
296   return 0;
297 }
298
299 //=======================================================================
300 //function : ParseOnOff
301 //purpose  :
302 //=======================================================================
303 Standard_Boolean ViewerTest::ParseOnOff (Standard_CString  theArg,
304                                          Standard_Boolean& theIsOn)
305 {
306   TCollection_AsciiString aFlag(theArg);
307   aFlag.LowerCase();
308   if (aFlag == "on"
309    || aFlag == "1")
310   {
311     theIsOn = Standard_True;
312     return Standard_True;
313   }
314   else if (aFlag == "off"
315         || aFlag == "0")
316   {
317     theIsOn = Standard_False;
318     return Standard_True;
319   }
320   return Standard_False;
321 }
322
323 //=======================================================================
324 //function : GetSelectedShapes
325 //purpose  :
326 //=======================================================================
327 void ViewerTest::GetSelectedShapes (TopTools_ListOfShape& theSelectedShapes)
328 {
329   for (GetAISContext()->InitSelected(); GetAISContext()->MoreSelected(); GetAISContext()->NextSelected())
330   {
331     TopoDS_Shape aShape = GetAISContext()->SelectedShape();
332     if (!aShape.IsNull())
333     {
334       theSelectedShapes.Append (aShape);
335     }
336   }
337 }
338
339 //=======================================================================
340 //function : ParseLineType
341 //purpose  :
342 //=======================================================================
343 Standard_Boolean ViewerTest::ParseLineType (Standard_CString theArg,
344                                             Aspect_TypeOfLine& theType,
345                                             uint16_t& thePattern)
346 {
347   TCollection_AsciiString aTypeStr (theArg);
348   aTypeStr.LowerCase();
349   if (aTypeStr == "empty"
350    || aTypeStr == "-1")
351   {
352     theType = Aspect_TOL_EMPTY;
353     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
354   }
355   else if (aTypeStr == "solid"
356         || aTypeStr == "0")
357   {
358     theType = Aspect_TOL_SOLID;
359     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
360   }
361   else if (aTypeStr == "dot"
362         || aTypeStr == "2")
363   {
364     theType = Aspect_TOL_DOT;
365     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
366   }
367   else if (aTypeStr == "dash"
368         || aTypeStr == "1")
369   {
370     theType = Aspect_TOL_DASH;
371     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
372   }
373   else if (aTypeStr == "dotdash"
374         || aTypeStr == "3")
375   {
376     theType = Aspect_TOL_DOTDASH;
377     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
378   }
379   else
380   {
381     if (aTypeStr.StartsWith ("0x"))
382     {
383       aTypeStr = aTypeStr.SubString (3, aTypeStr.Length());
384     }
385
386     if (aTypeStr.Length() != 4
387     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (1)))
388     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (2)))
389     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (3)))
390     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (4))))
391     {
392       return Standard_False;
393     }
394
395     std::stringstream aStream;
396     aStream << std::setbase (16) << aTypeStr.ToCString();
397     if (aStream.fail())
398     {
399       return Standard_False;
400     }
401
402     Standard_Integer aNumber = -1;
403     aStream >> aNumber;
404     if (aStream.fail())
405     {
406       return Standard_False;
407     }
408
409     thePattern = (uint16_t )aNumber;
410     theType = Graphic3d_Aspects::DefaultLineTypeForPattern (thePattern);
411   }
412   return Standard_True;
413 }
414
415 //=======================================================================
416 //function : ParseMarkerType
417 //purpose  :
418 //=======================================================================
419 Standard_Boolean ViewerTest::ParseMarkerType (Standard_CString theArg,
420                                               Aspect_TypeOfMarker& theType,
421                                               Handle(Image_PixMap)& theImage)
422 {
423   theImage.Nullify();
424   TCollection_AsciiString aTypeStr (theArg);
425   aTypeStr.LowerCase();
426   if (aTypeStr == "empty")
427   {
428     theType = Aspect_TOM_EMPTY;
429   }
430   else if (aTypeStr == "point"
431         || aTypeStr == "dot"
432         || aTypeStr == ".")
433   {
434     theType = Aspect_TOM_POINT;
435   }
436   else if (aTypeStr == "plus"
437         || aTypeStr == "+")
438   {
439     theType = Aspect_TOM_PLUS;
440   }
441   else if (aTypeStr == "star"
442         || aTypeStr == "*")
443   {
444     theType = Aspect_TOM_STAR;
445   }
446   else if (aTypeStr == "cross"
447         || aTypeStr == "x")
448   {
449     theType = Aspect_TOM_X;
450   }
451   else if (aTypeStr == "circle"
452         || aTypeStr == "o")
453   {
454     theType = Aspect_TOM_O;
455   }
456   else if (aTypeStr == "pointincircle")
457   {
458     theType = Aspect_TOM_O_POINT;
459   }
460   else if (aTypeStr == "plusincircle")
461   {
462     theType = Aspect_TOM_O_PLUS;
463   }
464   else if (aTypeStr == "starincircle")
465   {
466     theType = Aspect_TOM_O_STAR;
467   }
468   else if (aTypeStr == "crossincircle"
469         || aTypeStr == "xcircle")
470   {
471     theType = Aspect_TOM_O_X;
472   }
473   else if (aTypeStr == "ring1")
474   {
475     theType = Aspect_TOM_RING1;
476   }
477   else if (aTypeStr == "ring2")
478   {
479     theType = Aspect_TOM_RING2;
480   }
481   else if (aTypeStr == "ring"
482         || aTypeStr == "ring3")
483   {
484     theType = Aspect_TOM_RING3;
485   }
486   else if (aTypeStr == "ball")
487   {
488     theType = Aspect_TOM_BALL;
489   }
490   else if (aTypeStr.IsIntegerValue())
491   {
492     const int aTypeInt = aTypeStr.IntegerValue();
493     if (aTypeInt < -1 || aTypeInt >= Aspect_TOM_USERDEFINED)
494     {
495       return Standard_False;
496     }
497     theType = (Aspect_TypeOfMarker )aTypeInt;
498   }
499   else
500   {
501     theType = Aspect_TOM_USERDEFINED;
502     Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
503     if (!anImage->Load (theArg))
504     {
505       return Standard_False;
506     }
507     if (anImage->Format() == Image_Format_Gray)
508     {
509       anImage->SetFormat (Image_Format_Alpha);
510     }
511     else if (anImage->Format() == Image_Format_GrayF)
512     {
513       anImage->SetFormat (Image_Format_AlphaF);
514     }
515     theImage = anImage;
516   }
517   return Standard_True;
518 }
519
520 //=======================================================================
521 //function : ParseShadingModel
522 //purpose  :
523 //=======================================================================
524 Standard_Boolean ViewerTest::ParseShadingModel (Standard_CString              theArg,
525                                                 Graphic3d_TypeOfShadingModel& theModel)
526 {
527   TCollection_AsciiString aTypeStr (theArg);
528   aTypeStr.LowerCase();
529   if (aTypeStr == "unlit"
530    || aTypeStr == "color"
531    || aTypeStr == "none")
532   {
533     theModel = Graphic3d_TOSM_UNLIT;
534   }
535   else if (aTypeStr == "flat"
536         || aTypeStr == "facet")
537   {
538     theModel = Graphic3d_TOSM_FACET;
539   }
540   else if (aTypeStr == "gouraud"
541         || aTypeStr == "vertex"
542         || aTypeStr == "vert")
543   {
544     theModel = Graphic3d_TOSM_VERTEX;
545   }
546   else if (aTypeStr == "phong"
547         || aTypeStr == "fragment"
548         || aTypeStr == "frag"
549         || aTypeStr == "pixel")
550   {
551     theModel = Graphic3d_TOSM_FRAGMENT;
552   }
553   else if (aTypeStr == "pbr")
554   {
555     theModel = Graphic3d_TOSM_PBR;
556   }
557   else if (aTypeStr == "pbr_facet")
558   {
559     theModel = Graphic3d_TOSM_PBR_FACET;
560   }
561   else if (aTypeStr == "default"
562         || aTypeStr == "def")
563   {
564     theModel = Graphic3d_TOSM_DEFAULT;
565   }
566   else if (aTypeStr.IsIntegerValue())
567   {
568     const int aTypeInt = aTypeStr.IntegerValue();
569     if (aTypeInt <= Graphic3d_TOSM_DEFAULT || aTypeInt >= Graphic3d_TypeOfShadingModel_NB)
570     {
571       return Standard_False;
572     }
573     theModel = (Graphic3d_TypeOfShadingModel)aTypeInt;
574   }
575   else
576   {
577     return Standard_False;
578   }
579   return Standard_True;
580 }
581
582 //=======================================================================
583 //function : parseZLayer
584 //purpose  :
585 //=======================================================================
586 Standard_Boolean ViewerTest::parseZLayer (Standard_CString theArg,
587                                           Standard_Boolean theToAllowInteger,
588                                           Graphic3d_ZLayerId& theLayer)
589 {
590   TCollection_AsciiString aName (theArg);
591   aName.LowerCase();
592   if (aName == "default"
593    || aName == "def")
594   {
595     theLayer = Graphic3d_ZLayerId_Default;
596   }
597   else if (aName == "top")
598   {
599     theLayer = Graphic3d_ZLayerId_Top;
600   }
601   else if (aName == "topmost")
602   {
603     theLayer = Graphic3d_ZLayerId_Topmost;
604   }
605   else if (aName == "overlay"
606         || aName == "toposd")
607   {
608     theLayer = Graphic3d_ZLayerId_TopOSD;
609   }
610   else if (aName == "underlay"
611         || aName == "botosd")
612   {
613     theLayer = Graphic3d_ZLayerId_BotOSD;
614   }
615   else if (aName == "undefined")
616   {
617     theLayer = Graphic3d_ZLayerId_UNKNOWN;
618   }
619   else if (!GetAISContext().IsNull())
620   {
621     const Handle(V3d_Viewer)& aViewer = ViewerTest::GetAISContext()->CurrentViewer();
622     TColStd_SequenceOfInteger aLayers;
623     aViewer->GetAllZLayers (aLayers);
624     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
625     {
626       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
627       if (TCollection_AsciiString::IsSameString (aSettings.Name(), aName, Standard_False))
628       {
629         theLayer = aLayeriter.Value();
630         return true;
631       }
632     }
633
634     if (!theToAllowInteger
635      || !aName.IsIntegerValue())
636     {
637       return false;
638     }
639     Graphic3d_ZLayerId aLayer = aName.IntegerValue();
640     if (aLayer == Graphic3d_ZLayerId_UNKNOWN
641      || std::find (aLayers.begin(), aLayers.end(), aLayer) != aLayers.end())
642     {
643       theLayer = aLayer;
644       return true;
645     }
646     return false;
647   }
648   return true;
649 }
650
651 //=======================================================================
652 //function : GetTypeNames
653 //purpose  :
654 //=======================================================================
655 static const char** GetTypeNames()
656 {
657   static const char* names[14] = {"Point","Axis","Trihedron","PlaneTrihedron", "Line","Circle","Plane",
658                           "Shape","ConnectedShape","MultiConn.Shape",
659                           "ConnectedInter.","MultiConn.",
660                           "Constraint","Dimension"};
661   static const char** ThePointer = names;
662   return ThePointer;
663 }
664
665 //=======================================================================
666 //function : GetTypeAndSignfromString
667 //purpose  :
668 //=======================================================================
669 void GetTypeAndSignfromString (const char* name,AIS_KindOfInteractive& TheType,Standard_Integer& TheSign)
670 {
671   const char ** thefullnames = GetTypeNames();
672   Standard_Integer index(-1);
673
674   for(Standard_Integer i=0;i<=13 && index==-1;i++)
675     if(!strcasecmp(name,thefullnames[i]))
676       index = i;
677
678   if(index ==-1){
679     TheType = AIS_KOI_None;
680     TheSign = -1;
681     return;
682   }
683
684   if(index<=6){
685     TheType = AIS_KOI_Datum;
686     TheSign = index+1;
687   }
688   else if (index <=9){
689     TheType = AIS_KOI_Shape;
690     TheSign = index-7;
691   }
692   else if(index<=11){
693     TheType = AIS_KOI_Object;
694     TheSign = index-10;
695   }
696   else{
697     TheType = AIS_KOI_Relation;
698     TheSign = index-12;
699   }
700
701 }
702
703
704
705 #include <string.h>
706 #include <Draw_Interpretor.hxx>
707 #include <Draw.hxx>
708 #include <Draw_Appli.hxx>
709 #include <DBRep.hxx>
710
711
712 #include <TCollection_AsciiString.hxx>
713 #include <V3d_Viewer.hxx>
714 #include <V3d_View.hxx>
715 #include <V3d.hxx>
716
717 #include <AIS_InteractiveContext.hxx>
718 #include <AIS_Shape.hxx>
719 #include <AIS_DisplayMode.hxx>
720 #include <TColStd_MapOfInteger.hxx>
721 #include <AIS_MapOfInteractive.hxx>
722 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
723 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
724 #include <ViewerTest_EventManager.hxx>
725
726 #include <TopoDS_Solid.hxx>
727 #include <BRepTools.hxx>
728 #include <BRep_Builder.hxx>
729 #include <TopAbs_ShapeEnum.hxx>
730
731 #include <TopoDS.hxx>
732 #include <BRep_Tool.hxx>
733
734
735 #include <Draw_Window.hxx>
736 #include <AIS_ListIteratorOfListOfInteractive.hxx>
737 #include <AIS_ListOfInteractive.hxx>
738 #include <AIS_DisplayMode.hxx>
739 #include <TopTools_ListOfShape.hxx>
740 #include <BRepOffsetAPI_MakeThickSolid.hxx>
741
742 //==============================================================================
743 //  VIEWER OBJECT MANAGEMENT GLOBAL VARIABLES
744 //==============================================================================
745 Standard_EXPORT ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(){
746   static ViewerTest_DoubleMapOfInteractiveAndName TheMap;
747   return TheMap;
748 }
749
750 //=======================================================================
751 //function : Display
752 //purpose  :
753 //=======================================================================
754 Standard_Boolean ViewerTest::Display (const TCollection_AsciiString&       theName,
755                                       const Handle(AIS_InteractiveObject)& theObject,
756                                       const Standard_Boolean               theToUpdate,
757                                       const Standard_Boolean               theReplaceIfExists)
758 {
759   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
760   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
761   if (aCtx.IsNull())
762   {
763     Message::SendFail ("Error: AIS context is not available.");
764     return Standard_False;
765   }
766
767   if (aMap.IsBound2 (theName))
768   {
769     if (!theReplaceIfExists)
770     {
771       Message::SendFail() << "Error: other interactive object has been already registered with name: " << theName << ".\n"
772                           << "Please use another name.";
773       return Standard_False;
774     }
775
776     if (Handle(AIS_InteractiveObject) anOldObj = aMap.Find2 (theName))
777     {
778       aCtx->Remove (anOldObj, theObject.IsNull() && theToUpdate);
779     }
780     aMap.UnBind2 (theName);
781   }
782
783   if (theObject.IsNull())
784   {
785     // object with specified name has been already unbound
786     return Standard_True;
787   }
788
789   // unbind AIS object if it was bound with another name
790   aMap.UnBind1 (theObject);
791
792   // can be registered without rebinding
793   aMap.Bind (theObject, theName);
794   aCtx->Display (theObject, theToUpdate);
795   return Standard_True;
796 }
797
798 //! Alias for ViewerTest::Display(), compatibility with old code.
799 Standard_EXPORT Standard_Boolean VDisplayAISObject (const TCollection_AsciiString&       theName,
800                                                     const Handle(AIS_InteractiveObject)& theObject,
801                                                     Standard_Boolean theReplaceIfExists = Standard_True)
802 {
803   return ViewerTest::Display (theName, theObject, Standard_True, theReplaceIfExists);
804 }
805
806 static NCollection_List<Handle(ViewerTest_EventManager)> theEventMgrs;
807
808 static Handle(V3d_View)&  a3DView()
809 {
810   static Handle(V3d_View) Viou;
811   return Viou;
812 }
813
814
815 Standard_EXPORT Handle(AIS_InteractiveContext)& TheAISContext(){
816   static Handle(AIS_InteractiveContext) aContext;
817   return aContext;
818 }
819
820 const Handle(V3d_View)& ViewerTest::CurrentView()
821 {
822   return a3DView();
823 }
824 void ViewerTest::CurrentView(const Handle(V3d_View)& V)
825 {
826   a3DView() = V;
827 }
828
829 const Handle(AIS_InteractiveContext)& ViewerTest::GetAISContext()
830 {
831   return TheAISContext();
832 }
833
834 void ViewerTest::SetAISContext (const Handle(AIS_InteractiveContext)& aCtx)
835 {
836   TheAISContext() = aCtx;
837   ViewerTest::ResetEventManager();
838 }
839
840 Handle(V3d_Viewer) ViewerTest::GetViewerFromContext()
841 {
842   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
843 }
844
845 Handle(V3d_Viewer) ViewerTest::GetCollectorFromContext()
846 {
847   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
848 }
849
850
851 void ViewerTest::SetEventManager(const Handle(ViewerTest_EventManager)& EM){
852   theEventMgrs.Prepend(EM);
853 }
854
855 void ViewerTest::UnsetEventManager()
856 {
857   theEventMgrs.RemoveFirst();
858 }
859
860
861 void ViewerTest::ResetEventManager()
862 {
863   theEventMgrs.Clear();
864   theEventMgrs.Prepend (new ViewerTest_EventManager (ViewerTest::CurrentView(), ViewerTest::GetAISContext()));
865 }
866
867 Handle(ViewerTest_EventManager) ViewerTest::CurrentEventManager()
868 {
869   return !theEventMgrs.IsEmpty()
870         ? theEventMgrs.First()
871         : Handle(ViewerTest_EventManager)();
872 }
873
874 //=======================================================================
875 //function : Get Context and active view
876 //purpose  :
877 //=======================================================================
878 static Standard_Boolean getCtxAndView (Handle(AIS_InteractiveContext)& theCtx,
879                                        Handle(V3d_View)&               theView)
880 {
881   theCtx  = ViewerTest::GetAISContext();
882   theView = ViewerTest::CurrentView();
883   if (theCtx.IsNull()
884    || theView.IsNull())
885   {
886     Message::SendFail ("Error: cannot find an active view!");
887     return Standard_False;
888   }
889   return Standard_True;
890 }
891
892 //==============================================================================
893 //function : Clear
894 //purpose  : Remove all the object from the viewer
895 //==============================================================================
896 void ViewerTest::Clear()
897 {
898   if (a3DView().IsNull())
899   {
900     return;
901   }
902
903   NCollection_Sequence<Handle(AIS_InteractiveObject)> aListRemoved;
904   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS()); anObjIter.More(); anObjIter.Next())
905   {
906     const Handle(AIS_InteractiveObject) anObj = anObjIter.Key1();
907     if (anObj->GetContext() != TheAISContext())
908     {
909       continue;
910     }
911
912     Message::SendInfo() << "Remove " << anObjIter.Key2();
913     TheAISContext()->Remove (anObj, Standard_False);
914     aListRemoved.Append (anObj);
915   }
916
917   TheAISContext()->RebuildSelectionStructs();
918   TheAISContext()->UpdateCurrentViewer();
919   if (aListRemoved.Size() == GetMapOfAIS().Extent())
920   {
921     GetMapOfAIS().Clear();
922   }
923   else
924   {
925     for (NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator anObjIter (aListRemoved); anObjIter.More(); anObjIter.Next())
926     {
927       GetMapOfAIS().UnBind1 (anObjIter.Value());
928     }
929   }
930 }
931
932 //==============================================================================
933 //function : CopyIsoAspect
934 //purpose  : Returns copy Prs3d_IsoAspect with new number of isolines.
935 //==============================================================================
936 static Handle(Prs3d_IsoAspect) CopyIsoAspect
937       (const Handle(Prs3d_IsoAspect) &theIsoAspect,
938        const Standard_Integer theNbIsos)
939 {
940   Quantity_Color    aColor = theIsoAspect->Aspect()->Color();
941   Aspect_TypeOfLine aType  = theIsoAspect->Aspect()->Type();
942   Standard_Real     aWidth = theIsoAspect->Aspect()->Width();
943
944   Handle(Prs3d_IsoAspect) aResult =
945     new Prs3d_IsoAspect(aColor, aType, aWidth, theNbIsos);
946
947   return aResult;
948 }
949
950 //==============================================================================
951 //function : visos
952 //purpose  : Returns or sets the number of U- and V- isos and isIsoOnPlane flag
953 //Draw arg : [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]
954 //==============================================================================
955 static int visos (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
956 {
957   if (TheAISContext().IsNull()) {
958     di << argv[0] << " Call 'vinit' before!\n";
959     return 1;
960   }
961
962   if (argc <= 1) {
963     di << "Current number of isos : " <<
964       TheAISContext()->IsoNumber(AIS_TOI_IsoU) << " " <<
965       TheAISContext()->IsoNumber(AIS_TOI_IsoV) << "\n";
966     di << "IsoOnPlane mode is " <<
967       (TheAISContext()->IsoOnPlane() ? "ON" : "OFF") << "\n";
968     di << "IsoOnTriangulation mode is " <<
969       (TheAISContext()->IsoOnTriangulation() ? "ON" : "OFF") << "\n";
970     return 0;
971   }
972
973   Standard_Integer aLastInd = argc - 1;
974   Standard_Boolean isChanged = Standard_False;
975   Standard_Integer aNbUIsos = 0;
976   Standard_Integer aNbVIsos = 0;
977
978   if (aLastInd >= 3) {
979     Standard_Boolean isIsoOnPlane = Standard_False;
980
981     if (strcmp(argv[aLastInd], "1") == 0) {
982       isIsoOnPlane = Standard_True;
983       isChanged    = Standard_True;
984     } else if (strcmp(argv[aLastInd], "0") == 0) {
985       isIsoOnPlane = Standard_False;
986       isChanged    = Standard_True;
987     }
988
989     if (isChanged) {
990       aNbVIsos = Draw::Atoi(argv[aLastInd - 1]);
991       aNbUIsos = Draw::Atoi(argv[aLastInd - 2]);
992       aLastInd -= 3;
993
994       di << "New number of isos : " << aNbUIsos << " " << aNbVIsos << "\n";
995       di << "New IsoOnPlane mode is " << (isIsoOnPlane ? "ON" : "OFF") << "\n";
996
997       TheAISContext()->IsoOnPlane(isIsoOnPlane);
998
999       if (aLastInd == 0) {
1000         // If there are no shapes provided set the default numbers.
1001         TheAISContext()->SetIsoNumber(aNbUIsos, AIS_TOI_IsoU);
1002         TheAISContext()->SetIsoNumber(aNbVIsos, AIS_TOI_IsoV);
1003       }
1004     }
1005   }
1006
1007   Standard_Integer i;
1008
1009   for (i = 1; i <= aLastInd; i++)
1010   {
1011     TCollection_AsciiString name(argv[i]);
1012     Handle(AIS_InteractiveObject) aShape;
1013     GetMapOfAIS().Find2(name, aShape);
1014     if (aShape.IsNull())
1015     {
1016       Message::SendFail() << "Syntax error: object '" << name << "' is not found";
1017       return 1;
1018     }
1019
1020     Handle(Prs3d_Drawer) CurDrawer = aShape->Attributes();
1021     Handle(Prs3d_IsoAspect) aUIso = CurDrawer->UIsoAspect();
1022     Handle(Prs3d_IsoAspect) aVIso = CurDrawer->VIsoAspect();
1023     if (isChanged)
1024     {
1025       CurDrawer->SetUIsoAspect(CopyIsoAspect(aUIso, aNbUIsos));
1026       CurDrawer->SetVIsoAspect(CopyIsoAspect(aVIso, aNbVIsos));
1027       TheAISContext()->SetLocalAttributes (aShape, CurDrawer, Standard_False);
1028       TheAISContext()->Redisplay (aShape, Standard_False);
1029     }
1030     else
1031     {
1032       di << "Number of isos for " << argv[i] << " : "
1033           << aUIso->Number() << " " << aVIso->Number() << "\n";
1034     }
1035   }
1036
1037   if (isChanged) {
1038     TheAISContext()->UpdateCurrentViewer();
1039   }
1040
1041   return 0;
1042 }
1043
1044 static Standard_Integer VDispSensi (Draw_Interpretor& ,
1045                                     Standard_Integer  theArgNb,
1046                                     Standard_CString* )
1047 {
1048   if (theArgNb > 1)
1049   {
1050     Message::SendFail ("Error: wrong syntax!");
1051     return 1;
1052   }
1053
1054   Handle(AIS_InteractiveContext) aCtx;
1055   Handle(V3d_View)               aView;
1056   if (!getCtxAndView (aCtx, aView))
1057   {
1058     return 1;
1059   }
1060
1061   aCtx->DisplayActiveSensitive (aView);
1062   return 0;
1063
1064 }
1065
1066 static Standard_Integer VClearSensi (Draw_Interpretor& ,
1067                                      Standard_Integer  theArgNb,
1068                                      Standard_CString* )
1069 {
1070   if (theArgNb > 1)
1071   {
1072     Message::SendFail ("Error: wrong syntax!");
1073     return 1;
1074   }
1075
1076   Handle(AIS_InteractiveContext) aCtx;
1077   Handle(V3d_View)               aView;
1078   if (!getCtxAndView (aCtx, aView))
1079   {
1080     return 1;
1081   }
1082   aCtx->ClearActiveSensitive (aView);
1083   return 0;
1084 }
1085
1086 //==============================================================================
1087 //function : VDir
1088 //purpose  : To list the displayed object with their attributes
1089 //==============================================================================
1090 static int VDir (Draw_Interpretor& theDI,
1091                  Standard_Integer theNbArgs,
1092                  const char** theArgVec)
1093 {
1094   TCollection_AsciiString aMatch;
1095   Standard_Boolean toFormat = Standard_False;
1096   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
1097   {
1098     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
1099     anArgCase.LowerCase();
1100     if (anArgCase == "-list"
1101      || anArgCase == "-format")
1102     {
1103       toFormat = Standard_True;
1104     }
1105     else if (aMatch.IsEmpty())
1106     {
1107       aMatch = theArgVec[anArgIter];
1108     }
1109     else
1110     {
1111       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
1112       return 1;
1113     }
1114   }
1115
1116   TCollection_AsciiString aRes;
1117   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); anIter.More(); anIter.Next())
1118   {
1119     if (!aMatch.IsEmpty())
1120     {
1121       const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aMatch + "' '" + anIter.Key2() + "'";
1122       if (theDI.Eval (aCheck.ToCString()) == 0
1123       && *theDI.Result() != '1')
1124       {
1125         continue;
1126       }
1127     }
1128
1129     if (toFormat)
1130     {
1131       aRes += TCollection_AsciiString("\t") + anIter.Key2() + "\n";
1132     }
1133     else
1134     {
1135       aRes += anIter.Key2() + " ";
1136     }
1137   }
1138   theDI.Reset();
1139   theDI << aRes;
1140   return 0;
1141 }
1142
1143 //! Auxiliary enumeration
1144 enum ViewerTest_StereoPair
1145 {
1146   ViewerTest_SP_Single,
1147   ViewerTest_SP_SideBySide,
1148   ViewerTest_SP_OverUnder
1149 };
1150
1151 //==============================================================================
1152 //function : VDump
1153 //purpose  : To dump the active view snapshot to image file
1154 //==============================================================================
1155 static Standard_Integer VDump (Draw_Interpretor& theDI,
1156                                Standard_Integer  theArgNb,
1157                                Standard_CString* theArgVec)
1158 {
1159   Handle(V3d_View) aView = ViewerTest::CurrentView();
1160   if (theArgNb < 2)
1161   {
1162     Message::SendFail ("Error: wrong number of arguments! Image file name should be specified at least.");
1163     return 1;
1164   }
1165   if (aView.IsNull())
1166   {
1167     Message::SendFail() << "Error: cannot find an active view!";
1168     return 1;
1169   }
1170
1171   Standard_Integer      anArgIter   = 1;
1172   Standard_CString      aFilePath   = theArgVec[anArgIter++];
1173   ViewerTest_StereoPair aStereoPair = ViewerTest_SP_Single;
1174   V3d_ImageDumpOptions  aParams;
1175   Handle(Graphic3d_Camera) aCustomCam;
1176   aParams.BufferType    = Graphic3d_BT_RGB;
1177   aParams.StereoOptions = V3d_SDO_MONO;
1178   for (; anArgIter < theArgNb; ++anArgIter)
1179   {
1180     TCollection_AsciiString anArg (theArgVec[anArgIter]);
1181     anArg.LowerCase();
1182     if (anArg == "-buffer")
1183     {
1184       if (++anArgIter >= theArgNb)
1185       {
1186         Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
1187         return 1;
1188       }
1189
1190       TCollection_AsciiString aBufArg (theArgVec[anArgIter]);
1191       aBufArg.LowerCase();
1192       if (aBufArg == "rgba")
1193       {
1194         aParams.BufferType = Graphic3d_BT_RGBA;
1195       }
1196       else if (aBufArg == "rgb")
1197       {
1198         aParams.BufferType = Graphic3d_BT_RGB;
1199       }
1200       else if (aBufArg == "red")
1201       {
1202         aParams.BufferType = Graphic3d_BT_Red;
1203       }
1204       else if (aBufArg == "depth")
1205       {
1206         aParams.BufferType = Graphic3d_BT_Depth;
1207       }
1208       else
1209       {
1210         Message::SendFail() << "Error: unknown buffer '" << aBufArg << "'";
1211         return 1;
1212       }
1213     }
1214     else if (anArgIter + 1 < theArgNb
1215           && anArg == "-xrpose")
1216     {
1217       TCollection_AsciiString anXRArg (theArgVec[++anArgIter]);
1218       anXRArg.LowerCase();
1219       if (anXRArg == "base")
1220       {
1221         aCustomCam = aView->View()->BaseXRCamera();
1222       }
1223       else if (anXRArg == "head")
1224       {
1225         aCustomCam = aView->View()->PosedXRCamera();
1226       }
1227       else if (anXRArg == "handleft"
1228             || anXRArg == "handright")
1229       {
1230         if (aView->View()->IsActiveXR())
1231         {
1232           aCustomCam = new Graphic3d_Camera();
1233           aView->View()->ComputeXRPosedCameraFromBase (*aCustomCam, anXRArg == "handleft"
1234                                                      ? aView->View()->XRSession()->LeftHandPose()
1235                                                      : aView->View()->XRSession()->RightHandPose());
1236         }
1237       }
1238       else
1239       {
1240         Message::SendFail() << "Syntax error: unknown XR pose '" << anXRArg << "'";
1241         return 1;
1242       }
1243       if (aCustomCam.IsNull())
1244       {
1245         Message::SendFail() << "Error: undefined XR pose";
1246         return 0;
1247       }
1248     }
1249     else if (anArg == "-stereo")
1250     {
1251       if (++anArgIter >= theArgNb)
1252       {
1253         Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
1254         return 1;
1255       }
1256
1257       TCollection_AsciiString aStereoArg (theArgVec[anArgIter]);
1258       aStereoArg.LowerCase();
1259       if (aStereoArg == "l"
1260        || aStereoArg == "left")
1261       {
1262         aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1263       }
1264       else if (aStereoArg == "r"
1265             || aStereoArg == "right")
1266       {
1267         aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1268       }
1269       else if (aStereoArg == "mono")
1270       {
1271         aParams.StereoOptions = V3d_SDO_MONO;
1272       }
1273       else if (aStereoArg == "blended"
1274             || aStereoArg == "blend"
1275             || aStereoArg == "stereo")
1276       {
1277         aParams.StereoOptions = V3d_SDO_BLENDED;
1278       }
1279       else if (aStereoArg == "sbs"
1280             || aStereoArg == "sidebyside")
1281       {
1282         aStereoPair = ViewerTest_SP_SideBySide;
1283       }
1284       else if (aStereoArg == "ou"
1285             || aStereoArg == "overunder")
1286       {
1287         aStereoPair = ViewerTest_SP_OverUnder;
1288       }
1289       else
1290       {
1291         Message::SendFail() << "Error: unknown stereo format '" << aStereoArg << "'";
1292         return 1;
1293       }
1294     }
1295     else if (anArg == "-rgba"
1296           || anArg ==  "rgba")
1297     {
1298       aParams.BufferType = Graphic3d_BT_RGBA;
1299     }
1300     else if (anArg == "-rgb"
1301           || anArg ==  "rgb")
1302     {
1303       aParams.BufferType = Graphic3d_BT_RGB;
1304     }
1305     else if (anArg == "-red"
1306           || anArg ==  "red")
1307     {
1308       aParams.BufferType = Graphic3d_BT_Red;
1309     }
1310     else if (anArg == "-depth"
1311           || anArg ==  "depth")
1312     {
1313       aParams.BufferType = Graphic3d_BT_Depth;
1314     }
1315     else if (anArg == "-width"
1316           || anArg ==  "width"
1317           || anArg ==  "sizex")
1318     {
1319       if (aParams.Width != 0)
1320       {
1321         Message::SendFail() << "Error: wrong syntax at " << theArgVec[anArgIter];
1322         return 1;
1323       }
1324       else if (++anArgIter >= theArgNb)
1325       {
1326         Message::SendFail() << "Error: integer value is expected right after 'width'";
1327         return 1;
1328       }
1329       aParams.Width = Draw::Atoi (theArgVec[anArgIter]);
1330     }
1331     else if (anArg == "-height"
1332           || anArg ==  "height"
1333           || anArg ==  "-sizey")
1334     {
1335       if (aParams.Height != 0)
1336       {
1337         Message::SendFail() << "Error: wrong syntax at " << theArgVec[anArgIter];
1338         return 1;
1339       }
1340       else if (++anArgIter >= theArgNb)
1341       {
1342         Message::SendFail() << "Error: integer value is expected right after 'height'";
1343         return 1;
1344       }
1345       aParams.Height = Draw::Atoi (theArgVec[anArgIter]);
1346     }
1347     else if (anArg == "-tile"
1348           || anArg == "-tilesize")
1349     {
1350       if (++anArgIter >= theArgNb)
1351       {
1352         Message::SendFail() << "Error: integer value is expected right after 'tileSize'";
1353         return 1;
1354       }
1355       aParams.TileSize = Draw::Atoi (theArgVec[anArgIter]);
1356     }
1357     else
1358     {
1359       Message::SendFail() << "Error: unknown argument '" << theArgVec[anArgIter] << "'";
1360       return 1;
1361     }
1362   }
1363   if ((aParams.Width <= 0 && aParams.Height >  0)
1364    || (aParams.Width >  0 && aParams.Height <= 0))
1365   {
1366     Message::SendFail() << "Error: dimensions " << aParams.Width << "x" << aParams.Height << " are incorrect";
1367     return 1;
1368   }
1369
1370   if (aParams.Width <= 0 || aParams.Height <= 0)
1371   {
1372     aView->Window()->Size (aParams.Width, aParams.Height);
1373   }
1374
1375   Image_AlienPixMap aPixMap;
1376   Image_Format aFormat = Image_Format_UNKNOWN;
1377   switch (aParams.BufferType)
1378   {
1379     case Graphic3d_BT_RGB:                 aFormat = Image_Format_RGB;   break;
1380     case Graphic3d_BT_RGBA:                aFormat = Image_Format_RGBA;  break;
1381     case Graphic3d_BT_Depth:               aFormat = Image_Format_GrayF; break;
1382     case Graphic3d_BT_RGB_RayTraceHdrLeft: aFormat = Image_Format_RGBF;  break;
1383     case Graphic3d_BT_Red:                 aFormat = Image_Format_Gray;  break;
1384   }
1385
1386   const bool wasImmUpdate = aView->SetImmediateUpdate (false);
1387   Handle(Graphic3d_Camera) aCamBack = aView->Camera();
1388   if (!aCustomCam.IsNull())
1389   {
1390     aView->SetCamera (aCustomCam);
1391   }
1392   switch (aStereoPair)
1393   {
1394     case ViewerTest_SP_Single:
1395     {
1396       if (!aView->ToPixMap (aPixMap, aParams))
1397       {
1398         theDI << "Fail: view dump failed!\n";
1399         return 0;
1400       }
1401       else if (aPixMap.SizeX() != Standard_Size(aParams.Width)
1402             || aPixMap.SizeY() != Standard_Size(aParams.Height))
1403       {
1404         theDI << "Fail: dumped dimensions "    << (Standard_Integer )aPixMap.SizeX() << "x" << (Standard_Integer )aPixMap.SizeY()
1405               << " are lesser than requested " << aParams.Width << "x" << aParams.Height << "\n";
1406       }
1407       break;
1408     }
1409     case ViewerTest_SP_SideBySide:
1410     {
1411       if (!aPixMap.InitZero (aFormat, aParams.Width * 2, aParams.Height))
1412       {
1413         theDI << "Fail: not enough memory for image allocation!\n";
1414         return 0;
1415       }
1416
1417       Image_PixMap aPixMapL, aPixMapR;
1418       aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
1419                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1420       aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizePixelBytes() * aParams.Width,
1421                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1422
1423       aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1424       Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams);
1425       aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1426       isOk          = isOk && aView->ToPixMap (aPixMapR, aParams);
1427       if (!isOk)
1428       {
1429         theDI << "Fail: view dump failed!\n";
1430         return 0;
1431       }
1432       break;
1433     }
1434     case ViewerTest_SP_OverUnder:
1435     {
1436       if (!aPixMap.InitZero (aFormat, aParams.Width, aParams.Height * 2))
1437       {
1438         theDI << "Fail: not enough memory for image allocation!\n";
1439         return 0;
1440       }
1441
1442       Image_PixMap aPixMapL, aPixMapR;
1443       aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
1444                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1445       aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizeRowBytes() * aParams.Height,
1446                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1447
1448       aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1449       Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams);
1450       aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1451       isOk          = isOk && aView->ToPixMap (aPixMapR, aParams);
1452       if (!isOk)
1453       {
1454         theDI << "Fail: view dump failed!\n";
1455         return 0;
1456       }
1457       break;
1458     }
1459   }
1460   if (!aCustomCam.IsNull())
1461   {
1462     aView->SetCamera (aCamBack);
1463   }
1464   aView->SetImmediateUpdate (wasImmUpdate);
1465
1466   if (!aPixMap.Save (aFilePath))
1467   {
1468     theDI << "Fail: image can not be saved!\n";
1469   }
1470   return 0;
1471 }
1472
1473 enum TypeOfDispOperation
1474 {
1475   TypeOfDispOperation_SetDispMode,
1476   TypeOfDispOperation_UnsetDispMode
1477 };
1478
1479 //! Displays,Erase...
1480 static void VwrTst_DispErase (const Handle(AIS_InteractiveObject)& thePrs,
1481                                                 const Standard_Integer theMode,
1482                                                 const TypeOfDispOperation theType,
1483                                                 const Standard_Boolean theToUpdate)
1484 {
1485   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1486   switch (theType)
1487   {
1488     case TypeOfDispOperation_SetDispMode:
1489     {
1490       if (!thePrs.IsNull())
1491       {
1492         aCtx->SetDisplayMode (thePrs, theMode, theToUpdate);
1493       }
1494       else
1495       {
1496         aCtx->SetDisplayMode ((AIS_DisplayMode )theMode, theToUpdate);
1497       }
1498       break;
1499     }
1500     case TypeOfDispOperation_UnsetDispMode:
1501     {
1502       if (!thePrs.IsNull())
1503       {
1504         aCtx->UnsetDisplayMode (thePrs, theToUpdate);
1505       }
1506       else
1507       {
1508         aCtx->SetDisplayMode (AIS_WireFrame, theToUpdate);
1509       }
1510       break;
1511     }
1512   }
1513 }
1514
1515 //=======================================================================
1516 //function :
1517 //purpose  :
1518 //=======================================================================
1519 static int VDispMode (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1520 {
1521   if (argc < 1
1522    || argc > 3)
1523   {
1524     Message::SendFail() << "Syntax error: wrong number of arguments";
1525     return 1;
1526   }
1527
1528   TypeOfDispOperation aType = TCollection_AsciiString (argv[0]) == "vunsetdispmode"
1529                             ? TypeOfDispOperation_UnsetDispMode
1530                             : TypeOfDispOperation_SetDispMode;
1531   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1532   if (aType == TypeOfDispOperation_UnsetDispMode)
1533   {
1534     if (argc == 1)
1535     {
1536       if (aCtx->NbSelected() == 0)
1537       {
1538         VwrTst_DispErase (Handle(AIS_InteractiveObject)(), -1, TypeOfDispOperation_UnsetDispMode, Standard_False);
1539       }
1540       else
1541       {
1542         for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
1543         {
1544           VwrTst_DispErase (aCtx->SelectedInteractive(), -1, TypeOfDispOperation_UnsetDispMode, Standard_False);
1545         }
1546       }
1547       aCtx->UpdateCurrentViewer();
1548     }
1549     else
1550     {
1551       TCollection_AsciiString aName = argv[1];
1552       Handle(AIS_InteractiveObject) aPrs;
1553       if (GetMapOfAIS().Find2 (aName, aPrs)
1554       && !aPrs.IsNull())
1555       {
1556         VwrTst_DispErase (aPrs, -1, TypeOfDispOperation_UnsetDispMode, Standard_True);
1557       }
1558     }
1559   }
1560   else if (argc == 2)
1561   {
1562     Standard_Integer aDispMode = Draw::Atoi (argv[1]);
1563     if (aCtx->NbSelected() == 0
1564      && aType == TypeOfDispOperation_SetDispMode)
1565     {
1566       VwrTst_DispErase (Handle(AIS_InteractiveObject)(), aDispMode, TypeOfDispOperation_SetDispMode, Standard_True);
1567     }
1568     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
1569     {
1570       VwrTst_DispErase (aCtx->SelectedInteractive(), aDispMode, aType, Standard_False);
1571     }
1572     aCtx->UpdateCurrentViewer();
1573   }
1574   else
1575   {
1576     Handle(AIS_InteractiveObject) aPrs;
1577     TCollection_AsciiString aName (argv[1]);
1578     if (GetMapOfAIS().Find2 (aName, aPrs)
1579      && !aPrs.IsNull())
1580     {
1581       VwrTst_DispErase (aPrs, Draw::Atoi(argv[2]), aType, Standard_True);
1582     }
1583   }
1584   return 0;
1585 }
1586
1587
1588 //=======================================================================
1589 //function :
1590 //purpose  :
1591 //=======================================================================
1592 static int VSubInt(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1593 {
1594   if(argc==1) return 1;
1595   Standard_Integer On = Draw::Atoi(argv[1]);
1596   const Handle(AIS_InteractiveContext)& Ctx = ViewerTest::GetAISContext();
1597
1598   if(argc==2)
1599   {
1600     TCollection_AsciiString isOnOff = On == 1 ? "on" : "off";
1601     di << "Sub intensite is turned " << isOnOff << " for " << Ctx->NbSelected() << "objects\n";
1602     for (Ctx->InitSelected(); Ctx->MoreSelected(); Ctx->NextSelected())
1603     {
1604       if(On==1)
1605       {
1606         Ctx->SubIntensityOn (Ctx->SelectedInteractive(), Standard_False);
1607       }
1608       else
1609       {
1610         Ctx->SubIntensityOff (Ctx->SelectedInteractive(), Standard_False);
1611       }
1612     }
1613
1614     Ctx->UpdateCurrentViewer();
1615   }
1616   else {
1617     Handle(AIS_InteractiveObject) IO;
1618     TCollection_AsciiString name = argv[2];
1619     if (GetMapOfAIS().Find2 (name, IO)
1620     && !IO.IsNull())
1621     {
1622       if(On==1)
1623         Ctx->SubIntensityOn(IO, Standard_True);
1624       else
1625         Ctx->SubIntensityOff(IO, Standard_True);
1626     }
1627     else return 1;
1628   }
1629   return 0;
1630 }
1631
1632 //! Auxiliary class to iterate presentations from different collections.
1633 class ViewTest_PrsIter
1634 {
1635 public:
1636
1637   //! Create and initialize iterator object.
1638   ViewTest_PrsIter (const TCollection_AsciiString& theName)
1639   : mySource (IterSource_All)
1640   {
1641     NCollection_Sequence<TCollection_AsciiString> aNames;
1642     if (!theName.IsEmpty())
1643     aNames.Append (theName);
1644     Init (aNames);
1645   }
1646
1647   //! Create and initialize iterator object.
1648   ViewTest_PrsIter (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1649   : mySource (IterSource_All)
1650   {
1651     Init (theNames);
1652   }
1653
1654   //! Initialize the iterator.
1655   void Init (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1656   {
1657     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1658     mySeq = theNames;
1659     mySelIter.Nullify();
1660     myCurrent.Nullify();
1661     myCurrentTrs.Nullify();
1662     if (!mySeq.IsEmpty())
1663     {
1664       mySource = IterSource_List;
1665       mySeqIter = NCollection_Sequence<TCollection_AsciiString>::Iterator (mySeq);
1666     }
1667     else if (aCtx->NbSelected() > 0)
1668     {
1669       mySource  = IterSource_Selected;
1670       mySelIter = aCtx;
1671       mySelIter->InitSelected();
1672     }
1673     else
1674     {
1675       mySource = IterSource_All;
1676       myMapIter.Initialize (GetMapOfAIS());
1677     }
1678     initCurrent();
1679   }
1680
1681   const TCollection_AsciiString& CurrentName() const
1682   {
1683     return myCurrentName;
1684   }
1685
1686   const Handle(AIS_InteractiveObject)& Current() const
1687   {
1688     return myCurrent;
1689   }
1690
1691   const Handle(Standard_Transient)& CurrentTrs() const
1692   {
1693     return myCurrentTrs;
1694   }
1695
1696   //! @return true if iterator points to valid object within collection
1697   Standard_Boolean More() const
1698   {
1699     switch (mySource)
1700     {
1701       case IterSource_All:      return myMapIter.More();
1702       case IterSource_List:     return mySeqIter.More();
1703       case IterSource_Selected: return mySelIter->MoreSelected();
1704     }
1705     return Standard_False;
1706   }
1707
1708   //! Go to the next item.
1709   void Next()
1710   {
1711     myCurrentName.Clear();
1712     myCurrentTrs.Nullify();
1713     myCurrent.Nullify();
1714     switch (mySource)
1715     {
1716       case IterSource_All:
1717       {
1718         myMapIter.Next();
1719         break;
1720       }
1721       case IterSource_List:
1722       {
1723         mySeqIter.Next();
1724         break;
1725       }
1726       case IterSource_Selected:
1727       {
1728         mySelIter->NextSelected();
1729         break;
1730       }
1731     }
1732     initCurrent();
1733   }
1734
1735 private:
1736
1737   void initCurrent()
1738   {
1739     switch (mySource)
1740     {
1741       case IterSource_All:
1742       {
1743         if (myMapIter.More())
1744         {
1745           myCurrentName = myMapIter.Key2();
1746           myCurrentTrs  = myMapIter.Key1();
1747           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1748         }
1749         break;
1750       }
1751       case IterSource_List:
1752       {
1753         if (mySeqIter.More())
1754         {
1755           if (!GetMapOfAIS().IsBound2 (mySeqIter.Value()))
1756           {
1757             Message::SendFail() << "Error: object " << mySeqIter.Value() << " is not displayed!";
1758             return;
1759           }
1760           myCurrentName = mySeqIter.Value();
1761           myCurrentTrs  = GetMapOfAIS().Find2 (mySeqIter.Value());
1762           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1763         }
1764         break;
1765       }
1766       case IterSource_Selected:
1767       {
1768         if (mySelIter->MoreSelected())
1769         {
1770           myCurrentName = GetMapOfAIS().Find1 (mySelIter->SelectedInteractive());
1771           myCurrent     = mySelIter->SelectedInteractive();
1772         }
1773         break;
1774       }
1775     }
1776   }
1777
1778 private:
1779
1780   enum IterSource
1781   {
1782     IterSource_All,
1783     IterSource_List,
1784     IterSource_Selected
1785   };
1786
1787 private:
1788
1789   Handle(AIS_InteractiveContext) mySelIter;    //!< iterator for current (selected) objects (IterSource_Selected)
1790   ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName myMapIter; //!< iterator for map of all objects (IterSource_All)
1791   NCollection_Sequence<TCollection_AsciiString>           mySeq;
1792   NCollection_Sequence<TCollection_AsciiString>::Iterator mySeqIter;
1793
1794   TCollection_AsciiString        myCurrentName;//!< current item name
1795   Handle(Standard_Transient)     myCurrentTrs; //!< current item (as transient object)
1796   Handle(AIS_InteractiveObject)  myCurrent;    //!< current item
1797
1798   IterSource                     mySource;     //!< iterated collection
1799
1800 };
1801
1802 //! Parse interior style name.
1803 static bool parseInteriorStyle (const TCollection_AsciiString& theArg,
1804                                 Aspect_InteriorStyle& theStyle)
1805 {
1806   TCollection_AsciiString anArg (theArg);
1807   anArg.LowerCase();
1808   if (anArg == "empty")
1809   {
1810     theStyle = Aspect_IS_EMPTY;
1811   }
1812   else if (anArg == "hollow")
1813   {
1814     theStyle = Aspect_IS_HOLLOW;
1815   }
1816   else if (anArg == "solid")
1817   {
1818     theStyle = Aspect_IS_SOLID;
1819   }
1820   else if (anArg == "hatch")
1821   {
1822     theStyle = Aspect_IS_HATCH;
1823   }
1824   else if (anArg == "hiddenline"
1825         || anArg == "hidden-line"
1826         || anArg == "hidden_line")
1827   {
1828     theStyle = Aspect_IS_HIDDENLINE;
1829   }
1830   else if (anArg == "point")
1831   {
1832     theStyle = Aspect_IS_POINT;
1833   }
1834   else if (theArg.IsIntegerValue())
1835   {
1836     const Standard_Integer anIntStyle = theArg.IntegerValue();
1837     if (anIntStyle < Aspect_IS_EMPTY || anIntStyle > Aspect_IS_POINT)
1838     {
1839       return false;
1840     }
1841     theStyle = (Aspect_InteriorStyle)anIntStyle;
1842   }
1843   else
1844   {
1845     return false;
1846   }
1847   return true;
1848 }
1849
1850 //! Auxiliary structure for VAspects
1851 struct ViewerTest_AspectsChangeSet
1852 {
1853   Standard_Integer             ToSetVisibility;
1854   Standard_Integer             Visibility;
1855
1856   Standard_Integer             ToSetColor;
1857   Quantity_Color               Color;
1858   Standard_Integer             ToSetBackFaceColor;
1859   Quantity_Color               BackFaceColor;
1860
1861   Standard_Integer             ToSetLineWidth;
1862   Standard_Real                LineWidth;
1863
1864   Standard_Integer             ToSetTypeOfLine;
1865   uint16_t                     StippleLinePattern;
1866
1867   Standard_Integer             ToSetTypeOfMarker;
1868   Aspect_TypeOfMarker          TypeOfMarker;
1869   Handle(Image_PixMap)         MarkerImage;
1870
1871   Standard_Integer             ToSetMarkerSize;
1872   Standard_Real                MarkerSize;
1873
1874   Standard_Integer             ToSetTransparency;
1875   Standard_Real                Transparency;
1876
1877   Standard_Integer             ToSetAlphaMode;
1878   Graphic3d_AlphaMode          AlphaMode;
1879   Standard_ShortReal           AlphaCutoff;
1880
1881   Standard_Integer             ToSetMaterial;
1882   Graphic3d_NameOfMaterial     Material;
1883   TCollection_AsciiString      MatName;
1884
1885   NCollection_Sequence<TopoDS_Shape> SubShapes;
1886
1887   Standard_Integer             ToSetShowFreeBoundary;
1888   Standard_Integer             ToSetFreeBoundaryWidth;
1889   Standard_Real                FreeBoundaryWidth;
1890   Standard_Integer             ToSetFreeBoundaryColor;
1891   Quantity_Color               FreeBoundaryColor;
1892
1893   Standard_Integer             ToEnableIsoOnTriangulation;
1894
1895   Standard_Integer             ToSetFaceBoundaryDraw;
1896   Standard_Integer             ToSetFaceBoundaryUpperContinuity;
1897   GeomAbs_Shape                FaceBoundaryUpperContinuity;
1898
1899   Standard_Integer             ToSetFaceBoundaryColor;
1900   Quantity_Color               FaceBoundaryColor;
1901
1902   Standard_Integer             ToSetFaceBoundaryWidth;
1903   Standard_Real                FaceBoundaryWidth;
1904
1905   Standard_Integer             ToSetTypeOfFaceBoundaryLine;
1906   Aspect_TypeOfLine            TypeOfFaceBoundaryLine;
1907
1908   Standard_Integer             ToSetMaxParamValue;
1909   Standard_Real                MaxParamValue;
1910
1911   Standard_Integer             ToSetSensitivity;
1912   Standard_Integer             SelectionMode;
1913   Standard_Integer             Sensitivity;
1914
1915   Standard_Integer             ToSetHatch;
1916   Standard_Integer             StdHatchStyle;
1917   TCollection_AsciiString      PathToHatchPattern;
1918
1919   Standard_Integer             ToSetShadingModel;
1920   Graphic3d_TypeOfShadingModel ShadingModel;
1921   TCollection_AsciiString      ShadingModelName;
1922
1923   Standard_Integer             ToSetInterior;
1924   Aspect_InteriorStyle         InteriorStyle;
1925
1926   Standard_Integer             ToSetDrawSilhouette;
1927
1928   Standard_Integer             ToSetDrawEdges;
1929   Standard_Integer             ToSetQuadEdges;
1930
1931   Standard_Integer             ToSetEdgeColor;
1932   Quantity_ColorRGBA           EdgeColor;
1933
1934   Standard_Integer             ToSetEdgeWidth;
1935   Standard_Real                EdgeWidth;
1936
1937   Standard_Integer             ToSetTypeOfEdge;
1938   Aspect_TypeOfLine            TypeOfEdge;
1939
1940   //! Empty constructor
1941   ViewerTest_AspectsChangeSet()
1942   : ToSetVisibility   (0),
1943     Visibility        (1),
1944     ToSetColor        (0),
1945     Color             (DEFAULT_COLOR),
1946     ToSetBackFaceColor(0),
1947     BackFaceColor     (DEFAULT_COLOR),
1948     ToSetLineWidth    (0),
1949     LineWidth         (1.0),
1950     ToSetTypeOfLine   (0),
1951     StippleLinePattern(0xFFFF),
1952     ToSetTypeOfMarker (0),
1953     TypeOfMarker      (Aspect_TOM_PLUS),
1954     ToSetMarkerSize   (0),
1955     MarkerSize        (1.0),
1956     ToSetTransparency (0),
1957     Transparency      (0.0),
1958     ToSetAlphaMode    (0),
1959     AlphaMode         (Graphic3d_AlphaMode_BlendAuto),
1960     AlphaCutoff       (0.5f),
1961     ToSetMaterial     (0),
1962     Material          (Graphic3d_NOM_DEFAULT),
1963     ToSetShowFreeBoundary      (0),
1964     ToSetFreeBoundaryWidth     (0),
1965     FreeBoundaryWidth          (1.0),
1966     ToSetFreeBoundaryColor     (0),
1967     FreeBoundaryColor          (DEFAULT_FREEBOUNDARY_COLOR),
1968     ToEnableIsoOnTriangulation (0),
1969     //
1970     ToSetFaceBoundaryDraw      (0),
1971     ToSetFaceBoundaryUpperContinuity (0),
1972     FaceBoundaryUpperContinuity(GeomAbs_CN),
1973     ToSetFaceBoundaryColor     (0),
1974     FaceBoundaryColor          (Quantity_NOC_BLACK),
1975     ToSetFaceBoundaryWidth     (0),
1976     FaceBoundaryWidth          (1.0f),
1977     ToSetTypeOfFaceBoundaryLine(0),
1978     TypeOfFaceBoundaryLine     (Aspect_TOL_SOLID),
1979     //
1980     ToSetMaxParamValue         (0),
1981     MaxParamValue              (500000),
1982     ToSetSensitivity           (0),
1983     SelectionMode              (-1),
1984     Sensitivity                (-1),
1985     ToSetHatch                 (0),
1986     StdHatchStyle              (-1),
1987     ToSetShadingModel          (0),
1988     ShadingModel               (Graphic3d_TOSM_DEFAULT),
1989     ToSetInterior              (0),
1990     InteriorStyle              (Aspect_IS_SOLID),
1991     ToSetDrawSilhouette (0),
1992     ToSetDrawEdges    (0),
1993     ToSetQuadEdges    (0),
1994     ToSetEdgeColor    (0),
1995     ToSetEdgeWidth    (0),
1996     EdgeWidth         (1.0),
1997     ToSetTypeOfEdge   (0),
1998     TypeOfEdge        (Aspect_TOL_SOLID)
1999     {}
2000
2001   //! @return true if no changes have been requested
2002   Standard_Boolean IsEmpty() const
2003   {
2004     return ToSetVisibility        == 0
2005         && ToSetLineWidth         == 0
2006         && ToSetTransparency      == 0
2007         && ToSetAlphaMode         == 0
2008         && ToSetColor             == 0
2009         && ToSetBackFaceColor     == 0
2010         && ToSetMaterial          == 0
2011         && ToSetShowFreeBoundary  == 0
2012         && ToSetFreeBoundaryColor == 0
2013         && ToSetFreeBoundaryWidth == 0
2014         && ToEnableIsoOnTriangulation == 0
2015         && ToSetFaceBoundaryDraw == 0
2016         && ToSetFaceBoundaryUpperContinuity == 0
2017         && ToSetFaceBoundaryColor == 0
2018         && ToSetFaceBoundaryWidth == 0
2019         && ToSetTypeOfFaceBoundaryLine == 0
2020         && ToSetMaxParamValue     == 0
2021         && ToSetSensitivity       == 0
2022         && ToSetHatch             == 0
2023         && ToSetShadingModel      == 0
2024         && ToSetInterior          == 0
2025         && ToSetDrawSilhouette    == 0
2026         && ToSetDrawEdges         == 0
2027         && ToSetQuadEdges         == 0
2028         && ToSetEdgeColor         == 0
2029         && ToSetEdgeWidth         == 0
2030         && ToSetTypeOfEdge        == 0;
2031   }
2032
2033   //! @return true if properties are valid
2034   Standard_Boolean Validate() const
2035   {
2036     Standard_Boolean isOk = Standard_True;
2037     if (Visibility != 0 && Visibility != 1)
2038     {
2039       Message::SendFail() << "Error: the visibility should be equal to 0 or 1 (0 - invisible; 1 - visible) (specified " << Visibility << ")";
2040       isOk = Standard_False;
2041     }
2042     if (LineWidth <= 0.0
2043      || LineWidth >  10.0)
2044     {
2045       Message::SendFail() << "Error: the width should be within [1; 10] range (specified " << LineWidth << ")";
2046       isOk = Standard_False;
2047     }
2048     if (Transparency < 0.0
2049      || Transparency > 1.0)
2050     {
2051       Message::SendFail() << "Error: the transparency should be within [0; 1] range (specified " << Transparency << ")";
2052       isOk = Standard_False;
2053     }
2054     if (ToSetAlphaMode == 1
2055      && (AlphaCutoff <= 0.0f || AlphaCutoff >= 1.0f))
2056     {
2057       Message::SendFail() << "Error: alpha cutoff value should be within (0; 1) range (specified " << AlphaCutoff << ")";
2058       isOk = Standard_False;
2059     }
2060     if (FreeBoundaryWidth <= 0.0
2061      || FreeBoundaryWidth >  10.0)
2062     {
2063       Message::SendFail() << "Error: the free boundary width should be within [1; 10] range (specified " << FreeBoundaryWidth << ")";
2064       isOk = Standard_False;
2065     }
2066     if (MaxParamValue < 0.0)
2067     {
2068       Message::SendFail() << "Error: the max parameter value should be greater than zero (specified " << MaxParamValue << ")";
2069       isOk = Standard_False;
2070     }
2071     if (Sensitivity <= 0 && ToSetSensitivity)
2072     {
2073       Message::SendFail() << "Error: sensitivity parameter value should be positive (specified " << Sensitivity << ")";
2074       isOk = Standard_False;
2075     }
2076     if (ToSetHatch == 1 && StdHatchStyle < 0 && PathToHatchPattern == "")
2077     {
2078       Message::SendFail ("Error: hatch style must be specified");
2079       isOk = Standard_False;
2080     }
2081     if (ToSetShadingModel == 1
2082     && (ShadingModel < Graphic3d_TOSM_DEFAULT || ShadingModel > Graphic3d_TOSM_PBR_FACET))
2083     {
2084       Message::SendFail() << "Error: unknown shading model " << ShadingModelName << ".";
2085       isOk = Standard_False;
2086     }
2087     return isOk;
2088   }
2089
2090   //! Apply aspects to specified drawer.
2091   bool Apply (const Handle(Prs3d_Drawer)& theDrawer)
2092   {
2093     bool toRecompute = false;
2094     const Handle(Prs3d_Drawer)& aDefDrawer = ViewerTest::GetAISContext()->DefaultDrawer();
2095     if (ToSetShowFreeBoundary != 0)
2096     {
2097       theDrawer->SetFreeBoundaryDraw (ToSetShowFreeBoundary == 1);
2098       toRecompute = true;
2099     }
2100     if (ToSetFreeBoundaryWidth != 0)
2101     {
2102       if (ToSetFreeBoundaryWidth != -1
2103        || theDrawer->HasOwnFreeBoundaryAspect())
2104       {
2105         if (!theDrawer->HasOwnFreeBoundaryAspect())
2106         {
2107           Handle(Prs3d_LineAspect) aBoundaryAspect = new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2108           *aBoundaryAspect->Aspect() = *theDrawer->FreeBoundaryAspect()->Aspect();
2109           theDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2110           toRecompute = true;
2111         }
2112         theDrawer->FreeBoundaryAspect()->SetWidth (FreeBoundaryWidth);
2113       }
2114     }
2115     if (ToSetFreeBoundaryColor != 0)
2116     {
2117       Handle(Prs3d_LineAspect) aBoundaryAspect = new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2118       *aBoundaryAspect->Aspect() = *theDrawer->FreeBoundaryAspect()->Aspect();
2119       aBoundaryAspect->SetColor (FreeBoundaryColor);
2120       theDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2121       toRecompute = true;
2122     }
2123     if (ToSetTypeOfLine != 0)
2124     {
2125       if (ToSetTypeOfLine != -1
2126        || theDrawer->HasOwnLineAspect()
2127        || theDrawer->HasOwnWireAspect()
2128        || theDrawer->HasOwnFreeBoundaryAspect()
2129        || theDrawer->HasOwnUnFreeBoundaryAspect()
2130        || theDrawer->HasOwnSeenLineAspect())
2131       {
2132         toRecompute = theDrawer->SetOwnLineAspects() || toRecompute;
2133         theDrawer->LineAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2134         theDrawer->WireAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2135         theDrawer->FreeBoundaryAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2136         theDrawer->UnFreeBoundaryAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2137         theDrawer->SeenLineAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2138       }
2139     }
2140     if (ToSetTypeOfMarker != 0)
2141     {
2142       if (ToSetTypeOfMarker != -1
2143        || theDrawer->HasOwnPointAspect())
2144       {
2145         toRecompute = theDrawer->SetupOwnPointAspect (aDefDrawer) || toRecompute;
2146         theDrawer->PointAspect()->SetTypeOfMarker (TypeOfMarker);
2147         theDrawer->PointAspect()->Aspect()->SetMarkerImage (MarkerImage.IsNull() ? Handle(Graphic3d_MarkerImage)() : new Graphic3d_MarkerImage (MarkerImage));
2148       }
2149     }
2150     if (ToSetMarkerSize != 0)
2151     {
2152       if (ToSetMarkerSize != -1
2153        || theDrawer->HasOwnPointAspect())
2154       {
2155         toRecompute = theDrawer->SetupOwnPointAspect (aDefDrawer) || toRecompute;
2156         theDrawer->PointAspect()->SetScale (MarkerSize);
2157         toRecompute = true;
2158       }
2159     }
2160     if (ToSetMaxParamValue != 0)
2161     {
2162       if (ToSetMaxParamValue != -1
2163        || theDrawer->HasOwnMaximalParameterValue())
2164       {
2165         theDrawer->SetMaximalParameterValue (MaxParamValue);
2166         toRecompute = true;
2167       }
2168     }
2169     if (ToSetFaceBoundaryDraw != 0)
2170     {
2171       if (ToSetFaceBoundaryDraw != -1
2172        || theDrawer->HasOwnFaceBoundaryDraw())
2173       {
2174         toRecompute = true;
2175         theDrawer->SetFaceBoundaryDraw (ToSetFaceBoundaryDraw == 1);
2176       }
2177     }
2178     if (ToSetFaceBoundaryUpperContinuity != 0)
2179     {
2180       if (ToSetFaceBoundaryUpperContinuity != -1
2181        || theDrawer->HasOwnFaceBoundaryUpperContinuity())
2182       {
2183         toRecompute = true;
2184         if (ToSetFaceBoundaryUpperContinuity == -1)
2185         {
2186           theDrawer->UnsetFaceBoundaryUpperContinuity();
2187         }
2188         else
2189         {
2190           theDrawer->SetFaceBoundaryUpperContinuity (FaceBoundaryUpperContinuity);
2191         }
2192       }
2193     }
2194     if (ToSetFaceBoundaryColor != 0)
2195     {
2196       if (ToSetFaceBoundaryColor != -1
2197        || theDrawer->HasOwnFaceBoundaryAspect())
2198       {
2199         if (ToSetFaceBoundaryColor == -1)
2200         {
2201           toRecompute = true;
2202           theDrawer->SetFaceBoundaryAspect (Handle(Prs3d_LineAspect)());
2203         }
2204         else
2205         {
2206           toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2207           theDrawer->FaceBoundaryAspect()->SetColor (FaceBoundaryColor);
2208         }
2209       }
2210     }
2211     if (ToSetFaceBoundaryWidth != 0)
2212     {
2213       if (ToSetFaceBoundaryWidth != -1
2214        || theDrawer->HasOwnFaceBoundaryAspect())
2215       {
2216         toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2217         theDrawer->FaceBoundaryAspect()->SetWidth (FaceBoundaryWidth);
2218       }
2219     }
2220     if (ToSetTypeOfFaceBoundaryLine != 0)
2221     {
2222       if (ToSetTypeOfFaceBoundaryLine != -1
2223        || theDrawer->HasOwnFaceBoundaryAspect())
2224       {
2225         toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2226         theDrawer->FaceBoundaryAspect()->SetTypeOfLine (TypeOfFaceBoundaryLine);
2227       }
2228     }
2229     if (ToSetShadingModel != 0)
2230     {
2231       if (ToSetShadingModel != -1
2232        || theDrawer->HasOwnShadingAspect())
2233       {
2234         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2235         theDrawer->ShadingAspect()->Aspect()->SetShadingModel (ShadingModel);
2236       }
2237     }
2238     if (ToSetBackFaceColor != 0)
2239     {
2240       if (ToSetBackFaceColor != -1
2241        || theDrawer->HasOwnShadingAspect())
2242       {
2243         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2244         theDrawer->ShadingAspect()->SetColor (BackFaceColor, Aspect_TOFM_BACK_SIDE);
2245       }
2246     }
2247     if (ToSetAlphaMode != 0)
2248     {
2249       if (ToSetAlphaMode != -1
2250        || theDrawer->HasOwnShadingAspect())
2251       {
2252         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2253         theDrawer->ShadingAspect()->Aspect()->SetAlphaMode (AlphaMode, AlphaCutoff);
2254       }
2255     }
2256     if (ToSetHatch != 0)
2257     {
2258       if (ToSetHatch != -1
2259       ||  theDrawer->HasOwnShadingAspect())
2260       {
2261         theDrawer->SetupOwnShadingAspect (aDefDrawer);
2262         Handle(Graphic3d_AspectFillArea3d) anAsp = theDrawer->ShadingAspect()->Aspect();
2263         if (ToSetHatch == -1)
2264         {
2265           anAsp->SetInteriorStyle (Aspect_IS_SOLID);
2266         }
2267         else
2268         {
2269           anAsp->SetInteriorStyle (Aspect_IS_HATCH);
2270           if (!PathToHatchPattern.IsEmpty())
2271           {
2272             Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
2273             if (anImage->Load (TCollection_AsciiString (PathToHatchPattern.ToCString())))
2274             {
2275               anAsp->SetHatchStyle (new Graphic3d_HatchStyle (anImage));
2276             }
2277             else
2278             {
2279               Message::SendFail() << "Error: cannot load the following image: " << PathToHatchPattern;
2280             }
2281           }
2282           else if (StdHatchStyle != -1)
2283           {
2284             anAsp->SetHatchStyle (new Graphic3d_HatchStyle ((Aspect_HatchStyle)StdHatchStyle));
2285           }
2286         }
2287         toRecompute = true;
2288       }
2289     }
2290     if (ToSetInterior != 0)
2291     {
2292       if (ToSetInterior != -1
2293        || theDrawer->HasOwnShadingAspect())
2294       {
2295         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2296         theDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (InteriorStyle);
2297         if (InteriorStyle == Aspect_IS_HATCH
2298          && theDrawer->ShadingAspect()->Aspect()->HatchStyle().IsNull())
2299         {
2300           theDrawer->ShadingAspect()->Aspect()->SetHatchStyle (Aspect_HS_VERTICAL);
2301         }
2302       }
2303     }
2304     if (ToSetDrawSilhouette != 0)
2305     {
2306       if (ToSetDrawSilhouette != -1
2307        || theDrawer->HasOwnShadingAspect())
2308       {
2309         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2310         theDrawer->ShadingAspect()->Aspect()->SetDrawSilhouette (ToSetDrawSilhouette == 1);
2311       }
2312     }
2313     if (ToSetDrawEdges != 0)
2314     {
2315       if (ToSetDrawEdges != -1
2316        || theDrawer->HasOwnShadingAspect())
2317       {
2318         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2319         theDrawer->ShadingAspect()->Aspect()->SetDrawEdges (ToSetDrawEdges == 1);
2320       }
2321     }
2322     if (ToSetQuadEdges != 0)
2323     {
2324       if (ToSetQuadEdges != -1
2325           || theDrawer->HasOwnShadingAspect())
2326       {
2327         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2328         theDrawer->ShadingAspect()->Aspect()->SetSkipFirstEdge (ToSetQuadEdges == 1);
2329       }
2330     }
2331     if (ToSetEdgeWidth != 0)
2332     {
2333       if (ToSetEdgeWidth != -1
2334        || theDrawer->HasOwnShadingAspect())
2335       {
2336         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2337         theDrawer->ShadingAspect()->Aspect()->SetEdgeWidth (EdgeWidth);
2338       }
2339     }
2340     if (ToSetTypeOfEdge != 0)
2341     {
2342       if (ToSetTypeOfEdge != -1
2343        || theDrawer->HasOwnShadingAspect())
2344       {
2345         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2346         theDrawer->ShadingAspect()->Aspect()->SetEdgeLineType (TypeOfEdge);
2347         if (ToSetInterior == 0)
2348         {
2349           theDrawer->ShadingAspect()->Aspect()->SetDrawEdges (ToSetTypeOfEdge == 1
2350                                                            && TypeOfEdge != Aspect_TOL_EMPTY);
2351         }
2352       }
2353     }
2354     if (ToSetEdgeColor != 0)
2355     {
2356       if (ToSetEdgeColor != -1
2357        || theDrawer->HasOwnShadingAspect())
2358       {
2359         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2360         if (ToSetEdgeColor == -1)
2361         {
2362           theDrawer->ShadingAspect()->Aspect()->SetEdgeColor (theDrawer->ShadingAspect()->Aspect()->InteriorColor());
2363         }
2364         else
2365         {
2366           theDrawer->ShadingAspect()->Aspect()->SetEdgeColor (EdgeColor);
2367         }
2368       }
2369     }
2370     return toRecompute;
2371   }
2372 };
2373
2374 //==============================================================================
2375 //function : VAspects
2376 //purpose  :
2377 //==============================================================================
2378 static Standard_Integer VAspects (Draw_Interpretor& theDI,
2379                                   Standard_Integer  theArgNb,
2380                                   const char**      theArgVec)
2381 {
2382   TCollection_AsciiString aCmdName (theArgVec[0]);
2383   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2384   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2385   if (aCtx.IsNull())
2386   {
2387     Message::SendFail ("Error: no active view!");
2388     return 1;
2389   }
2390
2391   Standard_Integer anArgIter = 1;
2392   Standard_Boolean isDefaults = Standard_False;
2393   NCollection_Sequence<TCollection_AsciiString> aNames;
2394   for (; anArgIter < theArgNb; ++anArgIter)
2395   {
2396     TCollection_AsciiString anArg = theArgVec[anArgIter];
2397     if (anUpdateTool.parseRedrawMode (anArg))
2398     {
2399       continue;
2400     }
2401     else if (!anArg.IsEmpty()
2402            && anArg.Value (1) != '-')
2403     {
2404       aNames.Append (anArg);
2405     }
2406     else
2407     {
2408       if (anArg == "-defaults")
2409       {
2410         isDefaults = Standard_True;
2411         ++anArgIter;
2412       }
2413       break;
2414     }
2415   }
2416
2417   if (!aNames.IsEmpty() && isDefaults)
2418   {
2419     Message::SendFail ("Error: wrong syntax. If -defaults is used there should not be any objects' names!");
2420     return 1;
2421   }
2422
2423   NCollection_Sequence<ViewerTest_AspectsChangeSet> aChanges;
2424   aChanges.Append (ViewerTest_AspectsChangeSet());
2425   ViewerTest_AspectsChangeSet* aChangeSet = &aChanges.ChangeLast();
2426
2427   // parse syntax of legacy commands
2428   bool toParseAliasArgs = false;
2429   Standard_Boolean toDump = 0;
2430   Standard_Boolean toCompactDump = 0;
2431   Standard_Integer aDumpDepth = -1;
2432   if (aCmdName == "vsetwidth")
2433   {
2434     if (aNames.IsEmpty()
2435     || !aNames.Last().IsRealValue())
2436     {
2437       Message::SendFail ("Error: not enough arguments!");
2438       return 1;
2439     }
2440     aChangeSet->ToSetLineWidth = 1;
2441     aChangeSet->LineWidth = aNames.Last().RealValue();
2442     aNames.Remove (aNames.Length());
2443   }
2444   else if (aCmdName == "vunsetwidth")
2445   {
2446     aChangeSet->ToSetLineWidth = -1;
2447   }
2448   else if (aCmdName == "vsetcolor")
2449   {
2450     if (aNames.IsEmpty())
2451     {
2452       Message::SendFail ("Error: not enough arguments!");
2453       return 1;
2454     }
2455     aChangeSet->ToSetColor = 1;
2456
2457     Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
2458     Standard_Boolean     isOk   = Standard_False;
2459     if (Quantity_Color::ColorFromName (aNames.Last().ToCString(), aColor))
2460     {
2461       aChangeSet->Color = aColor;
2462       aNames.Remove (aNames.Length());
2463       isOk = Standard_True;
2464     }
2465     else if (Quantity_Color::ColorFromHex (aNames.Last().ToCString(), aChangeSet->Color))
2466     {
2467       aNames.Remove (aNames.Length());
2468       isOk = Standard_True;
2469     }
2470     else if (aNames.Length() >= 3)
2471     {
2472       const char* anArgVec[3] =
2473       {
2474         aNames.Value (aNames.Upper() - 2).ToCString(),
2475         aNames.Value (aNames.Upper() - 1).ToCString(),
2476         aNames.Value (aNames.Upper() - 0).ToCString(),
2477       };
2478
2479       Standard_Integer aNbParsed = ViewerTest::ParseColor (3, anArgVec, aChangeSet->Color);
2480       isOk = aNbParsed == 3;
2481       aNames.Remove (aNames.Length());
2482       aNames.Remove (aNames.Length());
2483       aNames.Remove (aNames.Length());
2484     }
2485     if (!isOk)
2486     {
2487       Message::SendFail ("Error: not enough arguments!");
2488       return 1;
2489     }
2490   }
2491   else if (aCmdName == "vunsetcolor")
2492   {
2493     aChangeSet->ToSetColor = -1;
2494   }
2495   else if (aCmdName == "vsettransparency")
2496   {
2497     if (aNames.IsEmpty()
2498     || !aNames.Last().IsRealValue())
2499     {
2500       Message::SendFail ("Error: not enough arguments!");
2501       return 1;
2502     }
2503     aChangeSet->ToSetTransparency = 1;
2504     aChangeSet->Transparency  = aNames.Last().RealValue();
2505     aNames.Remove (aNames.Length());
2506   }
2507   else if (aCmdName == "vunsettransparency")
2508   {
2509     aChangeSet->ToSetTransparency = -1;
2510   }
2511   else if (aCmdName == "vsetmaterial")
2512   {
2513     if (aNames.IsEmpty())
2514     {
2515       Message::SendFail ("Error: not enough arguments!");
2516       return 1;
2517     }
2518     aChangeSet->ToSetMaterial = 1;
2519     aChangeSet->MatName = aNames.Last();
2520     aNames.Remove (aNames.Length());
2521     if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString(), aChangeSet->Material))
2522     {
2523       Message::SendFail() << "Syntax error: unknown material '" << aChangeSet->MatName << "'.";
2524       return 1;
2525     }
2526   }
2527   else if (aCmdName == "vunsetmaterial")
2528   {
2529     aChangeSet->ToSetMaterial = -1;
2530   }
2531   else if (aCmdName == "vsetinteriorstyle")
2532   {
2533     if (aNames.IsEmpty()
2534     || !aNames.Last().IsRealValue())
2535     {
2536       Message::SendFail ("Error: not enough arguments!");
2537       return 1;
2538     }
2539     aChangeSet->ToSetInterior = 1;
2540     if (!parseInteriorStyle (aNames.Last(), aChangeSet->InteriorStyle))
2541     {
2542       Message::SendFail() << "Error: wrong syntax at " << aNames.Last();
2543       return 1;
2544     }
2545     aNames.Remove (aNames.Length());
2546   }
2547   else if (aCmdName == "vsetedgetype")
2548   {
2549     aChangeSet->ToSetDrawEdges = 1;
2550     toParseAliasArgs = true;
2551   }
2552   else if (aCmdName == "vunsetedgetype")
2553   {
2554     aChangeSet->ToSetDrawEdges  = -1;
2555     aChangeSet->ToSetEdgeColor  = -1;
2556     aChangeSet->ToSetTypeOfEdge = -1;
2557     aChangeSet->TypeOfEdge = Aspect_TOL_SOLID;
2558   }
2559   else if (aCmdName == "vshowfaceboundary")
2560   {
2561     aChangeSet->ToSetFaceBoundaryDraw = 1;
2562     toParseAliasArgs = true;
2563     if (aNames.Size() >= 2
2564      && aNames.Value (2).IsIntegerValue())
2565     {
2566       if (aNames.Size() == 7)
2567       {
2568         if (ViewerTest::ParseLineType (aNames.Value (7).ToCString(), aChangeSet->TypeOfFaceBoundaryLine))
2569         {
2570           aChangeSet->ToSetTypeOfFaceBoundaryLine = 1;
2571           aNames.Remove (7);
2572         }
2573       }
2574       if (aNames.Size() == 6
2575        && aNames.Value (6).IsRealValue())
2576       {
2577         aChangeSet->ToSetFaceBoundaryWidth = 1;
2578         aChangeSet->FaceBoundaryWidth = aNames.Value (6).RealValue();
2579         aNames.Remove (6);
2580       }
2581       if (aNames.Size() == 5
2582        && aNames.Value (3).IsIntegerValue()
2583        && aNames.Value (4).IsIntegerValue()
2584        && aNames.Value (5).IsIntegerValue())
2585       {
2586         aChangeSet->ToSetFaceBoundaryColor = 1;
2587         aChangeSet->FaceBoundaryColor = Quantity_Color (aNames.Value (3).IntegerValue() / 255.0,
2588                                                         aNames.Value (4).IntegerValue() / 255.0,
2589                                                         aNames.Value (5).IntegerValue() / 255.0,
2590                                                         Quantity_TOC_sRGB);
2591         aNames.Remove (5);
2592         aNames.Remove (4);
2593         aNames.Remove (3);
2594       }
2595       if (aNames.Size() == 2)
2596       {
2597         toParseAliasArgs = false;
2598         aChangeSet->ToSetFaceBoundaryDraw = aNames.Value (2).IntegerValue() == 1 ? 1 : -1;
2599         aNames.Remove (2);
2600       }
2601     }
2602   }
2603   else if (anArgIter >= theArgNb)
2604   {
2605     Message::SendFail ("Error: not enough arguments!");
2606     return 1;
2607   }
2608
2609   if (!aChangeSet->IsEmpty()
2610    && !toParseAliasArgs)
2611   {
2612     anArgIter = theArgNb;
2613   }
2614   for (; anArgIter < theArgNb; ++anArgIter)
2615   {
2616     TCollection_AsciiString anArg = theArgVec[anArgIter];
2617     anArg.LowerCase();
2618     if (anArg == "-setwidth"
2619      || anArg == "-width"
2620      || anArg == "-setlinewidth"
2621      || anArg == "-linewidth"
2622      || anArg == "-setedgewidth"
2623      || anArg == "-setedgeswidth"
2624      || anArg == "-edgewidth"
2625      || anArg == "-edgeswidth"
2626      || anArg == "-setfaceboundarywidth"
2627      || anArg == "-setboundarywidth"
2628      || anArg == "-faceboundarywidth"
2629      || anArg == "-boundarywidth")
2630     {
2631       if (++anArgIter >= theArgNb)
2632       {
2633         Message::SendFail() << "Error: wrong syntax at " << anArg;
2634         return 1;
2635       }
2636
2637       const Standard_Real aWidth = Draw::Atof (theArgVec[anArgIter]);
2638       if (anArg == "-setedgewidth"
2639        || anArg == "-setedgeswidth"
2640        || anArg == "-edgewidth"
2641        || anArg == "-edgeswidth"
2642        || aCmdName == "vsetedgetype")
2643       {
2644         aChangeSet->ToSetEdgeWidth = 1;
2645         aChangeSet->EdgeWidth = aWidth;
2646       }
2647       else if (anArg == "-setfaceboundarywidth"
2648             || anArg == "-setboundarywidth"
2649             || anArg == "-faceboundarywidth"
2650             || anArg == "-boundarywidth"
2651             || aCmdName == "vshowfaceboundary")
2652       {
2653         aChangeSet->ToSetFaceBoundaryWidth = 1;
2654         aChangeSet->FaceBoundaryWidth = aWidth;
2655       }
2656       else
2657       {
2658         aChangeSet->ToSetLineWidth = 1;
2659         aChangeSet->LineWidth = aWidth;
2660       }
2661     }
2662     else if (anArg == "-unsetwidth"
2663           || anArg == "-unsetlinewidth"
2664           || anArg == "-unsetedgewidth")
2665     {
2666       if (anArg == "-unsetedgewidth")
2667       {
2668         aChangeSet->ToSetEdgeWidth = -1;
2669         aChangeSet->EdgeWidth = 1.0;
2670       }
2671       else
2672       {
2673         aChangeSet->ToSetLineWidth = -1;
2674         aChangeSet->LineWidth = 1.0;
2675       }
2676     }
2677     else if (anArg == "-settransp"
2678           || anArg == "-settransparency"
2679           || anArg == "-transparency"
2680           || anArg == "-transp")
2681     {
2682       if (++anArgIter >= theArgNb)
2683       {
2684         Message::SendFail() << "Error: wrong syntax at " << anArg;
2685         return 1;
2686       }
2687       aChangeSet->ToSetTransparency = 1;
2688       aChangeSet->Transparency = Draw::Atof (theArgVec[anArgIter]);
2689       if (aChangeSet->Transparency >= 0.0
2690        && aChangeSet->Transparency <= Precision::Confusion())
2691       {
2692         aChangeSet->ToSetTransparency = -1;
2693         aChangeSet->Transparency = 0.0;
2694       }
2695     }
2696     else if (anArg == "-setalphamode"
2697           || anArg == "-alphamode")
2698     {
2699       if (++anArgIter >= theArgNb)
2700       {
2701         Message::SendFail() << "Error: wrong syntax at " << anArg;
2702         return 1;
2703       }
2704       aChangeSet->ToSetAlphaMode = 1;
2705       aChangeSet->AlphaCutoff = 0.5f;
2706       {
2707         TCollection_AsciiString aParam (theArgVec[anArgIter]);
2708         aParam.LowerCase();
2709         if (aParam == "opaque")
2710         {
2711           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Opaque;
2712         }
2713         else if (aParam == "mask")
2714         {
2715           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Mask;
2716         }
2717         else if (aParam == "blend")
2718         {
2719           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Blend;
2720         }
2721         else if (aParam == "blendauto"
2722               || aParam == "auto")
2723         {
2724           aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto;
2725         }
2726         else
2727         {
2728           Message::SendFail() << "Error: wrong syntax at " << aParam;
2729           return 1;
2730         }
2731       }
2732
2733       if (anArgIter + 1 < theArgNb
2734        && theArgVec[anArgIter + 1][0] != '-')
2735       {
2736         TCollection_AsciiString aParam2 (theArgVec[anArgIter + 1]);
2737         if (aParam2.IsRealValue())
2738         {
2739           aChangeSet->AlphaCutoff = (float )aParam2.RealValue();
2740           ++anArgIter;
2741         }
2742       }
2743     }
2744     else if (anArg == "-setvis"
2745           || anArg == "-setvisibility"
2746           || anArg == "-visibility")
2747     {
2748       if (++anArgIter >= theArgNb)
2749       {
2750         Message::SendFail() << "Error: wrong syntax at " << anArg;
2751         return 1;
2752       }
2753
2754       aChangeSet->ToSetVisibility = 1;
2755       aChangeSet->Visibility = Draw::Atoi (theArgVec[anArgIter]);
2756     }
2757     else if (anArg == "-setalpha"
2758           || anArg == "-alpha")
2759     {
2760       if (++anArgIter >= theArgNb)
2761       {
2762         Message::SendFail() << "Error: wrong syntax at " << anArg;
2763         return 1;
2764       }
2765       aChangeSet->ToSetTransparency = 1;
2766       aChangeSet->Transparency  = Draw::Atof (theArgVec[anArgIter]);
2767       if (aChangeSet->Transparency < 0.0
2768        || aChangeSet->Transparency > 1.0)
2769       {
2770         Message::SendFail() << "Error: the transparency should be within [0; 1] range (specified " << aChangeSet->Transparency << ")";
2771         return 1;
2772       }
2773       aChangeSet->Transparency = 1.0 - aChangeSet->Transparency;
2774       if (aChangeSet->Transparency >= 0.0
2775        && aChangeSet->Transparency <= Precision::Confusion())
2776       {
2777         aChangeSet->ToSetTransparency = -1;
2778         aChangeSet->Transparency = 0.0;
2779       }
2780     }
2781     else if (anArg == "-unsettransp"
2782           || anArg == "-unsettransparency"
2783           || anArg == "-unsetalpha"
2784           || anArg == "-opaque")
2785     {
2786       aChangeSet->ToSetTransparency = -1;
2787       aChangeSet->Transparency = 0.0;
2788     }
2789     else if (anArg == "-setcolor"
2790           || anArg == "-color"
2791           || anArg == "-setbackfacecolor"
2792           || anArg == "-backfacecolor"
2793           || anArg == "-setbackcolor"
2794           || anArg == "-backcolor"
2795           || anArg == "-setfaceboundarycolor"
2796           || anArg == "-setboundarycolor"
2797           || anArg == "-faceboundarycolor"
2798           || anArg == "-boundarycolor")
2799     {
2800       Quantity_Color aColor;
2801       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
2802                                                            theArgVec + anArgIter + 1,
2803                                                            aColor);
2804       if (aNbParsed == 0)
2805       {
2806         Message::SendFail() << "Syntax error at '" << anArg << "'";
2807         return 1;
2808       }
2809       anArgIter += aNbParsed;
2810       if (aCmdName == "vsetedgetype")
2811       {
2812         aChangeSet->ToSetEdgeColor = 1;
2813         aChangeSet->EdgeColor = Quantity_ColorRGBA (aColor);
2814       }
2815       else if (aCmdName == "vshowfaceboundary"
2816             || anArg == "-setfaceboundarycolor"
2817             || anArg == "-setboundarycolor"
2818             || anArg == "-faceboundarycolor"
2819             || anArg == "-boundarycolor")
2820       {
2821         aChangeSet->ToSetFaceBoundaryColor = 1;
2822         aChangeSet->FaceBoundaryColor = aColor;
2823       }
2824       else if (anArg == "-setbackfacecolor"
2825             || anArg == "-backfacecolor"
2826             || anArg == "-setbackcolor"
2827             || anArg == "-backcolor")
2828       {
2829         aChangeSet->ToSetBackFaceColor = 1;
2830         aChangeSet->BackFaceColor = aColor;
2831       }
2832       else
2833       {
2834         aChangeSet->ToSetColor = 1;
2835         aChangeSet->Color = aColor;
2836       }
2837     }
2838     else if (anArg == "-setlinetype"
2839           || anArg == "-linetype"
2840           || anArg == "-setedgetype"
2841           || anArg == "-setedgestype"
2842           || anArg == "-edgetype"
2843           || anArg == "-edgestype"
2844           || anArg == "-setfaceboundarystyle"
2845           || anArg == "-faceboundarystyle"
2846           || anArg == "-boundarystyle"
2847           || anArg == "-setfaceboundarytype"
2848           || anArg == "-faceboundarytype"
2849           || anArg == "-setboundarytype"
2850           || anArg == "-boundarytype"
2851           || anArg == "-type")
2852     {
2853       if (++anArgIter >= theArgNb)
2854       {
2855         Message::SendFail() << "Error: wrong syntax at " << anArg;
2856         return 1;
2857       }
2858       Aspect_TypeOfLine aLineType = Aspect_TOL_EMPTY;
2859       uint16_t aLinePattern = 0xFFFF;
2860       if (!ViewerTest::ParseLineType (theArgVec[anArgIter], aLineType, aLinePattern))
2861       {
2862         Message::SendFail() << "Error: wrong syntax at " << anArg;
2863         return 1;
2864       }
2865
2866       if (anArg == "-setedgetype"
2867        || anArg == "-setedgestype"
2868        || anArg == "-edgetype"
2869        || anArg == "-edgestype"
2870        || aCmdName == "vsetedgetype")
2871       {
2872         aChangeSet->TypeOfEdge = Graphic3d_Aspects::DefaultLineTypeForPattern (aLinePattern);
2873         aChangeSet->ToSetTypeOfEdge = 1;
2874       }
2875       else if (anArg == "-setfaceboundarystyle"
2876             || anArg == "-faceboundarystyle"
2877             || anArg == "-boundarystyle"
2878             || anArg == "-setfaceboundarytype"
2879             || anArg == "-faceboundarytype"
2880             || anArg == "-setboundarytype"
2881             || anArg == "-boundarytype"
2882             || aCmdName == "vshowfaceboundary")
2883       {
2884         aChangeSet->TypeOfFaceBoundaryLine = Graphic3d_Aspects::DefaultLineTypeForPattern (aLinePattern);
2885         aChangeSet->ToSetTypeOfFaceBoundaryLine = 1;
2886       }
2887       else
2888       {
2889         aChangeSet->StippleLinePattern = aLinePattern;
2890         aChangeSet->ToSetTypeOfLine = 1;
2891       }
2892     }
2893     else if (anArg == "-unsetlinetype"
2894           || anArg == "-unsetedgetype"
2895           || anArg == "-unsetedgestype")
2896     {
2897       if (anArg == "-unsetedgetype"
2898        || anArg == "-unsetedgestype")
2899       {
2900         aChangeSet->ToSetTypeOfEdge = -1;
2901       }
2902       else
2903       {
2904         aChangeSet->ToSetTypeOfLine = -1;
2905       }
2906     }
2907     else if (anArg == "-setmarkertype"
2908           || anArg == "-markertype"
2909           || anArg == "-setpointtype"
2910           || anArg == "-pointtype")
2911     {
2912       if (++anArgIter >= theArgNb)
2913       {
2914         Message::SendFail() << "Error: wrong syntax at " << anArg;
2915         return 1;
2916       }
2917       if (!ViewerTest::ParseMarkerType (theArgVec[anArgIter], aChangeSet->TypeOfMarker, aChangeSet->MarkerImage))
2918       {
2919         Message::SendFail() << "Error: wrong syntax at " << anArg;
2920         return 1;
2921       }
2922
2923       aChangeSet->ToSetTypeOfMarker = 1;
2924     }
2925     else if (anArg == "-unsetmarkertype"
2926           || anArg == "-unsetpointtype")
2927     {
2928       aChangeSet->ToSetTypeOfMarker = -1;
2929     }
2930     else if (anArg == "-setmarkersize"
2931           || anArg == "-markersize"
2932           || anArg == "-setpointsize"
2933           || anArg == "-pointsize")
2934     {
2935       if (++anArgIter >= theArgNb)
2936       {
2937         Message::SendFail() << "Error: wrong syntax at " << anArg;
2938         return 1;
2939       }
2940       aChangeSet->ToSetMarkerSize = 1;
2941       aChangeSet->MarkerSize = Draw::Atof (theArgVec[anArgIter]);
2942     }
2943     else if (anArg == "-unsetmarkersize"
2944           || anArg == "-unsetpointsize")
2945     {
2946       aChangeSet->ToSetMarkerSize = -1;
2947       aChangeSet->MarkerSize = 1.0;
2948     }
2949     else if (anArg == "-unsetcolor")
2950     {
2951       aChangeSet->ToSetColor = -1;
2952       aChangeSet->Color = DEFAULT_COLOR;
2953     }
2954     else if (anArg == "-setmat"
2955           || anArg == "-mat"
2956           || anArg == "-setmaterial"
2957           || anArg == "-material")
2958     {
2959       if (++anArgIter >= theArgNb)
2960       {
2961         Message::SendFail() << "Error: wrong syntax at " << anArg;
2962         return 1;
2963       }
2964       aChangeSet->ToSetMaterial = 1;
2965       aChangeSet->MatName = theArgVec[anArgIter];
2966       if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString(), aChangeSet->Material))
2967       {
2968         Message::SendFail() << "Syntax error: unknown material '" << aChangeSet->MatName << "'.";
2969         return 1;
2970       }
2971     }
2972     else if (anArg == "-unsetmat"
2973           || anArg == "-unsetmaterial")
2974     {
2975       aChangeSet->ToSetMaterial = -1;
2976       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
2977     }
2978     else if (anArg == "-subshape"
2979           || anArg == "-subshapes")
2980     {
2981       if (isDefaults)
2982       {
2983         Message::SendFail() << "Error: wrong syntax. -subshapes can not be used together with -defaults call!";
2984         return 1;
2985       }
2986
2987       if (aNames.IsEmpty())
2988       {
2989         Message::SendFail() << "Error: main objects should specified explicitly when -subshapes is used!";
2990         return 1;
2991       }
2992
2993       aChanges.Append (ViewerTest_AspectsChangeSet());
2994       aChangeSet = &aChanges.ChangeLast();
2995
2996       for (++anArgIter; anArgIter < theArgNb; ++anArgIter)
2997       {
2998         Standard_CString aSubShapeName = theArgVec[anArgIter];
2999         if (*aSubShapeName == '-')
3000         {
3001           --anArgIter;
3002           break;
3003         }
3004
3005         TopoDS_Shape aSubShape = DBRep::Get (aSubShapeName);
3006         if (aSubShape.IsNull())
3007         {
3008           Message::SendFail() << "Error: shape " << aSubShapeName << " doesn't found!";
3009           return 1;
3010         }
3011         aChangeSet->SubShapes.Append (aSubShape);
3012       }
3013
3014       if (aChangeSet->SubShapes.IsEmpty())
3015       {
3016         Message::SendFail() << "Error: empty list is specified after -subshapes!";
3017         return 1;
3018       }
3019     }
3020     else if (anArg == "-setfreeboundary"
3021           || anArg == "-freeboundary"
3022           || anArg == "-setfb"
3023           || anArg == "-fb")
3024     {
3025       bool toEnable = true;
3026       if (!ViewerTest::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
3027       {
3028         Message::SendFail() << "Error: wrong syntax at " << anArg;
3029         return 1;
3030       }
3031       ++anArgIter;
3032       aChangeSet->ToSetShowFreeBoundary = toEnable ? 1 : -1;
3033     }
3034     else if (anArg == "-setfreeboundarywidth"
3035           || anArg == "-freeboundarywidth"
3036           || anArg == "-setfbwidth"
3037           || anArg == "-fbwidth")
3038     {
3039       if (++anArgIter >= theArgNb)
3040       {
3041         Message::SendFail() << "Error: wrong syntax at " << anArg;
3042         return 1;
3043       }
3044       aChangeSet->ToSetFreeBoundaryWidth = 1;
3045       aChangeSet->FreeBoundaryWidth = Draw::Atof (theArgVec[anArgIter]);
3046     }
3047     else if (anArg == "-unsetfreeboundarywidth"
3048           || anArg == "-unsetfbwidth")
3049     {
3050       aChangeSet->ToSetFreeBoundaryWidth = -1;
3051       aChangeSet->FreeBoundaryWidth = 1.0;
3052     }
3053     else if (anArg == "-setfreeboundarycolor"
3054           || anArg == "-freeboundarycolor"
3055           || anArg == "-setfbcolor"
3056           || anArg == "-fbcolor")
3057     {
3058       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3059                                                            theArgVec + anArgIter + 1,
3060                                                            aChangeSet->FreeBoundaryColor);
3061       if (aNbParsed == 0)
3062       {
3063         Message::SendFail() << "Syntax error at '" << anArg << "'";
3064         return 1;
3065       }
3066       anArgIter += aNbParsed;
3067       aChangeSet->ToSetFreeBoundaryColor = 1;
3068     }
3069     else if (anArg == "-unsetfreeboundarycolor"
3070           || anArg == "-unsetfbcolor")
3071     {
3072       aChangeSet->ToSetFreeBoundaryColor = -1;
3073       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
3074     }
3075     else if (anArg == "-setisoontriangulation"
3076           || anArg == "-isoontriangulation"
3077           || anArg == "-setisoontriang"
3078           || anArg == "-isoontriang")
3079     {
3080       bool toEnable = true;
3081       if (!ViewerTest::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
3082       {
3083         Message::SendFail() << "Error: wrong syntax at " << anArg;
3084         return 1;
3085       }
3086       ++anArgIter;
3087       aChangeSet->ToEnableIsoOnTriangulation = toEnable ? 1 : -1;
3088     }
3089     else if (anArg == "-setfaceboundarydraw"
3090           || anArg == "-setdrawfaceboundary"
3091           || anArg == "-setdrawfaceboundaries"
3092           || anArg == "-setshowfaceboundary"
3093           || anArg == "-setshowfaceboundaries"
3094           || anArg == "-setdrawfaceedges"
3095           || anArg == "-faceboundarydraw"
3096           || anArg == "-drawfaceboundary"
3097           || anArg == "-drawfaceboundaries"
3098           || anArg == "-showfaceboundary"
3099           || anArg == "-showfaceboundaries"
3100           || anArg == "-drawfaceedges"
3101           || anArg == "-faceboundary"
3102           || anArg == "-faceboundaries"
3103           || anArg == "-faceedges")
3104     {
3105       bool toEnable = true;
3106       if (!ViewerTest::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
3107       {
3108         Message::SendFail() << "Error: wrong syntax at " << anArg;
3109         return 1;
3110       }
3111       ++anArgIter;
3112       aChangeSet->ToSetFaceBoundaryDraw = toEnable ? 1 : -1;
3113     }
3114     else if (anArg == "-unsetfaceboundary"
3115           || anArg == "-unsetboundary")
3116     {
3117       aChangeSet->ToSetFaceBoundaryDraw  = -1;
3118       aChangeSet->ToSetFaceBoundaryColor = -1;
3119     }
3120     else if (anArg == "-setmostcontinuity"
3121           || anArg == "-mostcontinuity")
3122     {
3123       TCollection_AsciiString aClassArg (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "");
3124       aClassArg.LowerCase();
3125       GeomAbs_Shape aClass = GeomAbs_CN;
3126       if (aClassArg == "c0"
3127        || aClassArg == "0")
3128       {
3129         aClass = GeomAbs_C0;
3130       }
3131       else if (aClassArg == "c1"
3132             || aClassArg == "1")
3133       {
3134         aClass = GeomAbs_C1;
3135       }
3136       else if (aClassArg == "c2"
3137             || aClassArg == "2")
3138       {
3139         aClass = GeomAbs_C2;
3140       }
3141       else if (aClassArg == "c3"
3142             || aClassArg == "3")
3143       {
3144         aClass = GeomAbs_C3;
3145       }
3146       else if (aClassArg == "cn"
3147             || aClassArg == "n")
3148       {
3149         aClass = GeomAbs_CN;
3150       }
3151       else
3152       {
3153         Message::SendFail() << "Syntax error at '" << anArg << "'";
3154         return 1;
3155       }
3156
3157       ++anArgIter;
3158       aChangeSet->ToSetFaceBoundaryUpperContinuity = 1;
3159       aChangeSet->FaceBoundaryUpperContinuity = aClass;
3160     }
3161     else if (anArg == "-setmaxparamvalue"
3162           || anArg == "-maxparamvalue")
3163     {
3164       if (++anArgIter >= theArgNb)
3165       {
3166         Message::SendFail() << "Error: wrong syntax at " << anArg;
3167         return 1;
3168       }
3169       aChangeSet->ToSetMaxParamValue = 1;
3170       aChangeSet->MaxParamValue = Draw::Atof (theArgVec[anArgIter]);
3171     }
3172     else if (anArg == "-setsensitivity"
3173           || anArg == "-sensitivity")
3174     {
3175       if (isDefaults)
3176       {
3177         Message::SendFail() << "Error: wrong syntax. -setSensitivity can not be used together with -defaults call!";
3178         return 1;
3179       }
3180
3181       if (aNames.IsEmpty())
3182       {
3183         Message::SendFail() << "Error: object and selection mode should specified explicitly when -setSensitivity is used!";
3184         return 1;
3185       }
3186
3187       if (anArgIter + 2 >= theArgNb)
3188       {
3189         Message::SendFail() << "Error: wrong syntax at " << anArg;
3190         return 1;
3191       }
3192       aChangeSet->ToSetSensitivity = 1;
3193       aChangeSet->SelectionMode = Draw::Atoi (theArgVec[++anArgIter]);
3194       aChangeSet->Sensitivity = Draw::Atoi (theArgVec[++anArgIter]);
3195     }
3196     else if (anArg == "-sethatch"
3197           || anArg == "-hatch")
3198     {
3199       if (isDefaults)
3200       {
3201         Message::SendFail() << "Error: wrong syntax. -setHatch can not be used together with -defaults call!";
3202         return 1;
3203       }
3204
3205       if (aNames.IsEmpty())
3206       {
3207         Message::SendFail() << "Error: object should be specified explicitly when -setHatch is used!";
3208         return 1;
3209       }
3210
3211       aChangeSet->ToSetHatch = 1;
3212       TCollection_AsciiString anArgHatch (theArgVec[++anArgIter]);
3213       if (anArgHatch.Length() <= 2)
3214       {
3215         const Standard_Integer anIntStyle = Draw::Atoi (anArgHatch.ToCString());
3216         if (anIntStyle < 0
3217          || anIntStyle >= Aspect_HS_NB)
3218         {
3219           Message::SendFail() << "Error: hatch style is out of range [0, " << (Aspect_HS_NB - 1) << "]!";
3220           return 1;
3221         }
3222         aChangeSet->StdHatchStyle = anIntStyle;
3223       }
3224       else
3225       {
3226         aChangeSet->PathToHatchPattern = anArgHatch;
3227       }
3228     }
3229     else if (anArg == "-setshadingmodel"
3230           || anArg == "-setshading"
3231           || anArg == "-shadingmodel"
3232           || anArg == "-shading")
3233     {
3234       if (++anArgIter >= theArgNb)
3235       {
3236         Message::SendFail() << "Error: wrong syntax at " << anArg;
3237         return 1;
3238       }
3239       aChangeSet->ToSetShadingModel = 1;
3240       aChangeSet->ShadingModelName  = theArgVec[anArgIter];
3241       if (!ViewerTest::ParseShadingModel (theArgVec[anArgIter], aChangeSet->ShadingModel))
3242       {
3243         Message::SendFail() << "Error: wrong syntax at " << anArg;
3244         return 1;
3245       }
3246     }
3247     else if (anArg == "-unsetshadingmodel")
3248     {
3249       aChangeSet->ToSetShadingModel = -1;
3250       aChangeSet->ShadingModel = Graphic3d_TOSM_DEFAULT;
3251     }
3252     else if (anArg == "-setinterior"
3253           || anArg == "-setinteriorstyle"
3254           || anArg == "-interior"
3255           || anArg == "-interiorstyle")
3256     {
3257       if (++anArgIter >= theArgNb)
3258       {
3259         Message::SendFail() << "Error: wrong syntax at " << anArg;
3260         return 1;
3261       }
3262       aChangeSet->ToSetInterior = 1;
3263       if (!parseInteriorStyle (theArgVec[anArgIter], aChangeSet->InteriorStyle))
3264       {
3265         Message::SendFail() << "Error: wrong syntax at " << anArg;
3266         return 1;
3267       }
3268     }
3269     else if (anArg == "-unsetinterior")
3270     {
3271       aChangeSet->ToSetInterior = -1;
3272       aChangeSet->InteriorStyle = Aspect_IS_SOLID;
3273     }
3274     else if (anArg == "-setdrawoutline"
3275           || anArg == "-setdrawsilhouette"
3276           || anArg == "-setoutline"
3277           || anArg == "-setsilhouette"
3278           || anArg == "-outline"
3279           || anArg == "-outlined"
3280           || anArg == "-silhouette")
3281     {
3282       bool toDrawOutline = true;
3283       if (anArgIter + 1 < theArgNb
3284        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toDrawOutline))
3285       {
3286         ++anArgIter;
3287       }
3288       aChangeSet->ToSetDrawSilhouette = toDrawOutline ? 1 : -1;
3289     }
3290     else if (anArg == "-setdrawedges"
3291           || anArg == "-setdrawedge"
3292           || anArg == "-drawedges"
3293           || anArg == "-drawedge"
3294           || anArg == "-edges")
3295     {
3296       bool toDrawEdges = true;
3297       if (anArgIter + 1 < theArgNb
3298        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toDrawEdges))
3299       {
3300         ++anArgIter;
3301       }
3302       aChangeSet->ToSetDrawEdges = toDrawEdges ? 1 : -1;
3303     }
3304     else if (anArg == "-setquadedges"
3305           || anArg == "-setquads"
3306           || anArg == "-quads"
3307           || anArg == "-skipfirstedge")
3308     {
3309       bool isQuadMode = true;
3310       if (anArgIter + 1 < theArgNb
3311        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isQuadMode))
3312       {
3313         ++anArgIter;
3314       }
3315       aChangeSet->ToSetQuadEdges = isQuadMode ? 1 : -1;
3316     }
3317     else if (anArg == "-setedgecolor"
3318           || anArg == "-setedgescolor"
3319           || anArg == "-edgecolor"
3320           || anArg == "-edgescolor")
3321     {
3322       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3323                                                            theArgVec + anArgIter + 1,
3324                                                            aChangeSet->EdgeColor);
3325       if (aNbParsed == 0)
3326       {
3327         Message::SendFail() << "Syntax error at '" << anArg << "'";
3328         return 1;
3329       }
3330       anArgIter += aNbParsed;
3331       aChangeSet->ToSetEdgeColor = 1;
3332     }
3333     else if (anArg == "-unset")
3334     {
3335       aChangeSet->ToSetVisibility = 1;
3336       aChangeSet->Visibility = 1;
3337       aChangeSet->ToSetLineWidth = -1;
3338       aChangeSet->LineWidth = 1.0;
3339       aChangeSet->ToSetTypeOfLine = -1;
3340       aChangeSet->StippleLinePattern = 0xFFFF;
3341       aChangeSet->ToSetTypeOfMarker = -1;
3342       aChangeSet->TypeOfMarker = Aspect_TOM_PLUS;
3343       aChangeSet->ToSetMarkerSize = -1;
3344       aChangeSet->MarkerSize = 1.0;
3345       aChangeSet->ToSetTransparency = -1;
3346       aChangeSet->Transparency = 0.0;
3347       aChangeSet->ToSetAlphaMode = -1;
3348       aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto;
3349       aChangeSet->AlphaCutoff = 0.5f;
3350       aChangeSet->ToSetColor = -1;
3351       aChangeSet->Color = DEFAULT_COLOR;
3352       //aChangeSet->ToSetBackFaceColor = -1; // should be reset by ToSetColor
3353       //aChangeSet->BackFaceColor = DEFAULT_COLOR;
3354       aChangeSet->ToSetMaterial = -1;
3355       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
3356       aChangeSet->ToSetShowFreeBoundary = -1;
3357       aChangeSet->ToSetFreeBoundaryColor = -1;
3358       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
3359       aChangeSet->ToSetFreeBoundaryWidth = -1;
3360       aChangeSet->FreeBoundaryWidth = 1.0;
3361       aChangeSet->ToEnableIsoOnTriangulation = -1;
3362       //
3363       aChangeSet->ToSetFaceBoundaryDraw = -1;
3364       aChangeSet->ToSetFaceBoundaryUpperContinuity = -1;
3365       aChangeSet->FaceBoundaryUpperContinuity = GeomAbs_CN;
3366       aChangeSet->ToSetFaceBoundaryColor = -1;
3367       aChangeSet->FaceBoundaryColor = Quantity_NOC_BLACK;
3368       aChangeSet->ToSetFaceBoundaryWidth = -1;
3369       aChangeSet->FaceBoundaryWidth = 1.0f;
3370       aChangeSet->ToSetTypeOfFaceBoundaryLine = -1;
3371       aChangeSet->TypeOfFaceBoundaryLine = Aspect_TOL_SOLID;
3372       //
3373       aChangeSet->ToSetHatch = -1;
3374       aChangeSet->StdHatchStyle = -1;
3375       aChangeSet->PathToHatchPattern.Clear();
3376       aChangeSet->ToSetShadingModel = -1;
3377       aChangeSet->ShadingModel = Graphic3d_TOSM_DEFAULT;
3378       aChangeSet->ToSetInterior = -1;
3379       aChangeSet->InteriorStyle = Aspect_IS_SOLID;
3380       aChangeSet->ToSetDrawSilhouette = -1;
3381       aChangeSet->ToSetDrawEdges = -1;
3382       aChangeSet->ToSetQuadEdges = -1;
3383       aChangeSet->ToSetEdgeColor = -1;
3384       aChangeSet->EdgeColor = Quantity_ColorRGBA (DEFAULT_COLOR);
3385       aChangeSet->ToSetEdgeWidth = -1;
3386       aChangeSet->EdgeWidth = 1.0;
3387       aChangeSet->ToSetTypeOfEdge = -1;
3388       aChangeSet->TypeOfEdge = Aspect_TOL_SOLID;
3389     }
3390     else if (anArg == "-dumpjson")
3391     {
3392       toDump = Standard_True;
3393     }
3394     else if (anArg == "-dumpcompact")
3395     {
3396       toCompactDump = Standard_False;
3397       if (++anArgIter >= theArgNb && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toCompactDump))
3398         ++anArgIter;
3399     }
3400     else if (anArg == "-dumpdepth")
3401     {
3402       if (++anArgIter >= theArgNb)
3403       {
3404         Message::SendFail() << "Error: wrong syntax at " << anArg;
3405         return 1;
3406       }
3407       aDumpDepth = Draw::Atoi (theArgVec[anArgIter]);
3408     }
3409     else
3410     {
3411       Message::SendFail() << "Error: wrong syntax at " << anArg;
3412       return 1;
3413     }
3414   }
3415
3416   for (NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
3417        aChangesIter.More(); aChangesIter.Next())
3418   {
3419     if (!aChangesIter.Value().Validate())
3420     {
3421       return 1;
3422     }
3423   }
3424
3425   // special case for -defaults parameter.
3426   // all changed values will be set to DefaultDrawer.
3427   if (isDefaults)
3428   {
3429     const Handle(Prs3d_Drawer)& aDrawer = aCtx->DefaultDrawer();
3430     aChangeSet->Apply (aDrawer);
3431     if (aChangeSet->ToSetLineWidth != 0)
3432     {
3433       aDrawer->LineAspect()->SetWidth (aChangeSet->LineWidth);
3434       aDrawer->WireAspect()->SetWidth (aChangeSet->LineWidth);
3435       aDrawer->UnFreeBoundaryAspect()->SetWidth (aChangeSet->LineWidth);
3436       aDrawer->SeenLineAspect()->SetWidth (aChangeSet->LineWidth);
3437     }
3438     if (aChangeSet->ToSetColor != 0)
3439     {
3440       aDrawer->ShadingAspect()->SetColor        (aChangeSet->Color);
3441       aDrawer->LineAspect()->SetColor           (aChangeSet->Color);
3442       aDrawer->UnFreeBoundaryAspect()->SetColor (aChangeSet->Color);
3443       aDrawer->SeenLineAspect()->SetColor       (aChangeSet->Color);
3444       aDrawer->WireAspect()->SetColor           (aChangeSet->Color);
3445       aDrawer->PointAspect()->SetColor          (aChangeSet->Color);
3446     }
3447     if (aChangeSet->ToSetTransparency != 0)
3448     {
3449       aDrawer->ShadingAspect()->SetTransparency (aChangeSet->Transparency);
3450     }
3451     if (aChangeSet->ToSetMaterial != 0)
3452     {
3453       aDrawer->ShadingAspect()->SetMaterial (aChangeSet->Material);
3454     }
3455     if (aChangeSet->ToEnableIsoOnTriangulation != 0)
3456     {
3457       aDrawer->SetIsoOnTriangulation (aChangeSet->ToEnableIsoOnTriangulation == 1);
3458     }
3459
3460     // redisplay all objects in context
3461     for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
3462     {
3463       Handle(AIS_InteractiveObject)  aPrs = aPrsIter.Current();
3464       if (!aPrs.IsNull())
3465       {
3466         aCtx->Redisplay (aPrs, Standard_False);
3467       }
3468     }
3469     if (toDump)
3470     {
3471       Standard_SStream aStream;
3472       aDrawer->DumpJson (aStream, aDumpDepth);
3473
3474       if (toCompactDump)
3475         theDI << Standard_Dump::Text (aStream);
3476       else
3477         theDI << Standard_Dump::FormatJson (aStream);
3478     }
3479     return 0;
3480   }
3481
3482   for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
3483   {
3484     const TCollection_AsciiString& aName = aPrsIter.CurrentName();
3485     Handle(AIS_InteractiveObject)  aPrs  = aPrsIter.Current();
3486     if (aPrs.IsNull())
3487     {
3488       return 1;
3489     }
3490
3491     Handle(Prs3d_Drawer)           aDrawer = aPrs->Attributes();
3492     Handle(AIS_ColoredShape) aColoredPrs;
3493     Standard_Boolean toDisplay = Standard_False;
3494     Standard_Boolean toRedisplay = Standard_False;
3495     if (aChanges.Length() > 1 || aChangeSet->ToSetVisibility == 1)
3496     {
3497       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aPrs);
3498       if (aShapePrs.IsNull())
3499       {
3500         Message::SendFail() << "Error: an object " << aName << " is not an AIS_Shape presentation!";
3501         return 1;
3502       }
3503       aColoredPrs = Handle(AIS_ColoredShape)::DownCast (aShapePrs);
3504       if (aColoredPrs.IsNull())
3505       {
3506         aColoredPrs = new AIS_ColoredShape (aShapePrs);
3507         if (aShapePrs->HasDisplayMode())
3508         {
3509           aColoredPrs->SetDisplayMode (aShapePrs->DisplayMode());
3510         }
3511         aColoredPrs->SetLocalTransformation (aShapePrs->LocalTransformation());
3512         aCtx->Remove (aShapePrs, Standard_False);
3513         GetMapOfAIS().UnBind2 (aName);
3514         GetMapOfAIS().Bind (aColoredPrs, aName);
3515         toDisplay = Standard_True;
3516         aShapePrs = aColoredPrs;
3517         aPrs      = aColoredPrs;
3518       }
3519     }
3520
3521     if (!aPrs.IsNull())
3522     {
3523       NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
3524       aChangeSet = &aChangesIter.ChangeValue();
3525       if (aChangeSet->ToSetVisibility == 1)
3526       {
3527         Handle(AIS_ColoredDrawer) aColDrawer = aColoredPrs->CustomAspects (aColoredPrs->Shape());
3528         aColDrawer->SetHidden (aChangeSet->Visibility == 0);
3529       }
3530       else if (aChangeSet->ToSetMaterial == 1)
3531       {
3532         aCtx->SetMaterial (aPrs, aChangeSet->Material, Standard_False);
3533       }
3534       else if (aChangeSet->ToSetMaterial == -1)
3535       {
3536         aCtx->UnsetMaterial (aPrs, Standard_False);
3537       }
3538       if (aChangeSet->ToSetColor == 1)
3539       {
3540         aCtx->SetColor (aPrs, aChangeSet->Color, Standard_False);
3541       }
3542       else if (aChangeSet->ToSetColor == -1)
3543       {
3544         aCtx->UnsetColor (aPrs, Standard_False);
3545       }
3546       if (aChangeSet->ToSetTransparency == 1)
3547       {
3548         aCtx->SetTransparency (aPrs, aChangeSet->Transparency, Standard_False);
3549       }
3550       else if (aChangeSet->ToSetTransparency == -1)
3551       {
3552         aCtx->UnsetTransparency (aPrs, Standard_False);
3553       }
3554       if (aChangeSet->ToSetLineWidth == 1)
3555       {
3556         aCtx->SetWidth (aPrs, aChangeSet->LineWidth, Standard_False);
3557       }
3558       else if (aChangeSet->ToSetLineWidth == -1)
3559       {
3560         aCtx->UnsetWidth (aPrs, Standard_False);
3561       }
3562       else if (aChangeSet->ToEnableIsoOnTriangulation != 0)
3563       {
3564         aCtx->IsoOnTriangulation (aChangeSet->ToEnableIsoOnTriangulation == 1, aPrs);
3565         toRedisplay = Standard_True;
3566       }
3567       else if (aChangeSet->ToSetSensitivity != 0)
3568       {
3569         aCtx->SetSelectionSensitivity (aPrs, aChangeSet->SelectionMode, aChangeSet->Sensitivity);
3570       }
3571       if (!aDrawer.IsNull())
3572       {
3573         toRedisplay = aChangeSet->Apply (aDrawer) || toRedisplay;
3574       }
3575
3576       for (aChangesIter.Next(); aChangesIter.More(); aChangesIter.Next())
3577       {
3578         aChangeSet = &aChangesIter.ChangeValue();
3579         for (NCollection_Sequence<TopoDS_Shape>::Iterator aSubShapeIter (aChangeSet->SubShapes);
3580              aSubShapeIter.More(); aSubShapeIter.Next())
3581         {
3582           const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
3583           if (!aChangeSet->IsEmpty())
3584           {
3585             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
3586             aChangeSet->Apply (aCurColDrawer);
3587           }
3588           if (aChangeSet->ToSetVisibility == 1)
3589           {
3590             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
3591             aCurColDrawer->SetHidden (aChangeSet->Visibility == 0);
3592           }
3593           if (aChangeSet->ToSetColor == 1)
3594           {
3595             aColoredPrs->SetCustomColor (aSubShape, aChangeSet->Color);
3596           }
3597           if (aChangeSet->ToSetTransparency == 1)
3598           {
3599             aColoredPrs->SetCustomTransparency (aSubShape, aChangeSet->Transparency);
3600           }
3601           if (aChangeSet->ToSetLineWidth == 1)
3602           {
3603             aColoredPrs->SetCustomWidth (aSubShape, aChangeSet->LineWidth);
3604           }
3605           if (aChangeSet->ToSetColor     == -1
3606            || aChangeSet->ToSetLineWidth == -1)
3607           {
3608             aColoredPrs->UnsetCustomAspects (aSubShape, Standard_True);
3609           }
3610           if (aChangeSet->ToSetSensitivity != 0)
3611           {
3612             aCtx->SetSelectionSensitivity (aPrs, aChangeSet->SelectionMode, aChangeSet->Sensitivity);
3613           }
3614         }
3615       }
3616       if (toDisplay)
3617       {
3618         aCtx->Display (aPrs, Standard_False);
3619       }
3620       if (toRedisplay)
3621       {
3622         aCtx->Redisplay (aPrs, Standard_False);
3623       }
3624       else if (!aColoredPrs.IsNull())
3625       {
3626         aCtx->Redisplay (aColoredPrs, Standard_False);
3627       }
3628       else
3629       {
3630         aPrs->SynchronizeAspects();
3631       }
3632
3633       if (toDump)
3634       {
3635         Standard_SStream aStream;
3636         aDrawer->DumpJson (aStream);
3637
3638         theDI << aName << ": \n";
3639         theDI << Standard_Dump::FormatJson (aStream);
3640         theDI << "\n";
3641       }
3642     }
3643   }
3644   return 0;
3645 }
3646
3647 //==============================================================================
3648 //function : VDonly2
3649 //author   : ege
3650 //purpose  : Display only a selected or named  object
3651 //           if there is no selected or named object s, nothing is done
3652 //==============================================================================
3653 static int VDonly2 (Draw_Interpretor& ,
3654                     Standard_Integer  theArgNb,
3655                     const char**      theArgVec)
3656 {
3657   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
3658   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
3659   if (aCtx.IsNull())
3660   {
3661     Message::SendFail ("Error: no active view!");
3662     return 1;
3663   }
3664
3665   Standard_Integer anArgIter = 1;
3666   for (; anArgIter < theArgNb; ++anArgIter)
3667   {
3668     if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
3669     {
3670       break;
3671     }
3672   }
3673
3674   NCollection_Map<Handle(Standard_Transient)> aDispSet;
3675   if (anArgIter >= theArgNb)
3676   {
3677     // display only selected objects
3678     if (aCtx->NbSelected() < 1)
3679     {
3680       return 0;
3681     }
3682
3683     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
3684     {
3685       aDispSet.Add (aCtx->SelectedInteractive());
3686     }
3687   }
3688   else
3689   {
3690     // display only specified objects
3691     for (; anArgIter < theArgNb; ++anArgIter)
3692     {
3693       TCollection_AsciiString aName = theArgVec[anArgIter];
3694       Handle(AIS_InteractiveObject) aShape;
3695       if (GetMapOfAIS().Find2 (aName, aShape)
3696       && !aShape.IsNull())
3697       {
3698         aCtx->Display (aShape, Standard_False);
3699         aDispSet.Add (aShape);
3700       }
3701     }
3702   }
3703
3704   // weed out other objects
3705   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); anIter.More(); anIter.Next())
3706   {
3707     if (aDispSet.Contains (anIter.Key1()))
3708     {
3709       continue;
3710     }
3711
3712     if (Handle(AIS_InteractiveObject) aShape = anIter.Key1())
3713     {
3714       aCtx->Erase (aShape, Standard_False);
3715     }
3716   }
3717   return 0;
3718 }
3719
3720 //==============================================================================
3721 //function : VRemove
3722 //purpose  : Removes selected or named objects.
3723 //           If there is no selected or named objects,
3724 //           all objects in the viewer can be removed with argument -all.
3725 //           If -context is in arguments, the object is not deleted from the map of
3726 //           objects (deleted only from the current context).
3727 //==============================================================================
3728 int VRemove (Draw_Interpretor& theDI,
3729              Standard_Integer  theArgNb,
3730              const char**      theArgVec)
3731 {
3732   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
3733   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
3734   if (aCtx.IsNull())
3735   {
3736     Message::SendFail ("Error: no active view!");
3737     return 1;
3738   }
3739
3740   Standard_Boolean isContextOnly = Standard_False;
3741   Standard_Boolean toRemoveAll   = Standard_False;
3742   Standard_Boolean toPrintInfo   = Standard_True;
3743   Standard_Boolean toFailOnError = Standard_True;
3744
3745   Standard_Integer anArgIter = 1;
3746   for (; anArgIter < theArgNb; ++anArgIter)
3747   {
3748     TCollection_AsciiString anArg = theArgVec[anArgIter];
3749     anArg.LowerCase();
3750     if (anArg == "-context")
3751     {
3752       isContextOnly = Standard_True;
3753     }
3754     else if (anArg == "-all")
3755     {
3756       toRemoveAll = Standard_True;
3757     }
3758     else if (anArg == "-noinfo")
3759     {
3760       toPrintInfo = Standard_False;
3761     }
3762     else if (anArg == "-noerror"
3763           || anArg == "-nofail")
3764     {
3765       toFailOnError = Standard_False;
3766     }
3767     else if (anUpdateTool.parseRedrawMode (anArg))
3768     {
3769       continue;
3770     }
3771     else
3772     {
3773       break;
3774     }
3775   }
3776   if (toRemoveAll
3777    && anArgIter < theArgNb)
3778   {
3779     Message::SendFail ("Error: wrong syntax!");
3780     return 1;
3781   }
3782
3783   NCollection_List<TCollection_AsciiString> anIONameList;
3784   if (toRemoveAll)
3785   {
3786     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3787          anIter.More(); anIter.Next())
3788     {
3789       anIONameList.Append (anIter.Key2());
3790     }
3791   }
3792   else if (anArgIter < theArgNb) // removed objects names are in argument list
3793   {
3794     for (; anArgIter < theArgNb; ++anArgIter)
3795     {
3796       const TCollection_AsciiString aName (theArgVec[anArgIter]);
3797       if (aName.Search ("*") != -1)
3798       {
3799         for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aPrsIter (GetMapOfAIS()); aPrsIter.More(); aPrsIter.Next())
3800         {
3801           if (aPrsIter.Key1()->GetContext() != aCtx)
3802           {
3803             continue;
3804           }
3805           const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aName + "' '" + aPrsIter.Key2() + "'";
3806           if (theDI.Eval (aCheck.ToCString()) == 0
3807           && *theDI.Result() == '1')
3808           {
3809             anIONameList.Append (aPrsIter.Key2());
3810           }
3811         }
3812         theDI.Reset();
3813         continue;
3814       }
3815
3816       Handle(AIS_InteractiveObject) anIO;
3817       if (!GetMapOfAIS().Find2 (aName, anIO))
3818       {
3819         if (toFailOnError)
3820         {
3821           Message::SendFail() << "Syntax error: '" << aName << "' was not bound to some object.";
3822           return 1;
3823         }
3824       }
3825       else if (anIO->GetContext() != aCtx)
3826       {
3827         if (toFailOnError)
3828         {
3829           Message::SendFail() << "Syntax error: '" << aName << "' was not displayed in current context.\n"
3830                               << "Please activate view with this object displayed and try again.";
3831           return 1;
3832         }
3833       }
3834       else
3835       {
3836         anIONameList.Append (aName);
3837       }
3838     }
3839   }
3840   else if (aCtx->NbSelected() > 0)
3841   {
3842     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3843          anIter.More(); anIter.Next())
3844     {
3845       if (!aCtx->IsSelected (anIter.Key1()))
3846       {
3847         continue;
3848       }
3849
3850       anIONameList.Append (anIter.Key2());
3851       continue;
3852     }
3853   }
3854
3855   // Unbind all removed objects from the map of displayed IO.
3856   for (NCollection_List<TCollection_AsciiString>::Iterator anIter (anIONameList);
3857        anIter.More(); anIter.Next())
3858   {
3859     const Handle(AIS_InteractiveObject) anIO = GetMapOfAIS().Find2 (anIter.Value());
3860     aCtx->Remove (anIO, Standard_False);
3861     if (toPrintInfo)
3862     {
3863       theDI << anIter.Value() << " ";
3864     }
3865     if (!isContextOnly)
3866     {
3867       GetMapOfAIS().UnBind2 (anIter.Value());
3868     }
3869   }
3870   return 0;
3871 }
3872
3873 //==============================================================================
3874 //function : VErase
3875 //purpose  : Erase some selected or named objects
3876 //           if there is no selected or named objects, the whole viewer is erased
3877 //==============================================================================
3878 int VErase (Draw_Interpretor& theDI,
3879             Standard_Integer  theArgNb,
3880             const char**      theArgVec)
3881 {
3882   const Handle(AIS_InteractiveContext)& aCtx  = ViewerTest::GetAISContext();
3883   const Handle(V3d_View)&               aView = ViewerTest::CurrentView();
3884   ViewerTest_AutoUpdater anUpdateTool (aCtx, aView);
3885   if (aCtx.IsNull())
3886   {
3887     Message::SendFail ("Error: no active view!");
3888     return 1;
3889   }
3890
3891   const Standard_Boolean toEraseAll = TCollection_AsciiString (theArgNb > 0 ? theArgVec[0] : "") == "veraseall";
3892
3893   Standard_Integer anArgIter = 1;
3894   Standard_Boolean toEraseInView = Standard_False;
3895   Standard_Boolean toFailOnError = Standard_True;
3896   TColStd_SequenceOfAsciiString aNamesOfEraseIO;
3897   for (; anArgIter < theArgNb; ++anArgIter)
3898   {
3899     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
3900     anArgCase.LowerCase();
3901     if (anUpdateTool.parseRedrawMode (anArgCase))
3902     {
3903       continue;
3904     }
3905     else if (anArgCase == "-view"
3906           || anArgCase == "-inview")
3907     {
3908       toEraseInView = Standard_True;
3909     }
3910     else if (anArgCase == "-noerror"
3911           || anArgCase == "-nofail")
3912     {
3913       toFailOnError = Standard_False;
3914     }
3915     else
3916     {
3917       aNamesOfEraseIO.Append (theArgVec[anArgIter]);
3918     }
3919   }
3920
3921   if (!aNamesOfEraseIO.IsEmpty() && toEraseAll)
3922   {
3923     Message::SendFail() << "Error: wrong syntax, " << theArgVec[0] << " too much arguments.";
3924     return 1;
3925   }
3926
3927   if (!aNamesOfEraseIO.IsEmpty())
3928   {
3929     // Erase named objects
3930     NCollection_IndexedDataMap<Handle(AIS_InteractiveObject), TCollection_AsciiString> aPrsList;
3931     for (TColStd_SequenceOfAsciiString::Iterator anIter (aNamesOfEraseIO); anIter.More(); anIter.Next())
3932     {
3933       const TCollection_AsciiString& aName = anIter.Value();
3934       if (aName.Search ("*") != -1)
3935       {
3936         for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aPrsIter (GetMapOfAIS()); aPrsIter.More(); aPrsIter.Next())
3937         {
3938           const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aName + "' '" + aPrsIter.Key2() + "'";
3939           if (theDI.Eval (aCheck.ToCString()) == 0
3940           && *theDI.Result() == '1')
3941           {
3942             aPrsList.Add (aPrsIter.Key1(), aPrsIter.Key2());
3943           }
3944         }
3945         theDI.Reset();
3946       }
3947       else
3948       {
3949         Handle(AIS_InteractiveObject) anIO;
3950         if (!GetMapOfAIS().Find2 (aName, anIO))
3951         {
3952           if (toFailOnError)
3953           {
3954             Message::SendFail() << "Syntax error: '" << aName << "' is not found";
3955             return 1;
3956           }
3957         }
3958         else
3959         {
3960           aPrsList.Add (anIO, aName);
3961         }
3962       }
3963     }
3964
3965     for (NCollection_IndexedDataMap<Handle(AIS_InteractiveObject), TCollection_AsciiString>::Iterator anIter (aPrsList); anIter.More(); anIter.Next())
3966     {
3967       theDI << anIter.Value() << " ";
3968       if (toEraseInView)
3969       {
3970         aCtx->SetViewAffinity (anIter.Key(), aView, Standard_False);
3971       }
3972       else
3973       {
3974         aCtx->Erase (anIter.Key(), Standard_False);
3975       }
3976     }
3977   }
3978   else if (!toEraseAll && aCtx->NbSelected() > 0)
3979   {
3980     // Erase selected objects
3981     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3982          anIter.More(); anIter.Next())
3983     {
3984       const Handle(AIS_InteractiveObject) anIO = anIter.Key1();
3985       if (!anIO.IsNull()
3986        && aCtx->IsSelected (anIO))
3987       {
3988         theDI << anIter.Key2() << " ";
3989         if (toEraseInView)
3990         {
3991           aCtx->SetViewAffinity (anIO, aView, Standard_False);
3992         }
3993       }
3994     }
3995
3996     if (!toEraseInView)
3997     {
3998       aCtx->EraseSelected (Standard_False);
3999     }
4000   }
4001   else
4002   {
4003     // Erase all objects
4004     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
4005          anIter.More(); anIter.Next())
4006     {
4007       Handle(AIS_InteractiveObject) anIO = anIter.Key1();
4008       if (!anIO.IsNull())
4009       {
4010         if (toEraseInView)
4011         {
4012           aCtx->SetViewAffinity (anIO, aView, Standard_False);
4013         }
4014         else
4015         {
4016           aCtx->Erase (anIO, Standard_False);
4017         }
4018       }
4019     }
4020   }
4021
4022   return 0;
4023 }
4024
4025 //==============================================================================
4026 //function : VDisplayAll
4027 //purpose  : Display all the objects of the Map
4028 //==============================================================================
4029 static int VDisplayAll (Draw_Interpretor& ,
4030                         Standard_Integer  theArgNb,
4031                         const char**      theArgVec)
4032
4033 {
4034   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
4035   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
4036   if (aCtx.IsNull())
4037   {
4038     Message::SendFail ("Error: no active view!");
4039     return 1;
4040   }
4041
4042   Standard_Integer anArgIter = 1;
4043   for (; anArgIter < theArgNb; ++anArgIter)
4044   {
4045     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
4046     anArgCase.LowerCase();
4047     if (anUpdateTool.parseRedrawMode (anArgCase))
4048     {
4049       continue;
4050     }
4051     else
4052     {
4053       break;
4054     }
4055   }
4056   if (anArgIter < theArgNb)
4057   {
4058     Message::SendFail() << theArgVec[0] << "Error: wrong syntax";
4059     return 1;
4060   }
4061
4062   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
4063        anIter.More(); anIter.Next())
4064   {
4065     aCtx->Erase (anIter.Key1(), Standard_False);
4066   }
4067
4068   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
4069        anIter.More(); anIter.Next())
4070   {
4071     aCtx->Display (anIter.Key1(), Standard_False);
4072   }
4073   return 0;
4074 }
4075
4076 //! Auxiliary method to check if presentation exists
4077 inline Standard_Integer checkMode (const Handle(AIS_InteractiveContext)& theCtx,
4078                                    const Handle(AIS_InteractiveObject)&  theIO,
4079                                    const Standard_Integer                theMode)
4080 {
4081   if (theIO.IsNull() || theCtx.IsNull())
4082   {
4083     return -1;
4084   }
4085
4086   if (theMode != -1)
4087   {
4088     if (theCtx->MainPrsMgr()->HasPresentation (theIO, theMode))
4089     {
4090       return theMode;
4091     }
4092   }
4093   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theIO->DisplayMode()))
4094   {
4095     return theIO->DisplayMode();
4096   }
4097   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theCtx->DisplayMode()))
4098   {
4099     return theCtx->DisplayMode();
4100   }
4101
4102   return -1;
4103 }
4104
4105 enum ViewerTest_BndAction
4106 {
4107   BndAction_Hide,
4108   BndAction_Show,
4109   BndAction_Print
4110 };
4111
4112 //! Auxiliary method to print bounding box of presentation
4113 inline void bndPresentation (Draw_Interpretor&                         theDI,
4114                              const Handle(PrsMgr_PresentationManager)& theMgr,
4115                              const Handle(AIS_InteractiveObject)&      theObj,
4116                              const Standard_Integer                    theDispMode,
4117                              const TCollection_AsciiString&            theName,
4118                              const ViewerTest_BndAction                theAction,
4119                              const Handle(Prs3d_Drawer)&               theStyle)
4120 {
4121   switch (theAction)
4122   {
4123     case BndAction_Hide:
4124     {
4125       theMgr->Unhighlight (theObj);
4126       break;
4127     }
4128     case BndAction_Show:
4129     {
4130       theMgr->Color (theObj, theStyle, theDispMode);
4131       break;
4132     }
4133     case BndAction_Print:
4134     {
4135       Bnd_Box aBox;
4136       for (PrsMgr_Presentations::Iterator aPrsIter (theObj->Presentations()); aPrsIter.More(); aPrsIter.Next())
4137       {
4138         if (aPrsIter.Value()->Mode() != theDispMode)
4139           continue;
4140
4141         aBox = aPrsIter.Value()->MinMaxValues();
4142       }
4143       gp_Pnt aMin = aBox.CornerMin();
4144       gp_Pnt aMax = aBox.CornerMax();
4145       theDI << theName  << "\n"
4146             << aMin.X() << " " << aMin.Y() << " " << aMin.Z() << " "
4147             << aMax.X() << " " << aMax.Y() << " " << aMax.Z() << "\n";
4148       break;
4149     }
4150   }
4151 }
4152
4153 //==============================================================================
4154 //function : VBounding
4155 //purpose  :
4156 //==============================================================================
4157 int VBounding (Draw_Interpretor& theDI,
4158                Standard_Integer  theArgNb,
4159                const char**      theArgVec)
4160 {
4161   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
4162   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
4163   if (aCtx.IsNull())
4164   {
4165     Message::SendFail ("Error: no active view!");
4166     return 1;
4167   }
4168
4169   ViewerTest_BndAction anAction = BndAction_Show;
4170   Standard_Integer     aMode    = -1;
4171
4172   Handle(Prs3d_Drawer) aStyle;
4173
4174   Standard_Integer anArgIter = 1;
4175   for (; anArgIter < theArgNb; ++anArgIter)
4176   {
4177     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4178     anArg.LowerCase();
4179     if (anArg == "-print")
4180     {
4181       anAction = BndAction_Print;
4182     }
4183     else if (anArg == "-show")
4184     {
4185       anAction = BndAction_Show;
4186     }
4187     else if (anArg == "-hide")
4188     {
4189       anAction = BndAction_Hide;
4190     }
4191     else if (anArg == "-mode")
4192     {
4193       if (++anArgIter >= theArgNb)
4194       {
4195         Message::SendFail() << "Error: wrong syntax at " << anArg;
4196         return 1;
4197       }
4198       aMode = Draw::Atoi (theArgVec[anArgIter]);
4199     }
4200     else if (!anUpdateTool.parseRedrawMode (anArg))
4201     {
4202       break;
4203     }
4204   }
4205
4206   if (anAction == BndAction_Show)
4207   {
4208     aStyle = new Prs3d_Drawer();
4209     aStyle->SetMethod (Aspect_TOHM_BOUNDBOX);
4210     aStyle->SetColor  (Quantity_NOC_GRAY99);
4211   }
4212
4213   Standard_Integer aHighlightedMode = -1;
4214   if (anArgIter < theArgNb)
4215   {
4216     // has a list of names
4217     for (; anArgIter < theArgNb; ++anArgIter)
4218     {
4219       TCollection_AsciiString aName = theArgVec[anArgIter];
4220       Handle(AIS_InteractiveObject) anIO;
4221       if (!GetMapOfAIS().Find2 (aName, anIO))
4222       {
4223         Message::SendFail() << "Error: presentation " << aName << " does not exist";
4224         return 1;
4225       }
4226
4227       aHighlightedMode = checkMode (aCtx, anIO, aMode);
4228       if (aHighlightedMode == -1)
4229       {
4230         Message::SendFail() << "Error: object " << aName << " has no presentation with mode " << aMode;
4231         return 1;
4232       }
4233       bndPresentation (theDI, aCtx->MainPrsMgr(), anIO, aHighlightedMode, aName, anAction, aStyle);
4234     }
4235   }
4236   else if (aCtx->NbSelected() > 0)
4237   {
4238     // remove all currently selected objects
4239     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
4240     {
4241       Handle(AIS_InteractiveObject) anIO = aCtx->SelectedInteractive();
4242       aHighlightedMode = checkMode (aCtx, anIO, aMode);
4243       if (aHighlightedMode != -1)
4244       {
4245         bndPresentation (theDI, aCtx->MainPrsMgr(), anIO, aHighlightedMode,
4246           GetMapOfAIS().IsBound1 (anIO) ? GetMapOfAIS().Find1 (anIO) : "", anAction, aStyle);
4247       }
4248     }
4249   }
4250   else
4251   {
4252     // all objects
4253     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
4254          anIter.More(); anIter.Next())
4255     {
4256       Handle(AIS_InteractiveObject) anIO = anIter.Key1();
4257       aHighlightedMode = checkMode (aCtx, anIO, aMode);
4258       if (aHighlightedMode != -1)
4259       {
4260         bndPresentation (theDI, aCtx->MainPrsMgr(), anIO, aHighlightedMode, anIter.Key2(), anAction, aStyle);
4261       }
4262     }
4263   }
4264   return 0;
4265 }
4266
4267 //==============================================================================
4268 //function : VTexture
4269 //purpose  :
4270 //==============================================================================
4271 Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
4272 {
4273   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
4274   if (aCtx.IsNull())
4275   {
4276     Message::SendFail() << "Error: no active view!";
4277     return 1;
4278   }
4279
4280   int  toModulate     = -1;
4281   bool toSetFilter    = false;
4282   bool toSetAniso     = false;
4283   bool toSetTrsfAngle = false;
4284   bool toSetTrsfTrans = false;
4285   bool toSetTrsfScale = false;
4286   Standard_ShortReal aTrsfRotAngle = 0.0f;
4287   Graphic3d_Vec2 aTrsfTrans (0.0f, 0.0f);
4288   Graphic3d_Vec2 aTrsfScale (1.0f, 1.0f);
4289   Graphic3d_TypeOfTextureFilter      aFilter       = Graphic3d_TOTF_NEAREST;
4290   Graphic3d_LevelOfTextureAnisotropy anAnisoFilter = Graphic3d_LOTA_OFF;
4291
4292   Handle(AIS_InteractiveObject) aTexturedIO;
4293   Handle(AIS_Shape) aTexturedShape;
4294   Handle(Graphic3d_TextureSet) aTextureSetOld;
4295   NCollection_Vector<Handle(Graphic3d_Texture2Dmanual)> aTextureVecNew;
4296   bool toSetGenRepeat = false;
4297   bool toSetGenScale  = false;
4298   bool toSetGenOrigin = false;
4299   bool toSetImage     = false;
4300   bool toComputeUV    = false;
4301
4302   const TCollection_AsciiString aCommandName (theArgVec[0]);
4303   bool toSetDefaults = aCommandName == "vtexdefault";
4304
4305   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
4306   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
4307   {
4308     const TCollection_AsciiString aName     = theArgVec[anArgIter];
4309     TCollection_AsciiString       aNameCase = aName;
4310     aNameCase.LowerCase();
4311     if (anUpdateTool.parseRedrawMode (aName))
4312     {
4313       continue;
4314     }
4315     else if (aTexturedIO.IsNull())
4316     {
4317       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfIO = GetMapOfAIS();
4318       if (aMapOfIO.IsBound2 (aName))
4319       {
4320         aTexturedIO = aMapOfIO.Find2 (aName);
4321         aTexturedShape = Handle(AIS_Shape)::DownCast (aTexturedIO);
4322       }
4323       if (aTexturedIO.IsNull())
4324       {
4325         Message::SendFail() << "Syntax error: shape " << aName << " does not exists in the viewer.";
4326         return 1;
4327       }
4328
4329       if (aTexturedIO->Attributes()->HasOwnShadingAspect())
4330       {
4331         aTextureSetOld = aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureSet();
4332       }
4333     }
4334     else if (!aTexturedShape.IsNull()
4335           && (aNameCase == "-scale"
4336            || aNameCase == "-setscale"
4337            || aCommandName == "vtexscale"))
4338     {
4339       if (aCommandName != "vtexscale")
4340       {
4341         ++anArgIter;
4342       }
4343       if (anArgIter < theArgsNb)
4344       {
4345         TCollection_AsciiString aValU (theArgVec[anArgIter]);
4346         TCollection_AsciiString aValUCase = aValU;
4347         aValUCase.LowerCase();
4348         toSetGenScale = true;
4349         if (aValUCase == "off")
4350         {
4351           aTexturedShape->SetTextureScaleUV (gp_Pnt2d (1.0, 1.0));
4352           continue;
4353         }
4354         else if (anArgIter + 1 < theArgsNb)
4355         {
4356           TCollection_AsciiString aValV (theArgVec[anArgIter + 1]);
4357           if (aValU.IsRealValue()
4358            && aValV.IsRealValue())
4359           {
4360             aTexturedShape->SetTextureScaleUV (gp_Pnt2d (aValU.RealValue(), aValV.RealValue()));
4361             ++anArgIter;
4362             continue;
4363           }
4364         }
4365       }
4366       Message::SendFail() << "Syntax error: unexpected argument '" << aName << "'";
4367       return 1;
4368     }
4369     else if (!aTexturedShape.IsNull()
4370           && (aNameCase == "-origin"
4371            || aNameCase == "-setorigin"
4372            || aCommandName == "vtexorigin"))
4373     {
4374       if (aCommandName != "vtexorigin")
4375       {
4376         ++anArgIter;
4377       }
4378       if (anArgIter < theArgsNb)
4379       {
4380         TCollection_AsciiString aValU (theArgVec[anArgIter]);
4381         TCollection_AsciiString aValUCase = aValU;
4382         aValUCase.LowerCase();
4383         toSetGenOrigin = true;
4384         if (aValUCase == "off")
4385         {
4386           aTexturedShape->SetTextureOriginUV (gp_Pnt2d (0.0, 0.0));
4387           continue;
4388         }
4389         else if (anArgIter + 1 < theArgsNb)
4390         {
4391           TCollection_AsciiString aValV (theArgVec[anArgIter + 1]);
4392           if (aValU.IsRealValue()
4393            && aValV.IsRealValue())
4394           {
4395             aTexturedShape->SetTextureOriginUV (gp_Pnt2d (aValU.RealValue(), aValV.RealValue()));
4396             ++anArgIter;
4397             continue;
4398           }
4399         }
4400       }
4401       Message::SendFail() << "Syntax error: unexpected argument '" << aName << "'";
4402       return 1;
4403     }
4404     else if (!aTexturedShape.IsNull()
4405           && (aNameCase == "-repeat"
4406            || aNameCase == "-setrepeat"
4407            || aCommandName == "vtexrepeat"))
4408     {
4409       if (aCommandName != "vtexrepeat")
4410       {
4411         ++anArgIter;
4412       }
4413       if (anArgIter < theArgsNb)
4414       {
4415         TCollection_AsciiString aValU (theArgVec[anArgIter]);
4416         TCollection_AsciiString aValUCase = aValU;
4417         aValUCase.LowerCase();
4418         toSetGenRepeat = true;
4419         if (aValUCase == "off")
4420         {
4421           aTexturedShape->SetTextureRepeatUV (gp_Pnt2d (1.0, 1.0));
4422           continue;
4423         }
4424         else if (anArgIter + 1 < theArgsNb)
4425         {
4426           TCollection_AsciiString aValV (theArgVec[anArgIter + 1]);
4427           if (aValU.IsRealValue()
4428            && aValV.IsRealValue())
4429           {
4430             aTexturedShape->SetTextureRepeatUV (gp_Pnt2d (aValU.RealValue(), aValV.RealValue()));
4431             ++anArgIter;
4432             continue;
4433           }
4434         }
4435       }
4436       Message::SendFail() << "Syntax error: unexpected argument '" << aName << "'";
4437       return 1;
4438     }
4439     else if (aNameCase == "-modulate")
4440     {
4441       bool toModulateBool = true;
4442       if (anArgIter + 1 < theArgsNb
4443        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toModulateBool))
4444       {
4445         ++anArgIter;
4446       }
4447       toModulate = toModulateBool ? 1 : 0;
4448     }
4449     else if ((aNameCase == "-setfilter"
4450            || aNameCase == "-filter")
4451            && anArgIter + 1 < theArgsNb)
4452     {
4453       TCollection_AsciiString aValue (theArgVec[anArgIter + 1]);
4454       aValue.LowerCase();
4455       ++anArgIter;
4456       toSetFilter = true;
4457       if (aValue == "nearest")
4458       {
4459         aFilter = Graphic3d_TOTF_NEAREST;
4460       }
4461       else if (aValue == "bilinear")
4462       {
4463         aFilter = Graphic3d_TOTF_BILINEAR;
4464       }
4465       else if (aValue == "trilinear")
4466       {
4467         aFilter = Graphic3d_TOTF_TRILINEAR;
4468       }
4469       else
4470       {
4471         Message::SendFail() << "Syntax error: unexpected argument '" << aValue << "'";
4472         return 1;
4473       }
4474     }
4475     else if ((aNameCase == "-setaniso"
4476            || aNameCase == "-setanisofilter"
4477            || aNameCase == "-aniso"
4478            || aNameCase == "-anisofilter")
4479            && anArgIter + 1 < theArgsNb)
4480     {
4481       TCollection_AsciiString aValue (theArgVec[anArgIter + 1]);
4482       aValue.LowerCase();
4483       ++anArgIter;
4484       toSetAniso = true;
4485       if (aValue == "off")
4486       {
4487         anAnisoFilter = Graphic3d_LOTA_OFF;
4488       }
4489       else if (aValue == "fast")
4490       {
4491         anAnisoFilter = Graphic3d_LOTA_FAST;
4492       }
4493       else if (aValue == "middle")
4494       {
4495         anAnisoFilter = Graphic3d_LOTA_MIDDLE;
4496       }
4497       else if (aValue == "quality"
4498             || aValue == "high")
4499       {
4500         anAnisoFilter =  Graphic3d_LOTA_QUALITY;
4501       }
4502       else
4503       {
4504         Message::SendFail() << "Syntax error: unexpected argument '" << aValue << "'";
4505         return 1;
4506       }
4507     }
4508     else if ((aNameCase == "-rotateangle"
4509            || aNameCase == "-rotangle"
4510            || aNameCase == "-rotate"
4511            || aNameCase == "-angle"
4512            || aNameCase == "-trsfangle")
4513            && anArgIter + 1 < theArgsNb)
4514     {
4515       aTrsfRotAngle  = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 1]));
4516       toSetTrsfAngle = true;
4517       ++anArgIter;
4518     }
4519     else if ((aNameCase == "-trsftrans"
4520            || aNameCase == "-trsftranslate"
4521            || aNameCase == "-translate"
4522            || aNameCase == "-translation")
4523            && anArgIter + 2 < theArgsNb)
4524     {
4525       aTrsfTrans.x() = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 1]));
4526       aTrsfTrans.y() = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 2]));
4527       toSetTrsfTrans = true;
4528       anArgIter += 2;
4529     }
4530     else if ((aNameCase == "-trsfscale")
4531            && anArgIter + 2 < theArgsNb)
4532     {
4533       aTrsfScale.x() = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 1]));
4534       aTrsfScale.y() = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 2]));
4535       toSetTrsfScale = true;
4536       anArgIter += 2;
4537     }
4538     else if (aNameCase == "-default"
4539           || aNameCase == "-defaults")
4540     {
4541       toSetDefaults = true;
4542     }
4543     else if ((aNameCase == "-video")
4544            && anArgIter + 1 < theArgsNb)
4545     {
4546       const TCollection_AsciiString anInput (theArgVec[++anArgIter]);
4547       Handle(Graphic3d_MediaTextureSet) aMedia = Handle(Graphic3d_MediaTextureSet)::DownCast (aTextureSetOld);
4548       if (aMedia.IsNull())
4549       {
4550         aMedia = new Graphic3d_MediaTextureSet();
4551       }
4552       if (aMedia->Input() != anInput)
4553       {
4554         aMedia->OpenInput (anInput, false);
4555       }
4556       else
4557       {
4558         if (aMedia->SwapFrames()
4559         && !aCtx->CurrentViewer()->ZLayerSettings (aTexturedIO->ZLayer()).IsImmediate())
4560         {
4561           ViewerTest::CurrentView()->Invalidate();
4562         }
4563       }
4564       if (aTexturedIO->Attributes()->SetupOwnShadingAspect (aCtx->DefaultDrawer())
4565        && aTexturedShape.IsNull())
4566       {
4567         aTexturedIO->SetToUpdate();
4568       }
4569
4570       toComputeUV = aTextureSetOld.IsNull();
4571       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOn (true);
4572       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureSet (aMedia);
4573       aTextureSetOld.Nullify();
4574     }
4575     else if (aCommandName == "vtexture"
4576           && (aTextureVecNew.IsEmpty()
4577            || aNameCase.StartsWith ("-tex")))
4578     {
4579       Standard_Integer aTexIndex = 0;
4580       TCollection_AsciiString aTexName = aName;
4581       if (aNameCase.StartsWith ("-tex"))
4582       {
4583         if (anArgIter + 1 >= theArgsNb
4584          || aNameCase.Length() < 5)
4585         {
4586           Message::SendFail() << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'";
4587           return 1;
4588         }
4589
4590         TCollection_AsciiString aTexIndexStr = aNameCase.SubString (5, aNameCase.Length());
4591         if (!aTexIndexStr.IsIntegerValue())
4592         {
4593           Message::SendFail() << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'";
4594           return 1;
4595         }
4596
4597         aTexIndex = aTexIndexStr.IntegerValue();
4598         aTexName  = theArgVec[anArgIter + 1];
4599         ++anArgIter;
4600       }
4601       if (aTexIndex >= Graphic3d_TextureUnit_NB
4602        || aTexIndex >= aCtx->CurrentViewer()->Driver()->InquireLimit (Graphic3d_TypeOfLimit_MaxCombinedTextureUnits))
4603       {
4604         Message::SendFail ("Error: too many textures specified");
4605         return 1;
4606       }
4607
4608       toSetImage = true;
4609       if (aTexName.IsIntegerValue())
4610       {
4611         const Standard_Integer aValue = aTexName.IntegerValue();
4612         if (aValue < 0 || aValue >= Graphic3d_Texture2D::NumberOfTextures())
4613         {
4614           Message::SendFail() << "Syntax error: texture with ID " << aValue << " is undefined!";
4615           return 1;
4616         }
4617         aTextureVecNew.SetValue (aTexIndex, new Graphic3d_Texture2Dmanual (Graphic3d_NameOfTexture2D (aValue)));
4618       }
4619       else if (aTexName == "?")
4620       {
4621         const TCollection_AsciiString aTextureFolder = Graphic3d_TextureRoot::TexturesFolder();
4622
4623         theDi << "\n Files in current directory : \n\n";
4624         theDi.Eval ("glob -nocomplain *");
4625
4626         TCollection_AsciiString aCmnd ("glob -nocomplain ");
4627         aCmnd += aTextureFolder;
4628         aCmnd += "/* ";
4629
4630         theDi << "Files in " << aTextureFolder << " : \n\n";
4631         theDi.Eval (aCmnd.ToCString());
4632         return 0;
4633       }
4634       else if (aTexName != "off")
4635       {
4636         if (!OSD_File (aTexName).Exists())
4637         {
4638           Message::SendFail() << "Syntax error: non-existing image file has been specified '" << aTexName << "'.";
4639           return 1;
4640         }
4641         aTextureVecNew.SetValue (aTexIndex, new Graphic3d_Texture2Dmanual (aTexName));
4642       }
4643       else
4644       {
4645         aTextureVecNew.SetValue (aTexIndex, Handle(Graphic3d_Texture2Dmanual)());
4646       }
4647
4648       if (aTextureVecNew.Value (aTexIndex))
4649       {
4650         aTextureVecNew.ChangeValue(aTexIndex)->GetParams()->SetTextureUnit((Graphic3d_TextureUnit)aTexIndex);
4651       }
4652     }
4653     else
4654     {
4655       Message::SendFail() << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'";
4656       return 1;
4657     }
4658   }
4659
4660   if (toSetImage)
4661   {
4662     // check if new image set is equal to already set one
4663     Standard_Integer aNbChanged = 0;
4664     Handle(Graphic3d_TextureSet) aTextureSetNew;
4665     if (!aTextureVecNew.IsEmpty())
4666     {
4667       aNbChanged = aTextureVecNew.Size();
4668       aTextureSetNew = new Graphic3d_TextureSet (aTextureVecNew.Size());
4669       for (Standard_Integer aTexIter = 0; aTexIter < aTextureSetNew->Size(); ++aTexIter)
4670       {
4671         Handle(Graphic3d_Texture2Dmanual)& aTextureNew = aTextureVecNew.ChangeValue (aTexIter);
4672         Handle(Graphic3d_TextureRoot) aTextureOld;
4673         if (!aTextureSetOld.IsNull()
4674           && aTexIter < aTextureSetOld->Size())
4675         {
4676           aTextureOld = aTextureSetOld->Value (aTexIter);
4677         }
4678
4679         if (!aTextureOld.IsNull()
4680          && !aTextureNew.IsNull())
4681         {
4682           *aTextureNew->GetParams() = *aTextureOld->GetParams();
4683           if (Handle(Graphic3d_Texture2Dmanual) anOldManualTex = Handle(Graphic3d_Texture2Dmanual)::DownCast (aTextureOld))
4684           {
4685             TCollection_AsciiString aFilePathOld, aFilePathNew;
4686             aTextureOld->Path().SystemName (aFilePathOld);
4687             aTextureNew->Path().SystemName (aFilePathNew);
4688             if (aTextureNew->Name() == anOldManualTex->Name()
4689              && aFilePathOld == aFilePathNew
4690              && (!aFilePathNew.IsEmpty() || aTextureNew->Name() != Graphic3d_NOT_2D_UNKNOWN))
4691             {
4692               --aNbChanged;
4693               aTextureNew = anOldManualTex;
4694             }
4695           }
4696         }
4697         aTextureSetNew->SetValue (aTexIter, aTextureNew);
4698       }
4699     }
4700     if (aNbChanged == 0
4701      && ((aTextureSetOld.IsNull() && aTextureSetNew.IsNull())
4702       || (aTextureSetOld->Size() == aTextureSetNew->Size())))
4703     {
4704       aTextureSetNew = aTextureSetOld;
4705     }
4706
4707     if (aTexturedIO->Attributes()->SetupOwnShadingAspect (aCtx->DefaultDrawer())
4708      && aTexturedShape.IsNull())
4709     {
4710       aTexturedIO->SetToUpdate();
4711     }
4712
4713     toComputeUV = !aTextureSetNew.IsNull() && aTextureSetOld.IsNull();
4714     aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOn (!aTextureSetNew.IsNull());
4715     aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureSet (aTextureSetNew);
4716     aTextureSetOld.Nullify();
4717   }
4718
4719   if (toSetDefaults)
4720   {
4721     if (toModulate != -1)
4722     {
4723       toModulate = 1;
4724     }
4725     if (!toSetFilter)
4726     {
4727       toSetFilter = true;
4728       aFilter     = Graphic3d_TOTF_BILINEAR;
4729     }
4730     if (!toSetAniso)
4731     {
4732       toSetAniso    = true;
4733       anAnisoFilter = Graphic3d_LOTA_OFF;
4734     }
4735     if (!toSetTrsfAngle)
4736     {
4737       toSetTrsfAngle = true;
4738       aTrsfRotAngle  = 0.0f;
4739     }
4740     if (!toSetTrsfTrans)
4741     {
4742       toSetTrsfTrans = true;
4743       aTrsfTrans = Graphic3d_Vec2 (0.0f, 0.0f);
4744     }
4745     if (!toSetTrsfScale)
4746     {
4747       toSetTrsfScale = true;
4748       aTrsfScale = Graphic3d_Vec2 (1.0f, 1.0f);
4749     }
4750   }
4751
4752   if (aCommandName == "vtexture"
4753    && theArgsNb == 2)
4754   {
4755     if (!aTextureSetOld.IsNull())
4756     {
4757       //toComputeUV = true; // we can keep UV vertex attributes
4758       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOff();
4759       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureSet (Handle(Graphic3d_TextureSet)());
4760       aTextureSetOld.Nullify();
4761     }
4762   }
4763
4764   if (aTexturedIO->Attributes()->HasOwnShadingAspect()
4765   && !aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap().IsNull())
4766   {
4767     if (toModulate != -1)
4768     {
4769       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetModulate (toModulate == 1);
4770     }
4771     if (toSetTrsfAngle)
4772     {
4773       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetRotation (aTrsfRotAngle); // takes degrees
4774     }
4775     if (toSetTrsfTrans)
4776     {
4777       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetTranslation (aTrsfTrans);
4778     }
4779     if (toSetTrsfScale)
4780     {
4781       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetScale (aTrsfScale);
4782     }
4783     if (toSetFilter)
4784     {
4785       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetFilter (aFilter);
4786     }
4787     if (toSetAniso)
4788     {
4789       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetAnisoFilter (anAnisoFilter);
4790     }
4791   }
4792
4793   // set default values if requested
4794   if (!toSetGenRepeat
4795    && (aCommandName == "vtexrepeat"
4796     || toSetDefaults))
4797   {
4798     if (!aTexturedShape.IsNull())
4799     {
4800       aTexturedShape->SetTextureRepeatUV (gp_Pnt2d (1.0, 1.0));
4801     }
4802     toSetGenRepeat = true;
4803   }
4804   if (!toSetGenOrigin
4805    && (aCommandName == "vtexorigin"
4806     || toSetDefaults))
4807   {
4808     if (!aTexturedShape.IsNull())
4809     {
4810       aTexturedShape->SetTextureOriginUV (gp_Pnt2d (0.0, 0.0));
4811     }
4812     toSetGenOrigin = true;
4813   }
4814   if (!toSetGenScale
4815    && (aCommandName == "vtexscale"
4816     || toSetDefaults))
4817   {
4818     if (!aTexturedShape.IsNull())
4819     {
4820       aTexturedShape->SetTextureScaleUV  (gp_Pnt2d (1.0, 1.0));
4821     }
4822     toSetGenScale = true;
4823   }
4824
4825   if (toSetGenRepeat || toSetGenOrigin || toSetGenScale || toComputeUV)
4826   {
4827     if (!aTexturedShape.IsNull())
4828     {
4829       aTexturedShape->SetToUpdate (AIS_Shaded);
4830       if (toSetImage)
4831       {
4832         if ((aTexturedIO->HasDisplayMode() && aTexturedIO->DisplayMode() != AIS_Shaded)
4833          || aCtx->DisplayMode() != AIS_Shaded)
4834         {
4835           aCtx->SetDisplayMode (aTexturedIO, AIS_Shaded, false);
4836         }
4837       }
4838     }
4839   }
4840   aCtx->Display (aTexturedIO, false);
4841   aTexturedIO->SynchronizeAspects();
4842   return 0;
4843 }
4844
4845 //! Auxiliary method to parse transformation persistence flags
4846 inline Standard_Boolean parseTrsfPersFlag (const TCollection_AsciiString& theFlagString,
4847                                            Graphic3d_TransModeFlags&      theFlags)
4848 {
4849   if (theFlagString == "zoom")
4850   {
4851     theFlags = Graphic3d_TMF_ZoomPers;
4852   }
4853   else if (theFlagString == "rotate")
4854   {
4855     theFlags = Graphic3d_TMF_RotatePers;
4856   }
4857   else if (theFlagString == "zoomrotate")
4858   {
4859     theFlags = Graphic3d_TMF_ZoomRotatePers;
4860   }
4861   else if (theFlagString == "trihedron"
4862         || theFlagString == "triedron")
4863   {
4864     theFlags = Graphic3d_TMF_TriedronPers;
4865   }
4866   else if (theFlagString == "none")
4867   {
4868     theFlags = Graphic3d_TMF_None;
4869   }
4870   else
4871   {
4872     return Standard_False;
4873   }
4874
4875   return Standard_True;
4876 }
4877
4878 //! Auxiliary method to parse transformation persistence flags
4879 inline Standard_Boolean parseTrsfPersCorner (const TCollection_AsciiString& theString,
4880                                              Aspect_TypeOfTriedronPosition& theCorner)
4881 {
4882   TCollection_AsciiString aString (theString);
4883   aString.LowerCase();
4884   if (aString == "center")
4885   {
4886     theCorner = Aspect_TOTP_CENTER;
4887   }
4888   else if (aString == "top"
4889         || aString == "upper")
4890   {
4891     theCorner = Aspect_TOTP_TOP;
4892   }
4893   else if (aString == "bottom"
4894         || aString == "lower")
4895   {
4896     theCorner = Aspect_TOTP_BOTTOM;
4897   }
4898   else if (aString == "left")
4899   {
4900     theCorner = Aspect_TOTP_LEFT;
4901   }
4902   else if (aString == "right")
4903   {
4904     theCorner = Aspect_TOTP_RIGHT;
4905   }
4906   else if (aString == "topleft"
4907         || aString == "leftupper"
4908         || aString == "upperleft")
4909   {
4910     theCorner = Aspect_TOTP_LEFT_UPPER;
4911   }
4912   else if (aString == "bottomleft"
4913         || aString == "leftlower"
4914         || aString == "lowerleft")
4915   {
4916     theCorner = Aspect_TOTP_LEFT_LOWER;
4917   }
4918   else if (aString == "topright"
4919         || aString == "rightupper"
4920         || aString == "upperright")
4921   {
4922     theCorner = Aspect_TOTP_RIGHT_UPPER;
4923   }
4924   else if (aString == "bottomright"
4925         || aString == "lowerright"
4926         || aString == "rightlower")
4927   {
4928     theCorner = Aspect_TOTP_RIGHT_LOWER;
4929   }
4930   else
4931   {
4932     return Standard_False;
4933   }
4934
4935   return Standard_True;
4936 }
4937
4938 //==============================================================================
4939 //function : VDisplay2
4940 //author   : ege
4941 //purpose  : Display an object from its name
4942 //==============================================================================
4943 static int VDisplay2 (Draw_Interpretor& theDI,
4944                       Standard_Integer  theArgNb,
4945                       const char**      theArgVec)
4946 {
4947   if (theArgNb < 2)
4948   {
4949     Message::SendFail ("Syntax error: wrong number of arguments.");
4950     return 1;
4951   }
4952   if (theArgNb == 2
4953    && TCollection_AsciiString (theArgVec[1]) == "*")
4954   {
4955     // alias
4956     return VDisplayAll (theDI, 1, theArgVec);
4957   }
4958
4959   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
4960   if (aCtx.IsNull())
4961   {
4962     ViewerTest::ViewerInit();
4963     aCtx = ViewerTest::GetAISContext();
4964   }
4965
4966   // Parse input arguments
4967   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
4968   Standard_Integer   isMutable      = -1;
4969   Graphic3d_ZLayerId aZLayer        = Graphic3d_ZLayerId_UNKNOWN;
4970   Standard_Boolean   toReDisplay    = Standard_False;
4971   Standard_Integer   isSelectable   = -1;
4972   Standard_Integer   anObjDispMode  = -2;
4973   Standard_Integer   anObjHighMode  = -2;
4974   Standard_Boolean   toSetTrsfPers  = Standard_False;
4975   Handle(Graphic3d_TransformPers) aTrsfPers;
4976   TColStd_SequenceOfAsciiString aNamesOfDisplayIO;
4977   AIS_DisplayStatus aDispStatus = AIS_DS_None;
4978   Standard_Integer toDisplayInView = Standard_False;
4979   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4980   {
4981     const TCollection_AsciiString aName     = theArgVec[anArgIter];
4982     TCollection_AsciiString       aNameCase = aName;
4983     aNameCase.LowerCase();
4984     if (anUpdateTool.parseRedrawMode (aName))
4985     {
4986       continue;
4987     }
4988     else if (aNameCase == "-mutable")
4989     {
4990       isMutable = 1;
4991     }
4992     else if (aNameCase == "-neutral")
4993     {
4994       aDispStatus = AIS_DS_Displayed;
4995     }
4996     else if (aNameCase == "-immediate"
4997           || aNameCase == "-top")
4998     {
4999       aZLayer = Graphic3d_ZLayerId_Top;
5000     }
5001     else if (aNameCase == "-topmost")
5002     {
5003       aZLayer = Graphic3d_ZLayerId_Topmost;
5004     }
5005     else if (aNameCase == "-osd"
5006           || aNameCase == "-toposd"
5007           || aNameCase == "-overlay")
5008     {
5009       aZLayer = Graphic3d_ZLayerId_TopOSD;
5010     }
5011     else if (aNameCase == "-botosd"
5012           || aNameCase == "-underlay")
5013     {
5014       aZLayer = Graphic3d_ZLayerId_BotOSD;
5015     }
5016     else if (aNameCase == "-select"
5017           || aNameCase == "-selectable")
5018     {
5019       isSelectable = 1;
5020     }
5021     else if (aNameCase == "-noselect"
5022           || aNameCase == "-noselection")
5023     {
5024       isSelectable = 0;
5025     }
5026     else if (aNameCase == "-dispmode"
5027           || aNameCase == "-displaymode")
5028     {
5029       if (++anArgIter >= theArgNb)
5030       {
5031         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
5032         return 1;
5033       }
5034
5035       anObjDispMode = Draw::Atoi (theArgVec [anArgIter]);
5036     }
5037     else if (aNameCase == "-himode"
5038           || aNameCase == "-highmode"
5039           || aNameCase == "-highlightmode")
5040     {
5041       if (++anArgIter >= theArgNb)
5042       {
5043         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
5044         return 1;
5045       }
5046
5047       anObjHighMode = Draw::Atoi (theArgVec [anArgIter]);
5048     }
5049     else if (aNameCase == "-3d")
5050     {
5051       toSetTrsfPers  = Standard_True;
5052       aTrsfPers.Nullify();
5053     }
5054     else if (aNameCase == "-2d"
5055           || aNameCase == "-trihedron"
5056           || aNameCase == "-triedron")
5057     {
5058       toSetTrsfPers  = Standard_True;
5059       aTrsfPers = new Graphic3d_TransformPers (aNameCase == "-2d" ? Graphic3d_TMF_2d : Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER);
5060
5061       if (anArgIter + 1 < theArgNb)
5062       {
5063         Aspect_TypeOfTriedronPosition aCorner = Aspect_TOTP_CENTER;
5064         if (parseTrsfPersCorner (theArgVec[anArgIter + 1], aCorner))
5065         {
5066           ++anArgIter;
5067           aTrsfPers->SetCorner2d (aCorner);
5068
5069           if (anArgIter + 2 < theArgNb)
5070           {
5071             TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
5072             TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
5073             if (anX.IsIntegerValue()
5074              && anY.IsIntegerValue())
5075             {
5076               anArgIter += 2;
5077               aTrsfPers->SetOffset2d (Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue()));
5078             }
5079           }
5080         }
5081       }
5082     }
5083     else if (aNameCase == "-trsfpers"
5084           || aNameCase == "-pers")
5085     {
5086       if (++anArgIter >= theArgNb
5087        || !aTrsfPers.IsNull())
5088       {
5089         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
5090         return 1;
5091       }
5092
5093       toSetTrsfPers  = Standard_True;
5094       Graphic3d_TransModeFlags aTrsfPersFlags = Graphic3d_TMF_None;
5095       TCollection_AsciiString aPersFlags (theArgVec [anArgIter]);
5096       aPersFlags.LowerCase();
5097       if (!parseTrsfPersFlag (aPersFlags, aTrsfPersFlags))
5098       {
5099         Message::SendFail() << "Error: wrong transform persistence flags " << theArgVec [anArgIter] << ".";
5100         return 1;
5101       }
5102
5103       if (aTrsfPersFlags == Graphic3d_TMF_TriedronPers)
5104       {
5105         aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER);
5106       }
5107       else if (aTrsfPersFlags != Graphic3d_TMF_None)
5108       {
5109         aTrsfPers = new Graphic3d_TransformPers (aTrsfPersFlags, gp_Pnt());
5110       }
5111     }
5112     else if (aNameCase == "-trsfperspos"
5113           || aNameCase == "-perspos")
5114     {
5115       if (anArgIter + 2 >= theArgNb
5116        || aTrsfPers.IsNull())
5117       {
5118         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
5119         return 1;
5120       }
5121
5122       TCollection_AsciiString aX (theArgVec[++anArgIter]);
5123       TCollection_AsciiString aY (theArgVec[++anArgIter]);
5124       TCollection_AsciiString aZ = "0";
5125       if (!aX.IsRealValue()
5126        || !aY.IsRealValue())
5127       {
5128         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
5129         return 1;
5130       }
5131       if (anArgIter + 1 < theArgNb)
5132       {
5133         TCollection_AsciiString aTemp = theArgVec[anArgIter + 1];
5134         if (aTemp.IsRealValue())
5135         {
5136           aZ = aTemp;
5137           ++anArgIter;
5138         }
5139       }
5140
5141       const gp_Pnt aPnt (aX.RealValue(), aY.RealValue(), aZ.RealValue());
5142       if (aTrsfPers->IsZoomOrRotate())
5143       {
5144         aTrsfPers->SetAnchorPoint (aPnt);
5145       }
5146       else if (aTrsfPers->IsTrihedronOr2d())
5147       {
5148         aTrsfPers = Graphic3d_TransformPers::FromDeprecatedParams (aTrsfPers->Mode(), aPnt);
5149       }
5150     }
5151     else if (aNameCase == "-layer"
5152           || aNameCase == "-zlayer")
5153     {
5154       ++anArgIter;
5155       if (anArgIter >= theArgNb
5156       || !ViewerTest::ParseZLayer (theArgVec[anArgIter], aZLayer)
5157       ||  aZLayer == Graphic3d_ZLayerId_UNKNOWN)
5158       {
5159         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
5160         return 1;
5161       }
5162     }
5163     else if (aNameCase == "-view"
5164           || aNameCase == "-inview")
5165     {
5166       toDisplayInView = Standard_True;
5167     }
5168     else if (aNameCase == "-redisplay")
5169     {
5170       toReDisplay = Standard_True;
5171     }
5172     else if (aNameCase == "-erased"
5173           || aNameCase == "-load")
5174     {
5175       aDispStatus = AIS_DS_Erased;
5176     }
5177     else
5178     {
5179       aNamesOfDisplayIO.Append (aName);
5180     }
5181   }
5182
5183   if (aNamesOfDisplayIO.IsEmpty())
5184   {
5185     Message::SendFail ("Syntax error: wrong number of arguments.");
5186     return 1;
5187   }
5188
5189   // Display interactive objects
5190   for (Standard_Integer anIter = 1; anIter <= aNamesOfDisplayIO.Length(); ++anIter)
5191   {
5192     const TCollection_AsciiString& aName = aNamesOfDisplayIO.Value (anIter);
5193     Handle(AIS_InteractiveObject) aShape;
5194     if (!GetMapOfAIS().Find2 (aName, aShape))
5195     {
5196       // create the AIS_Shape from a name
5197       TopoDS_Shape aDrawShape = DBRep::GetExisting (aName);
5198       if (!aDrawShape.IsNull())
5199       {
5200         aShape = new AIS_Shape (aDrawShape);
5201         if (isMutable != -1)
5202         {
5203           aShape->SetMutable (isMutable == 1);
5204         }
5205         if (aZLayer != Graphic3d_ZLayerId_UNKNOWN)
5206         {
5207           aShape->SetZLayer (aZLayer);
5208         }
5209         if (toSetTrsfPers)
5210         {
5211           aCtx->SetTransformPersistence (aShape, aTrsfPers);
5212         }
5213         if (anObjDispMode != -2)
5214         {
5215           if (anObjDispMode == -1)
5216           {
5217             aShape->UnsetDisplayMode();
5218           }
5219           if (!aShape->AcceptDisplayMode (anObjDispMode))
5220           {
5221             Message::SendFail() << "Syntax error: " << aShape->DynamicType()->Name() << " rejects " << anObjDispMode << " display mode";
5222             return 1;
5223           }
5224           else
5225           {
5226             aShape->SetDisplayMode (anObjDispMode);
5227           }
5228         }
5229         if (anObjHighMode != -2)
5230         {
5231           if (anObjHighMode != -1
5232           && !aShape->AcceptDisplayMode (anObjHighMode))
5233           {
5234             Message::SendFail() << "Syntax error: " << aShape->DynamicType()->Name() << " rejects " << anObjHighMode << " display mode";
5235             return 1;
5236           }
5237           aShape->SetHilightMode (anObjHighMode);
5238         }
5239
5240         GetMapOfAIS().Bind (aShape, aName);
5241         Standard_Integer aDispMode = aShape->HasDisplayMode()
5242                                    ? aShape->DisplayMode()
5243                                    : (aShape->AcceptDisplayMode (aCtx->DisplayMode())
5244                                     ? aCtx->DisplayMode()
5245                                     : 0);
5246         Standard_Integer aSelMode = -1;
5247         if (isSelectable ==  1 || (isSelectable == -1 && aCtx->GetAutoActivateSelection()))
5248         {
5249           aSelMode = aShape->GlobalSelectionMode();
5250         }
5251
5252         aCtx->Display (aShape, aDispMode, aSelMode, Standard_False, aDispStatus);
5253         if (toDisplayInView)
5254         {
5255           for (V3d_ListOfViewIterator aViewIter (aCtx->CurrentViewer()->DefinedViewIterator()); aViewIter.More(); aViewIter.Next())
5256           {
5257             aCtx->SetViewAffinity (aShape, aViewIter.Value(), Standard_False);
5258           }
5259           aCtx->SetViewAffinity (aShape, ViewerTest::CurrentView(), Standard_True);
5260         }
5261       }
5262       else
5263       {
5264         Message::SendFail() << "Error: object with name '" << aName << "' does not exist!";
5265       }
5266       continue;
5267     }
5268
5269     if (isMutable != -1)
5270     {
5271       aShape->SetMutable (isMutable == 1);
5272     }
5273     if (aZLayer != Graphic3d_ZLayerId_UNKNOWN)
5274     {
5275       aShape->SetZLayer (aZLayer);
5276     }
5277     if (toSetTrsfPers)
5278     {
5279       aCtx->SetTransformPersistence (aShape, aTrsfPers);
5280     }
5281     if (anObjDispMode != -2)
5282     {
5283       aShape->SetDisplayMode (anObjDispMode);
5284     }
5285     if (anObjHighMode != -2)
5286     {
5287       aShape->SetHilightMode (anObjHighMode);
5288     }
5289     Standard_Integer aDispMode = aShape->HasDisplayMode()
5290                                 ? aShape->DisplayMode()
5291                                 : (aShape->AcceptDisplayMode (aCtx->DisplayMode())
5292                                 ? aCtx->DisplayMode()
5293                                 : 0);
5294     Standard_Integer aSelMode = -1;
5295     if (isSelectable ==  1 || (isSelectable == -1 && aCtx->GetAutoActivateSelection()))
5296     {
5297       aSelMode = aShape->GlobalSelectionMode();
5298     }
5299
5300     if (aShape->Type() == AIS_KOI_Datum)
5301     {
5302       aCtx->Display (aShape, Standard_False);
5303     }
5304     else
5305     {
5306       theDI << "Display " << aName << "\n";
5307
5308       // update the Shape in the AIS_Shape
5309       TopoDS_Shape      aNewShape = DBRep::GetExisting (aName);
5310       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(aShape);
5311       if (!aShapePrs.IsNull())
5312       {
5313         if (!aShapePrs->Shape().IsEqual (aNewShape))
5314         {
5315           toReDisplay = Standard_True;
5316         }
5317         aShapePrs->Set (aNewShape);
5318       }
5319       if (toReDisplay)
5320       {
5321         aCtx->Redisplay (aShape, Standard_False);
5322       }
5323
5324       if (aSelMode == -1)
5325       {
5326         aCtx->Erase (aShape, Standard_False);
5327       }
5328       aCtx->Display (aShape, aDispMode, aSelMode, Standard_False, aDispStatus);
5329       if (toDisplayInView)
5330       {
5331         aCtx->SetViewAffinity (aShape, ViewerTest::CurrentView(), Standard_True);
5332       }
5333     }
5334   }
5335
5336   return 0;
5337 }
5338
5339 //=======================================================================
5340 //function : VNbDisplayed
5341 //purpose  : Returns number of displayed objects
5342 //=======================================================================
5343 static Standard_Integer VNbDisplayed (Draw_Interpretor& theDi,
5344                                       Standard_Integer theArgsNb,
5345                                       const char** theArgVec)
5346 {
5347   if(theArgsNb != 1)
5348   {
5349     theDi << "Usage : " << theArgVec[0] << "\n";
5350     return 1;
5351   }
5352
5353   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5354   if (aContextAIS.IsNull())
5355   {
5356     Message::SendFail ("Syntax error: AIS context is not available.");
5357     return 1;
5358   }
5359
5360   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5361   if(aContext.IsNull())
5362   {
5363     theDi << "use 'vinit' command before " << theArgVec[0] << "\n";
5364     return 1;
5365   }
5366
5367   AIS_ListOfInteractive aListOfIO;
5368   aContextAIS->DisplayedObjects (aListOfIO);
5369
5370   theDi << aListOfIO.Extent() << "\n";
5371   return 0;
5372 }
5373
5374 //===============================================================================================
5375 //function : VUpdate
5376 //purpose  :
5377 //===============================================================================================
5378 static int VUpdate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
5379 {
5380   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5381   if (aContextAIS.IsNull())
5382   {
5383     Message::SendFail ("Syntax error: AIS context is not available.");
5384     return 1;
5385   }
5386
5387   if (theArgsNb < 2)
5388   {
5389     Message::SendFail ("Syntax error: insufficient arguments. Type help for more information.");
5390     return 1;
5391   }
5392
5393   AIS_ListOfInteractive aListOfIO;
5394   for (int anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
5395   {
5396     TCollection_AsciiString aName = TCollection_AsciiString (theArgVec[anArgIt]);
5397
5398     Handle(AIS_InteractiveObject) anAISObj;
5399     GetMapOfAIS().Find2 (aName, anAISObj);
5400     if (anAISObj.IsNull())
5401     {
5402       Message::SendFail() << theArgVec[0] << ": no AIS interactive object named \"" << aName << "\".";
5403       return 1;
5404     }
5405
5406     aListOfIO.Append (anAISObj);
5407   }
5408
5409   AIS_ListIteratorOfListOfInteractive anIOIt (aListOfIO);
5410   for (; anIOIt.More(); anIOIt.Next())
5411   {
5412     aContextAIS->Update (anIOIt.Value(), Standard_False);
5413   }
5414
5415   aContextAIS->UpdateCurrentViewer();
5416
5417   return 0;
5418 }
5419
5420 //==============================================================================
5421 //function : VShading
5422 //purpose  : Sharpen or roughten the quality of the shading
5423 //Draw arg : vshading ShapeName 0.1->0.00001  1 deg-> 30 deg
5424 //==============================================================================
5425 static int VShading(Draw_Interpretor& ,Standard_Integer argc, const char** argv)
5426 {
5427   Standard_Real    myDevCoef;
5428   Handle(AIS_InteractiveObject) TheAisIO;
5429
5430   // Verifications
5431   const Standard_Boolean HaveToSet = (strcasecmp(argv[0],"vsetshading") == 0);
5432   if (argc < 3) {
5433     myDevCoef  = 0.0008;
5434   } else {
5435     myDevCoef  =Draw::Atof(argv[2]);
5436   }
5437
5438   TCollection_AsciiString name=argv[1];
5439   GetMapOfAIS().Find2(name, TheAisIO);
5440   if (TheAisIO.IsNull())
5441   {
5442     TopoDS_Shape aDrawShape = DBRep::GetExisting (name);
5443     if (!aDrawShape.IsNull())
5444     {
5445       TheAisIO = new AIS_Shape (aDrawShape);
5446     }
5447   }
5448
5449   if (HaveToSet)
5450     TheAISContext()->SetDeviationCoefficient(TheAisIO,myDevCoef,Standard_True);
5451   else
5452     TheAISContext()->SetDeviationCoefficient(TheAisIO,0.0008,Standard_True);
5453
5454   TheAISContext()->Redisplay (TheAisIO, Standard_True);
5455   return 0;
5456 }
5457
5458 //! Auxiliary method to print Interactive Object information
5459 static void objInfo (const NCollection_Map<Handle(AIS_InteractiveObject)>& theDetected,
5460                      const Handle(AIS_InteractiveObject)&                  theObj,
5461                      Draw_Interpretor&                                     theDI)
5462 {
5463   if (theObj.IsNull())
5464   {
5465     theDI << "NULL presentation\n";
5466     return;
5467   }
5468
5469   theDI << (TheAISContext()->IsDisplayed (theObj) ? "Displayed"  : "Hidden   ")
5470         << (TheAISContext()->IsSelected  (theObj) ? " Selected" : "         ")
5471         << (theDetected.Contains (theObj)         ? " Detected" : "         ")
5472         << " Type: ";
5473   if (theObj->Type() == AIS_KOI_Datum)
5474   {
5475     // AIS_Datum
5476     if      (theObj->Signature() == 3) { theDI << " AIS_Trihedron"; }
5477     else if (theObj->Signature() == 2) { theDI << " AIS_Axis"; }
5478     else if (theObj->Signature() == 6) { theDI << " AIS_Circle"; }
5479     else if (theObj->Signature() == 5) { theDI << " AIS_Line"; }
5480     else if (theObj->Signature() == 7) { theDI << " AIS_Plane"; }
5481     else if (theObj->Signature() == 1) { theDI << " AIS_Point"; }
5482     else if (theObj->Signature() == 4) { theDI << " AIS_PlaneTrihedron"; }
5483   }
5484   // AIS_Shape
5485   else if (theObj->Type()      == AIS_KOI_Shape
5486         && theObj->Signature() == 0)
5487   {
5488     theDI << " AIS_Shape";
5489   }
5490   else if (theObj->Type() == AIS_KOI_Relation)
5491   {
5492     // PrsDim_Dimention and AIS_Relation
5493     Handle(PrsDim_Relation) aRelation = Handle(PrsDim_Relation)::DownCast (theObj);
5494     switch (aRelation->KindOfDimension())
5495     {
5496       case PrsDim_KOD_PLANEANGLE:     theDI << " PrsDim_AngleDimension"; break;
5497       case PrsDim_KOD_LENGTH:         theDI << " PrsDim_Chamf2/3dDimension/PrsDim_LengthDimension"; break;
5498       case PrsDim_KOD_DIAMETER:       theDI << " PrsDim_DiameterDimension"; break;
5499       case PrsDim_KOD_ELLIPSERADIUS:  theDI << " PrsDim_EllipseRadiusDimension"; break;
5500       //case PrsDim_KOD_FILLETRADIUS:   theDI << " PrsDim_FilletRadiusDimension "; break;
5501       case PrsDim_KOD_OFFSET:         theDI << " PrsDim_OffsetDimension"; break;
5502       case PrsDim_KOD_RADIUS:         theDI << " PrsDim_RadiusDimension"; break;
5503       default:                     theDI << " UNKNOWN dimension"; break;
5504     }
5505   }
5506   else
5507   {
5508     theDI << " UserPrs";
5509   }
5510   theDI << " (" << theObj->DynamicType()->Name() << ")";
5511 }
5512
5513 //! Print information about locally selected sub-shapes
5514 template <typename T>
5515 static void printLocalSelectionInfo (const T& theContext, Draw_Interpretor& theDI)
5516 {
5517   const Standard_Boolean isGlobalCtx = (theContext->DynamicType() == STANDARD_TYPE(AIS_InteractiveContext));
5518   TCollection_AsciiString aPrevName;
5519   for (theContext->InitSelected(); theContext->MoreSelected(); theContext->NextSelected())
5520   {
5521     const Handle(AIS_Shape) aShapeIO = Handle(AIS_Shape)::DownCast (theContext->SelectedInteractive());
5522     const Handle(SelectMgr_EntityOwner) anOwner = theContext->SelectedOwner();
5523     if (aShapeIO.IsNull() || anOwner.IsNull())
5524       continue;
5525     if (isGlobalCtx)
5526     {
5527       if (anOwner == aShapeIO->GlobalSelOwner())
5528         continue;
5529     }
5530     const TopoDS_Shape      aSubShape = theContext->SelectedShape();
5531     if (aSubShape.IsNull()
5532       || aShapeIO.IsNull()
5533       || !GetMapOfAIS().IsBound1 (aShapeIO))
5534     {
5535       continue;
5536     }
5537
5538     const TCollection_AsciiString aParentName = GetMapOfAIS().Find1 (aShapeIO);
5539     TopTools_MapOfShape aFilter;
5540     Standard_Integer    aNumber = 0;
5541     const TopoDS_Shape  aShape  = aShapeIO->Shape();
5542     for (TopExp_Explorer anIter (aShape, aSubShape.ShapeType());
5543          anIter.More(); anIter.Next())
5544     {
5545       if (!aFilter.Add (anIter.Current()))
5546       {
5547         continue; // filter duplicates
5548       }
5549
5550       ++aNumber;
5551       if (!anIter.Current().IsSame (aSubShape))
5552       {
5553         continue;
5554       }
5555
5556       Standard_CString aShapeName = NULL;
5557       switch (aSubShape.ShapeType())
5558       {
5559         case TopAbs_COMPOUND:  aShapeName = " Compound"; break;
5560         case TopAbs_COMPSOLID: aShapeName = "CompSolid"; break;
5561         case TopAbs_SOLID:     aShapeName = "    Solid"; break;
5562         case TopAbs_SHELL:     aShapeName = "    Shell"; break;
5563         case TopAbs_FACE:      aShapeName = "     Face"; break;
5564         case TopAbs_WIRE:      aShapeName = "     Wire"; break;
5565         case TopAbs_EDGE:      aShapeName = "     Edge"; break;
5566         case TopAbs_VERTEX:    aShapeName = "   Vertex"; break;
5567         default:
5568         case TopAbs_SHAPE:     aShapeName = "    Shape"; break;
5569       }
5570
5571       if (aParentName != aPrevName)
5572       {
5573         theDI << "Locally selected sub-shapes within " << aParentName << ":\n";
5574         aPrevName = aParentName;
5575       }
5576       theDI << "  " << aShapeName << " #" << aNumber << "\n";
5577       break;
5578     }
5579   }
5580 }
5581
5582 //==============================================================================
5583 //function : VState
5584 //purpose  :
5585 //==============================================================================
5586 static Standard_Integer VState (Draw_Interpretor& theDI,
5587                                 Standard_Integer  theArgNb,
5588                                 Standard_CString* theArgVec)
5589 {
5590   Handle(AIS_InteractiveContext) aCtx = TheAISContext();
5591   if (aCtx.IsNull())
5592   {
5593     Message::SendFail ("Error: No opened viewer!");
5594     return 1;
5595   }
5596
5597   Standard_Boolean toPrintEntities = Standard_False;
5598   Standard_Boolean toCheckSelected = Standard_False;
5599
5600   for (Standard_Integer anArgIdx = 1; anArgIdx < theArgNb; ++anArgIdx)
5601   {
5602     TCollection_AsciiString anOption (theArgVec[anArgIdx]);
5603     anOption.LowerCase();
5604     if (anOption == "-detectedentities"
5605       || anOption == "-entities")
5606     {
5607       toPrintEntities = Standard_True;
5608     }
5609     else if (anOption == "-hasselected")
5610     {
5611       toCheckSelected = Standard_True;
5612     }
5613   }
5614
5615   if (toCheckSelected)
5616   {
5617     aCtx->InitSelected();
5618     TCollection_AsciiString hasSelected (static_cast<Standard_Integer> (aCtx->HasSelectedShape()));
5619     theDI << "Check if context has selected shape: " << hasSelected << "\n";
5620
5621     return 0;
5622   }
5623
5624   if (toPrintEntities)
5625   {
5626     theDI << "Detected entities:\n";
5627     Handle(StdSelect_ViewerSelector3d) aSelector = aCtx->MainSelector();
5628
5629     SelectMgr_SelectingVolumeManager aMgr = aSelector->GetManager();
5630     for (Standard_Integer aPickIter = 1; aPickIter <= aSelector->NbPicked(); ++aPickIter)
5631     {
5632       const SelectMgr_SortCriterion&         aPickData = aSelector->PickedData (aPickIter);
5633       const Handle(Select3D_SensitiveEntity)& anEntity = aSelector->PickedEntity (aPickIter);
5634       const Handle(SelectMgr_EntityOwner)& anOwner = anEntity->OwnerId();
5635       Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
5636
5637       TCollection_AsciiString aName;
5638       GetMapOfAIS().Find1 (anObj, aName);
5639       aName.LeftJustify (20, ' ');
5640       char anInfoStr[512];
5641       if (aPickData.Normal.SquareModulus() > ShortRealEpsilon())
5642       {
5643         Sprintf (anInfoStr,
5644                  " Depth: %g Distance: %g Point: %g %g %g Normal: %g %g %g",
5645                  aPickData.Depth,
5646                  aPickData.MinDist,
5647                  aPickData.Point.X(), aPickData.Point.Y(), aPickData.Point.Z(),
5648                  aPickData.Normal.x(), aPickData.Normal.y(), aPickData.Normal.z());
5649       }
5650       else
5651       {
5652         Sprintf (anInfoStr,
5653                  " Depth: %g Distance: %g Point: %g %g %g",
5654                  aPickData.Depth,
5655                  aPickData.MinDist,
5656                  aPickData.Point.X(), aPickData.Point.Y(), aPickData.Point.Z());
5657       }
5658       theDI << "  " << aName
5659             << anInfoStr
5660             << " (" << anEntity->DynamicType()->Name() << ")"
5661             << "\n";
5662
5663       Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast (anOwner);
5664       if (!aBRepOwner.IsNull())
5665       {
5666         theDI << "                       Detected Shape: "
5667               << aBRepOwner->Shape().TShape()->DynamicType()->Name()
5668               << "\n";
5669       }
5670
5671       Handle(Select3D_SensitiveWire) aWire = Handle(Select3D_SensitiveWire)::DownCast (anEntity);
5672       if (!aWire.IsNull())
5673       {
5674         Handle(Select3D_SensitiveEntity) aSen = aWire->GetLastDetected();
5675         theDI << "                       Detected Child: "
5676               << aSen->DynamicType()->Name()
5677               << "\n";
5678       }
5679
5680       Handle(Select3D_SensitivePrimitiveArray) aPrimArr = Handle(Select3D_SensitivePrimitiveArray)::DownCast (anEntity);
5681       if (!aPrimArr.IsNull())
5682       {
5683         theDI << "                       Detected Element: "
5684               << aPrimArr->LastDetectedElement()
5685               << "\n";
5686       }
5687     }
5688     return 0;
5689   }
5690
5691   NCollection_Map<Handle(AIS_InteractiveObject)> aDetected;
5692   for (aCtx->InitDetected(); aCtx->MoreDetected(); aCtx->NextDetected())
5693   {
5694     aDetected.Add (Handle(AIS_InteractiveObject)::DownCast (aCtx->DetectedCurrentOwner()->Selectable()));
5695   }
5696
5697   const Standard_Boolean toShowAll = (theArgNb >= 2 && *theArgVec[1] == '*');
5698   if (theArgNb >= 2
5699    && !toShowAll)
5700   {
5701     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5702     {
5703       const TCollection_AsciiString anObjName = theArgVec[anArgIter];
5704       Handle(AIS_InteractiveObject) anObj;
5705       if (!GetMapOfAIS().Find2 (anObjName, anObj))
5706       {
5707         theDI << anObjName << " doesn't exist!\n";
5708         continue;
5709       }
5710
5711       TCollection_AsciiString aName = anObjName;
5712       aName.LeftJustify (20, ' ');
5713       theDI << "  " << aName << " ";
5714       objInfo (aDetected, anObj, theDI);
5715       theDI << "\n";
5716     }
5717     return 0;
5718   }
5719
5720   if (aCtx->NbSelected() > 0 && !toShowAll)
5721   {
5722     NCollection_DataMap<Handle(SelectMgr_EntityOwner), TopoDS_Shape> anOwnerShapeMap;
5723     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
5724     {
5725       const Handle(SelectMgr_EntityOwner) anOwner = aCtx->SelectedOwner();
5726       const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
5727       // handle whole object selection
5728       if (anOwner == anObj->GlobalSelOwner())
5729       {
5730         TCollection_AsciiString aName;
5731         GetMapOfAIS().Find1 (anObj, aName);
5732         aName.LeftJustify (20, ' ');
5733         theDI << aName << " ";
5734         objInfo (aDetected, anObj, theDI);
5735         theDI << "\n";
5736       }
5737     }
5738
5739     // process selected sub-shapes
5740     printLocalSelectionInfo (aCtx, theDI);
5741
5742     return 0;
5743   }
5744
5745   theDI << "Neutral-point state:\n";
5746   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
5747        anObjIter.More(); anObjIter.Next())
5748   {
5749     if (anObjIter.Key1().IsNull())
5750     {
5751       continue;
5752     }
5753
5754     TCollection_AsciiString aName = anObjIter.Key2();
5755     aName.LeftJustify (20, ' ');
5756     theDI << "  " << aName << " ";
5757     objInfo (aDetected, anObjIter.Key1(), theDI);
5758     theDI << "\n";
5759   }
5760   printLocalSelectionInfo (aCtx, theDI);
5761   return 0;
5762 }
5763
5764 //=======================================================================
5765 //function : PickShape
5766 //purpose  : First Activate the rightmode + Put Filters to be able to
5767 //           pick objets that are of type <TheType>...
5768 //=======================================================================
5769
5770 TopoDS_Shape ViewerTest::PickShape (const TopAbs_ShapeEnum theShapeType,
5771                                     const Standard_Integer theMaxPick)
5772 {
5773   Handle(TopTools_HArray1OfShape) aResArray = new TopTools_HArray1OfShape (1, 1);
5774   PickShapes (theShapeType, aResArray, theMaxPick);
5775   return aResArray->First();
5776 }
5777
5778 //=======================================================================
5779 //function : PickShapes
5780 //purpose  :
5781 //=======================================================================
5782 Standard_Boolean ViewerTest::PickShapes (const TopAbs_ShapeEnum theShapeType,
5783                                          Handle(TopTools_HArray1OfShape)& theResArray,
5784                                          const Standard_Integer theMaxPick)
5785 {
5786   const Standard_Integer aNbToReach = theResArray->Length();
5787   if (aNbToReach > 1)
5788   {
5789     Message::SendWarning ("WARNING : Pick with Shift+ MB1 for Selection of more than 1 object");
5790   }
5791
5792   // step 1: prepare the data
5793   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
5794   aCtx->RemoveFilters();
5795   AIS_ListOfInteractive aDispObjects;
5796   aCtx->DisplayedObjects (aDispObjects);
5797   if (theShapeType == TopAbs_SHAPE)
5798   {
5799     aCtx->AddFilter (new AIS_TypeFilter (AIS_KOI_Shape));
5800   }
5801   else
5802   {
5803     aCtx->AddFilter (new StdSelect_ShapeTypeFilter (theShapeType));
5804   }
5805
5806   const Standard_Integer aSelMode = AIS_Shape::SelectionMode (theShapeType);
5807   for (AIS_ListOfInteractive::Iterator anObjIter (aDispObjects); anObjIter.More(); anObjIter.Next())
5808   {
5809     if (Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (anObjIter.Value()))
5810     {
5811       aCtx->SetSelectionModeActive (aShapePrs, aSelMode, true, AIS_SelectionModesConcurrency_Single);
5812     }
5813   }
5814
5815   // step 2 : wait for the selection...
5816   Standard_Integer aNbPickGood = 0, aNbPickFail = 0;
5817   Standard_Integer argccc = 5;
5818   const char *bufff[] = { "A", "B", "C", "D", "E" };
5819   const char **argvvv = (const char** )bufff;
5820   for (; aNbPickGood < aNbToReach && aNbPickFail <= theMaxPick; )
5821   {
5822     while (ViewerMainLoop (argccc, argvvv)) {}
5823     Standard_Integer aNbStored = aCtx->NbSelected();
5824     if (aNbStored != aNbPickGood)
5825     {
5826       aNbPickGood = aNbStored;
5827     }
5828     else
5829     {
5830       ++aNbPickFail;
5831     }
5832     Message::SendInfo() << "NbPicked =  " << aNbPickGood << " |  Nb Pick Fail :" << aNbPickFail;
5833   }
5834
5835   // step3 get result.
5836   if (aNbPickFail >= aNbToReach)
5837   {
5838     return Standard_False;
5839   }
5840
5841   Standard_Integer anIndex = theResArray->Lower();
5842   for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected(), ++anIndex)
5843   {
5844     if (aCtx->HasSelectedShape())
5845     {
5846       theResArray->SetValue (anIndex, aCtx->SelectedShape());
5847     }
5848     else
5849     {
5850       Handle(AIS_InteractiveObject) IO = aCtx->SelectedInteractive();
5851       theResArray->SetValue (anIndex, Handle(AIS_Shape)::DownCast (IO)->Shape());
5852     }
5853   }
5854
5855   aCtx->RemoveFilters();
5856   if (theShapeType != TopAbs_SHAPE)
5857   {
5858     for (AIS_ListOfInteractive::Iterator anObjIter (aDispObjects); anObjIter.More(); anObjIter.Next())
5859     {
5860       if (Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (anObjIter.Value()))
5861       {
5862         aCtx->SetSelectionModeActive (aShapePrs, aSelMode, true, AIS_SelectionModesConcurrency_Single);
5863       }
5864     }
5865   }
5866   return Standard_True;
5867 }
5868
5869 //=======================================================================
5870 //function : VPickShape
5871 //purpose  :
5872 //=======================================================================
5873 static int VPickShape( Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5874 {
5875   TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
5876   if (argc != 1)
5877   {
5878     TCollection_AsciiString aShapeArg (argv[1]);
5879     aShapeArg.LowerCase();
5880     aShapeType = TopAbs_COMPOUND;
5881     if      (aShapeArg == "v"
5882           || aShapeArg == "vertex") aShapeType = TopAbs_VERTEX;
5883     else if (aShapeArg == "e"
5884           || aShapeArg == "edge")   aShapeType = TopAbs_EDGE;
5885     else if (aShapeArg == "w"
5886           || aShapeArg == "wire")   aShapeType = TopAbs_WIRE;
5887     else if (aShapeArg == "f"
5888           || aShapeArg == "face")   aShapeType = TopAbs_FACE;
5889     else if (aShapeArg == "shape")  aShapeType = TopAbs_SHAPE;
5890     else if (aShapeArg == "shell")  aShapeType = TopAbs_SHELL;
5891     else if (aShapeArg == "solid")  aShapeType = TopAbs_SOLID;
5892     else
5893     {
5894       Message::SendFail() << "Syntax error at '" << argv[1] << "'";
5895       return 1;
5896     }
5897   }
5898
5899   static Standard_Integer THE_NB_SHAPES_OF_TYPE[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
5900   static const TCollection_AsciiString THE_NAME_TYPE[8] = {"COMPS","SOL","SHE","F","W","E","V","SHAP"};
5901
5902   const Standard_Integer aNbToPick = argc > 2 ? argc - 2 : 1;
5903   if (aNbToPick == 1)
5904   {
5905     TopoDS_Shape aPickedShape = ViewerTest::PickShape (aShapeType);
5906     if (aPickedShape.IsNull())
5907     {
5908       return 1;
5909     }
5910
5911     TCollection_AsciiString aName;
5912     if (argc > 2)
5913     {
5914       aName = argv[2];
5915     }
5916     else
5917     {
5918       const int aShapeIndex = ++THE_NB_SHAPES_OF_TYPE[Standard_Integer(aShapeType)];
5919       aName = TCollection_AsciiString ("Picked_") + THE_NAME_TYPE[Standard_Integer(aShapeType)] + "_" + aShapeIndex;
5920     }
5921
5922     DBRep::Set (aName.ToCString(), aPickedShape);
5923     Handle(AIS_Shape) aShapePrs = new AIS_Shape (aPickedShape);
5924     ViewerTest::Display (aName, aShapePrs, false, true);
5925     di << "Name of picked shape: " << aName <<"\n";
5926   }
5927   else
5928   {
5929     TCollection_AsciiString aName (argv[2]);
5930     aName.LowerCase();
5931     const Standard_Boolean isAutoNaming = aName == ".";
5932     Handle(TopTools_HArray1OfShape) aPickedArray = new TopTools_HArray1OfShape (1, aNbToPick);
5933     if (ViewerTest::PickShapes (aShapeType, aPickedArray))
5934     {
5935       for (Standard_Integer aPickedIter = aPickedArray->Lower(); aPickedIter <= aPickedArray->Upper(); ++aPickedIter)
5936       {
5937         TopoDS_Shape aPickedShape = aPickedArray->Value (aPickedIter);
5938         aName.Clear();
5939         if (!aPickedShape.IsNull()
5940          && isAutoNaming)
5941         {
5942           const int aShapeIndex = ++THE_NB_SHAPES_OF_TYPE[Standard_Integer(aShapeType)];
5943           aName = TCollection_AsciiString ("Picked_") + THE_NAME_TYPE[Standard_Integer(aShapeType)] + "_" + aShapeIndex;
5944         }
5945         else
5946         {
5947           aName = argv[1 + aPickedIter];
5948         }
5949
5950         DBRep::Set (aName.ToCString(), aPickedShape);
5951         Handle(AIS_Shape) aShapePrs = new AIS_Shape (aPickedShape);
5952         di << "Display of picked shape #" << aPickedIter << " - name: " << aName <<"\n";
5953         ViewerTest::Display (aName, aShapePrs, false, true);
5954       }
5955     }
5956   }
5957   TheAISContext()->UpdateCurrentViewer();
5958   return 0;
5959 }
5960
5961 //=======================================================================
5962 //function : VSelFilter
5963 //purpose  :
5964 //=======================================================================
5965 static int VSelFilter(Draw_Interpretor& , Standard_Integer theArgc,
5966                       const char** theArgv)
5967 {
5968   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5969   if (aContext.IsNull())
5970   {
5971     Message::SendFail ("Error: AIS context is not available.");
5972     return 1;
5973   }
5974
5975   for (Standard_Integer anArgIter = 1; anArgIter < theArgc; ++anArgIter)
5976   {
5977     TCollection_AsciiString anArg (theArgv[anArgIter]);
5978     anArg.LowerCase();
5979     if (anArg == "-clear")
5980     {
5981       aContext->RemoveFilters();
5982     }
5983     else if (anArg == "-type"
5984           && anArgIter + 1 < theArgc)
5985     {
5986       TCollection_AsciiString aVal (theArgv[++anArgIter]);
5987       TopAbs_ShapeEnum aShapeType = TopAbs_COMPOUND;
5988       if (!TopAbs::ShapeTypeFromString (aVal.ToCString(), aShapeType))
5989       {
5990         Message::SendFail() << "Syntax error: wrong command attribute value '" << aVal << "'";
5991         return 1;
5992       }
5993
5994       Handle(SelectMgr_Filter) aFilter;
5995       if (aShapeType == TopAbs_SHAPE)
5996       {
5997         aFilter = new AIS_TypeFilter (AIS_KOI_Shape);
5998       }
5999       else
6000       {
6001         aFilter = new StdSelect_ShapeTypeFilter (aShapeType);
6002       }
6003       aContext->AddFilter (aFilter);
6004     }
6005     else
6006     {
6007       Message::SendFail() << "Syntax error: unknown argument '" << theArgv[anArgIter] << "'";
6008       return 1;
6009     }
6010   }
6011   return 0;
6012 }
6013
6014 //=======================================================================
6015 //function : VPickSelected
6016 //purpose  :
6017 //=======================================================================
6018 static int VPickSelected (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgs)
6019 {
6020   static Standard_Integer aCount = 0;
6021   TCollection_AsciiString aName = "PickedShape_";
6022
6023   if (theArgNb > 1)
6024   {
6025     aName = theArgs[1];
6026   }
6027   else
6028   {
6029     aName = aName + aCount++ + "_";
6030   }
6031
6032   Standard_Integer anIdx = 0;
6033   for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected(), ++anIdx)
6034   {
6035     TopoDS_Shape aShape;
6036     if (TheAISContext()->HasSelectedShape())
6037     {
6038       aShape = TheAISContext()->SelectedShape();
6039     }
6040     else
6041     {
6042       Handle(AIS_InteractiveObject) IO = TheAISContext()->SelectedInteractive();
6043       aShape = Handle(AIS_Shape)::DownCast (IO)->Shape();
6044     }
6045
6046     TCollection_AsciiString aCurrentName = aName;
6047     if (anIdx > 0)
6048     {
6049       aCurrentName += anIdx;
6050     }
6051
6052     DBRep::Set ((aCurrentName).ToCString(), aShape);
6053
6054     Handle(AIS_Shape) aNewShape = new AIS_Shape (aShape);
6055     GetMapOfAIS().Bind (aNewShape, aCurrentName);
6056     TheAISContext()->Display (aNewShape, Standard_False);
6057   }
6058
6059   TheAISContext()->UpdateCurrentViewer();
6060
6061   return 0;
6062 }
6063
6064 //=======================================================================
6065 //function : list of known objects
6066 //purpose  :
6067 //=======================================================================
6068 static int VIOTypes( Draw_Interpretor& di, Standard_Integer , const char** )
6069 {
6070   //                             1234567890         12345678901234567         123456789
6071   TCollection_AsciiString Colum [3]={"Standard Types","Type Of Object","Signature"};
6072   TCollection_AsciiString BlankLine(64,'_');
6073   Standard_Integer i ;
6074
6075   di<<"/n"<<BlankLine.ToCString()<<"\n";
6076
6077   for( i =0;i<=2;i++)
6078     Colum[i].Center(20,' ');
6079   for(i=0;i<=2;i++)
6080     di<<"|"<<Colum[i].ToCString();
6081   di<<"|\n";
6082
6083   di<<BlankLine.ToCString()<<"\n";
6084
6085   //  TCollection_AsciiString thetypes[5]={"Datum","Shape","Object","Relation","None"};
6086   const char ** names = GetTypeNames();
6087
6088   TCollection_AsciiString curstring;
6089   TCollection_AsciiString curcolum[3];
6090
6091
6092   // les objets de type Datum..
6093   curcolum[1]+="Datum";
6094   for(i =0;i<=6;i++){
6095     curcolum[0].Clear();
6096     curcolum[0] += names[i];
6097
6098     curcolum[2].Clear();
6099     curcolum[2]+=TCollection_AsciiString(i+1);
6100
6101     for(Standard_Integer j =0;j<=2;j++){
6102       curcolum[j].Center(20,' ');
6103       di<<"|"<<curcolum[j].ToCString();
6104     }
6105     di<<"|\n";
6106   }
6107   di<<BlankLine.ToCString()<<"\n";
6108
6109   // les objets de type shape
6110   curcolum[1].Clear();
6111   curcolum[1]+="Shape";
6112   curcolum[1].Center(20,' ');
6113
6114   for(i=0;i<=2;i++){
6115     curcolum[0].Clear();
6116     curcolum[0] += names[7+i];
6117     curcolum[2].Clear();
6118     curcolum[2]+=TCollection_AsciiString(i);
6119
6120     for(Standard_Integer j =0;j<=2;j++){
6121       curcolum[j].Center(20,' ');
6122       di<<"|"<<curcolum[j].ToCString();
6123     }
6124     di<<"|\n";
6125   }
6126   di<<BlankLine.ToCString()<<"\n";
6127   // les IO de type objet...
6128   curcolum[1].Clear();
6129   curcolum[1]+="Object";
6130   curcolum[1].Center(20,' ');
6131   for(i=0;i<=1;i++){
6132     curcolum[0].Clear();
6133     curcolum[0] += names[10+i];
6134     curcolum[2].Clear();
6135     curcolum[2]+=TCollection_AsciiString(i);
6136
6137     for(Standard_Integer j =0;j<=2;j++){
6138       curcolum[j].Center(20,' ');
6139       di<<"|"<<curcolum[j].ToCString();
6140     }
6141     di<<"|\n";
6142   }
6143   di<<BlankLine.ToCString()<<"\n";
6144   // les contraintes et dimensions.
6145   // pour l'instant on separe juste contraintes et dimensions...
6146   // plus tard, on detaillera toutes les sortes...
6147   curcolum[1].Clear();
6148   curcolum[1]+="Relation";
6149   curcolum[1].Center(20,' ');
6150   for(i=0;i<=1;i++){
6151     curcolum[0].Clear();
6152     curcolum[0] += names[12+i];
6153     curcolum[2].Clear();
6154     curcolum[2]+=TCollection_AsciiString(i);
6155
6156     for(Standard_Integer j =0;j<=2;j++){
6157       curcolum[j].Center(20,' ');
6158       di<<"|"<<curcolum[j].ToCString();
6159     }
6160     di<<"|\n";
6161   }
6162   di<<BlankLine.ToCString()<<"\n";
6163
6164
6165   return 0;
6166 }
6167
6168
6169 static int VEraseType( Draw_Interpretor& , Standard_Integer argc, const char** argv)
6170 {
6171   if(argc!=2) return 1;
6172
6173   AIS_KindOfInteractive TheType;
6174   Standard_Integer TheSign(-1);
6175   GetTypeAndSignfromString(argv[1],TheType,TheSign);
6176
6177
6178   AIS_ListOfInteractive LIO;
6179
6180   // en attendant l'amelioration ais pour les dimensions...
6181   //
6182   Standard_Integer dimension_status(-1);
6183   if(TheType==AIS_KOI_Relation){
6184     dimension_status = TheSign ==1 ? 1 : 0;
6185     TheSign=-1;
6186   }
6187
6188   TheAISContext()->DisplayedObjects(TheType,TheSign,LIO);
6189   Handle(AIS_InteractiveObject) curio;
6190   for(AIS_ListIteratorOfListOfInteractive it(LIO);it.More();it.Next()){
6191     curio  = it.Value();
6192
6193     if(dimension_status == -1)
6194       TheAISContext()->Erase(curio,Standard_False);
6195     else {
6196       PrsDim_KindOfDimension KOD = Handle(PrsDim_Relation)::DownCast (curio)->KindOfDimension();
6197       if ((dimension_status==0 && KOD == PrsDim_KOD_NONE)||
6198           (dimension_status==1 && KOD != PrsDim_KOD_NONE))
6199         TheAISContext()->Erase(curio,Standard_False);
6200     }
6201   }
6202   TheAISContext()->UpdateCurrentViewer();
6203   return 0;
6204 }
6205 static int VDisplayType(Draw_Interpretor& , Standard_Integer argc, const char** argv)
6206 {
6207   if(argc!=2) return 1;
6208
6209   AIS_KindOfInteractive TheType;
6210   Standard_Integer TheSign(-1);
6211   GetTypeAndSignfromString(argv[1],TheType,TheSign);
6212
6213   // en attendant l'amelioration ais pour les dimensions...
6214   //
6215   Standard_Integer dimension_status(-1);
6216   if(TheType==AIS_KOI_Relation){
6217     dimension_status = TheSign ==1 ? 1 : 0;
6218     TheSign=-1;
6219   }
6220
6221   AIS_ListOfInteractive LIO;
6222   TheAISContext()->ObjectsInside(LIO,TheType,TheSign);
6223   Handle(AIS_InteractiveObject) curio;
6224   for(AIS_ListIteratorOfListOfInteractive it(LIO);it.More();it.Next()){
6225     curio  = it.Value();
6226     if(dimension_status == -1)
6227       TheAISContext()->Display(curio,Standard_False);
6228     else {
6229       PrsDim_KindOfDimension KOD = Handle(PrsDim_Relation)::DownCast (curio)->KindOfDimension();
6230       if ((dimension_status==0 && KOD == PrsDim_KOD_NONE)||
6231           (dimension_status==1 && KOD != PrsDim_KOD_NONE))
6232         TheAISContext()->Display(curio,Standard_False);
6233     }
6234
6235   }
6236
6237   TheAISContext()->UpdateCurrentViewer();
6238   return 0;
6239 }
6240
6241 static Standard_Integer vr(Draw_Interpretor& , Standard_Integer , const char** a)
6242 {
6243   std::ifstream s(a[1]);
6244   BRep_Builder builder;
6245   TopoDS_Shape shape;
6246   BRepTools::Read(shape, s, builder);
6247   DBRep::Set(a[1], shape);
6248   Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
6249   Handle(AIS_Shape) ais = new AIS_Shape(shape);
6250   Ctx->Display (ais, Standard_True);
6251   return 0;
6252 }
6253
6254 //===============================================================================================
6255 //function : VBsdf
6256 //purpose  :
6257 //===============================================================================================
6258 static int VBsdf (Draw_Interpretor& theDI,
6259                   Standard_Integer  theArgsNb,
6260                   const char**      theArgVec)
6261 {
6262   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
6263   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6264   if (aView.IsNull()
6265    || aViewer.IsNull())
6266   {
6267     Message::SendFail ("Error: No active viewer!");
6268     return 1;
6269   }
6270
6271   ViewerTest_CmdParser aCmd;
6272
6273   aCmd.SetDescription ("Adjusts parameters of material BSDF:");
6274
6275   aCmd.AddOption ("print|echo|p", "Prints BSDF");
6276
6277   aCmd.AddOption ("noupdate|update", "Suppresses viewer redraw call");
6278
6279   aCmd.AddOption ("kc", "Weight of coat specular/glossy BRDF");
6280   aCmd.AddOption ("kd", "Weight of base diffuse BRDF");
6281   aCmd.AddOption ("ks", "Weight of base specular/glossy BRDF");
6282   aCmd.AddOption ("kt", "Weight of base specular/glossy BTDF");
6283   aCmd.AddOption ("le", "Radiance emitted by surface");
6284
6285   aCmd.AddOption ("coatFresnel|cf", "Fresnel reflectance of coat layer. Allowed formats: Constant R, Schlick R G B, Dielectric N, Conductor N K");
6286   aCmd.AddOption ("baseFresnel|bf", "Fresnel reflectance of base layer. Allowed formats: Constant R, Schlick R G B, Dielectric N, Conductor N K");
6287
6288   aCmd.AddOption ("coatRoughness|cr", "Roughness of coat glossy BRDF");
6289   aCmd.AddOption ("baseRoughness|br", "Roughness of base glossy BRDF");
6290
6291   aCmd.AddOption ("absorpCoeff|af", "Absorption coeff of base transmission BTDF");
6292   aCmd.AddOption ("absorpColor|ac", "Absorption color of base transmission BTDF");
6293
6294   aCmd.AddOption ("normalize|n", "Normalizes BSDF to ensure energy conservation");
6295
6296   aCmd.Parse (theArgsNb, theArgVec);
6297
6298   if (aCmd.HasOption ("help"))
6299   {
6300     theDI.PrintHelp (theArgVec[0]);
6301     return 0;
6302   }
6303
6304   // check viewer update mode
6305   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
6306   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6307   {
6308     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
6309     {
6310       break;
6311     }
6312   }
6313
6314   // find object
6315   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
6316   Handle(AIS_InteractiveObject) anIObj;
6317   if (!GetMapOfAIS().Find2 (aName, anIObj))
6318   {
6319     Message::SendFail ("Error: no active viewer");
6320     return 1;
6321   }
6322
6323   Graphic3d_MaterialAspect aMaterial = anIObj->Attributes()->ShadingAspect()->Material();
6324   Graphic3d_BSDF aBSDF = aMaterial.BSDF();
6325
6326   if (aCmd.HasOption ("print"))
6327   {
6328     theDI << "\n"
6329       << "Kc:               " << aBSDF.Kc.r() << ", " << aBSDF.Kc.g() << ", " << aBSDF.Kc.b() << "\n"
6330       << "Kd:               " << aBSDF.Kd.r() << ", " << aBSDF.Kd.g() << ", " << aBSDF.Kd.b() << "\n"
6331       << "Ks:               " << aBSDF.Ks.r() << ", " << aBSDF.Ks.g() << ", " << aBSDF.Ks.b() << "\n"
6332       << "Kt:               " << aBSDF.Kt.r() << ", " << aBSDF.Kt.g() << ", " << aBSDF.Kt.b() << "\n"
6333       << "Le:               " << aBSDF.Le.r() << ", " << aBSDF.Le.g() << ", " << aBSDF.Le.b() << "\n";
6334
6335     for (int aLayerID = 0; aLayerID < 2; ++aLayerID)
6336     {
6337       const Graphic3d_Vec4 aFresnel = aLayerID < 1 ? aBSDF.FresnelCoat.Serialize()
6338                                                    : aBSDF.FresnelBase.Serialize();
6339
6340       theDI << (aLayerID < 1 ? "Coat Fresnel:     "
6341                              : "Base Fresnel:     ");
6342
6343       if (aFresnel.x() >= 0.f)
6344       {
6345         theDI << "Schlick " << "R = " << aFresnel.r() << ", "
6346                             << "G = " << aFresnel.g() << ", "
6347                             << "B = " << aFresnel.b() << "\n";
6348       }
6349       else if (aFresnel.x() >= -1.5f)
6350       {
6351         theDI << "Constant " << aFresnel.z() << "\n";
6352       }
6353       else if (aFresnel.x() >= -2.5f)
6354       {
6355         theDI << "Conductor " << "N = " << aFresnel.y() << ", "
6356                               << "K = " << aFresnel.z() << "\n";
6357       }
6358       else
6359       {
6360         theDI << "Dielectric " << "N = " << aFresnel.y() << "\n";
6361       }
6362     }
6363
6364     theDI << "Coat roughness:   " << aBSDF.Kc.w() << "\n"
6365           << "Base roughness:   " << aBSDF.Ks.w() << "\n"
6366           << "Absorption coeff: " << aBSDF.Absorption.w() << "\n"
6367           << "Absorption color: " << aBSDF.Absorption.r() << ", "
6368                                   << aBSDF.Absorption.g() << ", "
6369                                   << aBSDF.Absorption.b() << "\n";
6370
6371     return 0;
6372   }
6373
6374   if (aCmd.HasOption ("coatRoughness", 1, Standard_True))
6375   {
6376     aBSDF.Kc.w() = aCmd.ArgFloat ("coatRoughness");
6377   }
6378
6379   if (aCmd.HasOption ("baseRoughness", 1, Standard_True))
6380   {
6381     aBSDF.Ks.w () = aCmd.ArgFloat ("baseRoughness");
6382   }
6383
6384   if (aCmd.HasOption ("absorpCoeff", 1, Standard_True))
6385   {
6386     aBSDF.Absorption.w() = aCmd.ArgFloat ("absorpCoeff");
6387   }
6388
6389   if (aCmd.HasOption ("absorpColor", 3, Standard_True))
6390   {
6391     const Graphic3d_Vec3 aRGB = aCmd.ArgVec3f ("absorpColor");
6392
6393     aBSDF.Absorption.r() = aRGB.r();
6394     aBSDF.Absorption.g() = aRGB.g();
6395     aBSDF.Absorption.b() = aRGB.b();
6396   }
6397
6398   if (aCmd.HasOption ("kc", 3) || aCmd.HasOption ("kc", 1, Standard_True))
6399   {
6400     Graphic3d_Vec3 aKc;
6401
6402     if (aCmd.HasOption ("kc", 3))
6403     {
6404       aKc = aCmd.ArgVec3f ("kc");
6405     }
6406     else
6407     {
6408       aKc = Graphic3d_Vec3 (aCmd.ArgFloat ("kc"));
6409     }
6410
6411     aBSDF.Kc.r() = aKc.r();
6412     aBSDF.Kc.g() = aKc.g();
6413     aBSDF.Kc.b() = aKc.b();
6414   }
6415
6416   if (aCmd.HasOption ("kd", 3))
6417   {
6418     aBSDF.Kd = aCmd.ArgVec3f ("kd");
6419   }
6420   else if (aCmd.HasOption ("kd", 1, Standard_True))
6421   {
6422     aBSDF.Kd = Graphic3d_Vec3 (aCmd.ArgFloat ("kd"));
6423   }
6424
6425   if (aCmd.HasOption ("ks", 3) || aCmd.HasOption ("ks", 1, Standard_True))
6426   {
6427     Graphic3d_Vec3 aKs;
6428
6429     if (aCmd.HasOption ("ks", 3))
6430     {
6431       aKs = aCmd.ArgVec3f ("ks");
6432     }
6433     else
6434     {
6435       aKs = Graphic3d_Vec3 (aCmd.ArgFloat ("ks"));
6436     }
6437
6438     aBSDF.Ks.r() = aKs.r();
6439     aBSDF.Ks.g() = aKs.g();
6440     aBSDF.Ks.b() = aKs.b();
6441   }
6442
6443   if (aCmd.HasOption ("kt", 3))
6444   {
6445     aBSDF.Kt = aCmd.ArgVec3f ("kt");
6446   }
6447   else if (aCmd.HasOption ("kt", 1, Standard_True))
6448   {
6449     aBSDF.Kt = Graphic3d_Vec3 (aCmd.ArgFloat ("kt"));
6450   }
6451
6452   if (aCmd.HasOption ("le", 3))
6453   {
6454     aBSDF.Le = aCmd.ArgVec3f ("le");
6455   }
6456   else if (aCmd.HasOption ("le", 1, Standard_True))
6457   {
6458     aBSDF.Le = Graphic3d_Vec3 (aCmd.ArgFloat ("le"));
6459   }
6460
6461   const std::string aFresnelErrorMessage =
6462     "Error! Wrong Fresnel type. Allowed types are: Constant F, Schlick R G B, Dielectric N, Conductor N K\n";
6463
6464   for (int aLayerID = 0; aLayerID < 2; ++aLayerID)
6465   {
6466     const std::string aFresnel = aLayerID < 1 ? "baseFresnel"
6467                                               : "coatFresnel";
6468
6469     if (aCmd.HasOption (aFresnel, 4)) // Schlick: type R G B
6470     {
6471       std::string aFresnelType = aCmd.Arg (aFresnel, 0);
6472       std::transform (aFresnelType.begin (), aFresnelType.end (), aFresnelType.begin (), ::LowerCase);
6473
6474       if (aFresnelType == "schlick")
6475       {
6476         Graphic3d_Vec3 aRGB (static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 1).c_str())),
6477                              static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 2).c_str())),
6478                              static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 3).c_str())));
6479
6480         aRGB.r() = std::min (std::max (aRGB.r(), 0.f), 1.f);
6481         aRGB.g() = std::min (std::max (aRGB.g(), 0.f), 1.f);
6482         aRGB.b() = std::min (std::max (aRGB.b(), 0.f), 1.f);
6483
6484         (aLayerID < 1 ? aBSDF.FresnelBase : aBSDF.FresnelCoat) = Graphic3d_Fresnel::CreateSchlick (aRGB);
6485       }
6486       else
6487       {
6488         theDI << aFresnelErrorMessage.c_str() << "\n";
6489       }
6490     }
6491     else if (aCmd.HasOption (aFresnel, 3)) // Conductor: type N K
6492     {
6493       std::string aFresnelType = aCmd.Arg (aFresnel, 0);
6494       std::transform (aFresnelType.begin (), aFresnelType.end (), aFresnelType.begin (), ::LowerCase);
6495
6496       if (aFresnelType == "conductor")
6497       {
6498         const float aN = static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 1).c_str()));
6499         const float aK = static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 2).c_str()));
6500
6501         (aLayerID < 1 ? aBSDF.FresnelBase : aBSDF.FresnelCoat) = Graphic3d_Fresnel::CreateConductor (aN, aK);
6502       }
6503       else
6504       {
6505         theDI << aFresnelErrorMessage.c_str() << "\n";
6506       }
6507     }
6508     else if (aCmd.HasOption (aFresnel, 2)) // Dielectric or Constant: type N|C
6509     {
6510       std::string aFresnelType = aCmd.Arg (aFresnel, 0);
6511       std::transform (aFresnelType.begin (), aFresnelType.end (), aFresnelType.begin (), ::LowerCase);
6512
6513       if (aFresnelType == "constant")
6514       {
6515         const float aR = static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 1).c_str()));
6516
6517         (aLayerID < 1 ? aBSDF.FresnelBase : aBSDF.FresnelCoat) = Graphic3d_Fresnel::CreateConstant (aR);
6518       }
6519       else if (aFresnelType == "dielectric")
6520       {
6521         const float aN = static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 1).c_str()));
6522
6523         (aLayerID < 1 ? aBSDF.FresnelBase : aBSDF.FresnelCoat) = Graphic3d_Fresnel::CreateDielectric (aN);
6524       }
6525       else
6526       {
6527         theDI << aFresnelErrorMessage.c_str() << "\n";
6528       }
6529     }
6530   }
6531
6532   if (aCmd.HasOption ("normalize"))
6533   {
6534     aBSDF.Normalize();
6535   }
6536
6537   aMaterial.SetBSDF (aBSDF);
6538   anIObj->SetMaterial (aMaterial);
6539
6540   return 0;
6541 }
6542
6543 //==============================================================================
6544 //function : VLoadSelection
6545 //purpose  : Adds given objects to map of AIS and loads selection primitives for them
6546 //==============================================================================
6547 static Standard_Integer VLoadSelection (Draw_Interpretor& /*theDi*/,
6548                                         Standard_Integer theArgNb,
6549                                         const char** theArgVec)
6550 {
6551   if (theArgNb < 2)
6552   {
6553     Message::SendFail ("Syntax error: wrong number of arguments.");
6554     return 1;
6555   }
6556
6557   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6558   if (aCtx.IsNull())
6559   {
6560     ViewerTest::ViewerInit();
6561     aCtx = ViewerTest::GetAISContext();
6562   }
6563
6564   // Parse input arguments
6565   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6566   {
6567     const TCollection_AsciiString aName = theArgVec[anArgIter];
6568     Handle(AIS_InteractiveObject) aShape;
6569     if (!GetMapOfAIS().Find2 (aName, aShape))
6570     {
6571       TopoDS_Shape aDrawShape = DBRep::GetExisting (aName);
6572       if (!aDrawShape.IsNull())
6573       {
6574         aShape = new AIS_Shape (aDrawShape);
6575         GetMapOfAIS().Bind (aShape, aName);
6576       }
6577     }
6578     if (aShape.IsNull())
6579     {
6580       Message::SendFail() << "Syntax error: presentation '" << aName << "' not found";
6581       return 1;
6582     }
6583
6584     aCtx->Load (aShape, -1);
6585     aCtx->Activate (aShape, aShape->GlobalSelectionMode(), Standard_True);
6586   }
6587   return 0;
6588 }
6589
6590 //==============================================================================
6591 //function : ViewerTest::Commands
6592 //purpose  : Add all the viewer command in the Draw_Interpretor
6593 //==============================================================================
6594
6595 void ViewerTest::Commands(Draw_Interpretor& theCommands)
6596 {
6597   ViewerTest::ViewerCommands(theCommands);
6598   ViewerTest::RelationCommands(theCommands);
6599   ViewerTest::ObjectCommands(theCommands);
6600   ViewerTest::FilletCommands(theCommands);
6601   ViewerTest::OpenGlCommands(theCommands);
6602
6603   const char *group = "AIS_Display";
6604
6605   // display
6606   theCommands.Add("visos",
6607       "visos [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]\n"
6608       "\tIf last 3 optional parameters are not set prints numbers of U-, V- isolines and IsoOnPlane.\n",
6609       __FILE__, visos, group);
6610
6611   theCommands.Add("vdisplay",
6612               "vdisplay [-noupdate|-update] [-local] [-mutable] [-neutral]"
6613       "\n\t\t:          [-trsfPers {zoom|rotate|zoomRotate|none}=none]"
6614       "\n\t\t:                            [-trsfPersPos X Y [Z]] [-3d]"
6615       "\n\t\t:          [-2d|-trihedron [{top|bottom|left|right|topLeft"
6616       "\n\t\t:                           |topRight|bottomLeft|bottomRight}"
6617       "\n\t\t:                                         [offsetX offsetY]]]"
6618       "\n\t\t:          [-dispMode mode] [-highMode mode]"
6619       "\n\t\t:          [-layer index] [-top|-topmost|-overlay|-underlay]"
6620       "\n\t\t:          [-redisplay] [-erased]"
6621       "\n\t\t:          name1 [name2] ... [name n]"
6622       "\n\t\t: Displays named objects."
6623       "\n\t\t: Option -local enables displaying of objects in local"
6624       "\n\t\t: selection context. Local selection context will be opened"
6625       "\n\t\t: if there is not any."
6626       "\n\t\t:  -noupdate    Suppresses viewer redraw call."
6627       "\n\t\t:  -mutable     Enables optimizations for mutable objects."
6628       "\n\t\t:  -neutral     Draws objects in main viewer."
6629       "\n\t\t:  -erased      Loads the object into context, but does not display it."
6630       "\n\t\t:  -layer       Sets z-layer for objects."
6631       "\n\t\t:               Alternatively -overlay|-underlay|-top|-topmost"
6632       "\n\t\t:               options can be used for the default z-layers."
6633       "\n\t\t:  -top         Draws object on top of main presentations"
6634       "\n\t\t:               but below topmost."
6635       "\n\t\t:  -topmost     Draws in overlay for 3D presentations."
6636       "\n\t\t:               with independent Depth."
6637       "\n\t\t:  -overlay     Draws objects in overlay for 2D presentations."
6638       "\n\t\t:               (On-Screen-Display)"
6639       "\n\t\t:  -underlay    Draws objects in underlay for 2D presentations."
6640       "\n\t\t:               (On-Screen-Display)"
6641       "\n\t\t:  -selectable|-noselect Controls selection of objects."
6642       "\n\t\t:  -trsfPers    Sets a transform persistence flags."
6643       "\n\t\t:  -trsfPersPos Sets an anchor point for transform persistence."
6644       "\n\t\t:  -2d          Displays object in screen coordinates."
6645       "\n\t\t:               (DY looks up)"
6646       "\n\t\t:  -dispmode    Sets display mode for objects."
6647       "\n\t\t:  -highmode    Sets hilight mode for objects."
6648       "\n\t\t:  -redisplay   Recomputes presentation of objects.",
6649       __FILE__, VDisplay2, group);
6650
6651   theCommands.Add ("vnbdisplayed",
6652       "vnbdisplayed"
6653       "\n\t\t: Returns number of displayed objects",
6654       __FILE__, VNbDisplayed, group);
6655
6656   theCommands.Add ("vupdate",
6657       "vupdate name1 [name2] ... [name n]"
6658       "\n\t\t: Updates named objects in interactive context",
6659       __FILE__, VUpdate, group);
6660
6661   theCommands.Add("verase",
6662       "verase [-noupdate|-update] [-local] [name1] ...  [name n] [-noerror]"
6663       "\n\t\t: Erases selected or named objects."
6664       "\n\t\t: If there are no selected or named objects the whole viewer is erased."
6665       "\n\t\t: Option -local enables erasing of selected or named objects without"
6666       "\n\t\t: closing local selection context."
6667       "\n\t\t: Option -noerror prevents exception on non-existing objects.",
6668       __FILE__, VErase, group);
6669
6670   theCommands.Add("vremove",
6671       "vremove [-noupdate|-update] [-context] [-all] [-noinfo] [name1] ...  [name n] [-noerror]"
6672       "or vremove [-context] -all to remove all objects"
6673       "\n\t\t: Removes selected or named objects."
6674       "\n\t\t  If -context is in arguments, the objects are not deleted"
6675       "\n\t\t  from the map of objects and names."
6676       "\n\t\t: Option -local enables removing of selected or named objects without"
6677       "\n\t\t: closing local selection context. Empty local selection context will be"
6678       "\n\t\t: closed."
6679       "\n\t\t: Option -noupdate suppresses viewer redraw call."
6680       "\n\t\t: Option -noinfo suppresses displaying the list of removed objects."
6681       "\n\t\t: Option -noerror prevents exception on non-existing objects.",
6682       __FILE__, VRemove, group);
6683
6684   theCommands.Add("vdonly",
6685                   "vdonly [-noupdate|-update] [name1] ...  [name n]"
6686       "\n\t\t: Displays only selected or named objects",
6687                   __FILE__,VDonly2,group);
6688
6689   theCommands.Add("vdisplayall",
6690       "vdisplayall"
6691       "\n\t\t: Displays all erased interactive objects (see vdir and vstate).",
6692       __FILE__, VDisplayAll, group);
6693
6694   theCommands.Add("veraseall",
6695       "veraseall"
6696       "\n\t\t: Erases all objects displayed in the viewer.",
6697       __FILE__, VErase, group);
6698
6699   theCommands.Add("verasetype",
6700       "verasetype <Type>"
6701       "\n\t\t: Erase all the displayed objects of one given kind (see vtypes)",
6702       __FILE__, VEraseType, group);
6703   theCommands.Add("vbounding",
6704               "vbounding [-noupdate|-update] [-mode] name1 [name2 [...]]"
6705       "\n\t\t:           [-print] [-hide]"
6706       "\n\t\t: Temporarily display bounding box of specified Interactive"
6707       "\n\t\t: Objects, or print it to console if -print is specified."
6708       "\n\t\t: Already displayed box might be hidden by -hide option.",
6709                   __FILE__,VBounding,group);
6710
6711   theCommands.Add("vdisplaytype",
6712                   "vdisplaytype        : vdisplaytype <Type> <Signature> \n\t display all the objects of one given kind (see vtypes) which are stored the AISContext ",
6713                   __FILE__,VDisplayType,group);
6714
6715   theCommands.Add("vsetdispmode",
6716                   "vsetdispmode [name] mode(1,2,..)"
6717       "\n\t\t: Sets display mode for all, selected or named objects.",
6718                   __FILE__,VDispMode,group);
6719
6720   theCommands.Add("vunsetdispmode",
6721                   "vunsetdispmode [name]"
6722       "\n\t\t: Unsets custom display mode for selected or named objects.",
6723                   __FILE__,VDispMode,group);
6724
6725   theCommands.Add("vdir",
6726               "vdir [mask] [-list]"
6727       "\n\t\t: Lists all objects displayed in 3D viewer"
6728       "\n\t\t:    mask - name filter like prefix*"
6729       "\n\t\t:   -list - format list with new-line per name; OFF by default",
6730                   __FILE__,VDir,group);
6731
6732 #ifdef HAVE_FREEIMAGE
6733   #define DUMP_FORMATS "{png|bmp|jpg|gif}"
6734 #else
6735   #define DUMP_FORMATS "{ppm}"
6736 #endif
6737   theCommands.Add("vdump",
6738               "vdump <filename>." DUMP_FORMATS " [-width Width -height Height]"
6739       "\n\t\t:       [-buffer rgb|rgba|depth=rgb]"
6740       "\n\t\t:       [-stereo mono|left|right|blend|sideBySide|overUnder=mono]"
6741       "\n\t\t:       [-xrPose base|head|handLeft|handRight=base]"
6742       "\n\t\t:       [-tileSize Size=0]"
6743       "\n\t\t: Dumps content of the active view into image file",
6744                   __FILE__,VDump,group);
6745
6746   theCommands.Add("vsub",      "vsub 0/1 (off/on) [obj]        : Subintensity(on/off) of selected objects",
6747                   __FILE__,VSubInt,group);
6748
6749   theCommands.Add("vaspects",
6750               "vaspects [-noupdate|-update] [name1 [name2 [...]] | -defaults]"
6751       "\n\t\t:          [-setVisibility 0|1]"
6752       "\n\t\t:          [-setColor ColorName] [-setcolor R G B] [-unsetColor]"
6753       "\n\t\t:          [-setBackFaceColor Color]"
6754       "\n\t\t:          [-setMaterial MatName] [-unsetMaterial]"
6755       "\n\t\t:          [-setTransparency Transp] [-unsetTransparency]"
6756       "\n\t\t:          [-setWidth LineWidth] [-unsetWidth]"
6757       "\n\t\t:          [-setLineType {solid|dash|dot|dotDash|0xHexPattern}] [-unsetLineType]"
6758       "\n\t\t:          [-setMarkerType {.|+|x|O|xcircle|pointcircle|ring1|ring2|ring3|ball|ImagePath}]"
6759       "\n\t\t:          [-unsetMarkerType]"
6760       "\n\t\t:          [-setMarkerSize Scale] [-unsetMarkerSize]"
6761       "\n\t\t:          [-freeBoundary {off/on | 0/1}]"
6762       "\n\t\t:          [-setFreeBoundaryWidth Width] [-unsetFreeBoundaryWidth]"
6763       "\n\t\t:          [-setFreeBoundaryColor {ColorName | R G B}] [-unsetFreeBoundaryColor]"
6764       "\n\t\t:          [-subshapes subname1 [subname2 [...]]]"
6765       "\n\t\t:          [-isoontriangulation 0|1]"
6766       "\n\t\t:          [-setMaxParamValue {value}]"
6767       "\n\t\t:          [-setSensitivity {selection_mode} {value}]"
6768       "\n\t\t:          [-setShadingModel {unlit|flat|gouraud|phong}]"
6769       "\n\t\t:          [-unsetShadingModel]"
6770       "\n\t\t:          [-setInterior {solid|hatch|hidenline|point}]"
6771       "\n\t\t:          [-unsetInterior] [-setHatch HatchStyle]"
6772       "\n\t\t:          [-setFaceBoundaryDraw {0|1}] [-setMostContinuity {c0|c1|c2|c3|cn}"
6773       "\n\t\t:          [-setFaceBoundaryWidth LineWidth] [-setFaceBoundaryColor R G B] [-setFaceBoundaryType LineType]"
6774       "\n\t\t:          [-setDrawEdges {0|1}] [-setEdgeType LineType] [-setEdgeColor R G B] [-setQuadEdges {0|1}]"
6775       "\n\t\t:          [-setDrawSilhouette {0|1}]"
6776       "\n\t\t:          [-setAlphaMode {opaque|mask|blend|blendauto} [alphaCutOff=0.5]]"
6777       "\n\t\t:          [-dumpJson]"
6778       "\n\t\t:          [-dumpCompact {0|1}]"
6779       "\n\t\t:          [-dumpDepth depth]"
6780       "\n\t\t:          [-freeBoundary {off/on | 0/1}]"
6781       "\n\t\t: Manage presentation properties of all, selected or named objects."
6782       "\n\t\t: When -subshapes is specified than following properties will be"
6783       "\n\t\t: assigned to specified sub-shapes."
6784       "\n\t\t: When -defaults is specified than presentation properties will be"
6785       "\n\t\t: assigned to all objects that have not their own specified properties"
6786       "\n\t\t: and to all objects to be displayed in the future."
6787       "\n\t\t: If -defaults is used there should not be any objects' names and -subshapes specifier."
6788       "\n\t\t: See also vlistcolors and vlistmaterials to list named colors and materials"
6789       "\n\t\t: accepted by arguments -setMaterial and -setColor",
6790                   __FILE__,VAspects,group);
6791
6792   theCommands.Add("vsetcolor",
6793       "vsetcolor [-noupdate|-update] [name] ColorName"
6794       "\n\t\t: Sets color for all, selected or named objects."
6795       "\n\t\t: Alias for vaspects -setcolor [name] ColorName.",
6796                   __FILE__,VAspects,group);
6797
6798   theCommands.Add("vunsetcolor",
6799                   "vunsetcolor [-noupdate|-update] [name]"
6800       "\n\t\t: Resets color for all, selected or named objects."
6801       "\n\t\t: Alias for vaspects -unsetcolor [name].",
6802                   __FILE__,VAspects,group);
6803
6804   theCommands.Add("vsettransparency",
6805                   "vsettransparency [-noupdate|-update] [name] Coefficient"
6806       "\n\t\t: Sets transparency for all, selected or named objects."
6807       "\n\t\t: The Coefficient may be between 0.0 (opaque) and 1.0 (fully transparent)."
6808       "\n\t\t: Alias for vaspects -settransp [name] Coefficient.",
6809                   __FILE__,VAspects,group);
6810
6811   theCommands.Add("vunsettransparency",
6812                   "vunsettransparency [-noupdate|-update] [name]"
6813       "\n\t\t: Resets transparency for all, selected or named objects."
6814       "\n\t\t: Alias for vaspects -unsettransp [name].",
6815                   __FILE__,VAspects,group);
6816
6817   theCommands.Add("vsetmaterial",
6818                   "vsetmaterial [-noupdate|-update] [name] MaterialName"
6819       "\n\t\t: Alias for vaspects -setmaterial [name] MaterialName.",
6820                   __FILE__,VAspects,group);
6821
6822   theCommands.Add("vunsetmaterial",
6823                   "vunsetmaterial [-noupdate|-update] [name]"
6824       "\n\t\t: Alias for vaspects -unsetmaterial [name].",
6825                   __FILE__,VAspects,group);
6826
6827   theCommands.Add("vsetwidth",
6828                   "vsetwidth [-noupdate|-update] [name] width(0->10)"
6829       "\n\t\t: Alias for vaspects -setwidth [name] width.",
6830                   __FILE__,VAspects,group);
6831
6832   theCommands.Add("vunsetwidth",
6833                   "vunsetwidth [-noupdate|-update] [name]"
6834       "\n\t\t: Alias for vaspects -unsetwidth [name].",
6835                   __FILE__,VAspects,group);
6836
6837   theCommands.Add("vsetinteriorstyle",
6838     "vsetinteriorstyle [-noupdate|-update] [name] Style"
6839     "\n\t\t: Alias for vaspects -setInterior [name] Style.",
6840                   __FILE__,VAspects,group);
6841
6842   theCommands.Add ("vsetedgetype",
6843     "vsetedgetype [name] [-type {solid, dash, dot}] [-color R G B] [-width value]"
6844     "\n\t\t: Alias for vaspects [name] -setEdgeType Type.",
6845       __FILE__, VAspects, group);
6846
6847   theCommands.Add ("vunsetedgetype",
6848     "vunsetedgetype [name]"
6849     "\n\t\t: Alias for vaspects [name] -unsetEdgeType.",
6850       __FILE__, VAspects, group);
6851
6852   theCommands.Add ("vshowfaceboundary",
6853     "vshowfaceboundary [name]"
6854     "\n\t\t: Alias for vaspects [name] -setFaceBoundaryDraw on",
6855       __FILE__, VAspects, group);
6856
6857   theCommands.Add("vsensdis",
6858       "vsensdis : Display active entities (sensitive entities of one of the standard types corresponding to active selection modes)."
6859       "\n\t\t: Standard entity types are those defined in Select3D package:"
6860       "\n\t\t: - sensitive box"
6861       "\n\t\t: - sensitive face"
6862       "\n\t\t: - sensitive curve"
6863       "\n\t\t: - sensitive segment"
6864       "\n\t\t: - sensitive circle"
6865       "\n\t\t: - sensitive point"
6866       "\n\t\t: - sensitive triangulation"
6867       "\n\t\t: - sensitive triangle"
6868       "\n\t\t: Custom(application - defined) sensitive entity types are not processed by this command.",
6869       __FILE__,VDispSensi,group);
6870
6871   theCommands.Add("vsensera",
6872       "vsensera : erase active entities",
6873       __FILE__,VClearSensi,group);
6874
6875   theCommands.Add("vsetshading",
6876       "vsetshading  : vsetshading name Quality(default=0.0008) "
6877       "\n\t\t: Sets deflection coefficient that defines the quality of the shape representation in the shading mode.",
6878       __FILE__,VShading,group);
6879
6880   theCommands.Add("vunsetshading",
6881       "vunsetshading :vunsetshading name "
6882       "\n\t\t: Sets default deflection coefficient (0.0008) that defines the quality of the shape representation in the shading mode.",
6883       __FILE__,VShading,group);
6884
6885   theCommands.Add ("vtexture",
6886                    "vtexture [-noupdate|-update] name [ImageFile|IdOfTexture|off]"
6887                    "\n\t\t:          [-tex0 Image0] [-tex1 Image1] [...]"
6888                    "\n\t\t:          [-origin {u v|off}] [-scale {u v|off}] [-repeat {u v|off}]"
6889                    "\n\t\t:          [-trsfTrans du dv] [-trsfScale su sv] [-trsfAngle Angle]"
6890                    "\n\t\t:          [-modulate {on|off}]"
6891                    "\n\t\t:          [-setFilter {nearest|bilinear|trilinear}]"
6892                    "\n\t\t:          [-setAnisoFilter {off|low|middle|quality}]"
6893                    "\n\t\t:          [-default]"
6894                    "\n\t\t: The texture can be specified by filepath"
6895                    "\n\t\t: or as ID (0<=IdOfTexture<=20) specifying one of the predefined textures."
6896                    "\n\t\t: The options are:"
6897                    "\n\t\t:   -scale     Setup texture scaling for generating coordinates; (1, 1) by default"
6898                    "\n\t\t:   -origin    Setup texture origin  for generating coordinates; (0, 0) by default"
6899                    "\n\t\t:   -repeat    Setup texture repeat  for generating coordinates; (1, 1) by default"
6900                    "\n\t\t:   -modulate  Enable or disable texture color modulation"
6901                    "\n\t\t:   -trsfAngle Setup dynamic texture coordinates transformation - rotation angle"
6902                    "\n\t\t:   -trsfTrans Setup dynamic texture coordinates transformation - translation vector"
6903                    "\n\t\t:   -trsfScale Setup dynamic texture coordinates transformation - scale vector"
6904                    "\n\t\t:   -setFilter Setup texture filter"
6905                    "\n\t\t:   -setAnisoFilter Setup anisotropic filter for texture with mip-levels"
6906                    "\n\t\t:   -default   Sets texture mapping default parameters",
6907                     __FILE__, VTexture, group);
6908
6909   theCommands.Add("vtexscale",
6910                   "vtexscale name ScaleU ScaleV"
6911                   "\n\t\t: Alias for vtexture name -setScale ScaleU ScaleV.",
6912                   __FILE__,VTexture,group);
6913
6914   theCommands.Add("vtexorigin",
6915                   "vtexorigin name OriginU OriginV"
6916                   "\n\t\t: Alias for vtexture name -setOrigin OriginU OriginV.",
6917                   __FILE__,VTexture,group);
6918
6919   theCommands.Add("vtexrepeat",
6920                   "vtexrepeat name RepeatU RepeatV"
6921                   "\n\t\t: Alias for vtexture name -setRepeat RepeatU RepeatV.",
6922                   VTexture,group);
6923
6924   theCommands.Add("vtexdefault",
6925                   "vtexdefault name"
6926                   "\n\t\t: Alias for vtexture name -default.",
6927                   VTexture,group);
6928
6929   theCommands.Add("vstate",
6930       "vstate [-entities] [-hasSelected] [name1] ... [nameN]"
6931       "\n\t\t: Reports show/hidden state for selected or named objects"
6932       "\n\t\t:   -entities - print low-level information about detected entities"
6933       "\n\t\t:   -hasSelected - prints 1 if context has selected shape and 0 otherwise",
6934                   __FILE__,VState,group);
6935
6936   theCommands.Add("vpickshapes",
6937                   "vpickshape subtype(VERTEX,EDGE,WIRE,FACE,SHELL,SOLID) [name1 or .] [name2 or .] [name n or .]"
6938                   "\n\t\t: Hold Ctrl and pick object by clicking Left mouse button."
6939                   "\n\t\t: Hold also Shift for multiple selection.",
6940                   __FILE__, VPickShape, group);
6941
6942   theCommands.Add("vtypes",
6943                   "vtypes : list of known types and signatures in AIS - To be Used in vpickobject command for selection with filters",
6944                   VIOTypes,group);
6945
6946   theCommands.Add("vr",
6947       "vr filename"
6948       "\n\t\t: Reads shape from BREP-format file and displays it in the viewer. ",
6949                   __FILE__,vr, group);
6950
6951   theCommands.Add("vselfilter",
6952                   "vselfilter [-type {VERTEX|EDGE|WIRE|FACE|SHAPE|SHELL|SOLID}] [-clear]"
6953     "\nSets selection shape type filter in context or remove all filters."
6954     "\n    : Option -type set type of selection filter. Filters are applyed with Or combination."
6955     "\n    : Option -clear remove all filters in context",
6956                   __FILE__,VSelFilter,group);
6957
6958   theCommands.Add("vpickselected", "vpickselected [name]: extract selected shape.",
6959     __FILE__, VPickSelected, group);
6960
6961   theCommands.Add ("vloadselection",
6962     "vloadselection [-context] [name1] ... [nameN] : allows to load selection"
6963     "\n\t\t: primitives for the shapes with names given without displaying them.",
6964     __FILE__, VLoadSelection, group);
6965
6966   theCommands.Add("vbsdf", "vbsdf [name] [options]"
6967     "\nAdjusts parameters of material BSDF:"
6968     "\n    -help : Shows this message"
6969     "\n    -print : Print BSDF"
6970     "\n    -kd : Weight of the Lambertian BRDF"
6971     "\n    -kr : Weight of the reflection BRDF"
6972     "\n    -kt : Weight of the transmission BTDF"
6973     "\n    -ks : Weight of the glossy Blinn BRDF"
6974     "\n    -le : Self-emitted radiance"
6975     "\n    -fresnel : Fresnel coefficients; Allowed fresnel formats are: Constant x,"
6976     "\n               Schlick x y z, Dielectric x, Conductor x y"
6977     "\n    -roughness : Roughness of material (Blinn's exponent)"
6978     "\n    -absorpcoeff : Absorption coefficient (only for transparent material)"
6979     "\n    -absorpcolor : Absorption color (only for transparent material)"
6980     "\n    -normalize : Normalize BSDF coefficients",
6981     __FILE__, VBsdf, group);
6982
6983 }
6984
6985 //=====================================================================
6986 //========================= for testing Draft and Rib =================
6987 //=====================================================================
6988 #include <BRepOffsetAPI_MakeThickSolid.hxx>
6989 #include <DBRep.hxx>
6990 #include <TopoDS_Face.hxx>
6991 #include <gp_Pln.hxx>
6992 #include <BRepOffsetAPI_DraftAngle.hxx>
6993 #include <Precision.hxx>
6994 #include <BRepAlgo.hxx>
6995 #include <OSD_Environment.hxx>
6996 #include <DrawTrSurf.hxx>
6997
6998 //=======================================================================
6999 //function : IsValid
7000 //purpose  :
7001 //=======================================================================
7002 static Standard_Boolean IsValid(const TopTools_ListOfShape& theArgs,
7003                                 const TopoDS_Shape& theResult,
7004                                 const Standard_Boolean closedSolid,
7005                                 const Standard_Boolean GeomCtrl)
7006 {
7007   OSD_Environment check ("DONT_SWITCH_IS_VALID") ;
7008   TCollection_AsciiString checkValid = check.Value();
7009   Standard_Boolean ToCheck = Standard_True;
7010   if (!checkValid.IsEmpty()) {
7011 #ifdef OCCT_DEBUG
7012     std::cout <<"DONT_SWITCH_IS_VALID positionnee a :"<<checkValid.ToCString()<<"\n";
7013 #endif
7014     if ( checkValid=="true" || checkValid=="TRUE" ) {
7015       ToCheck= Standard_False;
7016     }
7017   } else {
7018 #ifdef OCCT_DEBUG
7019     std::cout <<"DONT_SWITCH_IS_VALID non positionne\n";
7020 #endif
7021   }
7022   Standard_Boolean IsValid = Standard_True;
7023   if (ToCheck)
7024     IsValid = BRepAlgo::IsValid(theArgs,theResult,closedSolid,GeomCtrl) ;
7025   return IsValid;
7026
7027 }
7028
7029 //===============================================================================
7030 // TDraft : test draft, uses AIS Viewer
7031 // Solid Face Plane Angle  Reverse
7032 //===============================================================================
7033 static Standard_Integer TDraft(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
7034 {
7035   if (argc < 5) return 1;
7036 // argv[1] - TopoDS_Shape Solid
7037 // argv[2] - TopoDS_Shape Face
7038 // argv[3] - TopoDS_Shape Plane
7039 // argv[4] - Standard_Real Angle
7040 // argv[5] - Standard_Integer Reverse
7041
7042 //  Sprintf(prefix, argv[1]);
7043   Standard_Real anAngle = 0;
7044   Standard_Boolean Rev = Standard_False;
7045   Standard_Integer rev = 0;
7046   TopoDS_Shape Solid  = DBRep::Get (argv[1]);
7047   TopoDS_Shape face   = DBRep::Get (argv[2]);
7048   TopoDS_Face Face    = TopoDS::Face(face);
7049   TopoDS_Shape Plane  = DBRep::Get (argv[3]);
7050   if (Plane.IsNull ()) {
7051     di << "TEST : Plane is NULL\n";
7052     return 1;
7053   }
7054   anAngle = Draw::Atof(argv[4]);
7055   anAngle = 2*M_PI * anAngle / 360.0;
7056   gp_Pln aPln;
7057   Handle( Geom_Surface )aSurf;
7058   PrsDim_KindOfSurface aSurfType;
7059   Standard_Real Offset;
7060   gp_Dir aDir;
7061   if(argc > 4) { // == 5
7062     rev = Draw::Atoi(argv[5]);
7063     Rev = (rev)? Standard_True : Standard_False;
7064   }
7065
7066   TopoDS_Face face2 = TopoDS::Face(Plane);
7067   if(!PrsDim::GetPlaneFromFace(face2, aPln, aSurf, aSurfType, Offset))
7068     {
7069       di << "TEST : Can't find plane\n";
7070       return 1;
7071     }
7072
7073   aDir = aPln.Axis().Direction();
7074   if (!aPln.Direct())
7075     aDir.Reverse();
7076   if (Plane.Orientation() == TopAbs_REVERSED)
7077     aDir.Reverse();
7078   di << "TEST : gp::Resolution() = " << gp::Resolution() << "\n";
7079
7080   BRepOffsetAPI_DraftAngle Draft (Solid);
7081
7082   if(Abs(anAngle)< Precision::Angular()) {
7083     di << "TEST : NULL angle\n";
7084     return 1;}
7085
7086   if(Rev) anAngle = - anAngle;
7087   Draft.Add (Face, aDir, anAngle, aPln);
7088   Draft.Build ();
7089   if (!Draft.IsDone())  {
7090     di << "TEST : Draft Not DONE \n";
7091     return 1;
7092   }
7093   TopTools_ListOfShape Larg;
7094   Larg.Append(Solid);
7095   if (!IsValid(Larg,Draft.Shape(),Standard_True,Standard_False)) {
7096     di << "TEST : DesignAlgo returns Not valid\n";
7097     return 1;
7098   }
7099
7100   Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
7101   Handle(AIS_Shape) ais = new AIS_Shape(Draft.Shape());
7102
7103   if ( !ais.IsNull() ) {
7104     ais->SetColor(DEFAULT_COLOR);
7105     ais->SetMaterial(DEFAULT_MATERIAL);
7106     // Display the AIS_Shape without redraw
7107     Ctx->Display(ais, Standard_False);
7108
7109     const char *Name = "draft1";
7110     Handle(AIS_InteractiveObject) an_object;
7111     if (GetMapOfAIS().Find2(Name, an_object))
7112     {
7113       if (!an_object.IsNull())
7114       {
7115         Ctx->Remove (an_object, Standard_True);
7116       }
7117       GetMapOfAIS().UnBind2 (Name);
7118     }
7119     GetMapOfAIS().Bind(ais, Name);
7120 //  DBRep::Set("draft", ais->Shape());
7121   }
7122   Ctx->Display(ais, Standard_True);
7123   return 0;
7124 }
7125
7126 //==============================================================================
7127 //function : splitParameter
7128 //purpose  : Split parameter string to parameter name and parameter value
7129 //==============================================================================
7130 Standard_Boolean ViewerTest::SplitParameter (const TCollection_AsciiString& theString,
7131                                              TCollection_AsciiString&       theName,
7132                                              TCollection_AsciiString&       theValue)
7133 {
7134   Standard_Integer aParamNameEnd = theString.FirstLocationInSet ("=", 1, theString.Length());
7135
7136   if (aParamNameEnd == 0)
7137   {
7138     return Standard_False;
7139   }
7140
7141   TCollection_AsciiString aString (theString);
7142   if (aParamNameEnd != 0)
7143   {
7144     theValue = aString.Split (aParamNameEnd);
7145     aString.Split (aString.Length() - 1);
7146     theName = aString;
7147   }
7148
7149   return Standard_True;
7150 }
7151
7152 //============================================================================
7153 //  MyCommands
7154 //============================================================================
7155 void ViewerTest::MyCommands( Draw_Interpretor& theCommands)
7156 {
7157
7158   DrawTrSurf::BasicCommands(theCommands);
7159   const char* group = "Check Features Operations commands";
7160
7161   theCommands.Add("Draft","Draft    Solid Face Plane Angle Reverse",
7162                   __FILE__,
7163                   &TDraft,group); //Draft_Modification
7164 }
7165
7166 //==============================================================================
7167 // ViewerTest::Factory
7168 //==============================================================================
7169 void ViewerTest::Factory(Draw_Interpretor& theDI)
7170 {
7171   // definition of Viewer Command
7172   ViewerTest::Commands(theDI);
7173
7174 #ifdef OCCT_DEBUG
7175       theDI << "Draw Plugin : OCC V2d & V3d commands are loaded\n";
7176 #endif
7177 }
7178
7179 // Declare entry point PLUGINFACTORY
7180 DPLUGIN(ViewerTest)