f1c3a1c43ea68d5128c58ec66c0a579ec5395f10
[occt.git] / src / ViewerTest / ViewerTest_ObjectCommands.cxx
1 // Created on: 1998-11-12
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <ViewerTest.hxx>
18
19 #include <AIS_PlaneTrihedron.hxx>
20
21 #include <Quantity_NameOfColor.hxx>
22 #include <Draw_Interpretor.hxx>
23 #include <Draw.hxx>
24 #include <Draw_Appli.hxx>
25 #include <DBRep.hxx>
26 #include <DBRep_DrawableShape.hxx>
27
28 #include <Font_BRepFont.hxx>
29 #include <Font_BRepTextBuilder.hxx>
30 #include <Font_FontMgr.hxx>
31 #include <Message.hxx>
32 #include <NCollection_List.hxx>
33
34 #include <OSD_Chronometer.hxx>
35 #include <TCollection_AsciiString.hxx>
36 #include <V3d_Viewer.hxx>
37 #include <V3d_View.hxx>
38 #include <V3d.hxx>
39
40 #include <AIS_Shape.hxx>
41 #include <AIS_DisplayMode.hxx>
42 #include <AIS_PointCloud.hxx>
43 #include <TColStd_MapOfInteger.hxx>
44 #include <AIS_MapOfInteractive.hxx>
45 #include <ViewerTest_AutoUpdater.hxx>
46 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
47 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
48 #include <ViewerTest_EventManager.hxx>
49
50 #include <TopoDS_Solid.hxx>
51 #include <BRepTools.hxx>
52 #include <BRep_Builder.hxx>
53 #include <TopAbs_ShapeEnum.hxx>
54
55 #include <TopoDS.hxx>
56 #include <BRep_Tool.hxx>
57 #include <TopExp_Explorer.hxx>
58
59 #include <BRepAdaptor_Curve.hxx>
60 #include <BRepAdaptor_Surface.hxx>
61
62 #include <TopAbs.hxx>
63 #include <TopExp.hxx>
64 #include <TopoDS_Vertex.hxx>
65 #include <TopoDS_Shape.hxx>
66 #include <TopoDS_Face.hxx>
67
68 #include <Draw_Window.hxx>
69 #include <AIS_ListIteratorOfListOfInteractive.hxx>
70 #include <AIS_ListOfInteractive.hxx>
71 #include <AIS_ColoredShape.hxx>
72 #include <AIS_DisplayMode.hxx>
73 #include <AIS_Shape.hxx>
74
75 #include <AIS_InteractiveContext.hxx>
76 #include <Geom_Plane.hxx>
77 #include <gp_Pln.hxx>
78 #include <TCollection_ExtendedString.hxx>
79 #include <TCollection_HAsciiString.hxx>
80 #include <GC_MakePlane.hxx>
81 #include <gp_Circ.hxx>
82 #include <AIS_Axis.hxx>
83 #include <Geom_Axis2Placement.hxx>
84 #include <Geom_Axis1Placement.hxx>
85 #include <AIS_Trihedron.hxx>
86 #include <AIS_Axis.hxx>
87 #include <gp_Trsf.hxx>
88 #include <gp_Quaternion.hxx>
89 #include <TopLoc_Location.hxx>
90
91 #include <HLRAlgo_Projector.hxx>
92 #include <HLRBRep_Algo.hxx>
93 #include <HLRBRep_PolyAlgo.hxx>
94 #include <HLRBRep_PolyHLRToShape.hxx>
95 #include <HLRBRep_HLRToShape.hxx>
96 #include <Aspect_Window.hxx>
97
98 #include <Graphic3d_ArrayOfPoints.hxx>
99 #include <Graphic3d_ArrayOfSegments.hxx>
100 #include <Graphic3d_ArrayOfPolylines.hxx>
101 #include <Graphic3d_ArrayOfTriangles.hxx>
102 #include <Graphic3d_ArrayOfTriangleFans.hxx>
103 #include <Graphic3d_ArrayOfTriangleStrips.hxx>
104 #include <Graphic3d_ArrayOfQuadrangles.hxx>
105 #include <Graphic3d_ArrayOfQuadrangleStrips.hxx>
106 #include <Graphic3d_ArrayOfPolygons.hxx>
107 #include <Graphic3d_AttribBuffer.hxx>
108 #include <Graphic3d_AspectMarker3d.hxx>
109 #include <Graphic3d_Group.hxx>
110 #include <Standard_Real.hxx>
111
112 #include <AIS_Circle.hxx>
113 #include <BRepBuilderAPI_MakeEdge.hxx>
114 #include <BRepBuilderAPI_MakeFace.hxx>
115 #include <BRepBuilderAPI_MakeWire.hxx>
116 #include <Geom_Circle.hxx>
117 #include <GC_MakeCircle.hxx>
118 #include <Select3D_SensitiveCircle.hxx>
119 #include <SelectMgr_EntityOwner.hxx>
120 #include <SelectMgr_Selection.hxx>
121 #include <StdFail_NotDone.hxx>
122 #include <StdPrs_ShadedShape.hxx>
123 #include <TopoDS_Wire.hxx>
124
125 #include <AIS_MultipleConnectedInteractive.hxx>
126 #include <AIS_ConnectedInteractive.hxx>
127 #include <AIS_TextLabel.hxx>
128 #include <TopLoc_Location.hxx>
129 #include <TColStd_ListOfInteger.hxx>
130 #include <TColStd_ListIteratorOfListOfInteger.hxx>
131
132 #include <Select3D_SensitiveSegment.hxx>
133 #include <Select3D_SensitivePrimitiveArray.hxx>
134 #include <Select3D_SensitivePoint.hxx>
135 #include <BRepAdaptor_Curve.hxx>
136 #include <StdPrs_Curve.hxx>
137
138 #include <BRepExtrema_ExtPC.hxx>
139 #include <BRepExtrema_ExtPF.hxx>
140
141 #include <Prs3d_Arrow.hxx>
142 #include <Prs3d_ArrowAspect.hxx>
143 #include <Prs3d_DatumAttribute.hxx>
144 #include <Prs3d_DatumAspect.hxx>
145 #include <Prs3d_Drawer.hxx>
146 #include <Prs3d_VertexDrawMode.hxx>
147 #include <Prs3d_LineAspect.hxx>
148 #include <Prs3d_PointAspect.hxx>
149 #include <Prs3d_Presentation.hxx>
150 #include <Prs3d_TextAspect.hxx>
151 #include <Prs3d_ToolCylinder.hxx>
152 #include <Prs3d_ToolSphere.hxx>
153 #include <Prs3d_ToolTorus.hxx>
154
155 #include <Image_AlienPixMap.hxx>
156 #include <TColStd_HArray1OfAsciiString.hxx>
157 #include <TColStd_HSequenceOfAsciiString.hxx>
158
159 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
160 extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
161                                            const Handle(AIS_InteractiveObject)& theAISObj,
162                                            Standard_Boolean theReplaceIfExists = Standard_True);
163 extern Handle(AIS_InteractiveContext)& TheAISContext();
164
165 namespace
166 {
167   static bool convertToColor (const Handle(TColStd_HSequenceOfAsciiString)& theColorValues,
168                               Quantity_Color& theColor)
169   {
170     const char* anArgs[3] =
171     {
172       theColorValues->Size() >= 1 ? theColorValues->Value (1).ToCString() : "",
173       theColorValues->Size() >= 2 ? theColorValues->Value (2).ToCString() : "",
174       theColorValues->Size() >= 3 ? theColorValues->Value (3).ToCString() : ""
175     };
176     return Draw::ParseColor (theColorValues->Size(), anArgs, theColor) != 0;
177   }
178
179   static bool convertToDatumPart (const TCollection_AsciiString& theValue,
180                                   Prs3d_DatumParts& theDatumPart)
181   {
182     TCollection_AsciiString aValue = theValue;
183     aValue.LowerCase();
184     if      (aValue == "origin")  theDatumPart = Prs3d_DP_Origin;
185     else if (aValue == "xaxis")   theDatumPart = Prs3d_DP_XAxis;
186     else if (aValue == "yaxis")   theDatumPart = Prs3d_DP_YAxis;
187     else if (aValue == "zaxis")   theDatumPart = Prs3d_DP_ZAxis;
188     else if (aValue == "xarrow")  theDatumPart = Prs3d_DP_XArrow;
189     else if (aValue == "yarrow")  theDatumPart = Prs3d_DP_YArrow;
190     else if (aValue == "zarrow")  theDatumPart = Prs3d_DP_ZArrow;
191     else if (aValue == "xoyaxis") theDatumPart = Prs3d_DP_XOYAxis;
192     else if (aValue == "yozaxis") theDatumPart = Prs3d_DP_YOZAxis;
193     else if (aValue == "xozaxis") theDatumPart = Prs3d_DP_XOZAxis;
194     else if (aValue == "whole")   theDatumPart = Prs3d_DP_None;
195     else
196     {
197       return false;
198     }
199     return true;
200   }
201
202   static void convertToDatumParts (const TCollection_AsciiString& theValue,
203                                    NCollection_List<Prs3d_DatumParts>& theParts)
204   {
205     TCollection_AsciiString aValue = theValue;
206     const Standard_Integer aSplitPos = theValue.Search ("|");
207     Prs3d_DatumParts aPart = Prs3d_DP_None;
208     if (aSplitPos > 0)
209     {
210       convertToDatumParts (theValue.SubString (aSplitPos + 1, theValue.Length()), theParts);
211       if (aSplitPos == 1) // first symbol
212       {
213         return;
214       }
215       aValue = theValue.SubString (1, aSplitPos - 1);
216     }
217     if (convertToDatumPart (aValue, aPart))
218     {
219       theParts.Append (aPart);
220     }
221   }
222
223   static bool convertToDatumAttribute (const TCollection_AsciiString& theValue,
224                                        Prs3d_DatumAttribute& theAttribute)
225   {
226     TCollection_AsciiString aValue = theValue;
227     aValue.LowerCase();
228     if      (aValue == "xaxislength")       theAttribute = Prs3d_DA_XAxisLength;
229     else if (aValue == "yaxislength")       theAttribute = Prs3d_DA_YAxisLength;
230     else if (aValue == "zaxislength")       theAttribute = Prs3d_DA_ZAxisLength;
231     else if (aValue == "tuberadiuspercent") theAttribute = Prs3d_DP_ShadingTubeRadiusPercent;
232     else if (aValue == "coneradiuspercent") theAttribute = Prs3d_DP_ShadingConeRadiusPercent;
233     else if (aValue == "conelengthpercent") theAttribute = Prs3d_DP_ShadingConeLengthPercent;
234     else if (aValue == "originradiuspercent") theAttribute = Prs3d_DP_ShadingOriginRadiusPercent;
235     else if (aValue == "shadingnumberoffacettes") theAttribute = Prs3d_DP_ShadingNumberOfFacettes;
236     else
237       return false;
238     return true;
239   }
240
241   static void convertToDatumAttributes (const TCollection_AsciiString& theValue,
242                                         NCollection_List<Prs3d_DatumAttribute>& theAttributes)
243   {
244     TCollection_AsciiString aValue = theValue;
245     const Standard_Integer aSplitPos = theValue.Search ("|");
246     Prs3d_DatumAttribute anAttribute = Prs3d_DA_XAxisLength;
247     if (aSplitPos > 0)
248     {
249       convertToDatumAttributes (theValue.SubString (aSplitPos + 1, theValue.Length()), theAttributes);
250       if (aSplitPos == 1) // first symbol
251       {
252         return;
253       }
254       aValue = theValue.SubString (1, aSplitPos - 1);
255     }
256     if (convertToDatumAttribute (aValue, anAttribute))
257     {
258       theAttributes.Append (anAttribute);
259     }
260   }
261
262   static bool convertToDatumAxes (const TCollection_AsciiString& theValue,
263                                   Prs3d_DatumAxes& theDatumAxes)
264   {
265     TCollection_AsciiString aValue = theValue;
266     aValue.LowerCase();
267     if      (aValue == "x")   theDatumAxes = Prs3d_DA_XAxis;
268     else if (aValue == "y")   theDatumAxes = Prs3d_DA_YAxis;
269     else if (aValue == "z")   theDatumAxes = Prs3d_DA_ZAxis;
270     else if (aValue == "xy")  theDatumAxes = Prs3d_DA_XYAxis;
271     else if (aValue == "zy")  theDatumAxes = Prs3d_DA_YZAxis;
272     else if (aValue == "xz")  theDatumAxes = Prs3d_DA_XZAxis;
273     else if (aValue == "xyz") theDatumAxes = Prs3d_DA_XYZAxis;
274     else
275     {
276       return false;
277     }
278     return true;
279   }
280
281   static Standard_Boolean setTrihedronParams (Standard_Integer  theArgsNb,
282                                               const char** theArgVec,
283                                               Handle(AIS_Trihedron) theTrihedron)
284   {
285     NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
286     TCollection_AsciiString aParseKey;
287     for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
288     {
289       TCollection_AsciiString anArg (theArgVec [anArgIt]);
290       if (anArg.Value (1) == '-'
291       && !anArg.IsRealValue())
292       {
293         aParseKey = anArg;
294         aParseKey.Remove (1);
295         aParseKey.LowerCase();
296         std::string aKey = aParseKey.ToCString();
297         aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString());
298         continue;
299       }
300
301       if (aParseKey.IsEmpty())
302       {
303         continue;
304       }
305
306       aMapOfArgs (aParseKey)->Append (anArg);
307     }
308
309     // Check parameters
310     if ((aMapOfArgs.IsBound ("xaxis") && !aMapOfArgs.IsBound ("zaxis"))
311     || (!aMapOfArgs.IsBound ("xaxis") &&  aMapOfArgs.IsBound ("zaxis")))
312     {
313       Message::SendFail ("Syntax error: -xaxis and -zaxis parameters are to set together");
314       return Standard_False;
315     }
316
317     Handle(TColStd_HSequenceOfAsciiString) aValues;
318     Handle(Geom_Axis2Placement) aComponent = theTrihedron->Component();
319     if (aMapOfArgs.Find ("origin", aValues))
320     {
321       aComponent->SetLocation (gp_Pnt (aValues->Value (1).RealValue(),
322                                        aValues->Value (2).RealValue(),
323                                        aValues->Value (3).RealValue()));
324     }
325     Handle(TColStd_HSequenceOfAsciiString) aXValues, aZValues;
326     if (aMapOfArgs.Find ("xaxis", aXValues) && aMapOfArgs.Find ("zaxis", aZValues))
327     {
328       gp_Dir aXDir (aXValues->Value (1).RealValue(),
329                     aXValues->Value (2).RealValue(),
330                     aXValues->Value (3).RealValue());
331
332       gp_Dir aZDir (aZValues->Value (1).RealValue(),
333                     aZValues->Value (2).RealValue(),
334                     aZValues->Value (3).RealValue());
335
336       if (!aZDir.IsNormal (aXDir, M_PI / 180.0))
337       {
338         Message::SendFail ("Syntax error - parameters 'xaxis' and 'zaxis' are not applied as VectorX is not normal to VectorZ");
339         return Standard_False;
340       }
341
342       aComponent->SetAx2 (gp_Ax2 (aComponent->Location(), aZDir, aXDir));
343     }
344
345     if (aMapOfArgs.Find ("dispmode", aValues))
346     {
347       TCollection_AsciiString aValue (aValues->Value (1));
348       bool isWireframe = true;
349       if (aValue.IsEqual ("sh") || aValue.IsEqual ("shading"))
350         isWireframe = false;
351       theTrihedron->SetDatumDisplayMode (isWireframe ? Prs3d_DM_WireFrame
352                                                      : Prs3d_DM_Shaded);
353     }
354
355     if (aMapOfArgs.Find ("hidelabels", aValues))
356     {
357       Standard_Boolean toHideLabels = Standard_True;
358       if (aValues->Size() == 1)
359       {
360         Draw::ParseOnOff (aValues->First().ToCString(), toHideLabels);
361       }
362       else if (aValues->Size() != 0)
363       {
364         Message::SendFail ("Syntax error: -hidelabels expects parameter 'on' or 'off' after");
365         return Standard_False;
366       }
367
368       if (!theTrihedron->Attributes()->HasOwnDatumAspect())
369       {
370         theTrihedron->Attributes()->SetDatumAspect (new Prs3d_DatumAspect());
371       }
372       theTrihedron->Attributes()->DatumAspect()->SetDrawLabels (!toHideLabels);
373     }
374
375     if (aMapOfArgs.Find ("hidearrows", aValues))
376     {
377       Standard_Boolean toHideArrows = Standard_True;
378       if (aValues->Size() == 1)
379       {
380         Draw::ParseOnOff (aValues->First().ToCString(), toHideArrows);
381       }
382       else if (aValues->Size() != 0)
383       {
384         Message::SendFail ("Syntax error: -hidearrows expects parameter 'on' or 'off' after");
385         return Standard_False;
386       }
387
388       if (!theTrihedron->Attributes()->HasOwnDatumAspect())
389       {
390         theTrihedron->Attributes()->SetDatumAspect (new Prs3d_DatumAspect());
391       }
392       theTrihedron->Attributes()->DatumAspect()->SetDrawArrows (!toHideArrows);
393     }
394
395     if (aMapOfArgs.Find ("color", aValues))
396     {
397       NCollection_List<Prs3d_DatumParts> aParts;
398       if (aValues->Size() < 2)
399       {
400         Message::SendFail ("Syntax error: -color wrong parameters");
401         return Standard_False;
402       }
403
404       convertToDatumParts (aValues->Value(1), aParts);
405       aValues->Remove (1); // datum part is processed
406       Quantity_Color aColor;
407       if (!convertToColor (aValues, aColor))
408       {
409         Message::SendFail ("Syntax error: -color wrong parameters");
410         return Standard_False;
411       }
412
413       for (NCollection_List<Prs3d_DatumParts>::Iterator anIterator (aParts); anIterator.More(); anIterator.Next())
414       {
415         Prs3d_DatumParts aDatumPart = anIterator.Value();
416         if (aDatumPart == Prs3d_DP_None)
417         {
418           theTrihedron->SetColor (aColor);
419         }
420         else
421         {
422           theTrihedron->SetDatumPartColor (aDatumPart, aColor);
423         }
424       }
425     }
426
427     if (aMapOfArgs.Find ("textcolor", aValues))
428     {
429       Quantity_Color aColor;
430       if (!convertToColor (aValues, aColor))
431       {
432         Message::SendFail ("Syntax error: -textcolor wrong parameters");
433         return Standard_False;
434       }
435       theTrihedron->SetTextColor (aColor);
436     }
437
438     if (aMapOfArgs.Find ("arrowcolor", aValues))
439     {
440       Quantity_Color aColor;
441       if (!convertToColor (aValues, aColor))
442       {
443         Message::SendFail ("Syntax error: -arrowcolor wrong parameters");
444         return Standard_False;
445       }
446       theTrihedron->SetArrowColor (aColor);
447     }
448
449     if (aMapOfArgs.Find ("attribute", aValues))
450     {
451       NCollection_List<Prs3d_DatumAttribute> anAttributes;
452       if (aValues->Size() != 2)
453       {
454         Message::SendFail ("Syntax error: -attribute wrong parameters");
455         return Standard_False;
456       }
457
458       convertToDatumAttributes (aValues->Value (1), anAttributes);
459       if (!theTrihedron->Attributes()->HasOwnDatumAspect())
460         theTrihedron->Attributes()->SetDatumAspect(new Prs3d_DatumAspect());
461       for (NCollection_List<Prs3d_DatumAttribute>::Iterator anIterator (anAttributes); anIterator.More(); anIterator.Next())
462       {
463         theTrihedron->Attributes()->DatumAspect()->SetAttribute (anIterator.Value(), aValues->Value (2).RealValue());
464       }
465     }
466
467     if (aMapOfArgs.Find ("priority", aValues))
468     {
469       Prs3d_DatumParts aDatumPart;
470       if (aValues->Size() < 2
471       || !convertToDatumPart (aValues->Value (1), aDatumPart))
472       {
473         Message::SendFail ("Syntax error: -priority wrong parameters");
474         return Standard_False;
475       }
476       theTrihedron->SetSelectionPriority (aDatumPart, aValues->Value (2).IntegerValue());
477     }
478
479     if (aMapOfArgs.Find ("labels", aValues)
480      || aMapOfArgs.Find ("label", aValues))
481     {
482       Prs3d_DatumParts aDatumPart = Prs3d_DP_None;
483       if (aValues->Size() >= 2
484        && convertToDatumPart(aValues->Value(1), aDatumPart)
485        && aDatumPart >= Prs3d_DP_XAxis
486        && aDatumPart <= Prs3d_DP_ZAxis) // labels are set to axes only
487       {
488         theTrihedron->SetLabel (aDatumPart, aValues->Value (2));
489       }
490       else
491       {
492         Message::SendFail ("Syntax error: -labels wrong parameters");
493         return Standard_False;
494       }
495     }
496
497     if (aMapOfArgs.Find ("drawaxes", aValues))
498     {
499       Prs3d_DatumAxes aDatumAxes = Prs3d_DA_XAxis;
500       if (aValues->Size() < 1
501       || !convertToDatumAxes (aValues->Value (1), aDatumAxes))
502       {
503         Message::SendFail ("Syntax error: -drawaxes wrong parameters");
504         return Standard_False;
505       }
506       if (!theTrihedron->Attributes()->HasOwnDatumAspect())
507         theTrihedron->Attributes()->SetDatumAspect(new Prs3d_DatumAspect());
508       theTrihedron->Attributes()->DatumAspect()->SetDrawDatumAxes (aDatumAxes);
509     }
510     return Standard_True;
511   }
512
513   //! Auxiliary function to parse font aspect style argument
514   static Standard_Boolean parseFontStyle (const TCollection_AsciiString& theArg,
515                                           Font_FontAspect&               theAspect)
516   {
517     if (theArg == "regular"
518      || *theArg.ToCString() == 'r')
519     {
520       theAspect = Font_FA_Regular;
521       return Standard_True;
522     }
523     else if (theArg == "bolditalic"
524           || theArg == "bold-italic"
525           || theArg == "italic-bold"
526           || theArg == "italicbold")
527     {
528       theAspect = Font_FA_BoldItalic;
529       return Standard_True;
530     }
531     else if (theArg == "bold"
532           || *theArg.ToCString() == 'b')
533     {
534       theAspect = Font_FA_Bold;
535       return Standard_True;
536     }
537     else if (theArg == "italic"
538           || *theArg.ToCString() == 'i')
539     {
540       theAspect = Font_FA_Italic;
541       return Standard_True;
542     }
543     return Standard_False;
544   }
545
546   //! Auxiliary function to parse font strict level argument
547   static Standard_Integer parseFontStrictLevel (const Standard_Integer theArgNb,
548                                                 const char**           theArgVec,
549                                                 Font_StrictLevel&      theLevel)
550   {
551     if (theArgNb >= 1)
552     {
553       TCollection_AsciiString anArg (theArgVec[0]);
554       anArg.LowerCase();
555       if (anArg == "any")
556       {
557         theLevel = Font_StrictLevel_Any;
558         return 1;
559       }
560       else if (anArg == "aliases")
561       {
562         theLevel = Font_StrictLevel_Aliases;
563         return 1;
564       }
565       else if (anArg == "strict")
566       {
567         theLevel = Font_StrictLevel_Strict;
568         return 1;
569       }
570     }
571     theLevel = Font_StrictLevel_Strict;
572     return 0;
573   }
574 }
575
576 //==============================================================================
577 //function : Vtrihedron 2d
578 //purpose  : Create a plane with a 2D  trihedron from a faceselection
579 //Draw arg : vtri2d  name
580 //==============================================================================
581 static int VTrihedron2D (Draw_Interpretor& /*theDI*/,
582                          Standard_Integer  theArgsNum,
583                          const char**      theArgVec)
584 {
585   if (theArgsNum != 2)
586   {
587     Message::SendFail() << "Syntax error: wrong number of arguments.";
588     return 1;
589   }
590
591   TopTools_ListOfShape aShapes;
592   ViewerTest::GetSelectedShapes (aShapes);
593
594   if (aShapes.Extent() != 1)
595   {
596     Message::SendFail ("Error: wrong number of selected shapes.");
597     return 1;
598   }
599
600   const TopoDS_Shape& aShape = aShapes.First();
601
602   TopoDS_Face     aFace = TopoDS::Face (aShape);
603   TopExp_Explorer aFaceExp (aFace, TopAbs_EDGE);
604   TopoDS_Edge     anEdge0 = TopoDS::Edge (aFaceExp.Current());
605
606   gp_Pnt A,B,C;
607   if (aFaceExp.More())
608   {
609     aFaceExp.Next();
610     TopoDS_Edge anEdge1 = TopoDS::Edge (aFaceExp.Current() );
611     BRepAdaptor_Curve aCurve0 (anEdge0);
612     BRepAdaptor_Curve aCurve1 (anEdge1);
613     A = aCurve1.Value (0.1);
614     B = aCurve1.Value (0.9);
615     C = aCurve0.Value (0.5);
616   }
617   else
618   {
619     BRepAdaptor_Curve aCurve0 (anEdge0);
620     A = aCurve0.Value (0.1);
621     B = aCurve0.Value (0.9);
622     C = aCurve0.Value (0.5);
623   }
624
625   GC_MakePlane aMkPlane (A,B,C);
626
627   Handle(AIS_PlaneTrihedron) anAISPlaneTri = new AIS_PlaneTrihedron (aMkPlane.Value());
628   TCollection_AsciiString aName (theArgVec[1]);
629
630   VDisplayAISObject (aName, anAISPlaneTri);
631
632   return 0;
633 }
634
635 //=======================================================================
636 //function : VTrihedron
637 //purpose  :
638 //=======================================================================
639 static int VTrihedron (Draw_Interpretor& ,
640                        Standard_Integer theArgsNb,
641                        const char** theArgVec)
642 {
643   if (theArgsNb < 2)
644   {
645     Message::SendFail ("Syntax error: the wrong number of input parameters");
646     return 1;
647   }
648
649   TCollection_AsciiString aName (theArgVec[1]);
650   gp_Pln aWorkingPlane;
651   Standard_Boolean toUpdate = Standard_True;
652
653   NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
654   NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
655
656   Handle(AIS_Trihedron) aTrihedron;
657   Handle(AIS_InteractiveObject) anObject;
658   if (GetMapOfAIS().Find2 (aName, anObject))
659   {
660     aTrihedron = Handle(AIS_Trihedron)::DownCast (anObject);
661     if (aTrihedron.IsNull())
662     {
663       Message::SendFail ("Syntax error: no trihedron with this name");
664       return 1;
665     }
666   }
667   else
668   {
669     Handle(Geom_Axis2Placement) aPlacement = new Geom_Axis2Placement (gp_Pnt (0.0, 0.0, 0.0),
670                                                                       gp::DZ(), gp::DX());
671     aTrihedron = new AIS_Trihedron (aPlacement);
672   }
673
674   if (!setTrihedronParams (theArgsNb, theArgVec, aTrihedron))
675   {
676     return 1;
677   }
678
679   // Redisplay a dimension after parameter changing.
680   if (ViewerTest::GetAISContext()->IsDisplayed (aTrihedron))
681   {
682     ViewerTest::GetAISContext()->Redisplay (aTrihedron, toUpdate);
683   }
684   else
685   {
686     VDisplayAISObject (theArgVec[1], aTrihedron);
687   }
688
689   return 0;
690 }
691
692 //==============================================================================
693 //function : VSize
694 //author   : ege
695 //purpose  : Change the size of a named or selected trihedron
696 //           if no name : it affects the trihedrons witch are selected otherwise nothing is donne
697 //           if no value, the value is set at 100 by default
698 //Draw arg : vsize [name] [size]
699 //==============================================================================
700
701 static int VSize (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
702
703 {
704   // Declaration de booleens
705   Standard_Boolean             ThereIsName;
706   Standard_Boolean             ThereIsCurrent;
707   Standard_Real                value;
708   Standard_Boolean             hascol;
709
710   Quantity_Color col = Quantity_NOC_BLACK;
711
712   // Verification des arguments
713   if ( argc>3 ) {di<<argv[0]<<" Syntaxe error\n"; return 1;}
714
715   // Verification du nombre d'arguments
716   if (argc==1)      {ThereIsName=Standard_False;value=100;}
717   else if (argc==2) {ThereIsName=Standard_False;value=Draw::Atof(argv[1]);}
718   else              {ThereIsName=Standard_True;value=Draw::Atof(argv[2]);}
719
720   // On set le booleen ThereIsCurrent
721   if (TheAISContext() -> NbSelected() > 0) {ThereIsCurrent=Standard_True;}
722   else {ThereIsCurrent=Standard_False;}
723
724
725
726   //===============================================================
727   // Il n'y a pas de nom  mais des objets selectionnes
728   //===============================================================
729   if (!ThereIsName && ThereIsCurrent)
730   {
731
732     ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName
733       it (GetMapOfAIS());
734
735     while ( it.More() ) {
736
737       Handle(AIS_InteractiveObject) aShape = it.Key1();
738
739       if (!aShape.IsNull() &&  TheAISContext()->IsSelected(aShape) )
740       {
741
742         // On verifie que l'AIS InteraciveObject selectionne est bien
743         // un AIS_Trihedron
744         if (aShape->Type()==AIS_KOI_Datum && aShape->Signature()==3) {
745
746           if (aShape->HasColor())
747           {
748             hascol = Standard_True;
749
750             // On recupere la couleur de aShape
751             aShape->Color (col);
752           }
753           else
754           {
755             hascol = Standard_False;
756           }
757
758           // On downcast aShape  de AIS_InteractiveObject a AIS_Trihedron
759           // pour lui appliquer la methode SetSize()
760           Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast (aShape);
761
762           // C'est bien un triedre,on chage sa valeur!
763           aTrihedron->SetSize(value);
764
765           // On donne la couleur au Trihedron
766           if(hascol)   aTrihedron->SetColor(col);
767           else         aTrihedron->UnsetColor();
768
769
770           // The trihedron hasn't be errased from the map
771           // so you just have to redisplay it
772           TheAISContext() ->Redisplay(aTrihedron,Standard_False);
773
774         }
775
776       }
777
778       it.Next();
779     }
780
781     TheAISContext() ->UpdateCurrentViewer();
782   }
783
784   //===============================================================
785   // Il n'y a pas d'arguments et aucuns objets selectionne Rien A Faire!
786   //===============================================================
787
788
789
790   //===============================================================
791   // Il y a un nom de triedre passe en argument
792   //===============================================================
793   if (ThereIsName) {
794     TCollection_AsciiString name=argv[1];
795
796     // on verifie que ce nom correspond bien a une shape
797     Handle(AIS_InteractiveObject) aShape;
798     if (GetMapOfAIS().Find2(name, aShape))
799     {
800       // On verifie que l'AIS InteraciveObject est bien
801       // un AIS_Trihedron
802       if (!aShape.IsNull() &&
803         aShape->Type()==AIS_KOI_Datum && aShape->Signature()==3)
804       {
805         if (aShape->HasColor())
806         {
807           hascol=Standard_True;
808
809           // On recupere la couleur de aShape
810           aShape->Color (col);
811         }
812         else
813         {
814           hascol = Standard_False;
815         }
816
817         // On downcast aShape de AIS_InteractiveObject a AIS_Trihedron
818         // pour lui appliquer la methode SetSize()
819         Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast (aShape);
820
821         // C'est bien un triedre,on chage sa valeur
822         aTrihedron->SetSize(value);
823
824         // On donne la couleur au Trihedron
825         if(hascol)   aTrihedron->SetColor(col);
826         else         aTrihedron->UnsetColor();
827
828         // The trihedron hasn't be errased from the map
829         // so you just have to redisplay it
830         TheAISContext() ->Redisplay(aTrihedron,Standard_False);
831
832         TheAISContext() ->UpdateCurrentViewer();
833       }
834     }
835   }
836   return 0;
837 }
838
839
840 //==============================================================================
841
842 //==============================================================================
843 //function : VPlaneTrihedron
844 //purpose  : Create a plane from a trihedron selection. If no arguments are set, the default
845 //Draw arg : vplanetri  name
846 //==============================================================================
847 #include <AIS_Plane.hxx>
848
849
850
851 static int VPlaneTrihedron (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
852
853 {
854   // Verification des arguments
855   if ( argc!=2) {di<<argv[0]<<" error\n"; return 1;}
856
857   if (TheAISContext()->NbSelected() != 1)
858   {
859     Message::SendFail ("Error: Wrong number of selected shapes.");
860     return 1;
861   }
862
863   TheAISContext()->InitSelected();
864   Handle(AIS_InteractiveObject) aTest = TheAISContext()->SelectedInteractive();
865   Handle(AIS_Plane) aPlane = Handle(AIS_Plane)::DownCast (aTest);
866   if (aPlane.IsNull())
867   {
868     Message::SendFail ("Error: Selected shape is not a plane.");
869     return 1;
870   }
871
872   VDisplayAISObject (argv[1], aPlane);
873
874   return 0;
875 }
876
877
878
879 //==============================================================================
880 // Fonction        First click      2de click
881 //
882 // vaxis           vertex           vertex
883 //                 edge             None
884 // vaxispara       edge             vertex
885 // vaxisortho      edge             Vertex
886 // vaxisinter      Face             Face
887 //==============================================================================
888
889 //==============================================================================
890 //function : VAxisBuilder
891 //purpose  :
892 //Draw arg : vaxis AxisName Xa Ya Za Xb Yb Zb
893 //==============================================================================
894 #include <TopoDS_Edge.hxx>
895 #include <TopoDS_Vertex.hxx>
896 #include <TopExp.hxx>
897 #include <Geom_Line.hxx>
898
899 static int VAxisBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
900 {
901   // Declarations
902   Standard_Boolean HasArg;
903   TCollection_AsciiString name;
904
905   // Verification
906   if (argc<2 || argc>8 ) {di<<" Syntaxe error\n";return 1;}
907   if (argc==8) HasArg=Standard_True;
908   else HasArg=Standard_False;
909
910   name=argv[1];
911
912   TopTools_ListOfShape aShapes;
913   ViewerTest::GetSelectedShapes (aShapes);
914
915   // Cas ou il y a des arguments
916   // Purpose: Teste le constructeur AIS_Axis::AIS_Axis(x: Line from Geom)
917   if (HasArg) {
918     Standard_Real coord[6];
919     for(Standard_Integer i=0;i<=5;i++){
920       coord[i]=Draw::Atof(argv[2+i]);
921     }
922     gp_Pnt p1(coord[0],coord[1],coord[2]), p2(coord[3],coord[4],coord[5]) ;
923
924     gp_Vec myVect (p1,p2);
925     Handle(Geom_Line) myLine=new Geom_Line (p1 ,myVect );
926     Handle(AIS_Axis) TheAxis=new AIS_Axis (myLine );
927     GetMapOfAIS().Bind (TheAxis,name);
928     TheAISContext()->Display(TheAxis, Standard_True);
929   }
930
931   // Pas d'arguments
932   else {
933     // fonction vaxis
934     // Purpose: Teste le constructeur AIS_Axis::AIS_Axis (x:Axis1Placement from Geom)
935     if ( !strcasecmp(argv[0], "vaxis")) {
936       if (aShapes.Extent() != 2 && aShapes.Extent() != 1)
937       {
938         Message::SendFail ("Error: Wrong number of selected shapes.");
939         return 1;
940       }
941
942       const TopoDS_Shape& aShapeA = aShapes.First();
943       if (aShapeA.ShapeType() == TopAbs_VERTEX)
944       {
945         if (aShapes.Extent() != 2)
946         {
947           Message::SendFail ("Error: Wrong number of selected shapes.");
948           return 1;
949         }
950
951         const TopoDS_Shape& aShapeB = aShapes.Last();
952         if (aShapeB.ShapeType() != TopAbs_VERTEX)
953         {
954           Message::SendFail ("Syntax error: You should select two vertices or one edge.");
955           return 1;
956         }
957
958         // Construction de l'axe
959         gp_Pnt A = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
960         gp_Pnt B = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
961         gp_Vec V (A,B);
962         gp_Dir D (V);
963         Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (A,D);
964         Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
965         GetMapOfAIS().Bind (TheAxis,name);
966         TheAISContext()->Display (TheAxis, Standard_True);
967       }
968       else
969       {
970         TopoDS_Edge    ed =TopoDS::Edge (aShapeA);
971         TopoDS_Vertex  Va,Vb;
972         TopExp::Vertices(ed,Va,Vb );
973         gp_Pnt A=BRep_Tool::Pnt(Va);
974         gp_Pnt B=BRep_Tool::Pnt(Vb);
975         gp_Vec  V (A,B);
976         gp_Dir   D (V);
977         Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (A,D);
978         Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
979         GetMapOfAIS().Bind (TheAxis,name);
980         TheAISContext()->Display (TheAxis, Standard_True);
981       }
982
983     }
984
985     // Fonction axispara
986     // Purpose: Teste le constructeur AIS_Axis::AIS_Axis(x: Axis2Placement from Geom, y: TypeOfAxis from AIS)
987     else if ( !strcasecmp(argv[0], "vaxispara"))
988     {
989       if (aShapes.Extent() != 2)
990       {
991         Message::SendFail ("Error: Wrong number of selected shapes.");
992         return 1;
993       }
994
995       const TopoDS_Shape& aShapeA = aShapes.First();
996       const TopoDS_Shape& aShapeB = aShapes.Last();
997       if (!(aShapeA.ShapeType() == TopAbs_EDGE
998          && aShapeB.ShapeType() == TopAbs_VERTEX))
999       {
1000         Message::SendFail ("Syntax error: You should select face and then vertex.");
1001         return 1;
1002       }
1003
1004       TopoDS_Edge    ed=TopoDS::Edge (aShapeA);
1005       gp_Pnt B=BRep_Tool::Pnt(TopoDS::Vertex(aShapeB));
1006       TopoDS_Vertex  Va,Vc;
1007       TopExp::Vertices(ed,Va,Vc );
1008       gp_Pnt A=BRep_Tool::Pnt(Va);
1009       gp_Pnt C=BRep_Tool::Pnt(Vc);
1010       gp_Vec  V (A,C);
1011       gp_Dir   D (V);
1012       Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (B,D);
1013       Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
1014       GetMapOfAIS().Bind (TheAxis,name);
1015       TheAISContext()->Display (TheAxis, Standard_True);
1016
1017     }
1018
1019     // Fonction axisortho
1020     else
1021     {
1022       if (aShapes.Extent() != 2)
1023       {
1024         Message::SendFail ("Error: Wrong number of selected shapes.");
1025         return 1;
1026       }
1027
1028       const TopoDS_Shape& aShapeA = aShapes.First();
1029       const TopoDS_Shape& aShapeB = aShapes.Last();
1030       if (!(aShapeA.ShapeType() == TopAbs_EDGE
1031          && aShapeB.ShapeType() == TopAbs_VERTEX))
1032       {
1033         Message::SendFail ("Syntax error: You should select face and then vertex.");
1034         return 1;
1035       }
1036
1037       // Construction de l'axe
1038       TopoDS_Edge    ed=TopoDS::Edge(aShapeA) ;
1039       gp_Pnt B=BRep_Tool::Pnt(TopoDS::Vertex(aShapeB) );
1040       TopoDS_Vertex  Va,Vc;
1041       TopExp::Vertices(ed,Va,Vc );
1042       gp_Pnt A=BRep_Tool::Pnt(Va);
1043       gp_Pnt C=BRep_Tool::Pnt(Vc);
1044       gp_Pnt E(A.Y()+A.Z()-C.Y()-C.Z()  ,C.X()-A.X() ,C.X()-A.X() );
1045       gp_Vec  V (A,E);
1046       gp_Dir   D (V);
1047       Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (B,D);
1048       Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
1049       GetMapOfAIS().Bind (TheAxis,name);
1050       TheAISContext()->Display (TheAxis, Standard_True);
1051
1052     }
1053
1054   }
1055   return 0;
1056 }
1057
1058
1059 //==============================================================================
1060 // Fonction        First click      Result
1061 //
1062 // vpoint          vertex           AIS_Point=Vertex
1063 //                 edge             AIS_Point=Middle of the edge
1064 //==============================================================================
1065
1066 //==============================================================================
1067 //function : VPointBuilder
1068 //purpose  :
1069 //==============================================================================
1070 #include <TopoDS_Edge.hxx>
1071 #include <TopoDS_Vertex.hxx>
1072 #include <TopExp.hxx>
1073 #include <AIS_Point.hxx>
1074 #include <Geom_CartesianPoint.hxx>
1075
1076 static int VPointBuilder(Draw_Interpretor& ,
1077                          Standard_Integer theArgNb,
1078                          const char** theArgVec)
1079 {
1080   TCollection_AsciiString aName;
1081   gp_Pnt aPnt (RealLast(), 0.0, 0.0);
1082   bool is2d = false, isNoSel = false;
1083   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
1084   {
1085     TCollection_AsciiString anArg (theArgVec[anArgIter]);
1086     anArg.LowerCase();
1087     if (anArg == "-2d")
1088     {
1089       is2d = true;
1090     }
1091     else if (anArg == "-nosel"
1092           || anArg == "-noselection")
1093     {
1094       isNoSel = true;
1095     }
1096     else if (aName.IsEmpty())
1097     {
1098       aName = theArgVec[anArgIter];
1099     }
1100     else if (aPnt.X() == RealLast()
1101           && anArgIter + 1 < theArgNb
1102           && Draw::ParseReal (theArgVec[anArgIter + 0], aPnt.ChangeCoord().ChangeCoord (1))
1103           && Draw::ParseReal (theArgVec[anArgIter + 1], aPnt.ChangeCoord().ChangeCoord (2)))
1104     {
1105       if (anArgIter + 2 < theArgNb
1106        && TCollection_AsciiString (theArgVec[anArgIter + 2]) != "-2d"
1107        && Draw::ParseReal (theArgVec[anArgIter + 2], aPnt.ChangeCoord().ChangeCoord (3)))
1108       {
1109         anArgIter += 2;
1110       }
1111       else
1112       {
1113         anArgIter += 1;
1114       }
1115     }
1116     else
1117     {
1118       Message::SendFail() << "Syntax error at argument '" << anArg << "'\n";
1119       return 1;
1120     }
1121   }
1122
1123   if (aPnt.X() == RealLast())
1124   {
1125     TopTools_ListOfShape aShapes;
1126     ViewerTest::GetSelectedShapes (aShapes);
1127     TopoDS_Shape aShapeA;
1128     if (aShapes.Extent() == 1)
1129     {
1130       aShapeA = aShapes.First();
1131     }
1132     switch (!aShapeA.IsNull() ? aShapeA.ShapeType() : TopAbs_SHAPE)
1133     {
1134       case TopAbs_VERTEX:
1135       {
1136         aPnt = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
1137         break;
1138       }
1139       case TopAbs_EDGE: // edge middle point
1140       {
1141         const TopoDS_Edge& anEdge = TopoDS::Edge (aShapeA);
1142         TopoDS_Vertex aVertPair[2];
1143         TopExp::Vertices (anEdge, aVertPair[0], aVertPair[1]);
1144         const gp_Pnt A = BRep_Tool::Pnt (aVertPair[0]);
1145         const gp_Pnt B = BRep_Tool::Pnt (aVertPair[1]);
1146         aPnt = (A.XYZ() + B.XYZ()) / 2;
1147         break;
1148       }
1149       default:
1150       {
1151         Message::SendFail() << "Error: Wrong number of selected shapes.\n"
1152                             << "\tYou should select one edge or vertex.";
1153         return 1;
1154       }
1155     }
1156   }
1157
1158   if (is2d)
1159   {
1160     aPnt.SetY (-aPnt.Y());
1161   }
1162   Handle(Geom_CartesianPoint ) aGeomPoint = new Geom_CartesianPoint (aPnt);
1163   Handle(AIS_Point) aPointPrs = new AIS_Point (aGeomPoint);
1164   if (is2d)
1165   {
1166     aPointPrs->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER));
1167     aPointPrs->SetZLayer (Graphic3d_ZLayerId_TopOSD);
1168   }
1169   ViewerTest::Display (aName, aPointPrs);
1170   if (isNoSel)
1171   {
1172     ViewerTest::GetAISContext()->Deactivate (aPointPrs);
1173   }
1174   return 0;
1175 }
1176
1177 //==============================================================================
1178 // Function        1st click   2de click  3de click
1179 // vplane          Vertex      Vertex     Vertex
1180 //                 Vertex      Edge
1181 //                 Edge        Vertex
1182 //                 Face
1183 // vplanepara      Face        Vertex
1184 //                 Vertex      Face
1185 // vplaneortho     Face        Edge
1186 //                 Edge        Face
1187 //==============================================================================
1188
1189 //==============================================================================
1190 //function : VPlaneBuilder
1191 //purpose  : Build an AIS_Plane from selected entities or Named AIS components
1192 //Draw arg : vplane PlaneName [AxisName]  [PointName] [TypeOfSensitivity]
1193 //                            [PointName] [PointName] [PointName] [TypeOfSensitivity]
1194 //                            [PlaneName] [PointName] [TypeOfSensitivity]
1195 //==============================================================================
1196
1197 static Standard_Integer VPlaneBuilder (Draw_Interpretor& /*di*/,
1198                                        Standard_Integer argc,
1199                                        const char** argv)
1200 {
1201   // Declarations
1202   Standard_Boolean hasArg;
1203   TCollection_AsciiString aName;
1204
1205   // Verification
1206   if (argc<2 || argc>6 )
1207   {
1208     Message::SendFail ("Syntax error: wrong number of arguments");
1209     return 1;
1210   }
1211   if (argc == 6 || argc==5 || argc==4)
1212     hasArg=Standard_True;
1213   else 
1214     hasArg=Standard_False;
1215
1216   aName=argv[1];
1217
1218   // There are some arguments
1219   if (hasArg)
1220   {
1221     Handle(AIS_InteractiveObject) aShapeA;
1222     if (!GetMapOfAIS().Find2 (argv[2], aShapeA))
1223     {
1224       Message::SendFail ("Syntax error: 1st name is not displayed");
1225       return 1;
1226     }
1227
1228     // The first argument is an AIS_Point
1229     if (!aShapeA.IsNull() &&
1230         aShapeA->Type()==AIS_KOI_Datum &&
1231         aShapeA->Signature()==1)
1232     {
1233         // The second argument must also be an AIS_Point
1234         Handle(AIS_InteractiveObject) aShapeB;
1235         if (argc<5 || !GetMapOfAIS().Find2 (argv[3], aShapeB))
1236         {
1237           Message::SendFail ("Syntax error: 2nd name is not displayed");
1238           return 1;
1239         }
1240         // If B is not an AIS_Point
1241         if (aShapeB.IsNull() ||
1242           (!(aShapeB->Type()==AIS_KOI_Datum && aShapeB->Signature()==1)))
1243         {
1244           Message::SendFail ("Syntax error: 2nd object is expected to be an AIS_Point");
1245           return 1;
1246         }
1247         // The third object is an AIS_Point
1248         Handle(AIS_InteractiveObject) aShapeC;
1249         if (!GetMapOfAIS().Find2(argv[4], aShapeC)) 
1250         {
1251           Message::SendFail ("Syntax error: 3d name is not displayed");
1252           return 1; 
1253         }
1254         // If C is not an AIS_Point
1255         if (aShapeC.IsNull() ||
1256           (!(aShapeC->Type()==AIS_KOI_Datum && aShapeC->Signature()==1)))
1257         {
1258           Message::SendFail ("Syntax error: 3d object is expected to be an AIS_Point");
1259           return 1;
1260         }
1261
1262         // Treatment of objects A, B, C
1263         // Downcast an AIS_IO to AIS_Point
1264         Handle(AIS_Point) anAISPointA = Handle(AIS_Point)::DownCast( aShapeA);
1265         Handle(AIS_Point) anAISPointB = Handle(AIS_Point)::DownCast( aShapeB);
1266         Handle(AIS_Point) anAISPointC = Handle(AIS_Point)::DownCast( aShapeC);
1267
1268         Handle(Geom_CartesianPoint ) aCartPointA = 
1269           Handle(Geom_CartesianPoint)::DownCast( anAISPointA->Component());
1270
1271         Handle(Geom_CartesianPoint ) aCartPointB = 
1272           Handle(Geom_CartesianPoint)::DownCast( anAISPointB->Component());
1273
1274         Handle(Geom_CartesianPoint ) aCartPointC = 
1275           Handle(Geom_CartesianPoint)::DownCast( anAISPointC->Component());
1276
1277         // Verification that the three points are different
1278         if(Abs(aCartPointB->X()-aCartPointA->X())<=Precision::Confusion() &&
1279            Abs(aCartPointB->Y()-aCartPointA->Y())<=Precision::Confusion() &&
1280            Abs(aCartPointB->Z()-aCartPointA->Z())<=Precision::Confusion())
1281         {
1282           // B=A
1283           Message::SendFail ("Error: same points");
1284           return 1;
1285         }
1286         if(Abs(aCartPointC->X()-aCartPointA->X())<=Precision::Confusion() &&
1287            Abs(aCartPointC->Y()-aCartPointA->Y())<=Precision::Confusion() &&
1288            Abs(aCartPointC->Z()-aCartPointA->Z())<=Precision::Confusion())
1289         {
1290           // C=A
1291           Message::SendFail ("Error: same points");
1292           return 1;
1293         }
1294         if(Abs(aCartPointC->X()-aCartPointB->X())<=Precision::Confusion() &&
1295            Abs(aCartPointC->Y()-aCartPointB->Y())<=Precision::Confusion() &&
1296            Abs(aCartPointC->Z()-aCartPointB->Z())<=Precision::Confusion())
1297         {
1298           // C=B
1299           Message::SendFail ("Error: same points");
1300           return 1;
1301         }
1302
1303         gp_Pnt A = aCartPointA->Pnt();
1304         gp_Pnt B = aCartPointB->Pnt();
1305         gp_Pnt C = aCartPointC->Pnt();
1306
1307         // Construction of AIS_Plane
1308         GC_MakePlane MkPlane (A,B,C);
1309         Handle(Geom_Plane) aGeomPlane = MkPlane.Value();
1310         Handle(AIS_Plane)  anAISPlane = new AIS_Plane(aGeomPlane );
1311         GetMapOfAIS().Bind (anAISPlane,aName );
1312         if (argc == 6)
1313         {
1314           Standard_Integer aType = Draw::Atoi (argv[5]);
1315           if (aType != 0 && aType != 1)
1316           {
1317             Message::SendFail("Syntax error: wrong type of sensitivity.\n"
1318                               "Should be one of the following values:\n"
1319                               "0 - Interior\n"
1320                               "1 - Boundary");
1321             return 1;
1322           }
1323           else
1324           {
1325             anAISPlane->SetTypeOfSensitivity (Select3D_TypeOfSensitivity (aType));
1326           }
1327         }
1328         TheAISContext()->Display (anAISPlane, Standard_True);
1329       }
1330
1331       // The first argument is an AIS_Axis
1332       // Creation of a plane orthogonal to the axis through a point
1333     else if (aShapeA->Type()==AIS_KOI_Datum && aShapeA->Signature()==2 ) {
1334       // The second argument should be an AIS_Point
1335       Handle(AIS_InteractiveObject) aShapeB;
1336       if (argc!=4 || !GetMapOfAIS().Find2 (argv[3], aShapeB))
1337       {
1338         Message::SendFail ("Syntax error: 2d name is not displayed");
1339         return 1;
1340       }
1341       // If B is not an AIS_Point
1342       if (aShapeB.IsNull() ||
1343         (!(aShapeB->Type()==AIS_KOI_Datum && aShapeB->Signature()==1)))
1344       {
1345         Message::SendFail ("Syntax error: 2d object is expected to be an AIS_Point");
1346         return 1;
1347       }
1348
1349       // Treatment of objects A and B
1350       Handle(AIS_Axis) anAISAxisA = Handle(AIS_Axis)::DownCast(aShapeA);
1351       Handle(AIS_Point) anAISPointB = Handle(AIS_Point)::DownCast(aShapeB);
1352
1353       Handle(Geom_Line ) aGeomLineA = anAISAxisA ->Component();
1354       Handle(Geom_Point) aGeomPointB = anAISPointB->Component()  ;
1355
1356       gp_Ax1 anAxis = aGeomLineA->Position();
1357       Handle(Geom_CartesianPoint) aCartPointB = 
1358         Handle(Geom_CartesianPoint)::DownCast(aGeomPointB);
1359
1360       gp_Dir D =anAxis.Direction();
1361       gp_Pnt B = aCartPointB->Pnt();
1362
1363       // Construction of AIS_Plane
1364       Handle(Geom_Plane) aGeomPlane = new Geom_Plane(B,D);
1365       Handle(AIS_Plane) anAISPlane = new AIS_Plane(aGeomPlane,B );
1366       GetMapOfAIS().Bind (anAISPlane,aName );
1367       if (argc == 5)
1368       {
1369         Standard_Integer aType = Draw::Atoi (argv[4]);
1370         if (aType != 0 && aType != 1)
1371         {
1372           Message::SendFail ("Syntax error: wrong type of sensitivity!\n"
1373                              "Should be one of the following values:\n"
1374                              "0 - Interior\n"
1375                              "1 - Boundary");
1376           return 1;
1377         }
1378         else
1379         {
1380           anAISPlane->SetTypeOfSensitivity (Select3D_TypeOfSensitivity (aType));
1381         }
1382       }
1383       TheAISContext()->Display (anAISPlane, Standard_True);
1384
1385     }
1386     // The first argumnet is an AIS_Plane
1387     // Creation of a plane parallel to the plane passing through the point
1388     else if (aShapeA->Type()==AIS_KOI_Datum && aShapeA->Signature()==7)
1389     {
1390       // The second argument should be an AIS_Point
1391       Handle(AIS_InteractiveObject) aShapeB;
1392       if (argc!=4 || !GetMapOfAIS().Find2 (argv[3], aShapeB))
1393       {
1394         Message::SendFail ("Syntax error: 2d name is not displayed");
1395         return 1;
1396       }
1397       // B should be an AIS_Point
1398       if (aShapeB.IsNull() ||
1399          (!(aShapeB->Type()==AIS_KOI_Datum && aShapeB->Signature()==1)))
1400       {
1401         Message::SendFail ("Syntax error: 2d object is expected to be an AIS_Point");
1402         return 1;
1403       }
1404
1405       // Treatment of objects A and B
1406       Handle(AIS_Plane) anAISPlaneA = Handle(AIS_Plane)::DownCast(aShapeA);
1407       Handle(AIS_Point) anAISPointB = Handle(AIS_Point)::DownCast(aShapeB);
1408
1409       Handle(Geom_Plane) aNewGeomPlane= anAISPlaneA->Component();
1410       Handle(Geom_Point) aGeomPointB = anAISPointB->Component();
1411
1412       Handle(Geom_CartesianPoint) aCartPointB = 
1413         Handle(Geom_CartesianPoint)::DownCast(aGeomPointB);
1414       gp_Pnt B= aCartPointB->Pnt();
1415
1416       // Construction of an AIS_Plane
1417       Handle(AIS_Plane) anAISPlane = new AIS_Plane(aNewGeomPlane, B);
1418       GetMapOfAIS().Bind (anAISPlane, aName);
1419       if (argc == 5)
1420       {
1421         Standard_Integer aType = Draw::Atoi (argv[4]);
1422         if (aType != 0 && aType != 1)
1423         {
1424           Message::SendFail ("Syntax error: wrong type of sensitivity!\n"
1425                              "Should be one of the following values:\n"
1426                              "0 - Interior\n"
1427                              "1 - Boundary");
1428           return 1;
1429         }
1430         else
1431         {
1432           anAISPlane->SetTypeOfSensitivity (Select3D_TypeOfSensitivity (aType));
1433         }
1434       }
1435       TheAISContext()->Display (anAISPlane, Standard_True);
1436     }
1437     // Error
1438     else
1439     {
1440       Message::SendFail ("Syntax error: 1st object is not an AIS");
1441       return 1;
1442     }
1443   }
1444   // There are no arguments
1445   else 
1446   {
1447     TopTools_ListOfShape aShapes;
1448     ViewerTest::GetSelectedShapes (aShapes);
1449
1450     // Function vplane
1451     // Test the constructor AIS_Plane::AIS_Plane(Geom_Plane, Standard_Boolean )
1452     if (!strcasecmp(argv[0], "vplane"))
1453     {
1454       if (aShapes.Extent() < 1 || aShapes.Extent() > 3)
1455       {
1456         Message::SendFail() << "Error: Wront number of selected shapes.\n"
1457                             << "\tYou should one of variant: face, edge and vertex or three vertices.";
1458         return 1;
1459       }
1460
1461       const TopoDS_Shape& aShapeA = aShapes.First();
1462       if (aShapeA.ShapeType() == TopAbs_VERTEX)
1463       {
1464         if (aShapes.Extent() == 2)
1465         {
1466           const TopoDS_Shape& aShapeB = aShapes.Last();
1467           if (aShapeB.ShapeType() != TopAbs_EDGE)
1468           {
1469             Message::SendFail ("Syntax error: Together with vertex should be edge.");
1470             return 1;
1471           }
1472
1473           // Verify that the vertex is not on the edge ShapeB
1474           TopoDS_Edge anEdgeB = TopoDS::Edge(aShapeB);
1475           TopoDS_Vertex aVertA = TopoDS::Vertex(aShapeA);
1476
1477           BRepExtrema_ExtPC OrthoProj(aVertA, anEdgeB);
1478           if (OrthoProj.SquareDistance(1)<Precision::Approximation())
1479           {
1480             // The vertex is on the edge
1481             Message::SendFail ("Error: point is on the edge");
1482             return 1;
1483           }
1484           else
1485           {
1486             gp_Pnt A = BRep_Tool::Pnt(aVertA);
1487             TopoDS_Vertex aVBa, aVBb;
1488             TopExp::Vertices(anEdgeB ,aVBa ,aVBb);
1489             gp_Pnt aBa = BRep_Tool::Pnt(aVBa);
1490             gp_Pnt aBb = BRep_Tool::Pnt(aVBb);
1491             GC_MakePlane MkPlane (A, aBa, aBb);
1492             Handle(Geom_Plane) aGeomPlane = MkPlane.Value();
1493             Handle(AIS_Plane) anAISPlane = new AIS_Plane (aGeomPlane);
1494             GetMapOfAIS().Bind (anAISPlane, aName);
1495             TheAISContext()->Display (anAISPlane, Standard_True);
1496           }
1497         }
1498         else if (aShapes.Extent() == 3)
1499         {
1500           TopTools_ListOfShape::Iterator anIter (aShapes);
1501
1502           anIter.Next();
1503           const TopoDS_Shape& aShapeB = anIter.Value();
1504
1505           anIter.Next();
1506           const TopoDS_Shape& aShapeC = anIter.Value();
1507
1508           if (!(aShapeB.ShapeType() == TopAbs_VERTEX
1509              && aShapeC.ShapeType() == TopAbs_VERTEX))
1510           {
1511             Message::SendFail ("Syntax error: You should one of variant: face, edge and vertex or three vertices.");
1512             return 1;
1513           }
1514
1515           gp_Pnt A = BRep_Tool::Pnt(TopoDS::Vertex(aShapeA));
1516           gp_Pnt B = BRep_Tool::Pnt(TopoDS::Vertex(aShapeB));
1517           gp_Pnt C = BRep_Tool::Pnt(TopoDS::Vertex(aShapeC));
1518           GC_MakePlane MkPlane(A, B, C);
1519           Handle(Geom_Plane) aGeomPlane = MkPlane.Value();
1520           Handle(AIS_Plane) anAISPlane = new AIS_Plane (aGeomPlane);
1521           GetMapOfAIS().Bind (anAISPlane, aName);
1522           TheAISContext()->Display (anAISPlane, Standard_True);
1523         }
1524         else
1525         {
1526           Message::SendFail ("Syntax error: You should one of variant: face, edge and vertex or three vertices.");
1527           return 1;
1528         }
1529       }
1530       else if (aShapeA.ShapeType() == TopAbs_EDGE)
1531       {
1532         if (aShapes.Extent() != 2)
1533         {
1534           Message::SendFail ("Error: wrong number of selected shapes.");
1535           return 1;
1536         }
1537
1538         const TopoDS_Shape& aShapeB = aShapes.Last();
1539         if (aShapeB.ShapeType() != TopAbs_VERTEX)
1540         {
1541           Message::SendFail ("Syntax error: Together with edge should be vertex.");
1542           return 1;
1543         }
1544
1545         // Check that the vertex aShapeB is not on the edge
1546         TopoDS_Edge anEdgeA = TopoDS::Edge(aShapeA);
1547         TopoDS_Vertex aVertB = TopoDS::Vertex(aShapeB);
1548
1549         BRepExtrema_ExtPC OrthoProj (aVertB, anEdgeA);
1550         if (OrthoProj.SquareDistance(1)<Precision::Approximation())
1551         {
1552           // The vertex is on the edge
1553           Message::SendFail ("Error point is on the edge");
1554           return 1;
1555         }
1556
1557         gp_Pnt B = BRep_Tool::Pnt(aVertB);
1558         TopoDS_Vertex aVAa, aVAb;
1559         TopExp::Vertices(anEdgeA, aVAa, aVAb);
1560         gp_Pnt Aa = BRep_Tool::Pnt(aVAa);
1561         gp_Pnt Ab = BRep_Tool::Pnt(aVAb);
1562         GC_MakePlane MkPlane (B,Aa,Ab);
1563         Handle(Geom_Plane) aGeomPlane = MkPlane.Value();
1564         Handle(AIS_Plane) anAISPlane = new AIS_Plane (aGeomPlane);
1565         GetMapOfAIS().Bind (anAISPlane ,aName);
1566         TheAISContext()->Display (anAISPlane, Standard_True);
1567       }
1568       else if (aShapeA.ShapeType() == TopAbs_FACE)
1569       {
1570         TopoDS_Face aFace = TopoDS::Face(aShapeA);
1571         BRepAdaptor_Surface aSurface (aFace, Standard_False);
1572         if (aSurface.GetType()==GeomAbs_Plane)
1573         {
1574           gp_Pln aPlane = aSurface.Plane();
1575           Handle(Geom_Plane) aGeomPlane = new Geom_Plane(aPlane);
1576           Handle(AIS_Plane) anAISPlane = new AIS_Plane(aGeomPlane);
1577           GetMapOfAIS().Bind (anAISPlane, aName);
1578           TheAISContext()->Display (anAISPlane, Standard_True);
1579         }
1580         else
1581         {
1582           Message::SendFail ("Error: surface is not Plane");
1583           return 1;
1584         }
1585       }
1586       else
1587       {
1588         Message::SendFail ("Syntax error: You should one of variant: face, edge and vertex or three vertices");
1589         return 1;
1590       }
1591     }
1592
1593     // Function vPlanePara
1594     // ===================
1595     // test the constructor AIS_Plane::AIS_Plane(Geom_Plane,gp_Pnt)
1596     else if (!strcasecmp(argv[0], "vplanepara"))
1597     {
1598       if (aShapes.Extent() != 2)
1599       {
1600         Message::SendFail ("Error: Wrong number of selected shapes.");
1601         return 1;
1602       }
1603
1604       const TopoDS_Shape* aShapeA = &aShapes.First();
1605       const TopoDS_Shape* aShapeB = &aShapes.Last();
1606       if (aShapeA->ShapeType() != TopAbs_VERTEX)
1607       {
1608         std::swap (aShapeA, aShapeB);
1609       }
1610
1611       if (!(aShapeA->ShapeType() == TopAbs_VERTEX
1612          && aShapeB->ShapeType() == TopAbs_FACE))
1613       {
1614         Message::SendFail ("Syntax error: you should select face and vertex.");
1615         return 1;
1616       }
1617
1618       gp_Pnt A = BRep_Tool::Pnt(TopoDS::Vertex(*aShapeA));
1619
1620       TopoDS_Face aFace = TopoDS::Face(*aShapeB);
1621       BRepAdaptor_Surface aSurface (aFace, Standard_False);
1622       if (aSurface.GetType() == GeomAbs_Plane)
1623       {
1624         gp_Pln aPlane = aSurface.Plane();
1625         // Construct a plane parallel to aGeomPlane through A
1626         aPlane.SetLocation(A);
1627         Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
1628         Handle(AIS_Plane) aAISPlane = new AIS_Plane (aGeomPlane, A);
1629         GetMapOfAIS().Bind (aAISPlane ,aName);
1630         TheAISContext()->Display (aAISPlane, Standard_True);
1631       }
1632       else
1633       {
1634         Message::SendFail ("Error: Builded surface is not a plane.");
1635         return 1;
1636       }
1637     }
1638
1639     // Function vplaneortho
1640     // ====================
1641     // test the constructor AIS_Plane::AIS_Plane(Geom_Plane,gp_Pnt,gp_Pnt,gp_Pnt)
1642     else
1643     {
1644       if (aShapes.Extent() != 2)
1645       {
1646         Message::SendFail ("Error: wrong number of selected shapes.");
1647         return 1;
1648       }
1649
1650       const TopoDS_Shape* aShapeA = &aShapes.First();
1651       const TopoDS_Shape* aShapeB = &aShapes.Last();
1652
1653       if (aShapeA->ShapeType() != TopAbs_EDGE)
1654       {
1655         std::swap (aShapeA, aShapeB);
1656       }
1657
1658       if (!(aShapeA->ShapeType() == TopAbs_EDGE
1659          && aShapeB->ShapeType() == TopAbs_FACE))
1660       {
1661         Message::SendFail ("Error: you should select edge and face.");
1662         return 1;
1663       }
1664
1665       // Construction of plane
1666       TopoDS_Edge anEdgeA = TopoDS::Edge(*aShapeA);
1667       TopoDS_Vertex aVAa, aVAb;
1668       TopExp::Vertices(anEdgeA, aVAa, aVAb);
1669       gp_Pnt Aa = BRep_Tool::Pnt(aVAa);
1670       gp_Pnt Ab = BRep_Tool::Pnt(aVAb);
1671       gp_Vec ab (Aa,Ab);
1672
1673       gp_Dir Dab (ab);
1674       // Creation of rotation axis
1675       gp_Ax1 aRotAxis (Aa,Dab);
1676
1677       TopoDS_Face aFace = TopoDS::Face(*aShapeB);
1678       // The edge must be parallel to the face
1679       BRepExtrema_ExtPF aHeightA (aVAa, aFace);
1680       BRepExtrema_ExtPF aHeightB (aVAb, aFace);
1681       // Compare to heights
1682       if (fabs(sqrt(aHeightA.SquareDistance(1)) - sqrt(aHeightB.SquareDistance(1)))
1683           >Precision::Confusion())
1684       {
1685         // the edge is not parallel to the face
1686         Message::SendFail ("Error: the edge is not parallel to the face");
1687         return 1;
1688       }
1689       // the edge is OK
1690       BRepAdaptor_Surface aSurface (aFace, Standard_False);
1691       if (aSurface.GetType()==GeomAbs_Plane)
1692       {
1693         gp_Pln aPlane = aSurface.Plane();
1694         // It rotates a half turn round the axis of rotation
1695         aPlane.Rotate(aRotAxis , M_PI/2);
1696
1697         Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
1698         // constructed aGeomPlane parallel to a plane containing the edge (center mid-edge)
1699         gp_Pnt aMiddle ((Aa.X()+Ab.X() )/2 ,(Aa.Y()+Ab.Y() )/2 ,(Aa.Z()+Ab.Z() )/2 );
1700         Handle(AIS_Plane) anAISPlane = new AIS_Plane (aGeomPlane, aMiddle);
1701         GetMapOfAIS().Bind (anAISPlane, aName);
1702         TheAISContext()->Display (anAISPlane, Standard_True);
1703       }
1704       else
1705       {
1706         Message::SendFail ("Error: surface is not Plane");
1707         return 1;
1708       }
1709     }
1710   }
1711   return 0;
1712 }
1713
1714 //===============================================================================================
1715 //function : VChangePlane
1716 //purpose  :
1717 //===============================================================================================
1718 static int VChangePlane (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
1719 {
1720   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
1721   if (aContextAIS.IsNull())
1722   {
1723     Message::SendFail ("Error: no active viewer.");
1724     return 1;
1725   }
1726
1727   if (theArgsNb < 3 || theArgsNb > 11)
1728   {
1729     Message::SendFail ("Syntax error: wrong number of arguments.");
1730     return 1;
1731   }
1732
1733   TCollection_AsciiString aName (theArgVec[1]);
1734
1735   Handle(AIS_Plane) aPlane = GetMapOfAIS().IsBound2(aName)
1736     ? Handle(AIS_Plane)::DownCast (GetMapOfAIS().Find2 (aName))
1737     : NULL;
1738
1739   if ( aPlane.IsNull() )
1740   {
1741     Message::SendFail() << "Syntax error: there is no interactive plane with the given name '" << aName << "'.";
1742     return 1;
1743   }
1744
1745   Standard_Real aCenterX = aPlane->Center().X();
1746   Standard_Real aCenterY = aPlane->Center().Y();
1747   Standard_Real aCenterZ = aPlane->Center().Z();
1748
1749   Standard_Real aDirX = aPlane->Component()->Axis().Direction().X();
1750   Standard_Real aDirY = aPlane->Component()->Axis().Direction().Y();
1751   Standard_Real aDirZ = aPlane->Component()->Axis().Direction().Z();
1752
1753   Standard_Real aSizeX = 0.0;
1754   Standard_Real aSizeY = 0.0;
1755   aPlane->Size (aSizeX, aSizeY);
1756   Standard_Boolean isUpdate = Standard_True;
1757
1758   TCollection_AsciiString aPName, aPValue;
1759   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
1760   {
1761     const TCollection_AsciiString anArg = theArgVec[anArgIt];
1762     TCollection_AsciiString anArgCase = anArg;
1763     anArgCase.UpperCase();
1764     if (ViewerTest::SplitParameter (anArg, aPName, aPValue))
1765     {
1766       aPName.UpperCase();
1767       if (aPName.IsEqual ("X"))
1768       {
1769         aCenterX = aPValue.RealValue();
1770       }
1771       else if (aPName.IsEqual ("Y"))
1772       {
1773         aCenterY = aPValue.RealValue();
1774       }
1775       else if (aPName.IsEqual ("Z"))
1776       {
1777         aCenterZ = aPValue.RealValue();
1778       }
1779       else if (aPName.IsEqual ("DX"))
1780       {
1781         aDirX = aPValue.RealValue();
1782       }
1783       else if (aPName.IsEqual ("DY"))
1784       {
1785         aDirY = aPValue.RealValue();
1786       }
1787       else if (aPName.IsEqual ("DZ"))
1788       {
1789         aDirZ = aPValue.RealValue();
1790       }
1791       else if (aPName.IsEqual ("SX"))
1792       {
1793         aSizeX = aPValue.RealValue();
1794       }
1795       else if (aPName.IsEqual ("SY"))
1796       {
1797         aSizeY = aPValue.RealValue();
1798       }
1799     }
1800     else if (anArg.IsEqual ("NOUPDATE"))
1801     {
1802       isUpdate = Standard_False;
1803     }
1804   }
1805
1806   gp_Dir aDirection (aDirX, aDirY, aDirZ);
1807   gp_Pnt aCenterPnt (aCenterX, aCenterY, aCenterZ);
1808   aPlane->SetCenter (aCenterPnt);
1809   aPlane->SetComponent (new Geom_Plane (aCenterPnt, aDirection));
1810   aPlane->SetSize (aSizeX, aSizeY);
1811
1812   aContextAIS->Update (aPlane, isUpdate);
1813
1814   return 0;
1815 }
1816
1817 //==============================================================================
1818 // Fonction  vline
1819 // ---------------  Uniquement par parametre. Pas de selection dans le viewer.
1820 //==============================================================================
1821
1822 //==============================================================================
1823 //function : VLineBuilder
1824 //purpose  : Build an AIS_Line
1825 //Draw arg : vline LineName  [AIS_PointName] [AIS_PointName]
1826 //                           [Xa] [Ya] [Za]   [Xb] [Yb] [Zb]
1827 //==============================================================================
1828 #include <Geom_CartesianPoint.hxx>
1829 #include <AIS_Line.hxx>
1830
1831
1832 static int VLineBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1833 {
1834   // Verifications
1835   if (argc!=4 && argc!=8 && argc!=2 )  {di<<"vline error: number of arguments not correct \n";return 1; }
1836
1837   // On recupere les parametres
1838   Handle(AIS_InteractiveObject) theShapeA;
1839   Handle(AIS_InteractiveObject) theShapeB;
1840
1841   // Parametres: AIS_Point AIS_Point
1842   // ===============================
1843   if (argc==4) {
1844     GetMapOfAIS().Find2 (argv[2], theShapeA);
1845     // On verifie que c'est bien une AIS_Point
1846     if (!theShapeA.IsNull() &&
1847       theShapeA->Type()==AIS_KOI_Datum && theShapeA->Signature()==1) {
1848         // on recupere le deuxieme AIS_Point
1849         GetMapOfAIS().Find2 (argv[3], theShapeB);
1850         if (theShapeB.IsNull() ||
1851           (!(theShapeB->Type()==AIS_KOI_Datum && theShapeB->Signature()==1)))
1852         {
1853           di <<"vline error: wrong type of 2de argument.\n";
1854           return 1;
1855         }
1856       }
1857     else {di <<"vline error: wrong type of 1st argument.\n";return 1; }
1858     // Les deux parametres sont du bon type. On verifie que les points ne sont pas confondus
1859     Handle(AIS_Point) theAISPointA= Handle(AIS_Point)::DownCast (theShapeA);
1860     Handle(AIS_Point) theAISPointB= Handle(AIS_Point)::DownCast (theShapeB);
1861
1862     Handle(Geom_Point ) myGeomPointBA=  theAISPointA->Component();
1863     Handle(Geom_CartesianPoint ) myCartPointA= Handle(Geom_CartesianPoint)::DownCast (myGeomPointBA);
1864     //    Handle(Geom_CartesianPoint ) myCartPointA= *(Handle(Geom_CartesianPoint)*)& (theAISPointA->Component() ) ;
1865
1866     Handle(Geom_Point ) myGeomPointB=  theAISPointB->Component();
1867     Handle(Geom_CartesianPoint ) myCartPointB= Handle(Geom_CartesianPoint)::DownCast (myGeomPointB);
1868     //    Handle(Geom_CartesianPoint ) myCartPointB= *(Handle(Geom_CartesianPoint)*)& (theAISPointB->Component() ) ;
1869
1870     if (myCartPointB->X()==myCartPointA->X() && myCartPointB->Y()==myCartPointA->Y() && myCartPointB->Z()==myCartPointA->Z() ) {
1871       // B=A
1872       di<<"vline error: same points\n";return 1;
1873     }
1874     // Les deux points sont OK...Construction de l'AIS_Line (en faite, le segment AB)
1875     Handle(AIS_Line) theAISLine= new AIS_Line(myCartPointA,myCartPointB );
1876     GetMapOfAIS().Bind(theAISLine,argv[1] );
1877     TheAISContext()->Display (theAISLine, Standard_True);
1878
1879   }
1880
1881   // Parametres 6 Reals
1882   // ==================
1883
1884   else if (argc==8) {
1885     // On verifie que les deux points ne sont pas confondus
1886
1887     Standard_Real coord[6];
1888     for(Standard_Integer i=0;i<=2;i++){
1889       coord[i]=Draw::Atof(argv[2+i]);
1890       coord[i+3]=Draw::Atof(argv[5+i]);
1891     }
1892
1893     Handle(Geom_CartesianPoint ) myCartPointA=new Geom_CartesianPoint (coord[0],coord[1],coord[2] );
1894     Handle(Geom_CartesianPoint ) myCartPointB=new Geom_CartesianPoint (coord[3],coord[4],coord[5] );
1895
1896     Handle(AIS_Line) theAISLine= new AIS_Line(myCartPointA,myCartPointB );
1897     GetMapOfAIS().Bind(theAISLine,argv[1] );
1898     TheAISContext()->Display (theAISLine, Standard_True);
1899
1900   }
1901
1902   // Pas de parametres: Selection dans le viewer.
1903   // ============================================
1904
1905   else
1906   {
1907     TopTools_ListOfShape aShapes;
1908     ViewerTest::GetSelectedShapes (aShapes);
1909     if (aShapes.Extent() != 2)
1910     {
1911       Message::SendFail ("Error: wrong number of selected shapes.");
1912       return 1;
1913     }
1914
1915     const TopoDS_Shape& aShapeA = aShapes.First();
1916     const TopoDS_Shape& aShapeB = aShapes.Last();
1917
1918     if (!(aShapeA.ShapeType() == TopAbs_VERTEX
1919        && aShapeB.ShapeType() == TopAbs_VERTEX))
1920     {
1921       Message::SendFail ("Error: you should select two different vertex.");
1922       return 1;
1923     }
1924
1925     // Construction de la line
1926     gp_Pnt A = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
1927     gp_Pnt B = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
1928
1929     Handle(Geom_CartesianPoint ) myCartPointA=new Geom_CartesianPoint(A);
1930     Handle(Geom_CartesianPoint ) myCartPointB=new Geom_CartesianPoint(B);
1931
1932     Handle(AIS_Line) theAISLine= new AIS_Line(myCartPointA,myCartPointB );
1933     GetMapOfAIS().Bind(theAISLine,argv[1] );
1934     TheAISContext()->Display (theAISLine, Standard_True);
1935   }
1936
1937   return 0;
1938 }
1939
1940 //==============================================================================
1941 // class   : FilledCircle
1942 // purpose : creates filled circle based on AIS_InteractiveObject 
1943 //           and Geom_Circle.
1944 //           This class is used to check method Matches() of class 
1945 //           Select3D_SensitiveCircle with member myFillStatus = Standard_True, 
1946 //           because none of AIS classes provides creation of 
1947 //           Select3D_SensitiveCircle with member myFillStatus = Standard_True 
1948 //           (look method ComputeSelection() )
1949 //============================================================================== 
1950
1951 Handle(Geom_Circle) CreateCircle(gp_Pnt theCenter, Standard_Real theRadius) 
1952 {
1953   gp_Ax2 anAxes(theCenter, gp_Dir(gp_Vec(0., 0., 1.))); 
1954   gp_Circ aCirc(anAxes, theRadius);
1955   Handle(Geom_Circle) aCircle = new Geom_Circle(aCirc);
1956   return aCircle;
1957 }
1958
1959 class FilledCircle : public AIS_InteractiveObject 
1960 {
1961 public:
1962     // CASCADE RTTI
1963     DEFINE_STANDARD_RTTI_INLINE(FilledCircle,AIS_InteractiveObject); 
1964
1965     FilledCircle(gp_Pnt theCenter, Standard_Real theRadius);
1966     FilledCircle(Handle(Geom_Circle) theCircle);
1967
1968 private:
1969     TopoDS_Face ComputeFace();
1970
1971     // Virtual methods implementation
1972     void Compute (  const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
1973                   const Handle(Prs3d_Presentation)& thePresentation,
1974                   const Standard_Integer theMode) Standard_OVERRIDE;
1975
1976     void ComputeSelection (  const Handle(SelectMgr_Selection)& theSelection, 
1977                            const Standard_Integer theMode) Standard_OVERRIDE;
1978
1979 protected:
1980     Handle(Geom_Circle) myCircle;
1981     Standard_Boolean myFilledStatus;
1982
1983 }; 
1984
1985
1986 FilledCircle::FilledCircle(gp_Pnt theCenter, Standard_Real theRadius) 
1987 {
1988   myCircle = CreateCircle(theCenter, theRadius);
1989   myFilledStatus = Standard_True;
1990 }
1991
1992 FilledCircle::FilledCircle(Handle(Geom_Circle) theCircle) 
1993 {
1994   myCircle = theCircle;
1995   myFilledStatus = Standard_True;
1996 }
1997
1998 TopoDS_Face FilledCircle::ComputeFace() 
1999 {
2000   // Create edge from myCircle 
2001   BRepBuilderAPI_MakeEdge anEdgeMaker(myCircle->Circ());
2002   TopoDS_Edge anEdge = anEdgeMaker.Edge(); 
2003
2004   // Create wire from anEdge 
2005   BRepBuilderAPI_MakeWire aWireMaker(anEdge);
2006   TopoDS_Wire aWire = aWireMaker.Wire();
2007
2008   // Create face from aWire
2009   BRepBuilderAPI_MakeFace aFaceMaker(aWire);
2010   TopoDS_Face aFace = aFaceMaker.Face();
2011
2012   return aFace;
2013 }
2014
2015 void FilledCircle::Compute(const Handle(PrsMgr_PresentationManager3d) &/*thePresentationManager*/, 
2016                            const Handle(Prs3d_Presentation) &thePresentation, 
2017                            const Standard_Integer theMode) 
2018 {
2019   thePresentation->Clear();
2020
2021   TopoDS_Face aFace = ComputeFace();
2022
2023   if (aFace.IsNull()) return;
2024   if (theMode != 0) return;
2025
2026   StdPrs_ShadedShape::Add(thePresentation, aFace, myDrawer);
2027 }
2028
2029 void FilledCircle::ComputeSelection(const Handle(SelectMgr_Selection) &theSelection, 
2030                                     const Standard_Integer /*theMode*/)
2031 {
2032   Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
2033   Handle(Select3D_SensitiveCircle) aSensitiveCircle = new Select3D_SensitiveCircle (anEntityOwner, myCircle->Circ(), myFilledStatus);
2034   theSelection->Add(aSensitiveCircle);
2035 }
2036
2037 //==============================================================================
2038 // Fonction  vcircle
2039 // -----------------  Uniquement par parametre. Pas de selection dans le viewer.
2040 //==============================================================================
2041
2042 //==============================================================================
2043 //function : VCircleBuilder
2044 //purpose  : Build an AIS_Circle
2045 //Draw arg : vcircle CircleName PlaneName PointName Radius IsFilled
2046 //                              PointName PointName PointName IsFilled
2047 //==============================================================================
2048
2049 void DisplayCircle (Handle (Geom_Circle) theGeomCircle,
2050                     TCollection_AsciiString theName, 
2051                     Standard_Boolean isFilled) 
2052 {
2053   Handle(AIS_InteractiveObject) aCircle;
2054   if (isFilled) 
2055   {
2056     aCircle = new FilledCircle(theGeomCircle);
2057   }
2058   else
2059   {
2060     aCircle = new AIS_Circle(theGeomCircle);
2061     Handle(AIS_Circle)::DownCast (aCircle)->SetFilledCircleSens (Standard_False);
2062   }
2063
2064   // Check if there is an object with given name
2065   // and remove it from context
2066   if (GetMapOfAIS().IsBound2(theName)) 
2067   {
2068     Handle(AIS_InteractiveObject) anInterObj = GetMapOfAIS().Find2(theName);
2069     TheAISContext()->Remove(anInterObj, Standard_False);
2070     GetMapOfAIS().UnBind2(theName);
2071    }
2072
2073    // Bind the circle to its name
2074    GetMapOfAIS().Bind(aCircle, theName);
2075
2076    // Display the circle
2077    TheAISContext()->Display (aCircle, Standard_True);
2078   
2079 }
2080
2081 static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
2082 {
2083   // Verification of the arguments
2084   if (argc>6 || argc<2) 
2085   { 
2086     Message::SendFail ("Syntax error: wrong number of arguments");
2087     return 1;
2088   }
2089
2090   // There are all arguments
2091   if (argc == 6) 
2092   {
2093     // Get arguments
2094     TCollection_AsciiString aName(argv[1]);
2095     Standard_Boolean isFilled = Draw::Atoi(argv[5]) != 0;
2096
2097     Handle(AIS_InteractiveObject) theShapeA, theShapeB;
2098     GetMapOfAIS().Find2 (argv[2], theShapeA);
2099     GetMapOfAIS().Find2 (argv[3], theShapeB);
2100
2101     // Arguments: AIS_Point AIS_Point AIS_Point
2102     // ========================================
2103     if (!theShapeA.IsNull() && !theShapeB.IsNull() &&
2104       theShapeA->Type()==AIS_KOI_Datum && theShapeA->Signature()==1)
2105     {
2106       if (theShapeB->Type()!=AIS_KOI_Datum || theShapeB->Signature()!=1 ) 
2107       {
2108         Message::SendFail ("Error: 2d argument is unexpected to be a point");
2109         return 1;
2110       }
2111       // The third object must be a point
2112       Handle(AIS_InteractiveObject) theShapeC;
2113       GetMapOfAIS().Find2 (argv[4], theShapeC);
2114       if (theShapeC.IsNull() ||
2115         theShapeC->Type()!=AIS_KOI_Datum || theShapeC->Signature()!=1 ) 
2116       {
2117         Message::SendFail ("Error: 3d argument is unexpected to be a point");
2118         return 1;
2119       }
2120         // tag
2121         // Verify that the three points are different
2122         Handle(AIS_Point) theAISPointA = Handle(AIS_Point)::DownCast(theShapeA);
2123         Handle(AIS_Point) theAISPointB = Handle(AIS_Point)::DownCast(theShapeB);
2124         Handle(AIS_Point) theAISPointC = Handle(AIS_Point)::DownCast(theShapeC);
2125         
2126         Handle(Geom_Point) myGeomPointA = theAISPointA->Component();
2127         Handle(Geom_CartesianPoint) myCartPointA = 
2128           Handle(Geom_CartesianPoint)::DownCast(myGeomPointA);
2129
2130         Handle(Geom_Point) myGeomPointB = theAISPointB->Component();
2131         Handle(Geom_CartesianPoint) myCartPointB =
2132           Handle(Geom_CartesianPoint)::DownCast(myGeomPointB);
2133
2134         Handle(Geom_Point) myGeomPointC = theAISPointC->Component();
2135         Handle(Geom_CartesianPoint) myCartPointC =
2136           Handle(Geom_CartesianPoint)::DownCast(myGeomPointC);
2137
2138         // Test A=B
2139         if (Abs(myCartPointA->X()-myCartPointB->X()) <= Precision::Confusion() && 
2140             Abs(myCartPointA->Y()-myCartPointB->Y()) <= Precision::Confusion() && 
2141             Abs(myCartPointA->Z()-myCartPointB->Z()) <= Precision::Confusion() ) 
2142         {
2143           Message::SendFail ("Error: Same points");
2144           return 1;
2145         }
2146         // Test A=C
2147         if (Abs(myCartPointA->X()-myCartPointC->X()) <= Precision::Confusion() &&
2148             Abs(myCartPointA->Y()-myCartPointC->Y()) <= Precision::Confusion() && 
2149             Abs(myCartPointA->Z()-myCartPointC->Z()) <= Precision::Confusion() ) 
2150         {
2151           Message::SendFail ("Error: Same points");
2152           return 1;
2153         }
2154         // Test B=C
2155         if (Abs(myCartPointB->X()-myCartPointC->X()) <= Precision::Confusion() && 
2156             Abs(myCartPointB->Y()-myCartPointC->Y()) <= Precision::Confusion() && 
2157             Abs(myCartPointB->Z()-myCartPointC->Z()) <= Precision::Confusion() ) 
2158         {
2159           Message::SendFail ("Error: Same points");
2160           return 1;
2161         }
2162         // Construction of the circle
2163         GC_MakeCircle Cir = GC_MakeCircle (myCartPointA->Pnt(), 
2164           myCartPointB->Pnt(), myCartPointC->Pnt() );
2165         Handle (Geom_Circle) theGeomCircle;
2166         try 
2167         {
2168           theGeomCircle = Cir.Value();
2169         }
2170         catch (StdFail_NotDone const&)
2171         {
2172           Message::SendFail ("Error: can't create circle");
2173           return -1;
2174         }
2175
2176         DisplayCircle(theGeomCircle, aName, isFilled);
2177     }
2178
2179     // Arguments: AIS_Plane AIS_Point Real
2180     // ===================================
2181     else if (theShapeA->Type() == AIS_KOI_Datum && 
2182       theShapeA->Signature() == 7 ) 
2183     {
2184       if (theShapeB->Type() != AIS_KOI_Datum || 
2185         theShapeB->Signature() != 1 ) 
2186       {
2187         Message::SendFail ("Error: 2d element is a unexpected to be a point");
2188         return 1;
2189       }
2190       // Check that the radius is >= 0
2191       if (Draw::Atof(argv[4]) <= 0 ) 
2192       {
2193         Message::SendFail ("Syntax error: the radius must be >=0");
2194         return 1;
2195       }
2196
2197       // Recover the normal to the plane
2198       Handle(AIS_Plane) theAISPlane = Handle(AIS_Plane)::DownCast(theShapeA);
2199       Handle(AIS_Point) theAISPointB = Handle(AIS_Point)::DownCast(theShapeB); 
2200
2201       Handle(Geom_Plane) myGeomPlane = theAISPlane->Component();
2202       Handle(Geom_Point) myGeomPointB = theAISPointB->Component();
2203       Handle(Geom_CartesianPoint) myCartPointB = 
2204         Handle(Geom_CartesianPoint)::DownCast(myGeomPointB);
2205
2206       gp_Pln mygpPlane = myGeomPlane->Pln();
2207       gp_Ax1 thegpAxe = mygpPlane.Axis();
2208       gp_Dir theDir = thegpAxe.Direction();
2209       gp_Pnt theCenter = myCartPointB->Pnt();
2210       Standard_Real TheR = Draw::Atof(argv[4]);
2211       GC_MakeCircle Cir = GC_MakeCircle (theCenter, theDir ,TheR);
2212       Handle (Geom_Circle) theGeomCircle;
2213       try 
2214       {
2215         theGeomCircle = Cir.Value();
2216       }
2217       catch (StdFail_NotDone const&)
2218       {
2219         Message::SendFail ("Error: can't create circle");
2220         return -1;
2221       }
2222
2223       DisplayCircle(theGeomCircle, aName, isFilled);
2224
2225     }
2226
2227     // Error
2228     else
2229     {
2230       Message::SendFail ("Error: 1st argument has an unexpected type");
2231       return 1;
2232     }
2233
2234   }
2235   // No arguments: selection in the viewer
2236   // =========================================
2237   else 
2238   {
2239     // Get the name of the circle 
2240     TCollection_AsciiString aName(argv[1]);
2241
2242     TopTools_ListOfShape aShapes;
2243     ViewerTest::GetSelectedShapes (aShapes);
2244     if (aShapes.Extent() != 3 && aShapes.Extent() != 2)
2245     {
2246       Message::SendFail ("Error: Wrong number of selected shapes.");
2247       return 1;
2248     }
2249
2250     const TopoDS_Shape& aShapeA = aShapes.First();
2251     if (aShapeA.ShapeType() == TopAbs_VERTEX ) 
2252     {
2253       if (aShapes.Extent() != 3)
2254       {
2255         Message::SendFail ("Error: wrong number of selected shapes.");
2256         return 1;
2257       }
2258
2259       TopTools_ListOfShape::Iterator anIter (aShapes);
2260
2261       anIter.Next();
2262       const TopoDS_Shape& aShapeB = anIter.Value();
2263
2264       anIter.Next();
2265       const TopoDS_Shape& aShapeC = anIter.Value();
2266       
2267       // Get isFilled
2268       Standard_Boolean isFilled;
2269       std::cout << "Enter filled status (0 or 1)\n";
2270       std::cin >> isFilled;
2271
2272       // Construction of the circle
2273       gp_Pnt A = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
2274       gp_Pnt B = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
2275       gp_Pnt C = BRep_Tool::Pnt (TopoDS::Vertex (aShapeC));
2276
2277       GC_MakeCircle Cir = GC_MakeCircle (A, B, C);
2278       Handle (Geom_Circle) theGeomCircle;
2279       try 
2280       {
2281         theGeomCircle = Cir.Value();
2282       }
2283       catch (StdFail_NotDone const&)
2284       {
2285         Message::SendFail ("Error: can't create circle");
2286         return -1;
2287       }
2288
2289       DisplayCircle(theGeomCircle, aName, isFilled);
2290
2291     }
2292     else if (aShapeA.ShapeType() == TopAbs_FACE)
2293     {
2294       const TopoDS_Shape& aShapeB = aShapes.Last();
2295
2296       // Recover the radius 
2297       Standard_Real theRad;
2298       do 
2299       {
2300         std::cout << " Enter the value of the radius:\n";
2301         std::cin >> theRad;
2302       } while (theRad <= 0);
2303       
2304       // Get filled status
2305       Standard_Boolean isFilled;
2306       std::cout << "Enter filled status (0 or 1)\n";
2307       std::cin >> isFilled;
2308
2309       // Recover the normal to the plane. tag
2310       TopoDS_Face myFace = TopoDS::Face(aShapeA);
2311       BRepAdaptor_Surface mySurface (myFace, Standard_False);
2312       gp_Pln myPlane = mySurface.Plane();
2313       Handle(Geom_Plane) theGeomPlane = new Geom_Plane (myPlane);
2314       gp_Pln mygpPlane = theGeomPlane->Pln();
2315       gp_Ax1 thegpAxe = mygpPlane.Axis();
2316       gp_Dir theDir = thegpAxe.Direction();
2317
2318       // Recover the center
2319       gp_Pnt theCenter = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
2320
2321       // Construct the circle
2322       GC_MakeCircle Cir = GC_MakeCircle (theCenter, theDir ,theRad);
2323       Handle (Geom_Circle) theGeomCircle;
2324       try 
2325       {
2326         theGeomCircle = Cir.Value();
2327       }
2328       catch (StdFail_NotDone const&)
2329       {
2330         Message::SendFail ("Error: can't create circle");
2331         return -1;
2332       }
2333
2334       DisplayCircle(theGeomCircle, aName, isFilled);
2335     }
2336     else
2337     {
2338       Message::SendFail ("Error: You should select face and vertex or three vertices.");
2339       return 1;
2340     }
2341   }
2342
2343   return 0;
2344 }
2345
2346 //=======================================================================
2347 //function : VDrawText
2348 //purpose  :
2349 //=======================================================================
2350 static int VDrawText (Draw_Interpretor& theDI,
2351                       Standard_Integer  theArgsNb,
2352                       const char**      theArgVec)
2353 {
2354   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
2355   if (theArgsNb < 3)
2356   {
2357     Message::SendFail ("Syntax error: wrong number of arguments. See usage:");
2358     theDI.PrintHelp (theArgVec[0]);
2359     return 1;
2360   }
2361   else if (aContext.IsNull())
2362   {
2363     Message::SendFail ("Error: no active viewer");
2364     return 1;
2365   }
2366
2367   Standard_Integer           anArgIt = 1;
2368   TCollection_ExtendedString aName (theArgVec[anArgIt++], Standard_True);
2369   TCollection_ExtendedString aText (theArgVec[anArgIt++], Standard_True);
2370   Handle(AIS_TextLabel)      aTextPrs;
2371   ViewerTest_AutoUpdater     anAutoUpdater (aContext, ViewerTest::CurrentView());
2372
2373   Standard_Boolean isNewPrs = Standard_False;
2374   if (GetMapOfAIS().IsBound2 (aName))
2375   {
2376     aTextPrs = Handle(AIS_TextLabel)::DownCast (GetMapOfAIS().Find2 (aName));
2377   }
2378
2379   if (aTextPrs.IsNull())
2380   {
2381     isNewPrs = Standard_True;
2382     aTextPrs = new AIS_TextLabel();
2383     aTextPrs->SetFont ("Courier");
2384   }
2385
2386   aTextPrs->SetText (aText);
2387
2388   Handle(Graphic3d_TransformPers) aTrsfPers;
2389   Aspect_TypeOfDisplayText aDisplayType = Aspect_TODT_NORMAL;
2390
2391   Standard_Boolean aHasPlane = Standard_False;
2392   gp_Dir           aNormal;
2393   gp_Dir           aDirection;
2394   gp_Pnt           aPos;
2395
2396
2397   Handle(Font_TextFormatter) aTextFormatter;
2398   for (; anArgIt < theArgsNb; ++anArgIt)
2399   {
2400     TCollection_AsciiString aParam (theArgVec[anArgIt]);
2401     aParam.LowerCase();
2402
2403     if (anAutoUpdater.parseRedrawMode (aParam))
2404     {
2405       continue;
2406     }
2407     else if (aParam == "-pos"
2408           || aParam == "-position")
2409     {
2410       if (anArgIt + 3 >= theArgsNb)
2411       {
2412         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
2413         return 1;
2414       }
2415
2416       aPos.SetX (Draw::Atof (theArgVec[++anArgIt]));
2417       aPos.SetY (Draw::Atof (theArgVec[++anArgIt]));
2418       aPos.SetZ (Draw::Atof (theArgVec[++anArgIt]));
2419       aTextPrs->SetPosition (aPos);
2420     }
2421     else if (aParam == "-color")
2422     {
2423       Quantity_Color aColor;
2424       Standard_Integer aNbParsed = Draw::ParseColor (theArgsNb - anArgIt - 1,
2425                                                      theArgVec + anArgIt + 1,
2426                                                      aColor);
2427       if (aNbParsed == 0)
2428       {
2429         Message::SendFail() << "Syntax error at '" << aParam << "'";
2430         return 1;
2431       }
2432       anArgIt += aNbParsed;
2433       aTextPrs->SetColor (aColor);
2434     }
2435     else if (aParam == "-halign")
2436     {
2437       if (++anArgIt >= theArgsNb)
2438       {
2439         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam.ToCString() << "'";
2440         return 1;
2441       }
2442
2443       TCollection_AsciiString aType (theArgVec[anArgIt]);
2444       aType.LowerCase();
2445       if (aType == "left")
2446       {
2447         aTextPrs->SetHJustification (Graphic3d_HTA_LEFT);
2448       }
2449       else if (aType == "center")
2450       {
2451         aTextPrs->SetHJustification (Graphic3d_HTA_CENTER);
2452       }
2453       else if (aType == "right")
2454       {
2455         aTextPrs->SetHJustification (Graphic3d_HTA_RIGHT);
2456       }
2457       else
2458       {
2459         Message::SendFail() << "Syntax error at '" << aParam << "'";
2460         return 1;
2461       }
2462     }
2463     else if (aParam == "-valign")
2464     {
2465       if (++anArgIt >= theArgsNb)
2466       {
2467         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2468         return 1;
2469       }
2470
2471       TCollection_AsciiString aType (theArgVec[anArgIt]);
2472       aType.LowerCase();
2473       if (aType == "top")
2474       {
2475         aTextPrs->SetVJustification (Graphic3d_VTA_TOP);
2476       }
2477       else if (aType == "center")
2478       {
2479         aTextPrs->SetVJustification (Graphic3d_VTA_CENTER);
2480       }
2481       else if (aType == "bottom")
2482       {
2483         aTextPrs->SetVJustification (Graphic3d_VTA_BOTTOM);
2484       }
2485       else if (aType == "topfirstline")
2486       {
2487         aTextPrs->SetVJustification (Graphic3d_VTA_TOPFIRSTLINE);
2488       }
2489       else
2490       {
2491         Message::SendFail() << "Syntax error at '" << aParam << "'";
2492         return 1;
2493       }
2494     }
2495     else if (aParam == "-angle")
2496     {
2497       if (++anArgIt >= theArgsNb)
2498       {
2499         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2500         return 1;
2501       }
2502
2503       aTextPrs->SetAngle (Draw::Atof (theArgVec[anArgIt]) * (M_PI / 180.0));
2504     }
2505     else if (aParam == "-zoom")
2506     {
2507       if (++anArgIt >= theArgsNb)
2508       {
2509         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2510         return 1;
2511       }
2512
2513       aTextPrs->SetZoomable (Draw::Atoi (theArgVec[anArgIt]) == 1);
2514     }
2515     else if (aParam == "-height")
2516     {
2517       if (++anArgIt >= theArgsNb)
2518       {
2519         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2520         return 1;
2521       }
2522
2523       aTextPrs->SetHeight (Draw::Atof(theArgVec[anArgIt]));
2524     }
2525     else if (aParam == "-wrapping")
2526     {
2527       if (++anArgIt >= theArgsNb)
2528       {
2529         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2530         return 1;
2531       }
2532
2533       if (aTextFormatter.IsNull())
2534       {
2535         aTextFormatter = new Font_TextFormatter();
2536       }
2537       aTextFormatter->SetWrapping ((Standard_ShortReal)Draw::Atof(theArgVec[anArgIt]));
2538     }
2539     else if (aParam == "-aspect")
2540     {
2541       if (++anArgIt >= theArgsNb)
2542       {
2543         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2544         return 1;
2545       }
2546
2547       TCollection_AsciiString anOption (theArgVec[anArgIt]);
2548       anOption.LowerCase();
2549       Font_FontAspect aFontAspect = Font_FA_Undefined;
2550       if (!parseFontStyle (anOption, aFontAspect))
2551       {
2552         Message::SendFail() << "Syntax error: unknown font aspect '" << anOption << "'";
2553         return 1;
2554       }
2555       aTextPrs->SetFontAspect (aFontAspect);
2556     }
2557     else if (aParam == "-font")
2558     {
2559       if (++anArgIt >= theArgsNb)
2560       {
2561         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2562         return 1;
2563       }
2564
2565       aTextPrs->SetFont (theArgVec[anArgIt]);
2566     }
2567     else if (aParam == "-plane")
2568     {
2569       if (anArgIt + 6 >= theArgsNb)
2570       {
2571         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2572         return 1;
2573       }
2574
2575       Standard_Real aX = Draw::Atof (theArgVec[++anArgIt]);
2576       Standard_Real aY = Draw::Atof (theArgVec[++anArgIt]);
2577       Standard_Real aZ = Draw::Atof (theArgVec[++anArgIt]);
2578       aNormal.SetCoord (aX, aY, aZ);
2579
2580       aX = Draw::Atof (theArgVec[++anArgIt]);
2581       aY = Draw::Atof (theArgVec[++anArgIt]);
2582       aZ = Draw::Atof (theArgVec[++anArgIt]);
2583       aDirection.SetCoord (aX, aY, aZ);
2584
2585       aHasPlane = Standard_True;
2586     }
2587     else if (aParam == "-flipping")
2588     {
2589       aTextPrs->SetFlipping (Standard_True);
2590     }
2591     else if (aParam == "-ownanchor")
2592     {
2593       if (++anArgIt >= theArgsNb)
2594       {
2595         std::cout << "Error: wrong number of values for parameter '" << aParam.ToCString() << "'.\n";
2596         return 1;
2597       }
2598       aTextPrs->SetOwnAnchorPoint (Draw::Atoi (theArgVec[anArgIt]) == 1);
2599     }
2600     else if (aParam == "-disptype"
2601           || aParam == "-displaytype")
2602     {
2603       if (++anArgIt >= theArgsNb)
2604       {
2605         Message::SendFail() << "Syntax error: wrong number of values for parameter '" << aParam << "'";
2606         return 1;
2607       }
2608       TCollection_AsciiString aType (theArgVec[anArgIt]);
2609       aType.LowerCase();
2610       if (aType == "subtitle")
2611         aDisplayType = Aspect_TODT_SUBTITLE;
2612       else if (aType == "decal")
2613         aDisplayType = Aspect_TODT_DEKALE;
2614       else if (aType == "blend")
2615         aDisplayType = Aspect_TODT_BLEND;
2616       else if (aType == "dimension")
2617         aDisplayType = Aspect_TODT_DIMENSION;
2618       else if (aType == "normal")
2619         aDisplayType = Aspect_TODT_NORMAL;
2620       else if (aType == "shadow")
2621         aDisplayType = Aspect_TODT_SHADOW;
2622       else
2623       {
2624         Message::SendFail() << "Syntax error: wrong display type '" << aType << "'";
2625         return 1;
2626       }
2627     }
2628     else if (aParam == "-subcolor"
2629           || aParam == "-subtitlecolor")
2630     {
2631       Quantity_Color aColor;
2632       Standard_Integer aNbParsed = Draw::ParseColor (theArgsNb - anArgIt - 1,
2633                                                      theArgVec + anArgIt + 1,
2634                                                      aColor);
2635       if (aNbParsed == 0)
2636       {
2637         Message::SendFail() << "Syntax error at '" << aParam << "'";
2638         return 1;
2639       }
2640       anArgIt += aNbParsed;
2641       aTextPrs->SetColorSubTitle (aColor);
2642     }
2643     else if (aParam == "-2d")
2644     {
2645       aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_2d);
2646     }
2647     else if (aParam == "-trsfperspos"
2648           || aParam == "-perspos")
2649     {
2650       if (anArgIt + 2 >= theArgsNb)
2651       {
2652         Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'.";
2653         return 1;
2654       }
2655
2656       TCollection_AsciiString aX (theArgVec[++anArgIt]);
2657       TCollection_AsciiString aY (theArgVec[++anArgIt]);
2658       TCollection_AsciiString aZ = "0";
2659       if (!aX.IsIntegerValue()
2660        || !aY.IsIntegerValue())
2661       {
2662         Message::SendFail() << "Error: wrong syntax at '" << aParam << "'.";
2663         return 1;
2664       }
2665       if (anArgIt + 1 < theArgsNb)
2666       {
2667         TCollection_AsciiString aTemp = theArgVec[anArgIt + 1];
2668         if (aTemp.IsIntegerValue())
2669         {
2670           aZ = aTemp;
2671           ++anArgIt;
2672         }
2673       }
2674
2675       aTrsfPers = Graphic3d_TransformPers::FromDeprecatedParams (Graphic3d_TMF_2d, gp_Pnt (aX.IntegerValue(), aY.IntegerValue(), aZ.IntegerValue()));
2676     }
2677     else
2678     {
2679       Message::SendFail() << "Syntax error: unknown argument '" << aParam << "'";
2680       return 1;
2681     }
2682   }
2683
2684   aTextPrs->SetTextFormatter (aTextFormatter);
2685
2686   if (aHasPlane)
2687   {
2688     aTextPrs->SetOrientation3D (gp_Ax2 (aPos, aNormal, aDirection));
2689   }
2690
2691   aTextPrs->SetDisplayType (aDisplayType);
2692
2693   if (!aTrsfPers.IsNull())
2694   {
2695     aContext->SetTransformPersistence (aTextPrs, aTrsfPers);
2696     aTextPrs->SetZLayer(Graphic3d_ZLayerId_TopOSD);
2697     if (aTextPrs->Position().Z() != 0)
2698     {
2699       aTextPrs->SetPosition (gp_Pnt(aTextPrs->Position().X(), aTextPrs->Position().Y(), 0));
2700     }
2701   }
2702   else if (!aTextPrs->TransformPersistence().IsNull())
2703   {
2704     aContext->SetTransformPersistence (aTextPrs, Handle(Graphic3d_TransformPers)());
2705   }
2706
2707   if (isNewPrs)
2708   {
2709     ViewerTest::Display (aName, aTextPrs, Standard_False);
2710   }
2711   else
2712   {
2713     aContext->Redisplay (aTextPrs, Standard_False, Standard_True);
2714   }
2715   return 0;
2716 }
2717
2718 #include <math.h>
2719 #include <gp_Pnt.hxx>
2720 #include <Graphic3d_ArrayOfPoints.hxx>
2721 #include <Graphic3d_ArrayOfPrimitives.hxx>
2722 #include <Graphic3d_ArrayOfTriangles.hxx>
2723 #include <Poly_Array1OfTriangle.hxx>
2724 #include <Poly_Triangle.hxx>
2725 #include <Poly_Triangulation.hxx>
2726 #include <TColgp_Array1OfPnt.hxx>
2727 #include <TShort_Array1OfShortReal.hxx>
2728 #include <TShort_HArray1OfShortReal.hxx>
2729
2730 #include <AIS_Triangulation.hxx>
2731 #include <StdPrs_ToolTriangulatedShape.hxx>
2732 #include <Poly_Connect.hxx>
2733 #include <TColgp_Array1OfDir.hxx>
2734 #include <Graphic3d_GraphicDriver.hxx>
2735
2736 #include <TColStd_Array1OfInteger.hxx>
2737 #include <TColStd_HArray1OfInteger.hxx>
2738 #include <Prs3d_ShadingAspect.hxx>
2739 #include <Graphic3d_MaterialAspect.hxx>
2740 #include <Graphic3d_AspectFillArea3d.hxx>
2741
2742 #include <BRepPrimAPI_MakeCylinder.hxx>
2743 #include <TopoDS_Shape.hxx>
2744 #include <TopExp_Explorer.hxx>
2745 #include <TopAbs.hxx>
2746 #include <AIS_InteractiveObject.hxx>
2747
2748
2749 //===============================================================================================
2750 //function : CalculationOfSphere
2751 //author   : psn
2752 //purpose  : Create a Sphere
2753 //===============================================================================================
2754
2755 Handle( Poly_Triangulation ) CalculationOfSphere( double X , double Y , double Z ,
2756                                                   int res ,
2757                                                   double Radius ){
2758   double mRadius = Radius;
2759   double mCenter[3] = {X,Y,Z};
2760   int mThetaResolution;
2761   int mPhiResolution;
2762   double mStartTheta = 0;//StartTheta;
2763   double mEndTheta = 360;//EndTheta;
2764   double mStartPhi = 0;//StartPhi;
2765   double mEndPhi = 180;//EndPhi;
2766   res = res < 4 ? 4 : res;
2767
2768   mThetaResolution = res;
2769   mPhiResolution = res;
2770
2771   int i, j;
2772   int jStart, jEnd, numOffset;
2773   double x[3], n[3], deltaPhi, deltaTheta, phi, theta, radius;
2774   double startTheta, endTheta, startPhi, endPhi;
2775   int base, numPoles=0, thetaResolution, phiResolution;
2776
2777   int pts[3];
2778   int piece = -1;
2779   int numPieces = 1;
2780   if ( numPieces > mThetaResolution ) {
2781     numPieces = mThetaResolution;
2782   }
2783
2784   int localThetaResolution =  mThetaResolution;
2785   double localStartTheta =  mStartTheta;
2786   double localEndTheta =  mEndTheta;
2787
2788   while ( localEndTheta < localStartTheta ) {
2789     localEndTheta += 360.0;
2790   }
2791
2792   deltaTheta = (localEndTheta - localStartTheta) / localThetaResolution;
2793
2794   // Change the ivars based on pieces.
2795   int start, end;
2796   start = piece * localThetaResolution / numPieces;
2797   end = (piece+1) * localThetaResolution / numPieces;
2798   localEndTheta = localStartTheta + (double)(end) * deltaTheta;
2799   localStartTheta = localStartTheta + (double)(start) * deltaTheta;
2800   localThetaResolution = end - start;
2801
2802   // Create north pole if needed
2803   int number_point = 0;
2804   int number_pointArray = 0;
2805
2806   if ( mStartPhi <= 0.0 ) {
2807     number_pointArray++;
2808     numPoles++;
2809   }
2810   if ( mEndPhi >= 180.0 ) {
2811     number_pointArray++;
2812     numPoles++;
2813   }
2814
2815   // Check data, determine increments, and convert to radians
2816   startTheta = (localStartTheta < localEndTheta ? localStartTheta : localEndTheta);
2817   startTheta *= M_PI  / 180.0;
2818   endTheta = (localEndTheta > localStartTheta ? localEndTheta : localStartTheta);
2819   endTheta *= M_PI  / 180.0;
2820
2821
2822   startPhi = ( mStartPhi <  mEndPhi ?  mStartPhi :  mEndPhi);
2823   startPhi *= M_PI  / 180.0;
2824   endPhi = ( mEndPhi >  mStartPhi ?  mEndPhi :  mStartPhi);
2825   endPhi *= M_PI  / 180.0;
2826
2827   phiResolution =  mPhiResolution - numPoles;
2828   deltaPhi = (endPhi - startPhi) / ( mPhiResolution - 1);
2829   thetaResolution = localThetaResolution;
2830   if ( fabs(localStartTheta - localEndTheta) < 360.0 ) {
2831     ++localThetaResolution;
2832   }
2833   deltaTheta = (endTheta - startTheta) / thetaResolution;
2834
2835   jStart = ( mStartPhi <= 0.0 ? 1 : 0);
2836   jEnd = ( mEndPhi >= 180.0 ?  mPhiResolution - 1 :  mPhiResolution);
2837
2838   // Create intermediate points
2839   for ( i = 0; i < localThetaResolution; i++ ) {
2840     for ( j = jStart; j < jEnd; j++ ) {
2841         number_pointArray++;
2842     }
2843   }
2844
2845   //Generate mesh connectivity
2846   base = phiResolution * localThetaResolution;
2847
2848   int number_triangle = 0 ;
2849   if ( mStartPhi <= 0.0 ) { // around north pole
2850     number_triangle += localThetaResolution;
2851   }
2852
2853   if ( mEndPhi >= 180.0 ) { // around south pole
2854     number_triangle += localThetaResolution;
2855   }
2856
2857   // bands in-between poles
2858   for ( i=0; i < localThetaResolution; i++){
2859     for ( j=0; j < (phiResolution-1); j++){
2860        number_triangle +=2;
2861     }
2862   }
2863
2864   Handle( Poly_Triangulation ) polyTriangulation = new Poly_Triangulation(number_pointArray, number_triangle, false);
2865   TColgp_Array1OfPnt& PointsOfArray = polyTriangulation->ChangeNodes();
2866   Poly_Array1OfTriangle& pArrayTriangle = polyTriangulation->ChangeTriangles();
2867
2868   if (  mStartPhi <= 0.0 ){
2869       x[0] =  mCenter[0];
2870       x[1] =  mCenter[1];
2871       x[2] =  mCenter[2] +  mRadius;
2872       PointsOfArray.SetValue(1,gp_Pnt(x[0],x[1],x[2]));
2873   }
2874
2875   // Create south pole if needed
2876   if (  mEndPhi >= 180.0 ){
2877       x[0] =  mCenter[0];
2878       x[1] =  mCenter[1];
2879       x[2] =  mCenter[2] -  mRadius;
2880       PointsOfArray.SetValue(2,gp_Pnt(x[0],x[1],x[2]));
2881   }
2882
2883   number_point = 3;
2884   for ( i=0; i < localThetaResolution; i++){
2885     theta = localStartTheta * M_PI / 180.0 + i*deltaTheta;
2886     for ( j = jStart; j < jEnd; j++){
2887         phi = startPhi + j*deltaPhi;
2888         radius =  mRadius * sin((double)phi);
2889         n[0] = radius * cos((double)theta);
2890         n[1] = radius * sin((double)theta);
2891         n[2] =  mRadius * cos((double)phi);
2892         x[0] = n[0] +  mCenter[0];
2893         x[1] = n[1] +  mCenter[1];
2894         x[2] = n[2] +  mCenter[2];
2895         PointsOfArray.SetValue(number_point,gp_Pnt(x[0],x[1],x[2]));
2896         number_point++;
2897       }
2898     }
2899
2900   numPoles = 3;
2901   number_triangle = 1;
2902   if ( mStartPhi <= 0.0 ){// around north pole
2903     for (i=0; i < localThetaResolution; i++){
2904         pts[0] = phiResolution*i + numPoles;
2905         pts[1] = (phiResolution*(i+1) % base) + numPoles;
2906         pts[2] = 1;
2907         pArrayTriangle.SetValue(number_triangle,Poly_Triangle(pts[0],pts[1],pts[2]));
2908         number_triangle++;
2909       }
2910     }
2911
2912   if (  mEndPhi >= 180.0 ){ // around south pole
2913     numOffset = phiResolution - 1 + numPoles;
2914     for (i=0; i < localThetaResolution; i++){
2915         pts[0] = phiResolution*i + numOffset;
2916         pts[2] = ((phiResolution*(i+1)) % base) + numOffset;
2917         pts[1] = numPoles - 1;
2918         pArrayTriangle.SetValue(number_triangle,Poly_Triangle(pts[0],pts[1],pts[2]));
2919         number_triangle++;
2920       }
2921     }
2922
2923   // bands in-between poles
2924
2925   for (i=0; i < localThetaResolution; i++){
2926     for (j=0; j < (phiResolution-1); j++){
2927         pts[0] = phiResolution*i + j + numPoles;
2928         pts[1] = pts[0] + 1;
2929         pts[2] = ((phiResolution*(i+1)+j) % base) + numPoles + 1;
2930         pArrayTriangle.SetValue(number_triangle,Poly_Triangle(pts[0],pts[1],pts[2]));
2931         number_triangle++;
2932         pts[1] = pts[2];
2933         pts[2] = pts[1] - 1;
2934         pArrayTriangle.SetValue(number_triangle,Poly_Triangle(pts[0],pts[1],pts[2]));
2935         number_triangle++;
2936       }
2937     }
2938
2939   Poly_Connect* pc = new Poly_Connect(polyTriangulation);
2940
2941   Handle(TShort_HArray1OfShortReal) Normals = new TShort_HArray1OfShortReal(1, polyTriangulation->NbNodes() * 3);
2942
2943   Standard_Integer index[3];
2944   Standard_Real Tol = Precision::Confusion();
2945
2946   gp_Dir Nor;
2947   for (i = PointsOfArray.Lower(); i <= PointsOfArray.Upper(); i++) {
2948       gp_XYZ eqPlan(0, 0, 0);
2949       for ( pc->Initialize(i); pc->More(); pc->Next()) {
2950         pArrayTriangle(pc->Value()).Get(index[0], index[1], index[2]);
2951         gp_XYZ v1(PointsOfArray(index[1]).Coord()-PointsOfArray(index[0]).Coord());
2952         gp_XYZ v2(PointsOfArray(index[2]).Coord()-PointsOfArray(index[1]).Coord());
2953         gp_XYZ vv = v1^v2;
2954         Standard_Real mod = vv.Modulus();
2955         if(mod < Tol) continue;
2956         eqPlan += vv/mod;
2957       }
2958
2959       Standard_Real modmax = eqPlan.Modulus();
2960
2961       if(modmax > Tol)
2962         Nor = gp_Dir(eqPlan);
2963       else
2964         Nor = gp_Dir(0., 0., 1.);
2965       
2966       Standard_Integer k = (i - PointsOfArray.Lower()) * 3;
2967       Normals->SetValue(k + 1, (Standard_ShortReal)Nor.X());
2968       Normals->SetValue(k + 2, (Standard_ShortReal)Nor.Y());
2969       Normals->SetValue(k + 3, (Standard_ShortReal)Nor.Z());
2970   }
2971
2972   delete pc;
2973   polyTriangulation->SetNormals(Normals);
2974
2975   return polyTriangulation;
2976 }
2977
2978 //===============================================================================================
2979 //function : VDrawSphere
2980 //author   : psn
2981 //purpose  : Create an AIS shape.
2982 //===============================================================================================
2983 static int VDrawSphere (Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
2984 {
2985   // check for errors
2986   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
2987   if (aContextAIS.IsNull())
2988   {
2989     Message::SendFail ("Error: no active viewer");
2990     return 1;
2991   }
2992   else if (argc < 3)
2993   {
2994     Message::SendFail() << "Syntax error: wrong number of arguments.\n"
2995                         << "Use: " << argv[0] << " shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToShowEdges=0]";
2996     return 1;
2997   }
2998
2999   // read the arguments
3000   TCollection_AsciiString aShapeName (argv[1]);
3001   Standard_Integer aResolution = Draw::Atoi (argv[2]);
3002   Standard_Real aCenterX = (argc > 5) ? Draw::Atof (argv[3]) : 0.0;
3003   Standard_Real aCenterY = (argc > 5) ? Draw::Atof (argv[4]) : 0.0;
3004   Standard_Real aCenterZ = (argc > 5) ? Draw::Atof (argv[5]) : 0.0;
3005   Standard_Real aRadius =  (argc > 6) ? Draw::Atof (argv[6]) : 100.0;
3006   Standard_Boolean toShowEdges = (argc > 7) ? Draw::Atoi (argv[7]) == 1 : Standard_False;
3007   Standard_Boolean toPrintInfo = (argc > 8) ? Draw::Atoi (argv[8]) == 1 : Standard_True;
3008
3009   // remove AIS object with given name from map
3010   VDisplayAISObject (aShapeName, Handle(AIS_InteractiveObject)());
3011
3012   if (toPrintInfo)
3013     std::cout << "Compute Triangulation...\n";
3014   Handle(AIS_Triangulation) aShape
3015     = new AIS_Triangulation (CalculationOfSphere (aCenterX, aCenterY, aCenterZ,
3016                                                   aResolution,
3017                                                   aRadius));
3018   Standard_Integer aNumberPoints    = aShape->GetTriangulation()->Nodes().Length();
3019   Standard_Integer aNumberTriangles = aShape->GetTriangulation()->Triangles().Length();
3020
3021   // stupid initialization of Green color in RGBA space as integer
3022   // probably wrong for big-endian CPUs
3023   const Graphic3d_Vec4ub aColor (0, 255, 0, 0);
3024
3025   // setup colors array per vertex
3026   Handle(TColStd_HArray1OfInteger) aColorArray = new TColStd_HArray1OfInteger (1, aNumberPoints);
3027   for (Standard_Integer aNodeId = 1; aNodeId <= aNumberPoints; ++aNodeId)
3028   {
3029     aColorArray->SetValue (aNodeId, *reinterpret_cast<const Standard_Integer*> (aColor.GetData()));
3030   }
3031   aShape->SetColors (aColorArray);
3032
3033   // show statistics
3034   Standard_Integer aPointsSize      = aNumberPoints * 3 * sizeof(float);  // 3x GLfloat
3035   Standard_Integer aNormalsSize     = aNumberPoints * 3 * sizeof(float);  // 3x GLfloat
3036   Standard_Integer aColorsSize      = aNumberPoints * 3 * sizeof(float);  // 3x GLfloat without alpha
3037   Standard_Integer aTrianglesSize   = aNumberTriangles * 3 * sizeof(int); // 3x GLint
3038   Standard_Integer aPolyConnectSize = aNumberPoints * 4 + aNumberTriangles * 6 * 4;
3039   Standard_Integer aTotalSize       = aPointsSize + aNormalsSize + aColorsSize + aTrianglesSize;
3040   aTotalSize >>= 20; //MB
3041   aNormalsSize >>= 20;
3042   aColorsSize >>= 20;
3043   aTrianglesSize >>= 20;
3044   aPolyConnectSize >>= 20;
3045   if (toPrintInfo)
3046   {
3047     std::cout << "NumberOfPoints:    " << aNumberPoints << "\n"
3048       << "NumberOfTriangles: " << aNumberTriangles << "\n"
3049       << "Amount of memory required for PolyTriangulation without Normals: " << (aTotalSize - aNormalsSize) << " Mb\n"
3050       << "Amount of memory for colors: " << aColorsSize << " Mb\n"
3051       << "Amount of memory for PolyConnect: " << aPolyConnectSize << " Mb\n"
3052       << "Amount of graphic card memory required: " << aTotalSize << " Mb\n";
3053   }
3054
3055   // Setting material properties, very important for desirable visual result!
3056   Graphic3d_MaterialAspect aMat (Graphic3d_NOM_PLASTIC);
3057   aMat.SetAmbientColor (Quantity_Color (Graphic3d_Vec3 (0.04f)));
3058   aMat.SetSpecularColor(Quantity_Color (Graphic3d_Vec3 (0.50f)));
3059   Handle(Graphic3d_AspectFillArea3d) anAspect
3060     = new Graphic3d_AspectFillArea3d (Aspect_IS_SOLID,
3061                                       Quantity_NOC_RED,
3062                                       Quantity_NOC_YELLOW,
3063                                       Aspect_TOL_SOLID,
3064                                       1.0,
3065                                       aMat,
3066                                       aMat);
3067   Handle(Prs3d_ShadingAspect) aShAsp = new Prs3d_ShadingAspect();
3068   anAspect->SetDrawEdges (toShowEdges);
3069   aShAsp->SetAspect (anAspect);
3070   aShape->Attributes()->SetShadingAspect (aShAsp);
3071
3072   VDisplayAISObject (aShapeName, aShape);
3073   return 0;
3074 }
3075
3076 //=============================================================================
3077 //function : VComputeHLR
3078 //purpose  :
3079 //=============================================================================
3080
3081 static int VComputeHLR (Draw_Interpretor& ,
3082                         Standard_Integer theArgNb,
3083                         const char** theArgVec)
3084 {
3085   TCollection_AsciiString aShapeName, aHlrName;
3086   TopoDS_Shape aSh;
3087   gp_Pnt anEye;
3088   gp_Dir aDir;
3089   gp_Ax2 aProjAx;
3090   bool hasViewDirArg = false;
3091   Prs3d_TypeOfHLR anAlgoType = Prs3d_TOH_PolyAlgo;
3092   bool toShowCNEdges = false, toShowHiddenEdges = false;
3093   int aNbIsolines = 0;
3094   if (Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext())
3095   {
3096     gp_Dir aRight;
3097     Handle(V3d_View) aView = ViewerTest::CurrentView();
3098     Standard_Integer aWidth, aHeight;
3099     Standard_Real aCentX, aCentY, aCentZ, aDirX, aDirY, aDirZ;
3100     Standard_Real aRightX, aRightY, aRightZ;
3101     aView->Window()->Size (aWidth, aHeight);
3102
3103     aView->ConvertWithProj (aWidth, aHeight/2, 
3104                             aRightX, aRightY, aRightZ,
3105                             aDirX, aDirY, aDirZ);
3106     aView->ConvertWithProj (aWidth/2, aHeight/2, 
3107                             aCentX, aCentY, aCentZ,
3108                             aDirX, aDirY, aDirZ);
3109
3110     anEye.SetCoord (-aCentX, -aCentY, -aCentZ);
3111     aDir.SetCoord (-aDirX, -aDirY, -aDirZ);
3112     aRight.SetCoord (aRightX - aCentX, aRightY - aCentY, aRightZ - aCentZ);
3113     aProjAx.SetLocation (anEye);
3114     aProjAx.SetDirection (aDir);
3115     aProjAx.SetXDirection (aRight);
3116   }
3117   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3118   {
3119     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
3120     anArgCase.LowerCase();
3121     if (anArgIter + 1 < theArgNb
3122      && (anArgCase == "-algotype"
3123       || anArgCase == "-algo"
3124       || anArgCase == "-type"))
3125     {
3126       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
3127       anArgNext.LowerCase();
3128       if (anArgNext == "polyalgo")
3129       {
3130         anAlgoType = Prs3d_TOH_PolyAlgo;
3131       }
3132       else if (anArgNext == "algo")
3133       {
3134         anAlgoType = Prs3d_TOH_Algo;
3135       }
3136       else
3137       {
3138         Message::SendFail() << "Syntax error: unknown algo type '" << anArgNext << "'";
3139         return 1;
3140       }
3141     }
3142     else if (anArgCase == "-showhiddenedges"
3143           || anArgCase == "-hiddenedges"
3144           || anArgCase == "-hidden")
3145     {
3146       toShowHiddenEdges = true;
3147       if (anArgIter + 1 < theArgNb
3148        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toShowHiddenEdges))
3149       {
3150         ++anArgIter;
3151       }
3152     }
3153     else if (anArgCase == "-showtangentedges"
3154           || anArgCase == "-tangentedges"
3155           || anArgCase == "-tangent")
3156     {
3157       toShowCNEdges = true;
3158       if (anArgIter + 1 < theArgNb
3159        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toShowCNEdges))
3160       {
3161         ++anArgIter;
3162       }
3163     }
3164     else if (anArgIter + 1 < theArgNb
3165           && (anArgCase == "-nbiso"
3166            || anArgCase == "-nbisolines"))
3167     {
3168       aNbIsolines = Draw::Atoi (theArgVec[++anArgIter]);
3169     }
3170     else if (aSh.IsNull())
3171     {
3172       aSh = DBRep::Get (theArgVec[anArgIter]);
3173       aShapeName = theArgVec[anArgIter];
3174       if (aSh.IsNull())
3175       {
3176         BRep_Builder aBrepBuilder;
3177         BRepTools::Read (aSh, theArgVec[anArgIter], aBrepBuilder);
3178         if (aSh.IsNull())
3179         {
3180           Message::SendFail() << "Syntax error: no shape with name " << theArgVec[anArgIter] << " found";
3181           return 1;
3182         }
3183       }
3184     }
3185     else if (aHlrName.IsEmpty())
3186     {
3187       aHlrName = theArgVec[anArgIter];
3188     }
3189     else if (!hasViewDirArg
3190           && anArgIter + 8 < theArgNb)
3191     {
3192       hasViewDirArg = true;
3193       gp_Dir anUp;
3194       anEye.SetCoord (Draw::Atof (theArgVec[anArgIter + 0]), Draw::Atof (theArgVec[anArgIter + 1]), Draw::Atof (theArgVec[anArgIter + 2]));
3195       aDir .SetCoord (Draw::Atof (theArgVec[anArgIter + 3]), Draw::Atof (theArgVec[anArgIter + 4]), Draw::Atof (theArgVec[anArgIter + 5]));
3196       anUp .SetCoord (Draw::Atof (theArgVec[anArgIter + 6]), Draw::Atof (theArgVec[anArgIter + 7]), Draw::Atof (theArgVec[anArgIter + 8]));
3197       aProjAx.SetLocation (anEye);
3198       aProjAx.SetDirection (aDir);
3199       aProjAx.SetYDirection (anUp);
3200       anArgIter += 8;
3201     }
3202     else
3203     {
3204       Message::SendFail() << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
3205       return 1;
3206     }
3207   }
3208
3209   if (aHlrName.IsEmpty() || aSh.IsNull()
3210    || (ViewerTest::GetAISContext().IsNull() && hasViewDirArg))
3211   {
3212     Message::SendFail ("Syntax error: wrong number of arguments");
3213     return 1;
3214   }
3215
3216   HLRAlgo_Projector aProjector (aProjAx);
3217   TopoDS_Shape aVisible[6];
3218   TopoDS_Shape aHidden[6];
3219   if (anAlgoType == Prs3d_TOH_PolyAlgo)
3220   {
3221     Handle(HLRBRep_PolyAlgo) aPolyAlgo = new HLRBRep_PolyAlgo();
3222     aPolyAlgo->Projector (aProjector);
3223     aPolyAlgo->Load (aSh);
3224     aPolyAlgo->Update();
3225
3226     HLRBRep_PolyHLRToShape aHLRToShape;
3227     aHLRToShape.Update (aPolyAlgo);
3228
3229     aVisible[HLRBRep_Sharp]   = aHLRToShape.VCompound();
3230     aVisible[HLRBRep_OutLine] = aHLRToShape.OutLineVCompound(); // extract visible outlines
3231     aVisible[HLRBRep_Rg1Line] = aHLRToShape.Rg1LineVCompound();
3232     if (toShowCNEdges)
3233     {
3234       aVisible[HLRBRep_RgNLine] = aHLRToShape.RgNLineVCompound();
3235     }
3236     if (toShowHiddenEdges)
3237     {
3238       aHidden[HLRBRep_Sharp]   = aHLRToShape.HCompound();
3239       aHidden[HLRBRep_OutLine] = aHLRToShape.OutLineHCompound();
3240       aHidden[HLRBRep_Rg1Line] = aHLRToShape.Rg1LineHCompound();
3241       if (toShowCNEdges)
3242       {
3243         aHidden[HLRBRep_RgNLine] = aHLRToShape.RgNLineHCompound();
3244       }
3245     }
3246   }
3247   else
3248   {
3249     Handle(HLRBRep_Algo) aHlrAlgo = new HLRBRep_Algo();
3250     aHlrAlgo->Add (aSh, aNbIsolines);
3251     aHlrAlgo->Projector (aProjector);
3252     aHlrAlgo->Update();
3253     aHlrAlgo->Hide();
3254
3255     HLRBRep_HLRToShape aHLRToShape (aHlrAlgo);
3256     aVisible[HLRBRep_Sharp]   = aHLRToShape.VCompound();
3257     aVisible[HLRBRep_OutLine] = aHLRToShape.OutLineVCompound();
3258     aVisible[HLRBRep_Rg1Line] = aHLRToShape.Rg1LineVCompound();
3259     if (toShowCNEdges)
3260     {
3261       aVisible[HLRBRep_RgNLine] = aHLRToShape.RgNLineVCompound();
3262     }
3263     aVisible[HLRBRep_IsoLine] = aHLRToShape.IsoLineVCompound();
3264
3265     if (toShowHiddenEdges)
3266     {
3267       aHidden[HLRBRep_Sharp]   = aHLRToShape.HCompound();
3268       aHidden[HLRBRep_OutLine] = aHLRToShape.OutLineHCompound();
3269       aHidden[HLRBRep_Rg1Line] = aHLRToShape.Rg1LineHCompound();
3270       if (toShowCNEdges)
3271       {
3272         aHidden[HLRBRep_RgNLine] = aHLRToShape.RgNLineHCompound();
3273       }
3274       aHidden[HLRBRep_IsoLine] = aHLRToShape.IsoLineHCompound();
3275     }
3276     // extract 3d
3277     //aVisible[HLRBRep_Sharp]   = aHLRToShape.CompoundOfEdges (HLRBRep_Sharp, Standard_True, Standard_True);
3278     //aVisible[HLRBRep_OutLine] = aHLRToShape.OutLineVCompound3d();
3279   }
3280
3281   TopoDS_Compound aCompRes, aCompVis, aCompHid;
3282   BRep_Builder aBuilder;
3283   aBuilder.MakeCompound (aCompVis);
3284   aBuilder.MakeCompound (aCompHid);
3285   aBuilder.MakeCompound (aCompRes);
3286   for (int aTypeIter = 0; aTypeIter < 6; ++aTypeIter)
3287   {
3288     if (!aVisible[aTypeIter].IsNull())
3289     {
3290       aBuilder.Add (aCompVis, aVisible[aTypeIter]);
3291     }
3292     if (!aHidden[aTypeIter].IsNull())
3293     {
3294       aBuilder.Add (aCompHid, aHidden[aTypeIter]);
3295     }
3296   }
3297   aBuilder.Add (aCompRes, aCompVis);
3298   aBuilder.Add (aCompRes, aCompHid);
3299
3300   // create an AIS shape and display it
3301   if (!ViewerTest::GetAISContext().IsNull())
3302   {
3303     Handle(AIS_ColoredShape) anObject = new AIS_ColoredShape (aCompRes);
3304     if (toShowHiddenEdges)
3305     {
3306       Handle(Prs3d_LineAspect) aLineAspect = new Prs3d_LineAspect (Quantity_Color (Quantity_NOC_RED), Aspect_TOL_DASH, 1.0f);
3307       for (int aTypeIter = 0; aTypeIter < 6; ++aTypeIter)
3308       {
3309         if (!aHidden[aTypeIter].IsNull())
3310         {
3311           Handle(AIS_ColoredDrawer) aDrawer = anObject->CustomAspects (aHidden[aTypeIter]);
3312           aDrawer->SetLineAspect (aLineAspect);
3313           aDrawer->SetWireAspect (aLineAspect);
3314           aDrawer->SetFreeBoundaryAspect (aLineAspect);
3315           aDrawer->SetUnFreeBoundaryAspect (aLineAspect);
3316         }
3317       }
3318     }
3319     ViewerTest::Display (aHlrName, anObject, true);
3320   }
3321
3322   DBRep::Set (aHlrName.ToCString(), aCompRes);
3323   return 0;
3324 }
3325
3326 // This class is a wrap for Graphic3d_ArrayOfPrimitives; it is used for
3327 // manipulating and displaying such an array with AIS context
3328
3329 class MyPArrayObject : public AIS_InteractiveObject
3330 {
3331
3332 public:
3333
3334   MyPArrayObject (const Handle(Graphic3d_ArrayOfPrimitives)& thePArray) : myPArray (thePArray) {}
3335
3336   MyPArrayObject (Graphic3d_TypeOfPrimitiveArray thePrimType,
3337                   const Handle(TColStd_HArray1OfAsciiString)& theDesc,
3338                   const Handle(Graphic3d_AspectMarker3d)& theMarkerAspect)
3339   {
3340     Init (thePrimType, theDesc, theMarkerAspect, Standard_False);
3341   }
3342
3343   //! Initialize the array from specified description.
3344   Standard_Boolean Init (Graphic3d_TypeOfPrimitiveArray thePrimType,
3345                          const Handle(TColStd_HArray1OfAsciiString)& theDesc,
3346                          const Handle(Graphic3d_AspectMarker3d)& theMarkerAspect,
3347                          Standard_Boolean theToPatch);
3348
3349   DEFINE_STANDARD_RTTI_INLINE(MyPArrayObject,AIS_InteractiveObject);
3350
3351   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; }
3352
3353   //! Sets color to this interactive object
3354   //! @param theColor the color to be set
3355   virtual void SetColor (const Quantity_Color& theColor) Standard_OVERRIDE;
3356
3357 private:
3358
3359   void Compute (const Handle(PrsMgr_PresentationManager3d)& aPresentationManager,
3360                 const Handle(Prs3d_Presentation)& aPresentation,
3361                 const Standard_Integer aMode) Standard_OVERRIDE;
3362
3363   void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
3364                          const Standard_Integer /*theMode*/) Standard_OVERRIDE;
3365
3366   bool CheckInputCommand (const TCollection_AsciiString theCommand,
3367                           const Handle(TColStd_HArray1OfAsciiString)& theArgsArray,
3368                           Standard_Integer &theArgIndex,
3369                           Standard_Integer theArgCount,
3370                           Standard_Integer theMaxArgs);
3371
3372   //! Sets color for the shading aspect of the drawer used in this interactive object
3373   //! @param theColor the color to be set
3374   void setColorForShadingAspect(const Quantity_Color& theColor);
3375
3376   //! Replaces shading aspect from myDrawer->Link() with the own shading aspect of myDrawer for this interactive object
3377   void replaceShadingAspect();
3378
3379 protected:
3380
3381   Handle(Graphic3d_AspectMarker3d) myMarkerAspect;
3382   Handle(Graphic3d_ArrayOfPrimitives) myPArray;
3383
3384 };
3385
3386 void MyPArrayObject::Compute (const Handle(PrsMgr_PresentationManager3d)& /*aPresentationManager*/,
3387                               const Handle(Prs3d_Presentation)& thePrs,
3388                               const Standard_Integer theMode)
3389 {
3390   if (myPArray.IsNull() || theMode != 0)
3391   {
3392     return;
3393   }
3394
3395   Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
3396   if (!myMarkerAspect.IsNull())
3397   {
3398     aGroup->SetGroupPrimitivesAspect (myMarkerAspect);
3399   }
3400   else
3401   {
3402     aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
3403   }
3404   aGroup->AddPrimitiveArray (myPArray);
3405 }
3406
3407 Standard_Boolean MyPArrayObject::Init (Graphic3d_TypeOfPrimitiveArray thePrimType,
3408                                        const Handle(TColStd_HArray1OfAsciiString)& theDesc,
3409                                        const Handle(Graphic3d_AspectMarker3d)& theMarkerAspect,
3410                                        Standard_Boolean theToPatch)
3411 {
3412   myMarkerAspect = theMarkerAspect;
3413   if (!theToPatch)
3414   {
3415     myPArray.Nullify();
3416   }
3417
3418   // Parsing array description
3419   Standard_Integer aVertexNum = 0, aBoundNum = 0, aEdgeNum = 0;
3420   Graphic3d_ArrayFlags anArrayFlags = Graphic3d_ArrayFlags_None;
3421
3422   const Standard_Integer anArgsCount = theDesc->Length();
3423   TCollection_AsciiString aCommand;
3424   for (Standard_Integer anArgIndex = theDesc->Lower(); anArgIndex <= theDesc->Upper(); )
3425   {
3426     aCommand = theDesc->Value (anArgIndex);
3427     aCommand.LowerCase();
3428
3429     if (CheckInputCommand ("-deinterleaved", theDesc, anArgIndex, 0, anArgsCount))
3430     {
3431       anArrayFlags |= Graphic3d_ArrayFlags_AttribsDeinterleaved;
3432     }
3433     else if (CheckInputCommand ("-mutable", theDesc, anArgIndex, 0, anArgsCount))
3434     {
3435       anArrayFlags |= Graphic3d_ArrayFlags_AttribsMutable;
3436       anArrayFlags |= Graphic3d_ArrayFlags_IndexesMutable;
3437     }
3438     // vertex command
3439     else if (CheckInputCommand ("v", theDesc, anArgIndex, 3, anArgsCount))
3440     {
3441       // vertex has a normal or normal with color or texel
3442       if (CheckInputCommand ("n", theDesc, anArgIndex, 3, anArgsCount))
3443       {
3444         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_VertexNormal;
3445       }
3446
3447       // vertex has a color
3448       if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
3449       {
3450         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_VertexColor;
3451       }
3452
3453       // vertex has a texel
3454       if (CheckInputCommand ("t", theDesc, anArgIndex, 2, anArgsCount))
3455       {
3456         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_VertexTexel;
3457       }
3458
3459       aVertexNum++;
3460     }
3461     // bound command
3462     else if (CheckInputCommand ("b", theDesc, anArgIndex, 1, anArgsCount))
3463     {
3464       // bound has color
3465       if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
3466       {
3467         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_BoundColor;
3468       }
3469
3470       aBoundNum++;
3471     }
3472     // edge command
3473     else if (CheckInputCommand ("e", theDesc, anArgIndex, 1, anArgsCount))
3474     {
3475       aEdgeNum++;
3476     }
3477     // unknown command
3478     else
3479       anArgIndex++;
3480   }
3481
3482   if (myPArray.IsNull())
3483   {
3484     myPArray = Graphic3d_ArrayOfPrimitives::CreateArray (thePrimType, aVertexNum, aBoundNum, aEdgeNum, anArrayFlags);
3485   }
3486   else
3487   {
3488     if (myPArray->Type() != thePrimType
3489     ||  aVertexNum > myPArray->VertexNumberAllocated()
3490     ||  aEdgeNum   > myPArray->EdgeNumberAllocated()
3491     ||  aBoundNum  > myPArray->BoundNumberAllocated()
3492     || !myPArray->Attributes()->IsMutable()
3493     || (!myPArray->Indices().IsNull() && !myPArray->Indices()->IsMutable()))
3494     {
3495       Message::SendFail ("Syntax error: array cannot be patched");
3496       return Standard_False;
3497     }
3498
3499     myPArray->Attributes()->NbElements = aVertexNum;
3500     if (Handle(Graphic3d_AttribBuffer) anAttribs = Handle(Graphic3d_AttribBuffer)::DownCast (myPArray->Attributes()))
3501     {
3502       anAttribs->Invalidate (0, aVertexNum - 1);
3503     }
3504     if (!myPArray->Indices().IsNull())
3505     {
3506       myPArray->Indices()->NbElements = aEdgeNum;
3507     }
3508     if (!myPArray->Bounds().IsNull())
3509     {
3510       myPArray->Bounds()->NbBounds = aBoundNum;
3511     }
3512   }
3513
3514   Standard_Integer aVertIndex = 0;
3515   for (Standard_Integer anArgIndex = theDesc->Lower(); anArgIndex <= theDesc->Upper(); )
3516   {
3517     aCommand = theDesc->Value (anArgIndex);
3518     aCommand.LowerCase();
3519     if (!aCommand.IsAscii()
3520       || aCommand.IsEmpty())
3521     {
3522       break;
3523     }
3524
3525     // skip beautifiers (syntax is not actually validated)
3526     if (aCommand == "-deinterleaved"
3527      || aCommand == "-mutable"
3528      || aCommand.Value (1) == '('
3529      || aCommand.Value (1) == ')'
3530      || aCommand.Value (1) == ',')
3531     {
3532       ++anArgIndex;
3533     }
3534     // vertex command
3535     else if (CheckInputCommand ("v", theDesc, anArgIndex, 3, anArgsCount))
3536     {
3537       const Graphic3d_Vec3 aVert ((float )theDesc->Value (anArgIndex - 3).RealValue(),
3538                                   (float )theDesc->Value (anArgIndex - 2).RealValue(),
3539                                   (float )theDesc->Value (anArgIndex - 1).RealValue());
3540       if ((anArrayFlags & Graphic3d_ArrayFlags_AttribsDeinterleaved) != 0
3541        || (anArrayFlags & Graphic3d_ArrayFlags_AttribsMutable) != 0)
3542       {
3543         ++aVertIndex;
3544         myPArray->SetVertice (aVertIndex, aVert.x(), aVert.y(), aVert.z());
3545       }
3546       else
3547       {
3548         aVertIndex = myPArray->AddVertex (aVert);
3549       }
3550
3551       // vertex has a normal or normal with color or texel
3552       if (CheckInputCommand ("n", theDesc, anArgIndex, 3, anArgsCount))
3553       {
3554         const Graphic3d_Vec3 aNorm ((float )theDesc->Value (anArgIndex - 3).RealValue(),
3555                                     (float )theDesc->Value (anArgIndex - 2).RealValue(),
3556                                     (float )theDesc->Value (anArgIndex - 1).RealValue());
3557         myPArray->SetVertexNormal (aVertIndex, aNorm.x(), aNorm.y(), aNorm.z());
3558       }
3559       
3560       if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
3561       {
3562         const Graphic3d_Vec3d aCol (theDesc->Value (anArgIndex - 3).RealValue(),
3563                                     theDesc->Value (anArgIndex - 2).RealValue(),
3564                                     theDesc->Value (anArgIndex - 1).RealValue());
3565         myPArray->SetVertexColor (aVertIndex, aCol.r(), aCol.g(), aCol.b());
3566       }
3567       if (CheckInputCommand ("t", theDesc, anArgIndex, 2, anArgsCount))
3568       {
3569         const Graphic3d_Vec2 aTex ((float )theDesc->Value (anArgIndex - 2).RealValue(),
3570                                    (float )theDesc->Value (anArgIndex - 1).RealValue());
3571         myPArray->SetVertexTexel (aVertIndex, aTex.x(), aTex.y());
3572       }
3573     }
3574     // bounds command
3575     else if (CheckInputCommand ("b", theDesc, anArgIndex, 1, anArgsCount))
3576     {
3577       Standard_Integer aVertCount = theDesc->Value (anArgIndex - 1).IntegerValue();
3578
3579       if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
3580         myPArray->AddBound (aVertCount,
3581                             theDesc->Value (anArgIndex - 3).RealValue(),
3582                             theDesc->Value (anArgIndex - 2).RealValue(),
3583                             theDesc->Value (anArgIndex - 1).RealValue());
3584
3585       else
3586         myPArray->AddBound (aVertCount);
3587     }
3588     // edge command
3589     else if (CheckInputCommand ("e", theDesc, anArgIndex, 1, anArgsCount))
3590     {
3591       const Standard_Integer anEdge = theDesc->Value (anArgIndex - 1).IntegerValue();
3592       myPArray->AddEdge (anEdge);
3593     }
3594     // unknown command
3595     else
3596     {
3597       Message::SendFail() << "Syntax error: unknown argument '" << theDesc->Value(anArgIndex) << "'";
3598       return Standard_False;
3599     }
3600   }
3601   return Standard_True;
3602 }
3603
3604 //=======================================================================
3605 // function : SetColor
3606 // purpose  :
3607 //=======================================================================
3608 void MyPArrayObject::SetColor (const Quantity_Color& theColor)
3609 {
3610   AIS_InteractiveObject::SetColor (theColor);
3611   setColorForShadingAspect (theColor);
3612   if (myMarkerAspect)
3613   {
3614     myMarkerAspect->SetColor (theColor);
3615   }
3616   SynchronizeAspects();
3617 }
3618
3619 void MyPArrayObject::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
3620                                        const Standard_Integer theMode)
3621 {
3622   if (theMode != 0
3623    || myPArray.IsNull())
3624   {
3625     return;
3626   }
3627
3628   Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this);
3629   if (Handle(Graphic3d_ArrayOfTriangles) aTris = Handle(Graphic3d_ArrayOfTriangles)::DownCast (myPArray))
3630   {
3631     Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anOwner);
3632     aSensitive->InitTriangulation (myPArray->Attributes(), myPArray->Indices(), TopLoc_Location(), true);
3633     theSelection->Add (aSensitive);
3634   }
3635   else if (Handle(Graphic3d_ArrayOfSegments) aSegs = Handle(Graphic3d_ArrayOfSegments)::DownCast (myPArray))
3636   {
3637     if (aSegs->EdgeNumber() > 0)
3638     {
3639       for (Standard_Integer aPntIter = 1; aPntIter <= aSegs->EdgeNumber(); aPntIter += 2)
3640       {
3641         Handle(Select3D_SensitiveSegment) aSeg = new Select3D_SensitiveSegment (anOwner, aSegs->Vertice (aSegs->Edge (aPntIter)), aSegs->Vertice (aSegs->Edge (aPntIter + 1)));
3642         aSeg->SetSensitivityFactor (4);
3643         theSelection->Add (aSeg);
3644       }
3645     }
3646     else
3647     {
3648       for (Standard_Integer aPntIter = 1; aPntIter <= aSegs->VertexNumber(); aPntIter += 2)
3649       {
3650         Handle(Select3D_SensitiveSegment) aSeg = new Select3D_SensitiveSegment (anOwner, aSegs->Vertice (aPntIter), aSegs->Vertice (aPntIter + 1));
3651         aSeg->SetSensitivityFactor (4);
3652         theSelection->Add (aSeg);
3653       }
3654     }
3655   }
3656   else
3657   {
3658     Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anOwner);
3659     aSensitive->SetSensitivityFactor (8);
3660     aSensitive->InitPoints (myPArray->Attributes(), myPArray->Indices(), TopLoc_Location(), true);
3661     theSelection->Add (aSensitive);
3662   }
3663 }
3664
3665 bool MyPArrayObject::CheckInputCommand (const TCollection_AsciiString theCommand,
3666                                        const Handle(TColStd_HArray1OfAsciiString)& theArgsArray,
3667                                        Standard_Integer &theArgIndex,
3668                                        Standard_Integer theArgCount,
3669                                        Standard_Integer theMaxArgs)
3670 {
3671   // check if there is more elements than expected
3672   if (theArgIndex >= theMaxArgs)
3673     return false;
3674
3675   TCollection_AsciiString aStrCommand = theArgsArray->Value (theArgIndex);
3676   aStrCommand.LowerCase();
3677   if (aStrCommand.Search(theCommand) != 1 ||
3678       theArgIndex + (theArgCount - 1) >= theMaxArgs)
3679     return false;
3680
3681   // go to the first data element
3682   theArgIndex++;
3683
3684   // check data if it can be converted to numeric
3685   for (int aElement = 0; aElement < theArgCount; aElement++, theArgIndex++)
3686   {
3687     aStrCommand = theArgsArray->Value (theArgIndex);
3688     if (!aStrCommand.IsRealValue())
3689       return false;
3690   }
3691
3692   return true;
3693 }
3694
3695 //=======================================================================
3696 // function : setColorForShadingAspect
3697 // purpose  :
3698 //=======================================================================
3699 void MyPArrayObject::setColorForShadingAspect (const Quantity_Color& theColor)
3700 {
3701   if (myDrawer->SetupOwnShadingAspect())
3702   {
3703     replaceShadingAspect();
3704   }
3705   myDrawer->ShadingAspect()->SetColor (theColor);
3706 }
3707
3708 //=======================================================================
3709 // function : replaceShadingAspect
3710 // purpose  :
3711 //=======================================================================
3712 void MyPArrayObject::replaceShadingAspect()
3713 {
3714   if (!myDrawer->Link())
3715   {
3716     return;
3717   }
3718   Graphic3d_MapOfAspectsToAspects anAspectReplacementMap;
3719   anAspectReplacementMap.Bind (myDrawer->Link()->ShadingAspect()->Aspect(), myDrawer->ShadingAspect()->Aspect());
3720   replaceAspects (anAspectReplacementMap);
3721 }
3722
3723 //=============================================================================
3724 //function : VDrawPArray
3725 //purpose  : Draws primitives array from list of vertexes, bounds, edges
3726 //=============================================================================
3727
3728 static int VDrawPArray (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3729 {
3730   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
3731   if (aContextAIS.IsNull())
3732   {
3733     Message::SendFail ("Error: no active Viewer");
3734     return 1;
3735   }
3736   else if (argc < 3)
3737   {
3738     Message::SendFail ("Syntax error: wrong number of arguments");
3739     return 1;
3740   }
3741
3742   // read the arguments
3743   Standard_Integer anArgIndex = 1;
3744   TCollection_AsciiString aName (argv[anArgIndex++]);
3745   TCollection_AsciiString anArrayType (argv[anArgIndex++]);
3746   anArrayType.LowerCase();
3747   Handle(MyPArrayObject) aPObject;
3748   if (anArrayType == "-shape")
3749   {
3750     Standard_CString aShapeName = argv[anArgIndex++];
3751     TopoDS_Shape aShape = DBRep::Get (aShapeName);
3752     Handle(Graphic3d_ArrayOfPrimitives) aTris = StdPrs_ShadedShape::FillTriangles (aShape);
3753     if (aShape.IsNull())
3754     {
3755       Message::SendFail() << "Syntax error: shape '" << aShapeName << "' is not found";
3756       return 1;
3757     }
3758     else if (aTris.IsNull())
3759     {
3760       Message::SendFail() << "Syntax error: shape '" << aShapeName << "' is not triangulated";
3761       return 1;
3762     }
3763
3764     aPObject = new MyPArrayObject (aTris);
3765     ViewerTest::Display (aName, aPObject);
3766     return 0;
3767   }
3768   else if (anArrayType == "-patch"
3769         || anArrayType == "-modify"
3770         || anArrayType == "-edit")
3771   {
3772     if (argc >= 3)
3773     {
3774       anArrayType = argv[anArgIndex++];
3775       anArrayType.LowerCase();
3776     }
3777
3778     if (GetMapOfAIS().IsBound2 (aName))
3779     {
3780       aPObject = Handle(MyPArrayObject)::DownCast (GetMapOfAIS().Find2 (aName));
3781     }
3782     if (aPObject.IsNull())
3783     {
3784       Message::SendFail() << "Syntax error: object '" << aName << "' cannot be found";
3785       return 1;
3786     }
3787   }
3788
3789   Standard_Boolean hasVertex = Standard_False;
3790
3791   Graphic3d_TypeOfPrimitiveArray aPrimType = Graphic3d_TOPA_UNDEFINED;
3792   if (anArrayType == "points")
3793   {
3794     aPrimType = Graphic3d_TOPA_POINTS;
3795   }
3796   else if (anArrayType == "segments")
3797   {
3798     aPrimType = Graphic3d_TOPA_SEGMENTS;
3799   }
3800   else if (anArrayType == "polylines")
3801   {
3802     aPrimType = Graphic3d_TOPA_POLYLINES;
3803   }
3804   else if (anArrayType == "triangles")
3805   {
3806     aPrimType = Graphic3d_TOPA_TRIANGLES;
3807   }
3808   else if (anArrayType == "trianglefans")
3809   {
3810     aPrimType = Graphic3d_TOPA_TRIANGLEFANS;
3811   }
3812   else if (anArrayType == "trianglestrips")
3813   {
3814     aPrimType = Graphic3d_TOPA_TRIANGLESTRIPS;
3815   }
3816   else if (anArrayType == "quads")
3817   {
3818     aPrimType = Graphic3d_TOPA_QUADRANGLES;
3819   }
3820   else if (anArrayType == "quadstrips")
3821   {
3822     aPrimType = Graphic3d_TOPA_QUADRANGLESTRIPS;
3823   }
3824   else if (anArrayType == "polygons")
3825   {
3826     aPrimType = Graphic3d_TOPA_POLYGONS;
3827   }
3828   if (aPrimType == Graphic3d_TOPA_UNDEFINED)
3829   {
3830     Message::SendFail ("Syntax error: unexpected type of primitives array");
3831     return 1;
3832   }
3833
3834   Standard_Integer aLowerArg = anArgIndex;
3835   Handle(TColStd_HArray1OfAsciiString) anArgsArray = new TColStd_HArray1OfAsciiString (0, argc - 3);
3836   for (; anArgIndex < argc; ++anArgIndex)
3837   {
3838     TCollection_AsciiString aCommand (argv[anArgIndex]);
3839     aCommand.LowerCase();
3840     if (!aCommand.IsAscii())
3841     {
3842       di << "Unexpected argument: #" << anArgIndex - 1 << " , "
3843          << "should be an array element: 'v', 'b', 'e' \n";
3844       break;
3845     }
3846
3847     if (aCommand == "v")
3848     {
3849       hasVertex = Standard_True;
3850     }
3851
3852     anArgsArray->SetValue (anArgIndex - aLowerArg, aCommand);
3853   }
3854
3855   if (!hasVertex)
3856   {
3857     di << "You should pass any verticies in the list of array elements\n";
3858     return 1;
3859   }
3860
3861   Handle(Graphic3d_AspectMarker3d)    anAspPoints;
3862   if (aPrimType == Graphic3d_TOPA_POINTS)
3863   {
3864     anAspPoints = new Graphic3d_AspectMarker3d (Aspect_TOM_POINT, Quantity_NOC_YELLOW, 1.0f);
3865   }
3866
3867   // create primitives array object
3868   if (aPObject.IsNull())
3869   {
3870     // register the object in map
3871     aPObject = new MyPArrayObject (aPrimType, anArgsArray, anAspPoints);
3872     VDisplayAISObject (aName, aPObject);
3873   }
3874   else
3875   {
3876     aPObject->Init (aPrimType, anArgsArray, anAspPoints, Standard_True);
3877     ViewerTest::CurrentView()->Redraw();
3878   }
3879   return 0;
3880 }
3881
3882 namespace
3883 {
3884   //! Auxiliary function for parsing translation vector - either 2D or 3D.
3885   static Standard_Integer parseTranslationVec (Standard_Integer theArgNb,
3886                                                const char**     theArgVec,
3887                                                gp_Vec&          theVec)
3888   {
3889     if (theArgNb < 2)
3890     {
3891       return 0;
3892     }
3893
3894     TCollection_AsciiString anX (theArgVec[0]);
3895     TCollection_AsciiString anY (theArgVec[1]);
3896     if (!anX.IsRealValue()
3897      || !anY.IsRealValue())
3898     {
3899       return 0;
3900     }
3901
3902     theVec.SetX (anX.RealValue());
3903     theVec.SetY (anY.RealValue());
3904     if (theArgNb >= 3)
3905     {
3906       TCollection_AsciiString anZ (theArgVec[2]);
3907       if (anZ.IsRealValue())
3908       {
3909         theVec.SetZ (anZ.RealValue());
3910         return 3;
3911       }
3912     }
3913     return 2;
3914   }
3915 }
3916
3917 //=======================================================================
3918 //function : VSetLocation
3919 //purpose  : Change location of AIS interactive object
3920 //=======================================================================
3921
3922 static Standard_Integer VSetLocation (Draw_Interpretor& theDI,
3923                                       Standard_Integer  theArgNb,
3924                                       const char**      theArgVec)
3925 {
3926   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3927   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
3928   if (aContext.IsNull())
3929   {
3930     Message::SendFail ("Error: no active viewer");
3931     return 1;
3932   }
3933
3934   Standard_Boolean toPrintInfo = Standard_True;
3935   Handle(AIS_InteractiveObject) anObj;
3936   TCollection_AsciiString aCmdName (theArgVec[0]);
3937   aCmdName.LowerCase();
3938   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3939   {
3940     TCollection_AsciiString anArg = theArgVec[anArgIter];
3941     anArg.LowerCase();
3942     if (anUpdateTool.parseRedrawMode (anArg))
3943     {
3944       continue;
3945     }
3946     else if (anObj.IsNull())
3947     {
3948       const TCollection_AsciiString aName (theArgVec[anArgIter]);
3949       GetMapOfAIS().Find2 (aName, anObj);
3950       if (anObj.IsNull())
3951       {
3952         Message::SendFail() << "Error: object '" << aName << "' is not displayed";
3953         return 1;
3954       }
3955     }
3956     else if (anArg == "-reset")
3957     {
3958       toPrintInfo = Standard_False;
3959       aContext->SetLocation (anObj, gp_Trsf());
3960     }
3961     else if (anArg == "-copyfrom"
3962           || anArg == "-copy")
3963     {
3964       if (anArgIter + 1 >= theArgNb)
3965       {
3966         Message::SendFail() << "Syntax error at '" << anArg << "'";
3967         return 1;
3968       }
3969
3970       const TCollection_AsciiString aName2 (theArgVec[anArgIter + 1]);
3971       Handle(AIS_InteractiveObject) anObj2;
3972       GetMapOfAIS().Find2 (aName2, anObj2);
3973       if (anObj2.IsNull())
3974       {
3975         Message::SendFail() << "Error: object '" << aName2 << "' is not displayed";
3976         return 1;
3977       }
3978
3979       ++anArgIter;
3980       aContext->SetLocation (anObj, anObj2->LocalTransformation());
3981     }
3982     else if (anArg == "-rotate"
3983           || anArg == "-prerotate")
3984     {
3985       toPrintInfo = Standard_False;
3986       if (anArgIter + 7 >= theArgNb)
3987       {
3988         Message::SendFail() << "Syntax error at '" << anArg << "'";
3989         return 1;
3990       }
3991
3992       gp_Trsf aTrsf;
3993       aTrsf.SetRotation (gp_Ax1 (gp_Pnt (Draw::Atof (theArgVec[anArgIter + 1]),
3994                                          Draw::Atof (theArgVec[anArgIter + 2]),
3995                                          Draw::Atof (theArgVec[anArgIter + 3])),
3996                                  gp_Vec (Draw::Atof (theArgVec[anArgIter + 4]),
3997                                          Draw::Atof (theArgVec[anArgIter + 5]),
3998                                          Draw::Atof (theArgVec[anArgIter + 6]))),
3999          &