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