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