11643aedbfe00ccc3bd8071a90e411ef3011015d
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 // Robert Boehne 30 May 2000 : Dec Osf
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #ifdef WNT
29 #include <windows.h>
30 #endif
31
32 #include <Graphic3d_AspectMarker3d.hxx>
33 #include <Graphic3d_GraphicDriver.hxx>
34 #include <Graphic3d_ExportFormat.hxx>
35 #include <ViewerTest.hxx>
36 #include <ViewerTest_EventManager.hxx>
37 #include <Visual3d_View.hxx>
38 #include <Visual3d_ViewManager.hxx>
39 #include <V3d_LayerMgr.hxx>
40 #include <NIS_View.hxx>
41 #include <NIS_Triangulated.hxx>
42 #include <NIS_InteractiveContext.hxx>
43 #include <AIS_InteractiveContext.hxx>
44 #include <Draw_Interpretor.hxx>
45 #include <Draw.hxx>
46 #include <Draw_Appli.hxx>
47 #include <Aspect_PrintAlgo.hxx>
48 #include <Image_AlienPixMap.hxx>
49 #include <OSD_Timer.hxx>
50 #include <TColStd_SequenceOfInteger.hxx>
51 #include <Visual3d_LayerItem.hxx>
52 #include <V3d_LayerMgr.hxx>
53 #include <V3d_LayerMgrPointer.hxx>
54 #include <Aspect_TypeOfLine.hxx>
55 #include <Image_Diff.hxx>
56
57 #ifdef WNT
58 #undef DrawText
59 #endif
60
61 #include <Visual3d_Layer.hxx>
62 #include <cstdlib>
63
64 #ifndef WNT
65 #include <Graphic3d_GraphicDevice.hxx>
66 #include <Xw_GraphicDevice.hxx>
67 #include <Xw_WindowQuality.hxx>
68 #include <Xw_Window.hxx>
69 #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
70 #include <X11/Xutil.h>
71 #include <tk.h>
72
73 #else
74
75 #include <Graphic3d_WNTGraphicDevice.hxx>
76 #include <WNT_WClass.hxx>
77 #include <WNT_Window.hxx>
78
79 #define _CRT_SECURE_NO_DEPRECATE
80 #pragma warning (disable:4996)
81
82 #endif
83
84 #define OCC120
85
86 //==============================================================================
87
88 //==============================================================================
89 //  VIEWER GLOBAL VARIABLES
90 //==============================================================================
91
92 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
93
94 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
95 extern const Handle(NIS_InteractiveContext)& TheNISContext();
96
97 #ifdef WNT
98 static Handle(Graphic3d_WNTGraphicDevice)& GetG3dDevice(){
99   static Handle(Graphic3d_WNTGraphicDevice) GD;
100   return GD;
101 }
102
103 static Handle(WNT_Window)& VT_GetWindow() {
104   static Handle(WNT_Window) WNTWin;
105   return WNTWin;
106 }
107
108 #else
109 static Handle(Graphic3d_GraphicDevice)& GetG3dDevice(){
110   static Handle(Graphic3d_GraphicDevice) GD;
111   return GD;
112 }
113 static Handle(Xw_Window)& VT_GetWindow(){
114   static Handle(Xw_Window) XWWin;
115   return XWWin;
116 }
117 static Display *display;
118
119 static void VProcessEvents(ClientData,int);
120 #endif
121
122 #ifdef OCC120
123 static Standard_Boolean DegenerateMode = Standard_True;
124 #endif
125
126 #define ZCLIPWIDTH 1.
127
128 static void OSWindowSetup();
129
130 //==============================================================================
131 //  EVENT GLOBAL VARIABLES
132 //==============================================================================
133
134 static int Start_Rot = 0;
135 static int ZClipIsOn = 0;
136 static int X_Motion= 0,Y_Motion=0; // Current cursor position
137 static int X_ButtonPress = 0, Y_ButtonPress = 0; // Last ButtonPress position
138
139
140 //==============================================================================
141
142 #ifdef WNT
143 static LRESULT WINAPI ViewerWindowProc(
144                                        HWND hwnd,
145                                        UINT uMsg,
146                                        WPARAM wParam,
147                                        LPARAM lParam );
148 static LRESULT WINAPI AdvViewerWindowProc(
149   HWND hwnd,
150   UINT uMsg,
151   WPARAM wParam,
152   LPARAM lParam );
153 #endif
154
155
156 //==============================================================================
157 //function : WClass
158 //purpose  :
159 //==============================================================================
160
161 const Handle(MMgt_TShared)& ViewerTest::WClass()
162 {
163   static Handle(MMgt_TShared) theWClass;
164 #ifdef WNT
165   if (theWClass.IsNull()) {
166     theWClass = new WNT_WClass ("GW3D_Class", AdvViewerWindowProc,
167       CS_VREDRAW | CS_HREDRAW, 0, 0,
168       ::LoadCursor (NULL, IDC_ARROW));
169   }
170 #endif
171   return theWClass;
172 }
173
174 //==============================================================================
175 //function : ViewerInit
176 //purpose  : Create the window viewer and initialize all the global variable
177 //==============================================================================
178
179 void ViewerTest::ViewerInit (const Standard_Integer thePxLeft,  const Standard_Integer thePxTop,
180                              const Standard_Integer thePxWidth, const Standard_Integer thePxHeight)
181 {
182   static Standard_Boolean isFirst = Standard_True;
183
184   // Default position and dimension of the viewer window.
185   // Note that left top corner is set to be sufficiently small to have 
186   // window fit in the small screens (actual for remote desktops, see #23003).
187   // The position corresponds to the window's client area, thus some 
188   // gap is added for window frame to be visible.
189   Standard_Integer aPxLeft   = 20;
190   Standard_Integer aPxTop    = 40;
191   Standard_Integer aPxWidth  = 409;
192   Standard_Integer aPxHeight = 409;
193   if (thePxWidth != 0 && thePxHeight != 0)
194   {
195     aPxLeft   = thePxLeft;
196     aPxTop    = thePxTop;
197     aPxWidth  = thePxWidth;
198     aPxHeight = thePxHeight;
199   }
200
201   if (isFirst)
202   {
203     // Create the Graphic device
204 #ifdef WNT
205     if (GetG3dDevice().IsNull()) GetG3dDevice() = new Graphic3d_WNTGraphicDevice();
206     if (VT_GetWindow().IsNull())
207     {
208       // Create the Graphic device and the window
209       Handle(WNT_GraphicDevice) g_Device = new WNT_GraphicDevice();
210
211       VT_GetWindow() = new WNT_Window (g_Device, "Test3d",
212                                        Handle(WNT_WClass)::DownCast (WClass()),
213                                        WS_OVERLAPPEDWINDOW,
214                                        aPxLeft, aPxTop,
215                                        aPxWidth, aPxHeight,
216                                        Quantity_NOC_BLACK);
217       VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
218     }
219 #else
220     if (GetG3dDevice().IsNull()) GetG3dDevice() =
221       new Graphic3d_GraphicDevice (getenv ("DISPLAY"), Xw_TOM_READONLY);
222     if (VT_GetWindow().IsNull())
223     {
224       VT_GetWindow() = new Xw_Window (GetG3dDevice(),
225                                       "Test3d",
226                                       aPxLeft, aPxTop,
227                                       aPxWidth, aPxHeight,
228                                       Xw_WQ_3DQUALITY,
229                                       Quantity_NOC_BLACK);
230       VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
231     }
232 #endif
233
234     Handle(V3d_Viewer) a3DViewer, a3DCollector;
235     // Viewer and View creation
236
237     TCollection_ExtendedString NameOfWindow("Visu3D");
238
239     a3DViewer = new V3d_Viewer(GetG3dDevice(), NameOfWindow.ToExtString());
240     NameOfWindow = TCollection_ExtendedString("Collector");
241     a3DCollector = new V3d_Viewer(GetG3dDevice(), NameOfWindow.ToExtString());
242     a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
243     a3DCollector->SetDefaultBackgroundColor(Quantity_NOC_STEELBLUE);
244     Handle(NIS_View) aView = Handle(NIS_View)::DownCast(ViewerTest::CurrentView());
245     if (aView.IsNull())
246     {
247       //Handle(V3d_View) a3DViewCol = a3DViewer->CreateView();
248       aView = new NIS_View (a3DViewer, VT_GetWindow());
249       ViewerTest::CurrentView(aView);
250       TheNISContext()->AttachView (aView);
251     }
252
253     // AIS setup
254     if ( ViewerTest::GetAISContext().IsNull() ) {
255       Handle(AIS_InteractiveContext) C =
256         new AIS_InteractiveContext(a3DViewer,a3DCollector);
257       ViewerTest::SetAISContext(C);
258     }
259
260     // Setup for X11 or NT
261     OSWindowSetup();
262     // Viewer and View creation
263
264     a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
265
266     Handle (V3d_View) V = ViewerTest::CurrentView();
267
268     V->SetDegenerateModeOn();
269 #ifdef OCC120
270     DegenerateMode = V->DegenerateModeIsOn();
271 #endif
272     //    V->SetWindow(VT_GetWindow(), NULL, MyViewProc, NULL);
273
274     V->SetZClippingDepth(0.5);
275     V->SetZClippingWidth(ZCLIPWIDTH/2.);
276     a3DViewer->SetDefaultLights();
277     a3DViewer->SetLightOn();
278
279 #ifndef WNT
280 #if TCL_MAJOR_VERSION  < 8
281     Tk_CreateFileHandler((void*)ConnectionNumber(display),
282       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
283 #else
284     Tk_CreateFileHandler(ConnectionNumber(display),
285       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
286 #endif
287 #endif
288
289     isFirst = Standard_False;
290   }
291   VT_GetWindow()->Map();
292 }
293
294 //==============================================================================
295 //function : Vinit
296 //purpose  : Create the window viewer and initialize all the global variable
297 //    Use Tk_CreateFileHandler on UNIX to cath the X11 Viewer event
298 //==============================================================================
299
300 static int VInit (Draw_Interpretor& , Standard_Integer argc, const char** argv)
301 {
302   Standard_Integer aPxLeft   = (argc > 1) ? atoi (argv[1]) : 0;
303   Standard_Integer aPxTop    = (argc > 2) ? atoi (argv[2]) : 0;
304   Standard_Integer aPxWidth  = (argc > 3) ? atoi (argv[3]) : 0;
305   Standard_Integer aPxHeight = (argc > 4) ? atoi (argv[4]) : 0;
306   ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight);
307   return 0;
308 }
309
310 //==============================================================================
311 //function : ProcessKeyPress
312 //purpose  : Handle KeyPress event from a CString
313 //==============================================================================
314
315 static void ProcessKeyPress( char *buf_ret )
316 {
317   //cout << "KeyPress" << endl;
318   const Handle(V3d_View) aView = ViewerTest::CurrentView();
319   const Handle(NIS_View) aNisView = Handle(NIS_View)::DownCast (aView);
320   // Letter in alphabetic order
321
322   if ( !strcasecmp(buf_ret, "A") ) {
323     // AXO
324     aView->SetProj(V3d_XposYnegZpos);
325   }
326   else if ( !strcasecmp(buf_ret, "D") ) {
327     // Reset
328     aView->Reset();
329   }
330   else if ( !strcasecmp(buf_ret, "F") ) {
331     // FitAll
332     if (aNisView.IsNull())
333       aView->FitAll();
334     else
335       aNisView->FitAll3d();
336   }
337   else if ( !strcasecmp(buf_ret, "H") ) {
338     // HLR
339     cout << "HLR" << endl;
340 #ifdef OCC120
341     if (aView->DegenerateModeIsOn()) ViewerTest::CurrentView()->SetDegenerateModeOff();
342     else aView->SetDegenerateModeOn();
343     DegenerateMode = aView->DegenerateModeIsOn();
344 #else
345     ViewerTest::CurrentView()->SetDegenerateModeOff();
346 #endif
347   }
348   else if ( !strcasecmp(buf_ret, "S") ) {
349     // SHADING
350     cout << "passage en mode 1 (shading pour les shapes)" << endl;
351 #ifndef OCC120
352     ViewerTest::CurrentView()->SetDegenerateModeOn();
353 #endif
354     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
355     if(Ctx->NbCurrents()==0 ||
356       Ctx->NbSelected()==0)
357       Ctx->SetDisplayMode(AIS_Shaded);
358     else{
359       if(Ctx->HasOpenedContext()){
360         for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
361           Ctx->SetDisplayMode(Ctx->Interactive(),1,Standard_False);
362       }
363       else{
364         for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent())
365           Ctx->SetDisplayMode(Ctx->Current(),1,Standard_False);
366       }
367       Ctx->UpdateCurrentViewer();
368     }
369   }
370   else if ( !strcasecmp(buf_ret, "U") ) {
371     // Unset display mode
372     cout<<"passage au mode par defaut"<<endl;
373 #ifndef OCC120
374     ViewerTest::CurrentView()->SetDegenerateModeOn();
375 #endif
376     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
377     if(Ctx->NbCurrents()==0 ||
378       Ctx->NbSelected()==0)
379       Ctx->SetDisplayMode(AIS_WireFrame);
380     else{
381       if(Ctx->HasOpenedContext()){
382         for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
383           Ctx->UnsetDisplayMode(Ctx->Interactive(),Standard_False);
384       }
385       else{
386         for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent())
387           Ctx->UnsetDisplayMode(Ctx->Current(),Standard_False);
388       }
389       Ctx->UpdateCurrentViewer();
390     }
391
392   }
393   else if ( !strcasecmp(buf_ret, "T") ) {
394     // Top
395     aView->SetProj(V3d_Zpos);
396   }
397   else if ( !strcasecmp(buf_ret, "B") ) {
398     // Bottom
399     aView->SetProj(V3d_Zneg);
400   }
401   else if ( !strcasecmp(buf_ret, "L") ) {
402     // Left
403     aView->SetProj(V3d_Xneg);
404   }
405   else if ( !strcasecmp(buf_ret, "R") ) {
406     // Right
407     aView->SetProj(V3d_Xpos);
408   }
409
410   else if ( !strcasecmp(buf_ret, "W") ) {
411     // WIREFRAME
412 #ifndef OCC120
413     ViewerTest::CurrentView()->SetDegenerateModeOn();
414 #endif
415     cout << "passage en mode 0 (filaire pour les shapes)" << endl;
416 #ifndef OCC120
417     ViewerTest::CurrentView()->SetDegenerateModeOn();
418 #endif
419     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
420     if(Ctx->NbCurrents()==0 ||
421       Ctx->NbSelected()==0)
422       Ctx->SetDisplayMode(AIS_WireFrame);
423     else{
424       if(Ctx->HasOpenedContext()){
425         for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
426           Ctx->SetDisplayMode(Ctx->Interactive(),0,Standard_False);
427       }
428       else{
429         for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent())
430           Ctx->SetDisplayMode(Ctx->Current(),0,Standard_False);
431       }
432       Ctx->UpdateCurrentViewer();
433     }
434   }
435   else if ( !strcasecmp(buf_ret, "Z") ) {
436     // ZCLIP
437
438     if ( ZClipIsOn ) {
439       cout << "ZClipping OFF" << endl;
440       ZClipIsOn = 0;
441
442       aView->SetZClippingType(V3d_OFF);
443       aView->Redraw();
444     }
445     else {
446       cout << "ZClipping ON" << endl;
447       ZClipIsOn = 1;
448
449       aView->SetZClippingType(V3d_FRONT);
450       aView->Redraw();
451     }
452   }
453   else if ( !strcasecmp(buf_ret, ",") ) {
454     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
455
456
457   }
458   else if ( !strcasecmp(buf_ret, ".") ) {
459     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
460   }
461   // Number
462   else{
463     Standard_Integer Num = atoi(buf_ret);
464     if(Num>=0 && Num<=7)
465       ViewerTest::StandardModeActivation(Num);
466   }
467 }
468
469 //==============================================================================
470 //function : ProcessExpose
471 //purpose  : Redraw the View on an Expose Event
472 //==============================================================================
473
474 static void ProcessExpose(  )
475 { //cout << "Expose" << endl;
476   ViewerTest::CurrentView()->Redraw();
477 }
478
479 //==============================================================================
480 //function : ProcessConfigure
481 //purpose  : Resize the View on an Configure Event
482 //==============================================================================
483
484 static void ProcessConfigure()
485 {
486   Handle(V3d_View) V = ViewerTest::CurrentView();
487   V->MustBeResized();
488   V->Update();
489   V->Redraw();
490 }
491
492 //==============================================================================
493 //function : ProcessButton1Press
494 //purpose  : Picking
495 //==============================================================================
496
497 static Standard_Boolean ProcessButton1Press(
498   Standard_Integer ,
499   const char** argv,
500   Standard_Boolean pick,
501   Standard_Boolean shift )
502 {
503   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
504   if ( pick ) {
505     Standard_Real X, Y, Z;
506
507     ViewerTest::CurrentView()->Convert(X_Motion, Y_Motion, X, Y, Z);
508
509     Draw::Set(argv[1], X);
510     Draw::Set(argv[2], Y);
511     Draw::Set(argv[3], Z);}
512
513   if(shift)
514     EM->ShiftSelect();
515   else
516     EM->Select();
517
518   pick = 0;
519   return pick;
520 }
521
522 //==============================================================================
523 //function : ProcessButton3Press
524 //purpose  : Start Rotation
525 //==============================================================================
526
527 static void ProcessButton3Press()
528
529 { // Start rotation
530   Start_Rot = 1;
531   ViewerTest::CurrentView()->SetDegenerateModeOn();
532   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
533
534 }
535 //==============================================================================
536 //function : ProcessButtonRelease
537 //purpose  : Start Rotation
538 //==============================================================================
539
540 static void ProcessButtonRelease()
541
542 { // End rotation
543 #ifdef OCC120
544   if (Start_Rot) {
545     Start_Rot = 0;
546     if (!DegenerateMode) ViewerTest::CurrentView()->SetDegenerateModeOff();
547   }
548 #else
549   Start_Rot = 0;
550   ViewerTest::CurrentView()->SetDegenerateModeOff();
551 #endif
552 }
553
554 //==============================================================================
555 //function : ProcessZClipMotion
556 //purpose  : Zoom
557 //==============================================================================
558
559 void ProcessZClipMotion()
560 {
561   Handle(V3d_View)  a3DView = ViewerTest::CurrentView();
562   if ( Abs(X_Motion - X_ButtonPress) > 2 ) {
563     static Standard_Real CurZPos = 0.;
564
565     //Quantity_Length VDX, VDY;
566     //a3DView->Size(VDX,VDY);
567     //Standard_Real VDZ = a3DView->ZSize();
568     //printf("View size (%lf,%lf,%lf)\n", VDX, VDY, VDZ);
569
570     Quantity_Length dx = a3DView->Convert(X_Motion - X_ButtonPress);
571
572     // Front = Depth + width/2.
573     Standard_Real D = 0.5;
574     Standard_Real W = 0.1;
575
576     CurZPos += (dx);
577
578     D += CurZPos;
579
580     //printf("dx %lf Depth %lf Width %lf\n", dx, D, W);
581
582     a3DView->SetZClippingType(V3d_OFF);
583     a3DView->SetZClippingDepth(D);
584     a3DView->SetZClippingWidth(W);
585     a3DView->SetZClippingType(V3d_FRONT);
586
587     a3DView->Redraw();
588
589     X_ButtonPress = X_Motion;
590     Y_ButtonPress = Y_Motion;
591   }
592 }
593
594 //==============================================================================
595 //function : ProcessControlButton1Motion
596 //purpose  : Zoom
597 //==============================================================================
598
599 static void ProcessControlButton1Motion()
600 {
601   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
602
603   X_ButtonPress = X_Motion;
604   Y_ButtonPress = Y_Motion;
605 }
606
607 //==============================================================================
608 //function : ProcessControlButton2Motion
609 //purpose  : Pann
610 //==============================================================================
611
612 static void ProcessControlButton2Motion()
613 {
614   Quantity_Length dx = ViewerTest::CurrentView()->Convert(X_Motion - X_ButtonPress);
615   Quantity_Length dy = ViewerTest::CurrentView()->Convert(Y_Motion - Y_ButtonPress);
616
617   dy = -dy; // Xwindow Y axis is from top to Bottom
618
619   ViewerTest::CurrentView()->Panning( dx, dy );
620
621   X_ButtonPress = X_Motion;
622   Y_ButtonPress = Y_Motion;
623 }
624
625 //==============================================================================
626 //function : ProcessControlButton3Motion
627 //purpose  : Rotation
628 //==============================================================================
629
630 static void ProcessControlButton3Motion()
631 {
632   if ( Start_Rot ) ViewerTest::CurrentView()->Rotation( X_Motion, Y_Motion);
633 }
634
635 //==============================================================================
636 //function : ProcessPointerMotion
637 //purpose  : Rotation
638 //==============================================================================
639
640 static void ProcessMotion()
641 {
642   //pre-hilights detected objects at mouse position
643
644   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
645   EM->MoveTo(X_Motion, Y_Motion);
646 }
647
648
649 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
650 {
651   Xpix = X_Motion;Ypix=Y_Motion;
652 }
653
654 //==============================================================================
655 //function : ViewProject: implements VAxo, VTop, VLeft, ...
656 //purpose  : Switches to an axonometric, top, left and other views
657 //==============================================================================
658
659 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
660 {
661   if ( ViewerTest::CurrentView().IsNull() ) 
662   {
663     di<<"Call vinit before this command, please"<<"\n";
664     return 1;
665   }
666
667   ViewerTest::CurrentView()->SetProj(ori);
668   return 0;
669 }
670
671 //==============================================================================
672 //function : VAxo
673 //purpose  : Switch to an Axonometric view
674 //Draw arg : No args
675 //==============================================================================
676
677 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
678 {
679   return ViewProject(di, V3d_XposYnegZpos);
680 }
681
682 //==============================================================================
683 //function : VTop
684 //purpose  : Switch to a Top View
685 //Draw arg : No args
686 //==============================================================================
687
688 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
689 {
690   return ViewProject(di, V3d_Zpos);
691 }
692
693 //==============================================================================
694 //function : VBottom
695 //purpose  : Switch to a Bottom View
696 //Draw arg : No args
697 //==============================================================================
698
699 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
700 {
701   return ViewProject(di, V3d_Zneg);
702 }
703
704 //==============================================================================
705 //function : VLeft
706 //purpose  : Switch to a Left View
707 //Draw arg : No args
708 //==============================================================================
709
710 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
711 {
712   return ViewProject(di, V3d_Ypos);
713 }
714
715 //==============================================================================
716 //function : VRight
717 //purpose  : Switch to a Right View
718 //Draw arg : No args
719 //==============================================================================
720
721 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
722 {
723   return ViewProject(di, V3d_Yneg);
724 }
725
726 //==============================================================================
727 //function : VFront
728 //purpose  : Switch to a Front View
729 //Draw arg : No args
730 //==============================================================================
731
732 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
733 {
734   return ViewProject(di, V3d_Xpos);
735 }
736
737 //==============================================================================
738 //function : VBack
739 //purpose  : Switch to a Back View
740 //Draw arg : No args
741 //==============================================================================
742
743 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
744 {
745   return ViewProject(di, V3d_Xneg);
746 }
747
748 //==============================================================================
749 //function : VHelp
750 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
751 //Draw arg : No args
752 //==============================================================================
753
754 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
755 {
756
757   di << "Q : Quit the application" << "\n";
758
759   di << "========================="<<"\n";
760   di << "F : FitAll" << "\n";
761   di << "T : TopView" << "\n";
762   di << "B : BottomView" << "\n";
763   di << "R : RightView" << "\n";
764   di << "L : LeftView" << "\n";
765   di << "A : AxonometricView" << "\n";
766   di << "D : ResetView" << "\n";
767
768   di << "========================="<<"\n";
769   di << "S : Shading" << "\n";
770   di << "W : Wireframe" << "\n";
771   di << "H : HidelLineRemoval" << "\n";
772   di << "U : Unset display mode" << "\n";
773
774   di << "========================="<<"\n";
775   di << "Selection mode "<<"\n";
776   di << "0 : Shape" <<"\n";
777   di << "1 : Vertex" <<"\n";
778   di << "2 : Edge" <<"\n";
779   di << "3 : Wire" <<"\n";
780   di << "4 : Face" <<"\n";
781   di << "5 : Shell" <<"\n";
782   di << "6 : Solid" <<"\n";
783   di << "7 : Compound" <<"\n";
784
785   di << "========================="<<"\n";
786   di << "Z : Switch Z clipping On/Off" << "\n";
787   di << ", : Hilight next detected" << "\n";
788   di << ". : Hilight previous detected" << "\n";
789
790   return 0;
791 }
792
793 Standard_Boolean IsDragged = Standard_False;
794
795 Standard_Integer xx1, yy1, xx2, yy2;
796 //the first and last point in viewer co-ordinates
797
798 Standard_Boolean DragFirst;
799
800
801 #ifdef WNT
802
803 static Standard_Boolean Ppick = 0;
804 static Standard_Integer Pargc = 0;
805 static const char**           Pargv = NULL;
806
807
808 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
809                                           UINT Msg,
810                                           WPARAM wParam,
811                                           LPARAM lParam )
812 {
813   if ( !ViewerTest::CurrentView().IsNull() ) {
814
815     WPARAM fwKeys = wParam;
816
817     switch( Msg ) {
818
819     case WM_LBUTTONUP:
820       IsDragged = Standard_False;
821       if( !DragFirst )
822       {
823         HDC hdc = GetDC( hwnd );
824         HGDIOBJ anObj = SelectObject( hdc, GetStockObject( WHITE_PEN ) );
825         SelectObject( hdc, GetStockObject( HOLLOW_BRUSH ) );
826         SetROP2( hdc, R2_NOT );
827         Rectangle( hdc, xx1, yy1, xx2, yy2 );
828         ReleaseDC( hwnd, hdc );
829
830         const Handle(ViewerTest_EventManager) EM =
831           ViewerTest::CurrentEventManager();
832         if ( fwKeys & MK_SHIFT )
833           EM->ShiftSelect( min( xx1, xx2 ), max( yy1, yy2 ),
834           max( xx1, xx2 ), min( yy1, yy2 ));
835         else
836           EM->Select( min( xx1, xx2 ), max( yy1, yy2 ),
837           max( xx1, xx2 ), min( yy1, yy2 ));
838       }
839       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
840
841     case WM_LBUTTONDOWN:
842       if( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) )
843       {
844         IsDragged = Standard_True;
845         DragFirst = Standard_True;
846         xx1 = LOWORD(lParam);
847         yy1 = HIWORD(lParam);
848       }
849       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
850
851       break;
852
853     case WM_MOUSEMOVE:
854       if( IsDragged )
855       {
856         HDC hdc = GetDC( hwnd );
857
858         HGDIOBJ anObj = SelectObject( hdc, GetStockObject( WHITE_PEN ) );
859         SelectObject( hdc, GetStockObject( HOLLOW_BRUSH ) );
860         SetROP2( hdc, R2_NOT );
861
862         if( !DragFirst )
863           Rectangle( hdc, xx1, yy1, xx2, yy2 );
864
865         DragFirst = Standard_False;
866         xx2 = LOWORD(lParam);
867         yy2 = HIWORD(lParam);
868
869         Rectangle( hdc, xx1, yy1, xx2, yy2 );
870
871         SelectObject( hdc, anObj );
872
873         ReleaseDC( hwnd, hdc );
874       }
875       else
876         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
877       break;
878
879     default:
880       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
881     }
882     return 0;
883   }
884   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
885 }
886
887
888 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
889                                        UINT Msg,
890                                        WPARAM wParam,
891                                        LPARAM lParam )
892 {
893   /*static Standard_Boolean Ppick = 0;
894   static Standard_Integer Pargc = 0;
895   static char**           Pargv = NULL;*/
896
897   static int Up = 1;
898
899   if ( !ViewerTest::CurrentView().IsNull() ) {
900     PAINTSTRUCT    ps;
901
902     switch( Msg ) {
903     case WM_CLOSE:
904       // do not destroy the window - just hide it!
905       VT_GetWindow()->Unmap();
906       return 0;
907     case WM_PAINT:
908       //cout << "\t WM_PAINT" << endl;
909       BeginPaint(hwnd, &ps);
910       EndPaint(hwnd, &ps);
911       ProcessExpose();
912       break;
913
914     case WM_SIZE:
915       //cout << "\t WM_SIZE" << endl;
916       ProcessConfigure();
917       break;
918
919     case WM_KEYDOWN:
920       //cout << "\t WM_KEYDOWN " << (int) wParam << endl;
921
922       if ( (wParam != VK_SHIFT) && (wParam != VK_CONTROL) ) {
923         char c[2];
924         c[0] = (char) wParam;
925         c[1] = '\0';
926         ProcessKeyPress( c);
927       }
928       break;
929
930     case WM_LBUTTONUP:
931     case WM_MBUTTONUP:
932     case WM_RBUTTONUP:
933       //cout << "\t WM_xBUTTONUP" << endl;
934       Up = 1;
935       ProcessButtonRelease();
936       break;
937
938     case WM_LBUTTONDOWN:
939     case WM_MBUTTONDOWN:
940     case WM_RBUTTONDOWN:
941       {
942         //cout << "\t WM_xBUTTONDOWN" << endl;
943         WPARAM fwKeys = wParam;
944
945         Up = 0;
946
947         X_ButtonPress = LOWORD(lParam);
948         Y_ButtonPress = HIWORD(lParam);
949
950         if ( Msg == WM_LBUTTONDOWN) {
951           if(fwKeys & MK_CONTROL) {
952             Ppick = ProcessButton1Press( Pargc, Pargv, Ppick,  (fwKeys & MK_SHIFT) );
953           } else
954             ProcessButton1Press( Pargc, Pargv, Ppick,  (fwKeys & MK_SHIFT) );
955         }
956         else if ( Msg == WM_RBUTTONDOWN ) {
957           // Start rotation
958           ProcessButton3Press( );
959         }
960       }
961       break;
962
963     case WM_MOUSEMOVE:
964       {
965         //cout << "\t WM_MOUSEMOVE" << endl;
966         WPARAM fwKeys = wParam;
967         X_Motion = LOWORD(lParam);
968         Y_Motion = HIWORD(lParam);
969
970         if ( Up &&
971           fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON ) ) {
972             Up = 0;
973             X_ButtonPress = LOWORD(lParam);
974             Y_ButtonPress = HIWORD(lParam);
975
976             if ( fwKeys & MK_RBUTTON ) {
977               // Start rotation
978               ProcessButton3Press();
979             }
980           }
981
982           if ( fwKeys & MK_CONTROL ) {
983             if ( fwKeys & MK_LBUTTON ) {
984               ProcessControlButton1Motion();
985             }
986             else if ( fwKeys & MK_MBUTTON ||
987               ((fwKeys&MK_LBUTTON) &&
988               (fwKeys&MK_RBUTTON) ) ){
989                 ProcessControlButton2Motion();
990               }
991             else if ( fwKeys & MK_RBUTTON ) {
992               ProcessControlButton3Motion();
993             }
994           }
995 #ifdef BUG
996           else if ( fwKeys & MK_SHIFT ) {
997             if ( fwKeys & MK_MBUTTON ||
998               ((fwKeys&MK_LBUTTON) &&
999               (fwKeys&MK_RBUTTON) ) ) {
1000                 cout << "ProcessZClipMotion()" << endl;
1001                 ProcessZClipMotion();
1002               }
1003           }
1004 #endif
1005           else
1006             if (( fwKeys & MK_MBUTTON || ((fwKeys&MK_LBUTTON) && (fwKeys&MK_RBUTTON) ) )){
1007               ProcessZClipMotion();
1008             }
1009             else {
1010               ProcessMotion();
1011             }
1012       }
1013       break;
1014
1015     default:
1016       return( DefWindowProc( hwnd, Msg, wParam, lParam ));
1017     }
1018     return 0L;
1019   }
1020
1021   return DefWindowProc( hwnd, Msg, wParam, lParam );
1022 }
1023
1024
1025
1026
1027 //==============================================================================
1028 //function : ViewerMainLoop
1029 //purpose  : Get a Event on the view and dispatch it
1030 //==============================================================================
1031
1032
1033 static int ViewerMainLoop(Standard_Integer argc, const char** argv)
1034 {
1035
1036   //cout << "No yet implemented on WNT" << endl;
1037   /*static Standard_Boolean Ppick = 0;
1038   static Standard_Integer Pargc = 0;
1039   static char**           Pargv = NULL;*/
1040
1041   //Ppick = (argc > 0)? -1 : 0;
1042   Ppick = (argc > 0)? 1 : 0;
1043   Pargc = argc;
1044   Pargv = argv;
1045
1046   if ( Ppick ) {
1047     MSG msg;
1048     msg.wParam = 1;
1049
1050     cout << "Start picking" << endl;
1051
1052     //while ( Ppick == -1 ) {
1053     while ( Ppick == 1 ) {
1054       // Wait for a ProcessButton1Press() to toggle pick to 1 or 0
1055       if (GetMessage(&msg, NULL, 0, 0) ) {
1056         TranslateMessage(&msg);
1057         DispatchMessage(&msg);
1058       }
1059     }
1060
1061     cout << "Picking done" << endl;
1062   }
1063
1064   return Ppick;
1065 }
1066
1067
1068 #else
1069
1070 int min( int a, int b )
1071 {
1072   if( a<b )
1073     return a;
1074   else
1075     return b;
1076 }
1077
1078 int max( int a, int b )
1079 {
1080   if( a>b )
1081     return a;
1082   else
1083     return b;
1084 }
1085
1086 int ViewerMainLoop(Standard_Integer argc, const char** argv)
1087
1088 { Standard_Boolean pick = argc > 0;
1089
1090 // X11 Event loop
1091
1092 static XEvent report;
1093
1094 XNextEvent( display, &report );
1095 //    cout << "rep type = " << report.type << endl;
1096 //    cout << "rep button = " << report.xbutton.button << endl;
1097
1098 switch ( report.type ) {
1099       case Expose:
1100         {
1101           ProcessExpose();
1102         }
1103         break;
1104       case ConfigureNotify:
1105         {
1106           ProcessConfigure();
1107         }
1108         break;
1109       case KeyPress:
1110         {
1111
1112           KeySym ks_ret ;
1113           char buf_ret[11] ;
1114           int ret_len ;
1115           XComposeStatus status_in_out;
1116
1117           ret_len = XLookupString( ( XKeyEvent *)&report ,
1118             (char *) buf_ret , 10 ,
1119             &ks_ret , &status_in_out ) ;
1120
1121
1122           buf_ret[ret_len] = '\0' ;
1123
1124           if ( ret_len ) {
1125             ProcessKeyPress( buf_ret);
1126           }
1127         }
1128         break;
1129       case ButtonPress:
1130         //  cout << "ButtonPress" << endl;
1131         {
1132           X_ButtonPress = report.xbutton.x;
1133           Y_ButtonPress = report.xbutton.y;
1134
1135           if ( report.xbutton.button == Button1 )
1136             if(  report.xbutton.state & ControlMask )
1137               pick = ProcessButton1Press( argc, argv, pick,
1138               ( report.xbutton.state & ShiftMask) );
1139             else
1140             {
1141               IsDragged = Standard_True;
1142               xx1 = X_ButtonPress;
1143               yy1 = Y_ButtonPress;
1144               DragFirst = Standard_True;
1145             }
1146           else if ( report.xbutton.button == Button3 )
1147             // Start rotation
1148             ProcessButton3Press();
1149         }
1150         break;
1151       case ButtonRelease:
1152         {
1153           //    cout<<"relachement du bouton "<<(report.xbutton.button==3 ? "3": "on s'en fout") <<endl;
1154           //    cout << IsDragged << endl;
1155           //    cout << DragFirst << endl;
1156
1157           if( IsDragged )
1158           {
1159             if( !DragFirst )
1160             {
1161               Aspect_Handle aWindow = VT_GetWindow()->XWindow();
1162               GC gc = XCreateGC( display, aWindow, 0, 0 );
1163               //  XSetFunction( display, gc, GXinvert );
1164               XDrawRectangle( display, aWindow, gc, min( xx1, xx2 ), min( yy1, yy2 ), abs( xx2-xx1 ), abs( yy2-yy1 ) );
1165             }
1166
1167             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
1168             if( aContext.IsNull() )
1169             {
1170               cout << "The context is null. Please use vinit before createmesh" << endl;
1171               return 0;
1172             }
1173
1174             Standard_Boolean ShiftPressed = ( report.xbutton.state & ShiftMask );
1175             if( report.xbutton.button==1 )
1176               if( DragFirst )
1177                 if( ShiftPressed )
1178                 {
1179                   aContext->ShiftSelect();
1180                   //                   cout << "shift select" << endl;
1181                 }
1182                 else
1183                 {
1184                   aContext->Select();
1185                   //                   cout << "select" << endl;
1186                 }
1187               else
1188                 if( ShiftPressed )
1189                 {
1190                   aContext->ShiftSelect( min( xx1, xx2 ), min( yy1, yy2 ),
1191                     max( xx1, xx2 ), max( yy1, yy2 ),
1192                     ViewerTest::CurrentView());
1193                   //                   cout << "shift select" << endl;
1194                 }
1195                 else
1196                 {
1197                   aContext->Select( min( xx1, xx2 ), min( yy1, yy2 ),
1198                     max( xx1, xx2 ), max( yy1, yy2 ),
1199                     ViewerTest::CurrentView() );
1200                   //                   cout << "select" << endl;
1201                 }
1202             else
1203               ProcessButtonRelease();
1204
1205             IsDragged = Standard_False;
1206           }
1207           else
1208             ProcessButtonRelease();
1209         }
1210         break;
1211       case MotionNotify:
1212         {
1213           //    XEvent dummy;
1214
1215           X_Motion = report.xmotion.x;
1216           Y_Motion = report.xmotion.y;
1217
1218           if( IsDragged )
1219           {
1220             Aspect_Handle aWindow = VT_GetWindow()->XWindow();
1221             GC gc = XCreateGC( display, aWindow, 0, 0 );
1222             XSetFunction( display, gc, GXinvert );
1223
1224             if( !DragFirst )
1225               XDrawRectangle( display, aWindow, gc, min( xx1, xx2 ), min( yy1, yy2 ), abs( xx2-xx1 ), abs( yy2-yy1 ) );
1226
1227             xx2 = X_Motion;
1228             yy2 = Y_Motion;
1229             DragFirst = Standard_False;
1230
1231             //cout << "draw rect : " << xx2 << ", " << yy2 << endl;
1232             XDrawRectangle( display, aWindow, gc, min( xx1, xx2 ), min( yy1, yy2 ), abs( xx2-xx1 ), abs( yy2-yy1 ) );
1233           }
1234           else
1235           {
1236
1237             //cout << "MotionNotify " << X_Motion << "," << Y_Motion << endl;
1238
1239             // remove all the ButtonMotionMask
1240             while( XCheckMaskEvent( display, ButtonMotionMask, &report) ) ;
1241
1242             if ( ZClipIsOn && report.xmotion.state & ShiftMask ) {
1243               if ( Abs(X_Motion - X_ButtonPress) > 2 ) {
1244
1245                 Quantity_Length VDX, VDY;
1246
1247                 ViewerTest::CurrentView()->Size(VDX,VDY);
1248                 Standard_Real VDZ =0 ;
1249                 VDZ = ViewerTest::CurrentView()->ZSize();
1250
1251                 //          printf("%lf,%lf,%lf\n", VDX, VDY, VDZ);
1252                 printf("%f,%f,%f\n", VDX, VDY, VDZ);
1253
1254                 Quantity_Length dx = 0 ;
1255                 dx = ViewerTest::CurrentView()->Convert(X_Motion - X_ButtonPress);
1256
1257                 cout << dx << endl;
1258
1259                 dx = dx / VDX * VDZ;
1260
1261                 cout << dx << endl;
1262
1263                 // Front = Depth + width/2.
1264                 //ViewerTest::CurrentView()->SetZClippingDepth(dx);
1265                 //ViewerTest::CurrentView()->SetZClippingWidth(0.);
1266
1267                 ViewerTest::CurrentView()->Redraw();
1268               }
1269             }
1270
1271             if ( report.xmotion.state & ControlMask ) {
1272               if ( report.xmotion.state & Button1Mask ) {
1273                 ProcessControlButton1Motion();
1274               }
1275               else if ( report.xmotion.state & Button2Mask ) {
1276                 ProcessControlButton2Motion();
1277               }
1278               else if ( report.xmotion.state & Button3Mask ) {
1279                 ProcessControlButton3Motion();
1280               }
1281             }
1282             else {
1283               ProcessMotion();
1284             }
1285           }
1286         }
1287         break;
1288 }
1289
1290
1291 return pick;
1292 }
1293
1294 //==============================================================================
1295 //function : VProcessEvents
1296 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
1297 //       event in the Viewer window
1298 //==============================================================================
1299
1300 static void VProcessEvents(ClientData,int)
1301 {
1302   //cout << "VProcessEvents" << endl;
1303
1304   // test for X Event
1305   while (XPending(display)) {
1306     ViewerMainLoop( 0, NULL);
1307   }
1308 }
1309 #endif
1310
1311 //==============================================================================
1312 //function : OSWindowSetup
1313 //purpose  : Setup for the X11 window to be able to cath the event
1314 //==============================================================================
1315
1316
1317 static void OSWindowSetup()
1318 {
1319 #ifndef WNT
1320   // X11
1321
1322   Window  window   = VT_GetWindow()->XWindow();
1323
1324   Standard_Address theDisplay = GetG3dDevice()->XDisplay();
1325   display = (Display * ) theDisplay;
1326   //  display = (Display *)GetG3dDevice()->XDisplay();
1327
1328   XSynchronize(display, 1);
1329
1330   VT_GetWindow()->Map();
1331
1332   // X11 : For keyboard on SUN
1333   XWMHints wmhints;
1334   wmhints.flags = InputHint;
1335   wmhints.input = 1;
1336
1337   XSetWMHints( display, window, &wmhints);
1338
1339   XSelectInput( display, window,  ExposureMask | KeyPressMask |
1340     ButtonPressMask | ButtonReleaseMask |
1341     StructureNotifyMask |
1342     PointerMotionMask |
1343     Button1MotionMask | Button2MotionMask |
1344     Button3MotionMask
1345     );
1346
1347   XSynchronize(display, 0);
1348
1349 #else
1350   // WNT
1351 #endif
1352
1353 }
1354
1355
1356 //==============================================================================
1357 //function : VFit
1358
1359 //purpose  : Fitall, no DRAW arguments
1360 //Draw arg : No args
1361 //==============================================================================
1362
1363 static int VFit(Draw_Interpretor& , Standard_Integer , const char** )
1364 {
1365   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1366   Handle(NIS_View) V = Handle(NIS_View)::DownCast(aView);
1367   if (V.IsNull() == Standard_False) {
1368     V->FitAll3d();
1369   } else if (aView.IsNull() == Standard_False) {
1370     aView->FitAll();
1371   }
1372   return 0;
1373 }
1374
1375 //==============================================================================
1376 //function : VZFit
1377 //purpose  : ZFitall, no DRAW arguments
1378 //Draw arg : No args
1379 //==============================================================================
1380
1381 static int VZFit(Draw_Interpretor& , Standard_Integer , const char** )
1382 {
1383   Handle(V3d_View) V = ViewerTest::CurrentView();
1384   if ( !V.IsNull() ) V->ZFitAll(); return 0; }
1385
1386
1387 static int VRepaint(Draw_Interpretor& , Standard_Integer , const char** )
1388 {
1389   Handle(V3d_View) V = ViewerTest::CurrentView();
1390   if ( !V.IsNull() ) V->Redraw(); return 0;
1391 }
1392
1393
1394 //==============================================================================
1395 //function : VClear
1396 //purpose  : Remove all the object from the viewer
1397 //Draw arg : No args
1398 //==============================================================================
1399
1400 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
1401 {
1402   Handle(V3d_View) V = ViewerTest::CurrentView();
1403   if(!V.IsNull())
1404     ViewerTest::Clear();
1405   return 0;
1406 }
1407
1408 //==============================================================================
1409 //function : VPick
1410 //purpose  :
1411 //==============================================================================
1412
1413 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1414 { if (ViewerTest::CurrentView().IsNull() ) return 1;
1415
1416 if ( argc < 4 ) {
1417   di << argv[0] << "Invalid number of arguments" << "\n";
1418   return 1;
1419 }
1420
1421 while (ViewerMainLoop( argc, argv)) {
1422 }
1423
1424 return 0;
1425 }
1426
1427
1428
1429 //==============================================================================
1430 //function : InitViewerTest
1431 //purpose  : initialisation de toutes les variables static de  ViewerTest (dp)
1432 //==============================================================================
1433
1434 void ViewerTest_InitViewerTest (const Handle(AIS_InteractiveContext)& context)
1435 {
1436   Handle(V3d_Viewer) viewer = context->CurrentViewer();
1437   ViewerTest::SetAISContext(context);
1438   viewer->InitActiveViews();
1439   Handle(V3d_View) view = viewer->ActiveView();
1440   if (viewer->MoreActiveViews()) ViewerTest::CurrentView(view);
1441   ViewerTest::ResetEventManager();
1442   Handle(Aspect_GraphicDevice) device = viewer->Device();
1443   Handle(Aspect_Window) window = view->Window();
1444 #ifndef WNT
1445   // X11
1446   VT_GetWindow() = Handle(Xw_Window)::DownCast(window);
1447   GetG3dDevice() = Handle(Graphic3d_GraphicDevice)::DownCast(device);
1448   OSWindowSetup();
1449   static int first = 1;
1450   if ( first ) {
1451 #if TCL_MAJOR_VERSION  < 8
1452     Tk_CreateFileHandler((void*)ConnectionNumber(display),
1453       TK_READABLE, VProcessEvents, (ClientData) 0);
1454 #else
1455     Tk_CreateFileHandler(ConnectionNumber(display),
1456       TK_READABLE, VProcessEvents, (ClientData) 0);
1457 #endif
1458     first = 0;
1459   }
1460 #endif
1461 }
1462
1463
1464 //==============================================================================
1465 //function : VSetBg
1466 //purpose  : Load image as background
1467 //==============================================================================
1468
1469 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1470 {
1471   if (argc < 2 || argc > 3)
1472   {
1473     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background" << "\n";
1474     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE" << "\n";
1475     return 1;
1476   }
1477
1478   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
1479   if(AISContext.IsNull())
1480   {
1481     di << "use 'vinit' command before " << argv[0] << "\n";
1482     return 1;
1483   }
1484
1485   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
1486   if (argc == 3)
1487   {
1488     const char* szType = argv[2];
1489     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
1490     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
1491     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
1492     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
1493     else
1494     {
1495       di << "Wrong fill type : " << szType << "\n";
1496       di << "Must be one of CENTERED, TILED, STRETCH, NONE" << "\n";
1497       return 1;
1498     }
1499   }
1500
1501   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1502   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
1503
1504   return 0;
1505 }
1506
1507 //==============================================================================
1508 //function : VSetBgMode
1509 //purpose  : Change background image fill type
1510 //==============================================================================
1511
1512 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1513 {
1514   if (argc != 2)
1515   {
1516     di << "Usage : " << argv[0] << " filltype : Change background image mode" << "\n";
1517     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE" << "\n";
1518     return 1;
1519   }
1520
1521   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
1522   if(AISContext.IsNull())
1523   {
1524     di << "use 'vinit' command before " << argv[0] << "\n";
1525     return 1;
1526   }
1527
1528   Aspect_FillMethod aFillType;
1529   if (argc == 2)
1530   {
1531     const char* szType = argv[1];
1532     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
1533     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
1534     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
1535     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
1536     else
1537     {
1538       di << "Wrong fill type : " << szType << "\n";
1539       di << "Must be one of CENTERED, TILED, STRETCH, NONE" << "\n";
1540       return 1;
1541     }
1542   }
1543
1544   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1545   V3dView->SetBgImageStyle(aFillType, Standard_True);
1546
1547   return 0;
1548 }
1549
1550 //==============================================================================
1551 //function : VSetGradientBg
1552 //purpose  : Mount gradient background
1553 //==============================================================================
1554 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1555 {
1556   if (argc != 8 )
1557   {
1558     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background" << "\n";
1559     di << "R1,G1,B1,R2,G2,B2 = [0..255]" << "\n";
1560     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2" << "\n";
1561     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4" << "\n";
1562     return 1;
1563   }
1564
1565   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
1566   if(AISContext.IsNull())
1567   {
1568     di << "use 'vinit' command before " << argv[0] << "\n";
1569     return 1;
1570   }
1571   if (argc == 8)
1572   {
1573
1574     Standard_Real R1 = atof(argv[1])/255.;
1575     Standard_Real G1 = atof(argv[2])/255.;
1576     Standard_Real B1 = atof(argv[3])/255.;
1577     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
1578
1579     Standard_Real R2 = atof(argv[4])/255.;
1580     Standard_Real G2 = atof(argv[5])/255.;
1581     Standard_Real B2 = atof(argv[6])/255.;
1582
1583     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
1584     int aType = atoi(argv[7]);
1585     if( aType < 0 || aType > 8 )
1586     {
1587       di << "Wrong fill type " << "\n";
1588       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2" << "\n";
1589       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4" << "\n";
1590       return 1;
1591     }
1592
1593     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
1594
1595     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1596     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
1597   }
1598
1599   return 0;
1600 }
1601
1602 //==============================================================================
1603 //function : VSetGradientBgMode
1604 //purpose  : Change gradient background fill style
1605 //==============================================================================
1606 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1607 {
1608   if (argc != 2 )
1609   {
1610     di << "Usage : " << argv[0] << " Type : Change gradient background fill type" << "\n";
1611     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2" << "\n";
1612     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4" << "\n";
1613     return 1;
1614   }
1615
1616   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
1617   if(AISContext.IsNull())
1618   {
1619     di << "use 'vinit' command before " << argv[0] << "\n";
1620     return 1;
1621   }
1622   if (argc == 2)
1623   {
1624     int aType = atoi(argv[1]);
1625     if( aType < 0 || aType > 8 )
1626     {
1627       di << "Wrong fill type " << "\n";
1628       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2" << "\n";
1629       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4" << "\n";
1630       return 1;
1631     }
1632
1633     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
1634
1635     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1636     V3dView->SetBgGradientStyle( aMethod, 1 );
1637   }
1638
1639   return 0;
1640 }
1641
1642 //==============================================================================
1643 //function : VSetColorBg
1644 //purpose  : Set color background
1645 //==============================================================================
1646 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1647 {
1648   if (argc != 4 )
1649   {
1650     di << "Usage : " << argv[0] << " R G B : Set color background" << "\n";
1651     di << "R,G,B = [0..255]" << "\n";
1652     return 1;
1653   }
1654
1655   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
1656   if(AISContext.IsNull())
1657   {
1658     di << "use 'vinit' command before " << argv[0] << "\n";
1659     return 1;
1660   }
1661   if (argc == 4)
1662   {
1663
1664     Standard_Real R = atof(argv[1])/255.;
1665     Standard_Real G = atof(argv[2])/255.;
1666     Standard_Real B = atof(argv[3])/255.;
1667     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
1668
1669     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1670     V3dView->SetBackgroundColor( aColor );
1671     V3dView->Update();
1672   }
1673
1674   return 0;
1675 }
1676
1677 //==============================================================================
1678 //function : VScale
1679 //purpose  : View Scaling
1680 //==============================================================================
1681
1682 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1683 {
1684   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1685   if ( V3dView.IsNull() ) return 1;
1686
1687   if ( argc != 4 ) {
1688     di << argv[0] << "Invalid number of arguments" << "\n";
1689     return 1;
1690   }
1691   V3dView->SetAxialScale( atof(argv[1]),  atof(argv[2]),  atof(argv[3]) );
1692   return 0;
1693 }
1694 //==============================================================================
1695 //function : VTestZBuffTrihedron
1696 //purpose  : Displays a V3d_ZBUFFER'ed or V3d_WIREFRAME'd trihedron
1697 //==============================================================================
1698
1699 static int VTestZBuffTrihedron(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1700 {
1701   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1702   if ( V3dView.IsNull() ) return 1;
1703
1704   V3dView->ZBufferTriedronSetup();
1705
1706   if ( argc == 1 ) {
1707     // Set up default trihedron parameters
1708     V3dView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.1, V3d_ZBUFFER );
1709   } else
1710   if ( argc == 7 )
1711   {
1712     Aspect_TypeOfTriedronPosition aPosition = Aspect_TOTP_LEFT_LOWER;
1713     const char* aPosType = argv[1];
1714
1715     if ( strcmp(aPosType, "center") == 0 )
1716     {
1717       aPosition = Aspect_TOTP_CENTER;
1718     } else
1719     if (strcmp(aPosType, "left_lower") == 0)
1720     {
1721       aPosition = Aspect_TOTP_LEFT_LOWER;
1722     } else
1723     if (strcmp(aPosType, "left_upper") == 0)
1724     {
1725       aPosition = Aspect_TOTP_LEFT_UPPER;
1726     } else
1727     if (strcmp(aPosType, "right_lower") == 0)
1728     {
1729       aPosition = Aspect_TOTP_RIGHT_LOWER;
1730     } else
1731     if (strcmp(aPosType, "right_upper") == 0)
1732     {
1733       aPosition = Aspect_TOTP_RIGHT_UPPER;
1734     } else
1735     {
1736       di << argv[1] << " Invalid type of alignment"  << "\n";
1737       di << "Must be one of [ center, left_lower,"   << "\n";
1738       di << "left_upper, right_lower, right_upper ]" << "\n";
1739       return 1;
1740     }
1741
1742     Standard_Real R = atof(argv[2])/255.;
1743     Standard_Real G = atof(argv[3])/255.;
1744     Standard_Real B = atof(argv[4])/255.;
1745     Quantity_Color aColor(R, G, B, Quantity_TOC_RGB);
1746
1747     Standard_Real aScale = atof(argv[5]);
1748
1749     if( aScale <= 0.0 )
1750     {
1751       di << argv[5] << " Invalid value. Must be > 0" << "\n";
1752       return 1;
1753     }
1754
1755     V3d_TypeOfVisualization aPresentation = V3d_ZBUFFER;
1756     const char* aPresType = argv[6];
1757
1758     if ( strcmp(aPresType, "wireframe") == 0 )
1759     {
1760       aPresentation = V3d_WIREFRAME;
1761     } else
1762     if (strcmp(aPresType, "zbuffer") == 0)
1763     {
1764       aPresentation = V3d_ZBUFFER;
1765     } else
1766     {
1767       di << argv[6] << " Invalid type of visualization" << "\n";
1768       di << "Must be one of [ wireframe, zbuffer ]"     << "\n";
1769       return 1;
1770     }
1771
1772     V3dView->TriedronDisplay( aPosition, aColor.Name(), aScale, aPresentation );
1773
1774   } else
1775   {
1776     di << argv[0] << " Invalid number of arguments" << "\n";
1777     return 1;
1778   }
1779
1780   V3dView->ZFitAll();
1781
1782   return 0;
1783 }
1784
1785 //==============================================================================
1786 //function : VRotate
1787 //purpose  : Camera Rotating
1788 //==============================================================================
1789
1790 static int VRotate( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
1791   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1792   if ( V3dView.IsNull() ) {
1793     return 1;
1794   }
1795
1796   if ( argc == 4 ) {
1797     V3dView->Rotate( atof(argv[1]), atof(argv[2]), atof(argv[3]) );
1798     return 0;
1799   } else if ( argc == 7 ) {
1800     V3dView->Rotate( atof(argv[1]), atof(argv[2]), atof(argv[3]), atof(argv[4]), atof(argv[5]), atof(argv[6]) );
1801     return 0;
1802   } else {
1803     di << argv[0] << " Invalid number of arguments" << "\n";
1804     return 1;
1805   }
1806 }
1807
1808 //==============================================================================
1809 //function : VZoom
1810 //purpose  : View zoom in / out (relative to current zoom)
1811 //==============================================================================
1812
1813 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
1814   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1815   if ( V3dView.IsNull() ) {
1816     return 1;
1817   }
1818
1819   if ( argc == 2 ) {
1820     Standard_Real coef = atof(argv[1]);
1821     if ( coef <= 0.0 ) {
1822       di << argv[1] << "Invalid value" << "\n";
1823       return 1;
1824     }
1825     V3dView->SetZoom( atof(argv[1]) );
1826     return 0;
1827   } else {
1828     di << argv[0] << " Invalid number of arguments" << "\n";
1829     return 1;
1830   }
1831 }
1832
1833 //==============================================================================
1834 //function : VPan
1835 //purpose  : View panning (in pixels)
1836 //==============================================================================
1837
1838 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
1839   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1840   if ( V3dView.IsNull() ) return 1;
1841
1842   if ( argc == 3 ) {
1843     V3dView->Pan( atoi(argv[1]), atoi(argv[2]) );
1844     return 0;
1845   } else {
1846     di << argv[0] << " Invalid number of arguments" << "\n";
1847     return 1;
1848   }
1849 }
1850
1851
1852 //==============================================================================
1853 //function : VExport
1854 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
1855 //==============================================================================
1856
1857 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1858 {
1859   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
1860   if (V3dView.IsNull())
1861     return 1;
1862
1863   if (argc == 1)
1864   {
1865     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
1866     return 1;
1867   }
1868
1869   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
1870   TCollection_AsciiString aFormatStr;
1871
1872   TCollection_AsciiString aFileName (argv[1]);
1873   Standard_Integer aLen = aFileName.Length();
1874
1875   if (argc > 2)
1876   {
1877     aFormatStr = TCollection_AsciiString (argv[2]);
1878   }
1879   else if (aLen >= 4)
1880   {
1881     if (aFileName.Value (aLen - 2) == '.')
1882     {
1883       aFormatStr = aFileName.SubString (aLen - 1, aLen);
1884     }
1885     else if (aFileName.Value (aLen - 3) == '.')
1886     {
1887       aFormatStr = aFileName.SubString (aLen - 2, aLen);
1888     }
1889     else
1890     {
1891       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
1892       return 1;
1893     }
1894   }
1895   else
1896   {
1897     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
1898     return 1;
1899   }
1900
1901   aFormatStr.UpperCase();
1902   if (aFormatStr == "PS")
1903     anExpFormat = Graphic3d_EF_PostScript;
1904   else if (aFormatStr == "EPS")
1905     anExpFormat = Graphic3d_EF_EnhPostScript;
1906   else if (aFormatStr == "TEX")
1907     anExpFormat = Graphic3d_EF_TEX;
1908   else if (aFormatStr == "PDF")
1909     anExpFormat = Graphic3d_EF_PDF;
1910   else if (aFormatStr == "SVG")
1911     anExpFormat = Graphic3d_EF_SVG;
1912   else if (aFormatStr == "PGF")
1913     anExpFormat = Graphic3d_EF_PGF;
1914   else if (aFormatStr == "EMF")
1915     anExpFormat = Graphic3d_EF_EMF;
1916   else
1917   {
1918     std::cout << "Invalid export format '" << aFormatStr << "'\n";
1919     return 1;
1920   }
1921
1922   if (!V3dView->View()->Export (argv[1], anExpFormat))
1923   {
1924     std::cout << "Export failed!\n";
1925     return 1;
1926   }
1927   return 0;
1928 }
1929
1930 //==============================================================================
1931 //function : VColorScale
1932 //purpose  : representation color scale
1933 //==============================================================================
1934 #include <V3d_ColorScale.hxx>
1935
1936 static int VColorScale (Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
1937 {
1938   if ( argc != 1 && argc != 4 && argc != 5 && argc != 6 && argc != 8 )
1939   {
1940     di << "Usage : " << argv[0] << " [RangeMin = 0 RangeMax = 100 Intervals = 10 HeightFont = 16 Position = Right X = 0 Y = 0]  " << "\n";
1941     return 1;
1942   }
1943
1944   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1945   if(aContext.IsNull()) {
1946     di << argv[0] << " ERROR : use 'vinit' command before " << "\n";
1947     return -1;
1948   }
1949
1950   Standard_Real minRange = 0. , maxRange = 100. ;
1951
1952   Standard_Integer numIntervals = 10 ;
1953   Standard_Integer textHeight = 16;
1954   Aspect_TypeOfColorScalePosition position = Aspect_TOCSP_RIGHT;
1955   Standard_Real X = 0., Y = 0. ;
1956
1957   if ( argc < 9 )
1958   {
1959      if( argc > 3 )
1960      {
1961        minRange = atof( argv[1] );
1962        maxRange = atof( argv[2] );
1963        numIntervals = atoi( argv[3] );
1964      }
1965      if ( argc > 4 )
1966        textHeight = atoi( argv[4] );
1967      if ( argc > 5 )
1968        position = (Aspect_TypeOfColorScalePosition)atoi( argv[5] );
1969      if ( argc > 7 )
1970      {
1971        X = atof( argv[6] );
1972        Y = atof( argv[7] );
1973      }
1974   }
1975   Handle(V3d_View) curView = ViewerTest::CurrentView( );
1976   if ( curView.IsNull( ) )
1977     return 1;
1978   Handle(Aspect_ColorScale) aCSV = curView->ColorScale( );
1979   Handle(V3d_ColorScale) aCS = ( Handle( V3d_ColorScale )::DownCast( aCSV ) );
1980   if( ! aCS.IsNull( ) )
1981   {
1982     aCS->SetPosition( X , Y );
1983     aCS->SetHeight( 0.95) ;
1984     aCS->SetTextHeight( textHeight );
1985     aCS->SetRange( minRange , maxRange );
1986     aCS->SetNumberOfIntervals( numIntervals );
1987     aCS->SetLabelPosition( position );
1988     if( !curView->ColorScaleIsDisplayed() )
1989       curView->ColorScaleDisplay( );
1990   }
1991   return 0;
1992 }
1993
1994 //==============================================================================
1995 //function : VGraduatedTrihedron
1996 //purpose  : Displays a graduated trihedron
1997 //==============================================================================
1998
1999 static void AddMultibyteString (TCollection_ExtendedString &name, const char *arg)
2000 {
2001   const char *str = arg;
2002   while (*str)
2003   {
2004     unsigned short c1 = *str++;
2005     unsigned short c2 = *str++;
2006     if (!c1 || !c2) break;
2007     name += (Standard_ExtCharacter)((c1 << 8) | c2);
2008   }
2009 }
2010
2011 static int VGraduatedTrihedron(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2012 {
2013   // Check arguments
2014   if (argc != 2 && argc < 5)
2015   {
2016     di<<"Error: "<<argv[0]<<" - invalid number of arguments\n";
2017     di<<"Usage: type help "<<argv[0]<<"\n";
2018     return 1; //TCL_ERROR
2019   }
2020
2021   Handle(V3d_View) aV3dView = ViewerTest::CurrentView();
2022
2023   // Create 3D view if it doesn't exist
2024   if ( aV3dView.IsNull() )
2025   {
2026     ViewerTest::ViewerInit(); 
2027     aV3dView = ViewerTest::CurrentView();
2028     if( aV3dView.IsNull() )
2029     {
2030       di << "Error: Cannot create a 3D view\n";
2031       return 1; //TCL_ERROR
2032     }
2033   }
2034
2035   // Erase (==0) or display (!=0)
2036   const int display = atoi(argv[1]);
2037
2038   if (display)
2039   {
2040     // Text font
2041     TCollection_AsciiString font;
2042     if (argc < 6)
2043       font.AssignCat("Courier");
2044     else
2045       font.AssignCat(argv[5]);
2046
2047     // Text is multibyte
2048     const Standard_Boolean isMultibyte = (argc < 7)? Standard_False : (atoi(argv[6]) != 0);
2049
2050     // Set axis names
2051     TCollection_ExtendedString xname, yname, zname;
2052     if (argc >= 5)
2053     {
2054       if (isMultibyte)
2055       {
2056         AddMultibyteString(xname, argv[2]);
2057         AddMultibyteString(yname, argv[3]);
2058         AddMultibyteString(zname, argv[4]);
2059       }
2060       else
2061       {
2062         xname += argv[2];
2063         yname += argv[3];
2064         zname += argv[4];
2065       }
2066     }
2067     else
2068     {
2069       xname += "X (mm)";
2070       yname += "Y (mm)";
2071       zname += "Z (mm)";
2072     }
2073
2074     aV3dView->GraduatedTrihedronDisplay(xname, yname, zname,
2075                                         Standard_True/*xdrawname*/, Standard_True/*ydrawname*/, Standard_True/*zdrawname*/,
2076                                         Standard_True/*xdrawvalues*/, Standard_True/*ydrawvalues*/, Standard_True/*zdrawvalues*/,
2077                                         Standard_True/*drawgrid*/,
2078                                         Standard_True/*drawaxes*/,
2079                                         5/*nbx*/, 5/*nby*/, 5/*nbz*/,
2080                                         10/*xoffset*/, 10/*yoffset*/, 10/*zoffset*/,
2081                                         30/*xaxisoffset*/, 30/*yaxisoffset*/, 30/*zaxisoffset*/,
2082                                         Standard_True/*xdrawtickmarks*/, Standard_True/*ydrawtickmarks*/, Standard_True/*zdrawtickmarks*/,
2083                                         10/*xtickmarklength*/, 10/*ytickmarklength*/, 10/*ztickmarklength*/,
2084                                         Quantity_NOC_WHITE/*gridcolor*/,
2085                                         Quantity_NOC_RED/*xnamecolor*/,Quantity_NOC_GREEN/*ynamecolor*/,Quantity_NOC_BLUE1/*znamecolor*/,
2086                                         Quantity_NOC_RED/*xcolor*/,Quantity_NOC_GREEN/*ycolor*/,Quantity_NOC_BLUE1/*zcolor*/,font);
2087   }
2088   else
2089     aV3dView->GraduatedTrihedronErase();
2090
2091   ViewerTest::GetAISContext()->UpdateCurrentViewer();
2092   aV3dView->Redraw();
2093
2094   return 0;
2095 }
2096
2097 //==============================================================================
2098 //function : VPrintView
2099 //purpose  : Test printing algorithm, print the view to image file with given
2100 //           width and height. Printing implemented only for WNT.
2101 //==============================================================================
2102 static int VPrintView (Draw_Interpretor& di, Standard_Integer argc, 
2103                        const char** argv)
2104 {
2105 #ifndef WNT
2106   di << "Printing implemented only for wnt!\n";
2107   return 1;
2108 #else
2109
2110   Handle(AIS_InteractiveContext) aContextAIS = NULL;
2111   Handle(V3d_View) aView = NULL;
2112   aContextAIS = ViewerTest::GetAISContext();
2113   if (!aContextAIS.IsNull())
2114   {
2115     const Handle(V3d_Viewer)& Vwr = aContextAIS->CurrentViewer();
2116     Vwr->InitActiveViews();
2117     if(Vwr->MoreActiveViews())
2118       aView = Vwr->ActiveView();
2119   }
2120
2121   // check for errors
2122   if (aView.IsNull())
2123   {
2124     di << "Call vinit before!\n";
2125     return 1;
2126   }
2127   else if (argc < 4)
2128   {
2129     di << "Use: " << argv[0];
2130     di << " width height filename [print algo=0]\n";
2131     di << "width, height of the intermediate buffer for operation\n";
2132     di << "algo : {0|1}\n";
2133     di << "        0 - stretch algorithm\n";
2134     di << "        1 - tile algorithm\n";
2135     di << "test printing algorithms into an intermediate buffer\n";
2136     di << "with saving output to an image file\n";
2137     return 1;
2138   }
2139
2140   // get the input params
2141   Standard_Integer aWidth  = atoi (argv[1]);
2142   Standard_Integer aHeight = atoi (argv[2]);
2143   Standard_Integer aMode   = 0;
2144   TCollection_AsciiString aFileName = TCollection_AsciiString (argv[3]);
2145   if (argc==5)
2146     aMode = atoi (argv[4]);
2147
2148   // check the input parameters
2149   if (aWidth <= 0 || aHeight <= 0)
2150   {
2151     di << "Width and height must be positive values!\n";
2152     return 1;
2153   }
2154   if (aMode != 0 && aMode != 1)
2155     aMode = 0;
2156
2157   // define compatible bitmap
2158   HDC anDC = CreateCompatibleDC(0);
2159   BITMAPINFO aBitmapData;
2160   memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
2161   aBitmapData.bmiHeader.biSize          = sizeof (BITMAPINFOHEADER);
2162   aBitmapData.bmiHeader.biWidth         = aWidth ;
2163   aBitmapData.bmiHeader.biHeight        = aHeight;
2164   aBitmapData.bmiHeader.biPlanes        = 1;
2165   aBitmapData.bmiHeader.biBitCount      = 24;
2166   aBitmapData.bmiHeader.biXPelsPerMeter = 0;
2167   aBitmapData.bmiHeader.biYPelsPerMeter = 0;
2168   aBitmapData.bmiHeader.biClrUsed       = 0;
2169   aBitmapData.bmiHeader.biClrImportant  = 0;
2170   aBitmapData.bmiHeader.biCompression   = BI_RGB;
2171   aBitmapData.bmiHeader.biSizeImage     = 0;
2172
2173   // Create Device Independent Bitmap
2174   void* aBitsOut = NULL;
2175   HBITMAP aMemoryBitmap = CreateDIBSection (anDC, &aBitmapData, DIB_RGB_COLORS,
2176                                             &aBitsOut, NULL, 0);
2177   HGDIOBJ anOldBitmap   = SelectObject(anDC, aMemoryBitmap);
2178
2179   Standard_Boolean isSaved = Standard_False, isPrinted = Standard_False;
2180   if (aBitsOut != NULL)
2181   {    
2182     if (aMode == 0)
2183       isPrinted = aView->Print(anDC,1,1,0,Aspect_PA_STRETCH);
2184     else
2185       isPrinted = aView->Print(anDC,1,1,0,Aspect_PA_TILE);
2186
2187     // succesfully printed into an intermediate buffer
2188     if (isPrinted)
2189     {
2190       Image_PixMap aWrapper;
2191       aWrapper.InitWrapper (Image_PixMap::ImgBGR, (Standard_Byte* )aBitsOut, aWidth, aHeight, aWidth * 3 + aWidth % 4);
2192       aWrapper.SetTopDown (false);
2193
2194       Image_AlienPixMap anImageBitmap;
2195       anImageBitmap.InitCopy (aWrapper);
2196       isSaved = anImageBitmap.Save (aFileName);
2197     }
2198     else
2199     {
2200       di << "Print operation failed due to printing errors or\n";
2201       di << "insufficient memory available\n";
2202       di << "Please, try to use smaller dimensions for this test\n";
2203       di << "command, as it allocates intermediate buffer for storing\n";
2204       di << "the result\n";
2205     }
2206   }
2207   else
2208   {
2209     di << "Can't allocate memory for intermediate buffer\n";
2210     di << "Please use smaller dimensions\n";
2211   }
2212
2213   if (aMemoryBitmap)
2214   {
2215     SelectObject (anDC, anOldBitmap);
2216     DeleteObject (aMemoryBitmap);
2217     DeleteDC(anDC);
2218   }
2219
2220   if (!isSaved)
2221   {
2222     di << "Save to file operation failed. This operation may fail\n";
2223     di << "if you don't have enough available memory, then you can\n";
2224     di << "use smaller dimensions for the output file\n";
2225     return 1;
2226   }
2227
2228   return 0;
2229
2230 #endif
2231 }
2232
2233 //==============================================================================
2234 //function : VZLayer
2235 //purpose  : Test z layer operations for v3d viewer
2236 //==============================================================================
2237 static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2238 {
2239   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext ();
2240   if (aContextAIS.IsNull())
2241   {
2242     di << "Call vinit before!\n";
2243     return 1;
2244   }
2245   else if (argc < 2)
2246   {
2247     di << "Use: vzlayer " << argv[0];
2248     di << " add/del/get [id]\n";
2249     di << " add - add new z layer to viewer and print its id\n";
2250     di << " del - del z layer by its id\n";
2251     di << " get - print sequence of z layers in increasing order of their overlay level\n";
2252     di << "id - the layer identificator value defined when removing z layer\n";
2253     return 1;
2254   }
2255
2256   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
2257   if (aViewer.IsNull())
2258   {
2259     di << "No active viewer!\n";
2260     return 1;
2261   }
2262
2263   // perform operation
2264   TCollection_AsciiString anOp = TCollection_AsciiString (argv[1]);
2265   if (anOp == "add")
2266   {
2267     Standard_Integer aNewId;
2268     if (!aViewer->AddZLayer (aNewId))
2269     {
2270       di << "Impossible to add new z layer!\n";
2271       return 1;
2272     }
2273
2274     di << "New z layer added with index: " << aNewId << "\n";
2275   }
2276   else if (anOp == "del")
2277   {
2278     if (argc < 3)
2279     {
2280       di << "Please also provide as argument id of z layer to remove\n";
2281       return 1;
2282     }
2283
2284     Standard_Integer aDelId = atoi (argv[2]);
2285     if (!aViewer->RemoveZLayer (aDelId))
2286     {
2287       di << "Impossible to remove the z layer or invalid id!\n";
2288       return 1;
2289     }
2290
2291     di << "Z layer " << aDelId << " has been removed\n";
2292   }
2293   else if (anOp == "get")
2294   {
2295     TColStd_SequenceOfInteger anIds;
2296     aViewer->GetAllZLayers (anIds);
2297     for (Standard_Integer aSeqIdx = 1; aSeqIdx <= anIds.Length(); aSeqIdx++)
2298     {
2299       di << anIds.Value (aSeqIdx) << " ";
2300     }
2301
2302     di << "\n";
2303   }
2304   else
2305   {
2306     di << "Invalid operation, please use { add / del / get }\n";
2307     return 1;
2308   }
2309
2310   return 0;
2311 }
2312
2313 DEFINE_STANDARD_HANDLE(V3d_TextItem, Visual3d_LayerItem)
2314
2315 // this class provides a presentation of text item in v3d view under-/overlayer
2316 class V3d_TextItem : public Visual3d_LayerItem
2317 {
2318 public:
2319
2320   // CASCADE RTTI
2321   DEFINE_STANDARD_RTTI(V3d_TextItem)
2322
2323   // constructor
2324   Standard_EXPORT V3d_TextItem(const TCollection_AsciiString& theText,
2325                                const Standard_Real theX1,
2326                                const Standard_Real theY1,
2327                                const Standard_Real theHeight,
2328                                const TCollection_AsciiString& theFontName,
2329                                const Quantity_Color& theColor,
2330                                const Quantity_Color& theSubtitleColor,
2331                                const Aspect_TypeOfDisplayText& theTypeOfDisplay,
2332                                const Handle(Visual3d_Layer)& theLayer);
2333
2334   // redraw method
2335   Standard_EXPORT void RedrawLayerPrs();
2336
2337 private:
2338
2339   Standard_Real            myX1;
2340   Standard_Real            myY1;
2341   Standard_Real            myHeight;
2342   TCollection_AsciiString  myText;
2343   TCollection_AsciiString  myFontName;
2344   Quantity_Color           myColor;
2345   Quantity_Color           mySubtitleColor;
2346   Aspect_TypeOfDisplayText myType;
2347   Handle(Visual3d_Layer)   myLayer;
2348
2349 };
2350
2351 IMPLEMENT_STANDARD_HANDLE(V3d_TextItem, Visual3d_LayerItem)
2352 IMPLEMENT_STANDARD_RTTIEXT(V3d_TextItem, Visual3d_LayerItem)
2353
2354 // create and add to display the text item
2355 V3d_TextItem::V3d_TextItem (const TCollection_AsciiString& theText,
2356                             const Standard_Real theX1,
2357                             const Standard_Real theY1,
2358                             const Standard_Real theHeight,
2359                             const TCollection_AsciiString& theFontName,
2360                             const Quantity_Color& theColor,
2361                             const Quantity_Color& theSubtitleColor,
2362                             const Aspect_TypeOfDisplayText& theTypeOfDisplay,
2363                             const Handle(Visual3d_Layer)& theLayer)
2364  : myX1 (theX1), myY1 (theY1),
2365    myText (theText),
2366    myHeight (theHeight),
2367    myLayer (theLayer),
2368    myColor (theColor),
2369    mySubtitleColor (theSubtitleColor),
2370    myType (theTypeOfDisplay),
2371    myFontName (theFontName)
2372 {
2373   if (!myLayer.IsNull ())
2374     myLayer->AddLayerItem (this);
2375 }
2376
2377 // render item
2378 void V3d_TextItem::RedrawLayerPrs ()
2379
2380   if (myLayer.IsNull ())
2381     return;
2382
2383   myLayer->SetColor (myColor);
2384   myLayer->SetTextAttributes (myFontName.ToCString (), myType, mySubtitleColor);
2385   myLayer->DrawText (myText.ToCString (), myX1, myY1, myHeight);
2386 }
2387
2388 DEFINE_STANDARD_HANDLE(V3d_LineItem, Visual3d_LayerItem)
2389
2390 // The Visual3d_LayerItem line item for "vlayerline" command
2391 // it provides a presentation of line with user-defined 
2392 // linewidth, linetype and transparency.
2393 class V3d_LineItem : public Visual3d_LayerItem 
2394 {
2395 public:
2396   // CASCADE RTTI
2397   DEFINE_STANDARD_RTTI(V3d_LineItem) 
2398   
2399   // constructor
2400   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
2401                                Standard_Real X2, Standard_Real Y2,
2402                                V3d_LayerMgrPointer theLayerMgr,
2403                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
2404                                Standard_Real theWidth    = 0.5,
2405                                Standard_Real theTransp   = 1.0);
2406
2407   // redraw method
2408   Standard_EXPORT   void RedrawLayerPrs();
2409
2410 private:
2411
2412   Standard_Real       myX1, myY1, myX2, myY2;
2413   Standard_Real       myWidth;
2414   Standard_Real       myTransparency;
2415   Aspect_TypeOfLine   myType;
2416   V3d_LayerMgrPointer myLayerMgr;
2417 };
2418
2419 IMPLEMENT_STANDARD_HANDLE(V3d_LineItem, Visual3d_LayerItem)
2420 IMPLEMENT_STANDARD_RTTIEXT(V3d_LineItem, Visual3d_LayerItem)
2421
2422 // default constructor for line item
2423 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1, 
2424                            Standard_Real X2, Standard_Real Y2,
2425                            V3d_LayerMgrPointer theLayerMgr,
2426                            Aspect_TypeOfLine theType,
2427                            Standard_Real theWidth,
2428                            Standard_Real theTransp) :
2429   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2), myLayerMgr(theLayerMgr),
2430   myType(theType), myWidth(theWidth), myTransparency(theTransp)
2431 {
2432   if (myLayerMgr && !myLayerMgr->Overlay().IsNull())
2433     myLayerMgr->Overlay()->AddLayerItem (this);
2434 }
2435
2436 // render line
2437 void V3d_LineItem::RedrawLayerPrs ()
2438 {
2439   Handle (Visual3d_Layer) aOverlay;
2440  
2441   if (myLayerMgr)
2442     aOverlay = myLayerMgr->Overlay();
2443
2444   if (!aOverlay.IsNull())
2445   {
2446     Quantity_Color aColor(1.0, 0, 0, Quantity_TOC_RGB);
2447     aOverlay->SetColor(aColor);
2448     aOverlay->SetTransparency((Standard_ShortReal)myTransparency);
2449     aOverlay->SetLineAttributes((Aspect_TypeOfLine)myType, myWidth);
2450     aOverlay->BeginPolyline();
2451     aOverlay->AddVertex(myX1, myY1);
2452     aOverlay->AddVertex(myX2, myY2);
2453     aOverlay->ClosePrimitive();
2454   }
2455 }
2456
2457 //=============================================================================
2458 //function : VLayerLine
2459 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
2460 //         : linewidth, transparency coefficient
2461 //============================================================================
2462 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2463 {
2464   // get the active view
2465   Handle(V3d_View) aView = ViewerTest::CurrentView();
2466   if (aView.IsNull())
2467   {
2468     di << "Call vinit before!\n";
2469     return 1;
2470   }
2471   else if (argc < 5)
2472   {
2473     di << "Use: " << argv[0];
2474     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
2475     di << " linetype : { 0 | 1 | 2 | 3 } \n";
2476     di << "              0 - solid  \n";
2477     di << "              1 - dashed \n";
2478     di << "              2 - dot    \n";
2479     di << "              3 - dashdot\n";
2480     di << " transparency : { 0.0 - 1.0 } \n";
2481     di << "                  0.0 - transparent\n";
2482     di << "                  1.0 - visible    \n";
2483     return 1;
2484   }
2485
2486   // get the input params
2487   Standard_Real X1 = atof(argv[1]);
2488   Standard_Real Y1 = atof(argv[2]);
2489   Standard_Real X2 = atof(argv[3]);
2490   Standard_Real Y2 = atof(argv[4]);
2491
2492   Standard_Real    aWidth = 0.5;
2493   Standard_Integer aType  = 0;
2494   Standard_Real    aTransparency = 1.0;
2495
2496   // has width
2497   if (argc > 5)
2498     aWidth = atof(argv[5]);
2499
2500   // has type
2501   if (argc > 6)
2502      aType = (Standard_Integer) atoi(argv[6]);
2503
2504   // has transparency
2505   if (argc > 7)
2506   {
2507     aTransparency = atof(argv[7]);
2508     if (aTransparency < 0 || aTransparency > 1.0) 
2509       aTransparency = 1.0;
2510   }
2511
2512   // select appropriate line type
2513   Aspect_TypeOfLine aLineType;
2514   switch (aType)
2515   {
2516     case 1:
2517       aLineType = Aspect_TOL_DASH;
2518     break;
2519
2520     case 2:
2521       aLineType = Aspect_TOL_DOT;
2522     break;
2523
2524     case 3:
2525       aLineType = Aspect_TOL_DOTDASH;
2526     break;
2527
2528     default:
2529       aLineType = Aspect_TOL_SOLID;
2530   }
2531
2532   // replace layer manager
2533   Handle(V3d_LayerMgr) aMgr = new V3d_LayerMgr(aView);
2534   aView->SetLayerMgr(aMgr);
2535
2536   // add line item
2537   Handle (V3d_LineItem) anItem = new V3d_LineItem(X1, Y1, X2, Y2, 
2538                                                   aMgr.operator->(),
2539                                                   aLineType, aWidth, 
2540                                                   aTransparency);
2541
2542   // update view
2543   aView->MustBeResized();
2544   aView->Redraw();
2545
2546   return 0;
2547 }
2548
2549 //=======================================================================
2550 //function : VOverlayText
2551 //purpose  : Test text displaying in view overlay
2552 //=======================================================================
2553 static int VOverlayText (Draw_Interpretor& di, Standard_Integer argc, const char**argv)
2554 {
2555   // get the active view
2556   Handle(V3d_View) aView = ViewerTest::CurrentView();
2557   if (aView.IsNull())
2558   {
2559     di << "No active view. Please call vinit.\n";
2560     return 1;
2561   }
2562   else if (argc < 4 || argc > 13)
2563   {
2564     di << "Use: " << argv[0];
2565     di << " text x y [height] [font_name] [text_color: R G B] [displayType]\n";
2566     di << "[background_color: R G B]\n";
2567     di << "  height - pixel height of the text (default=10.0)\n";
2568     di << "  font_name - name of font (default=courier)\n";
2569     di << "  text_color - R G B values of text color (default=255.0 255.0 255.0)\n";
2570     di << "  display_type = {normal/subtitle/decal/blend}, (default=normal)\n";
2571     di << "  background_color- R G B values used for subtitle and decal text\n";
2572     di << "(default=255.0 255.0 255.0)\n";
2573     return 1;
2574   }
2575   
2576   TCollection_AsciiString aText (argv[1]);
2577   Standard_Real aPosX = atof(argv[2]);
2578   Standard_Real aPosY = atof(argv[3]);
2579   Standard_Real aHeight = (argc >= 5) ? atof (argv[4]) : 10.0;
2580
2581   // font name
2582   TCollection_AsciiString aFontName = "Courier";
2583   if (argc >= 6)
2584     aFontName = TCollection_AsciiString (argv[5]);
2585
2586   // text colors
2587   Quantity_Parameter aColorRed   = 1.0;
2588   Quantity_Parameter aColorGreen = 1.0;
2589   Quantity_Parameter aColorBlue  = 1.0;
2590   if (argc >= 9)
2591   {
2592     aColorRed   = atof (argv[6])/255.;
2593     aColorGreen = atof (argv[7])/255.;
2594     aColorBlue  = atof (argv[8])/255.;
2595   }
2596
2597   // display type
2598   TCollection_AsciiString aDispStr;
2599   if (argc >= 10)
2600     aDispStr = TCollection_AsciiString (argv[9]);
2601
2602   Aspect_TypeOfDisplayText aTextType = Aspect_TODT_NORMAL;
2603   if (aDispStr.IsEqual ("subtitle"))
2604     aTextType = Aspect_TODT_SUBTITLE;
2605   else if (aDispStr.IsEqual ("decal"))
2606     aTextType = Aspect_TODT_DEKALE;
2607   else if (aDispStr.IsEqual ("blend"))
2608     aTextType = Aspect_TODT_BLEND;
2609
2610   // subtitle color
2611   Quantity_Parameter aSubRed   = 1.0;
2612   Quantity_Parameter aSubGreen = 1.0;
2613   Quantity_Parameter aSubBlue  = 1.0;
2614   if (argc == 13)
2615   {
2616     aSubRed   = atof (argv[10])/255.;
2617     aSubGreen = atof (argv[11])/255.;
2618     aSubBlue  = atof (argv[12])/255.;
2619   }
2620
2621   // check fo current overlay
2622   Handle(Visual3d_Layer) anOverlay = aView->Viewer()->Viewer()->OverLayer ();
2623   if (anOverlay.IsNull ())
2624   {
2625     Handle(V3d_LayerMgr) aMgr = new V3d_LayerMgr (aView);
2626     anOverlay = aMgr->Overlay ();
2627     aView->SetLayerMgr (aMgr);
2628   }
2629
2630   Quantity_Color aTextColor (aColorRed, aColorGreen, 
2631     aColorBlue, Quantity_TOC_RGB);
2632   Quantity_Color aSubtColor (aSubRed, aSubGreen, 
2633     aSubBlue, Quantity_TOC_RGB);
2634
2635   // add text item
2636   Handle(V3d_TextItem) anItem = new V3d_TextItem (aText, aPosX, aPosY,
2637     aHeight, aFontName, aTextColor, aSubtColor, aTextType, anOverlay);
2638
2639   // update view
2640   aView->MustBeResized();
2641   aView->Redraw();
2642
2643   return 0;
2644 }
2645
2646 //==============================================================================
2647 //function : VGrid
2648 //purpose  :
2649 //==============================================================================
2650
2651 static int VGrid (Draw_Interpretor& theDI,
2652                   Standard_Integer  theArgNb,
2653                   const char**      theArgVec)
2654 {
2655   // get the active view
2656   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
2657   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
2658   if (aView.IsNull() || aViewer.IsNull())
2659   {
2660     std::cerr << "No active view. Please call vinit.\n";
2661     return 1;
2662   }
2663
2664   Aspect_GridType     aType = aViewer->GridType();
2665   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
2666
2667   Standard_Integer anIter = 1;
2668   for (; anIter < theArgNb; ++anIter)
2669   {
2670     const char* aValue = theArgVec[anIter];
2671     if (*aValue == 'r')
2672     {
2673       aType = Aspect_GT_Rectangular;
2674     }
2675     else if (*aValue == 'c')
2676     {
2677       aType = Aspect_GT_Circular;
2678     }
2679     else if (*aValue == 'l')
2680     {
2681       aMode = Aspect_GDM_Lines;
2682     }
2683     else if (*aValue == 'p')
2684     {
2685       aMode = Aspect_GDM_Points;
2686     }
2687     else if (strcmp (aValue, "off" ) == 0)
2688     {
2689       aViewer->DeactivateGrid();
2690       return 0;
2691     }
2692     else
2693     {
2694       break;
2695     }
2696   }
2697
2698   Standard_Integer aTail = (theArgNb - anIter);
2699   if (aTail == 0)
2700   {
2701     aViewer->ActivateGrid (aType, aMode);
2702     return 0;
2703   }
2704   else if (aTail != 2 && aTail != 5)
2705   {
2706     std::cerr << "Incorrect arguments number! Usage:\n"
2707               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
2708     return 1;
2709   }
2710
2711   Quantity_Length anOriginX, anOriginY;
2712   Quantity_PlaneAngle aRotAngle;
2713   if (aType == Aspect_GT_Rectangular)
2714   {
2715     Quantity_Length aRStepX, aRStepY;
2716     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
2717
2718     anOriginX = atof (theArgVec[anIter++]);
2719     anOriginY = atof (theArgVec[anIter++]);
2720     if (aTail == 5)
2721     {
2722       aRStepX   = atof (theArgVec[anIter++]);
2723       aRStepY   = atof (theArgVec[anIter++]);
2724       aRotAngle = atof (theArgVec[anIter++]);
2725     }
2726     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
2727     aViewer->ActivateGrid (aType, aMode);
2728   }
2729   else if (aType == Aspect_GT_Circular)
2730   {
2731     Quantity_Length aRadiusStep;
2732     Standard_Integer aDivisionNumber;
2733     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
2734
2735     anOriginX = atof (theArgVec[anIter++]);
2736     anOriginY = atof (theArgVec[anIter++]);
2737     if (aTail == 5)
2738     {
2739       aRadiusStep     = atof (theArgVec[anIter++]);
2740       aDivisionNumber = atoi (theArgVec[anIter++]);
2741       aRotAngle       = atof (theArgVec[anIter++]);
2742     }
2743
2744     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
2745     aViewer->ActivateGrid (aType, aMode);
2746   }
2747
2748   return 0;
2749 }
2750
2751 //==============================================================================
2752 //function : VFps
2753 //purpose  :
2754 //==============================================================================
2755
2756 static int VFps (Draw_Interpretor& theDI,
2757                  Standard_Integer  theArgNb,
2758                  const char**      theArgVec)
2759 {
2760   // get the active view
2761   Handle(V3d_View) aView = ViewerTest::CurrentView();
2762   if (aView.IsNull())
2763   {
2764     std::cerr << "No active view. Please call vinit.\n";
2765     return 1;
2766   }
2767
2768   Standard_Integer aFramesNb = (theArgNb > 1) ? atoi(theArgVec[1]) : 100;
2769   if (aFramesNb <= 0)
2770   {
2771     std::cerr << "Incorrect arguments!\n";
2772     return 1;
2773   }
2774
2775   // the time is meaningless for first call
2776   // due to async OpenGl rendering
2777   aView->Redraw();
2778
2779   // redraw view in loop to estimate average values
2780   OSD_Timer aTimer;
2781   aTimer.Start();
2782   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
2783   {
2784     aView->Redraw();
2785   }
2786   aTimer.Stop();
2787   Standard_Real aCpu;
2788   const Standard_Real aTime = aTimer.ElapsedTime();
2789   aTimer.OSD_Chronometer::Show (aCpu);
2790
2791   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
2792   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
2793
2794   // return statistics
2795   theDI << "FPS: " << aFpsAver << "\n"
2796         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
2797
2798   return 0;
2799 }
2800
2801
2802 //==============================================================================
2803 //function : VVbo
2804 //purpose  :
2805 //==============================================================================
2806
2807 static int VVbo (Draw_Interpretor& theDI,
2808                  Standard_Integer  theArgNb,
2809                  const char**      theArgVec)
2810 {
2811   // get the context
2812   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
2813   if (aContextAIS.IsNull())
2814   {
2815     std::cerr << "No active view. Please call vinit.\n";
2816     return 1;
2817   }
2818
2819   Handle(Graphic3d_GraphicDriver) aDriver =
2820          Handle(Graphic3d_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Device()->GraphicDriver());
2821   if (aDriver.IsNull())
2822   {
2823     std::cerr << "Graphic driver not available.\n";
2824     return 1;
2825   }
2826
2827   if (theArgNb < 2)
2828   {
2829     //theDI << "VBO: " << aDriver->ToUseVBO() << "\n";
2830     //return 0;
2831     std::cerr << "Wrong number of arguments.\n";
2832     return 1;
2833   }
2834
2835   aDriver->EnableVBO (atoi(theArgVec[1]) != 0);
2836   return 0;
2837 }
2838
2839 //==============================================================================
2840 //function : VMemGpu
2841 //purpose  :
2842 //==============================================================================
2843
2844 static int VMemGpu (Draw_Interpretor& theDI,
2845                     Standard_Integer  theArgNb,
2846                     const char**      theArgVec)
2847 {
2848   // get the context
2849   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
2850   if (aContextAIS.IsNull())
2851   {
2852     std::cerr << "No active view. Please call vinit.\n";
2853     return 1;
2854   }
2855
2856   Handle(Graphic3d_GraphicDriver) aDriver =
2857          Handle(Graphic3d_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Device()->GraphicDriver());
2858   if (aDriver.IsNull())
2859   {
2860     std::cerr << "Graphic driver not available.\n";
2861     return 1;
2862   }
2863
2864   Standard_Size aFreeBytes = 0;
2865   TCollection_AsciiString anInfo;
2866   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
2867   {
2868     std::cerr << "Information not available.\n";
2869     return 1;
2870   }
2871
2872   if (theArgNb > 1 && *theArgVec[1] == 'f')
2873   {
2874     theDI << Standard_Real (aFreeBytes);
2875   }
2876   else
2877   {
2878     theDI << anInfo;
2879   }
2880
2881   return 0;
2882 }
2883
2884 // ==============================================================================
2885 // function : VReadPixel
2886 // purpose  :
2887 // ==============================================================================
2888 static int VReadPixel (Draw_Interpretor& theDI,
2889                        Standard_Integer  theArgNb,
2890                        const char**      theArgVec)
2891 {
2892   // get the active view
2893   Handle(V3d_View) aView = ViewerTest::CurrentView();
2894   if (aView.IsNull())
2895   {
2896     std::cerr << "No active view. Please call vinit.\n";
2897     return 1;
2898   }
2899   else if (theArgNb < 3)
2900   {
2901     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
2902     return 1;
2903   }
2904
2905   Image_PixMap::ImgFormat aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
2906   Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
2907
2908   Standard_Integer aWidth, aHeight;
2909   aView->Window()->Size (aWidth, aHeight);
2910   const Standard_Integer anX = atoi (theArgVec[1]);
2911   const Standard_Integer anY = atoi (theArgVec[2]);
2912   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
2913   {
2914     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
2915     return 1;
2916   }
2917
2918   Standard_Boolean toShowName = Standard_False;
2919   Standard_Boolean toShowHls  = Standard_False;
2920   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
2921   {
2922     TCollection_AsciiString aParam (theArgVec[anIter]);
2923     if (TCollection_AsciiString::ISSIMILAR      (aParam, TCollection_AsciiString ("rgb")))
2924     {
2925       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
2926       aBufferType = Graphic3d_BT_RGB;
2927     }
2928     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("hls")))
2929     {
2930       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
2931       aBufferType = Graphic3d_BT_RGB;
2932       toShowHls   = Standard_True;
2933     }
2934     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgbf")))
2935     {
2936       aFormat     = Image_PixMap::ImgRGBF;
2937       aBufferType = Graphic3d_BT_RGB;
2938     }
2939     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgba")))
2940     {
2941       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
2942       aBufferType = Graphic3d_BT_RGBA;
2943     }
2944     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("rgbaf")))
2945     {
2946       aFormat     = Image_PixMap::ImgRGBAF;
2947       aBufferType = Graphic3d_BT_RGBA;
2948     }
2949     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("depth")))
2950     {
2951       aFormat     = Image_PixMap::ImgGrayF;
2952       aBufferType = Graphic3d_BT_Depth;
2953     }
2954     else if (TCollection_AsciiString::ISSIMILAR (aParam, TCollection_AsciiString ("name")))
2955     {
2956       toShowName = Standard_True;
2957     }
2958   }
2959
2960   Image_PixMap anImage;
2961   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
2962   {
2963     std::cerr << "Image allocation failed\n";
2964     return 1;
2965   }
2966   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
2967   {
2968     std::cerr << "Image dump failed\n";
2969     return 1;
2970   }
2971
2972   Quantity_Parameter anAlpha;
2973   Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
2974   if (toShowName)
2975   {
2976     if (aBufferType == Graphic3d_BT_RGBA)
2977     {
2978       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha << "\n";
2979     }
2980     else
2981     {
2982       theDI << Quantity_Color::StringName (aColor.Name()) << "\n";
2983     }
2984   }
2985   else
2986   {
2987     switch (aBufferType)
2988     {
2989       default:
2990       case Graphic3d_BT_RGB:
2991       {
2992         if (toShowHls)
2993         {
2994           theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation() << "\n";
2995         }
2996         else
2997         {
2998           theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << "\n";
2999         }
3000         break;
3001       }
3002       case Graphic3d_BT_RGBA:
3003       {
3004         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha << "\n";
3005         break;
3006       }
3007       case Graphic3d_BT_Depth:
3008       {
3009         theDI << aColor.Red() << "\n";
3010         break;
3011       }
3012     }
3013   }
3014
3015   return 0;
3016 }
3017
3018 //==============================================================================
3019 //function : VDiffImage
3020 //purpose  : The draw-command compares two images.
3021 //==============================================================================
3022
3023 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
3024 {
3025   if (theArgNb < 6)
3026   {
3027     theDI << "Not enough arguments.\n";
3028     return 1;
3029   }
3030
3031   // image file names
3032   const char* anImgPathRef = theArgVec[1];
3033   const char* anImgPathNew = theArgVec[2];
3034
3035   // get string tolerance and check its validity
3036   Standard_Real aTolColor = atof (theArgVec[3]);
3037   if (aTolColor < 0.0)
3038     aTolColor = 0.0;
3039   if (aTolColor > 1.0)
3040     aTolColor = 1.0;
3041
3042   Standard_Boolean toBlackWhite     = (atoi (theArgVec[4]) == 1);
3043   Standard_Boolean isBorderFilterOn = (atoi (theArgVec[5]) == 1);
3044
3045   // image file of difference
3046   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
3047
3048   // compare the images
3049   Image_Diff aComparer;
3050   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
3051   {
3052     return 1;
3053   }
3054
3055   aComparer.SetColorTolerance (aTolColor);
3056   aComparer.SetBorderFilterOn (isBorderFilterOn);
3057   Standard_Integer aDiffColorsNb = aComparer.Compare();
3058   theDI << aDiffColorsNb << "\n";
3059
3060   // save image of difference
3061   if (aDiffImagePath != NULL)
3062   {
3063     aComparer.SaveDiffImage (aDiffImagePath);
3064   }
3065
3066   return 0;
3067 }
3068
3069 //=======================================================================
3070 //function : ViewerCommands
3071 //purpose  :
3072 //=======================================================================
3073
3074 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
3075 {
3076
3077   const char *group = "ZeViewer";
3078   theCommands.Add("vinit" ,
3079     "vinit            : vinit [leftPx topPx widthPx heightPx] : Create the Viewer window",
3080     __FILE__,VInit,group);
3081   theCommands.Add("vhelp" ,
3082     "vhelp            : display help on the viewer commands",
3083     __FILE__,VHelp,group);
3084   theCommands.Add("vtop" ,
3085     "vtop or <T>      : Top view" ,
3086     __FILE__,VTop,group);
3087   theCommands.Add("vbottom" ,
3088     "vbottom          : Bottom view" ,
3089     __FILE__,VBottom,group);
3090   theCommands.Add("vleft" ,
3091     "vleft            : Left view" ,
3092     __FILE__,VLeft,group);
3093   theCommands.Add("vright" ,
3094     "vright           : Right view" ,
3095     __FILE__,VRight,group);
3096   theCommands.Add("vaxo" ,
3097     " vaxo or <A>     : Axonometric view ",
3098     __FILE__,VAxo,group);
3099   theCommands.Add("vfront" ,
3100     "vfront           : Front view" ,
3101     __FILE__,VFront,group);
3102   theCommands.Add("vback" ,
3103     "vback            : Back view" ,
3104     __FILE__,VBack,group);
3105   theCommands.Add("vpick" ,
3106     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
3107     VPick,group);
3108   theCommands.Add("vfit"    ,
3109     "vfit or <F>         : vfit",
3110     __FILE__,VFit,group);
3111   theCommands.Add("vzfit"    ,
3112     "vzfit",
3113     __FILE__,VZFit,group);
3114   theCommands.Add("vrepaint",
3115     "vrepaint        : vrepaint, force redraw",
3116     __FILE__,VRepaint,group);
3117   theCommands.Add("vclear",
3118     "vclear          : vclear",
3119     __FILE__,VClear,group);
3120   theCommands.Add("vsetbg",
3121     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
3122     __FILE__,VSetBg,group);
3123   theCommands.Add("vsetbgmode",
3124     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
3125     __FILE__,VSetBgMode,group);
3126   theCommands.Add("vsetgradientbg",
3127     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
3128     __FILE__,VSetGradientBg,group);
3129   theCommands.Add("vsetgrbgmode",
3130     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
3131     __FILE__,VSetGradientBgMode,group);
3132   theCommands.Add("vsetcolorbg",
3133     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
3134     __FILE__,VSetColorBg,group);
3135   theCommands.Add("vscale",
3136     "vscale          : vscale X Y Z",
3137     __FILE__,VScale,group);
3138   theCommands.Add("vzbufftrihedron",
3139     "vzbufftrihedron [center|left_lower|left_upper|right_lower|right_upper"
3140     " textR=255 textG=255 textB=255 scale=0.1 wireframe|zbuffer]"
3141     " : Displays a V3d_ZBUFFER'ed or V3d_WIREFRAME'd trihedron",
3142     __FILE__,VTestZBuffTrihedron,group);
3143   theCommands.Add("vrotate",
3144     "vrotate         : vrotate AX AY AZ [X Y Z]",
3145     __FILE__,VRotate,group);
3146   theCommands.Add("vzoom",
3147     "vzoom           : vzoom coef",
3148     __FILE__,VZoom,group);
3149   theCommands.Add("vpan",
3150     "vpan            : vpan dx dy",
3151     __FILE__,VPan,group);
3152   theCommands.Add("vexport",
3153     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
3154     " : exports the view to a vector file of a given format"
3155     " : notice that EMF format requires patched gl2ps",
3156     __FILE__,VExport,group);
3157   theCommands.Add("vcolorscale",
3158     "vcolorscale     : vcolorscale [RangeMin = 0 RangeMax = 100 Intervals = 10 HeightFont = 16 Position = 2 X = 0 Y = 0]: draw color scale",
3159     __FILE__,VColorScale,group);
3160   theCommands.Add("vgraduatedtrihedron",
3161     "vgraduatedtrihedron : 1/0 (display/erase) [Xname Yname Zname [Font [isMultibyte]]]",
3162     __FILE__,VGraduatedTrihedron,group);
3163   theCommands.Add("vprintview" ,
3164     "vprintview : width height filename [algo=0] : Test print algorithm: algo = 0 - stretch, algo = 1 - tile",
3165     __FILE__,VPrintView,group);
3166   theCommands.Add("vzlayer",
3167     "vzlayer : add/del/get [id] : Z layer operations in v3d viewer: add new z layer, delete z layer, get z layer ids",
3168     __FILE__,VZLayer,group);
3169   theCommands.Add("voverlaytext",
3170     "voverlaytext : text x y [height] [font_name] [text_color: R G B] [display_type] [background_color: R G B]"
3171     " : height - pixel height of the text (default=10.0)"
3172     " : font_name - name of font (default=courier)"
3173     " : text_color - three values: RedColor GreenColor BlueColor (default = 255.0 255.0 255.0) "
3174     " : display_type = {normal/subtitle/decal/blend}, (default=normal) "
3175     " : background_color - three values: RedColor GreenColor BlueColor (default = 255.0 255.0 255.0), the parameter is defined for subtitle and decal display types ",
3176     __FILE__,VOverlayText,group);
3177   theCommands.Add("vlayerline",
3178     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
3179     __FILE__,VLayerLine,group);
3180   theCommands.Add ("vgrid",
3181     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
3182     " : Mode - rectangular or circular"
3183     " : Type - lines or points",
3184     __FILE__, VGrid, group);
3185   theCommands.Add ("vfps",
3186     "vfps [framesNb=100] : estimate average frame rate for active view",
3187     __FILE__, VFps, group);
3188   theCommands.Add ("vvbo",
3189     "vvbo {0|1} : turn VBO usage On/Off; affects only newly displayed objects",
3190     __FILE__, VVbo, group);
3191   theCommands.Add ("vmemgpu",
3192     "vmemgpu [f]: print system-dependent GPU memory information if available;"
3193     " with f option returns free memory in bytes",
3194     __FILE__, VMemGpu, group);
3195   theCommands.Add ("vreadpixel",
3196     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
3197     " : Read pixel value for active view",
3198     __FILE__, VReadPixel, group);
3199   theCommands.Add("diffimage",
3200     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
3201     __FILE__, VDiffImage, group);
3202 }