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