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