0032306: Draw Harness, ViewerTest - move window message processing to TKService
[occt.git] / src / ViewerTest / ViewerTest_ObjectCommands.cxx
1 // Created on: 1998-11-12
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-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 <ViewerTest.hxx>
18
19 #include <AIS_PlaneTrihedron.hxx>
20
21 #include <Quantity_NameOfColor.hxx>
22 #include <Draw_Interpretor.hxx>
23 #include <Draw.hxx>
24 #include <Draw_Appli.hxx>
25 #include <DBRep.hxx>
26 #include <DBRep_DrawableShape.hxx>
27
28 #include <Font_BRepFont.hxx>
29 #include <Font_BRepTextBuilder.hxx>
30 #include <Font_FontMgr.hxx>
31 #include <Message.hxx>
32 #include <NCollection_List.hxx>
33
34 #include <OSD_Chronometer.hxx>
35 #include <TCollection_AsciiString.hxx>
36 #include <V3d_Viewer.hxx>
37 #include <V3d_View.hxx>
38 #include <V3d.hxx>
39
40 #include <AIS_Shape.hxx>
41 #include <AIS_DisplayMode.hxx>
42 #include <AIS_PointCloud.hxx>
43 #include <TColStd_MapOfInteger.hxx>
44 #include <AIS_MapOfInteractive.hxx>
45 #include <ViewerTest_AutoUpdater.hxx>
46 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
47 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
48 #include <ViewerTest_EventManager.hxx>
49
50 #include <TopoDS_Solid.hxx>
51 #include <BRepTools.hxx>
52 #include <BRep_Builder.hxx>
53 #include <TopAbs_ShapeEnum.hxx>
54
55 #include <TopoDS.hxx>
56 #include <BRep_Tool.hxx>
57 #include <TopExp_Explorer.hxx>
58
59 #include <BRepAdaptor_Curve.hxx>
60 #include <BRepAdaptor_Surface.hxx>
61
62 #include <TopAbs.hxx>
63 #include <TopExp.hxx>
64 #include <TopoDS_Vertex.hxx>
65 #include <TopoDS_Shape.hxx>
66 #include <TopoDS_Face.hxx>
67
68 #include <Draw_Window.hxx>
69 #include <AIS_ListIteratorOfListOfInteractive.hxx>
70 #include <AIS_ListOfInteractive.hxx>
71 #include <AIS_ColoredShape.hxx>
72 #include <AIS_DisplayMode.hxx>
73 #include <AIS_Shape.hxx>
74
75 #include <AIS_InteractiveContext.hxx>
76 #include <Geom_Plane.hxx>
77 #include <gp_Pln.hxx>
78 #include <TCollection_ExtendedString.hxx>
79 #include <TCollection_HAsciiString.hxx>
80 #include <GC_MakePlane.hxx>
81 #include <gp_Circ.hxx>
82 #include <AIS_Axis.hxx>
83 #include <Geom_Axis2Placement.hxx>
84 #include <Geom_Axis1Placement.hxx>
85 #include <AIS_Trihedron.hxx>
86 #include <AIS_Axis.hxx>
87 #include <gp_Trsf.hxx>
88 #include <gp_Quaternion.hxx>
89 #include <TopLoc_Location.hxx>
90
91 #include <HLRAlgo_Projector.hxx>
92 #include <HLRBRep_Algo.hxx>
93 #include <HLRBRep_PolyAlgo.hxx>
94 #include <HLRBRep_PolyHLRToShape.hxx>
95 #include <HLRBRep_HLRToShape.hxx>
96 #include <Aspect_Window.hxx>
97
98 #include <Graphic3d_ArrayOfPoints.hxx>
99 #include <Graphic3d_ArrayOfSegments.hxx>
100 #include <Graphic3d_ArrayOfPolylines.hxx>
101 #include <Graphic3d_ArrayOfTriangles.hxx>
102 #include <Graphic3d_ArrayOfTriangleFans.hxx>
103 #include <Graphic3d_ArrayOfTriangleStrips.hxx>
104 #include <Graphic3d_ArrayOfQuadrangles.hxx>
105 #include <Graphic3d_ArrayOfQuadrangleStrips.hxx>
106 #include <Graphic3d_ArrayOfPolygons.hxx>
107 #include <Graphic3d_AttribBuffer.hxx>
108 #include <Graphic3d_AspectMarker3d.hxx>
109 #include <Graphic3d_Group.hxx>
110 #include <Standard_Real.hxx>
111
112 #include <AIS_Circle.hxx>
113 #include <BRepBuilderAPI_MakeEdge.hxx>
114 #include <BRepBuilderAPI_MakeFace.hxx>
115 #include <BRepBuilderAPI_MakeWire.hxx>
116 #include <Geom_Circle.hxx>
117 #include <GC_MakeCircle.hxx>
118 #include <Select3D_SensitiveCircle.hxx>
119 #include <SelectMgr_EntityOwner.hxx>
120 #include <SelectMgr_Selection.hxx>
121 #include <StdFail_NotDone.hxx>
122 #include <StdPrs_ShadedShape.hxx>
123 #include <TopoDS_Wire.hxx>
124
125 #include <AIS_MultipleConnectedInteractive.hxx>
126 #include <AIS_ConnectedInteractive.hxx>
127 #include <AIS_TextLabel.hxx>
128 #include <TopLoc_Location.hxx>
129 #include <TColStd_ListOfInteger.hxx>
130 #include <TColStd_ListIteratorOfListOfInteger.hxx>
131
132 #include <Select3D_SensitiveSegment.hxx>
133 #include <Select3D_SensitivePrimitiveArray.hxx>
134 #include <Select3D_SensitivePoint.hxx>
135 #include <BRepAdaptor_Curve.hxx>
136 #include <StdPrs_Curve.hxx>
137
138 #include <BRepExtrema_ExtPC.hxx>
139 #include <BRepExtrema_ExtPF.hxx>
140
141 #include <Prs3d_Arrow.hxx>
142 #include <Prs3d_ArrowAspect.hxx>
143 #include <Prs3d_DatumAttribute.hxx>
144 #include <Prs3d_DatumAspect.hxx>
145 #include <Prs3d_Drawer.hxx>
146 #include <Prs3d_VertexDrawMode.hxx>
147 #include <Prs3d_LineAspect.hxx>
148 #include <Prs3d_PointAspect.hxx>
149 #include <Prs3d_Presentation.hxx>
150 #include <Prs3d_TextAspect.hxx>
151 #include <Prs3d_ToolCylinder.hxx>
152 #include <Prs3d_ToolSphere.hxx>
153 #include <Prs3d_ToolTorus.hxx>
154
155 #include <Image_AlienPixMap.hxx>
156 #include <TColStd_HArray1OfAsciiString.hxx>
157 #include <TColStd_HSequenceOfAsciiString.hxx>
158
159 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
160 extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
161                                            const Handle(AIS_InteractiveObject)& theAISObj,
162                                            Standard_Boolean theReplaceIfExists = Standard_True);
163 extern Handle(AIS_InteractiveContext)& TheAISContext();
164
165 namespace
166 {
167   static bool convertToColor (const Handle(TColStd_HSequenceOfAsciiString)& theColorValues,
168                               Quantity_Color& theColor)
169   {
170     const char* anArgs[3] =
171     {
172       theColorValues->Size() >= 1 ? theColorValues->Value (1).ToCString() : "",
173       theColorValues->Size() >= 2 ? theColorValues->Value (2).ToCString() : "",
174       theColorValues->Size() >= 3 ? theColorValues->Value (3).ToCString() : ""
175     };
176     return Draw::ParseColor (theColorValues->Size(), anArgs, theColor) != 0;
177   }
178
179   static bool convertToDatumPart (const TCollection_AsciiString& theValue,
180                                   Prs3d_DatumParts& theDatumPart)
181   {
182     TCollection_AsciiString aValue = theValue;
183     aValue.LowerCase();
184     if      (aValue == "origin")  theDatumPart = Prs3d_DatumParts_Origin;
185     else if (aValue == "xaxis")   theDatumPart = Prs3d_DatumParts_XAxis;
186     else if (aValue == "yaxis")   theDatumPart = Prs3d_DatumParts_YAxis;
187     else if (aValue == "zaxis")   theDatumPart = Prs3d_DatumParts_ZAxis;
188     else if (aValue == "xarrow")  theDatumPart = Prs3d_DatumParts_XArrow;
189     else if (aValue == "yarrow")  theDatumPart = Prs3d_DatumParts_YArrow;
190     else if (aValue == "zarrow")  theDatumPart = Prs3d_DatumParts_ZArrow;
191     else if (aValue == "xoyaxis") theDatumPart = Prs3d_DatumParts_XOYAxis;
192     else if (aValue == "yozaxis") theDatumPart = Prs3d_DatumParts_YOZAxis;
193     else if (aValue == "xozaxis") theDatumPart = Prs3d_DatumParts_XOZAxis;
194     else if (aValue == "whole")   theDatumPart = Prs3d_DatumParts_None;
195     else
196     {
197       return false;
198     }
199     return true;
200   }
201
202   static void convertToDatumParts (const TCollection_AsciiString& theValue,
203                                    NCollection_List<Prs3d_DatumParts>& theParts)
204   {
205     TCollection_AsciiString aValue = theValue;
206     const Standard_Integer aSplitPos = theValue.Search ("|");
207     Prs3d_DatumParts aPart = Prs3d_DatumParts_None;
208     if (aSplitPos > 0)
209     {
210       convertToDatumParts (theValue.SubString (aSplitPos + 1, theValue.Length()), theParts);
211       if (aSplitPos == 1) // first symbol
212       {
213         return;
214       }
215       aValue = theValue.SubString (1, aSplitPos - 1);
216     }
217     if (convertToDatumPart (aValue, aPart))
218     {
219       theParts.Append (aPart);
220     }
221   }
222
223   static bool convertToDatumAttribute (const TCollection_AsciiString& theValue,
224                                        Prs3d_DatumAttribute& theAttribute)
225   {
226     TCollection_AsciiString aValue = theValue;
227     aValue.LowerCase();
228     if      (aValue == "xaxislength")       theAttribute = Prs3d_DatumAttribute_XAxisLength;
229     else if (aValue == "yaxislength")       theAttribute = Prs3d_DatumAttribute_YAxisLength;
230     else if (aValue == "zaxislength")       theAttribute = Prs3d_DatumAttribute_ZAxisLength;
231     else if (aValue == "tuberadiuspercent") theAttribute = Prs3d_DatumAttribute_ShadingTubeRadiusPercent;
232     else if (aValue == "coneradiuspercent") theAttribute = Prs3d_DatumAttribute_ShadingConeRadiusPercent;
233     else if (aValue == "conelengthpercent") theAttribute = Prs3d_DatumAttribute_ShadingConeLengthPercent;
234     else if (aValue == "originradiuspercent") theAttribute = Prs3d_DatumAttribute_ShadingOriginRadiusPercent;
235     else if (aValue == "shadingnumberoffacettes") theAttribute = Prs3d_DatumAttribute_ShadingNumberOfFacettes;
236     else
237       return false;
238     return true;
239   }
240
241   static void convertToDatumAttributes (const TCollection_AsciiString& theValue,
242                                         NCollection_List<Prs3d_DatumAttribute>& theAttributes)
243   {
244     TCollection_AsciiString aValue = theValue;
245     const Standard_Integer aSplitPos = theValue.Search ("|");
246     Prs3d_DatumAttribute anAttribute = Prs3d_DatumAttribute_XAxisLength;
247     if (aSplitPos > 0)
248     {
249       convertToDatumAttributes (theValue.SubString (aSplitPos + 1, theValue.Length()), theAttributes);
250       if (aSplitPos == 1) // first symbol
251       {
252         return;
253       }
254       aValue = theValue.SubString (1, aSplitPos - 1);
255     }
256     if (convertToDatumAttribute (aValue, anAttribute))
257     {
258       theAttributes.Append (anAttribute);
259     }
260   }
261
262   static bool convertToDatumAxes (const TCollection_AsciiString& theValue,
263                                   Prs3d_DatumAxes& theDatumAxes)
264   {
265     TCollection_AsciiString aValue = theValue;
266     aValue.LowerCase();
267     if      (aValue == "x")   theDatumAxes = Prs3d_DatumAxes_XAxis;
268     else if (aValue == "y")   theDatumAxes = Prs3d_DatumAxes_YAxis;
269     else if (aValue == "z")   theDatumAxes = Prs3d_DatumAxes_ZAxis;
270     else if (aValue == "xy")  theDatumAxes = Prs3d_DatumAxes_XYAxes;
271     else if (aValue == "zy")  theDatumAxes = Prs3d_DatumAxes_YZAxes;
272     else if (aValue == "xz")  theDatumAxes = Prs3d_DatumAxes_XZAxes;
273     else if (aValue == "xyz") theDatumAxes = Prs3d_DatumAxes_XYZAxes;
274     else
275     {
276       return false;
277     }
278     return true;
279   }
280
281   static Standard_Boolean setTrihedronParams (Standard_Integer  theArgsNb,
282                                               const char** theArgVec,
283                                               Handle(AIS_Trihedron) theTrihedron)
284   {
285     NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
286     TCollection_AsciiString aParseKey;
287     for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
288     {
289       TCollection_AsciiString anArg (theArgVec [anArgIt]);
290       if (anArg.Value (1) == '-'
291       && !anArg.IsRealValue (Standard_True))
292       {
293         aParseKey = anArg;
294         aParseKey.Remove (1);
295         aParseKey.LowerCase();
296         std::string aKey = aParseKey.ToCString();
297         aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString());
298         continue;
299       }
300
301       if (aParseKey.IsEmpty())
302       {
303         continue;
304       }
305
306       aMapOfArgs (aParseKey)->Append (anArg);
307     }
308
309     // Check parameters
310     if ((aMapOfArgs.IsBound ("xaxis") && !aMapOfArgs.IsBound ("zaxis"))
311     || (!aMapOfArgs.IsBound ("xaxis") &&  aMapOfArgs.IsBound ("zaxis")))
312     {
313       Message::SendFail ("Syntax error: -xaxis and -zaxis parameters are to set together");
314       return Standard_False;
315     }
316
317     Handle(TColStd_HSequenceOfAsciiString) aValues;
318     Handle(Geom_Axis2Placement) aComponent = theTrihedron->Component();
319     if (aMapOfArgs.Find ("origin", aValues))
320     {
321       aComponent->SetLocation (gp_Pnt (aValues->Value (1).RealValue(),
322                                        aValues->Value (2).RealValue(),
323                                        aValues->Value (3).RealValue()));
324     }
325     Handle(TColStd_HSequenceOfAsciiString) aXValues, aZValues;
326     if (aMapOfArgs.Find ("xaxis", aXValues) && aMapOfArgs.Find ("zaxis", aZValues))
327     {
328       gp_Dir aXDir (aXValues->Value (1).RealValue(),
329                     aXValues->Value (2).RealValue(),
330                     aXValues->Value (3).RealValue());
331
332       gp_Dir aZDir (aZValues->Value (1).RealValue(),
333                     aZValues->Value (2).RealValue(),
334                     aZValues->Value (3).RealValue());
335
336       if (!aZDir.IsNormal (aXDir, M_PI / 180.0))
337       {
338         Message::SendFail ("Syntax error - parameters 'xaxis' and 'zaxis' are not applied as VectorX is not normal to VectorZ");
339         return Standard_False;
340       }
341
342       aComponent->SetAx2 (gp_Ax2 (aComponent->Location(), aZDir, aXDir));
343     }
344
345     if (aMapOfArgs.Find ("dispmode", aValues))
346     {
347       TCollection_AsciiString aValue (aValues->Value (1));
348       bool isWireframe = true;
349       if (aValue.IsEqual ("sh") || aValue.IsEqual ("shading"))
350         isWireframe = false;
351       theTrihedron->SetDatumDisplayMode (isWireframe ? Prs3d_DM_WireFrame
352                                                      : Prs3d_DM_Shaded);
353     }
354
355     if (aMapOfArgs.Find ("hidelabels", aValues))
356     {
357       Standard_Boolean toHideLabels = Standard_True;
358       if (aValues->Size() == 1)
359       {
360         Draw::ParseOnOff (aValues->First().ToCString(), toHideLabels);
361       }
362       else if (aValues->Size() != 0)
363       {
364         Message::SendFail ("Syntax error: -hidelabels expects parameter 'on' or 'off' after");
365         return Standard_False;
366       }
367
368       if (!theTrihedron->Attributes()->HasOwnDatumAspect())
369       {
370         theTrihedron->Attributes()->SetDatumAspect (new Prs3d_DatumAspect());
371       }
372       theTrihedron->Attributes()->DatumAspect()->SetDrawLabels (!toHideLabels);
373     }
374
375     if (aMapOfArgs.Find ("hidearrows", aValues))
376     {
377       Standard_Boolean toHideArrows = Standard_True;
378       if (aValues->Size() == 1)
379       {
380         Draw::ParseOnOff (aValues->First().ToCString(), toHideArrows);
381       }
382       else if (aValues->Size() != 0)
383       {
384         Message::SendFail ("Syntax error: -hidearrows expects parameter 'on' or 'off' after");
385         return Standard_False;
386       }
387
388       if (!theTrihedron->Attributes()->HasOwnDatumAspect())
389       {
390         theTrihedron->Attributes()->SetDatumAspect (new Prs3d_DatumAspect());
391       }
392       theTrihedron->Attributes()->DatumAspect()->SetDrawArrows (!toHideArrows);
393     }
394
395     if (aMapOfArgs.Find ("color", aValues))
396     {
397       NCollection_List<Prs3d_DatumParts> aParts;
398       if (aValues->Size() < 2)
399       {
400         Message::SendFail ("Syntax error: -color wrong parameters");
401         return Standard_False;
402       }
403
404       convertToDatumParts (aValues->Value(1), aParts);
405       aValues->Remove (1); // datum part is processed
406       Quantity_Color aColor;
407       if (!convertToColor (aValues, aColor))
408       {
409         Message::SendFail ("Syntax error: -color wrong parameters");
410         return Standard_False;
411       }
412
413       for (NCollection_List<Prs3d_DatumParts>::Iterator anIterator (aParts); anIterator.More(); anIterator.Next())
414       {
415         Prs3d_DatumParts aDatumPart = anIterator.Value();
416         if (aDatumPart == Prs3d_DatumParts_None)
417         {
418           theTrihedron->SetColor (aColor);
419         }
420         else
421         {
422           theTrihedron->SetDatumPartColor (aDatumPart, aColor);
423         }
424       }
425     }
426
427     if (aMapOfArgs.Find ("textcolor", aValues))
428     {
429       Prs3d_DatumParts aDatumPart = Prs3d_DatumParts_None;
430       if (!aValues->IsEmpty()
431         && convertToDatumPart (aValues->First(), aDatumPart)
432         && aDatumPart >= Prs3d_DatumParts_XAxis
433         && aDatumPart <= Prs3d_DatumParts_ZAxis)
434       {
435         aValues->Remove (1); // datum part is processed
436       }
437
438       Quantity_Color aColor;
439       if (!convertToColor (aValues, aColor))
440       {
441         Message::SendFail ("Syntax error: -textcolor wrong parameters");
442         return Standard_False;
443       }
444
445       if (aDatumPart != Prs3d_DatumParts_None)
446       {
447         theTrihedron->SetTextColor (aDatumPart, aColor);
448       }
449       else
450       {
451         theTrihedron->SetTextColor (aColor);
452       }
453     }
454
455     if (aMapOfArgs.Find ("arrowcolor", aValues))
456     {
457       Prs3d_DatumParts aDatumPart = Prs3d_DatumParts_None;
458       if (!aValues->IsEmpty()
459         && convertToDatumPart (aValues->First(), aDatumPart)
460         && ((aDatumPart >= Prs3d_DatumParts_XArrow && aDatumPart <= Prs3d_DatumParts_ZArrow)
461          || (aDatumPart >= Prs3d_DatumParts_XAxis  && aDatumPart <= Prs3d_DatumParts_ZAxis)))
462       {
463         aValues->Remove (1); // datum part is processed
464       }
465
466       Quantity_Color aColor;
467       if (!convertToColor (aValues, aColor))
468       {
469         Message::SendFail ("Syntax error: -arrowcolor wrong parameters");
470         return Standard_False;
471       }
472
473       if (aDatumPart != Prs3d_DatumParts_None)
474       {
475         Prs3d_DatumParts anArrowPart = Prs3d_DatumAspect::ArrowPartForAxis (aDatumPart);
476         theTrihedron->SetArrowColor (anArrowPart, aColor);
477       }
478       else
479       {
480         theTrihedron->SetArrowColor (aColor);
481       }
482     }
483
484     if (aMapOfArgs.Find ("attribute", aValues))
485     {
486       NCollection_List<Prs3d_DatumAttribute> anAttributes;
487       if (aValues->Size() != 2)
488       {
489         Message::SendFail ("Syntax error: -attribute wrong parameters");
490         return Standard_False;
491       }
492
493       convertToDatumAttributes (aValues->Value (1), anAttributes);
494       if (!theTrihedron->Attributes()->HasOwnDatumAspect())
495         theTrihedron->Attributes()->SetDatumAspect(new Prs3d_DatumAspect());
496       for (NCollection_List<Prs3d_DatumAttribute>::Iterator anIterator (anAttributes); anIterator.More(); anIterator.Next())
497       {
498         theTrihedron->Attributes()->DatumAspect()->SetAttribute (anIterator.Value(), aValues->Value (2).RealValue());
499       }
500     }
501
502     if (aMapOfArgs.Find ("priority", aValues))
503     {
504       Prs3d_DatumParts aDatumPart;
505       if (aValues->Size() < 2
506       || !convertToDatumPart (aValues->Value (1), aDatumPart))
507       {
508         Message::SendFail ("Syntax error: -priority wrong parameters");
509         return Standard_False;
510       }
511       theTrihedron->SetSelectionPriority (aDatumPart, aValues->Value (2).IntegerValue());
512     }
513
514     if (aMapOfArgs.Find ("labels", aValues)
515      || aMapOfArgs.Find ("label", aValues))
516     {
517       Prs3d_DatumParts aDatumPart = Prs3d_DatumParts_None;
518       if (aValues->Size() >= 2
519        && convertToDatumPart(aValues->Value(1), aDatumPart)
520        && aDatumPart >= Prs3d_DatumParts_XAxis
521        && aDatumPart <= Prs3d_DatumParts_ZAxis) // labels are set to axes only
522       {
523         theTrihedron->SetLabel (aDatumPart, aValues->Value (2));
524       }
525       else
526       {
527         Message::SendFail ("Syntax error: -labels wrong parameters");
528         return Standard_False;
529       }
530     }
531
532     if (aMapOfArgs.Find ("drawaxes", aValues))
533     {
534       Prs3d_DatumAxes aDatumAxes = Prs3d_DatumAxes_XAxis;
535       if (aValues->Size() < 1
536       || !convertToDatumAxes (aValues->Value (1), aDatumAxes))
537       {
538         Message::SendFail ("Syntax error: -drawaxes wrong parameters");
539         return Standard_False;
540       }
541       if (!theTrihedron->Attributes()->HasOwnDatumAspect())
542         theTrihedron->Attributes()->SetDatumAspect(new Prs3d_DatumAspect());
543       theTrihedron->Attributes()->DatumAspect()->SetDrawDatumAxes (aDatumAxes);
544     }
545     return Standard_True;
546   }
547
548   //! Auxiliary function to parse font aspect style argument
549   static Standard_Boolean parseFontStyle (const TCollection_AsciiString& theArg,
550                                           Font_FontAspect&               theAspect)
551   {
552     if (theArg == "regular"
553      || *theArg.ToCString() == 'r')
554     {
555       theAspect = Font_FA_Regular;
556       return Standard_True;
557     }
558     else if (theArg == "bolditalic"
559           || theArg == "bold-italic"
560           || theArg == "italic-bold"
561           || theArg == "italicbold")
562     {
563       theAspect = Font_FA_BoldItalic;
564       return Standard_True;
565     }
566     else if (theArg == "bold"
567           || *theArg.ToCString() == 'b')
568     {
569       theAspect = Font_FA_Bold;
570       return Standard_True;
571     }
572     else if (theArg == "italic"
573           || *theArg.ToCString() == 'i')
574     {
575       theAspect = Font_FA_Italic;
576       return Standard_True;
577     }
578     return Standard_False;
579   }
580
581   //! Auxiliary function to parse font strict level argument
582   static Standard_Integer parseFontStrictLevel (const Standard_Integer theArgNb,
583                                                 const char**           theArgVec,
584                                                 Font_StrictLevel&      theLevel)
585   {
586     if (theArgNb >= 1)
587     {
588       TCollection_AsciiString anArg (theArgVec[0]);
589       anArg.LowerCase();
590       if (anArg == "any")
591       {
592         theLevel = Font_StrictLevel_Any;
593         return 1;
594       }
595       else if (anArg == "aliases")
596       {
597         theLevel = Font_StrictLevel_Aliases;
598         return 1;
599       }
600       else if (anArg == "strict")
601       {
602         theLevel = Font_StrictLevel_Strict;
603         return 1;
604       }
605     }
606     theLevel = Font_StrictLevel_Strict;
607     return 0;
608   }
609 }
610
611 //==============================================================================
612 //function : Vtrihedron 2d
613 //purpose  : Create a plane with a 2D  trihedron from a faceselection
614 //Draw arg : vtri2d  name
615 //==============================================================================
616 static int VTrihedron2D (Draw_Interpretor& /*theDI*/,
617                          Standard_Integer  theArgsNum,
618                          const char**      theArgVec)
619 {
620   if (ViewerTest::CurrentView().IsNull())
621   {
622     Message::SendFail ("Error: no active viewer");
623     return 1;
624   }
625   if (theArgsNum != 2)
626   {
627     Message::SendFail() << "Syntax error: wrong number of arguments.";
628     return 1;
629   }
630
631   TopTools_ListOfShape aShapes;
632   ViewerTest::GetSelectedShapes (aShapes);
633
634   if (aShapes.Extent() != 1)
635   {
636     Message::SendFail ("Error: wrong number of selected shapes.");
637     return 1;
638   }
639
640   const TopoDS_Shape& aShape = aShapes.First();
641
642   TopoDS_Face     aFace = TopoDS::Face (aShape);
643   TopExp_Explorer aFaceExp (aFace, TopAbs_EDGE);
644   TopoDS_Edge     anEdge0 = TopoDS::Edge (aFaceExp.Current());
645
646   gp_Pnt A,B,C;
647   if (aFaceExp.More())
648   {
649     aFaceExp.Next();
650     TopoDS_Edge anEdge1 = TopoDS::Edge (aFaceExp.Current() );
651     BRepAdaptor_Curve aCurve0 (anEdge0);
652     BRepAdaptor_Curve aCurve1 (anEdge1);
653     A = aCurve1.Value (0.1);
654     B = aCurve1.Value (0.9);
655     C = aCurve0.Value (0.5);
656   }
657   else
658   {
659     BRepAdaptor_Curve aCurve0 (anEdge0);
660     A = aCurve0.Value (0.1);
661     B = aCurve0.Value (0.9);
662     C = aCurve0.Value (0.5);
663   }
664
665   GC_MakePlane aMkPlane (A,B,C);
666
667   Handle(AIS_PlaneTrihedron) anAISPlaneTri = new AIS_PlaneTrihedron (aMkPlane.Value());
668   TCollection_AsciiString aName (theArgVec[1]);
669
670   VDisplayAISObject (aName, anAISPlaneTri);
671
672   return 0;
673 }
674
675 //=======================================================================
676 //function : VTrihedron
677 //purpose  :
678 //=======================================================================
679 static int VTrihedron (Draw_Interpretor& ,
680                        Standard_Integer theArgsNb,
681                        const char** theArgVec)
682 {
683   if (ViewerTest::CurrentView().IsNull())
684   {
685     Message::SendFail ("Error: no active viewer");
686     return 1;
687   }
688   if (theArgsNb < 2)
689   {
690     Message::SendFail ("Syntax error: the wrong number of input parameters");
691     return 1;
692   }
693
694   TCollection_AsciiString aName (theArgVec[1]);
695   gp_Pln aWorkingPlane;
696   Standard_Boolean toUpdate = Standard_True;
697
698   NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
699   NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
700
701   Handle(AIS_Trihedron) aTrihedron;
702   Handle(AIS_InteractiveObject) anObject;
703   if (GetMapOfAIS().Find2 (aName, anObject))
704   {
705     aTrihedron = Handle(AIS_Trihedron)::DownCast (anObject);
706     if (aTrihedron.IsNull())
707     {
708       Message::SendFail ("Syntax error: no trihedron with this name");
709       return 1;
710     }
711   }
712   else
713   {
714     Handle(Geom_Axis2Placement) aPlacement = new Geom_Axis2Placement (gp_Pnt (0.0, 0.0, 0.0),
715                                                                       gp::DZ(), gp::DX());
716     aTrihedron = new AIS_Trihedron (aPlacement);
717   }
718
719   if (!setTrihedronParams (theArgsNb, theArgVec, aTrihedron))
720   {
721     return 1;
722   }
723
724   // Redisplay a dimension after parameter changing.
725   if (ViewerTest::GetAISContext()->IsDisplayed (aTrihedron))
726   {
727     ViewerTest::GetAISContext()->Redisplay (aTrihedron, toUpdate);
728   }
729   else
730   {
731     VDisplayAISObject (theArgVec[1], aTrihedron);
732   }
733
734   return 0;
735 }
736
737 //==============================================================================
738 //function : VSize
739 //author   : ege
740 //purpose  : Change the size of a named or selected trihedron
741 //           if no name : it affects the trihedrons witch are selected otherwise nothing is donne
742 //           if no value, the value is set at 100 by default
743 //Draw arg : vsize [name] [size]
744 //==============================================================================
745 static int VSize (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
746 {
747   if (TheAISContext().IsNull())
748   {
749     Message::SendFail ("Error: no active viewer");
750     return 1;
751   }
752
753   TCollection_AsciiString aName;
754   Standard_Real aSize = 0.0;
755   switch (argc)
756   {
757     case 1:
758     {
759       aSize = 100;
760       break;
761     }
762     case 2:
763     {
764       aSize = Draw::Atof (argv[1]);
765       break;
766     }
767     case 3:
768     {
769       aName = argv[1];
770       aSize = Draw::Atof (argv[2]);
771       break;
772     }
773     default:
774     {
775       di << "Syntax error";
776       return 1;
777     }
778   }
779
780   NCollection_Sequence<Handle(AIS_Trihedron)> aTrihedrons;
781   if (!aName.IsEmpty())
782   {
783     Handle(AIS_InteractiveObject) aShape;
784     if (GetMapOfAIS().Find2 (aName, aShape))
785     {
786       if (Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast (aShape))
787       {
788         aTrihedrons.Append (aTrihedron);
789       }
790       else
791       {
792         di << "Syntax error: " << aName << " is not a trihedron";
793         return 1;
794       }
795     }
796   }
797   else if (TheAISContext()->NbSelected() > 0)
798   {
799     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName it (GetMapOfAIS()); it.More(); it.Next())
800     {
801       const Handle(AIS_InteractiveObject)& aShape = it.Key1();
802       if (!aShape.IsNull()
803        && TheAISContext()->IsSelected (aShape))
804       {
805         if (Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast (aShape))
806         {
807           aTrihedrons.Append (aTrihedron);
808         }
809       }
810     }
811   }
812
813   for (NCollection_Sequence<Handle(AIS_Trihedron)>::Iterator anObjIter (aTrihedrons); anObjIter.More(); anObjIter.Next())
814   {
815     const Handle(AIS_Trihedron)& aTrihedron = anObjIter.Value();
816     Quantity_Color aColor = Quantity_NOC_BLACK;
817     const bool hasColor = aTrihedron->HasColor();
818     if (hasColor)
819     {
820       aTrihedron->Color (aColor);
821     }
822
823     aTrihedron->SetSize (aSize);
824     if (hasColor) { aTrihedron->SetColor (aColor); }
825     else          { aTrihedron->UnsetColor(); }
826
827     TheAISContext()->Redisplay (aTrihedron, Standard_False);
828   }
829   if (!aTrihedrons.IsEmpty())
830   {
831     TheAISContext()->UpdateCurrentViewer();
832   }
833
834   return 0;
835 }
836
837 //==============================================================================
838
839 //==============================================================================
840 //function : VPlaneTrihedron
841 //purpose  : Create a plane from a trihedron selection. If no arguments are set, the default
842 //Draw arg : vplanetri  name
843 //==============================================================================
844 #include <AIS_Plane.hxx>
845
846
847
848 static int VPlaneTrihedron (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
849
850 {
851   // Verification des arguments
852   if ( argc!=2) {di<<argv[0]<<" error\n"; return 1;}
853
854   if (TheAISContext().IsNull())
855   {
856     Message::SendFail ("Error: no active viewer");
857     return 1;
858   }
859
860   if (TheAISContext()->NbSelected() != 1)
861   {
862     Message::SendFail ("Error: Wrong number of selected shapes.");
863     return 1;
864   }
865
866   TheAISContext()->InitSelected();
867   Handle(AIS_InteractiveObject) aTest = TheAISContext()->SelectedInteractive();
868   Handle(AIS_Plane) aPlane = Handle(AIS_Plane)::DownCast (aTest);
869   if (aPlane.IsNull())
870   {
871     Message::SendFail ("Error: Selected shape is not a plane.");
872     return 1;
873   }
874
875   VDisplayAISObject (argv[1], aPlane);
876
877   return 0;
878 }
879
880
881
882 //==============================================================================
883 // Fonction        First click      2de click
884 //
885 // vaxis           vertex           vertex
886 //                 edge             None
887 // vaxispara       edge             vertex
888 // vaxisortho      edge             Vertex
889 // vaxisinter      Face             Face
890 //==============================================================================
891
892 //==============================================================================
893 //function : VAxisBuilder
894 //purpose  :
895 //Draw arg : vaxis AxisName Xa Ya Za Xb Yb Zb
896 //==============================================================================
897 #include <TopoDS_Edge.hxx>
898 #include <TopoDS_Vertex.hxx>
899 #include <TopExp.hxx>
900 #include <Geom_Line.hxx>
901
902 static int VAxisBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
903 {
904   // Declarations
905   Standard_Boolean HasArg;
906   TCollection_AsciiString name;
907
908   // Verification
909   if (argc<2 || argc>8 ) {di<<" Syntaxe error\n";return 1;}
910   if (argc==8) HasArg=Standard_True;
911   else HasArg=Standard_False;
912
913   name=argv[1];
914
915   TopTools_ListOfShape aShapes;
916   ViewerTest::GetSelectedShapes (aShapes);
917
918   // Cas ou il y a des arguments
919   // Purpose: Teste le constructeur AIS_Axis::AIS_Axis(x: Line from Geom)
920   if (HasArg) {
921     Standard_Real coord[6];
922     for(Standard_Integer i=0;i<=5;i++){
923       coord[i]=Draw::Atof(argv[2+i]);
924     }
925     gp_Pnt p1(coord[0],coord[1],coord[2]), p2(coord[3],coord[4],coord[5]) ;
926
927     gp_Vec myVect (p1,p2);
928     Handle(Geom_Line) myLine=new Geom_Line (p1 ,myVect );
929     Handle(AIS_Axis) TheAxis=new AIS_Axis (myLine );
930     GetMapOfAIS().Bind (TheAxis,name);
931     TheAISContext()->Display(TheAxis, Standard_True);
932   }
933
934   // Pas d'arguments
935   else {
936     // fonction vaxis
937     // Purpose: Teste le constructeur AIS_Axis::AIS_Axis (x:Axis1Placement from Geom)
938     if ( !strcasecmp(argv[0], "vaxis")) {
939       if (aShapes.Extent() != 2 && aShapes.Extent() != 1)
940       {
941         Message::SendFail ("Error: Wrong number of selected shapes.");
942         return 1;
943       }
944
945       const TopoDS_Shape& aShapeA = aShapes.First();
946       if (aShapeA.ShapeType() == TopAbs_VERTEX)
947       {
948         if (aShapes.Extent() != 2)
949         {
950           Message::SendFail ("Error: Wrong number of selected shapes.");
951           return 1;
952         }
953
954         const TopoDS_Shape& aShapeB = aShapes.Last();
955         if (aShapeB.ShapeType() != TopAbs_VERTEX)
956         {
957           Message::SendFail ("Syntax error: You should select two vertices or one edge.");
958           return 1;
959         }
960
961         // Construction de l'axe
962         gp_Pnt A = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
963         gp_Pnt B = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
964         gp_Vec V (A,B);
965         gp_Dir D (V);
966         Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (A,D);
967         Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
968         GetMapOfAIS().Bind (TheAxis,name);
969         TheAISContext()->Display (TheAxis, Standard_True);
970       }
971       else
972       {
973         TopoDS_Edge    ed =TopoDS::Edge (aShapeA);
974         TopoDS_Vertex  Va,Vb;
975         TopExp::Vertices(ed,Va,Vb );
976         gp_Pnt A=BRep_Tool::Pnt(Va);
977         gp_Pnt B=BRep_Tool::Pnt(Vb);
978         gp_Vec  V (A,B);
979         gp_Dir   D (V);
980         Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (A,D);
981         Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
982         GetMapOfAIS().Bind (TheAxis,name);
983         TheAISContext()->Display (TheAxis, Standard_True);
984       }
985
986     }
987
988     // Fonction axispara
989     // Purpose: Teste le constructeur AIS_Axis::AIS_Axis(x: Axis2Placement from Geom, y: TypeOfAxis from AIS)
990     else if ( !strcasecmp(argv[0], "vaxispara"))
991     {
992       if (aShapes.Extent() != 2)
993       {
994         Message::SendFail ("Error: Wrong number of selected shapes.");
995         return 1;
996       }
997
998       const TopoDS_Shape& aShapeA = aShapes.First();
999       const TopoDS_Shape& aShapeB = aShapes.Last();
1000       if (!(aShapeA.ShapeType() == TopAbs_EDGE
1001          && aShapeB.ShapeType() == TopAbs_VERTEX))
1002       {
1003         Message::SendFail ("Syntax error: You should select face and then vertex.");
1004         return 1;
1005       }
1006
1007       TopoDS_Edge    ed=TopoDS::Edge (aShapeA);
1008       gp_Pnt B=BRep_Tool::Pnt(TopoDS::Vertex(aShapeB));
1009       TopoDS_Vertex  Va,Vc;
1010       TopExp::Vertices(ed,Va,Vc );
1011       gp_Pnt A=BRep_Tool::Pnt(Va);
1012       gp_Pnt C=BRep_Tool::Pnt(Vc);
1013       gp_Vec  V (A,C);
1014       gp_Dir   D (V);
1015       Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (B,D);
1016       Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
1017       GetMapOfAIS().Bind (TheAxis,name);
1018       TheAISContext()->Display (TheAxis, Standard_True);
1019
1020     }
1021
1022     // Fonction axisortho
1023     else
1024     {
1025       if (aShapes.Extent() != 2)
1026       {
1027         Message::SendFail ("Error: Wrong number of selected shapes.");
1028         return 1;
1029       }
1030
1031       const TopoDS_Shape& aShapeA = aShapes.First();
1032       const TopoDS_Shape& aShapeB = aShapes.Last();
1033       if (!(aShapeA.ShapeType() == TopAbs_EDGE
1034          && aShapeB.ShapeType() == TopAbs_VERTEX))
1035       {
1036         Message::SendFail ("Syntax error: You should select face and then vertex.");
1037         return 1;
1038       }
1039
1040       // Construction de l'axe
1041       TopoDS_Edge    ed=TopoDS::Edge(aShapeA) ;
1042       gp_Pnt B=BRep_Tool::Pnt(TopoDS::Vertex(aShapeB) );
1043       TopoDS_Vertex  Va,Vc;
1044       TopExp::Vertices(ed,Va,Vc );
1045       gp_Pnt A=BRep_Tool::Pnt(Va);
1046       gp_Pnt C=BRep_Tool::Pnt(Vc);
1047       gp_Pnt E(A.Y()+A.Z()-C.Y()-C.Z()  ,C.X()-A.X() ,C.X()-A.X() );
1048       gp_Vec  V (A,E);
1049       gp_Dir   D (V);
1050       Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (B,D);
1051       Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
1052       GetMapOfAIS().Bind (TheAxis,name);
1053       TheAISContext()->Display (TheAxis, Standard_True);
1054
1055     }
1056
1057   }
1058   return 0;
1059 }
1060
1061
1062 //==============================================================================
1063 // Fonction        First click      Result
1064 //
1065 // vpoint          vertex           AIS_Point=Vertex
1066 //                 edge             AIS_Point=Middle of the edge
1067 //==============================================================================
1068
1069 //==============================================================================
1070 //function : VPointBuilder
1071 //purpose  :
1072 //==============================================================================
1073 #include <TopoDS_Edge.hxx>
1074 #include <TopoDS_Vertex.hxx>
1075 #include <TopExp.hxx>
1076 #include <AIS_Point.hxx>
1077 #include <Geom_CartesianPoint.hxx>
1078
1079 static int VPointBuilder(Draw_Interpretor& ,
1080                          Standard_Integer theArgNb,
1081                          const char** theArgVec)
1082 {
1083   TCollection_AsciiString aName;
1084   gp_Pnt aPnt (RealLast(), 0.0, 0.0);
1085   bool is2d = false, isNoSel = false;
1086   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
1087   {
1088     TCollection_AsciiString anArg (theArgVec[anArgIter]);
1089     anArg.LowerCase();
1090     if (anArg == "-2d")
1091     {
1092       is2d = true;
1093     }
1094     else if (anArg == "-nosel"
1095           || anArg == "-noselection")
1096     {
1097       isNoSel = true;
1098     }
1099     else if (aName.IsEmpty())
1100     {
1101       aName = theArgVec[anArgIter];
1102     }
1103     else if (aPnt.X() == RealLast()
1104           && anArgIter + 1 < theArgNb
1105           && Draw::ParseReal (theArgVec[anArgIter + 0], aPnt.ChangeCoord().ChangeCoord (1))
1106           && Draw::ParseReal (theArgVec[anArgIter + 1], aPnt.ChangeCoord().ChangeCoord (2)))
1107     {
1108       if (anArgIter + 2 < theArgNb
1109        && TCollection_AsciiString (theArgVec[anArgIter + 2]) != "-2d"
1110        && Draw::ParseReal (theArgVec[anArgIter + 2], aPnt.ChangeCoord().ChangeCoord (3)))
1111       {
1112         anArgIter += 2;
1113       }
1114       else
1115       {
1116         anArgIter += 1;
1117       }
1118     }
1119     else
1120     {
1121       Message::SendFail() << "Syntax error at argument '" << anArg << "'\n";
1122       return 1;
1123     }
1124   }
1125
1126   if (aPnt.X() == RealLast())
1127   {
1128     TopTools_ListOfShape aShapes;
1129     ViewerTest::GetSelectedShapes (aShapes);
1130     TopoDS_Shape aShapeA;
1131     if (aShapes.Extent() == 1)
1132     {
1133       aShapeA = aShapes.First();
1134     }
1135     switch (!aShapeA.IsNull() ? aShapeA.ShapeType() : TopAbs_SHAPE)
1136     {
1137       case TopAbs_VERTEX:
1138       {
1139         aPnt = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
1140         break;
1141       }
1142       case TopAbs_EDGE: // edge middle point
1143       {
1144         const TopoDS_Edge& anEdge = TopoDS::Edge (aShapeA);
1145         TopoDS_Vertex aVertPair[2];
1146         TopExp::Vertices (anEdge, aVertPair[0], aVertPair[1]);
1147         const gp_Pnt A = BRep_Tool::Pnt (aVertPair[0]);
1148         const gp_Pnt B = BRep_Tool::Pnt (aVertPair[1]);
1149         aPnt = (A.XYZ() + B.XYZ()) / 2;
1150         break;
1151       }
1152       default:
1153       {
1154         Message::SendFail() << "Error: Wrong number of selected shapes.\n"
1155                             << "\tYou should select one edge or vertex.";
1156         return 1;
1157       }
1158     }
1159   }
1160
1161   if (is2d)
1162   {
1163     aPnt.SetY (-aPnt.Y());
1164   }
1165   Handle(Geom_CartesianPoint ) aGeomPoint = new Geom_CartesianPoint (aPnt);
1166   Handle(AIS_Point) aPointPrs = new AIS_Point (aGeomPoint);
1167   if (is2d)
1168   {
1169     aPointPrs->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER));
1170     aPointPrs->SetZLayer (Graphic3d_ZLayerId_TopOSD);
1171   }
1172   ViewerTest::Display (aName, aPointPrs);
1173   if (isNoSel)
1174   {
1175     ViewerTest::GetAISContext()->Deactivate (aPointPrs);
1176   }
1177   return 0;
1178 }
1179
1180 //==============================================================================
1181 // Function        1st click   2de click  3de click
1182 // vplane          Vertex      Vertex     Vertex
1183 //                 Vertex      Edge
1184 //                 Edge        Vertex
1185 //                 Face
1186 // vplanepara      Face        Vertex
1187 //                 Vertex      Face
1188 // vplaneortho     Face        Edge
1189 //                 Edge        Face
1190 //==============================================================================
1191
1192 //==============================================================================
1193 //function : VPlaneBuilder
1194 //purpose  : Build an AIS_Plane from selected entities or Named AIS components
1195 //Draw arg : vplane PlaneName [AxisName]  [PointName] [TypeOfSensitivity]
1196 //                            [PointName] [PointName] [PointName] [TypeOfSensitivity]
1197 //                            [PlaneName] [PointName] [TypeOfSensitivity]
1198 //==============================================================================
1199
1200 static Standard_Integer VPlaneBuilder (Draw_Interpretor& /*di*/,
1201                                        Standard_Integer argc,
1202                                        const char** argv)
1203 {
1204   // Declarations
1205   Standard_Boolean hasArg;
1206   TCollection_AsciiString aName;
1207
1208   // Verification
1209   if (argc<2 || argc>6 )
1210   {
1211     Message::SendFail ("Syntax error: wrong number of arguments");
1212     return 1;
1213   }
1214   if (argc == 6 || argc==5 || argc==4)
1215     hasArg=Standard_True;
1216   else 
1217     hasArg=Standard_False;
1218
1219   aName=argv[1];
1220
1221   // There are some arguments
1222   if (hasArg)
1223   {
1224     Handle(AIS_InteractiveObject) aShapeA;
1225     if (!GetMapOfAIS().Find2 (argv[2], aShapeA))
1226     {
1227       Message::SendFail ("Syntax error: 1st name is not displayed");
1228       return 1;
1229     }
1230
1231     // The first argument is an AIS_Point
1232     if (!aShapeA.IsNull()
1233       && aShapeA->Type() == AIS_KindOfInteractive_Datum
1234       && aShapeA->Signature() == 1)
1235     {
1236       // The second argument must also be an AIS_Point
1237       Handle(AIS_InteractiveObject) aShapeB;
1238       if (argc<5 || !GetMapOfAIS().Find2 (argv[3], aShapeB))
1239       {
1240         Message::SendFail ("Syntax error: 2nd name is not displayed");
1241         return 1;
1242       }
1243
1244       // If B is not an AIS_Point
1245       if (aShapeB.IsNull()
1246       || !(aShapeB->Type() == AIS_KindOfInteractive_Datum
1247         && aShapeB->Signature() == 1))
1248       {
1249         Message::SendFail ("Syntax error: 2nd object is expected to be an AIS_Point");
1250         return 1;
1251       }
1252
1253       // The third object is an AIS_Point
1254       Handle(AIS_InteractiveObject) aShapeC;
1255       if (!GetMapOfAIS().Find2(argv[4], aShapeC))
1256       {
1257         Message::SendFail ("Syntax error: 3d name is not displayed");
1258         return 1;
1259       }
1260
1261       // If C is not an AIS_Point
1262       if (aShapeC.IsNull()
1263       || !(aShapeC->Type() == AIS_KindOfInteractive_Datum
1264         && aShapeC->Signature() == 1))
1265       {
1266         Message::SendFail ("Syntax error: 3d object is expected to be an AIS_Point");
1267         return 1;
1268       }
1269
1270       // Treatment of objects A, B, C
1271       // Downcast an AIS_IO to AIS_Point
1272       Handle(AIS_Point) anAISPointA = Handle(AIS_Point)::DownCast (aShapeA);
1273       Handle(AIS_Point) anAISPointB = Handle(AIS_Point)::DownCast (aShapeB);
1274       Handle(AIS_Point) anAISPointC = Handle(AIS_Point)::DownCast (aShapeC);
1275
1276       Handle(Geom_CartesianPoint ) aCartPointA = Handle(Geom_CartesianPoint)::DownCast (anAISPointA->Component());
1277       Handle(Geom_CartesianPoint ) aCartPointB = Handle(Geom_CartesianPoint)::DownCast (anAISPointB->Component());
1278       Handle(Geom_CartesianPoint ) aCartPointC = Handle(Geom_CartesianPoint)::DownCast (anAISPointC->Component());
1279
1280       // Verification that the three points are different
1281       if (Abs(aCartPointB->X()-aCartPointA->X()) <= Precision::Confusion()
1282        && Abs(aCartPointB->Y()-aCartPointA->Y()) <= Precision::Confusion()
1283        && Abs(aCartPointB->Z()-aCartPointA->Z()) <= Precision::Confusion())
1284       {
1285         // B=A
1286         Message::SendFail ("Error: same points");
1287         return 1;
1288       }
1289       if (Abs(aCartPointC->X()-aCartPointA->X()) <= Precision::Confusion()
1290        && Abs(aCartPointC->Y()-aCartPointA->Y()) <= Precision::Confusion()
1291        && Abs(aCartPointC->Z()-aCartPointA->Z()) <= Precision::Confusion())
1292       {
1293         // C=A
1294         Message::SendFail ("Error: same points");
1295         return 1;
1296       }
1297       if (Abs(aCartPointC->X()-aCartPointB->X()) <= Precision::Confusion()
1298        && Abs(aCartPointC->Y()-aCartPointB->Y()) <= Precision::Confusion()
1299        && Abs(aCartPointC->Z()-aCartPointB->Z()) <= Precision::Confusion())
1300       {
1301         // C=B
1302         Message::SendFail ("Error: same points");
1303         return 1;
1304       }
1305
1306       gp_Pnt A = aCartPointA->Pnt();
1307       gp_Pnt B = aCartPointB->Pnt();
1308       gp_Pnt C = aCartPointC->Pnt();
1309
1310       // Construction of AIS_Plane
1311       GC_MakePlane MkPlane (A,B,C);
1312       Handle(Geom_Plane) aGeomPlane = MkPlane.Value();
1313       Handle(AIS_Plane)  anAISPlane = new AIS_Plane (aGeomPlane);
1314       GetMapOfAIS().Bind (anAISPlane, aName);
1315       if (argc == 6)
1316       {
1317         Standard_Integer aType = Draw::Atoi (argv[5]);
1318         if (aType != 0 && aType != 1)
1319         {
1320           Message::SendFail("Syntax error: wrong type of sensitivity.\n"
1321                             "Should be one of the following values:\n"
1322                             "0 - Interior\n"
1323                             "1 - Boundary");
1324           return 1;
1325         }
1326         else
1327         {
1328           anAISPlane->SetTypeOfSensitivity (Select3D_TypeOfSensitivity (aType));
1329         }
1330       }
1331       TheAISContext()->Display (anAISPlane, Standard_True);
1332     }
1333     // The first argument is an AIS_Axis
1334     // Creation of a plane orthogonal to the axis through a point
1335     else if (aShapeA->Type() == AIS_KindOfInteractive_Datum
1336           && aShapeA->Signature() == 2)
1337     {
1338       // The second argument should be an AIS_Point
1339       Handle(AIS_InteractiveObject) aShapeB;
1340       if (argc!=4 || !GetMapOfAIS().Find2 (argv[3], aShapeB))
1341       {
1342         Message::SendFail ("Syntax error: 2d name is not displayed");
1343         return 1;
1344       }
1345       // If B is not an AIS_Point
1346       if (aShapeB.IsNull()
1347       || !(aShapeB->Type() == AIS_KindOfInteractive_Datum
1348         && aShapeB->Signature() == 1))
1349       {
1350         Message::SendFail ("Syntax error: 2d object is expected to be an AIS_Point");
1351         return 1;
1352       }
1353
1354       // Treatment of objects A and B
1355       Handle(AIS_Axis) anAISAxisA = Handle(AIS_Axis)::DownCast(aShapeA);
1356       Handle(AIS_Point) anAISPointB = Handle(AIS_Point)::DownCast(aShapeB);
1357
1358       Handle(Geom_Line ) aGeomLineA = anAISAxisA->Component();
1359       Handle(Geom_Point) aGeomPointB = anAISPointB->Component();
1360
1361       gp_Ax1 anAxis = aGeomLineA->Position();
1362       Handle(Geom_CartesianPoint) aCartPointB = Handle(Geom_CartesianPoint)::DownCast(aGeomPointB);
1363
1364       gp_Dir D = anAxis.Direction();
1365       gp_Pnt B = aCartPointB->Pnt();
1366
1367       // Construction of AIS_Plane
1368       Handle(Geom_Plane) aGeomPlane = new Geom_Plane(B,D);
1369       Handle(AIS_Plane) anAISPlane = new AIS_Plane(aGeomPlane,B );
1370       GetMapOfAIS().Bind (anAISPlane,aName );
1371       if (argc == 5)
1372       {
1373         Standard_Integer aType = Draw::Atoi (argv[4]);
1374         if (aType != 0 && aType != 1)
1375         {
1376           Message::SendFail ("Syntax error: wrong type of sensitivity!\n"
1377                              "Should be one of the following values:\n"
1378                              "0 - Interior\n"
1379                              "1 - Boundary");
1380           return 1;
1381         }
1382         else
1383         {
1384           anAISPlane->SetTypeOfSensitivity (Select3D_TypeOfSensitivity (aType));
1385         }
1386       }
1387       TheAISContext()->Display (anAISPlane, Standard_True);
1388     }
1389     // The first argument is an AIS_Plane
1390     // Creation of a plane parallel to the plane passing through the point
1391     else if (aShapeA->Type() == AIS_KindOfInteractive_Datum
1392           && aShapeA->Signature() == 7)
1393     {
1394       // The second argument should be an AIS_Point
1395       Handle(AIS_InteractiveObject) aShapeB;
1396       if (argc!=4 || !GetMapOfAIS().Find2 (argv[3], aShapeB))
1397       {
1398         Message::SendFail ("Syntax error: 2d name is not displayed");
1399         return 1;
1400       }
1401       // B should be an AIS_Point
1402       if (aShapeB.IsNull()
1403        || !(aShapeB->Type()==AIS_KindOfInteractive_Datum
1404          && aShapeB->Signature() == 1))
1405       {
1406         Message::SendFail ("Syntax error: 2d object is expected to be an AIS_Point");
1407         return 1;
1408       }
1409
1410       // Treatment of objects A and B
1411       Handle(AIS_Plane) anAISPlaneA = Handle(AIS_Plane)::DownCast(aShapeA);
1412       Handle(AIS_Point) anAISPointB = Handle(AIS_Point)::DownCast(aShapeB);
1413
1414       Handle(Geom_Plane) aNewGeomPlane= anAISPlaneA->Component();
1415       Handle(Geom_Point) aGeomPointB = anAISPointB->Component();
1416
1417       Handle(Geom_CartesianPoint) aCartPointB = Handle(Geom_CartesianPoint)::DownCast(aGeomPointB);
1418       gp_Pnt B= aCartPointB->Pnt();
1419
1420       // Construction of an AIS_Plane
1421       Handle(AIS_Plane) anAISPlane = new AIS_Plane(aNewGeomPlane, B);
1422       GetMapOfAIS().Bind (anAISPlane, aName);
1423       if (argc == 5)
1424       {
1425         Standard_Integer aType = Draw::Atoi (argv[4]);
1426         if (aType != 0 && aType != 1)
1427         {
1428           Message::SendFail ("Syntax error: wrong type of sensitivity!\n"
1429                              "Should be one of the following values:\n"
1430                              "0 - Interior\n"
1431                              "1 - Boundary");
1432           return 1;
1433         }
1434         else
1435         {
1436           anAISPlane->SetTypeOfSensitivity (Select3D_TypeOfSensitivity (aType));
1437         }
1438       }
1439       TheAISContext()->Display (anAISPlane, Standard_True);
1440     }
1441     // Error
1442     else
1443     {
1444       Message::SendFail ("Syntax error: 1st object is not an AIS");
1445       return 1;
1446     }
1447   }
1448   // There are no arguments
1449   else 
1450   {
1451     TopTools_ListOfShape aShapes;
1452     ViewerTest::GetSelectedShapes (aShapes);
1453
1454     // Function vplane
1455     // Test the constructor AIS_Plane::AIS_Plane(Geom_Plane, Standard_Boolean )
1456     if (!strcasecmp(argv[0], "vplane"))
1457     {
1458       if (aShapes.Extent() < 1 || aShapes.Extent() > 3)
1459       {
1460         Message::SendFail() << "Error: Wront number of selected shapes.\n"
1461                             << "\tYou should one of variant: face, edge and vertex or three vertices.";
1462         return 1;
1463       }
1464
1465       const TopoDS_Shape& aShapeA = aShapes.First();
1466       if (aShapeA.ShapeType() == TopAbs_VERTEX)
1467       {
1468         if (aShapes.Extent() == 2)
1469         {
1470           const TopoDS_Shape& aShapeB = aShapes.Last();
1471           if (aShapeB.ShapeType() != TopAbs_EDGE)
1472           {
1473             Message::SendFail ("Syntax error: Together with vertex should be edge.");
1474             return 1;
1475           }
1476
1477           // Verify that the vertex is not on the edge ShapeB
1478           TopoDS_Edge anEdgeB = TopoDS::Edge(aShapeB);
1479           TopoDS_Vertex aVertA = TopoDS::Vertex(aShapeA);
1480
1481           BRepExtrema_ExtPC OrthoProj(aVertA, anEdgeB);
1482           if (OrthoProj.SquareDistance(1)<Precision::Approximation())
1483           {
1484             // The vertex is on the edge
1485             Message::SendFail ("Error: point is on the edge");
1486             return 1;
1487           }
1488           else
1489           {
1490             gp_Pnt A = BRep_Tool::Pnt(aVertA);
1491             TopoDS_Vertex aVBa, aVBb;
1492             TopExp::Vertices(anEdgeB ,aVBa ,aVBb);
1493             gp_Pnt aBa = BRep_Tool::Pnt(aVBa);
1494             gp_Pnt aBb = BRep_Tool::Pnt(aVBb);
1495             GC_MakePlane MkPlane (A, aBa, aBb);
1496             Handle(Geom_Plane) aGeomPlane = MkPlane.Value();
1497             Handle(AIS_Plane) anAISPlane = new AIS_Plane (aGeomPlane);
1498             GetMapOfAIS().Bind (anAISPlane, aName);
1499             TheAISContext()->Display (anAISPlane, Standard_True);
1500           }
1501         }
1502         else if (aShapes.Extent() == 3)
1503         {
1504           TopTools_ListOfShape::Iterator anIter (aShapes);
1505
1506           anIter.Next();
1507           const TopoDS_Shape& aShapeB = anIter.Value();
1508
1509           anIter.Next();
1510           const TopoDS_Shape& aShapeC = anIter.Value();
1511
1512           if (!(aShapeB.ShapeType() == TopAbs_VERTEX
1513              && aShapeC.ShapeType() == TopAbs_VERTEX))
1514           {
1515             Message::SendFail ("Syntax error: You should one of variant: face, edge and vertex or three vertices.");
1516             return 1;
1517           }
1518
1519           gp_Pnt A = BRep_Tool::Pnt(TopoDS::Vertex(aShapeA));
1520           gp_Pnt B = BRep_Tool::Pnt(TopoDS::Vertex(aShapeB));
1521           gp_Pnt C = BRep_Tool::Pnt(TopoDS::Vertex(aShapeC));
1522           GC_MakePlane MkPlane(A, B, C);
1523           Handle(Geom_Plane) aGeomPlane = MkPlane.Value();
1524           Handle(AIS_Plane) anAISPlane = new AIS_Plane (aGeomPlane);
1525           GetMapOfAIS().Bind (anAISPlane, aName);
1526           TheAISContext()->Display (anAISPlane, Standard_True);
1527         }
1528         else
1529         {
1530           Message::SendFail ("Syntax error: You should one of variant: face, edge and vertex or three vertices.");
1531           return 1;
1532         }
1533       }
1534       else if (aShapeA.ShapeType() == TopAbs_EDGE)
1535       {
1536         if (aShapes.Extent() != 2)
1537         {
1538           Message::SendFail ("Error: wrong number of selected shapes.");
1539           return 1;
1540         }
1541
1542         const TopoDS_Shape& aShapeB = aShapes.Last();
1543         if (aShapeB.ShapeType() != TopAbs_VERTEX)
1544         {
1545           Message::SendFail ("Syntax error: Together with edge should be vertex.");
1546           return 1;
1547         }
1548
1549         // Check that the vertex aShapeB is not on the edge
1550         TopoDS_Edge anEdgeA = TopoDS::Edge(aShapeA);
1551         TopoDS_Vertex aVertB = TopoDS::Vertex(aShapeB);
1552
1553         BRepExtrema_ExtPC OrthoProj (aVertB, anEdgeA);
1554         if (OrthoProj.SquareDistance(1)<Precision::Approximation())
1555         {
1556           // The vertex is on the edge
1557           Message::SendFail ("Error point is on the edge");
1558           return 1;
1559         }
1560
1561         gp_Pnt B = BRep_Tool::Pnt(aVertB);
1562         TopoDS_Vertex aVAa, aVAb;
1563         TopExp::Vertices(anEdgeA, aVAa, aVAb);
1564         gp_Pnt Aa = BRep_Tool::Pnt(aVAa);
1565         gp_Pnt Ab = BRep_Tool::Pnt(aVAb);
1566         GC_MakePlane MkPlane (B,Aa,Ab);
1567         Handle(Geom_Plane) aGeomPlane = MkPlane.Value();
1568         Handle(AIS_Plane) anAISPlane = new AIS_Plane (aGeomPlane);
1569         GetMapOfAIS().Bind (anAISPlane ,aName);
1570         TheAISContext()->Display (anAISPlane, Standard_True);
1571       }
1572       else if (aShapeA.ShapeType() == TopAbs_FACE)
1573       {
1574         TopoDS_Face aFace = TopoDS::Face(aShapeA);
1575         BRepAdaptor_Surface aSurface (aFace, Standard_False);
1576         if (aSurface.GetType()==GeomAbs_Plane)
1577         {
1578           gp_Pln aPlane = aSurface.Plane();
1579           Handle(Geom_Plane) aGeomPlane = new Geom_Plane(aPlane);
1580           Handle(AIS_Plane) anAISPlane = new AIS_Plane(aGeomPlane);
1581           GetMapOfAIS().Bind (anAISPlane, aName);
1582           TheAISContext()->Display (anAISPlane, Standard_True);
1583         }
1584         else
1585         {
1586           Message::SendFail ("Error: surface is not Plane");
1587           return 1;
1588         }
1589       }
1590       else
1591       {
1592         Message::SendFail ("Syntax error: You should one of variant: face, edge and vertex or three vertices");
1593         return 1;
1594       }
1595     }
1596
1597     // Function vPlanePara
1598     // ===================
1599     // test the constructor AIS_Plane::AIS_Plane(Geom_Plane,gp_Pnt)
1600     else if (!strcasecmp(argv[0], "vplanepara"))
1601     {
1602       if (aShapes.Extent() != 2)
1603       {
1604         Message::SendFail ("Error: Wrong number of selected shapes.");
1605         return 1;
1606       }
1607
1608       const TopoDS_Shape* aShapeA = &aShapes.First();
1609       const TopoDS_Shape* aShapeB = &aShapes.Last();
1610       if (aShapeA->ShapeType() != TopAbs_VERTEX)
1611       {
1612         std::swap (aShapeA, aShapeB);
1613       }
1614
1615       if (!(aShapeA->ShapeType() == TopAbs_VERTEX
1616          && aShapeB->ShapeType() == TopAbs_FACE))
1617       {
1618         Message::SendFail ("Syntax error: you should select face and vertex.");
1619         return 1;
1620       }
1621
1622       gp_Pnt A = BRep_Tool::Pnt(TopoDS::Vertex(*aShapeA));
1623
1624       TopoDS_Face aFace = TopoDS::Face(*aShapeB);
1625       BRepAdaptor_Surface aSurface (aFace, Standard_False);
1626       if (aSurface.GetType() == GeomAbs_Plane)
1627       {
1628         gp_Pln aPlane = aSurface.Plane();
1629         // Construct a plane parallel to aGeomPlane through A
1630         aPlane.SetLocation(A);
1631         Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
1632         Handle(AIS_Plane) aAISPlane = new AIS_Plane (aGeomPlane, A);
1633         GetMapOfAIS().Bind (aAISPlane ,aName);
1634         TheAISContext()->Display (aAISPlane, Standard_True);
1635       }
1636       else
1637       {
1638         Message::SendFail ("Error: Builded surface is not a plane.");
1639         return 1;
1640       }
1641     }
1642
1643     // Function vplaneortho
1644     // ====================
1645     // test the constructor AIS_Plane::AIS_Plane(Geom_Plane,gp_Pnt,gp_Pnt,gp_Pnt)
1646     else
1647     {
1648       if (aShapes.Extent() != 2)
1649       {
1650         Message::SendFail ("Error: wrong number of selected shapes.");
1651         return 1;
1652       }
1653
1654       const TopoDS_Shape* aShapeA = &aShapes.First();
1655       const TopoDS_Shape* aShapeB = &aShapes.Last();
1656
1657       if (aShapeA->ShapeType() != TopAbs_EDGE)
1658       {
1659         std::swap (aShapeA, aShapeB);
1660       }
1661
1662       if (!(aShapeA->ShapeType() == TopAbs_EDGE
1663          && aShapeB->ShapeType() == TopAbs_FACE))
1664       {
1665         Message::SendFail ("Error: you should select edge and face.");
1666         return 1;
1667       }
1668
1669       // Construction of plane
1670       TopoDS_Edge anEdgeA = TopoDS::Edge(*aShapeA);
1671       TopoDS_Vertex aVAa, aVAb;
1672       TopExp::Vertices(anEdgeA, aVAa, aVAb);
1673       gp_Pnt Aa = BRep_Tool::Pnt(aVAa);
1674       gp_Pnt Ab = BRep_Tool::Pnt(aVAb);
1675       gp_Vec ab (Aa,Ab);
1676
1677       gp_Dir Dab (ab);
1678       // Creation of rotation axis
1679       gp_Ax1 aRotAxis (Aa,Dab);
1680
1681       TopoDS_Face aFace = TopoDS::Face(*aShapeB);
1682       // The edge must be parallel to the face
1683       BRepExtrema_ExtPF aHeightA (aVAa, aFace);
1684       BRepExtrema_ExtPF aHeightB (aVAb, aFace);
1685       // Compare to heights
1686       if (fabs(sqrt(aHeightA.SquareDistance(1)) - sqrt(aHeightB.SquareDistance(1)))
1687           >Precision::Confusion())
1688       {
1689         // the edge is not parallel to the face
1690         Message::SendFail ("Error: the edge is not parallel to the face");
1691         return 1;
1692       }
1693       // the edge is OK
1694       BRepAdaptor_Surface aSurface (aFace, Standard_False);
1695       if (aSurface.GetType()==GeomAbs_Plane)
1696       {
1697         gp_Pln aPlane = aSurface.Plane();
1698         // It rotates a half turn round the axis of rotation
1699         aPlane.Rotate(aRotAxis , M_PI/2);
1700
1701         Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
1702         // constructed aGeomPlane parallel to a plane containing the edge (center mid-edge)
1703         gp_Pnt aMiddle ((Aa.X()+Ab.X() )/2 ,(Aa.Y()+Ab.Y() )/2 ,(Aa.Z()+Ab.Z() )/2 );
1704         Handle(AIS_Plane) anAISPlane = new AIS_Plane (aGeomPlane, aMiddle);
1705         GetMapOfAIS().Bind (anAISPlane, aName);
1706         TheAISContext()->Display (anAISPlane, Standard_True);
1707       }
1708       else
1709       {
1710         Message::SendFail ("Error: surface is not Plane");
1711         return 1;
1712       }
1713     }
1714   }
1715   return 0;
1716 }
1717
1718 //===============================================================================================
1719 //function : VChangePlane
1720 //purpose  :
1721 //===============================================================================================
1722 static int VChangePlane (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
1723 {
1724   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
1725   if (aContextAIS.IsNull())
1726   {
1727     Message::SendFail ("Error: no active viewer.");
1728     return 1;
1729   }
1730
1731   if (theArgsNb < 3 || theArgsNb > 11)
1732   {
1733     Message::SendFail ("Syntax error: wrong number of arguments.");
1734     return 1;
1735   }
1736
1737   TCollection_AsciiString aName (theArgVec[1]);
1738
1739   Handle(AIS_Plane) aPlane = GetMapOfAIS().IsBound2(aName)
1740     ? Handle(AIS_Plane)::DownCast (GetMapOfAIS().Find2 (aName))
1741     : NULL;
1742
1743   if ( aPlane.IsNull() )
1744   {
1745     Message::SendFail() << "Syntax error: there is no interactive plane with the given name '" << aName << "'.";
1746     return 1;
1747   }
1748
1749   Standard_Real aCenterX = aPlane->Center().X();
1750   Standard_Real aCenterY = aPlane->Center().Y();
1751   Standard_Real aCenterZ = aPlane->Center().Z();
1752
1753   Standard_Real aDirX = aPlane->Component()->Axis().Direction().X();
1754   Standard_Real aDirY = aPlane->Component()->Axis().Direction().Y();
1755   Standard_Real aDirZ = aPlane->Component()->Axis().Direction().Z();
1756
1757   Standard_Real aSizeX = 0.0;
1758   Standard_Real aSizeY = 0.0;
1759   aPlane->Size (aSizeX, aSizeY);
1760   Standard_Boolean isUpdate = Standard_True;
1761
1762   TCollection_AsciiString aPName, aPValue;
1763   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
1764   {
1765     const TCollection_AsciiString anArg = theArgVec[anArgIt];
1766     TCollection_AsciiString anArgCase = anArg;
1767     anArgCase.UpperCase();
1768     if (ViewerTest::SplitParameter (anArg, aPName, aPValue))
1769     {
1770       aPName.UpperCase();
1771       if (aPName.IsEqual ("X"))
1772       {
1773         aCenterX = aPValue.RealValue();
1774       }
1775       else if (aPName.IsEqual ("Y"))
1776       {
1777         aCenterY = aPValue.RealValue();
1778       }
1779       else if (aPName.IsEqual ("Z"))
1780       {
1781         aCenterZ = aPValue.RealValue();
1782       }
1783       else if (aPName.IsEqual ("DX"))
1784       {
1785         aDirX = aPValue.RealValue();
1786       }
1787       else if (aPName.IsEqual ("DY"))
1788       {
1789         aDirY = aPValue.RealValue();
1790       }
1791       else if (aPName.IsEqual ("DZ"))
1792       {
1793         aDirZ = aPValue.RealValue();
1794       }
1795       else if (aPName.IsEqual ("SX"))
1796       {
1797         aSizeX = aPValue.RealValue();
1798       }
1799       else if (aPName.IsEqual ("SY"))
1800       {
1801         aSizeY = aPValue.RealValue();
1802       }
1803     }
1804     else if (anArg.IsEqual ("NOUPDATE"))
1805     {
1806       isUpdate = Standard_False;
1807     }
1808   }
1809
1810   gp_Dir aDirection (aDirX, aDirY, aDirZ);
1811   gp_Pnt aCenterPnt (aCenterX, aCenterY, aCenterZ);
1812   aPlane->SetCenter (aCenterPnt);
1813   aPlane->SetComponent (new Geom_Plane (aCenterPnt, aDirection));
1814   aPlane->SetSize (aSizeX, aSizeY);
1815
1816   aContextAIS->Update (aPlane, isUpdate);
1817
1818   return 0;
1819 }
1820
1821 //==============================================================================
1822 // Fonction  vline
1823 // ---------------  Uniquement par parametre. Pas de selection dans le viewer.
1824 //==============================================================================
1825
1826 //==============================================================================
1827 //function : VLineBuilder
1828 //purpose  : Build an AIS_Line
1829 //Draw arg : vline LineName  [AIS_PointName] [AIS_PointName]
1830 //                           [Xa] [Ya] [Za]   [Xb] [Yb] [Zb]
1831 //==============================================================================
1832 #include <Geom_CartesianPoint.hxx>
1833 #include <AIS_Line.hxx>
1834
1835
1836 static int VLineBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1837 {
1838   if (argc == 4)   // parameters: AIS_Point AIS_Point
1839   {
1840     Handle(AIS_InteractiveObject) aShapeA, aShapeB;
1841     GetMapOfAIS().Find2 (argv[2], aShapeA);
1842     GetMapOfAIS().Find2 (argv[3], aShapeB);
1843     Handle(AIS_Point) anAISPointA = Handle(AIS_Point)::DownCast (aShapeA);
1844     Handle(AIS_Point) anAISPointB = Handle(AIS_Point)::DownCast (aShapeB);
1845     if (anAISPointA.IsNull()
1846      || anAISPointB.IsNull())
1847     {
1848       di << "vline error: wrong type of arguments\n";
1849       return 1;
1850     }
1851
1852     Handle(Geom_Point) aGeomPointBA = anAISPointA->Component();
1853     Handle(Geom_CartesianPoint) aCartPointA = Handle(Geom_CartesianPoint)::DownCast (aGeomPointBA);
1854
1855     Handle(Geom_Point) aGeomPointB = anAISPointB->Component();
1856     Handle(Geom_CartesianPoint) aCartPointB = Handle(Geom_CartesianPoint)::DownCast (aGeomPointB);
1857
1858     if (aCartPointB->X() == aCartPointA->X()
1859      && aCartPointB->Y() == aCartPointA->Y()
1860      && aCartPointB->Z() == aCartPointA->Z())
1861     {
1862       // B=A
1863       di << "vline error: same points\n";
1864       return 1;
1865     }
1866
1867     Handle(AIS_Line) anAISLine = new AIS_Line (aCartPointA, aCartPointB);
1868     GetMapOfAIS().Bind (anAISLine, argv[1]);
1869     TheAISContext()->Display (anAISLine, Standard_True);
1870   }
1871   else if (argc == 8) // parametres 6 reals
1872   {
1873     Standard_Real aCoord[6] = {};
1874     for (Standard_Integer i = 0; i <= 2; ++i)
1875     {
1876       aCoord[i]     = Draw::Atof (argv[2 + i]);
1877       aCoord[i + 3] = Draw::Atof (argv[5 + i]);
1878     }
1879
1880     Handle(Geom_CartesianPoint) aCartPointA = new Geom_CartesianPoint (aCoord[0], aCoord[1], aCoord[2]);
1881     Handle(Geom_CartesianPoint) aCartPointB = new Geom_CartesianPoint (aCoord[3], aCoord[4], aCoord[5]);
1882
1883     Handle(AIS_Line) anAISLine = new AIS_Line (aCartPointA, aCartPointB);
1884     GetMapOfAIS().Bind (anAISLine, argv[1]);
1885     TheAISContext()->Display (anAISLine, Standard_True);
1886
1887   }
1888   else if (argc == 2) // selection in 3D viewer
1889   {
1890     TopTools_ListOfShape aShapes;
1891     ViewerTest::GetSelectedShapes (aShapes);
1892     if (aShapes.Extent() != 2)
1893     {
1894       Message::SendFail ("Error: wrong number of selected shapes.");
1895       return 1;
1896     }
1897
1898     const TopoDS_Shape& aShapeA = aShapes.First();
1899     const TopoDS_Shape& aShapeB = aShapes.Last();
1900     if (aShapeA.ShapeType() != TopAbs_VERTEX
1901      || aShapeB.ShapeType() != TopAbs_VERTEX)
1902     {
1903       Message::SendFail ("Error: you should select two different vertex.");
1904       return 1;
1905     }
1906
1907     // Construction de la line
1908     gp_Pnt A = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
1909     gp_Pnt B = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
1910
1911     Handle(Geom_CartesianPoint) aCartPointA = new Geom_CartesianPoint (A);
1912     Handle(Geom_CartesianPoint) aCartPointB = new Geom_CartesianPoint (B);
1913
1914     Handle(AIS_Line) anAISLine = new AIS_Line (aCartPointA, aCartPointB);
1915     GetMapOfAIS().Bind (anAISLine, argv[1]);
1916     TheAISContext()->Display (anAISLine, Standard_True);
1917   }
1918   else
1919   {
1920     di << "Syntax error: wrong number of arguments";
1921     return 1;
1922   }
1923
1924   return 0;
1925 }
1926
1927 //==============================================================================
1928 // class   : FilledCircle
1929 // purpose : creates filled circle based on AIS_InteractiveObject 
1930 //           and Geom_Circle.
1931 //           This class is used to check method Matches() of class 
1932 //           Select3D_SensitiveCircle with member myFillStatus = Standard_True, 
1933 //           because none of AIS classes provides creation of 
1934 //           Select3D_SensitiveCircle with member myFillStatus = Standard_True 
1935 //           (look method ComputeSelection() )
1936 //============================================================================== 
1937
1938 Handle(Geom_Circle) CreateCircle(gp_Pnt theCenter, Standard_Real theRadius) 
1939 {
1940   gp_Ax2 anAxes(theCenter, gp_Dir(gp_Vec(0., 0., 1.))); 
1941   gp_Circ aCirc(anAxes, theRadius);
1942   Handle(Geom_Circle) aCircle = new Geom_Circle(aCirc);
1943   return aCircle;
1944 }
1945
1946 class FilledCircle : public AIS_InteractiveObject 
1947 {
1948 public:
1949   // CASCADE RTTI
1950   DEFINE_STANDARD_RTTI_INLINE(FilledCircle, AIS_InteractiveObject);
1951
1952   FilledCircle (gp_Pnt theCenter, Standard_Real theRadius);
1953   FilledCircle (Handle(Geom_Circle) theCircle);
1954
1955 private:
1956   TopoDS_Face ComputeFace();
1957
1958   // Virtual methods implementation
1959   virtual void Compute (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
1960                         const Handle(Prs3d_Presentation)& thePrs,
1961                         const Standard_Integer theMode) Standard_OVERRIDE;
1962
1963   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
1964                                  const Standard_Integer theMode) Standard_OVERRIDE;
1965
1966 protected:
1967
1968   Handle(Geom_Circle) myCircle;
1969   Standard_Boolean myFilledStatus;
1970
1971 }; 
1972
1973
1974 FilledCircle::FilledCircle(gp_Pnt theCenter, Standard_Real theRadius) 
1975 {
1976   myCircle = CreateCircle(theCenter, theRadius);
1977   myFilledStatus = Standard_True;
1978 }
1979
1980 FilledCircle::FilledCircle(Handle(Geom_Circle) theCircle) 
1981 {
1982   myCircle = theCircle;
1983   myFilledStatus = Standard_True;
1984 }
1985
1986 TopoDS_Face FilledCircle::ComputeFace() 
1987 {
1988   // Create edge from myCircle 
1989   BRepBuilderAPI_MakeEdge anEdgeMaker(myCircle->Circ());
1990   TopoDS_Edge anEdge = anEdgeMaker.Edge(); 
1991
1992   // Create wire from anEdge 
1993   BRepBuilderAPI_MakeWire aWireMaker(anEdge);
1994   TopoDS_Wire aWire = aWireMaker.Wire();
1995
1996   // Create face from aWire
1997   BRepBuilderAPI_MakeFace aFaceMaker(aWire);
1998   TopoDS_Face aFace = aFaceMaker.Face();
1999
2000   return aFace;
2001 }
2002
2003 void FilledCircle::Compute (const Handle(PrsMgr_PresentationManager)& ,
2004                             const Handle(Prs3d_Presentation)& thePrs,
2005                             const Standard_Integer theMode)
2006 {
2007   thePrs->Clear();
2008
2009   TopoDS_Face aFace = ComputeFace();
2010
2011   if (aFace.IsNull()) return;
2012   if (theMode != 0) return;
2013
2014   StdPrs_ShadedShape::Add (thePrs, aFace, myDrawer);
2015 }
2016
2017 void FilledCircle::ComputeSelection(const Handle(SelectMgr_Selection) &theSelection, 
2018                                     const Standard_Integer /*theMode*/)
2019 {
2020   Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
2021   Handle(Select3D_SensitiveCircle) aSensitiveCircle = new Select3D_SensitiveCircle (anEntityOwner, myCircle->Circ(), myFilledStatus);
2022   theSelection->Add(aSensitiveCircle);
2023 }
2024
2025 //==============================================================================
2026 // Fonction  vcircle
2027 // -----------------  Uniquement par parametre. Pas de selection dans le viewer.
2028 //==============================================================================
2029
2030 //==============================================================================
2031 //function : VCircleBuilder
2032 //purpose  : Build an AIS_Circle
2033 //Draw arg : vcircle CircleName PlaneName PointName Radius IsFilled
2034 //                              PointName PointName PointName IsFilled
2035 //==============================================================================
2036
2037 void DisplayCircle (Handle (Geom_Circle) theGeomCircle,
2038                     TCollection_AsciiString theName, 
2039                     Standard_Boolean isFilled) 
2040 {
2041   Handle(AIS_InteractiveObject) aCircle;
2042   if (isFilled) 
2043   {
2044     aCircle = new FilledCircle(theGeomCircle);
2045   }
2046   else
2047   {
2048     aCircle = new AIS_Circle(theGeomCircle);
2049     Handle(AIS_Circle)::DownCast (aCircle)->SetFilledCircleSens (Standard_False);
2050   }
2051
2052   // Check if there is an object with given name
2053   // and remove it from context
2054   if (GetMapOfAIS().IsBound2(theName)) 
2055   {
2056     Handle(AIS_InteractiveObject) anInterObj = GetMapOfAIS().Find2(theName);
2057     TheAISContext()->Remove(anInterObj, Standard_False);
2058     GetMapOfAIS().UnBind2(theName);
2059    }
2060
2061    // Bind the circle to its name
2062    GetMapOfAIS().Bind(aCircle, theName);
2063
2064    // Display the circle
2065    TheAISContext()->Display (aCircle, Standard_True);
2066   
2067 }
2068
2069 static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
2070 {
2071   if (argc > 6 || argc < 2)
2072   { 
2073     Message::SendFail ("Syntax error: wrong number of arguments");
2074     return 1;
2075   }
2076
2077   if (argc == 6) 
2078   {
2079     TCollection_AsciiString aName (argv[1]);
2080     Standard_Boolean isFilled = Draw::Atoi(argv[5]) != 0;
2081
2082     Handle(AIS_InteractiveObject) aShapeA, aShapeB;
2083     GetMapOfAIS().Find2 (argv[2], aShapeA);
2084     GetMapOfAIS().Find2 (argv[3], aShapeB);
2085
2086     // Arguments: AIS_Point AIS_Point AIS_Point
2087     if (!aShapeA.IsNull()
2088      && !aShapeB.IsNull()
2089      &&  aShapeA->Type() == AIS_KindOfInteractive_Datum
2090      &&  aShapeA->Signature() == 1)
2091     {
2092       Handle(AIS_InteractiveObject) aShapeC;
2093       GetMapOfAIS().Find2 (argv[4], aShapeC);
2094       Handle(AIS_Point) anAISPointA = Handle(AIS_Point)::DownCast (aShapeA);
2095       Handle(AIS_Point) anAISPointB = Handle(AIS_Point)::DownCast (aShapeB);
2096       Handle(AIS_Point) anAISPointC = Handle(AIS_Point)::DownCast (aShapeC);
2097       if (anAISPointA.IsNull()
2098        || anAISPointB.IsNull()
2099        || anAISPointC.IsNull())
2100       {
2101         Message::SendFail ("Error: arguments are expected to be points");
2102         return 1;
2103       }
2104
2105       // Verify that the three points are different
2106       Handle(Geom_CartesianPoint) aCartPointA = Handle(Geom_CartesianPoint)::DownCast (anAISPointA->Component());
2107       Handle(Geom_CartesianPoint) aCartPointB = Handle(Geom_CartesianPoint)::DownCast (anAISPointB->Component());
2108       Handle(Geom_CartesianPoint) aCartPointC = Handle(Geom_CartesianPoint)::DownCast (anAISPointC->Component());
2109       // Test A=B
2110       if (Abs(aCartPointA->X() - aCartPointB->X()) <= Precision::Confusion()
2111        && Abs(aCartPointA->Y() - aCartPointB->Y()) <= Precision::Confusion()
2112        && Abs(aCartPointA->Z() - aCartPointB->Z()) <= Precision::Confusion())
2113       {
2114         Message::SendFail ("Error: Same points");
2115         return 1;
2116       }
2117       // Test A=C
2118       if (Abs(aCartPointA->X() - aCartPointC->X()) <= Precision::Confusion()
2119        && Abs(aCartPointA->Y() - aCartPointC->Y()) <= Precision::Confusion()
2120        && Abs(aCartPointA->Z() - aCartPointC->Z()) <= Precision::Confusion())
2121       {
2122         Message::SendFail ("Error: Same points");
2123         return 1;
2124       }
2125       // Test B=C
2126       if (Abs(aCartPointB->X() - aCartPointC->X()) <= Precision::Confusion()
2127        && Abs(aCartPointB->Y() - aCartPointC->Y()) <= Precision::Confusion()
2128        && Abs(aCartPointB->Z() - aCartPointC->Z()) <= Precision::Confusion())
2129       {
2130         Message::SendFail ("Error: Same points");
2131         return 1;
2132       }
2133       // Construction of the circle
2134       GC_MakeCircle aCir = GC_MakeCircle (aCartPointA->Pnt(), aCartPointB->Pnt(), aCartPointC->Pnt());
2135       Handle (Geom_Circle) aGeomCircle;
2136       try
2137       {
2138         aGeomCircle = aCir.Value();
2139       }
2140       catch (StdFail_NotDone const&)
2141       {
2142         Message::SendFail ("Error: can't create circle");
2143         return 1;
2144       }
2145
2146       DisplayCircle (aGeomCircle, aName, isFilled);
2147     }
2148
2149     // Arguments: AIS_Plane AIS_Point Real
2150     else if (aShapeA->Type() == AIS_KindOfInteractive_Datum
2151           && aShapeA->Signature() == 7)
2152     {
2153       Handle(AIS_Plane) anAISPlane  = Handle(AIS_Plane)::DownCast (aShapeA);
2154       Handle(AIS_Point) anAISPointB = Handle(AIS_Point)::DownCast (aShapeB);
2155       if (anAISPointB.IsNull())
2156       {
2157         Message::SendFail ("Error: 2d element is a expected to be a point");
2158         return 1;
2159       }
2160
2161       // Check that the radius is >= 0
2162       const Standard_Real anR = Draw::Atof (argv[4]);
2163       if (anR <= 0)
2164       {
2165         Message::SendFail ("Syntax error: the radius must be >=0");
2166         return 1;
2167       }
2168
2169       // Recover the normal to the plane
2170       Handle(Geom_Plane) aGeomPlane  = anAISPlane->Component();
2171       Handle(Geom_Point) aGeomPointB = anAISPointB->Component();
2172       Handle(Geom_CartesianPoint) aCartPointB = Handle(Geom_CartesianPoint)::DownCast(aGeomPointB);
2173
2174       gp_Pln aGpPlane = aGeomPlane->Pln();
2175       gp_Ax1 aGpAxe = aGpPlane.Axis();
2176       gp_Dir aDir = aGpAxe.Direction();
2177       gp_Pnt aCenter = aCartPointB->Pnt();
2178       GC_MakeCircle aCir = GC_MakeCircle (aCenter, aDir, anR);
2179       Handle(Geom_Circle) aGeomCircle;
2180       try
2181       {
2182         aGeomCircle = aCir.Value();
2183       }
2184       catch (StdFail_NotDone const&)
2185       {
2186         Message::SendFail ("Error: can't create circle");
2187         return 1;
2188       }
2189
2190       DisplayCircle (aGeomCircle, aName, isFilled);
2191     }
2192     else
2193     {
2194       Message::SendFail ("Error: 1st argument has an unexpected type");
2195       return 1;
2196     }
2197   }
2198   else // No arguments: selection in the viewer
2199   {
2200     // Get the name of the circle 
2201     TCollection_AsciiString aName (argv[1]);
2202
2203     TopTools_ListOfShape aShapes;
2204     ViewerTest::GetSelectedShapes (aShapes);
2205     if (aShapes.Extent() != 3 && aShapes.Extent() != 2)
2206     {
2207       Message::SendFail ("Error: Wrong number of selected shapes.");
2208       return 1;
2209     }
2210
2211     const TopoDS_Shape& aShapeA = aShapes.First();
2212     if (aShapeA.ShapeType() == TopAbs_VERTEX)
2213     {
2214       if (aShapes.Extent() != 3)
2215       {
2216         Message::SendFail ("Error: wrong number of selected shapes.");
2217         return 1;
2218       }
2219
2220       TopTools_ListOfShape::Iterator anIter (aShapes);
2221
2222       anIter.Next();
2223       const TopoDS_Shape& aShapeB = anIter.Value();
2224
2225       anIter.Next();
2226       const TopoDS_Shape& aShapeC = anIter.Value();
2227       
2228       // Get isFilled
2229       Standard_Boolean isFilled;
2230       std::cout << "Enter filled status (0 or 1)\n";
2231       std::cin >> isFilled;
2232
2233       // Construction of the circle
2234       gp_Pnt A = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
2235       gp_Pnt B = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
2236       gp_Pnt C = BRep_Tool::Pnt (TopoDS::Vertex (aShapeC));
2237
2238       GC_MakeCircle aCir = GC_MakeCircle (A, B, C);
2239       Handle(Geom_Circle) aGeomCircle;
2240       try
2241       {
2242         aGeomCircle = aCir.Value();
2243       }
2244       catch (StdFail_NotDone const&)
2245       {
2246         Message::SendFail ("Error: can't create circle");
2247         return 1;
2248       }
2249
2250       DisplayCircle (aGeomCircle, aName, isFilled);
2251     }
2252     else if (aShapeA.ShapeType() == TopAbs_FACE)
2253     {
2254       const TopoDS_Shape& aShapeB = aShapes.Last();
2255
2256       // Recover the radius 
2257       Standard_Real aRad = 0.0;
2258       do
2259       {
2260         std::cout << " Enter the value of the radius:\n";
2261         std::cin >> aRad;
2262       } while (aRad <= 0);
2263
2264       // Get filled status
2265       Standard_Boolean isFilled;
2266       std::cout << "Enter filled status (0 or 1)\n";
2267       std::cin >> isFilled;
2268
2269       // Recover the normal to the plane. tag
2270       TopoDS_Face aFace = TopoDS::Face (aShapeA);
2271       BRepAdaptor_Surface aSurface (aFace, Standard_False);
2272       gp_Pln aPlane = aSurface.Plane();
2273       Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
2274       gp_Pln aGpPlane = aGeomPlane->Pln();
2275       gp_Ax1 aGpAxe = aGpPlane.Axis();
2276       gp_Dir aDir = aGpAxe.Direction();
2277
2278       // Recover the center
2279       gp_Pnt aCenter = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
2280
2281       // Construct the circle
2282       GC_MakeCircle aCir = GC_MakeCircle (aCenter, aDir, aRad);
2283       Handle(Geom_Circle) aGeomCircle;
2284       try
2285       {
2286         aGeomCircle = aCir.Value();
2287       }
2288       catch (StdFail_NotDone const&)
2289       {
2290         Message::SendFail ("Error: can't create circle");
2291         return 1;
2292       }
2293
2294       DisplayCircle (aGeomCircle, aName, isFilled);
2295     }
2296     else
2297     {
2298       Message::SendFail ("Error: You should select face and vertex or three vertices.");
2299       return 1;
2300     }
2301   }
2302
2303   return 0;
2304 }
2305
2306 //=======================================================================
2307 //function : VDrawText
2308 //purpose  :
2309 //=======================================================================
2310 static int VDrawText (Draw_Interpretor& theDI,
2311                       Standard_Integer  theArgsNb,
2312                       const char**      theArgVec)
2313 {
2314   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
2315   if (theArgsNb < 3)
2316   {
2317     Message::SendFail ("Syntax error: wrong number of arguments. See usage:");
2318     theDI.PrintHelp (theArgVec[0]);
2319     return 1;
2320   }
2321   else if (aContext.IsNull())
2322   {
2323     Message::SendFail ("Error: no active viewer");
2324     return 1;
2325   }
2326
2327   Standard_Integer           anArgIt = 1;
2328   TCollection_ExtendedString aName (theArgVec[anArgIt++], Standard_True);
2329   TCollection_ExtendedString aText (theArgVec[anArgIt++], Standard_True);
2330   Handle(AIS_TextLabel)      aTextPrs;
2331   ViewerTest_AutoUpdater     anAutoUpdater (aContext, ViewerTest::CurrentView());
2332
2333   Standard_Boolean isNewPrs = Standard_False;
2334   if (GetMapOfAIS().IsBound2 (aName))
2335   {
2336     aTextPrs = Handle(AIS_TextLabel)::DownCast (GetMapOfAIS().Find2 (aName));
2337   }
2338
2339   if (aTextPrs.IsNull())
2340   {
2341     isNewPrs = Standard_True;
2342     aTextPrs = new AIS_TextLabel();
2343     aTextPrs->SetFont ("Courier");
2344   }
2345
2346   aTextPrs->SetText (aText);
2347
2348   Handle(Graphic3d_TransformPers) aTrsfPers;
2349   Aspect_TypeOfDisplayText aDisplayType = Aspect_TODT_NORMAL;
2350
2351   Standard_Boolean aHasPlane = Standard_False;
2352   gp_Dir           aNormal;
2353   gp_Dir           aDirection;
2354   gp_Pnt           aPos;
2355
2356
2357   Handle(Font_TextFormatter) aTextFormatter;
2358   for (; anArgIt < theArgsNb; ++anArgIt)
2359   {
2360     TCollection_AsciiString aParam (theArgVec[anArgIt]);
2361     aParam.LowerCase();
2362
2363     if (anAutoUpdater.parseRedrawMode (aParam))
2364     {
2365       continue;
2366     }
2367     else if (aParam == "-pos"
2368           || aParam == "-position")
2369     {
2370       if (anArgIt + 3 >= theArgsNb)
2371       {
2372         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
2373         return 1;
2374       }
2375
2376       aPos.SetX (Draw::Atof (theArgVec[++anArgIt]));
2377       aPos.SetY (Draw::Atof (theArgVec[++anArgIt]));
2378       aPos.SetZ (Draw::Atof (theArgVec[++anArgIt]));
2379       aTextPrs->SetPosition (aPos);
2380     }
2381     else if (aParam == "-color")
2382     {
2383       Quantity_Color aColor;
2384       Standard_Integer aNbParsed = Draw::ParseColor (theArgsNb - anArgIt - 1,
2385                                                      theArgVec + anArgIt + 1,
2386                                                      aColor);
2387       if (aNbParsed == 0)
2388       {
2389         Message::SendFail() << "Syntax error at '" << aParam << "'";
2390         return 1;
2391       }
2392       anArgIt += aNbParsed;
2393       aTextPrs->SetColor (aColor);
2394     }
2395     else if (aParam == "-halign")
2396     {
2397       if (++anArgIt >= theArgsNb)
2398       {
2399         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam.ToCString() << "'";
2400         return 1;
2401       }
2402
2403       TCollection_AsciiString aType (theArgVec[anArgIt]);
2404       aType.LowerCase();
2405       if (aType == "left")
2406       {
2407         aTextPrs->SetHJustification (Graphic3d_HTA_LEFT);
2408       }
2409       else if (aType == "center")
2410       {
2411         aTextPrs->SetHJustification (Graphic3d_HTA_CENTER);
2412       }
2413       else if (aType == "right")
2414       {
2415         aTextPrs->SetHJustification (Graphic3d_HTA_RIGHT);
2416       }
2417       else
2418       {
2419         Message::SendFail() << "Syntax error at '" << aParam << "'";
2420         return 1;
2421       }
2422     }
2423     else if (aParam == "-valign")
2424     {
2425       if (++anArgIt >= theArgsNb)
2426       {
2427         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2428         return 1;
2429       }
2430
2431       TCollection_AsciiString aType (theArgVec[anArgIt]);
2432       aType.LowerCase();
2433       if (aType == "top")
2434       {
2435         aTextPrs->SetVJustification (Graphic3d_VTA_TOP);
2436       }
2437       else if (aType == "center")
2438       {
2439         aTextPrs->SetVJustification (Graphic3d_VTA_CENTER);
2440       }
2441       else if (aType == "bottom")
2442       {
2443         aTextPrs->SetVJustification (Graphic3d_VTA_BOTTOM);
2444       }
2445       else if (aType == "topfirstline")
2446       {
2447         aTextPrs->SetVJustification (Graphic3d_VTA_TOPFIRSTLINE);
2448       }
2449       else
2450       {
2451         Message::SendFail() << "Syntax error at '" << aParam << "'";
2452         return 1;
2453       }
2454     }
2455     else if (aParam == "-angle")
2456     {
2457       if (++anArgIt >= theArgsNb)
2458       {
2459         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2460         return 1;
2461       }
2462
2463       aTextPrs->SetAngle (Draw::Atof (theArgVec[anArgIt]) * (M_PI / 180.0));
2464     }
2465     else if (aParam == "-zoom")
2466     {
2467       if (++anArgIt >= theArgsNb)
2468       {
2469         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2470         return 1;
2471       }
2472
2473       aTextPrs->SetZoomable (Draw::Atoi (theArgVec[anArgIt]) == 1);
2474     }
2475     else if (aParam == "-height")
2476     {
2477       if (++anArgIt >= theArgsNb)
2478       {
2479         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2480         return 1;
2481       }
2482
2483       aTextPrs->SetHeight (Draw::Atof(theArgVec[anArgIt]));
2484     }
2485     else if (aParam == "-wrapping")
2486     {
2487       if (++anArgIt >= theArgsNb)
2488       {
2489         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2490         return 1;
2491       }
2492
2493       if (aTextFormatter.IsNull())
2494       {
2495         aTextFormatter = new Font_TextFormatter();
2496       }
2497       aTextFormatter->SetWrapping ((Standard_ShortReal)Draw::Atof(theArgVec[anArgIt]));
2498     }
2499     else if (aParam == "-aspect")
2500     {
2501       if (++anArgIt >= theArgsNb)
2502       {
2503         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2504         return 1;
2505       }
2506
2507       TCollection_AsciiString anOption (theArgVec[anArgIt]);
2508       anOption.LowerCase();
2509       Font_FontAspect aFontAspect = Font_FA_Undefined;
2510       if (!parseFontStyle (anOption, aFontAspect))
2511       {
2512         Message::SendFail() << "Syntax error: unknown font aspect '" << anOption << "'";
2513         return 1;
2514       }
2515       aTextPrs->SetFontAspect (aFontAspect);
2516     }
2517     else if (aParam == "-font")
2518     {
2519       if (++anArgIt >= theArgsNb)
2520       {
2521         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2522         return 1;
2523       }
2524
2525       aTextPrs->SetFont (theArgVec[anArgIt]);
2526     }
2527     else if (aParam == "-plane")
2528     {
2529       if (anArgIt + 6 >= theArgsNb)
2530       {
2531         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2532         return 1;
2533       }
2534
2535       Standard_Real aX = Draw::Atof (theArgVec[++anArgIt]);
2536       Standard_Real aY = Draw::Atof (theArgVec[++anArgIt]);
2537       Standard_Real aZ = Draw::Atof (theArgVec[++anArgIt]);
2538       aNormal.SetCoord (aX, aY, aZ);
2539
2540       aX = Draw::Atof (theArgVec[++anArgIt]);
2541       aY = Draw::Atof (theArgVec[++anArgIt]);
2542       aZ = Draw::Atof (theArgVec[++anArgIt]);
2543       aDirection.SetCoord (aX, aY, aZ);
2544
2545       aHasPlane = Standard_True;
2546     }
2547     else if (aParam == "-flipping")
2548     {
2549       aTextPrs->SetFlipping (Standard_True);
2550     }
2551     else if (aParam == "-ownanchor")
2552     {
2553       if (++anArgIt >= theArgsNb)
2554       {
2555         std::cout << "Error: wrong number of values for parameter '" << aParam.ToCString() << "'.\n";
2556         return 1;
2557       }
2558       aTextPrs->SetOwnAnchorPoint (Draw::Atoi (theArgVec[anArgIt]) == 1);
2559     }
2560     else if (aParam == "-disptype"
2561           || aParam == "-displaytype")
2562     {
2563       if (++anArgIt >= theArgsNb)
2564       {
2565         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2566         return 1;
2567       }
2568       TCollection_AsciiString aType (theArgVec[anArgIt]);
2569       aType.LowerCase();
2570       if (aType == "subtitle")
2571         aDisplayType = Aspect_TODT_SUBTITLE;
2572       else if (aType == "decal")
2573         aDisplayType = Aspect_TODT_DEKALE;
2574       else if (aType == "blend")
2575         aDisplayType = Aspect_TODT_BLEND;
2576       else if (aType == "dimension")
2577         aDisplayType = Aspect_TODT_DIMENSION;
2578       else if (aType == "normal")
2579         aDisplayType = Aspect_TODT_NORMAL;
2580       else if (aType == "shadow")
2581         aDisplayType = Aspect_TODT_SHADOW;
2582       else
2583       {
2584         Message::SendFail() << "Syntax error: wrong display type '" << aType << "'";
2585         return 1;
2586       }
2587     }
2588     else if (aParam == "-subcolor"
2589           || aParam == "-subtitlecolor")
2590     {
2591       Quantity_Color aColor;
2592       Standard_Integer aNbParsed = Draw::ParseColor (theArgsNb - anArgIt - 1,
2593                                                      theArgVec + anArgIt + 1,
2594                                                      aColor);
2595       if (aNbParsed == 0)
2596       {
2597         Message::SendFail() << "Syntax error at '" << aParam << "'";
2598         return 1;
2599       }
2600       anArgIt += aNbParsed;
2601       aTextPrs->SetColorSubTitle (aColor);
2602     }
2603     else if (aParam == "-2d")
2604     {
2605       aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_2d);
2606     }
2607     else if (aParam == "-trsfperspos"
2608           || aParam == "-perspos")
2609     {
2610       if (anArgIt + 2 >= theArgsNb)
2611       {
2612         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'.";
2613         return 1;
2614       }
2615
2616       TCollection_AsciiString aX (theArgVec[++anArgIt]);
2617       TCollection_AsciiString aY (theArgVec[++anArgIt]);
2618       TCollection_AsciiString aZ = "0";
2619       if (!aX.IsIntegerValue()
2620        || !aY.IsIntegerValue())
2621       {
2622         Message::SendFail() << "Error: wrong syntax at '" << aParam << "'.";
2623         return 1;
2624       }
2625       if (anArgIt + 1 < theArgsNb)
2626       {
2627         TCollection_AsciiString aTemp = theArgVec[anArgIt + 1];
2628         if (aTemp.IsIntegerValue())
2629         {
2630           aZ = aTemp;
2631           ++anArgIt;
2632         }
2633       }
2634
2635       Standard_Integer aCorner = Aspect_TOTP_CENTER;
2636       if      (aX.IntegerValue() > 0.0) { aCorner |= Aspect_TOTP_RIGHT; }
2637       else if (aX.IntegerValue() < 0.0) { aCorner |= Aspect_TOTP_LEFT; }
2638       if      (aY.IntegerValue() > 0.0) { aCorner |= Aspect_TOTP_TOP; }
2639       else if (aY.IntegerValue() < 0.0) { aCorner |= Aspect_TOTP_BOTTOM; }
2640       aTrsfPers = new Graphic3d_TransformPers (aTrsfPers->Mode(), Aspect_TypeOfTriedronPosition (aCorner), Graphic3d_Vec2i (aZ.IntegerValue()));
2641     }
2642     else
2643     {
2644       Message::SendFail() << "Syntax error: unknown argument '" << aParam << "'";
2645       return 1;
2646     }
2647   }
2648
2649   aTextPrs->SetTextFormatter (aTextFormatter);
2650
2651   if (aHasPlane)
2652   {
2653     aTextPrs->SetOrientation3D (gp_Ax2 (aPos, aNormal, aDirection));
2654   }
2655
2656   aTextPrs->SetDisplayType (aDisplayType);
2657
2658   if (!aTrsfPers.IsNull())
2659   {
2660     aContext->SetTransformPersistence (aTextPrs, aTrsfPers);
2661     aTextPrs->SetZLayer(Graphic3d_ZLayerId_TopOSD);
2662     if (aTextPrs->Position().Z() != 0)
2663     {
2664       aTextPrs->SetPosition (gp_Pnt(aTextPrs->Position().X(), aTextPrs->Position().Y(), 0));
2665     }
2666   }
2667   else if (!aTextPrs->TransformPersistence().IsNull())
2668   {
2669     aContext->SetTransformPersistence (aTextPrs, Handle(Graphic3d_TransformPers)());
2670   }
2671
2672   if (isNewPrs)
2673   {
2674     ViewerTest::Display (aName, aTextPrs, Standard_False);
2675   }
2676   else
2677   {
2678     aContext->Redisplay (aTextPrs, Standard_False, Standard_True);
2679   }
2680   return 0;
2681 }
2682
2683 #include <math.h>
2684 #include <gp_Pnt.hxx>
2685 #include <Graphic3d_ArrayOfPoints.hxx>
2686 #include <Graphic3d_ArrayOfPrimitives.hxx>
2687 #include <Graphic3d_ArrayOfTriangles.hxx>
2688 #include <Poly_Array1OfTriangle.hxx>
2689 #include <Poly_Triangle.hxx>
2690 #include <Poly_Triangulation.hxx>
2691 #include <TColgp_Array1OfPnt.hxx>
2692 #include <TShort_Array1OfShortReal.hxx>
2693 #include <TShort_HArray1OfShortReal.hxx>
2694
2695 #include <AIS_Triangulation.hxx>
2696 #include <StdPrs_ToolTriangulatedShape.hxx>
2697 #include <Poly_Connect.hxx>
2698 #include <TColgp_Array1OfDir.hxx>
2699 #include <Graphic3d_GraphicDriver.hxx>
2700
2701 #include <TColStd_Array1OfInteger.hxx>
2702 #include <TColStd_HArray1OfInteger.hxx>
2703 #include <Prs3d_ShadingAspect.hxx>
2704 #include <Graphic3d_MaterialAspect.hxx>
2705 #include <Graphic3d_AspectFillArea3d.hxx>
2706
2707 #include <BRepPrimAPI_MakeCylinder.hxx>
2708 #include <TopoDS_Shape.hxx>
2709 #include <TopExp_Explorer.hxx>
2710 #include <TopAbs.hxx>
2711 #include <AIS_InteractiveObject.hxx>
2712
2713
2714 //===============================================================================================
2715 //function : CalculationOfSphere
2716 //author   : psn
2717 //purpose  : Create a Sphere
2718 //===============================================================================================
2719
2720 Handle( Poly_Triangulation ) CalculationOfSphere( double X , double Y , double Z ,
2721                                                   int res ,
2722                                                   double Radius ){
2723   double mRadius = Radius;
2724   double mCenter[3] = {X,Y,Z};
2725   int mThetaResolution;
2726   int mPhiResolution;
2727   double mStartTheta = 0;//StartTheta;
2728   double mEndTheta = 360;//EndTheta;
2729   double mStartPhi = 0;//StartPhi;
2730   double mEndPhi = 180;//EndPhi;
2731   res = res < 4 ? 4 : res;
2732
2733   mThetaResolution = res;
2734   mPhiResolution = res;
2735
2736   int i, j;
2737   int jStart, jEnd, numOffset;
2738   double x[3], n[3], deltaPhi, deltaTheta, phi, theta, radius;
2739   double startTheta, endTheta, startPhi, endPhi;
2740   int base, numPoles=0, thetaResolution, phiResolution;
2741
2742   int pts[3];
2743   int piece = -1;
2744   int numPieces = 1;
2745   if ( numPieces > mThetaResolution ) {
2746     numPieces = mThetaResolution;
2747   }
2748
2749   int localThetaResolution =  mThetaResolution;
2750   double localStartTheta =  mStartTheta;
2751   double localEndTheta =  mEndTheta;
2752
2753   while ( localEndTheta < localStartTheta ) {
2754     localEndTheta += 360.0;
2755   }
2756
2757   deltaTheta = (localEndTheta - localStartTheta) / localThetaResolution;
2758
2759   // Change the ivars based on pieces.
2760   int start, end;
2761   start = piece * localThetaResolution / numPieces;
2762   end = (piece+1) * localThetaResolution / numPieces;
2763   localEndTheta = localStartTheta + (double)(end) * deltaTheta;
2764   localStartTheta = localStartTheta + (double)(start) * deltaTheta;
2765   localThetaResolution = end - start;
2766
2767   // Create north pole if needed
2768   int number_point = 0;
2769   int number_pointArray = 0;
2770
2771   if ( mStartPhi <= 0.0 ) {
2772     number_pointArray++;
2773     numPoles++;
2774   }
2775   if ( mEndPhi >= 180.0 ) {
2776     number_pointArray++;
2777     numPoles++;
2778   }
2779
2780   // Check data, determine increments, and convert to radians
2781   startTheta = (localStartTheta < localEndTheta ? localStartTheta : localEndTheta);
2782   startTheta *= M_PI  / 180.0;
2783   endTheta = (localEndTheta > localStartTheta ? localEndTheta : localStartTheta);
2784   endTheta *= M_PI  / 180.0;
2785
2786
2787   startPhi = ( mStartPhi <  mEndPhi ?  mStartPhi :  mEndPhi);
2788   startPhi *= M_PI  / 180.0;
2789   endPhi = ( mEndPhi >  mStartPhi ?  mEndPhi :  mStartPhi);
2790   endPhi *= M_PI  / 180.0;
2791
2792   phiResolution =  mPhiResolution - numPoles;
2793   deltaPhi = (endPhi - startPhi) / ( mPhiResolution - 1);
2794   thetaResolution = localThetaResolution;
2795   if ( fabs(localStartTheta - localEndTheta) < 360.0 ) {
2796     ++localThetaResolution;
2797   }
2798   deltaTheta = (endTheta - startTheta) / thetaResolution;
2799
2800   jStart = ( mStartPhi <= 0.0 ? 1 : 0);
2801   jEnd = ( mEndPhi >= 180.0 ?  mPhiResolution - 1 :  mPhiResolution);
2802
2803   // Create intermediate points
2804   for ( i = 0; i < localThetaResolution; i++ ) {
2805     for ( j = jStart; j < jEnd; j++ ) {
2806         number_pointArray++;
2807     }
2808   }
2809
2810   //Generate mesh connectivity
2811   base = phiResolution * localThetaResolution;
2812
2813   int number_triangle = 0 ;
2814   if ( mStartPhi <= 0.0 ) { // around north pole
2815     number_triangle += localThetaResolution;
2816   }
2817
2818   if ( mEndPhi >= 180.0 ) { // around south pole
2819     number_triangle += localThetaResolution;
2820   }
2821
2822   // bands in-between poles
2823   for ( i=0; i < localThetaResolution; i++){
2824     for ( j=0; j < (phiResolution-1); j++){
2825        number_triangle +=2;
2826     }
2827   }
2828
2829   Handle(Poly_Triangulation) polyTriangulation = new Poly_Triangulation (number_pointArray, number_triangle, false, true);
2830
2831   if (  mStartPhi <= 0.0 ){
2832       x[0] =  mCenter[0];
2833       x[1] =  mCenter[1];
2834       x[2] =  mCenter[2] +  mRadius;
2835       polyTriangulation->SetNode (1, gp_Pnt (x[0],x[1],x[2]));
2836   }
2837
2838   // Create south pole if needed
2839   if (  mEndPhi >= 180.0 ){
2840       x[0] =  mCenter[0];
2841       x[1] =  mCenter[1];
2842       x[2] =  mCenter[2] -  mRadius;
2843       polyTriangulation->SetNode (2, gp_Pnt (x[0],x[1],x[2]));
2844   }
2845
2846   number_point = 3;
2847   for ( i=0; i < localThetaResolution; i++){
2848     theta = localStartTheta * M_PI / 180.0 + i*deltaTheta;
2849     for ( j = jStart; j < jEnd; j++){
2850         phi = startPhi + j*deltaPhi;
2851         radius =  mRadius * sin((double)phi);
2852         n[0] = radius * cos((double)theta);
2853         n[1] = radius * sin((double)theta);
2854         n[2] =  mRadius * cos((double)phi);
2855         x[0] = n[0] +  mCenter[0];
2856         x[1] = n[1] +  mCenter[1];
2857         x[2] = n[2] +  mCenter[2];
2858         polyTriangulation->SetNode (number_point, gp_Pnt (x[0],x[1],x[2]));
2859         number_point++;
2860       }
2861     }
2862
2863   numPoles = 3;
2864   number_triangle = 1;
2865   if ( mStartPhi <= 0.0 ){// around north pole
2866     for (i=0; i < localThetaResolution; i++){
2867         pts[0] = phiResolution*i + numPoles;
2868         pts[1] = (phiResolution*(i+1) % base) + numPoles;
2869         pts[2] = 1;
2870         polyTriangulation->SetTriangle (number_triangle, Poly_Triangle (pts[0],pts[1],pts[2]));
2871         number_triangle++;
2872       }
2873     }
2874
2875   if (  mEndPhi >= 180.0 ){ // around south pole
2876     numOffset = phiResolution - 1 + numPoles;
2877     for (i=0; i < localThetaResolution; i++){
2878         pts[0] = phiResolution*i + numOffset;
2879         pts[2] = ((phiResolution*(i+1)) % base) + numOffset;
2880         pts[1] = numPoles - 1;
2881         polyTriangulation->SetTriangle (number_triangle, Poly_Triangle (pts[0],pts[1],pts[2]));
2882         number_triangle++;
2883       }
2884     }
2885
2886   // bands in-between poles
2887
2888   for (i=0; i < localThetaResolution; i++){
2889     for (j=0; j < (phiResolution-1); j++){
2890         pts[0] = phiResolution*i + j + numPoles;
2891         pts[1] = pts[0] + 1;
2892         pts[2] = ((phiResolution*(i+1)+j) % base) + numPoles + 1;
2893         polyTriangulation->SetTriangle (number_triangle, Poly_Triangle (pts[0],pts[1],pts[2]));
2894         number_triangle++;
2895         pts[1] = pts[2];
2896         pts[2] = pts[1] - 1;
2897         polyTriangulation->SetTriangle (number_triangle, Poly_Triangle (pts[0],pts[1],pts[2]));
2898         number_triangle++;
2899       }
2900     }
2901
2902   Poly_Connect pc (polyTriangulation);
2903
2904   Standard_Integer index[3];
2905   Standard_Real Tol = Precision::Confusion();
2906
2907   gp_Dir Nor;
2908   for (i = 1; i <= polyTriangulation->NbNodes(); i++)
2909   {
2910     gp_XYZ eqPlan(0, 0, 0);
2911     for (pc.Initialize (i); pc.More(); pc.Next())
2912     {
2913       polyTriangulation->Triangle (pc.Value()).Get (index[0], index[1], index[2]);
2914       gp_XYZ v1 (polyTriangulation->Node (index[1]).Coord() - polyTriangulation->Node (index[0]).Coord());
2915       gp_XYZ v2 (polyTriangulation->Node (index[2]).Coord() - polyTriangulation->Node (index[1]).Coord());
2916       gp_XYZ vv = v1^v2;
2917       Standard_Real mod = vv.Modulus();
2918       if(mod < Tol) continue;
2919       eqPlan += vv/mod;
2920     }
2921
2922     Standard_Real modmax = eqPlan.Modulus();
2923     if(modmax > Tol)
2924       Nor = gp_Dir(eqPlan);
2925     else
2926       Nor = gp_Dir(0., 0., 1.);
2927
2928     polyTriangulation->SetNormal (i, Nor.XYZ());
2929   }
2930
2931   return polyTriangulation;
2932 }
2933
2934 //===============================================================================================
2935 //function : VDrawSphere
2936 //author   : psn
2937 //purpose  : Create an AIS shape.
2938 //===============================================================================================
2939 static int VDrawSphere (Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
2940 {
2941   // check for errors
2942   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
2943   if (aContextAIS.IsNull())
2944   {
2945     Message::SendFail ("Error: no active viewer");
2946     return 1;
2947   }
2948   else if (argc < 3)
2949   {
2950     Message::SendFail() << "Syntax error: wrong number of arguments.\n"
2951                         << "Use: " << argv[0] << " shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToShowEdges=0]";
2952     return 1;
2953   }
2954
2955   // read the arguments
2956   TCollection_AsciiString aShapeName (argv[1]);
2957   Standard_Integer aResolution = Draw::Atoi (argv[2]);
2958   Standard_Real aCenterX = (argc > 5) ? Draw::Atof (argv[3]) : 0.0;
2959   Standard_Real aCenterY = (argc > 5) ? Draw::Atof (argv[4]) : 0.0;
2960   Standard_Real aCenterZ = (argc > 5) ? Draw::Atof (argv[5]) : 0.0;
2961   Standard_Real aRadius =  (argc > 6) ? Draw::Atof (argv[6]) : 100.0;
2962   Standard_Boolean toShowEdges = (argc > 7) ? Draw::Atoi (argv[7]) == 1 : Standard_False;
2963   Standard_Boolean toPrintInfo = (argc > 8) ? Draw::Atoi (argv[8]) == 1 : Standard_True;
2964
2965   // remove AIS object with given name from map
2966   VDisplayAISObject (aShapeName, Handle(AIS_InteractiveObject)());
2967
2968   if (toPrintInfo)
2969     std::cout << "Compute Triangulation...\n";
2970   Handle(AIS_Triangulation) aShape
2971     = new AIS_Triangulation (CalculationOfSphere (aCenterX, aCenterY, aCenterZ,
2972                                                   aResolution,
2973                                                   aRadius));
2974   const Standard_Integer aNumberPoints    = aShape->GetTriangulation()->NbNodes();
2975   const Standard_Integer aNumberTriangles = aShape->GetTriangulation()->NbTriangles();
2976
2977   // stupid initialization of Green color in RGBA space as integer
2978   // probably wrong for big-endian CPUs
2979   const Graphic3d_Vec4ub aColor (0, 255, 0, 0);
2980
2981   // setup colors array per vertex
2982   Handle(TColStd_HArray1OfInteger) aColorArray = new TColStd_HArray1OfInteger (1, aNumberPoints);
2983   for (Standard_Integer aNodeId = 1; aNodeId <= aNumberPoints; ++aNodeId)
2984   {
2985     aColorArray->SetValue (aNodeId, *reinterpret_cast<const Standard_Integer*> (aColor.GetData()));
2986   }
2987   aShape->SetColors (aColorArray);
2988
2989   // show statistics
2990   Standard_Integer aPointsSize      = aNumberPoints * 3 * sizeof(float);  // 3x GLfloat
2991   Standard_Integer aNormalsSize     = aNumberPoints * 3 * sizeof(float);  // 3x GLfloat
2992   Standard_Integer aColorsSize      = aNumberPoints * 3 * sizeof(float);  // 3x GLfloat without alpha
2993   Standard_Integer aTrianglesSize   = aNumberTriangles * 3 * sizeof(int); // 3x GLint
2994   Standard_Integer aPolyConnectSize = aNumberPoints * 4 + aNumberTriangles * 6 * 4;
2995   Standard_Integer aTotalSize       = aPointsSize + aNormalsSize + aColorsSize + aTrianglesSize;
2996   aTotalSize >>= 20; //MB
2997   aNormalsSize >>= 20;
2998   aColorsSize >>= 20;
2999   aTrianglesSize >>= 20;
3000   aPolyConnectSize >>= 20;
3001   if (toPrintInfo)
3002   {
3003     std::cout << "NumberOfPoints:    " << aNumberPoints << "\n"
3004       << "NumberOfTriangles: " << aNumberTriangles << "\n"
3005       << "Amount of memory required for PolyTriangulation without Normals: " << (aTotalSize - aNormalsSize) << " Mb\n"
3006       << "Amount of memory for colors: " << aColorsSize << " Mb\n"
3007       << "Amount of memory for PolyConnect: " << aPolyConnectSize << " Mb\n"
3008       << "Amount of graphic card memory required: " << aTotalSize << " Mb\n";
3009   }
3010
3011   // Setting material properties, very important for desirable visual result!
3012   Graphic3d_MaterialAspect aMat (Graphic3d_NameOfMaterial_Plastified);
3013   aMat.SetAmbientColor (Quantity_Color (Graphic3d_Vec3 (0.04f)));
3014   aMat.SetSpecularColor(Quantity_Color (Graphic3d_Vec3 (0.50f)));
3015   Handle(Graphic3d_AspectFillArea3d) anAspect
3016     = new Graphic3d_AspectFillArea3d (Aspect_IS_SOLID,
3017                                       Quantity_NOC_WHITE,
3018                                       Quantity_NOC_YELLOW,
3019                                       Aspect_TOL_SOLID,
3020                                       1.0,
3021                                       aMat,
3022                                       aMat);
3023   Handle(Prs3d_ShadingAspect) aShAsp = new Prs3d_ShadingAspect();
3024   anAspect->SetDrawEdges (toShowEdges);
3025   aShAsp->SetAspect (anAspect);
3026   aShape->Attributes()->SetShadingAspect (aShAsp);
3027
3028   VDisplayAISObject (aShapeName, aShape);
3029   return 0;
3030 }
3031
3032 //=============================================================================
3033 //function : VComputeHLR
3034 //purpose  :
3035 //=============================================================================
3036
3037 static int VComputeHLR (Draw_Interpretor& ,
3038                         Standard_Integer theArgNb,
3039                         const char** theArgVec)
3040 {
3041   TCollection_AsciiString aShapeName, aHlrName;
3042   TopoDS_Shape aSh;
3043   gp_Pnt anEye;
3044   gp_Dir aDir;
3045   gp_Ax2 aProjAx;
3046   bool hasViewDirArg = false;
3047   Prs3d_TypeOfHLR anAlgoType = Prs3d_TOH_PolyAlgo;
3048   bool toShowCNEdges = false, toShowHiddenEdges = false;
3049   int aNbIsolines = 0;
3050   if (Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext())
3051   {
3052     gp_Dir aRight;
3053     Handle(V3d_View) aView = ViewerTest::CurrentView();
3054     Standard_Integer aWidth, aHeight;
3055     Standard_Real aCentX, aCentY, aCentZ, aDirX, aDirY, aDirZ;
3056     Standard_Real aRightX, aRightY, aRightZ;
3057     aView->Window()->Size (aWidth, aHeight);
3058
3059     aView->ConvertWithProj (aWidth, aHeight/2, 
3060                             aRightX, aRightY, aRightZ,
3061                             aDirX, aDirY, aDirZ);
3062     aView->ConvertWithProj (aWidth/2, aHeight/2, 
3063                             aCentX, aCentY, aCentZ,
3064                             aDirX, aDirY, aDirZ);
3065
3066     anEye.SetCoord (-aCentX, -aCentY, -aCentZ);
3067     aDir.SetCoord (-aDirX, -aDirY, -aDirZ);
3068     aRight.SetCoord (aRightX - aCentX, aRightY - aCentY, aRightZ - aCentZ);
3069     aProjAx.SetLocation (anEye);
3070     aProjAx.SetDirection (aDir);
3071     aProjAx.SetXDirection (aRight);
3072   }
3073   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3074   {
3075     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
3076     anArgCase.LowerCase();
3077     if (anArgIter + 1 < theArgNb
3078      && (anArgCase == "-algotype"
3079       || anArgCase == "-algo"
3080       || anArgCase == "-type"))
3081     {
3082       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
3083       anArgNext.LowerCase();
3084       if (anArgNext == "polyalgo")
3085       {
3086         anAlgoType = Prs3d_TOH_PolyAlgo;
3087       }
3088       else if (anArgNext == "algo")
3089       {
3090         anAlgoType = Prs3d_TOH_Algo;
3091       }
3092       else
3093       {
3094         Message::SendFail() << "Syntax error: unknown algo type '" << anArgNext << "'";
3095         return 1;
3096       }
3097     }
3098     else if (anArgCase == "-showhiddenedges"
3099           || anArgCase == "-hiddenedges"
3100           || anArgCase == "-hidden")
3101     {
3102       toShowHiddenEdges = true;
3103       if (anArgIter + 1 < theArgNb
3104        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toShowHiddenEdges))
3105       {
3106         ++anArgIter;
3107       }
3108     }
3109     else if (anArgCase == "-showtangentedges"
3110           || anArgCase == "-tangentedges"
3111           || anArgCase == "-tangent")
3112     {
3113       toShowCNEdges = true;
3114       if (anArgIter + 1 < theArgNb
3115        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toShowCNEdges))
3116       {
3117         ++anArgIter;
3118       }
3119     }
3120     else if (anArgIter + 1 < theArgNb
3121           && (anArgCase == "-nbiso"
3122            || anArgCase == "-nbisolines"))
3123     {
3124       aNbIsolines = Draw::Atoi (theArgVec[++anArgIter]);
3125     }
3126     else if (aSh.IsNull())
3127     {
3128       aSh = DBRep::Get (theArgVec[anArgIter]);
3129       aShapeName = theArgVec[anArgIter];
3130       if (aSh.IsNull())
3131       {
3132         BRep_Builder aBrepBuilder;
3133         BRepTools::Read (aSh, theArgVec[anArgIter], aBrepBuilder);
3134         if (aSh.IsNull())
3135         {
3136           Message::SendFail() << "Syntax error: no shape with name " << theArgVec[anArgIter] << " found";
3137           return 1;
3138         }
3139       }
3140     }
3141     else if (aHlrName.IsEmpty())
3142     {
3143       aHlrName = theArgVec[anArgIter];
3144     }
3145     else if (!hasViewDirArg
3146           && anArgIter + 8 < theArgNb)
3147     {
3148       hasViewDirArg = true;
3149       gp_Dir anUp;
3150       anEye.SetCoord (Draw::Atof (theArgVec[anArgIter + 0]), Draw::Atof (theArgVec[anArgIter + 1]), Draw::Atof (theArgVec[anArgIter + 2]));
3151       aDir .SetCoord (Draw::Atof (theArgVec[anArgIter + 3]), Draw::Atof (theArgVec[anArgIter + 4]), Draw::Atof (theArgVec[anArgIter + 5]));
3152       anUp .SetCoord (Draw::Atof (theArgVec[anArgIter + 6]), Draw::Atof (theArgVec[anArgIter + 7]), Draw::Atof (theArgVec[anArgIter + 8]));
3153       aProjAx.SetLocation (anEye);
3154       aProjAx.SetDirection (aDir);
3155       aProjAx.SetYDirection (anUp);
3156       anArgIter += 8;
3157     }
3158     else
3159     {
3160       Message::SendFail() << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
3161       return 1;
3162     }
3163   }
3164
3165   if (aHlrName.IsEmpty() || aSh.IsNull()
3166    || (ViewerTest::GetAISContext().IsNull() && hasViewDirArg))
3167   {
3168     Message::SendFail ("Syntax error: wrong number of arguments");
3169     return 1;
3170   }
3171
3172   HLRAlgo_Projector aProjector (aProjAx);
3173   TopoDS_Shape aVisible[6];
3174   TopoDS_Shape aHidden[6];
3175   if (anAlgoType == Prs3d_TOH_PolyAlgo)
3176   {
3177     Handle(HLRBRep_PolyAlgo) aPolyAlgo = new HLRBRep_PolyAlgo();
3178     aPolyAlgo->Projector (aProjector);
3179     aPolyAlgo->Load (aSh);
3180     aPolyAlgo->Update();
3181
3182     HLRBRep_PolyHLRToShape aHLRToShape;
3183     aHLRToShape.Update (aPolyAlgo);
3184
3185     aVisible[HLRBRep_Sharp]   = aHLRToShape.VCompound();
3186     aVisible[HLRBRep_OutLine] = aHLRToShape.OutLineVCompound(); // extract visible outlines
3187     aVisible[HLRBRep_Rg1Line] = aHLRToShape.Rg1LineVCompound();
3188     if (toShowCNEdges)
3189     {
3190       aVisible[HLRBRep_RgNLine] = aHLRToShape.RgNLineVCompound();
3191     }
3192     if (toShowHiddenEdges)
3193     {
3194       aHidden[HLRBRep_Sharp]   = aHLRToShape.HCompound();
3195       aHidden[HLRBRep_OutLine] = aHLRToShape.OutLineHCompound();
3196       aHidden[HLRBRep_Rg1Line] = aHLRToShape.Rg1LineHCompound();
3197       if (toShowCNEdges)
3198       {
3199         aHidden[HLRBRep_RgNLine] = aHLRToShape.RgNLineHCompound();
3200       }
3201     }
3202   }
3203   else
3204   {
3205     Handle(HLRBRep_Algo) aHlrAlgo = new HLRBRep_Algo();
3206     aHlrAlgo->Add (aSh, aNbIsolines);
3207     aHlrAlgo->Projector (aProjector);
3208     aHlrAlgo->Update();
3209     aHlrAlgo->Hide();
3210
3211     HLRBRep_HLRToShape aHLRToShape (aHlrAlgo);
3212     aVisible[HLRBRep_Sharp]   = aHLRToShape.VCompound();
3213     aVisible[HLRBRep_OutLine] = aHLRToShape.OutLineVCompound();
3214     aVisible[HLRBRep_Rg1Line] = aHLRToShape.Rg1LineVCompound();
3215     if (toShowCNEdges)
3216     {
3217       aVisible[HLRBRep_RgNLine] = aHLRToShape.RgNLineVCompound();
3218     }
3219     aVisible[HLRBRep_IsoLine] = aHLRToShape.IsoLineVCompound();
3220
3221     if (toShowHiddenEdges)
3222     {
3223       aHidden[HLRBRep_Sharp]   = aHLRToShape.HCompound();
3224       aHidden[HLRBRep_OutLine] = aHLRToShape.OutLineHCompound();
3225       aHidden[HLRBRep_Rg1Line] = aHLRToShape.Rg1LineHCompound();
3226       if (toShowCNEdges)
3227       {
3228         aHidden[HLRBRep_RgNLine] = aHLRToShape.RgNLineHCompound();
3229       }
3230       aHidden[HLRBRep_IsoLine] = aHLRToShape.IsoLineHCompound();
3231     }
3232     // extract 3d
3233     //aVisible[HLRBRep_Sharp]   = aHLRToShape.CompoundOfEdges (HLRBRep_Sharp, Standard_True, Standard_True);
3234     //aVisible[HLRBRep_OutLine] = aHLRToShape.OutLineVCompound3d();
3235   }
3236
3237   TopoDS_Compound aCompRes, aCompVis, aCompHid;
3238   BRep_Builder aBuilder;
3239   aBuilder.MakeCompound (aCompVis);
3240   aBuilder.MakeCompound (aCompHid);
3241   aBuilder.MakeCompound (aCompRes);
3242   for (int aTypeIter = 0; aTypeIter < 6; ++aTypeIter)
3243   {
3244     if (!aVisible[aTypeIter].IsNull())
3245     {
3246       aBuilder.Add (aCompVis, aVisible[aTypeIter]);
3247     }
3248     if (!aHidden[aTypeIter].IsNull())
3249     {
3250       aBuilder.Add (aCompHid, aHidden[aTypeIter]);
3251     }
3252   }
3253   aBuilder.Add (aCompRes, aCompVis);
3254   aBuilder.Add (aCompRes, aCompHid);
3255
3256   // create an AIS shape and display it
3257   if (!ViewerTest::GetAISContext().IsNull())
3258   {
3259     Handle(AIS_ColoredShape) anObject = new AIS_ColoredShape (aCompRes);
3260     if (toShowHiddenEdges)
3261     {
3262       Handle(Prs3d_LineAspect) aLineAspect = new Prs3d_LineAspect (Quantity_Color (Quantity_NOC_RED), Aspect_TOL_DASH, 1.0f);
3263       for (int aTypeIter = 0; aTypeIter < 6; ++aTypeIter)
3264       {
3265         if (!aHidden[aTypeIter].IsNull())
3266         {
3267           Handle(AIS_ColoredDrawer) aDrawer = anObject->CustomAspects (aHidden[aTypeIter]);
3268           aDrawer->SetLineAspect (aLineAspect);
3269           aDrawer->SetWireAspect (aLineAspect);
3270           aDrawer->SetFreeBoundaryAspect (aLineAspect);
3271           aDrawer->SetUnFreeBoundaryAspect (aLineAspect);
3272         }
3273       }
3274     }
3275     ViewerTest::Display (aHlrName, anObject, true);
3276   }
3277
3278   DBRep::Set (aHlrName.ToCString(), aCompRes);
3279   return 0;
3280 }
3281
3282 // This class is a wrap for Graphic3d_ArrayOfPrimitives; it is used for
3283 // manipulating and displaying such an array with AIS context
3284
3285 class MyPArrayObject : public AIS_InteractiveObject
3286 {
3287
3288 public:
3289
3290   MyPArrayObject (const Handle(Graphic3d_ArrayOfPrimitives)& thePArray) : myPArray (thePArray) {}
3291
3292   MyPArrayObject (Graphic3d_TypeOfPrimitiveArray thePrimType,
3293                   const Handle(TColStd_HArray1OfAsciiString)& theDesc,
3294                   const Handle(Graphic3d_AspectMarker3d)& theMarkerAspect)
3295   {
3296     Init (thePrimType, theDesc, theMarkerAspect, Standard_False);
3297   }
3298
3299   //! Initialize the array from specified description.
3300   Standard_Boolean Init (Graphic3d_TypeOfPrimitiveArray thePrimType,
3301                          const Handle(TColStd_HArray1OfAsciiString)& theDesc,
3302                          const Handle(Graphic3d_AspectMarker3d)& theMarkerAspect,
3303                          Standard_Boolean theToPatch);
3304
3305   DEFINE_STANDARD_RTTI_INLINE(MyPArrayObject,AIS_InteractiveObject);
3306
3307   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; }
3308
3309   //! Sets color to this interactive object
3310   //! @param theColor the color to be set
3311   virtual void SetColor (const Quantity_Color& theColor) Standard_OVERRIDE;
3312
3313 private:
3314
3315   virtual void Compute (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
3316                 const Handle(Prs3d_Presentation)& thePrs,
3317                 const Standard_Integer theMode) Standard_OVERRIDE;
3318
3319   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
3320                                  const Standard_Integer theMode) Standard_OVERRIDE;
3321
3322   bool CheckInputCommand (const TCollection_AsciiString theCommand,
3323                           const Handle(TColStd_HArray1OfAsciiString)& theArgsArray,
3324                           Standard_Integer &theArgIndex,
3325                           Standard_Integer theArgCount,
3326                           Standard_Integer theMaxArgs);
3327
3328   //! Sets color for the shading aspect of the drawer used in this interactive object
3329   //! @param theColor the color to be set
3330   void setColorForShadingAspect(const Quantity_Color& theColor);
3331
3332   //! Replaces shading aspect from myDrawer->Link() with the own shading aspect of myDrawer for this interactive object
3333   void replaceShadingAspect();
3334
3335 protected:
3336
3337   Handle(Graphic3d_AspectMarker3d) myMarkerAspect;
3338   Handle(Graphic3d_ArrayOfPrimitives) myPArray;
3339
3340 };
3341
3342 void MyPArrayObject::Compute (const Handle(PrsMgr_PresentationManager)& ,
3343                               const Handle(Prs3d_Presentation)& thePrs,
3344                               const Standard_Integer theMode)
3345 {
3346   if (myPArray.IsNull() || theMode != 0)
3347   {
3348     return;
3349   }
3350
3351   Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
3352   if (!myMarkerAspect.IsNull())
3353   {
3354     aGroup->SetGroupPrimitivesAspect (myMarkerAspect);
3355   }
3356   else
3357   {
3358     aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
3359   }
3360   aGroup->AddPrimitiveArray (myPArray);
3361 }
3362
3363 Standard_Boolean MyPArrayObject::Init (Graphic3d_TypeOfPrimitiveArray thePrimType,
3364                                        const Handle(TColStd_HArray1OfAsciiString)& theDesc,
3365                                        const Handle(Graphic3d_AspectMarker3d)& theMarkerAspect,
3366                                        Standard_Boolean theToPatch)
3367 {
3368   myMarkerAspect = theMarkerAspect;
3369   if (!theToPatch)
3370   {
3371     myPArray.Nullify();
3372   }
3373
3374   // Parsing array description
3375   Standard_Integer aVertexNum = 0, aBoundNum = 0, aEdgeNum = 0;
3376   Graphic3d_ArrayFlags anArrayFlags = Graphic3d_ArrayFlags_None;
3377
3378   const Standard_Integer anArgsCount = theDesc->Length();
3379   TCollection_AsciiString aCommand;
3380   for (Standard_Integer anArgIndex = theDesc->Lower(); anArgIndex <= theDesc->Upper(); )
3381   {
3382     aCommand = theDesc->Value (anArgIndex);
3383     aCommand.LowerCase();
3384
3385     if (CheckInputCommand ("-deinterleaved", theDesc, anArgIndex, 0, anArgsCount))
3386     {
3387       anArrayFlags |= Graphic3d_ArrayFlags_AttribsDeinterleaved;
3388     }
3389     else if (CheckInputCommand ("-mutable", theDesc, anArgIndex, 0, anArgsCount))
3390     {
3391       anArrayFlags |= Graphic3d_ArrayFlags_AttribsMutable;
3392       anArrayFlags |= Graphic3d_ArrayFlags_IndexesMutable;
3393     }
3394     // vertex command
3395     else if (CheckInputCommand ("v", theDesc, anArgIndex, 3, anArgsCount))
3396     {
3397       // vertex has a normal or normal with color or texel
3398       if (CheckInputCommand ("n", theDesc, anArgIndex, 3, anArgsCount))
3399       {
3400         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_VertexNormal;
3401       }
3402
3403       // vertex has a color
3404       if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
3405       {
3406         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_VertexColor;
3407       }
3408
3409       // vertex has a texel
3410       if (CheckInputCommand ("t", theDesc, anArgIndex, 2, anArgsCount))
3411       {
3412         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_VertexTexel;
3413       }
3414
3415       aVertexNum++;
3416     }
3417     // bound command
3418     else if (CheckInputCommand ("b", theDesc, anArgIndex, 1, anArgsCount))
3419     {
3420       // bound has color
3421       if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
3422       {
3423         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_BoundColor;
3424       }
3425
3426       aBoundNum++;
3427     }
3428     // edge command
3429     else if (CheckInputCommand ("e", theDesc, anArgIndex, 1, anArgsCount))
3430     {
3431       aEdgeNum++;
3432     }
3433     // unknown command
3434     else
3435       anArgIndex++;
3436   }
3437
3438   if (myPArray.IsNull())
3439   {
3440     myPArray = Graphic3d_ArrayOfPrimitives::CreateArray (thePrimType, aVertexNum, aBoundNum, aEdgeNum, anArrayFlags);
3441     if (myPArray->HasVertexColors())
3442     {
3443       myDrawer->SetupOwnShadingAspect();
3444       Graphic3d_MaterialAspect aMat (Graphic3d_NameOfMaterial_Plastified);
3445       aMat.SetSpecularColor (Quantity_NOC_BLACK);
3446       aMat.SetEmissiveColor (Quantity_NOC_BLACK);
3447       aMat.SetAmbientColor (Quantity_Color (Graphic3d_Vec3 (0.5f)));
3448       aMat.SetDiffuseColor (Quantity_Color (Graphic3d_Vec3 (0.5f)));
3449       myDrawer->ShadingAspect()->SetMaterial (aMat);
3450       myDrawer->ShadingAspect()->SetColor (Quantity_NOC_WHITE);
3451     }
3452   }
3453   else
3454   {
3455     if (myPArray->Type() != thePrimType
3456     ||  aVertexNum > myPArray->VertexNumberAllocated()
3457     ||  aEdgeNum   > myPArray->EdgeNumberAllocated()
3458     ||  aBoundNum  > myPArray->BoundNumberAllocated()
3459     || !myPArray->Attributes()->IsMutable()
3460     || (!myPArray->Indices().IsNull() && !myPArray->Indices()->IsMutable()))
3461     {
3462       Message::SendFail ("Syntax error: array cannot be patched");
3463       return Standard_False;
3464     }
3465
3466     myPArray->Attributes()->NbElements = aVertexNum;
3467     if (Handle(Graphic3d_AttribBuffer) anAttribs = Handle(Graphic3d_AttribBuffer)::DownCast (myPArray->Attributes()))
3468     {
3469       anAttribs->Invalidate (0, aVertexNum - 1);
3470     }
3471     if (!myPArray->Indices().IsNull())
3472     {
3473       myPArray->Indices()->NbElements = aEdgeNum;
3474     }
3475     if (!myPArray->Bounds().IsNull())
3476     {
3477       myPArray->Bounds()->NbBounds = aBoundNum;
3478     }
3479   }
3480
3481   Standard_Integer aVertIndex = 0;
3482   for (Standard_Integer anArgIndex = theDesc->Lower(); anArgIndex <= theDesc->Upper(); )
3483   {
3484     aCommand = theDesc->Value (anArgIndex);
3485     aCommand.LowerCase();
3486     if (!aCommand.IsAscii()
3487       || aCommand.IsEmpty())
3488     {
3489       break;
3490     }
3491
3492     // skip beautifiers (syntax is not actually validated)
3493     if (aCommand == "-deinterleaved"
3494      || aCommand == "-mutable"
3495      || aCommand.Value (1) == '('
3496      || aCommand.Value (1) == ')'
3497      || aCommand.Value (1) == ',')
3498     {
3499       ++anArgIndex;
3500     }
3501     // vertex command
3502     else if (CheckInputCommand ("v", theDesc, anArgIndex, 3, anArgsCount))
3503     {
3504       const Graphic3d_Vec3 aVert ((float )theDesc->Value (anArgIndex - 3).RealValue(),
3505                                   (float )theDesc->Value (anArgIndex - 2).RealValue(),
3506                                   (float )theDesc->Value (anArgIndex - 1).RealValue());
3507       if ((anArrayFlags & Graphic3d_ArrayFlags_AttribsDeinterleaved) != 0
3508        || (anArrayFlags & Graphic3d_ArrayFlags_AttribsMutable) != 0)
3509       {
3510         ++aVertIndex;
3511         myPArray->SetVertice (aVertIndex, aVert.x(), aVert.y(), aVert.z());
3512       }
3513       else
3514       {
3515         aVertIndex = myPArray->AddVertex (aVert);
3516       }
3517
3518       // vertex has a normal or normal with color or texel
3519       if (CheckInputCommand ("n", theDesc, anArgIndex, 3, anArgsCount))
3520       {
3521         const Graphic3d_Vec3 aNorm ((float )theDesc->Value (anArgIndex - 3).RealValue(),
3522                                     (float )theDesc->Value (anArgIndex - 2).RealValue(),
3523                                     (float )theDesc->Value (anArgIndex - 1).RealValue());
3524         myPArray->SetVertexNormal (aVertIndex, aNorm.x(), aNorm.y(), aNorm.z());
3525       }
3526       
3527       if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
3528       {
3529         const Graphic3d_Vec3d aCol (theDesc->Value (anArgIndex - 3).RealValue(),
3530                                     theDesc->Value (anArgIndex - 2).RealValue(),
3531                                     theDesc->Value (anArgIndex - 1).RealValue());
3532         myPArray->SetVertexColor (aVertIndex, aCol.r(), aCol.g(), aCol.b());
3533       }
3534       if (CheckInputCommand ("t", theDesc, anArgIndex, 2, anArgsCount))
3535       {
3536         const Graphic3d_Vec2 aTex ((float )theDesc->Value (anArgIndex - 2).RealValue(),
3537                                    (float )theDesc->Value (anArgIndex - 1).RealValue());
3538         myPArray->SetVertexTexel (aVertIndex, aTex.x(), aTex.y());
3539       }
3540     }
3541     // bounds command
3542     else if (CheckInputCommand ("b", theDesc, anArgIndex, 1, anArgsCount))
3543     {
3544       Standard_Integer aVertCount = theDesc->Value (anArgIndex - 1).IntegerValue();
3545
3546       if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
3547         myPArray->AddBound (aVertCount,
3548                             theDesc->Value (anArgIndex - 3).RealValue(),
3549                             theDesc->Value (anArgIndex - 2).RealValue(),
3550                             theDesc->Value (anArgIndex - 1).RealValue());
3551
3552       else
3553         myPArray->AddBound (aVertCount);
3554     }
3555     // edge command
3556     else if (CheckInputCommand ("e", theDesc, anArgIndex, 1, anArgsCount))
3557     {
3558       const Standard_Integer anEdge = theDesc->Value (anArgIndex - 1).IntegerValue();
3559       myPArray->AddEdge (anEdge);
3560     }
3561     // unknown command
3562     else
3563     {
3564       Message::SendFail() << "Syntax error: unknown argument '" << theDesc->Value(anArgIndex) << "'";
3565       return Standard_False;
3566     }
3567   }
3568   return Standard_True;
3569 }
3570
3571 //=======================================================================
3572 // function : SetColor
3573 // purpose  :
3574 //=======================================================================
3575 void MyPArrayObject::SetColor (const Quantity_Color& theColor)
3576 {
3577   AIS_InteractiveObject::SetColor (theColor);
3578   setColorForShadingAspect (theColor);
3579   if (myMarkerAspect)
3580   {
3581     myMarkerAspect->SetColor (theColor);
3582   }
3583   SynchronizeAspects();
3584 }
3585
3586 void MyPArrayObject::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
3587                                        const Standard_Integer theMode)
3588 {
3589   if (theMode != 0
3590    || myPArray.IsNull())
3591   {
3592     return;
3593   }
3594
3595   Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this);
3596   if (Handle(Graphic3d_ArrayOfTriangles) aTris = Handle(Graphic3d_ArrayOfTriangles)::DownCast (myPArray))
3597   {
3598     Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anOwner);
3599     aSensitive->InitTriangulation (myPArray->Attributes(), myPArray->Indices(), TopLoc_Location(), true);
3600     theSelection->Add (aSensitive);
3601   }
3602   else if (Handle(Graphic3d_ArrayOfSegments) aSegs = Handle(Graphic3d_ArrayOfSegments)::DownCast (myPArray))
3603   {
3604     if (aSegs->EdgeNumber() > 0)
3605     {
3606       for (Standard_Integer aPntIter = 1; aPntIter <= aSegs->EdgeNumber(); aPntIter += 2)
3607       {
3608         Handle(Select3D_SensitiveSegment) aSeg = new Select3D_SensitiveSegment (anOwner, aSegs->Vertice (aSegs->Edge (aPntIter)), aSegs->Vertice (aSegs->Edge (aPntIter + 1)));
3609         aSeg->SetSensitivityFactor (4);
3610         theSelection->Add (aSeg);
3611       }
3612     }
3613     else
3614     {
3615       for (Standard_Integer aPntIter = 1; aPntIter <= aSegs->VertexNumber(); aPntIter += 2)
3616       {
3617         Handle(Select3D_SensitiveSegment) aSeg = new Select3D_SensitiveSegment (anOwner, aSegs->Vertice (aPntIter), aSegs->Vertice (aPntIter + 1));
3618         aSeg->SetSensitivityFactor (4);
3619         theSelection->Add (aSeg);
3620       }
3621     }
3622   }
3623   else
3624   {
3625     Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anOwner);
3626     aSensitive->SetSensitivityFactor (8);
3627     aSensitive->InitPoints (myPArray->Attributes(), myPArray->Indices(), TopLoc_Location(), true);
3628     theSelection->Add (aSensitive);
3629   }
3630 }
3631
3632 bool MyPArrayObject::CheckInputCommand (const TCollection_AsciiString theCommand,
3633                                        const Handle(TColStd_HArray1OfAsciiString)& theArgsArray,
3634                                        Standard_Integer &theArgIndex,
3635                                        Standard_Integer theArgCount,
3636                                        Standard_Integer theMaxArgs)
3637 {
3638   // check if there is more elements than expected
3639   if (theArgIndex >= theMaxArgs)
3640     return false;
3641
3642   TCollection_AsciiString aStrCommand = theArgsArray->Value (theArgIndex);
3643   aStrCommand.LowerCase();
3644   if (aStrCommand.Search(theCommand) != 1 ||
3645       theArgIndex + (theArgCount - 1) >= theMaxArgs)
3646     return false;
3647
3648   // go to the first data element
3649   theArgIndex++;
3650
3651   // check data if it can be converted to numeric
3652   for (int aElement = 0; aElement < theArgCount; aElement++, theArgIndex++)
3653   {
3654     aStrCommand = theArgsArray->Value (theArgIndex);
3655     if (!aStrCommand.IsRealValue (Standard_True))
3656       return false;
3657   }
3658
3659   return true;
3660 }
3661
3662 //=======================================================================
3663 // function : setColorForShadingAspect
3664 // purpose  :
3665 //=======================================================================
3666 void MyPArrayObject::setColorForShadingAspect (const Quantity_Color& theColor)
3667 {
3668   if (myDrawer->SetupOwnShadingAspect())
3669   {
3670     replaceShadingAspect();
3671   }
3672   myDrawer->ShadingAspect()->SetColor (theColor);
3673 }
3674
3675 //=======================================================================
3676 // function : replaceShadingAspect
3677 // purpose  :
3678 //=======================================================================
3679 void MyPArrayObject::replaceShadingAspect()
3680 {
3681   if (!myDrawer->Link())
3682   {
3683     return;
3684   }
3685   Graphic3d_MapOfAspectsToAspects anAspectReplacementMap;
3686   anAspectReplacementMap.Bind (myDrawer->Link()->ShadingAspect()->Aspect(), myDrawer->ShadingAspect()->Aspect());
3687   replaceAspects (anAspectReplacementMap);
3688 }
3689
3690 //=============================================================================
3691 //function : VDrawPArray
3692 //purpose  : Draws primitives array from list of vertexes, bounds, edges
3693 //=============================================================================
3694
3695 static int VDrawPArray (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3696 {
3697   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
3698   if (aContextAIS.IsNull())
3699   {
3700     Message::SendFail ("Error: no active Viewer");
3701     return 1;
3702   }
3703   else if (argc < 3)
3704   {
3705     Message::SendFail ("Syntax error: wrong number of arguments");
3706     return 1;
3707   }
3708
3709   // read the arguments
3710   Standard_Integer anArgIndex = 1;
3711   TCollection_AsciiString aName (argv[anArgIndex++]);
3712   TCollection_AsciiString anArrayType (argv[anArgIndex++]);
3713   anArrayType.LowerCase();
3714   Handle(MyPArrayObject) aPObject;
3715   if (anArrayType == "-shape")
3716   {
3717     Standard_CString aShapeName = argv[anArgIndex++];
3718     TopoDS_Shape aShape = DBRep::Get (aShapeName);
3719     Handle(Graphic3d_ArrayOfPrimitives) aTris = StdPrs_ShadedShape::FillTriangles (aShape);
3720     if (aShape.IsNull())
3721     {
3722       Message::SendFail() << "Syntax error: shape '" << aShapeName << "' is not found";
3723       return 1;
3724     }
3725     else if (aTris.IsNull())
3726     {
3727       Message::SendFail() << "Syntax error: shape '" << aShapeName << "' is not triangulated";
3728       return 1;
3729     }
3730
3731     aPObject = new MyPArrayObject (aTris);
3732     ViewerTest::Display (aName, aPObject);
3733     return 0;
3734   }
3735   else if (anArrayType == "-patch"
3736         || anArrayType == "-modify"
3737         || anArrayType == "-edit")
3738   {
3739     if (argc >= 3)
3740     {
3741       anArrayType = argv[anArgIndex++];
3742       anArrayType.LowerCase();
3743     }
3744
3745     if (GetMapOfAIS().IsBound2 (aName))
3746     {
3747       aPObject = Handle(MyPArrayObject)::DownCast (GetMapOfAIS().Find2 (aName));
3748     }
3749     if (aPObject.IsNull())
3750     {
3751       Message::SendFail() << "Syntax error: object '" << aName << "' cannot be found";
3752       return 1;
3753     }
3754   }
3755
3756   Standard_Boolean hasVertex = Standard_False;
3757
3758   Graphic3d_TypeOfPrimitiveArray aPrimType = Graphic3d_TOPA_UNDEFINED;
3759   if (anArrayType == "points")
3760   {
3761     aPrimType = Graphic3d_TOPA_POINTS;
3762   }
3763   else if (anArrayType == "segments")
3764   {
3765     aPrimType = Graphic3d_TOPA_SEGMENTS;
3766   }
3767   else if (anArrayType == "polylines")
3768   {
3769     aPrimType = Graphic3d_TOPA_POLYLINES;
3770   }
3771   else if (anArrayType == "triangles")
3772   {
3773     aPrimType = Graphic3d_TOPA_TRIANGLES;
3774   }
3775   else if (anArrayType == "trianglefans")
3776   {
3777     aPrimType = Graphic3d_TOPA_TRIANGLEFANS;
3778   }
3779   else if (anArrayType == "trianglestrips")
3780   {
3781     aPrimType = Graphic3d_TOPA_TRIANGLESTRIPS;
3782   }
3783   else if (anArrayType == "quads")
3784   {
3785     aPrimType = Graphic3d_TOPA_QUADRANGLES;
3786   }
3787   else if (anArrayType == "quadstrips")
3788   {
3789     aPrimType = Graphic3d_TOPA_QUADRANGLESTRIPS;
3790   }
3791   else if (anArrayType == "polygons")
3792   {
3793     aPrimType = Graphic3d_TOPA_POLYGONS;
3794   }
3795   if (aPrimType == Graphic3d_TOPA_UNDEFINED)
3796   {
3797     Message::SendFail ("Syntax error: unexpected type of primitives array");
3798     return 1;
3799   }
3800
3801   Standard_Integer aLowerArg = anArgIndex;
3802   Handle(TColStd_HArray1OfAsciiString) anArgsArray = new TColStd_HArray1OfAsciiString (0, argc - 3);
3803   for (; anArgIndex < argc; ++anArgIndex)
3804   {
3805     TCollection_AsciiString aCommand (argv[anArgIndex]);
3806     aCommand.LowerCase();
3807     if (!aCommand.IsAscii())
3808     {
3809       di << "Unexpected argument: #" << anArgIndex - 1 << " , "
3810          << "should be an array element: 'v', 'b', 'e' \n";
3811       break;
3812     }
3813
3814     if (aCommand == "v")
3815     {
3816       hasVertex = Standard_True;
3817     }
3818
3819     anArgsArray->SetValue (anArgIndex - aLowerArg, aCommand);
3820   }
3821
3822   if (!hasVertex)
3823   {
3824     di << "You should pass any verticies in the list of array elements\n";
3825     return 1;
3826   }
3827
3828   Handle(Graphic3d_AspectMarker3d)    anAspPoints;
3829   if (aPrimType == Graphic3d_TOPA_POINTS)
3830   {
3831     anAspPoints = new Graphic3d_AspectMarker3d (Aspect_TOM_POINT, Quantity_NOC_YELLOW, 1.0f);
3832   }
3833
3834   // create primitives array object
3835   if (aPObject.IsNull())
3836   {
3837     // register the object in map
3838     aPObject = new MyPArrayObject (aPrimType, anArgsArray, anAspPoints);
3839     VDisplayAISObject (aName, aPObject);
3840   }
3841   else
3842   {
3843     aPObject->Init (aPrimType, anArgsArray, anAspPoints, Standard_True);
3844     ViewerTest::CurrentView()->Redraw();
3845   }
3846   return 0;
3847 }
3848
3849 namespace
3850 {
3851   //! Auxiliary function for parsing translation vector - either 2D or 3D.
3852   static Standard_Integer parseTranslationVec (Standard_Integer theArgNb,
3853                                                const char**     theArgVec,
3854                                                gp_Vec&          theVec)
3855   {
3856     if (theArgNb < 2)
3857     {
3858       return 0;
3859     }
3860
3861     TCollection_AsciiString anX (theArgVec[0]);
3862     TCollection_AsciiString anY (theArgVec[1]);
3863     if (!anX.IsRealValue (Standard_True)
3864      || !anY.IsRealValue (Standard_True))
3865     {
3866       return 0;
3867     }
3868
3869     theVec.SetX (anX.RealValue());
3870     theVec.SetY (anY.RealValue());
3871     if (theArgNb >= 3)
3872     {
3873       TCollection_AsciiString anZ (theArgVec[2]);
3874       if (anZ.IsRealValue (Standard_True))
3875       {
3876         theVec.SetZ (anZ.RealValue());
3877         return 3;
3878       }
3879     }
3880     return 2;
3881   }
3882 }
3883
3884 //=======================================================================
3885 //function : VSetLocation
3886 //purpose  : Change location of AIS interactive object
3887 //=======================================================================
3888
3889 static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
3890                                       Standard_Integer  theArgNb,
3891                                       const char**      theArgVec)
3892 {
3893   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3894   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
3895   if (aContext.IsNull())
3896   {
3897     Message::SendFail ("Error: no active viewer");
3898     return 1;
3899   }
3900
3901   Standard_Boolean toPrintInfo = Standard_True;
3902   Handle(AIS_InteractiveObject) anObj;
3903   TCollection_AsciiString aCmdName (theArgVec[0]);
3904   aCmdName.LowerCase();
3905   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3906   {
3907     TCollection_AsciiString anArg = theArgVec[anArgIter];
3908     anArg.LowerCase();
3909     if (anUpdateTool.parseRedrawMode (anArg))
3910     {
3911       continue;
3912     }
3913     else if (anObj.IsNull())
3914     {
3915       const TCollection_AsciiString aName (theArgVec[anArgIter]);
3916       GetMapOfAIS().Find2 (aName, anObj);
3917       if (anObj.IsNull())
3918       {
3919         Message::SendFail() << "Error: object '" << aName << "' is not displayed";
3920         return 1;
3921       }
3922     }
3923     else if (anArg == "-reset")
3924     {
3925       toPrintInfo = Standard_False;
3926       aContext->SetLocation (anObj, gp_Trsf());
3927     }
3928     else if (anArg == "-copyfrom"
3929           || anArg == "-copy")
3930     {
3931       if (anArgIter + 1 >= theArgNb)
3932       {
3933         Message::SendFail() << "Syntax error at '" << anArg << "'";
3934         return 1;
3935       }
3936
3937       const TCollection_AsciiString aName2 (theArgVec[anArgIter + 1]);
3938       Handle(AIS_InteractiveObject) anObj2;
3939       GetMapOfAIS().Find2 (aName2, anObj2);
3940       if (anObj2.IsNull())
3941       {
3942         Message::SendFail() << "Error: object '" << aName2 << "' is not displayed";
3943         return 1;
3944       }
3945
3946       ++anArgIter;
3947       aContext->SetLocation (anObj, anObj2->LocalTransformation());
3948     }
3949     else if (anArg == "-rotate"
3950           || anArg == "-prerotate")
3951     {
3952       toPrintInfo = Standard_False;
3953       if (anArgIter + 7 >= theArgNb)
3954       {
3955         Message::SendFail() << "Syntax error at '" << anArg << "'";
3956         return 1;
3957       }
3958
3959       gp_Trsf aTrsf;
3960       aTrsf.SetRotation (gp_Ax1 (gp_Pnt (Draw::Atof (theArgVec[anArgIter + 1]),
3961                                          Draw::Atof (theArgVec[anArgIter + 2]),
3962                                          Draw::Atof (theArgVec[anArgIter + 3])),
3963                                  gp_Vec (Draw::Atof (theArgVec[anArgIter + 4]),
3964                                          Draw::Atof (theArgVec[anArgIter + 5]),
3965                                          Draw::Atof (theArgVec[anArgIter + 6]))),
3966                                          Draw::Atof (theArgVec[anArgIter + 7]) * (M_PI / 180.0));
3967       anArgIter += 7;
3968
3969       if (anArg == "-prerotate")
3970       {
3971         aTrsf = anObj->LocalTransformation() * aTrsf;
3972       }
3973       else
3974       {
3975         aTrsf = aTrsf * anObj->LocalTransformation();
3976      }
3977       aContext->SetLocation (anObj, aTrsf);
3978     }
3979     else if (anArg == "-translate"
3980           || anArg == "-pretranslate")
3981     {
3982       toPrintInfo = Standard_False;
3983       gp_Vec aLocVec;
3984       Standard_Integer aNbParsed = parseTranslationVec (theArgNb - anArgIter - 1, theArgVec + anArgIter + 1, aLocVec);
3985       anArgIter += aNbParsed;
3986       if (aNbParsed == 0)
3987       {
3988         Message::SendFail() << "Syntax error at '" << anArg << "'";
3989         return 1;
3990       }
3991
3992       gp_Trsf aTrsf;
3993       aTrsf.SetTranslationPart (aLocVec);
3994       if (anArg == "-pretranslate")
3995       {
3996         aTrsf = anObj->LocalTransformation() * aTrsf;
3997       }
3998       else
3999       {
4000         aTrsf = aTrsf * anObj->LocalTransformation();
4001       }
4002       aContext->SetLocation (anObj, aTrsf);
4003     }
4004     else if (anArg == "-scale"
4005           || anArg == "-prescale"
4006           || anArg == "-setscale")
4007     {
4008       toPrintInfo = Standard_False;
4009       gp_XYZ aScaleLoc;
4010       Standard_Real aScale = 1.0;
4011       Standard_Boolean toPrintScale = Standard_True;
4012       Standard_Boolean hasScaleLoc  = Standard_False;
4013       if (anArgIter + 4 < theArgNb)
4014       {
4015         TCollection_AsciiString aScaleArgs[4] =
4016         {
4017           TCollection_AsciiString (theArgVec[anArgIter + 1]),
4018           TCollection_AsciiString (theArgVec[anArgIter + 2]),
4019           TCollection_AsciiString (theArgVec[anArgIter + 3]),
4020           TCollection_AsciiString (theArgVec[anArgIter + 4])
4021         };
4022         Standard_Integer aScaleArgIter = 0;
4023         for (; aScaleArgIter < 4; ++aScaleArgIter)
4024         {
4025           if (!aScaleArgs[aScaleArgIter].IsRealValue (Standard_True))
4026           {
4027             break;
4028           }
4029         }
4030         if (aScaleArgIter == 4)
4031         {
4032           aScaleLoc.SetCoord (aScaleArgs[0].RealValue(), aScaleArgs[1].RealValue(), aScaleArgs[2].RealValue());
4033           aScale = aScaleArgs[3].RealValue();
4034           anArgIter += 4;
4035           toPrintScale = Standard_False;
4036           hasScaleLoc  = Standard_True;
4037         }
4038         else if (aScaleArgIter >= 1)
4039         {
4040           aScale = aScaleArgs[0].RealValue();
4041           ++anArgIter;
4042           toPrintScale = Standard_False;
4043         }
4044       }
4045       else if (anArgIter + 1 < theArgNb)
4046       {
4047         TCollection_AsciiString aScaleArg (theArgVec[anArgIter + 1]);
4048         if (aScaleArg.IsRealValue (Standard_True))
4049         {
4050           aScale = aScaleArg.RealValue();
4051           ++anArgIter;
4052           toPrintScale = Standard_False;
4053         }
4054       }
4055
4056       if (toPrintScale)
4057       {
4058         if (anArg == "-setscale"
4059          || anArg == "-prescale")
4060         {
4061           Message::SendFail() << "Syntax error at '" << anArg << "'";
4062           return 1;
4063         }
4064
4065         char aText[1024];
4066         Sprintf (aText, "%g ", anObj->LocalTransformation().ScaleFactor());
4067         theDI << aText;
4068         continue;
4069       }
4070
4071       if (anArg == "-setscale")
4072       {
4073         gp_Trsf aTrsf = anObj->LocalTransformation();
4074         if (hasScaleLoc)
4075         {
4076           aTrsf.SetScale (aScaleLoc, aScale);
4077         }
4078         else
4079         {
4080           aTrsf.SetScaleFactor (aScale);
4081         }
4082         aContext->SetLocation (anObj, aTrsf);
4083       }
4084       else
4085       {
4086         gp_Trsf aTrsf;
4087         if (hasScaleLoc)
4088         {
4089           aTrsf.SetScale (aScaleLoc, aScale);
4090         }
4091         else
4092         {
4093           aTrsf.SetScaleFactor (aScale);
4094         }
4095
4096         if (anArg == "-prescale")
4097         {
4098           aTrsf = anObj->LocalTransformation() * aTrsf;
4099         }
4100         else
4101         {
4102           aTrsf = aTrsf * anObj->LocalTransformation();
4103         }
4104         aContext->SetLocation (anObj, aTrsf);
4105       }
4106     }
4107     else if (anArg == "-mirror"
4108           || anArg == "-premirror")
4109     {
4110       toPrintInfo = Standard_False;
4111       if (anArgIter + 6 >= theArgNb)
4112       {
4113         Message::SendFail() << "Syntax error at '" << anArg << "'";
4114         return 1;
4115       }
4116
4117       gp_Trsf aTrsf;
4118       aTrsf.SetMirror (gp_Ax2 (gp_Pnt (Draw::Atof(theArgVec[theArgNb - 6]),
4119                                        Draw::Atof(theArgVec[theArgNb - 5]),
4120                                        Draw::Atof(theArgVec[theArgNb - 4])),
4121                                gp_Vec (Draw::Atof(theArgVec[theArgNb - 3]),
4122                                        Draw::Atof(theArgVec[theArgNb - 2]),
4123                                        Draw::Atof(theArgVec[theArgNb - 1]))));
4124       anArgIter += 6;
4125       if (anArg == "-premirror")
4126       {
4127         aTrsf = anObj->LocalTransformation() * aTrsf;
4128       }
4129       else
4130       {
4131         aTrsf = aTrsf * anObj->LocalTransformation();
4132       }
4133       aContext->SetLocation (anObj, aTrsf);
4134     }
4135     else if (anArg == "-setrotation"
4136           || anArg == "-rotation")
4137     {
4138       toPrintInfo = Standard_False;
4139       if (anArgIter + 4 < theArgNb)
4140       {
4141         TCollection_AsciiString aQuatArgs[4] =
4142         {
4143           TCollection_AsciiString (theArgVec[anArgIter + 1]),
4144           TCollection_AsciiString (theArgVec[anArgIter + 2]),
4145           TCollection_AsciiString (theArgVec[anArgIter + 3]),
4146           TCollection_AsciiString (theArgVec[anArgIter + 4])
4147         };
4148         Standard_Integer aQuatArgIter = 0;
4149         for (; aQuatArgIter < 4; ++aQuatArgIter)
4150         {
4151           if (!aQuatArgs[aQuatArgIter].IsRealValue (Standard_True))
4152           {
4153             break;
4154           }
4155         }
4156
4157         if (aQuatArgIter == 4)
4158         {
4159           anArgIter += 4;
4160           const gp_Quaternion aQuat (aQuatArgs[0].RealValue(),
4161                                      aQuatArgs[1].RealValue(),
4162                                      aQuatArgs[2].RealValue(),
4163                                      aQuatArgs[3].RealValue());
4164           gp_Trsf aTrsf = anObj->LocalTransformation();
4165           aTrsf.SetRotationPart (aQuat);
4166           aContext->SetLocation (anObj, aTrsf);
4167           continue;
4168         }
4169         else if (anArg == "-setrotation")
4170         {
4171           Message::SendFail() << "Syntax error at '" << anArg << "'";
4172           return 1;
4173         }
4174       }
4175
4176       char aText[1024];
4177       const gp_Quaternion aQuat = anObj->LocalTransformation().GetRotation();
4178       Sprintf (aText, "%g %g %g %g ", aQuat.X(), aQuat.Y(), aQuat.Z(), aQuat.W());
4179       theDI << aText;
4180     }
4181     else if (anArg == "-setlocation"
4182           || anArg == "-location")
4183     {
4184       toPrintInfo = Standard_False;
4185       gp_Vec aLocVec;
4186       Standard_Integer aNbParsed = parseTranslationVec (theArgNb - anArgIter - 1, theArgVec + anArgIter + 1, aLocVec);
4187       anArgIter += aNbParsed;
4188       if (aNbParsed != 0)
4189       {
4190         gp_Trsf aTrsf = anObj->LocalTransformation();
4191         aTrsf.SetTranslationPart (aLocVec);
4192         aContext->SetLocation (anObj, aTrsf);
4193       }
4194       else if (anArg == "-setlocation")
4195       {
4196         Message::SendFail() << "Syntax error at '" << anArg << "'";
4197         return 1;
4198       }
4199
4200       char aText[1024];
4201       const gp_XYZ aLoc = anObj->LocalTransformation().TranslationPart();
4202       Sprintf (aText, "%g %g %g ", aLoc.X(), aLoc.Y(), aLoc.Z());
4203       theDI << aText;
4204     }
4205     else if (aCmdName == "vsetlocation")
4206     {
4207       // compatibility with old syntax
4208       gp_Vec aLocVec;
4209       Standard_Integer aNbParsed = parseTranslationVec (theArgNb - anArgIter, theArgVec + anArgIter, aLocVec);
4210       if (aNbParsed == 0)
4211       {
4212         Message::SendFail() << "Syntax error at '" << anArg << "'";
4213         return 1;
4214       }
4215       anArgIter = anArgIter + aNbParsed - 1;
4216
4217       gp_Trsf aTrsf;
4218       aTrsf.SetTranslationPart (aLocVec);
4219       aContext->SetLocation (anObj, aTrsf);
4220       toPrintInfo = Standard_False;
4221     }
4222     else
4223     {
4224       Message::SendFail() << "Error: unknown argument '" << anArg << "'";
4225       return 1;
4226     }
4227   }
4228
4229   if (anObj.IsNull())
4230   {
4231     Message::SendFail ("Syntax error - wrong number of arguments");
4232     return 1;
4233   }
4234   else if (!toPrintInfo)
4235   {
4236     return 0;
4237   }
4238
4239   const gp_Trsf       aTrsf = anObj->LocalTransformation();
4240   const gp_XYZ        aLoc  = aTrsf.TranslationPart();
4241   const gp_Quaternion aRot  = aTrsf.GetRotation();
4242   char aText[4096];
4243   Sprintf (aText, "Location: %g %g %g\n"
4244                   "Rotation: %g %g %g %g\n"
4245                   "Scale:    %g\n",
4246                   aLoc.X(), aLoc.Y(), aLoc.Z(),
4247                   aRot.X(), aRot.Y(), aRot.Z(), aRot.W(),
4248                   aTrsf.ScaleFactor());
4249   theDI << aText;
4250   return 0;
4251 }
4252
4253 //! Find displayed object.
4254 static Handle(AIS_InteractiveObject) findConnectedObject (const TCollection_AsciiString& theName)
4255 {
4256   Handle(AIS_InteractiveObject) aPrs;
4257   if (!GetMapOfAIS().Find2 (theName, aPrs))
4258   {
4259     return Handle(AIS_InteractiveObject)();
4260   }
4261   if (Handle(AIS_ConnectedInteractive) aConnected = Handle(AIS_ConnectedInteractive)::DownCast (aPrs))
4262   {
4263     return aConnected;
4264   }
4265   else if (Handle(AIS_MultipleConnectedInteractive) aMultiCon = Handle(AIS_MultipleConnectedInteractive)::DownCast (aPrs))
4266   {
4267     return aMultiCon;
4268   }
4269
4270   // replace already displayed object with connected one
4271   TheAISContext()->Remove (aPrs, false);
4272   Handle(AIS_ConnectedInteractive) aConnected = new AIS_ConnectedInteractive();
4273   if (aPrs->HasDisplayMode())
4274   {
4275     aConnected->SetDisplayMode (aPrs->DisplayMode());
4276   }
4277   aConnected->Connect (aPrs, aPrs->LocalTransformationGeom());
4278   if (!aPrs->TransformPersistence().IsNull())
4279   {
4280     aConnected->SetTransformPersistence (aPrs->TransformPersistence());
4281   }
4282   ViewerTest::Display (theName, aConnected, false);
4283   return aConnected;
4284 }
4285
4286 //===============================================================================================
4287 //function : VConnect
4288 //purpose  : Creates and displays AIS_ConnectedInteractive object from input object and location
4289 //===============================================================================================
4290 static Standard_Integer VConnect (Draw_Interpretor& /*di*/,
4291                                   Standard_Integer argc,
4292                                   const char ** argv)
4293 {
4294   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4295   if (aContext.IsNull())
4296   {
4297     Message::SendFail ("Error: no active viewer");
4298     return 1;
4299   }
4300   if (argc < 6)
4301   {
4302     Message::SendFail ("Syntax error: expect at least 5 arguments");
4303     return 1;
4304   }
4305
4306   // Get values
4307   Standard_Integer anArgIter = 1;
4308   const TCollection_AsciiString aName (argv[anArgIter++]);
4309   Handle(AIS_MultipleConnectedInteractive) aMultiConObject;
4310   TCollection_AsciiString aColorString (argv[argc-1]);
4311   Quantity_Color aColor;
4312   Standard_Boolean hasColor = Standard_False;
4313   if (aColorString.Search ("color=") != -1)
4314   {
4315     hasColor = Standard_True;
4316     aColorString.Remove (1, 6);
4317     if (!Quantity_Color::ColorFromName (aColorString.ToCString(), aColor))
4318     {
4319       Message::SendFail() << "Syntax error at " << aColorString;
4320       return 1;
4321     }
4322   }
4323
4324   const Standard_Integer aNbShapes = hasColor ? (argc - 1) : argc;
4325   for (Standard_Integer i = 5; i < aNbShapes; ++i)
4326   {
4327     TCollection_AsciiString anOriginObjectName (argv[i]);
4328     Handle(AIS_InteractiveObject) anObject;
4329     if (aName.IsEqual (anOriginObjectName))
4330     {
4331       Message::SendFail ("Syntax error: equal names for connected objects");
4332       continue;
4333     }
4334
4335     anObject = findConnectedObject (anOriginObjectName);
4336     if (anObject.IsNull())
4337     {
4338       TopoDS_Shape aTDShape = DBRep::Get (anOriginObjectName);
4339       if (aTDShape.IsNull())
4340       {
4341         Message::SendFail() << "Syntax error: object " << anOriginObjectName << " doesn't exist";
4342         return 1;
4343       }
4344       Handle(AIS_Shape) aShapePrs = new AIS_Shape (aTDShape);
4345       Handle(AIS_ConnectedInteractive) aConnectedOrig = new AIS_ConnectedInteractive();
4346       aConnectedOrig->Connect (aShapePrs);
4347       anObject = aConnectedOrig;
4348
4349       aContext->Load (anObject);
4350       anObject->SetColor (aColor);
4351     }
4352
4353     if (aMultiConObject.IsNull())
4354     {
4355       aMultiConObject = new AIS_MultipleConnectedInteractive();
4356     }
4357
4358     aMultiConObject->Connect (anObject);
4359   }
4360   if (aMultiConObject.IsNull())
4361   {
4362     Message::SendFail ("Syntax error: can't connect input objects");
4363     return 1;
4364   }
4365
4366   // Create transformation
4367   gp_Trsf aTrsf; 
4368   aTrsf.SetTranslationPart (gp_Vec (Draw::Atof (argv[anArgIter + 0]),
4369                                     Draw::Atof (argv[anArgIter + 1]),
4370                                     Draw::Atof (argv[anArgIter + 2])));
4371   TopLoc_Location aLocation (aTrsf);
4372   anArgIter += 3;
4373
4374   aMultiConObject->SetLocalTransformation (aTrsf);
4375
4376   ViewerTest::Display (aName, aMultiConObject, true);
4377   return 0;
4378 }
4379
4380 //===============================================================================================
4381 //function : VConnectTo
4382 //purpose  : Creates and displays AIS_ConnectedInteractive object from input object and location 
4383 //===============================================================================================
4384 static Standard_Integer VConnectTo (Draw_Interpretor& /*di*/,
4385                                     Standard_Integer argc,
4386                                     const char ** argv)
4387 {
4388   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4389   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
4390   if (aContext.IsNull())
4391   {
4392     Message::SendFail ("Error: no active viewer");
4393     return 1;
4394   }
4395   if (argc != 6 && argc != 7)
4396   {
4397     Message::SendFail ("Syntax error: expect at least 5 arguments");
4398     return 1;
4399   }
4400
4401   Standard_Integer anArgIter = 1;
4402   TCollection_AsciiString aName (argv[anArgIter++]);
4403   Handle(AIS_InteractiveObject) anOriginObject;
4404
4405   TCollection_AsciiString anOriginObjectName(argv[5]);
4406   if (aName.IsEqual (anOriginObjectName))
4407   {
4408     Message::SendFail ("Syntax error: equal names for connected objects");
4409     return 1;
4410   }
4411   anOriginObject = findConnectedObject (anOriginObjectName);
4412   if (anOriginObject.IsNull())
4413   {
4414     TopoDS_Shape aTDShape = DBRep::Get (anOriginObjectName);
4415     if (aTDShape.IsNull())
4416     {
4417       Message::SendFail() << "Syntax error: object " << anOriginObjectName << " doesn't exist";
4418       return 1;
4419     }
4420
4421     Handle(AIS_Shape) aShapePrs = new AIS_Shape (aTDShape);
4422     Handle(AIS_ConnectedInteractive) aConnectedOrig = new AIS_ConnectedInteractive();
4423     aConnectedOrig->Connect (aShapePrs);
4424
4425     anOriginObject = aConnectedOrig;
4426     GetMapOfAIS().Bind (aConnectedOrig, anOriginObjectName);
4427   }
4428
4429   // Create transformation
4430   gp_Trsf aTrsf;
4431   aTrsf.SetTranslationPart (gp_Vec (Draw::Atof (argv[anArgIter + 0]),
4432                                     Draw::Atof (argv[anArgIter + 1]),
4433                                     Draw::Atof (argv[anArgIter + 2])));
4434   anArgIter += 3;
4435
4436   Handle(AIS_ConnectedInteractive) aConnected = new AIS_ConnectedInteractive();
4437   aConnected->Connect (anOriginObject, aTrsf);
4438   if (argc == 7)
4439   {
4440     TCollection_AsciiString anArg = argv[6];
4441     anArg.LowerCase();
4442     if (anArg == "-nodisplay")
4443     {
4444       // bind connected object without displaying it
4445       Handle(AIS_InteractiveObject) anObj;
4446       if (GetMapOfAIS().Find2 (aName, anObj))
4447       {
4448         TheAISContext()->Remove (anObj, false);
4449         GetMapOfAIS().UnBind2 (aName);
4450       }
4451       GetMapOfAIS().Bind (aConnected, aName);
4452       return 0;
4453     }
4454
4455     if (!anUpdateTool.parseRedrawMode (anArg))
4456     {
4457       Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
4458       return 1;
4459     }
4460   }
4461
4462   ViewerTest::Display (aName, aConnected, false);
4463   return 0;
4464 }
4465
4466 //=======================================================================
4467 //function : VDisconnect
4468 //purpose  :
4469 //=======================================================================
4470 static Standard_Integer VDisconnect (Draw_Interpretor& di,
4471                                      Standard_Integer argc,
4472                                      const char ** argv)
4473 {
4474   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4475   if (aContext.IsNull())
4476   {
4477     Message::SendFail( "Error: no active viewer");
4478     return 1;
4479   }
4480   
4481   if (argc != 3)
4482   {
4483     Message::SendFail() << "Syntax error: wrong number of arguments.\nUsage: " << argv[0] << " name object";
4484     return 1;
4485   }
4486
4487   TCollection_AsciiString aName (argv[1]);
4488   TCollection_AsciiString anObject (argv[2]);
4489   Standard_Integer anObjectNumber = Draw::Atoi (argv[2]);
4490
4491   // find objects
4492   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
4493   Handle(AIS_MultipleConnectedInteractive) anAssembly;
4494   if (!aMap.IsBound2 (aName) )
4495   {
4496     Message::SendFail ("Error: no active viewer");
4497     return 1;
4498   }
4499
4500   anAssembly = Handle(AIS_MultipleConnectedInteractive)::DownCast (aMap.Find2 (aName));
4501   if (anAssembly.IsNull())
4502   {
4503     di << "Not an assembly\n";
4504     return 1;
4505   }
4506
4507   Handle(AIS_InteractiveObject) anIObj;
4508   if (!aMap.Find2 (anObject, anIObj))
4509   {
4510     // try to interpret second argument as child number
4511     if (anObjectNumber > 0 && anObjectNumber <= anAssembly->Children().Size())
4512     {
4513       Standard_Integer aCounter = 1;
4514       for (PrsMgr_ListOfPresentableObjectsIter anIter (anAssembly->Children()); anIter.More(); anIter.Next())
4515       {
4516         if (aCounter == anObjectNumber)
4517         {
4518           anIObj = Handle(AIS_InteractiveObject)::DownCast (anIter.Value());
4519           break;
4520         }
4521         ++aCounter;
4522       }
4523     }
4524     else
4525     {
4526       Message::SendFail ("Error: no active viewer");
4527       return 1;
4528     }    
4529   }
4530
4531   aContext->Disconnect (anAssembly, anIObj);
4532   aContext->UpdateCurrentViewer();
4533   return 0;
4534 }
4535
4536 //=======================================================================
4537 //function : VAddConnected
4538 //purpose  :
4539 //=======================================================================
4540 static Standard_Integer VAddConnected (Draw_Interpretor& ,
4541                                        Standard_Integer argc,
4542                                        const char ** argv)
4543 {
4544   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4545   if (aContext.IsNull())
4546   {
4547     Message::SendFail ("Error: no active viewer");
4548     return 1;
4549   }
4550
4551   if (argc != 6)
4552   {
4553     Message::SendFail ("Syntax error: expect 5 arguments");
4554     return 1;
4555   }
4556
4557   const TCollection_AsciiString aName (argv[1]);
4558   const Standard_Real aX = Draw::Atof (argv[2]);
4559   const Standard_Real aY = Draw::Atof (argv[3]);
4560   const Standard_Real aZ = Draw::Atof (argv[4]);
4561   const TCollection_AsciiString anObjectName (argv[5]);
4562
4563   // find object
4564   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
4565   Handle(AIS_MultipleConnectedInteractive) anAssembly;
4566   {
4567     Handle(AIS_InteractiveObject) aPrs;
4568     aMap.Find2 (aName, aPrs);
4569     anAssembly = Handle(AIS_MultipleConnectedInteractive)::DownCast (aPrs);
4570     if (anAssembly.IsNull())
4571     {
4572       Message::SendFail() << "Syntax error: '" << aName << "' is not an assembly";
4573       return 1;
4574     }
4575   }
4576
4577   Handle(AIS_InteractiveObject) anIObj = findConnectedObject (anObjectName);
4578   if (anIObj.IsNull())
4579   {
4580     Message::SendFail() << "Syntax error: '" << anObjectName << "' is not displayed";
4581     return 1;
4582   }
4583
4584   gp_Trsf aTrsf;
4585   aTrsf.SetTranslation (gp_Vec (aX, aY, aZ));
4586  
4587   anAssembly->Connect (anIObj, aTrsf);
4588   TheAISContext()->Display (anAssembly, Standard_False);
4589   TheAISContext()->RecomputeSelectionOnly (anAssembly);
4590   aContext->UpdateCurrentViewer();
4591   return 0;
4592 }
4593
4594 //=======================================================================
4595 //function : VListConnected
4596 //purpose  :
4597 //=======================================================================
4598 static Standard_Integer VListConnected (Draw_Interpretor& /*di*/,
4599                                         Standard_Integer argc,
4600                                         const char ** argv)
4601 {
4602   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4603   if (aContext.IsNull())
4604   {
4605     Message::SendFail ("Error: no active viewer");
4606     return 1;
4607   }
4608   
4609   if (argc != 2)
4610   {
4611     Message::SendFail() << "Syntax error: wrong number of arguments.\nUsage: " << argv[0] << " name";
4612     return 1;
4613   }
4614
4615   TCollection_AsciiString aName (argv[1]);
4616
4617   // find object
4618   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
4619   Handle(AIS_MultipleConnectedInteractive) anAssembly;
4620   if (!aMap.IsBound2 (aName) )
4621   {
4622     Message::SendFail ("Error: no active viewer");
4623     return 1;
4624   }
4625
4626   anAssembly = Handle(AIS_MultipleConnectedInteractive)::DownCast (aMap.Find2 (aName));
4627   if (anAssembly.IsNull())
4628   {
4629     Message::SendFail ("Syntax error: Not an assembly");
4630     return 1;
4631   }
4632
4633   std::cout << "Children of " << aName << ":\n";
4634
4635   Standard_Integer aCounter = 1;
4636   for (PrsMgr_ListOfPresentableObjectsIter anIter (anAssembly->Children()); anIter.More(); anIter.Next())
4637   {
4638     Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anIter.Value());
4639     if (GetMapOfAIS().IsBound1 (anObj))
4640     {
4641       TCollection_AsciiString aCuurrentName = GetMapOfAIS().Find1 (anObj);
4642       std::cout << aCounter << ")  " << aCuurrentName << "    (" << anIter.Value()->DynamicType()->Name() << ")";
4643     }
4644
4645     std::cout << aCounter << ")  " << anIter.Value()->DynamicType()->Name();
4646
4647     Handle(AIS_ConnectedInteractive) aConnected = Handle(AIS_ConnectedInteractive)::DownCast (anIter.Value());
4648     if (!aConnected.IsNull() && !aConnected->ConnectedTo().IsNull() && aMap.IsBound1 (aConnected->ConnectedTo()))
4649     {
4650       std::cout << " connected to " << aMap.Find1 (aConnected->ConnectedTo());
4651     }
4652     std::cout << std::endl;
4653     
4654     ++aCounter;
4655   }
4656
4657   return 0;
4658 }
4659
4660 //=======================================================================
4661 //function : VChild
4662 //purpose  :
4663 //=======================================================================
4664 static Standard_Integer VChild (Draw_Interpretor& ,
4665                                 Standard_Integer theNbArgs,
4666                                 const char** theArgVec)
4667 {
4668   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4669   if (aContext.IsNull())
4670   {
4671     Message::SendFail ("Error: no active viewer");
4672     return 1;
4673   }
4674
4675   int toAdd = -1;
4676   Handle(AIS_InteractiveObject) aParent;
4677   bool hasActions = false;
4678   int toInheritTrsf = -1;
4679   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
4680   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
4681   {
4682     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4683     anArg.LowerCase();
4684     if (anUpdateTool.parseRedrawMode (anArg))
4685     {
4686       continue;
4687     }
4688     else if (anArg == "-add")
4689     {
4690       toAdd = 1;
4691       continue;
4692     }
4693     else if (anArg == "-remove")
4694     {
4695       toAdd = 0;
4696       continue;
4697     }
4698     else if (anArg == "-inheritparenttrsf"
4699       || anArg == "-inheritparentloc"
4700       || anArg == "-inheritparentlocation"
4701       || anArg == "-inheritparent"
4702       || anArg == "-noinheritparenttrsf"
4703       || anArg == "-noinheritparentloc"
4704       || anArg == "-noinheritparentlocation"
4705       || anArg == "-noinheritparent"
4706       || anArg == "-ignoreparenttrsf"
4707       || anArg == "-ignoreparentloc"
4708       || anArg == "-ignoreparentlocation"
4709       || anArg == "-ignoreparent")
4710     {
4711       bool aVal = true;
4712       if (anArgIter + 1 < theNbArgs
4713         && Draw::ParseOnOff(theArgVec[anArgIter + 1], aVal))
4714       {
4715         ++anArgIter;
4716       }
4717       if (anArg.StartsWith("-no")
4718         || anArg.StartsWith("-ignore"))
4719       {
4720         aVal = !aVal;
4721       }
4722       toInheritTrsf = aVal ? 1 : 0;
4723       continue;
4724     }
4725
4726     Handle(AIS_InteractiveObject) aChild;
4727     if (!GetMapOfAIS().Find2 (theArgVec[anArgIter], aChild))
4728     {
4729       Message::SendFail() << "Syntax error: object '" << theArgVec[anArgIter] << "' is not found";
4730       return 1;
4731     }
4732
4733     if (aParent.IsNull())
4734     {
4735       aParent = aChild;
4736     }
4737     else if (toAdd == -1)
4738     {
4739       Message::SendFail ("Syntax error: no action specified");
4740       return 1;
4741     }
4742     else
4743     {
4744       hasActions = true;
4745       if (toAdd == 1)
4746       {
4747         if(toInheritTrsf == 0)
4748           aParent->AddChildWithCurrentTransformation(aChild);
4749         else
4750           aParent->AddChild (aChild);
4751       }
4752       else
4753       {
4754         if (toInheritTrsf == 0)
4755           aParent->RemoveChildWithRestoreTransformation(aChild);
4756         else
4757           aParent->RemoveChild (aChild);
4758       }
4759     }
4760   }
4761   if (!hasActions)
4762   {
4763     Message::SendFail ("Syntax error: not enough arguments");
4764     return 1;
4765   }
4766   return 0;
4767 }
4768
4769 //=======================================================================
4770 //function : VParent
4771 //purpose  :
4772 //=======================================================================
4773 static Standard_Integer VParent(Draw_Interpretor&,
4774   Standard_Integer theNbArgs,
4775   const char** theArgVec)
4776 {
4777   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4778   if (aContext.IsNull())
4779   {
4780     Message::SendFail ("Error: no active viewer");
4781     return 1;
4782   }
4783
4784   if (theNbArgs < 2 )
4785   {
4786     Message::SendFail ("Syntax error: wrong number of arguments");
4787     return 1;
4788   }
4789
4790   TCollection_AsciiString aName(theArgVec[1]);
4791   Handle(AIS_InteractiveObject) aParent;
4792   if (!GetMapOfAIS().Find2(theArgVec[1], aParent))
4793   {
4794     Message::SendFail() << "Syntax error: object '" << theArgVec[1] << "' is not found";
4795     return 1;
4796   }
4797
4798   ViewerTest_AutoUpdater anUpdateTool(aContext, ViewerTest::CurrentView());
4799   for (Standard_Integer anArgIter = 2; anArgIter < theNbArgs; ++anArgIter)
4800   {
4801     TCollection_AsciiString anArg(theArgVec[anArgIter]);
4802     anArg.LowerCase();
4803     if (anArg == "-ignorevisu")
4804       aParent->SetPropagateVisualState(Standard_False);
4805   }
4806   return 0;
4807 }
4808
4809 //===============================================================================================
4810 //function : VSetSelectionMode
4811 //purpose  : vselmode
4812 //===============================================================================================
4813 static Standard_Integer VSetSelectionMode (Draw_Interpretor& /*di*/,
4814                                            Standard_Integer  theNbArgs,
4815                                            const char**      theArgv)
4816 {
4817   // Check errors
4818   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4819   if (anAISContext.IsNull())
4820   {
4821     Message::SendFail ("Error: no active Viewer");
4822     return 1;
4823   }
4824
4825   NCollection_Sequence<TCollection_AsciiString> anObjNames;
4826   Standard_Integer aSelectionMode = -1;
4827   Standard_Boolean toTurnOn = Standard_True;
4828   AIS_SelectionModesConcurrency aSelModeConcurrency = AIS_SelectionModesConcurrency_GlobalOrLocal;
4829   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
4830   {
4831     TCollection_AsciiString anArgCase (theArgv[anArgIter]);
4832     anArgCase.LowerCase();
4833     if (anArgCase == "-set"
4834      || anArgCase == "-replace"
4835      || anArgCase == "-single"
4836      || anArgCase == "-exclusive")
4837     {
4838       aSelModeConcurrency = AIS_SelectionModesConcurrency_Single;
4839     }
4840     else if (anArgCase == "-add"
4841           || anArgCase == "-combine"
4842           || anArgCase == "-combination"
4843           || anArgCase == "-multiple")
4844     {
4845       aSelModeConcurrency = AIS_SelectionModesConcurrency_Multiple;
4846     }
4847     else if (anArgCase == "-globalorlocal"
4848           || anArgCase == "-localorglobal")
4849     {
4850       aSelModeConcurrency = AIS_SelectionModesConcurrency_GlobalOrLocal;
4851     }
4852     else
4853     {
4854       anObjNames.Append (theArgv[anArgIter]);
4855     }
4856   }
4857   if (anObjNames.Size() < 2
4858   || !Draw::ParseOnOff (anObjNames.Last().ToCString(), toTurnOn))
4859   {
4860     Message::SendFail ("Syntax error: wrong number of arguments");
4861     return 1;
4862   }
4863   anObjNames.Remove (anObjNames.Upper());
4864   {
4865     const TCollection_AsciiString aSelModeString = anObjNames.Last();
4866     anObjNames.Remove (anObjNames.Upper());
4867     TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
4868     if (aSelModeString.IsIntegerValue())
4869     {
4870       aSelectionMode = aSelModeString.IntegerValue();
4871     }
4872     else if (TopAbs::ShapeTypeFromString (aSelModeString.ToCString(), aShapeType))
4873     {
4874       aSelectionMode = AIS_Shape::SelectionMode (aShapeType);
4875     }
4876     else
4877     {
4878       Message::SendFail() << "Syntax error: unknown selection mode '" << aSelModeString  << "'";
4879       return 1;
4880     }
4881   }
4882
4883   AIS_ListOfInteractive aTargetIOs;
4884   for (NCollection_Sequence<TCollection_AsciiString>::Iterator anObjIter (anObjNames); anObjIter.More(); anObjIter.Next())
4885   {
4886     const TCollection_AsciiString& aNameIO = anObjIter.Value();
4887     Handle(AIS_InteractiveObject) anIO;
4888     GetMapOfAIS().Find2 (aNameIO, anIO);
4889     if (anIO.IsNull())
4890     {
4891       Message::SendFail() << "Syntax error: undefined presentable object " << aNameIO;
4892       return 1;
4893     }
4894     aTargetIOs.Append (anIO);
4895   }
4896   if (aTargetIOs.IsEmpty())
4897   {
4898     anAISContext->DisplayedObjects (aTargetIOs);
4899   }
4900
4901   for (AIS_ListIteratorOfListOfInteractive aTargetIt (aTargetIOs); aTargetIt.More(); aTargetIt.Next())
4902   {
4903     const Handle(AIS_InteractiveObject)& anIO = aTargetIt.Value();
4904     anAISContext->SetSelectionModeActive (anIO, aSelectionMode, toTurnOn, aSelModeConcurrency);
4905   }
4906   return 0;
4907 }
4908
4909 //===============================================================================================
4910 //function : VSelectionNext
4911 //purpose  : 
4912 //===============================================================================================
4913 static Standard_Integer VSelectionNext(Draw_Interpretor& /*theDI*/,
4914                                  Standard_Integer /*theArgsNb*/,
4915                                  const char** /*theArgVec*/)
4916 {
4917   // Check errors
4918   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4919   Handle(V3d_View) aView = ViewerTest::CurrentView();
4920
4921   if (anAISContext.IsNull())
4922   {
4923     Message::SendFail ("Error: no active viewer");
4924     return 1;
4925   }
4926
4927   anAISContext->HilightNextDetected (aView);
4928   return 0;
4929 }
4930
4931 //===============================================================================================
4932 //function : VSelectionPrevious
4933 //purpose  : 
4934 //===============================================================================================
4935 static Standard_Integer VSelectionPrevious(Draw_Interpretor& /*theDI*/,
4936                                  Standard_Integer /*theArgsNb*/,
4937                                  const char** /*theArgVec*/)
4938 {
4939   // Check errors
4940   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4941   Handle(V3d_View) aView = ViewerTest::CurrentView();
4942
4943   if (anAISContext.IsNull())
4944   {
4945     Message::SendFail ("Error: no active viewer");
4946     return 1;
4947   }
4948
4949   anAISContext->HilightPreviousDetected (aView);
4950   return 0;
4951 }
4952
4953 //===========================================================================
4954 //function : VTriangle 
4955 //Draw arg : vtriangle Name PointName PointName PointName
4956 //purpose  : creates and displays Triangle
4957 //===========================================================================
4958 static Standard_Integer VTriangle (Draw_Interpretor& /*di*/,
4959                                    Standard_Integer argc,
4960                                    const char ** argv)
4961 {
4962   const Standard_Boolean isTri = TCollection_AsciiString (argv[0]) == "vtriangle";
4963   Handle(Graphic3d_ArrayOfPrimitives) aPrims;
4964   if (isTri)
4965   {
4966     aPrims = new Graphic3d_ArrayOfTriangles (3);
4967   }
4968   else
4969   {
4970     aPrims = new Graphic3d_ArrayOfSegments (2);
4971   }
4972
4973   if (argc != (2 + aPrims->VertexNumberAllocated()))
4974   {
4975     Message::SendFail ("Syntax error: wrong number of arguments");
4976     return 1;
4977   }
4978
4979   gp_Pnt aPnts[3];
4980   for (Standard_Integer aPntIter = 0; aPntIter < aPrims->VertexNumberAllocated(); ++aPntIter)
4981   {
4982     const TCollection_AsciiString aName (argv[2 + aPntIter]);
4983     if (Handle(AIS_Point) aPntPrs = Handle(AIS_Point)::DownCast (GetMapOfAIS().IsBound2 (aName) ? GetMapOfAIS().Find2 (aName) : NULL))
4984     {
4985       aPnts[aPntIter] = aPntPrs->Component()->Pnt();
4986     }
4987     else
4988     {
4989       TopoDS_Shape aShape = DBRep::Get (argv[2 + aPntIter]);
4990       if (aShape.IsNull()
4991        || aShape.ShapeType() != TopAbs_VERTEX)
4992       {
4993         Message::SendFail() << "Syntax error: argument " << aName << " must be a point";
4994         return 1;
4995       }
4996       aPnts[aPntIter] = BRep_Tool::Pnt (TopoDS::Vertex (aShape));
4997     }
4998
4999     for (Standard_Integer aPnt2Iter = 0; aPnt2Iter < aPntIter; ++aPnt2Iter)
5000     {
5001       if (aPnts[aPnt2Iter].IsEqual (aPnts[aPntIter], Precision::Confusion()))
5002       {
5003         Message::SendFail ("Syntax error: points should not be equal");
5004         return 1;
5005       }
5006     }
5007
5008     aPrims->AddVertex (aPnts[aPntIter]);
5009   }
5010
5011   Handle(AIS_InteractiveObject) aPrs = new MyPArrayObject (aPrims);
5012   if (!isTri)
5013   {
5014     aPrs->Attributes()->SetupOwnShadingAspect();
5015     aPrs->Attributes()->ShadingAspect()->Aspect()->SetColor (aPrs->Attributes()->LineAspect()->Aspect()->Color());
5016   }
5017   ViewerTest::Display (argv[1], aPrs);
5018   return 0;
5019 }
5020
5021 //===========================================================================
5022 //function : VTorus
5023 //purpose  : creates and displays a torus or torus segment
5024 //===========================================================================
5025 static Standard_Integer VTorus (Draw_Interpretor& /*di*/,
5026                                 Standard_Integer theNbArgs,
5027                                 const char** theArgVec)
5028 {
5029   if (ViewerTest::GetAISContext().IsNull())
5030   {
5031     Message::SendFail ("Error: no active viewer");
5032     return 1;
5033   }
5034
5035   TCollection_AsciiString aName;
5036   Standard_Integer aNbSlices = 100, aNbStacks = 100;
5037   Standard_Real aMajorRad = -1.0, aMinorRad = -1.0;
5038   Standard_Real aPipeAngle = 360.0, aSegAngle1 = 0.0, aSegAngle2 = 360.0;
5039   Standard_Real anAngles[3] = { -1.0, -1.0, -1.0 };
5040   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
5041   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
5042   {
5043     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5044     anArg.LowerCase();
5045     if (anUpdateTool.parseRedrawMode (anArg))
5046     {
5047       continue;
5048     }
5049     else if (anArgIter + 1 < theNbArgs
5050           && (anArg == "-nbslices"
5051            || anArg == "-slices")
5052           && Draw::ParseInteger (theArgVec[anArgIter + 1], aNbSlices))
5053     {
5054       ++anArgIter;
5055     }
5056     else if (anArgIter + 1 < theNbArgs
5057           && (anArg == "-nbstacks"
5058            || anArg == "-stacks")
5059           && Draw::ParseInteger (theArgVec[anArgIter + 1], aNbStacks))
5060     {
5061       ++anArgIter;
5062     }
5063     else if (anArgIter + 1 < theNbArgs
5064           && (anArg == "-radius"
5065            || anArg == "-majorradius")
5066           && Draw::ParseReal (theArgVec[anArgIter + 1], aMajorRad))
5067     {
5068       ++anArgIter;
5069     }
5070     else if (anArgIter + 1 < theNbArgs
5071           && (anArg == "-piperadius"
5072            || anArg == "-minoradius")
5073           && Draw::ParseReal (theArgVec[anArgIter + 1], aMinorRad))
5074     {
5075       ++anArgIter;
5076     }
5077     else if (anArgIter + 1 < theNbArgs
5078           && (anArg == "-pipeangle"
5079            || anArg == "-angle")
5080           && Draw::ParseReal (theArgVec[anArgIter + 1], aPipeAngle))
5081     {
5082       ++anArgIter;
5083     }
5084     else if (anArgIter + 1 < theNbArgs
5085           && (anArg == "-segmentanglefrom"
5086            || anArg == "-seganglefrom"
5087            || anArg == "-segmentangle1"
5088            || anArg == "-segangle1")
5089           && Draw::ParseReal (theArgVec[anArgIter + 1], aSegAngle1))
5090     {
5091       ++anArgIter;
5092     }
5093     else if (anArgIter + 1 < theNbArgs
5094           && (anArg == "-segmentangleto"
5095            || anArg == "-segangleto"
5096            || anArg == "-segmentangle2"
5097            || anArg == "-segangle2")
5098           && Draw::ParseReal (theArgVec[anArgIter + 1], aSegAngle2))
5099     {
5100       ++anArgIter;
5101     }
5102     else if (aName.IsEmpty())
5103     {
5104       aName = theArgVec[anArgIter];
5105     }
5106     else if (aMajorRad < 0.0
5107           && Draw::ParseReal (theArgVec[anArgIter], aMajorRad))
5108     {
5109       //
5110     }
5111     else if (aMinorRad < 0.0
5112           && Draw::ParseReal (theArgVec[anArgIter], aMinorRad))
5113     {
5114       //
5115     }
5116     else if (anAngles[0] < 0.0
5117           && Draw::ParseReal (theArgVec[anArgIter], anAngles[0]))
5118     {
5119       //
5120     }
5121     else if (anAngles[1] < 0.0
5122           && Draw::ParseReal (theArgVec[anArgIter], anAngles[1]))
5123     {
5124       //
5125     }
5126     else if (anAngles[2] < 0.0
5127           && Draw::ParseReal (theArgVec[anArgIter], anAngles[2]))
5128     {
5129       //
5130     }
5131     else
5132     {
5133       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
5134       return 1;
5135     }
5136   }
5137
5138   if (anAngles[2] > 0.0)
5139   {
5140     aSegAngle1 = anAngles[0];
5141     aSegAngle2 = anAngles[1];
5142     aPipeAngle = anAngles[2];
5143   }
5144   else if (anAngles[1] > 0.0)
5145   {
5146     aSegAngle1 = anAngles[0];
5147     aSegAngle2 = anAngles[1];
5148   }
5149   else if (anAngles[0] > 0.0)
5150   {
5151     aPipeAngle = anAngles[0];
5152   }
5153
5154   aSegAngle1 = aSegAngle1 * (M_PI / 180.0);
5155   aSegAngle2 = aSegAngle2 * (M_PI / 180.0);
5156   aPipeAngle = aPipeAngle * (M_PI / 180.0);
5157
5158   if (aMajorRad <= 0 || aMinorRad <= 0 || aNbSlices <= 0 || aNbStacks <= 0
5159    || Abs(aSegAngle2 - aSegAngle1) <= Precision::Angular()
5160    || Abs(aPipeAngle) <= Precision::Angular())
5161   {
5162     Message::SendFail ("Syntax error: wrong parameters");
5163     return 1;
5164   }
5165
5166   Handle(Graphic3d_ArrayOfTriangles) aTriangles = Prs3d_ToolTorus::Create (aMajorRad, aMinorRad, aSegAngle1, aSegAngle2, aPipeAngle, aNbSlices, aNbStacks, gp_Trsf());
5167   Handle(AIS_InteractiveObject) anIO = new MyPArrayObject (aTriangles);
5168   ViewerTest::Display (aName, anIO, false);
5169   return 0;
5170 }
5171
5172 //===========================================================================
5173 //function : VCylinder
5174 //purpose  : creates and displays a cylinder
5175 //===========================================================================
5176 static Standard_Integer VCylinder (Draw_Interpretor& /*di*/,
5177                                    Standard_Integer theNbArgs,
5178                                    const char** theArgVec)
5179 {
5180   if (ViewerTest::GetAISContext().IsNull())
5181   {
5182     Message::SendFail ("Error: no active viewer");
5183     return 1;
5184   }
5185
5186   TCollection_AsciiString aName;
5187   Standard_Integer aNbSlices = 100, aNbStacks = 1;
5188   Standard_Real aBotRad = -1.0, aTopRad = -1.0, aHeight = -1.0;
5189   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
5190   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
5191   {
5192     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5193     anArg.LowerCase();
5194     if (anUpdateTool.parseRedrawMode (anArg))
5195     {
5196       continue;
5197     }
5198     else if (anArgIter + 1 < theNbArgs
5199           && (anArg == "-nbslices"
5200            || anArg == "-slices")
5201           && Draw::ParseInteger (theArgVec[anArgIter + 1], aNbSlices))
5202     {
5203       ++anArgIter;
5204     }
5205     else if (anArgIter + 1 < theNbArgs
5206           && (anArg == "-nbstacks"
5207            || anArg == "-stacks")
5208           && Draw::ParseInteger (theArgVec[anArgIter + 1], aNbStacks))
5209     {
5210       ++anArgIter;
5211     }
5212     else if (anArgIter + 1 < theNbArgs
5213           && anArg == "-radius"
5214           && Draw::ParseReal (theArgVec[anArgIter + 1], aBotRad))
5215     {
5216       aTopRad = aBotRad;
5217       ++anArgIter;
5218     }
5219     else if (anArgIter + 1 < theNbArgs
5220           && anArg == "-bottomradius"
5221           && Draw::ParseReal (theArgVec[anArgIter + 1], aBotRad))
5222     {
5223       ++anArgIter;
5224     }
5225     else if (anArgIter + 1 < theNbArgs
5226           && anArg == "-topradius"
5227           && Draw::ParseReal (theArgVec[anArgIter + 1], aTopRad))
5228     {
5229       ++anArgIter;
5230     }
5231     else if (anArgIter + 1 < theNbArgs
5232           && anArg == "-height"
5233           && Draw::ParseReal (theArgVec[anArgIter + 1], aHeight))
5234     {
5235       ++anArgIter;
5236     }
5237     else if (aName.IsEmpty())
5238     {
5239       aName = theArgVec[anArgIter];
5240     }
5241     else if (aBotRad < 0.0
5242           && Draw::ParseReal (theArgVec[anArgIter], aBotRad))
5243     {
5244       //
5245     }
5246     else if (aTopRad < 0.0
5247           && Draw::ParseReal (theArgVec[anArgIter], aTopRad))
5248     {
5249       //
5250     }
5251     else if (aHeight < 0.0
5252           && Draw::ParseReal (theArgVec[anArgIter], aHeight))
5253     {
5254       //
5255     }
5256     else
5257     {
5258       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
5259       return 1;
5260     }
5261   }
5262
5263   if (aBotRad < 0 || aTopRad < 0 || aHeight <= 0 || aNbSlices < 3)
5264   {
5265     Message::SendFail ("Syntax error: wrong parameters");
5266     return 1;
5267   }
5268
5269   Handle(Graphic3d_ArrayOfTriangles) aTriangles = Prs3d_ToolCylinder::Create (aBotRad, aTopRad, aHeight, aNbSlices, aNbStacks, gp_Trsf());
5270   Handle(AIS_InteractiveObject) anIO = new MyPArrayObject (aTriangles);
5271   ViewerTest::Display (aName, anIO, false);
5272   return 0;
5273 }
5274
5275 //===========================================================================
5276 //function : VSphere
5277 //purpose  : creates and displays a sphere
5278 //===========================================================================
5279 static Standard_Integer VSphere (Draw_Interpretor& /*di*/,
5280                                  Standard_Integer theNbArgs,
5281                                  const char** theArgVec)
5282 {
5283   if (ViewerTest::GetAISContext().IsNull())
5284   {
5285     Message::SendFail ("Error: no active viewer");
5286     return 1;
5287   }
5288
5289   TCollection_AsciiString aName;
5290   Standard_Integer aNbSlices = 100, aNbStacks = 100;
5291   Standard_Real aRad = -1.0;
5292   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
5293   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
5294   {
5295     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5296     anArg.LowerCase();
5297     if (anUpdateTool.parseRedrawMode (anArg))
5298     {
5299       continue;
5300     }
5301     else if (anArgIter + 1 < theNbArgs
5302           && (anArg == "-nbslices"
5303            || anArg == "-slices")
5304           && Draw::ParseInteger (theArgVec[anArgIter + 1], aNbSlices))
5305     {
5306       ++anArgIter;
5307     }
5308     else if (anArgIter + 1 < theNbArgs
5309           && (anArg == "-nbstacks"
5310            || anArg == "-stacks")
5311           && Draw::ParseInteger (theArgVec[anArgIter + 1], aNbStacks))
5312     {
5313       ++anArgIter;
5314     }
5315     else if (anArgIter + 1 < theNbArgs
5316           && anArg == "-radius"
5317           && Draw::ParseReal (theArgVec[anArgIter + 1], aRad))
5318     {
5319       ++anArgIter;
5320     }
5321     else if (aName.IsEmpty())
5322     {
5323       aName = theArgVec[anArgIter];
5324     }
5325     else if (aRad < 0.0
5326           && Draw::ParseReal (theArgVec[anArgIter], aRad))
5327     {
5328       //
5329     }
5330     else
5331     {
5332       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
5333       return 1;
5334     }
5335   }
5336
5337   if (aRad <= 0 || aNbSlices <= 0 || aNbStacks <= 0)
5338   {
5339     Message::SendFail ("Syntax error: wrong parameters");
5340     return 1;
5341   }
5342
5343   Handle(Graphic3d_ArrayOfTriangles) aTriangles = Prs3d_ToolSphere::Create (aRad, aNbSlices, aNbStacks, gp_Trsf());
5344   Handle(AIS_InteractiveObject) anIO = new MyPArrayObject (aTriangles);
5345   ViewerTest::Display (aName, anIO, false);
5346   return 0;
5347 }
5348
5349 //=======================================================================
5350 //function : VObjZLayer
5351 //purpose  : Set or get z layer id for presentable object
5352 //=======================================================================
5353
5354 static Standard_Integer VObjZLayer (Draw_Interpretor& di,
5355                                     Standard_Integer argc,
5356                                     const char ** argv)
5357 {
5358   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5359   if (aContext.IsNull())
5360   {
5361     Message::SendFail ("Error: no active viewer");
5362     return 1;
5363   }
5364
5365   // get operation
5366   TCollection_AsciiString aOperation;
5367   if (argc >= 2)
5368     aOperation = TCollection_AsciiString (argv [1]);
5369
5370   // check for correct arguments
5371   if (!(argc == 4 && aOperation.IsEqual ("set")) &&
5372       !(argc == 3 && aOperation.IsEqual ("get")))
5373   {
5374     di << "Usage : " << argv[0] << " set/get object [layerid]\n";
5375     di << " set - set layer id for interactive object, layerid - z layer id\n";
5376     di << " get - get layer id of interactive object\n";
5377     di << " argument layerid should be passed for set operation only\n";
5378     return 1;
5379   }
5380
5381   // find object
5382   TCollection_AsciiString aName (argv[2]);
5383   Handle(AIS_InteractiveObject) anInterObj;
5384   GetMapOfAIS().Find2 (aName, anInterObj);
5385   if (anInterObj.IsNull())
5386   {
5387     Message::SendFail() << "Syntax error: object '" << aName << "' is not displayed";
5388     return 1;
5389   }
5390
5391   // process operation
5392   if (aOperation.IsEqual ("set"))
5393   {
5394     Standard_Integer aLayerId = Draw::Atoi (argv [3]);
5395     aContext->SetZLayer (anInterObj, aLayerId);
5396   }
5397   else if (aOperation.IsEqual ("get"))
5398   {
5399     di << "Z layer id: " << aContext->GetZLayer (anInterObj);
5400   }
5401   
5402   return 0;
5403 }
5404
5405 //=======================================================================
5406 //function : VPolygonOffset
5407 //purpose  : Set or get polygon offset parameters
5408 //=======================================================================
5409 static Standard_Integer VPolygonOffset(Draw_Interpretor& /*di*/,
5410                                        Standard_Integer argc,
5411                                        const char ** argv)
5412 {
5413   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5414   if (aContext.IsNull())
5415   {
5416     Message::SendFail ("Error: no active viewer");
5417     return 1;
5418   }
5419
5420   if (argc > 2 && argc != 5)
5421   {
5422     Message::SendFail() << "Syntax error: wrong number of arguments.\n"
5423                            "Usage: " << argv[0] << " [object [mode factor units]] - sets/gets polygon offset parameters for an object,"
5424                            "without arguments prints the default values";
5425     return 1;
5426   }
5427
5428   // find object
5429   Handle(AIS_InteractiveObject) anInterObj;
5430   if (argc >= 2)
5431   {
5432     TCollection_AsciiString aName (argv[1]);
5433     if (!GetMapOfAIS().Find2 (aName, anInterObj)
5434       || anInterObj.IsNull())
5435     {
5436       Message::SendFail() << "Syntax error: object '" << aName << "' is not displayed";
5437       return 1;
5438     }
5439   }
5440
5441   Standard_Integer aMode;
5442   Standard_ShortReal    aFactor, aUnits;
5443   if (argc == 5)
5444   {
5445     aMode   = Draw::Atoi(argv[2]);
5446     aFactor = (Standard_ShortReal) Draw::Atof(argv[3]);
5447     aUnits  = (Standard_ShortReal) Draw::Atof(argv[4]);
5448
5449     anInterObj->SetPolygonOffsets(aMode, aFactor, aUnits);
5450     aContext->UpdateCurrentViewer();
5451     return 0;
5452   }
5453   else if (argc == 2)
5454   {
5455     if (anInterObj->HasPolygonOffsets())
5456     {
5457       anInterObj->PolygonOffsets(aMode, aFactor, aUnits);
5458       std::cout << "Current polygon offset parameters for " << argv[1] << ":" << std::endl;
5459       std::cout << "\tMode: "   << aMode   << std::endl;
5460       std::cout << "\tFactor: " << aFactor << std::endl;
5461       std::cout << "\tUnits: "  << aUnits  << std::endl;
5462       return 0;
5463     }
5464     else
5465     {
5466       std::cout << "Specific polygon offset parameters are not set for " << argv[1] << std::endl;
5467     }
5468   }
5469
5470   std::cout << "Default polygon offset parameters:" << std::endl;
5471   aContext->DefaultDrawer()->ShadingAspect()->Aspect()->PolygonOffsets(aMode, aFactor, aUnits);
5472   std::cout << "\tMode: "   << aMode   << std::endl;
5473   std::cout << "\tFactor: " << aFactor << std::endl;
5474   std::cout << "\tUnits: "  << aUnits  << std::endl;
5475
5476   return 0;
5477 }
5478
5479 // This class is used for testing markers.
5480 class ViewerTest_MarkersArrayObject : public AIS_InteractiveObject
5481 {
5482
5483 public:
5484
5485   ViewerTest_MarkersArrayObject (const gp_XYZ& theStartPoint,
5486                                  const Standard_Integer& thePointsOnSide,
5487                                  Handle(Graphic3d_AspectMarker3d) theMarkerAspect = NULL)
5488   {
5489     myStartPoint = theStartPoint;
5490     myPointsOnSide = thePointsOnSide;
5491     myMarkerAspect = theMarkerAspect;
5492   }
5493
5494   DEFINE_STANDARD_RTTI_INLINE(ViewerTest_MarkersArrayObject,AIS_InteractiveObject);
5495
5496 private:
5497
5498   virtual void Compute (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
5499                         const Handle(Prs3d_Presentation)& thePrs,
5500                         const Standard_Integer theMode) Standard_OVERRIDE;
5501
5502   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
5503                                  const Standard_Integer theMode) Standard_OVERRIDE;
5504
5505 protected:
5506
5507   gp_XYZ myStartPoint;
5508   Standard_Integer myPointsOnSide;
5509   Handle(Graphic3d_AspectMarker3d) myMarkerAspect;
5510 };
5511
5512
5513 void ViewerTest_MarkersArrayObject::Compute (const Handle(PrsMgr_PresentationManager)& ,
5514                                              const Handle(Prs3d_Presentation)& aPresentation,
5515                                              const Standard_Integer )
5516 {
5517   Handle(Graphic3d_ArrayOfPrimitives) anArray = new Graphic3d_ArrayOfPoints ((Standard_Integer )Pow (myPointsOnSide, 3), myPointsOnSide != 1);
5518   if (myPointsOnSide == 1)
5519   {
5520     anArray->AddVertex (myStartPoint);
5521   }
5522   else
5523   {
5524     for (Standard_Real i = 1; i <= myPointsOnSide; i++)
5525     {
5526       for (Standard_Real j = 1; j <= myPointsOnSide; j++)
5527       {
5528         for (Standard_Real k = 1; k <= myPointsOnSide; k++)
5529         {
5530           anArray->AddVertex (myStartPoint.X() + i, myStartPoint.Y() + j, myStartPoint.Z() + k);
5531           anArray->SetVertexColor (anArray->VertexNumber(),
5532                                    i / myPointsOnSide,
5533                                    j / myPointsOnSide,
5534                                    k / myPointsOnSide);
5535         }
5536       }
5537     }
5538   }
5539
5540   aPresentation->Clear();
5541   if (!myMarkerAspect.IsNull())
5542   {
5543     aPresentation->CurrentGroup()->SetGroupPrimitivesAspect (myMarkerAspect);
5544   }
5545   aPresentation->CurrentGroup()->AddPrimitiveArray (anArray);
5546 }
5547
5548 void ViewerTest_MarkersArrayObject::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
5549                                        const Standard_Integer /*theMode*/)
5550 {
5551   Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this);
5552
5553   if (myPointsOnSide == 1)
5554   {
5555     gp_Pnt aPoint (myStartPoint);
5556     Handle(Select3D_SensitivePoint) aSensetivePoint = new Select3D_SensitivePoint (anEntityOwner, aPoint);
5557     theSelection->Add (aSensetivePoint);
5558   }
5559   else
5560   {
5561     for (Standard_Real i = 1; i <= myPointsOnSide; i++)
5562     {
5563       for (Standard_Real j = 1; j <= myPointsOnSide; j++)
5564       {
5565         for (Standard_Real k = 1; k <= myPointsOnSide; k++)
5566         {
5567           gp_Pnt aPoint (myStartPoint.X() + i, myStartPoint.Y() + j, myStartPoint.Z() + k);
5568           Handle(Select3D_SensitivePoint) aSensetivePoint = new Select3D_SensitivePoint (anEntityOwner, aPoint);
5569           theSelection->Add (aSensetivePoint);
5570         }
5571       }
5572     }
5573   }
5574 }
5575 //=======================================================================
5576 //function : VMarkersTest
5577 //purpose  : Draws an array of markers for testing purposes.
5578 //=======================================================================
5579 static Standard_Integer VMarkersTest (Draw_Interpretor&,
5580                                       Standard_Integer  theArgNb,
5581                                       const char**      theArgVec)
5582 {
5583   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5584   if (aContext.IsNull())
5585   {
5586     Message::SendFail ("Error: no active viewer");
5587     return 1;
5588   }
5589
5590   if (theArgNb < 5)
5591   {
5592     Message::SendFail ("Syntax error: wrong number of arguments");
5593     return 1;
5594   }
5595
5596   Standard_Integer anArgIter = 1;
5597
5598   TCollection_AsciiString aName (theArgVec[anArgIter++]);
5599   TCollection_AsciiString aFileName;
5600   gp_XYZ aPnt (Atof (theArgVec[anArgIter]),
5601                Atof (theArgVec[anArgIter + 1]),
5602                Atof (theArgVec[anArgIter + 2]));
5603   anArgIter += 3;
5604
5605   Standard_Integer aPointsOnSide = 10;
5606   Standard_Integer aMarkerType   = -1;
5607   Standard_Real    aScale        = 1.0;
5608   for (; anArgIter < theArgNb; ++anArgIter)
5609   {
5610     const TCollection_AsciiString anArg (theArgVec[anArgIter]);
5611     if (anArg.Search ("PointsOnSide=") > -1)
5612     {
5613       aPointsOnSide = anArg.Token ("=", 2).IntegerValue();
5614     }
5615     else if (anArg.Search ("MarkerType=") > -1)
5616     {
5617       aMarkerType = anArg.Token ("=", 2).IntegerValue();
5618     }
5619     else if (anArg.Search ("Scale=") > -1)
5620     {
5621       aScale = anArg.Token ("=", 2).RealValue();
5622     }
5623     else if (anArg.Search ("FileName=") > -1)
5624     {
5625       aFileName = anArg.Token ("=", 2);
5626     }
5627     else
5628     {
5629       Message::SendFail() << "Syntax error: wrong argument '" << anArg << "'";
5630       return 1;
5631     }
5632   }
5633
5634   Handle(Graphic3d_AspectMarker3d) anAspect;
5635   Handle(Image_AlienPixMap) anImage;
5636   Quantity_Color aColor (Quantity_NOC_GREEN1);
5637   if ((aMarkerType == Aspect_TOM_USERDEFINED || aMarkerType < 0)
5638    && !aFileName.IsEmpty())
5639   {
5640     anImage = new Image_AlienPixMap();
5641     if (!anImage->Load (aFileName))
5642     {
5643       Message::SendFail() << "Error: could not load image from file '" << aFileName << "'!";
5644       return 1;
5645     }
5646     if (anImage->Format() == Image_Format_Gray)
5647     {
5648       anImage->SetFormat (Image_Format_Alpha);
5649     }
5650     else if (anImage->Format() == Image_Format_GrayF)
5651     {
5652       anImage->SetFormat (Image_Format_AlphaF);
5653     }
5654     anAspect = new Graphic3d_AspectMarker3d (anImage);
5655   }
5656   else
5657   {
5658     anAspect = new Graphic3d_AspectMarker3d (aMarkerType >= 0 ? (Aspect_TypeOfMarker )aMarkerType : Aspect_TOM_POINT, aColor, aScale);
5659   }
5660
5661   Handle(ViewerTest_MarkersArrayObject) aMarkersArray = new ViewerTest_MarkersArrayObject (aPnt, aPointsOnSide, anAspect);
5662   VDisplayAISObject (aName, aMarkersArray);
5663
5664   return 0;
5665 }
5666
5667 //=======================================================================
5668 //function : TextToBrep
5669 //purpose  : Tool for conversion text to occt-shapes
5670 //=======================================================================
5671 static int TextToBRep (Draw_Interpretor& /*theDI*/,
5672                        Standard_Integer  theArgNb,
5673                        const char**      theArgVec)
5674 {
5675   // Check arguments
5676   if (theArgNb < 3)
5677   {
5678     Message::SendFail() << "Error: " << theArgVec[0] << " - invalid syntax";
5679     return 1;
5680   }
5681
5682   Standard_Integer anArgIt = 1;
5683   Standard_CString aName   = theArgVec[anArgIt++];
5684   Standard_CString aText   = theArgVec[anArgIt++];
5685
5686   Font_BRepFont           aFont;
5687   TCollection_AsciiString aFontName ("Courier");
5688   Standard_Real           aTextHeight        = 16.0;
5689   Font_FontAspect         aFontAspect        = Font_FA_Regular;
5690   Standard_Boolean        anIsCompositeCurve = Standard_False;
5691   gp_Ax3                  aPenAx3    (gp::XOY());
5692   gp_Dir                  aNormal    (0.0, 0.0, 1.0);
5693   gp_Dir                  aDirection (1.0, 0.0, 0.0);
5694   gp_Pnt                  aPenLoc;
5695
5696   Graphic3d_HorizontalTextAlignment aHJustification = Graphic3d_HTA_LEFT;
5697   Graphic3d_VerticalTextAlignment   aVJustification = Graphic3d_VTA_BOTTOM;
5698   Font_StrictLevel aStrictLevel = Font_StrictLevel_Any;
5699   for (; anArgIt < theArgNb; ++anArgIt)
5700   {
5701     TCollection_AsciiString aParam (theArgVec[anArgIt]);
5702     aParam.LowerCase();
5703
5704     if (aParam == "-pos"
5705      || aParam == "-position")
5706     {
5707       if (anArgIt + 3 >= theArgNb)
5708       {
5709         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
5710         return 1;
5711       }
5712
5713       aPenLoc.SetX (Draw::Atof(theArgVec[++anArgIt]));
5714       aPenLoc.SetY (Draw::Atof(theArgVec[++anArgIt]));
5715       aPenLoc.SetZ (Draw::Atof(theArgVec[++anArgIt]));
5716     }
5717     else if (aParam == "-halign")
5718     {
5719       if (++anArgIt >= theArgNb)
5720       {
5721         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
5722         return 1;
5723       }
5724
5725       TCollection_AsciiString aType (theArgVec[anArgIt]);
5726       aType.LowerCase();
5727       if (aType == "left")
5728       {
5729         aHJustification = Graphic3d_HTA_LEFT;
5730       }
5731       else if (aType == "center")
5732       {
5733         aHJustification = Graphic3d_HTA_CENTER;
5734       }
5735       else if (aType == "right")
5736       {
5737         aHJustification = Graphic3d_HTA_RIGHT;
5738       }
5739       else
5740       {
5741         Message::SendFail() << "Error: wrong syntax at '" << aParam << "'";
5742         return 1;
5743       }
5744     }
5745     else if (aParam == "-valign")
5746     {
5747       if (++anArgIt >= theArgNb)
5748       {
5749         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
5750         return 1;
5751       }
5752
5753       TCollection_AsciiString aType (theArgVec[anArgIt]);
5754       aType.LowerCase();
5755       if (aType == "top")
5756       {
5757         aVJustification = Graphic3d_VTA_TOP;
5758       }
5759       else if (aType == "center")
5760       {
5761         aVJustification = Graphic3d_VTA_CENTER;
5762       }
5763       else if (aType == "bottom")
5764       {
5765         aVJustification = Graphic3d_VTA_BOTTOM;
5766       }
5767       else if (aType == "topfirstline")
5768       {
5769         aVJustification = Graphic3d_VTA_TOPFIRSTLINE;
5770       }
5771       else
5772       {
5773         Message::SendFail() << "Error: wrong syntax at '" << aParam << "'";
5774         return 1;
5775       }
5776     }
5777     else if (aParam == "-height")
5778     {
5779       if (++anArgIt >= theArgNb)
5780       {
5781         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
5782         return 1;
5783       }
5784
5785       aTextHeight = Draw::Atof(theArgVec[anArgIt]);
5786     }
5787     else if (aParam == "-aspect")
5788     {
5789       if (++anArgIt >= theArgNb)
5790       {
5791         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
5792         return 1;
5793       }
5794
5795       TCollection_AsciiString anOption (theArgVec[anArgIt]);
5796       anOption.LowerCase();
5797       if (!parseFontStyle (anOption, aFontAspect))
5798       {
5799         Message::SendFail() << "Error: unknown font aspect '" << anOption << "'";
5800         return 1;
5801       }
5802     }
5803     else if (aParam == "-font")
5804     {
5805       if (++anArgIt >= theArgNb)
5806       {
5807         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
5808         return 1;
5809       }
5810
5811       aFontName = theArgVec[anArgIt];
5812     }
5813     else if (aParam == "-strict")
5814     {
5815       anArgIt += parseFontStrictLevel (theArgNb  - anArgIt - 1,
5816                                        theArgVec + anArgIt + 1,
5817                                        aStrictLevel);
5818     }
5819     else if (aParam == "-composite")
5820     {
5821       if (++anArgIt >= theArgNb)
5822       {
5823         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
5824         return 1;
5825       }
5826
5827       Draw::ParseOnOff (theArgVec[anArgIt], anIsCompositeCurve);
5828     }
5829     else if (aParam == "-plane")
5830     {
5831       if (anArgIt + 6 >= theArgNb)
5832       {
5833         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
5834         return 1;
5835       }
5836
5837       Standard_Real aX = Draw::Atof (theArgVec[++anArgIt]);
5838       Standard_Real aY = Draw::Atof (theArgVec[++anArgIt]);
5839       Standard_Real aZ = Draw::Atof (theArgVec[++anArgIt]);
5840       aNormal.SetCoord (aX, aY, aZ);
5841
5842       aX = Draw::Atof (theArgVec[++anArgIt]);
5843       aY = Draw::Atof (theArgVec[++anArgIt]);
5844       aZ = Draw::Atof (theArgVec[++anArgIt]);
5845       aDirection.SetCoord (aX, aY, aZ);
5846     }
5847     else
5848     {
5849       Message::SendFail() << "Warning! Unknown argument '" << aParam << "'";
5850     }
5851   }
5852
5853   aFont.SetCompositeCurveMode (anIsCompositeCurve);
5854   if (!aFont.FindAndInit (aFontName.ToCString(), aFontAspect, aTextHeight, aStrictLevel))
5855   {
5856     Message::SendFail ("Error: unable to load Font");
5857     return 1;
5858   }
5859
5860   aPenAx3 = gp_Ax3 (aPenLoc, aNormal, aDirection);
5861
5862   Font_BRepTextBuilder aBuilder;
5863   DBRep::Set (aName, aBuilder.Perform (aFont, aText, aPenAx3, aHJustification, aVJustification));
5864   return 0;
5865 }
5866
5867 //=======================================================================
5868 //function : VFont
5869 //purpose  : Font management
5870 //=======================================================================
5871 struct FontComparator
5872 {
5873   bool operator() (const Handle(Font_SystemFont)& theFontA,
5874                    const Handle(Font_SystemFont)& theFontB)
5875   {
5876     return theFontA->FontKey().IsLess (theFontB->FontKey());
5877   }
5878 };
5879
5880 static int VFont (Draw_Interpretor& theDI,
5881                   Standard_Integer  theArgNb,
5882                   const char**      theArgVec)
5883 {
5884   Handle(Font_FontMgr) aMgr = Font_FontMgr::GetInstance();
5885   bool toPrintList = theArgNb < 2, toPrintNames = false;
5886   Font_StrictLevel aStrictLevel = Font_StrictLevel_Any;
5887   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5888   {
5889     const TCollection_AsciiString anArg (theArgVec[anArgIter]);
5890     TCollection_AsciiString anArgCase (anArg);
5891     anArgCase.LowerCase();
5892     if (anArgCase == "-strict")
5893     {
5894       anArgIter += parseFontStrictLevel (theArgNb  - anArgIter - 1,
5895                                          theArgVec + anArgIter + 1,
5896                                          aStrictLevel);
5897     }
5898     else if (anArgCase == "-clear")
5899     {
5900       aMgr->ClearFontDataBase();
5901     }
5902     else if (anArgCase == "-init")
5903     {
5904       aMgr->InitFontDataBase();
5905     }
5906     else if (anArgCase == "-list")
5907     {
5908       toPrintList = true;
5909     }
5910     else if (anArgCase == "-names")
5911     {
5912       toPrintList = true;
5913       toPrintNames = true;
5914     }
5915     else if (anArgIter + 1 < theArgNb
5916           && (anArgCase == "-find"
5917            || anArgCase == "-findinfo"
5918            || anArgCase == "-findall"
5919            || anArgCase == "find"))
5920     {
5921       const TCollection_AsciiString aFontName (theArgVec[++anArgIter]);
5922       Font_FontAspect aFontAspect = Font_FA_Undefined;
5923       if (++anArgIter < theArgNb)
5924       {
5925         anArgCase = theArgVec[anArgIter];
5926         anArgCase.LowerCase();
5927         if (!parseFontStyle (anArgCase, aFontAspect))
5928         {
5929           --anArgIter;
5930         }
5931       }
5932
5933       const bool toFindAll   = (anArgCase == "-findall");
5934       const bool toPrintInfo = (anArgCase == "-findinfo");
5935       TCollection_AsciiString aResult;
5936       if (toFindAll
5937        || aFontName.Search ("*") != -1)
5938       {
5939         const Font_NListOfSystemFont aFonts = aMgr->GetAvailableFonts();
5940         std::vector<Handle(Font_SystemFont)> aFontsSorted;
5941         aFontsSorted.reserve (aFonts.Size());
5942         for (Font_NListOfSystemFont::Iterator aFontIter (aFonts); aFontIter.More(); aFontIter.Next())
5943         {
5944           aFontsSorted.push_back (aFontIter.Value());
5945         }
5946         std::stable_sort (aFontsSorted.begin(), aFontsSorted.end(), FontComparator());
5947         for (std::vector<Handle(Font_SystemFont)>::iterator aFontIter = aFontsSorted.begin(); aFontIter != aFontsSorted.end(); ++aFontIter)
5948         {
5949           const Handle(Font_SystemFont)& aFont = *aFontIter;
5950           const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match -nocase \"") + aFontName + "\" \"" + aFont->FontName() + "\"";
5951           if (theDI.Eval (aCheck.ToCString()) == 0
5952           && *theDI.Result() != '1')
5953           {
5954             theDI.Reset();
5955             continue;
5956           }
5957
5958           theDI.Reset();
5959           if (!aResult.IsEmpty())
5960           {
5961             aResult += "\n";
5962           }
5963
5964           aResult += toPrintInfo ? aFont->ToString() : aFont->FontName();
5965           if (!toFindAll)
5966           {
5967             break;
5968           }
5969         }
5970       }
5971       else if (Handle(Font_SystemFont) aFont = aMgr->FindFont (aFontName, aStrictLevel, aFontAspect))
5972       {
5973         aResult = toPrintInfo ? aFont->ToString() : aFont->FontName();
5974       }
5975
5976       if (!aResult.IsEmpty())
5977       {
5978         theDI << aResult;
5979       }
5980       else
5981       {
5982         Message::SendFail() << "Error: font '" << aFontName << "' is not found";
5983       }
5984     }
5985     else if (anArgIter + 1 < theArgNb
5986           && (anArgCase == "-add"
5987            || anArgCase == "add"
5988            || anArgCase == "-register"
5989            || anArgCase == "register"))
5990     {
5991       ++anArgIter;
5992       Standard_CString aFontPath = theArgVec[anArgIter++];
5993       TCollection_AsciiString aFontName;
5994       Font_FontAspect  aFontAspect = Font_FA_Undefined;
5995       Standard_Integer isSingelStroke = -1;
5996       for (; anArgIter < theArgNb; ++anArgIter)
5997       {
5998         anArgCase = theArgVec[anArgIter];
5999         anArgCase.LowerCase();
6000         if (aFontAspect == Font_FontAspect_UNDEFINED
6001          && parseFontStyle (anArgCase, aFontAspect))
6002         {
6003           continue;
6004         }
6005         else if (anArgCase == "singlestroke"
6006               || anArgCase == "singleline"
6007               || anArgCase == "oneline")
6008         {
6009           isSingelStroke = 1;
6010         }
6011         else if (aFontName.IsEmpty())
6012         {
6013           aFontName = theArgVec[anArgIter];
6014         }
6015         else
6016         {
6017           --anArgIter;
6018           break;
6019         }
6020       }
6021
6022       Handle(Font_SystemFont) aFont = aMgr->CheckFont (aFontPath);
6023       if (aFont.IsNull())
6024       {
6025         Message::SendFail() << "Error: font '" << aFontPath << "' is not found!";
6026         continue;
6027       }
6028
6029       if (aFontAspect != Font_FontAspect_UNDEFINED
6030       || !aFontName.IsEmpty())
6031       {
6032         TCollection_AsciiString aName = aFont->FontName();
6033         if (!aFontName.IsEmpty())
6034         {
6035           aName = aFontName;
6036         }
6037         Handle(Font_SystemFont) aFont2 = new Font_SystemFont (aName);
6038         if (aFontAspect != Font_FontAspect_UNDEFINED)
6039         {
6040           aFont2->SetFontPath (aFontAspect, aFontPath, 0);
6041         }
6042         else
6043         {
6044           for (int anAspectIter = 0; anAspectIter < Font_FontAspect_NB; ++anAspectIter)
6045           {
6046             aFont2->SetFontPath ((Font_FontAspect )anAspectIter,
6047                                  aFont->FontPath ((Font_FontAspect )anAspectIter),
6048                                  aFont->FontFaceId ((Font_FontAspect )anAspectIter));
6049           }
6050         }
6051         aFont = aFont2;
6052       }
6053       if (isSingelStroke != -1)
6054       {
6055         aFont->SetSingleStrokeFont (isSingelStroke == 1);
6056       }
6057
6058       aMgr->RegisterFont (aFont, Standard_True);
6059       theDI << aFont->ToString();
6060     }
6061     else if (anArgCase == "-aliases")
6062     {
6063       TCollection_AsciiString anAliasName;
6064       TColStd_SequenceOfHAsciiString aNames;
6065       if (anArgIter + 1 < theArgNb
6066       && *theArgVec[anArgIter + 1] != '-')
6067       {
6068         anAliasName = theArgVec[++anArgIter];
6069       }
6070       if (!anAliasName.IsEmpty())
6071       {
6072         aMgr->GetFontAliases (aNames, anAliasName);
6073       }
6074       else
6075       {
6076         aMgr->GetAllAliases (aNames);
6077       }
6078       for (TColStd_SequenceOfHAsciiString::Iterator aNameIter (aNames); aNameIter.More(); aNameIter.Next())
6079       {
6080         theDI << "{" << aNameIter.Value()->String() << "} ";
6081       }
6082     }
6083     else if (anArgIter + 2 < theArgNb
6084           && anArgCase == "-addalias")
6085     {
6086       TCollection_AsciiString anAliasName(theArgVec[++anArgIter]);
6087       TCollection_AsciiString aFontName  (theArgVec[++anArgIter]);
6088       aMgr->AddFontAlias (anAliasName, aFontName);
6089     }
6090     else if (anArgIter + 2 < theArgNb
6091           && anArgCase == "-removealias")
6092     {
6093       TCollection_AsciiString anAliasName(theArgVec[++anArgIter]);
6094       TCollection_AsciiString aFontName  (theArgVec[++anArgIter]);
6095       aMgr->RemoveFontAlias (anAliasName, aFontName);
6096     }
6097     else if (anArgIter + 1 < theArgNb
6098           && anArgCase == "-clearalias")
6099     {
6100       TCollection_AsciiString anAliasName(theArgVec[++anArgIter]);
6101       aMgr->RemoveFontAlias (anAliasName, "");
6102     }
6103     else if (anArgCase == "-clearaliases")
6104     {
6105       aMgr->RemoveFontAlias ("", "");
6106     }
6107     else if (anArgCase == "-verbose"
6108           || anArgCase == "-trace")
6109     {
6110       bool toEnable = true;
6111       if (anArgIter + 1 < theArgNb
6112        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6113       {
6114         ++anArgIter;
6115       }
6116       aMgr->SetTraceAliases (toEnable);
6117     }
6118     else if (anArgCase == "-unicodefallback"
6119           || anArgCase == "-fallback"
6120           || anArgCase == "-touseunicodesubsetfallback")
6121     {
6122       bool toEnable = true;
6123       if (anArgIter + 1 < theArgNb
6124        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6125       {
6126         ++anArgIter;
6127       }
6128       Font_FontMgr::ToUseUnicodeSubsetFallback() = toEnable;
6129     }
6130     else
6131     {
6132       Message::SendFail() << "Warning! Unknown argument '" << anArg << "'";
6133     }
6134   }
6135
6136   if (toPrintList)
6137   {
6138     // just print the list of available fonts
6139     Standard_Boolean isFirst = Standard_True;
6140     const Font_NListOfSystemFont aFonts = aMgr->GetAvailableFonts();
6141     std::vector<Handle(Font_SystemFont)> aFontsSorted;
6142     aFontsSorted.reserve (aFonts.Size());
6143     for (Font_NListOfSystemFont::Iterator aFontIter (aFonts); aFontIter.More(); aFontIter.Next())
6144     {
6145       aFontsSorted.push_back (aFontIter.Value());
6146     }
6147     std::stable_sort (aFontsSorted.begin(), aFontsSorted.end(), FontComparator());
6148     for (std::vector<Handle(Font_SystemFont)>::iterator aFontIter = aFontsSorted.begin(); aFontIter != aFontsSorted.end(); ++aFontIter)
6149     {
6150       const Handle(Font_SystemFont)& aFont = *aFontIter;
6151
6152       if (toPrintNames)
6153       {
6154         if (!isFirst)
6155         {
6156           theDI << "\n";
6157         }
6158         theDI << "\"" << aFont->FontName() << "\"";
6159       }
6160       else
6161       {
6162         if (!isFirst)
6163         {
6164           theDI << "\n";
6165         }
6166         theDI << aFont->ToString();
6167       }
6168       isFirst = Standard_False;
6169     }
6170     return 0;
6171   }
6172
6173   return 0;
6174 }
6175
6176 //=======================================================================
6177 //function : VVertexMode
6178 //purpose  : Switches vertex display mode for AIS_Shape or displays the current value
6179 //=======================================================================
6180
6181 static int VVertexMode (Draw_Interpretor& theDI,
6182                          Standard_Integer  theArgNum,
6183                          const char**      theArgs)
6184 {
6185   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6186   if (aContext.IsNull())
6187   {
6188     Message::SendFail ("Error: no active viewer");
6189     return 1;
6190   }
6191
6192   // No arguments --> print the current default vertex draw mode
6193   if (theArgNum == 1)
6194   {
6195     Prs3d_VertexDrawMode aCurrMode = aContext->DefaultDrawer()->VertexDrawMode();
6196     theDI <<  "Default vertex draw mode: " << (aCurrMode == Prs3d_VDM_Isolated ? "'isolated'" : "'all'") << "\n";
6197     return 0;
6198   }
6199
6200   // -set argument --> change the default vertex draw mode and the mode for all displayed or given object(s)
6201   TCollection_AsciiString aParam (theArgs[1]);
6202   if (aParam == "-set")
6203   {
6204     if (theArgNum == 2)
6205     {
6206       Message::SendFail ("Error: '-set' option not followed by the mode and optional object name(s)\n"
6207                          "Type 'help vvertexmode' for usage hints");
6208       return 1;
6209     }
6210
6211     TCollection_AsciiString aModeStr (theArgs[2]);
6212     Prs3d_VertexDrawMode aNewMode =
6213        aModeStr == "isolated" ? Prs3d_VDM_Isolated :
6214       (aModeStr == "all"      ? Prs3d_VDM_All :
6215                                 Prs3d_VDM_Inherited);
6216
6217     Standard_Boolean aRedrawNeeded = Standard_False;
6218     AIS_ListOfInteractive anObjs;
6219
6220     // No object(s) specified -> use all displayed
6221     if (theArgNum == 3)
6222     {
6223       theDI << "Setting the default vertex draw mode and updating all displayed objects...\n";
6224       aContext->DisplayedObjects (anObjs);
6225       aContext->DefaultDrawer()->SetVertexDrawMode (aNewMode);
6226       aRedrawNeeded = Standard_True;
6227     }
6228
6229     Handle(AIS_InteractiveObject) anObject;
6230     for (Standard_Integer aCount = 3; aCount < theArgNum; aCount++)
6231     {
6232       TCollection_AsciiString aName (theArgs[aCount]);
6233       if (!GetMapOfAIS().Find2 (aName, anObject))
6234       {
6235         theDI << "Warning: wrong object name ignored - " << theArgs[0] << "\n";
6236         continue;
6237       }
6238       anObjs.Append (anObject);
6239     }
6240
6241     for (AIS_ListIteratorOfListOfInteractive anIt (anObjs); anIt.More(); anIt.Next())
6242     {
6243       anObject = anIt.Value();
6244       anObject->Attributes()->SetVertexDrawMode (aNewMode);
6245       aContext->Redisplay (anObject, Standard_False);
6246       aRedrawNeeded = Standard_True;
6247     }
6248
6249     if (aRedrawNeeded)
6250       ViewerTest::CurrentView()->Redraw();
6251
6252     return 0;
6253   }
6254
6255   Handle(AIS_InteractiveObject) anObject;
6256   if (theArgNum > 2
6257   || !GetMapOfAIS().Find2 (aParam, anObject))
6258   {
6259     Message::SendFail ("Syntax error: invalid number of arguments");
6260     return 1;
6261   }
6262
6263   // One argument (object name) --> print the current vertex draw mode for the object
6264   Prs3d_VertexDrawMode aCurrMode = anObject->Attributes()->VertexDrawMode();
6265   theDI <<  "Object's vertex draw mode: " << (aCurrMode == Prs3d_VDM_Isolated ? "'isolated'" : "'all'") << "\n";
6266   return 0;
6267 }
6268
6269 //=======================================================================
6270 //function : VPointCloud
6271 //purpose  : Create interactive object for arbitrary set of points.
6272 //=======================================================================
6273 static Standard_Integer VPointCloud (Draw_Interpretor& theDI,
6274                                      Standard_Integer  theArgNum,
6275                                      const char**      theArgs)
6276 {
6277   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
6278   if (anAISContext.IsNull())
6279   {
6280     Message::SendFail ("Error: no active view!");
6281     return 1;
6282   }
6283
6284   // command to execute
6285   enum Command
6286   {
6287     CloudForShape, // generate point cloud for shape
6288     CloudSphere,   // generate point cloud for generic sphere
6289     Unknow
6290   };
6291
6292   // count number of non-optional command arguments
6293   Command aCmd = Unknow;
6294   Standard_Integer aCmdArgs = 0;
6295   for (Standard_Integer anArgIter = 1; anArgIter < theArgNum; ++anArgIter)
6296   {
6297     Standard_CString anArg = theArgs[anArgIter];
6298     TCollection_AsciiString aFlag (anArg);
6299     aFlag.LowerCase();
6300     if (aFlag.IsRealValue (Standard_True) || aFlag.Search ("-") != 1)
6301     {
6302       aCmdArgs++;
6303     }
6304   }
6305   switch (aCmdArgs)
6306   {
6307     case 2  : aCmd = CloudForShape; break;
6308     case 7  : aCmd = CloudSphere; break;
6309     default :
6310       Message::SendFail ("Syntax error: wrong number of arguments! See usage:");
6311       theDI.PrintHelp (theArgs[0]);
6312       return 1;
6313   }
6314
6315   // parse options
6316   Standard_Boolean toRandColors = Standard_False;
6317   Standard_Boolean hasNormals   = Standard_True;
6318   Standard_Boolean isSetArgNorm = Standard_False;
6319   Standard_Boolean hasUV        = Standard_False;
6320   for (Standard_Integer anArgIter = 1; anArgIter < theArgNum; ++anArgIter)
6321   {
6322     Standard_CString anArg = theArgs[anArgIter];
6323     TCollection_AsciiString aFlag (anArg);
6324     aFlag.LowerCase();
6325     if (aFlag == "-randcolors"
6326      || aFlag == "-randcolor")
6327     {
6328       if (isSetArgNorm && hasNormals)
6329       {
6330         Message::SendFail ("Syntax error: normals can not be enabled with colors at the same time");
6331         return 1;
6332       }
6333       toRandColors = Standard_True;
6334       hasNormals   = Standard_False;
6335     }
6336     else if (aFlag == "-normals"
6337           || aFlag == "-normal")
6338     {
6339       if (toRandColors)
6340       {
6341         Message::SendFail ("Syntax error: normals can not be enabled with colors at the same time");
6342         return 1;
6343       }
6344       isSetArgNorm = Standard_True;
6345       hasNormals   = Standard_True;
6346     }
6347     else if (aFlag == "-nonormals"
6348           || aFlag == "-nonormal")
6349     {
6350       isSetArgNorm = Standard_True;
6351       hasNormals   = Standard_False;
6352     }
6353     else if (aFlag == "-uv"
6354           || aFlag == "-texels")
6355     {
6356       hasUV = Standard_True;
6357     }
6358   }
6359
6360   Standard_CString aName = theArgs[1];
6361   Graphic3d_ArrayFlags aFlags = Graphic3d_ArrayFlags_None;
6362   if (hasNormals)
6363   {
6364     aFlags |= Graphic3d_ArrayFlags_VertexNormal;
6365   }
6366   if (toRandColors)
6367   {
6368     aFlags |= Graphic3d_ArrayFlags_VertexColor;
6369   }
6370   if (hasUV)
6371   {
6372     aFlags |= Graphic3d_ArrayFlags_VertexTexel;
6373   }
6374
6375   // generate arbitrary set of points
6376   Handle(Graphic3d_ArrayOfPoints) anArrayPoints;
6377   if (aCmd == CloudForShape)
6378   {
6379     Standard_CString aShapeName = theArgs[2];
6380     TopoDS_Shape     aShape     = DBRep::Get (aShapeName);
6381
6382     if (aShape.IsNull())
6383     {
6384       Message::SendFail() << "Error: no shape with name '" << aShapeName << "' found";
6385       return 1;
6386     }
6387
6388     // calculate number of points
6389     TopLoc_Location  aLocation;
6390     Standard_Integer aNbPoints = 0;
6391     for (TopExp_Explorer aFaceIt (aShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
6392     {
6393       const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
6394       Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aLocation);
6395       if (!aTriangulation.IsNull())
6396       {
6397         aNbPoints += aTriangulation->NbNodes();
6398       }
6399     }
6400     if (aNbPoints < 3)
6401     {
6402       Message::SendFail ("Error: shape should be triangulated");
6403       return 1;
6404     }
6405
6406     anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, aFlags);
6407     for (TopExp_Explorer aFaceIt (aShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
6408     {
6409       const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
6410       Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aLocation);
6411       if (aTriangulation.IsNull())
6412       {
6413         continue;
6414       }
6415
6416       const gp_Trsf&            aTrsf  = aLocation.Transformation();
6417
6418       // extract normals from nodes
6419       TColgp_Array1OfDir aNormals (1, hasNormals ? aTriangulation->NbNodes() : 1);
6420       if (hasNormals)
6421       {
6422         Poly_Connect aPolyConnect (aTriangulation);
6423         StdPrs_ToolTriangulatedShape::Normal (aFace, aPolyConnect, aNormals);
6424       }
6425
6426       for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter)
6427       {
6428         gp_Pnt aPoint = aTriangulation->Node (aNodeIter);
6429         if (!aLocation.IsIdentity())
6430         {
6431           aPoint.Transform (aTrsf);
6432           if (hasNormals)
6433           {
6434             aNormals (aNodeIter).Transform (aTrsf);
6435           }
6436         }
6437
6438         // add vertex into array of points
6439         const Standard_Integer anIndexOfPoint = anArrayPoints->AddVertex (aPoint);
6440         if (toRandColors)
6441         {
6442           Quantity_Color aColor (360.0 * Standard_Real(anIndexOfPoint) / Standard_Real(aNbPoints),
6443                                  1.0, 0.5, Quantity_TOC_HLS);
6444           anArrayPoints->SetVertexColor (anIndexOfPoint, aColor);
6445         }
6446
6447         if (hasNormals)
6448         {
6449           anArrayPoints->SetVertexNormal (anIndexOfPoint, aNormals (aNodeIter));
6450         }
6451         if (hasUV
6452          && aTriangulation->HasUVNodes())
6453         {
6454           anArrayPoints->SetVertexTexel (anIndexOfPoint, aTriangulation->UVNode (aNodeIter));
6455         }
6456       }
6457     }
6458   }
6459   else if (aCmd == CloudSphere)
6460   {
6461     Standard_Real aCenterX       = Draw::Atof (theArgs[2]);
6462     Standard_Real aCenterY       = Draw::Atof (theArgs[3]);
6463     Standard_Real aCenterZ       = Draw::Atof (theArgs[4]);
6464     Standard_Real aRadius        = Draw::Atof (theArgs[5]);
6465     Standard_Integer aNbPoints   = Draw::Atoi (theArgs[6]);
6466
6467     TCollection_AsciiString aDistribution = TCollection_AsciiString(theArgs[7]);
6468     aDistribution.LowerCase();
6469     if ( aDistribution != "surface" && aDistribution != "volume" )
6470     {
6471       Message::SendFail ("Syntax error: wrong arguments. See usage:");
6472       theDI.PrintHelp (theArgs[0]);
6473       return 1;
6474     }
6475     Standard_Boolean isSurface = aDistribution == "surface";
6476
6477     gp_Pnt aCenter(aCenterX, aCenterY, aCenterZ);
6478
6479     anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, aFlags);
6480     for (Standard_Integer aPntIt = 0; aPntIt < aNbPoints; ++aPntIt)
6481     {
6482       Standard_Real anAlpha   = (Standard_Real (rand() % 2000) / 1000.0) * M_PI;
6483       Standard_Real aBeta     = (Standard_Real (rand() % 2000) / 1000.0) * M_PI;
6484       Standard_Real aDistance = isSurface ?
6485         aRadius : (Standard_Real (rand() % aNbPoints) / aNbPoints) * aRadius;
6486
6487       gp_Dir aDir (Cos (anAlpha) * Sin (aBeta),
6488                    Sin (anAlpha),
6489                    Cos (anAlpha) * Cos (aBeta));
6490       gp_Pnt aPoint = aCenter.Translated (aDir.XYZ() * aDistance);
6491
6492       const Standard_Integer anIndexOfPoint = anArrayPoints->AddVertex (aPoint);
6493       if (toRandColors)
6494       {
6495         Quantity_Color aColor (360.0 * Standard_Real (anIndexOfPoint) / Standard_Real (aNbPoints),
6496                                1.0, 0.5, Quantity_TOC_HLS);
6497         anArrayPoints->SetVertexColor (anIndexOfPoint, aColor);
6498       }
6499
6500       if (hasNormals)
6501       {
6502         anArrayPoints->SetVertexNormal (anIndexOfPoint, aDir);
6503       }
6504       if (hasUV)
6505       {
6506         anArrayPoints->SetVertexTexel (anIndexOfPoint, gp_Pnt2d (anAlpha / 2.0 * M_PI,
6507                                                                  aBeta   / 2.0 * M_PI));
6508       }
6509     }
6510   }
6511
6512   // set array of points in point cloud object
6513   Handle(AIS_PointCloud) aPointCloud = new AIS_PointCloud();
6514   aPointCloud->SetPoints (anArrayPoints);
6515   VDisplayAISObject (aName, aPointCloud);
6516   return 0;
6517 }
6518
6519 //=======================================================================
6520 //function : VPriority
6521 //purpose  : Prints or sets the display priority for an object
6522 //=======================================================================
6523
6524 static int VPriority (Draw_Interpretor& theDI,
6525                       Standard_Integer  theArgNum,
6526                       const char**      theArgs)
6527 {
6528   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6529   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
6530   if (aContext.IsNull())
6531   {
6532     Message::SendFail ("Error: no active viewer");
6533     return 1;
6534   }
6535
6536   TCollection_AsciiString aLastArg (theArgs[theArgNum - 1]);
6537   Standard_Integer aPriority = -1;
6538   Standard_Integer aNbArgs   = theArgNum;
6539   if (aLastArg.IsIntegerValue())
6540   {
6541     aPriority = aLastArg.IntegerValue();
6542     --aNbArgs;
6543     if (aPriority < 0 || aPriority > 10)
6544     {
6545       Message::SendFail() << "Syntax error: the specified display priority value '" << aLastArg
6546                           << "' is outside the valid range [0..10]";
6547       return 1;
6548     }
6549   }
6550   else
6551   {
6552     anUpdateTool.Invalidate();
6553   }
6554
6555   if (aNbArgs < 2)
6556   {
6557     Message::SendFail ("Syntax error: wrong number of arguments! See usage:");
6558     theDI.PrintHelp (theArgs[0]);
6559     return 1;
6560   }
6561
6562   for (Standard_Integer anArgIter = 1; anArgIter < aNbArgs; ++anArgIter)
6563   {
6564     if (anUpdateTool.parseRedrawMode (theArgs[anArgIter]))
6565     {
6566       continue;
6567     }
6568
6569     TCollection_AsciiString aName (theArgs[anArgIter]);
6570     Handle(AIS_InteractiveObject) anIObj;
6571     GetMapOfAIS().Find2 (aName, anIObj);
6572     if (anIObj.IsNull())
6573     {
6574       Message::SendFail() << "Error: the object '" << theArgs[1] << "' is not displayed";
6575       return 1;
6576     }
6577
6578     if (aPriority < 1)
6579     {
6580       theDI << aContext->DisplayPriority (anIObj) << " ";
6581     }
6582     else
6583     {
6584       aContext->SetDisplayPriority (anIObj, aPriority);
6585     }
6586   }
6587   return 0;
6588 }
6589
6590 //! Auxiliary class for command vnormals.
6591 class MyShapeWithNormals : public AIS_Shape
6592 {
6593   DEFINE_STANDARD_RTTI_INLINE(MyShapeWithNormals, AIS_Shape);
6594 public:
6595
6596   Standard_Real    NormalLength;
6597   Standard_Integer NbAlongU;
6598   Standard_Integer NbAlongV;
6599   Standard_Boolean ToUseMesh;
6600   Standard_Boolean ToOrient;
6601
6602 public:
6603
6604   //! Main constructor.
6605   MyShapeWithNormals (const TopoDS_Shape& theShape)
6606   : AIS_Shape   (theShape),
6607     NormalLength(10),
6608     NbAlongU  (1),
6609     NbAlongV  (1),
6610     ToUseMesh (Standard_False),
6611     ToOrient  (Standard_False) {}
6612
6613 protected:
6614
6615   //! Compute presentation.
6616   virtual void Compute (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
6617                         const Handle(Prs3d_Presentation)& thePrs,
6618                         const Standard_Integer theMode) Standard_OVERRIDE
6619   {
6620     AIS_Shape::Compute (thePrsMgr, thePrs, theMode);
6621
6622     NCollection_DataMap<TopoDS_Face, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> > > aNormalMap;
6623     if (ToUseMesh)
6624     {
6625       DBRep_DrawableShape::addMeshNormals (aNormalMap, myshape, NormalLength);
6626     }
6627     else
6628     {
6629       DBRep_DrawableShape::addSurfaceNormals (aNormalMap, myshape, NormalLength, NbAlongU, NbAlongV);
6630     }
6631
6632     Handle(Graphic3d_Group) aPrsGroup = thePrs->NewGroup();
6633     aPrsGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
6634
6635     const Standard_Real aArrowAngle  = myDrawer->ArrowAspect()->Angle();
6636     const Standard_Real aArrowLength = myDrawer->ArrowAspect()->Length();
6637     for (NCollection_DataMap<TopoDS_Face, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> > >::Iterator aFaceIt (aNormalMap);
6638          aFaceIt.More(); aFaceIt.Next())
6639     {
6640       const Standard_Boolean toReverse = ToOrient && aFaceIt.Key().Orientation() == TopAbs_REVERSED;
6641       Handle(Graphic3d_ArrayOfSegments) aSegments = new Graphic3d_ArrayOfSegments (2 * aFaceIt.Value().Size());
6642       for (NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >::Iterator aPntIt (aFaceIt.Value()); aPntIt.More(); aPntIt.Next())
6643       {
6644         std::pair<gp_Pnt, gp_Pnt> aPair = aPntIt.Value();
6645         if (toReverse)
6646         {
6647           const gp_Vec aDir = aPair.first.XYZ() - aPair.second.XYZ();
6648           aPair.second = aPair.first.XYZ() + aDir.XYZ();
6649         }
6650
6651         aSegments->AddVertex (aPair.first);
6652         aSegments->AddVertex (aPair.second);
6653         Prs3d_Arrow::Draw (aPrsGroup, aPair.second, gp_Vec(aPair.first, aPair.second), aArrowAngle, aArrowLength);
6654       }
6655
6656       aPrsGroup->AddPrimitiveArray (aSegments);
6657     }
6658   }
6659
6660 };
6661
6662 //=======================================================================
6663 //function : VNormals
6664 //purpose  : Displays/Hides normals calculated on shape geometry or retrieved from triangulation
6665 //=======================================================================
6666 static int VNormals (Draw_Interpretor& theDI,
6667                      Standard_Integer  theArgNum,
6668                      const char**      theArgs)
6669 {
6670   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6671   if (aContext.IsNull())
6672   {
6673     Message::SendFail ("Error: no active viewer");
6674     return 1;
6675   }
6676   else if (theArgNum < 2)
6677   {
6678     Message::SendFail ("Syntax error: wrong number of arguments. See usage:");
6679     theDI.PrintHelp (theArgs[0]);
6680     return 1;
6681   }
6682
6683   Standard_Integer anArgIter = 1;
6684   Standard_CString aShapeName = theArgs[anArgIter++];
6685   TopoDS_Shape     aShape     = DBRep::Get (aShapeName);
6686   Standard_Boolean isOn = Standard_True;
6687   if (aShape.IsNull())
6688   {
6689     Message::SendFail() << "Error: shape with name '" << aShapeName << "' is not found";
6690     return 1;
6691   }
6692
6693   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6694   Handle(MyShapeWithNormals) aShapePrs;
6695   if (aMap.IsBound2 (aShapeName))
6696   {
6697     aShapePrs = Handle(MyShapeWithNormals)::DownCast (aMap.Find2 (aShapeName));
6698   }
6699
6700   Standard_Boolean isUseMesh = Standard_False;
6701   Standard_Real    aLength = 10.0;
6702   Standard_Integer aNbAlongU = 1, aNbAlongV = 1;
6703   Standard_Boolean isOriented = Standard_False;
6704   for (; anArgIter < theArgNum; ++anArgIter)
6705   {
6706     TCollection_AsciiString aParam (theArgs[anArgIter]);
6707     aParam.LowerCase();
6708     if (anArgIter == 2
6709      && Draw::ParseOnOff (aParam.ToCString(), isOn))
6710     {
6711       continue;
6712     }
6713     else if (aParam == "-usemesh"
6714           || aParam == "-mesh")
6715     {
6716       isUseMesh = Standard_True;
6717     }
6718     else if (aParam == "-length"
6719           || aParam == "-len")
6720     {
6721       ++anArgIter;
6722       aLength = anArgIter < theArgNum ? Draw::Atof (theArgs[anArgIter]) : 0.0;
6723       if (Abs (aLength) <= gp::Resolution())
6724       {
6725         Message::SendFail ("Syntax error: length should not be zero");
6726         return 1;
6727       }
6728     }
6729     else if (aParam == "-orient"
6730           || aParam == "-oriented")
6731     {
6732       isOriented = Standard_True;
6733       if (anArgIter + 1 < theArgNum
6734         && Draw::ParseOnOff (theArgs[anArgIter + 1], isOriented))
6735       {
6736         ++anArgIter;
6737       }
6738     }
6739     else if (aParam == "-nbalongu"
6740           || aParam == "-nbu")
6741     {
6742       ++anArgIter;
6743       aNbAlongU = anArgIter < theArgNum ? Draw::Atoi (theArgs[anArgIter]) : 0;
6744       if (aNbAlongU < 1)
6745       {
6746         Message::SendFail ("Syntax error: NbAlongU should be >=1");
6747         return 1;
6748       }
6749     }
6750     else if (aParam == "-nbalongv"
6751           || aParam == "-nbv")
6752     {
6753       ++anArgIter;
6754       aNbAlongV = anArgIter < theArgNum ? Draw::Atoi (theArgs[anArgIter]) : 0;
6755       if (aNbAlongV < 1)
6756       {
6757         Message::SendFail ("Syntax error: NbAlongV should be >=1");
6758         return 1;
6759       }
6760     }
6761     else if (aParam == "-nbalong"
6762           || aParam == "-nbuv")
6763     {
6764       ++anArgIter;
6765       aNbAlongU = anArgIter < theArgNum ? Draw::Atoi (theArgs[anArgIter]) : 0;
6766       aNbAlongV = aNbAlongU;
6767       if (aNbAlongU < 1)
6768       {
6769         Message::SendFail ("Syntax error: NbAlong should be >=1");
6770         return 1;
6771       }
6772     }
6773     else
6774     {
6775       Message::SendFail() << "Syntax error: unknown argument '" << aParam << "'";
6776       return 1;
6777     }
6778   }
6779
6780   if (isOn)
6781   {
6782     if (aShapePrs.IsNull())
6783     {
6784       aShapePrs = new MyShapeWithNormals (aShape);
6785     }
6786     aShapePrs->ToUseMesh    = isUseMesh;
6787     aShapePrs->ToOrient     = isOriented;
6788     aShapePrs->NormalLength = aLength;
6789     aShapePrs->NbAlongU     = aNbAlongU;
6790     aShapePrs->NbAlongV     = aNbAlongV;
6791     VDisplayAISObject (aShapeName, aShapePrs);
6792   }
6793   else if (!aShapePrs.IsNull())
6794   {
6795     VDisplayAISObject (aShapeName, new AIS_Shape (aShape));
6796   }
6797
6798   return 0;
6799 }
6800
6801 //=======================================================================
6802 //function : ObjectsCommands
6803 //purpose  :
6804 //=======================================================================
6805
6806 void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
6807 {
6808   const char *group ="AISObjects";
6809
6810   theCommands.Add ("vtrihedron",
6811                    "vtrihedron : vtrihedron name"
6812                    "\n\t\t: [-dispMode {wireframe|shading} ]"
6813                    "\n\t\t: [-origin x y z ]"
6814                    "\n\t\t: [-zaxis u v w -xaxis u v w ]"
6815                    "\n\t\t: [-drawAxes {X|Y|Z|XY|YZ|XZ|XYZ}]"
6816                    "\n\t\t: [-hideLabels {on|off}]"
6817                    "\n\t\t: [-hideArrows {on|off}]"
6818                    "\n\t\t: [-label {XAxis|YAxis|ZAxis} value]"
6819                    "\n\t\t: [-attribute {XAxisLength|YAxisLength|ZAxisLength"
6820                    "\n\t\t:             |TubeRadiusPercent|ConeRadiusPercent"
6821                    "\n\t\t:             |ConeLengthPercent|OriginRadiusPercent"
6822                    "\n\t\t:             |ShadingNumberOfFacettes} value]"
6823                    "\n\t\t: [-color {Origin|XAxis|YAxis|ZAxis|XOYAxis|YOZAxis"
6824                    "\n\t\t:         |XOZAxis|Whole} {r g b | colorName}]"
6825                    "\n\t\t: [-textColor  [XAxis|YAxis|ZAxis] {r g b | colorName}]"
6826                    "\n\t\t: [-arrowColor [XAxis|YAxis|ZAxis] {r g b | colorName}]"
6827                    "\n\t\t: [-priority {Origin|XAxis|YAxis|ZAxis|XArrow"
6828                    "\n\t\t:            |YArrow|ZArrow|XOYAxis|YOZAxis"
6829                    "\n\t\t:            |XOZAxis|Whole} value]"
6830                    "\n\t\t:"
6831                    "\n\t\t: Creates a new *AIS_Trihedron* object or changes parameters of "
6832                    "\n\t\t: existing trihedron. If no argument is set,"
6833                    "\n\t\t: the default trihedron (0XYZ) is created."
6834                    "\n\t\t: -dispMode mode of visualization: wf - wireframe,"
6835                    "\n\t\t:                                  sh - shading."
6836                    "\n\t\t:               Default value is wireframe."
6837                    "\n\t\t: -origin allows to set trihedron location."
6838                    "\n\t\t: -zaxis/-xaxis allows to set trihedron X and Z"
6839                    "\n\t\t:               directions. The directions should"
6840                    "\n\t\t:               be orthogonal. Y direction is calculated."
6841                    "\n\t\t: -drawAxes allows to set what axes are drawn in the"
6842                    "\n\t\t:           trihedron, default state is XYZ"
6843                    "\n\t\t: -hideLabels allows to show/hide trihedron labels"
6844                    "\n\t\t: -hideArrows allows to show/hide trihedron arrows"
6845                    "\n\t\t: -label allows to change default X/Y/Z titles of axes"
6846                    "\n\t\t: -attribute sets parameters of trihedron"
6847                    "\n\t\t: -color sets color properties of parts of trihedron"
6848                    "\n\t\t: -textColor sets color properties of trihedron labels"
6849                    "\n\t\t: -arrowColor sets color properties of trihedron arrows"
6850                    "\n\t\t: -priority allows to change default selection priority"
6851                    "\n\t\t: of trihedron components",
6852                    __FILE__,VTrihedron,group);
6853
6854   theCommands.Add("vtri2d",
6855     "vtri2d Name"
6856     "\n\t\t: Creates a plane with a 2D trihedron from an interactively selected face.",
6857     __FILE__,VTrihedron2D ,group);
6858
6859   theCommands.Add("vplanetri",
6860     "vplanetri name"
6861     "\n\t\t: Create a plane from a trihedron selection. If no arguments are set, the default",
6862     __FILE__,VPlaneTrihedron ,group);
6863
6864   theCommands.Add("vsize",
6865     "vsize       : vsize [name(Default=Current)] [size(Default=100)] "
6866     "\n\t\t: Changes the size of a named or selected trihedron."
6867     "\n\t\t: If the name is not defined: it affects the selected trihedrons otherwise nothing is done."
6868     "\n\t\t: If the value is not defined: it is set to 100 by default.",
6869     __FILE__,VSize,group);
6870
6871   theCommands.Add("vaxis",
6872     "vaxis name [Xa] [Ya] [Za] [Xb] [Yb] [Zb]"
6873     "\n\t\t: Creates an axis. If  the values are not defined, an axis is created by interactive selection of two vertices or one edge",
6874     __FILE__,VAxisBuilder,group);
6875
6876   theCommands.Add("vaxispara",
6877     "vaxispara name "
6878     "\n\t\t: Creates an axis by interactive selection of an edge and a vertex.",
6879     __FILE__,VAxisBuilder,group);
6880
6881   theCommands.Add("vaxisortho",
6882     "vaxisortho name "
6883     "\n\t\t: Creates an axis by interactive selection of an edge and a vertex. The axis will be orthogonal to the selected edge.",
6884     __FILE__,VAxisBuilder,group);
6885
6886   theCommands.Add("vpoint",
6887     "vpoint name [X Y [Z]] [-2d] [-nosel]"
6888     "\n\t\t: Creates a point from coordinates."
6889     "\n\t\t: If the values are not defined, a point is created from selected vertex or edge (center)."
6890     "\n\t\t:  -2d    defines on-screen 2D point from top-left window corner"
6891     "\n\t\t:  -nosel creates non-selectable presentation",
6892     __FILE__,VPointBuilder,group);
6893
6894   theCommands.Add("vplane",
6895     "vplane  PlaneName [AxisName/PlaneName/PointName] [PointName/PointName/PointName] [Nothing/Nothing/PointName] [TypeOfSensitivity {0|1}]"
6896     "\n\t\t: Creates a plane from named or interactively selected entities."
6897     "\n\t\t: TypeOfSensitivity:"
6898     "\n\t\t:   0 - Interior"
6899     "\n\t\t:   1 - Boundary",
6900     __FILE__,VPlaneBuilder,group);
6901
6902   theCommands.Add ("vchangeplane", "vchangeplane usage: \n"
6903     "   vchangeplane <plane_name>"
6904     " [x=center_x y=center_y z=center_z]"
6905     " [dx=dir_x dy=dir_y dz=dir_z]"
6906     " [sx=size_x sy=size_y]"
6907     " [noupdate]\n"
6908     "   - changes parameters of the plane:\n"
6909     "   - x y z     - center\n"
6910     "   - dx dy dz  - normal\n"
6911     "   - sx sy     - plane sizes\n"
6912     "   - noupdate  - do not update/redisplay the plane in context\n"
6913     "   Please enter coordinates in format \"param=value\" in arbitrary order.",
6914     __FILE__, VChangePlane, group);
6915
6916   theCommands.Add("vplanepara",
6917     "vplanepara  PlaneName  "
6918     "\n\t\t: Creates a plane from interactively selected vertex and face.",
6919     __FILE__,VPlaneBuilder,group);
6920
6921   theCommands.Add("vplaneortho",
6922     "vplaneortho  PlaneName  "
6923     "\n\t\t: Creates a plane from interactive selected face and coplanar edge. ",
6924     __FILE__,VPlaneBuilder,group);
6925
6926   theCommands.Add("vline",
6927     "vline LineName [Xa/PointName] [Ya/PointName] [Za] [Xb] [Yb] [Zb]  "
6928     "\n\t\t: Creates a line from coordinates, named or interactively selected vertices. ",
6929     __FILE__,VLineBuilder,group);
6930
6931   theCommands.Add("vcircle",
6932     "vcircle CircleName [PointName PointName PointName IsFilled]\n\t\t\t\t\t[PlaneName PointName Radius IsFilled]"
6933     "\n\t\t: Creates a circle from named or interactively selected entities."
6934     "\n\t\t: Parameter IsFilled is defined as 0 or 1.",
6935     __FILE__,VCircleBuilder,group);
6936
6937   theCommands.Add ("vdrawtext",
6938                    "vdrawtext name text"
6939                    "\n\t\t: [-pos X=0 Y=0 Z=0]"
6940                    "\n\t\t: [-color {R G B|name}=yellow]"
6941                    "\n\t\t: [-halign {left|center|right}=left]"
6942                    "\n\t\t: [-valign {top|center|bottom|topfirstline}=bottom}]"
6943                    "\n\t\t: [-angle angle=0]"
6944                    "\n\t\t: [-zoom {0|1}=0]"
6945                    "\n\t\t: [-height height=16]"
6946                    "\n\t\t: [-wrapping width=40]"
6947                    "\n\t\t: [-aspect {regular|bold|italic|boldItalic}=regular]"
6948                    "\n\t\t: [-font font=Times]"
6949                    "\n\t\t: [-2d]"
6950                    "\n\t\t: [-perspos {X Y Z}=0 0 0], where"
6951                    "\n\t\t X and Y define the coordinate origin in 2d space relative to the view window"
6952                    "\n\t\t Example: X=0 Y=0 is center, X=1 Y=1 is upper right corner etc..."
6953                    "\n\t\t Z coordinate defines the gap from border of view window (except center position)."
6954                    "\n\t\t: [-disptype {blend|decal|shadow|subtitle|dimension|normal}=normal}"
6955                    "\n\t\t: [-subcolor {R G B|name}=white]"
6956                    "\n\t\t: [-noupdate]"
6957                    "\n\t\t: [-plane NormX NormY NormZ DirX DirY DirZ]"
6958                    "\n\t\t: [-flipping]"
6959                    "\n\t\t: [-ownanchor {0|1}=1]"
6960                    "\n\t\t: Display text label at specified position.",
6961     __FILE__, VDrawText, group);
6962
6963   theCommands.Add("vdrawsphere",
6964     "vdrawsphere: vdrawsphere shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToShowEdges=0] [ToPrintInfo=1]\n",
6965     __FILE__,VDrawSphere,group);
6966
6967   theCommands.Add ("vlocation",
6968                 "vlocation name"
6969       "\n\t\t:   [-reset] [-copyFrom otherName]"
6970       "\n\t\t:   [-translate    X Y [Z]] [-rotate    x y z dx dy dz angle] [-scale    [X Y Z] scale]"
6971       "\n\t\t:   [-pretranslate X Y [Z]] [-prerotate x y z dx dy dz angle] [-prescale [X Y Z] scale]"
6972       "\n\t\t:   [-mirror x y z dx dy dz] [-premirror x y z dx dy dz]"
6973       "\n\t\t:   [-setLocation X Y [Z]] [-setRotation QX QY QZ QW] [-setScale [X Y Z] scale]"
6974       "\n\t\t: Object local transformation management:"
6975       "\n\t\t:   -reset        resets transformation to identity"
6976       "\n\t\t:   -translate    applies translation vector"
6977       "\n\t\t:   -rotate       applies rotation around axis"
6978       "\n\t\t:   -scale        applies scale factor with optional anchor"
6979       "\n\t\t:   -mirror       applies mirror transformation"
6980       "\n\t\t:   -pretranslate pre-multiplies translation vector"
6981       "\n\t\t:   -prerotate    pre-multiplies rotation around axis"
6982       "\n\t\t:   -prescale     pre-multiplies scale  transformation"
6983       "\n\t\t:   -premirror    pre-multiplies mirror transformation"
6984       "\n\t\t:   -setLocation  overrides translation part"
6985       "\n\t\t:   -setRotation  overrides rotation part with specified quaternion"
6986       "\n\t\t:   -setScale     overrides scale factor",
6987         __FILE__, VSetLocation, group);
6988   theCommands.Add ("vsetlocation",
6989                    "alias for vlocation",
6990         __FILE__, VSetLocation, group);
6991   theCommands.Add ("vchild",
6992                    "vchild parent [-add] [-remove] [-ignoreParentTrsf {0|1}] child1 [child2] [...]"
6993       "\n\t\t: Command for testing low-level presentation connections."
6994       "\n\t\t: vconnect command should be used instead.",
6995         __FILE__, VChild, group);
6996   theCommands.Add("vparent",
6997     "vparent parent [-ignoreVisu]"
6998     "\n\t\t: Command for testing object properties as parent in the hierarchy."
6999     "\n\t\t: Arguments:"
7000     "\n\t\t:   -ignoreVisu do not propagate the visual state (display/erase/color) to children objects",
7001     __FILE__, VParent, group);
7002   theCommands.Add ("vcomputehlr",
7003                 "vcomputehlr shapeInput hlrResult [-algoType {algo|polyAlgo}=polyAlgo]"
7004       "\n\t\t:   [eyeX eyeY eyeZ dirX dirY dirZ upX upY upZ]"
7005       "\n\t\t:   [-showTangentEdges {on|off}=off] [-nbIsolines N=0] [-showHiddenEdges {on|off}=off]"
7006       "\n\t\t: Arguments:"
7007       "\n\t\t:  shapeInput - name of the initial shape"
7008       "\n\t\t:  hlrResult - result HLR object from initial shape"
7009       "\n\t\t:  eye, dir are eye position and look direction"
7010       "\n\t\t:  up is the look up direction vector"
7011       "\n\t\t:  -algoType HLR algorithm to use"
7012       "\n\t\t:  -showTangentEdges include tangent edges"
7013       "\n\t\t:  -nbIsolines include isolines"
7014       "\n\t\t:  -showHiddenEdges include hidden edges"
7015       "\n\t\t: Use vtop to see projected HLR shape.",
7016     __FILE__, VComputeHLR, group);
7017
7018   theCommands.Add("vdrawparray",
7019                 "vdrawparray name TypeOfArray={points|segments|polylines|triangles"
7020       "\n\t\t:                                |trianglefans|trianglestrips|quads|quadstrips|polygons}"
7021       "\n\t\t:              [-deinterleaved|-mutable]"
7022       "\n\t\t:              [vertex={'v' x y z [normal={'n' nx ny nz}] [color={'c' r g b}] [texel={'t' tx ty}]]"
7023       "\n\t\t:              [bound= {'b' nbVertices [bound_color={'c' r g b}]]"
7024       "\n\t\t:              [edge=  {'e' vertexId]"
7025       "\n\t\t:              [-shape shapeName] [-patch]"
7026       "\n\t\t: Commands create an Interactive Object for specified Primitive Array definition (Graphic3d_ArrayOfPrimitives)"
7027       "\n\t\t: with the main purpose is covering various combinations by tests",
7028     __FILE__,VDrawPArray,group);
7029
7030   theCommands.Add("vconnect", 
7031     "vconnect name Xo Yo Zo object1 object2 ... [color=NAME]"
7032     "\n\t\t: Creates and displays AIS_ConnectedInteractive object from input object and location.",
7033     __FILE__, VConnect, group);
7034
7035   theCommands.Add("vconnectto",
7036     "vconnectto : instance_name Xo Yo Zo object [-nodisplay|-noupdate|-update]"
7037     "  Makes an instance 'instance_name' of 'object' with position (Xo Yo Zo)."
7038     "\n\t\t:   -nodisplay - only creates interactive object, but not displays it",
7039     __FILE__, VConnectTo,group);
7040
7041   theCommands.Add("vdisconnect",
7042     "vdisconnect assembly_name (object_name | object_number | 'all')"
7043     "  Disconnects all objects from assembly or disconnects object by name or number (use vlistconnected to enumerate assembly children).",
7044     __FILE__,VDisconnect,group);
7045
7046   theCommands.Add("vaddconnected",
7047     "vaddconnected assembly_name object_name"
7048     "Adds object to assembly.",
7049     __FILE__,VAddConnected,group);
7050
7051   theCommands.Add("vlistconnected",
7052     "vlistconnected assembly_name"
7053     "Lists objects in assembly.",
7054     __FILE__,VListConnected,group);
7055
7056
7057   theCommands.Add("vselmode", 
7058                 "vselmode [object] selectionMode {on|off}"
7059       "\n\t\t:            [{-add|-set|-globalOrLocal}=-globalOrLocal]"
7060       "\n\t\t: Switches selection mode for the specified object or for all objects in context."
7061       "\n\t\t: Selection mode is either an integer number specific to Interactive Object,"
7062       "\n\t\t: or sub-shape type in case of AIS_Shape:"
7063       "\n\t\t:   Shape, Vertex, Edge, Wire, Face, Shell, Solid, CompSolid, Compound"
7064       "\n\t\t: The integer mode 0 (Shape in case of AIS_Shape) is reserved for selecting object as whole."
7065       "\n\t\t: Additional options:"
7066       "\n\t\t:  -add           already activated selection modes will be left activated"
7067       "\n\t\t:  -set           already activated selection modes will be deactivated"
7068       "\n\t\t:  -globalOrLocal (default) if new mode is Global selection mode,"
7069       "\n\t\t:                 then active local selection modes will be deactivated"
7070       "\n\t\t:                 and the samthen active local selection modes will be deactivated",
7071     __FILE__, VSetSelectionMode, group);
7072
7073   theCommands.Add("vselnext",
7074     "vselnext : hilight next detected",
7075     __FILE__, VSelectionNext, group);
7076
7077   theCommands.Add("vselprev",
7078     "vselnext : hilight previous detected",
7079     __FILE__, VSelectionPrevious, group);
7080
7081   theCommands.Add("vtriangle",
7082     "vtriangle Name PointName PointName PointName"
7083     "\n\t\t: Creates and displays a filled triangle from named points.", 
7084     __FILE__, VTriangle,group);
7085
7086   theCommands.Add("vsegment",
7087     "vsegment Name PointName PointName"
7088     "\n\t\t: Creates and displays a segment from named points.", 
7089     __FILE__, VTriangle,group);
7090
7091   theCommands.Add ("vtorus",
7092                    "vtorus name [R1 R2 [Angle1=0 Angle2=360] [Angle=360]]"
7093                    "\n\t\t:             [-radius R1] [-pipeRadius R2]"
7094                    "\n\t\t:             [-pipeAngle Angle=360] [-segmentAngle1 Angle1=0 -segmentAngle2 Angle2=360]"
7095                    "\n\t\t:             [-nbSlices Number=100] [-nbStacks Number=100] [-noupdate]"
7096                    "\n\t\t: Creates and displays a torus or torus segment."
7097                    "\n\t\t: Parameters of the torus :"
7098                    "\n\t\t: - R1     distance from the center of the pipe to the center of the torus"
7099                    "\n\t\t: - R2     radius of the pipe"
7100                    "\n\t\t: - Angle1 first angle to create a torus ring segment"
7101                    "\n\t\t: - Angle2 second angle to create a torus ring segment"
7102                    "\n\t\t: - Angle  angle to create a torus pipe segment",
7103                    __FILE__, VTorus, group);
7104
7105   theCommands.Add ("vcylinder",
7106                    "vcylinder name [R1 R2 Height] [-height H] [-radius R] [-bottomRadius R1 -topRadius R2]"
7107                    "\n\t\t:                [-nbSlices Number=100] [-noupdate]"
7108                    "\n\t\t: Creates and displays a cylinder."
7109                    "\n\t\t: Parameters of the cylinder :"
7110                    "\n\t\t: - R1     cylinder bottom radius"
7111                    "\n\t\t: - R2     cylinder top radius"
7112                    "\n\t\t: - Height cylinder height",
7113                    __FILE__, VCylinder, group);
7114
7115   theCommands.Add ("vsphere",
7116                    "vsphere name [-radius] R"
7117                    "\n\t\t:              [-nbSlices Number=100] [-nbStacks Number=100] [-noupdate]"
7118                    "\n\t\t: Creates and displays a sphere.",
7119                    __FILE__, VSphere, group);
7120
7121   theCommands.Add("vobjzlayer",
7122     "vobjzlayer : set/get object [layerid] - set or get z layer id for the interactive object",
7123     __FILE__, VObjZLayer, group);
7124   
7125   theCommands.Add("vpolygonoffset",
7126     "vpolygonoffset : [object [mode factor units]] - sets/gets polygon offset parameters for an object, without arguments prints the default values",
7127     __FILE__, VPolygonOffset, group);
7128
7129   theCommands.Add ("vmarkerstest",
7130                    "vmarkerstest: name X Y Z [PointsOnSide=10] [MarkerType=0] [Scale=1.0] [FileName=ImageFile]\n",
7131                    __FILE__, VMarkersTest, group);
7132
7133   theCommands.Add ("text2brep",
7134                    "text2brep: name text"
7135                    "\n\t\t: [-pos X=0 Y=0 Z=0]"
7136                    "\n\t\t: [-halign {left|center|right}=left]"
7137                    "\n\t\t: [-valign {top|center|bottom|topfirstline}=bottom}]"
7138                    "\n\t\t: [-height height=16]"
7139                    "\n\t\t: [-aspect {regular|bold|italic|boldItalic}=regular]"
7140                    "\n\t\t: [-font font=Courier] [-strict {strict|aliases|any}=any]"
7141                    "\n\t\t: [-composite {on|off}=off]"
7142                    "\n\t\t: [-plane NormX NormY NormZ DirX DirY DirZ]",
7143                    __FILE__, TextToBRep, group);
7144   theCommands.Add ("vfont",
7145                             "vfont [-add pathToFont [fontName] [regular,bold,italic,boldItalic=undefined] [singleStroke]]"
7146                    "\n\t\t:        [-strict {any|aliases|strict}] [-find fontName [regular,bold,italic,boldItalic=undefined]] [-verbose {on|off}]"
7147                    "\n\t\t:        [-findAll fontNameMask] [-findInfo fontName]"
7148                    "\n\t\t:        [-unicodeFallback {on|off}]"
7149                    "\n\t\t:        [-clear] [-init] [-list] [-names]"
7150                    "\n\t\t:        [-aliases [aliasName]] [-addAlias Alias FontName] [-removeAlias Alias FontName] [-clearAlias Alias] [-clearAliases]"
7151                    "\n\t\t: Work with font registry - register font, list available fonts, find font."
7152                    "\n\t\t: -findAll  is same as -find, but can print more than one font when mask is passed."
7153                    "\n\t\t: -findInfo is same as -find, but prints complete font information instead of family name.",
7154                    __FILE__, VFont, group);
7155
7156   theCommands.Add ("vvertexmode",
7157                    "vvertexmode [name | -set {isolated | all | inherited} [name1 name2 ...]]\n"
7158                    "vvertexmode - prints the default vertex draw mode\n"
7159                    "vvertexmode name - prints the vertex draw mode of the given object\n"
7160                    "vvertexmode -set {isolated | all | inherited} - sets the default vertex draw mode and updates the mode for all displayed objects\n"
7161                    "vvertexmode -set {isolated | all | inherited} name1 name2 ... - sets the vertex draw mode for the specified object(s)\n",
7162                    __FILE__, VVertexMode, group);
7163
7164   theCommands.Add ("vpointcloud",
7165                    "vpointcloud name shape [-randColor] [-normals] [-noNormals] [-uv]"
7166                    "\n\t\t: Create an interactive object for arbitrary set of points"
7167                    "\n\t\t: from triangulated shape."
7168                    "\n"
7169                    "vpointcloud name x y z r npts {surface|volume}\n"
7170                    "            ... [-randColor] [-normals] [-noNormals] [-uv]"
7171                    "\n\t\t: Create arbitrary set of points (npts) randomly distributed"
7172                    "\n\t\t: on spheric surface or within spheric volume (x y z r)."
7173                    "\n\t\t:"
7174                    "\n\t\t: Additional options:"
7175                    "\n\t\t:  -randColor - generate random color per point"
7176                    "\n\t\t:  -normals   - generate normal per point (default)"
7177                    "\n\t\t:  -noNormals - do not generate normal per point"
7178                    "\n",
7179                    __FILE__, VPointCloud, group);
7180
7181   theCommands.Add("vpriority",
7182     "vpriority [-noupdate|-update] name [value]\n\t\t  prints or sets the display priority for an object",
7183     __FILE__,
7184     VPriority, group);
7185
7186   theCommands.Add ("vnormals",
7187                    "vnormals usage:\n"
7188                    "vnormals Shape [{on|off}=on] [-length {10}] [-nbAlongU {1}] [-nbAlongV {1}] [-nbAlong {1}]"
7189                    "\n\t\t:        [-useMesh] [-oriented {0}1}=0]"
7190                    "\n\t\t:  Displays/Hides normals calculated on shape geometry or retrieved from triangulation",
7191                    __FILE__, VNormals, group);
7192 }