0031582: Configuration, CMake - OCCT fails to build with VTK 9.0
[occt.git] / src / IVtkDraw / IVtkDraw.cxx
1 // Created on: 2012-02-03 
2 // 
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS 
4 // 
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifdef _WIN32
17   #include <windows.h>
18   #include <WNT_WClass.hxx>
19   #include <WNT_Window.hxx>
20 #endif
21
22 #include <Draw.hxx>
23 #include <Draw_Interpretor.hxx>
24 #include <Draw_PluginMacro.hxx>
25 #include <TCollection_AsciiString.hxx>
26 #include <TopoDS_Shape.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRepTools.hxx>
29 #include <DBRep.hxx>
30 #include <NCollection_DoubleMap.hxx>
31 #include <NCollection_List.hxx>
32 #include <NCollection_DataMap.hxx>
33 #include <TopTools_DataMapOfIntegerShape.hxx>
34 #include <OpenGl_GraphicDriver.hxx>
35 #include <V3d.hxx>
36 #include <V3d_TypeOfOrientation.hxx>
37 #include <Aspect_DisplayConnection.hxx>
38
39 #include <IVtk_Types.hxx>
40 #include <IVtkVTK_ShapeData.hxx>
41 #include <IVtkOCC_Shape.hxx>
42 #include <IVtkOCC_ShapeMesher.hxx>
43 #include <IVtkTools_ShapeDataSource.hxx>
44 #include <IVtkTools_ShapeObject.hxx>
45 #include <IVtkTools_SubPolyDataFilter.hxx>
46 #include <IVtkTools_DisplayModeFilter.hxx>
47 #include <IVtkTools_ShapePicker.hxx>
48
49 #include <IVtkDraw.hxx>
50 #include <IVtkDraw_HighlightAndSelectionPipeline.hxx>
51 #include <IVtkDraw_Interactor.hxx>
52
53 // prevent disabling some MSVC warning messages by VTK headers 
54 #include <Standard_WarningsDisable.hxx>
55 #include <vtkAlgorithmOutput.h>
56 #include <vtkAppendPolyData.h>
57 #include <vtkBMPWriter.h>
58 #include <vtkCamera.h>
59 #include <vtkCellData.h>
60 #include <vtkCommand.h>
61 #include <vtkGeometryFilter.h>
62 #include <vtkIdTypeArray.h>
63 #include <vtkImageResize.h>
64 #include <vtkImageWriter.h>
65 #include <vtkInteractorStyleTrackballCamera.h>
66 #include <vtkJPEGWriter.h>
67 #include <vtkPNGWriter.h>
68 #include <vtkPNMWriter.h>
69 #include <vtkPolyDataMapper.h>
70 #include <vtkProperty.h>
71 #include <vtkRenderWindow.h>
72 #include <vtkRenderer.h>
73 #include <vtkRenderWindowInteractor.h>
74 #include <vtkSmartPointer.h>
75 #include <vtkTIFFWriter.h>
76 #include <vtkWindowToImageFilter.h>
77 #ifndef _WIN32
78   #include <X11/X.h>
79   #include <X11/Shell.h>
80   #include <X11/Xlib.h>
81   #include <X11/Xutil.h>
82   #include <GL/glx.h>
83   #include <Xw_Window.hxx>
84   #include <vtkXRenderWindowInteractor.h>
85   #include <vtkXOpenGLRenderWindow.h>
86   #include <tk.h>
87 #endif
88 #include <Standard_WarningsRestore.hxx>
89
90 #if (VTK_MAJOR_VERSION > 8) || (VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 1)
91   #define HAVE_VTK_SRGB
92 #endif
93
94 //================================================================
95 // TYPE DEFINITIONS
96 //================================================================
97
98 typedef NCollection_DoubleMap<TopoDS_Shape, TCollection_AsciiString> DoubleMapOfShapesAndNames;
99 typedef NCollection_DoubleMap<vtkSmartPointer<vtkActor>, TCollection_AsciiString> DoubleMapOfActorsAndNames;
100
101 typedef IVtkDraw_HighlightAndSelectionPipeline PipelinePtr;
102
103 //================================================================
104 // GLOBAL VARIABLES
105 //================================================================
106
107 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
108
109 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
110 {
111   static Handle(Aspect_DisplayConnection) aDisplayConnection;
112   return aDisplayConnection;
113 }
114
115 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
116 {
117   GetDisplayConnection() = theDisplayConnection;
118 }
119
120 static DoubleMapOfShapesAndNames& GetMapOfShapes()
121 {
122   static DoubleMapOfShapesAndNames aMap;
123   return aMap;
124 }
125
126 static DoubleMapOfActorsAndNames& GetMapOfActors()
127 {
128   static DoubleMapOfActorsAndNames aMap;
129   return aMap;
130 }
131
132 static vtkSmartPointer<vtkRenderer>& GetRenderer()
133 {
134   static vtkSmartPointer<vtkRenderer> aRenderer;
135   return aRenderer;
136 }
137
138 static Handle(ShapePipelineMap)& GetPipelines()
139 {
140   static Handle(ShapePipelineMap) aPLMap;
141   if (aPLMap.IsNull())
142   {
143     aPLMap = new ShapePipelineMap();
144   }
145
146   return aPLMap;
147 }
148
149 static Handle(PipelinePtr) GetPipeline (const IVtk_IdType& theShapeID)
150 {
151   Handle(PipelinePtr) aPtr;
152   GetPipelines()->Find (theShapeID, aPtr);
153   return aPtr;
154 }
155
156 //! Get VTK render pipeline with shape ID got from actor.
157 static Handle(PipelinePtr) PipelineByActor (const vtkSmartPointer<vtkActor>& theActor)
158 {
159   IVtk_IdType aShapeID = IVtkTools_ShapeObject::GetShapeSource (theActor)->GetShape()->GetId();
160   return GetPipeline (aShapeID);
161 }
162
163 //! Get VTK render pipeline with actor that has the input name.
164 static Handle(PipelinePtr) PipelineByActorName (const TCollection_AsciiString& theName)
165 {
166   const vtkSmartPointer<vtkActor>& anActor = GetMapOfActors().Find2 (theName);
167   return PipelineByActor (anActor);
168 }
169
170 #ifdef _WIN32
171
172 static Handle(WNT_Window)& GetWindow()
173 {
174   static Handle(WNT_Window) aWindow;
175   return aWindow;
176 }
177
178 #else
179
180 static Handle(Xw_Window)& GetWindow()
181 {
182   static Handle(Xw_Window) aXWWin;
183   return aXWWin;
184 }
185
186 #endif
187
188 static vtkSmartPointer<IVtkDraw_Interactor>& GetInteractor()
189 {
190   static vtkSmartPointer<IVtkDraw_Interactor> anInteractor;
191   return anInteractor;
192 }
193
194 static vtkSmartPointer<IVtkTools_ShapePicker>& GetPicker()
195 {
196   static vtkSmartPointer<IVtkTools_ShapePicker> aPicker;
197   return aPicker;
198 }
199
200 //! Generate identical number for shape
201 Standard_Integer GenerateId()
202 {
203   static unsigned int aShapesCounter = (unsigned int )-1;
204   return (Standard_Integer )++aShapesCounter;
205 }
206
207 //=========================================================
208 // Function : WClass
209 // Purpose  :
210 //=========================================================
211 const Handle(WNT_WClass)& IVtkDraw::WClass()
212 {
213   static Handle(WNT_WClass) aWindowClass;
214 #ifdef _WIN32
215   if (aWindowClass.IsNull())
216   {
217     aWindowClass = new WNT_WClass ("GWVTK_Class", NULL,
218                                    CS_VREDRAW | CS_HREDRAW, 0, 0,
219                                    ::LoadCursorW (NULL, IDC_ARROW));
220   }
221 #endif
222   return aWindowClass;
223 }
224
225 //==============================================================
226 // Function : ViewerInit
227 // Purpose  :
228 //==============================================================
229 void IVtkDraw::ViewerInit (const IVtkWinParams& theParams)
230 {
231   Standard_Integer aPxLeft  =   0, aPxTop    = 460;
232   Standard_Integer aPxWidth = 409, aPxHeight = 409;
233   if (theParams.TopLeft.x() != 0)
234   {
235     aPxLeft = theParams.TopLeft.x();
236   }
237   if (theParams.TopLeft.y() != 0)
238   {
239     aPxTop = theParams.TopLeft.y();
240   }
241   if (theParams.Size.x() != 0)
242   {
243     aPxWidth = theParams.Size.x();
244   }
245   if (theParams.Size.y() != 0)
246   {
247     aPxHeight = theParams.Size.y();
248   }
249
250   if (!GetRenderer())
251   {
252     SetDisplayConnection (new Aspect_DisplayConnection ());
253 #ifdef _WIN32
254     if (GetWindow().IsNull())
255     {
256       GetWindow() = new WNT_Window ("IVtkTest", WClass(),
257                                     WS_OVERLAPPEDWINDOW,
258                                     aPxLeft, aPxTop,
259                                     aPxWidth, aPxHeight,
260                                     Quantity_NOC_BLACK);
261       GetWindow()->SetVirtual (Draw_VirtualWindows);
262     }
263 #else
264
265     if (GetWindow().IsNull())
266     {
267       GetWindow() = new Xw_Window (GetDisplayConnection(),
268                                    "IVtkTest",
269                                    aPxLeft, aPxTop,
270                                    aPxWidth, aPxHeight);
271       GetWindow()->SetVirtual (Draw_VirtualWindows);
272     }
273 #endif
274     // Init pipeline
275     GetRenderer() = vtkSmartPointer<vtkRenderer>::New();
276
277     vtkSmartPointer<vtkRenderWindow> aRenWin = vtkSmartPointer<vtkRenderWindow>::New();
278     aRenWin->AddRenderer (GetRenderer());
279     GetRenderer()->GetActiveCamera()->ParallelProjectionOn();
280     aRenWin->SetSize (aPxWidth, aPxHeight);
281
282     aRenWin->SetMultiSamples (theParams.NbMsaaSample);
283     aRenWin->SetAlphaBitPlanes (1);
284   #ifdef HAVE_VTK_SRGB
285     aRenWin->SetUseSRGBColorSpace (theParams.UseSRGBColorSpace);
286   #else
287     if (theParams.UseSRGBColorSpace)
288     {
289       Message::SendWarning() << "Warning: skipped option -srgb unsupported by old VTK";
290     }
291   #endif
292
293 #ifdef _WIN32
294     aRenWin->SetWindowId((void*)GetWindow()->HWindow());
295 #else
296     Window aWindowId = GetWindow()->XWindow();
297     aRenWin->SetWindowId ((void*)aWindowId);
298     Display *aDisplayId = GetDisplayConnection()->GetDisplay();
299     aRenWin->SetDisplayId (aDisplayId);
300
301     // Setup XWindow
302     XSynchronize (aDisplayId, 1);
303     GetWindow()->Map();
304
305     // X11 : For keyboard on SUN
306     XWMHints wmhints;
307     wmhints.flags = InputHint;
308     wmhints.input = 1;
309
310     XSetWMHints (aDisplayId, aWindowId, &wmhints);
311
312     XSelectInput (aDisplayId, aWindowId,  ExposureMask | KeyPressMask |
313       ButtonPressMask | ButtonReleaseMask |
314       StructureNotifyMask |
315       PointerMotionMask |
316       Button1MotionMask | Button2MotionMask |
317       Button3MotionMask
318       );
319
320     XSynchronize (aDisplayId, 0);
321
322 #endif
323
324     // Init interactor
325     GetInteractor() = vtkSmartPointer<IVtkDraw_Interactor>::New();
326     GetInteractor()->SetRenderWindow (aRenWin);
327     GetInteractor()->SetOCCWindow (GetWindow());
328
329     vtkSmartPointer<vtkInteractorStyleTrackballCamera>
330       aStyle = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
331     GetInteractor()->SetInteractorStyle (aStyle);
332
333     // Init picker
334     GetPicker() = vtkSmartPointer<IVtkTools_ShapePicker>::New();
335     GetPicker()->SetTolerance (0.025f);
336     GetPicker()->SetRenderer (GetRenderer());
337
338     GetInteractor()->SetShapePicker (GetPicker());
339     GetInteractor()->SetPipelines (GetPipelines());
340     GetInteractor()->Initialize();
341
342     aRenWin->SetOffScreenRendering(Draw_VirtualWindows);
343     aRenWin->Render();
344   }
345
346   GetWindow()->Map();
347 }
348
349 //================================================================
350 // Function : VtkInit
351 // Purpose  : 
352 //================================================================
353 static Standard_Integer VtkInit (Draw_Interpretor& ,
354                                  Standard_Integer theNbArgs,
355                                  const char** theArgVec)
356 {
357   bool hasSize = false;
358   IVtkDraw::IVtkWinParams aParams;
359   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
360   {
361     TCollection_AsciiString anArg (theArgVec[anArgIter]);
362     anArg.LowerCase();
363     if (anArg == "-msaa"
364      && anArgIter + 1 < theNbArgs)
365     {
366       aParams.NbMsaaSample = Draw::Atoi (theArgVec[++anArgIter]);
367     }
368     else if (anArg == "-srgb")
369     {
370       aParams.UseSRGBColorSpace = true;
371       if (anArgIter + 1 < theNbArgs
372        && Draw::ParseOnOff (theArgVec[anArgIter + 1], aParams.UseSRGBColorSpace))
373       {
374         ++anArgIter;
375       }
376     }
377     else if (!hasSize
378           && anArgIter + 3 < theNbArgs)
379     {
380       aParams.TopLeft.SetValues (Draw::Atoi (theArgVec[anArgIter + 0]),
381                                  Draw::Atoi (theArgVec[anArgIter + 1]));
382       aParams.Size   .SetValues (Draw::Atoi (theArgVec[anArgIter + 2]),
383                                  Draw::Atoi (theArgVec[anArgIter + 3]));
384     }
385     else
386     {
387       Message::SendFail() << "Syntax error at '" << anArg << "'";
388       return 1;
389     }
390   }
391
392   IVtkDraw::ViewerInit (aParams);
393   return 0;
394 }
395
396 //================================================================
397 // Function : VtkClose
398 // Purpose  :
399 //================================================================
400 static Standard_Integer VtkClose (Draw_Interpretor& ,
401                                   Standard_Integer theNbArgs,
402                                   const char** )
403 {
404   if (theNbArgs > 1)
405   {
406     Message::SendFail() << "Syntax error: wrong number of arguments";
407     return 1;
408   }
409
410   if (GetWindow())
411   {
412     GetWindow()->Unmap();
413   }
414
415   GetWindow().Nullify();
416   if (GetInteractor())
417   {
418     GetInteractor()->GetRenderWindow()->Finalize();
419     //GetInteractor()->SetRenderWindow (NULL);
420     GetInteractor()->TerminateApp();
421   }
422
423   GetInteractor() = NULL;
424   GetRenderer() = NULL;
425   GetPicker() = NULL;
426   return 0;
427 }
428
429 //================================================================
430 // Function : VtkRenderParams
431 // Purpose  :
432 //================================================================
433 static Standard_Integer VtkRenderParams (Draw_Interpretor& ,
434                                          Standard_Integer theNbArgs,
435                                          const char** theArgVec)
436 {
437   if (!GetInteractor()
438    || !GetInteractor()->IsEnabled())
439   {
440     Message::SendFail() << "Syntax error: call ivtkinit before";
441     return 1;
442   }
443   else if (theNbArgs <= 1)
444   {
445     Message::SendFail() << "Syntax error: wrong number of arguments";
446     return 1;
447   }
448
449   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
450   {
451     TCollection_AsciiString anArg (theArgVec[anArgIter]);
452     anArg.LowerCase();
453     if (anArg == "-depthpeeling"
454      && anArgIter + 1 < theNbArgs)
455     {
456       Standard_Integer aNbLayers = Draw::Atoi (theArgVec[++anArgIter]);
457       GetRenderer()->SetUseDepthPeeling (aNbLayers > 0);
458       GetRenderer()->SetMaximumNumberOfPeels (aNbLayers);
459     }
460     else if (anArg == "-shadows")
461     {
462       bool toUseShadows = true;
463       if (anArgIter + 1 < theNbArgs
464        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toUseShadows))
465       {
466         ++anArgIter;
467       }
468     #if (VTK_MAJOR_VERSION >= 7)
469       GetRenderer()->SetUseShadows (toUseShadows);
470     #else
471       Message::SendWarning() << "Warning: skipped option -shadows unsupported by old VTK";
472     #endif
473     }
474     else
475     {
476       Message::SendFail() << "Syntax error at '" << anArg << "'";
477       return 1;
478     }
479   }
480
481   GetInteractor()->GetRenderWindow()->Render();
482   return 0;
483 }
484
485
486 //================================================================
487 // Function : CreateActor
488 // Purpose  : 
489 //================================================================
490 vtkActor* CreateActor (const Standard_Integer theId,
491                        const TopoDS_Shape& theShape)
492 {
493   if ( theShape.IsNull() )
494   {
495     return NULL;
496   }
497
498   Handle(PipelinePtr) aPL = new PipelinePtr (theShape, theId);
499   GetPipelines()->Bind (theId, aPL);
500
501   return aPL->Actor();
502 }
503
504 //================================================================
505 // Function : VtkDisplay
506 // Purpose  : 
507 //================================================================
508
509 static Standard_Integer VtkDisplay (Draw_Interpretor& ,
510                                     Standard_Integer theArgNum,
511                                     const char** theArgs)
512 {
513   if (!GetInteractor()
514    || !GetInteractor()->IsEnabled())
515   {
516     Message::SendFail() << "Error : call ivtkinit before";
517     return 1;
518   }
519   if (theArgNum < 2)
520   {
521     Message::SendFail() << "Error : expects at least 1 argument\n";
522     return 1;
523   }
524
525   TCollection_AsciiString aName;
526   TopoDS_Shape anOldShape, aNewShape;
527   vtkSmartPointer<vtkRenderer>& aRenderer = GetRenderer();
528   for (Standard_Integer anIndex = 1; anIndex < theArgNum; ++anIndex)
529   {
530     // Get name of shape
531     aName = theArgs[anIndex];
532     // Get shape from DRAW
533     aNewShape = DBRep::Get (theArgs[anIndex]);
534
535     // The shape is already in the map
536     if (GetMapOfShapes().IsBound2 (aName))
537     {
538       // Get shape from map
539       anOldShape = GetMapOfShapes().Find2 (aName);
540       // Equal shapes
541       if (anOldShape.IsEqual (aNewShape))
542       {
543         // Get actor from map and display it
544         PipelineByActorName (aName)->AddToRenderer (aRenderer);
545       }
546       // Different shapes
547       else
548       {
549         if (aNewShape.IsNull()) continue;
550         // Create actor from DRAW shape
551         vtkActor* anActor = CreateActor (GenerateId(), aNewShape);
552         // Remove old actor from render
553         PipelineByActorName (aName)->RemoveFromRenderer (aRenderer);
554         // Update maps
555         GetMapOfShapes().UnBind2 (aName);
556         GetMapOfShapes().Bind (aNewShape, aName);
557         GetMapOfActors().UnBind2 (aName);
558         GetMapOfActors().Bind (anActor, aName);
559         // Display new actor
560         PipelineByActorName (aName)->AddToRenderer (aRenderer);
561         // Compute selection for displayed actors
562         GetPicker()->SetSelectionMode (SM_Shape, Standard_True);
563       }
564     }
565     // There is no shape with given name in map
566     else
567     {
568       if (aNewShape.IsNull()) continue;
569       // Create actor from DRAW shape
570       Standard_Integer anId = GenerateId();
571       vtkSmartPointer<vtkActor> anActor = CreateActor (anId, aNewShape);
572       // Update maps
573       GetMapOfShapes().Bind (aNewShape, aName);
574       GetMapOfActors().Bind (anActor, aName);
575       // Display actor
576       GetPipeline(anId)->AddToRenderer(aRenderer);
577
578       // Compute selection for displayed actors
579       GetPicker()->SetSelectionMode (SM_Shape, Standard_True);
580     }
581   }
582
583   // Redraw window
584   aRenderer->ResetCamera();
585   GetInteractor()->GetRenderWindow()->Render();
586
587   return 0;
588 }
589
590 //================================================================
591 // Function : VtkErase
592 // Purpose  : 
593 //================================================================
594 static Standard_Integer VtkErase (Draw_Interpretor& ,
595                                   Standard_Integer theArgNum,
596                                   const char** theArgs)
597 {
598   if (!GetInteractor()
599    || !GetInteractor()->IsEnabled())
600   {
601     Message::SendFail() << "Error: call ivtkinit before";
602     return 1;
603   }
604
605   vtkSmartPointer<vtkRenderer> aRenderer = GetRenderer();
606   if (theArgNum == 1)
607   {
608     // Erase all objects
609     DoubleMapOfActorsAndNames::Iterator anIterator (GetMapOfActors());
610     while (anIterator.More())
611     {
612       PipelineByActor (anIterator.Key1())->RemoveFromRenderer (aRenderer);
613       anIterator.Next();
614     }
615   }
616   else
617   {
618     // Erase named objects
619     for (Standard_Integer anIndex = 1; anIndex < theArgNum; ++anIndex)
620     {
621       TCollection_AsciiString aName = theArgs[anIndex];
622       vtkSmartPointer<vtkActor> anActor;
623       if (!GetMapOfActors().Find2 (aName, anActor))
624       {
625         Message::SendFail() << "Syntax error: object '" << aName << "' not found";
626         return 1;
627       }
628
629       PipelineByActorName (aName)->RemoveFromRenderer (aRenderer);
630     }
631   }
632
633   // Redraw window
634   aRenderer->ResetCamera();
635   GetInteractor()->GetRenderWindow()->Render();
636   return 0;
637 }
638
639 //================================================================
640 // Function : VtkRemove
641 // Purpose  : Remove the actor from memory.
642 //================================================================
643 static Standard_Integer VtkRemove (Draw_Interpretor& ,
644                                    Standard_Integer theArgNum,
645                                    const char** theArgs)
646 {
647   if (!GetInteractor()
648    || !GetInteractor()->IsEnabled())
649   {
650     Message::SendFail() << "Error: call ivtkinit before";
651     return 1;
652   }
653
654   vtkSmartPointer<vtkRenderer> aRenderer = GetRenderer();
655   if (theArgNum == 1)
656   {
657     // Remove all actors from the renderer
658     DoubleMapOfActorsAndNames::Iterator anIterator(GetMapOfActors());
659     while (anIterator.More())
660     {
661       vtkSmartPointer<IVtkTools_ShapeDataSource> aSrc = IVtkTools_ShapeObject::GetShapeSource (anIterator.Key1());
662       if (aSrc.GetPointer() != NULL && !aSrc->GetShape().IsNull())
663       {
664         GetPicker()->RemoveSelectableObject(aSrc->GetShape());
665       }
666       else
667       {
668         aRenderer->RemoveActor(anIterator.Key1());
669       }
670       anIterator.Next();
671     }
672     // Remove all pipelines from the renderer
673     for (ShapePipelineMap::Iterator anIt(*GetPipelines()); anIt.More(); anIt.Next())
674     {
675       anIt.Value()->RemoveFromRenderer(aRenderer);
676     }
677     // Clear maps and remove all TopoDS_Shapes, actors and pipelines
678     GetMapOfShapes().Clear();
679     GetMapOfActors().Clear();
680     GetPipelines()->Clear();
681   }
682   else
683   {
684     // Remove named objects
685     for (Standard_Integer anIndex = 1; anIndex < theArgNum; ++anIndex)
686     {
687       TCollection_AsciiString aName = theArgs[anIndex];
688       vtkSmartPointer<vtkActor> anActor;
689       if (!GetMapOfActors().Find2 (aName, anActor))
690       {
691         Message::SendFail() << "Syntax error: object '" << aName << "' not found";
692         return 1;
693       }
694
695       // Remove the actor and its pipeline (if found) from the renderer
696       vtkSmartPointer<IVtkTools_ShapeDataSource> aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor);
697       if (aSrc.GetPointer() != NULL && !aSrc->GetShape().IsNull())
698       {
699         IVtk_IdType aShapeID = aSrc->GetShape()->GetId();
700         GetPicker()->RemoveSelectableObject (aSrc->GetShape());
701         GetPipeline (aSrc->GetShape()->GetId())->RemoveFromRenderer (aRenderer);
702         GetPipelines()->UnBind (aShapeID); // Remove a pipepline
703       }
704       else
705       {
706         aRenderer->RemoveActor (anActor);
707       }
708       // Remove the TopoDS_Shape and the actor
709       GetMapOfShapes().UnBind2 (aName); // Remove a TopoDS shape
710       GetMapOfActors().UnBind2 (aName); // Remove an actor
711     }
712   }
713
714   // Redraw window
715   aRenderer->ResetCamera();
716   GetInteractor()->GetRenderWindow()->Render();
717   return 0;
718 }
719
720 //================================================================
721 // Function  : VtkSetDisplayMode
722 // Purpose   : 
723 // Draw args : ivtksetdispmode [name] mode(0,1)
724 //================================================================
725 static Standard_Integer VtkSetDisplayMode (Draw_Interpretor& ,
726                                            Standard_Integer theArgNum,
727                                            const char** theArgs)
728 {
729   if (!GetInteractor()
730    || !GetInteractor()->IsEnabled())
731   {
732     Message::SendFail() << "Error: call ivtkinit before";
733     return 1;
734   }
735   else if (theArgNum != 2 && theArgNum != 3)
736   {
737     Message::SendFail() << "Syntax error: expects 1 or 2 arguments";
738     return 1;
739   }
740
741   if (theArgNum == 2)
742   {
743     // Set disp mode for all objects
744     Standard_Integer aMode =  Draw::Atoi (theArgs[1]); // Get mode
745     DoubleMapOfActorsAndNames::Iterator anIter (GetMapOfActors());
746     while (anIter.More())
747     {
748       vtkSmartPointer<vtkActor> anActor = anIter.Key1();
749       IVtkTools_ShapeDataSource* aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor);
750       if (aSrc)
751       {
752         IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape();
753         if (!anOccShape.IsNull())
754         {
755           IVtkTools_DisplayModeFilter* aFilter = GetPipeline ( anOccShape->GetId() )->GetDisplayModeFilter();
756           aFilter->SetDisplayMode((IVtk_DisplayMode)aMode);
757           aFilter->Modified();
758           aFilter->Update();
759         }
760       }
761       anIter.Next();
762     }
763   }
764   // Set disp mode for named object
765   else 
766   {
767     TCollection_AsciiString aName = theArgs[1];
768     vtkSmartPointer<vtkActor> anActor;
769     if (!GetMapOfActors().Find2 (aName, anActor))
770     {
771       Message::SendFail() << "Syntax error: object '" << aName << "' not found";
772       return 1;
773     }
774
775     Standard_Integer aMode = atoi(theArgs[2]);
776     vtkSmartPointer<IVtkTools_ShapeDataSource> aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor);
777     if (aSrc)
778     {
779       IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape();
780       if (!anOccShape.IsNull())
781       {
782         IVtkTools_DisplayModeFilter* aFilter = GetPipeline (anOccShape->GetId())->GetDisplayModeFilter();
783         aFilter->SetDisplayMode ((IVtk_DisplayMode)aMode);
784         aFilter->Modified();
785         aFilter->Update();
786       }
787     }
788   }
789
790   // Redraw window
791   GetInteractor()->Render();
792   return 0;
793 }
794
795 //================================================================
796 // Function  : VtkSetBoundaryDraw
797 // Purpose   :
798 //================================================================
799 static Standard_Integer VtkSetBoundaryDraw (Draw_Interpretor& ,
800                                             Standard_Integer theArgNum,
801                                             const char** theArgs)
802 {
803   if (!GetInteractor()
804    || !GetInteractor()->IsEnabled())
805   {
806     Message::SendFail() << "Error: call ivtkinit before";
807     return 1;
808   }
809   else if (theArgNum != 2 && theArgNum != 3)
810   {
811     Message::SendFail() << "Syntax error: expects 1 or 2 arguments";
812     return 1;
813   }
814
815   if (theArgNum == 2)
816   {
817     // Set disp mode for all objects
818     Standard_Boolean toDraw = true;
819     Draw::ParseOnOff (theArgs[1], toDraw);
820     DoubleMapOfActorsAndNames::Iterator anIter(GetMapOfActors());
821     while (anIter.More())
822     {
823       vtkSmartPointer<vtkActor> anActor = anIter.Key1();
824       // Set Red color for boundary edges
825       vtkLookupTable* aTable = (vtkLookupTable*)anActor->GetMapper()->GetLookupTable();
826       IVtkTools::SetLookupTableColor(aTable, MT_SharedEdge, 1., 0., 0., 1.);
827
828       IVtkTools_ShapeDataSource* aSrc = IVtkTools_ShapeObject::GetShapeSource(anActor);
829       if (aSrc)
830       {
831         IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape();
832         if (!anOccShape.IsNull())
833         {
834           IVtkTools_DisplayModeFilter* aFilter = GetPipeline(anOccShape->GetId())->GetDisplayModeFilter();
835           aFilter->SetDisplayMode(DM_Shading);
836           aFilter->SetFaceBoundaryDraw(toDraw != 0);
837           aFilter->Modified();
838           aFilter->Update();
839         }
840       }
841       anIter.Next();
842     }
843   }
844   else
845   {
846     // Set disp mode for named object
847     TCollection_AsciiString aName = theArgs[1];
848     vtkSmartPointer<vtkActor> anActor;
849     if (!GetMapOfActors().Find2 (aName, anActor))
850     {
851       Message::SendFail() << "Syntax error: object '" << aName << "' not found";
852       return 1;
853     }
854
855     Standard_Boolean toDraw = true;
856     Draw::ParseOnOff (theArgs[2], toDraw);
857
858     // Set Red color for boundary edges
859     vtkLookupTable* aTable = (vtkLookupTable*)anActor->GetMapper()->GetLookupTable();
860     IVtkTools::SetLookupTableColor (aTable, MT_SharedEdge, 1., 0., 0., 1.);
861
862     vtkSmartPointer<IVtkTools_ShapeDataSource> aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor);
863     if (aSrc)
864     {
865       IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape();
866       if (!anOccShape.IsNull())
867       {
868         IVtkTools_DisplayModeFilter* aFilter = GetPipeline (anOccShape->GetId())->GetDisplayModeFilter();
869         aFilter->SetDisplayMode (DM_Shading);
870         aFilter->SetFaceBoundaryDraw (toDraw != 0);
871         aFilter->Modified();
872         aFilter->Update();
873       }
874     }
875   }
876
877   // Redraw window
878   GetInteractor()->Render();
879   return 0;
880 }
881
882 //================================================================
883 // Function  : VtkSetSelectionMode
884 // Purpose   :
885 //================================================================
886 static Standard_Integer VtkSetSelectionMode (Draw_Interpretor& ,
887                                              Standard_Integer theArgNum,
888                                              const char** theArgs)
889 {
890   if (!GetInteractor()
891    || !GetInteractor()->IsEnabled())
892   {
893     Message::SendFail() << "Error: call ivtkinit before";
894     return 1;
895   }
896   else if (theArgNum != 3 && theArgNum != 4)
897   {
898     Message::SendFail() << "Syntax error: expects 2 or 3 arguments";
899     return 1;
900   }
901
902   if (theArgNum == 3)
903   {
904     // Set sel mode for all objects
905     const Standard_Integer aMode = Draw::Atoi (theArgs[1]);
906     Standard_Boolean isTurnOn = true;
907     if (aMode < 0 || aMode > 8 || !Draw::ParseOnOff (theArgs[2], isTurnOn))
908     {
909       Message::SendFail() << "Syntax error: only 0-8 selection modes are supported";
910       return 1;
911     }
912     DoubleMapOfActorsAndNames::Iterator anIter (GetMapOfActors());
913     while (anIter.More())
914     {
915       vtkSmartPointer<vtkActor> anActor = anIter.Key1();
916       if (aMode == SM_Shape && isTurnOn)
917       {
918         IVtk_SelectionModeList aList = GetPicker()->GetSelectionModes (anActor);
919         IVtk_SelectionModeList::Iterator anIt (aList);
920         // Turn off all sel modes differed from SM_Shape
921         while (anIt.More())
922         {
923           IVtk_SelectionMode aCurMode = anIt.Value();
924           if (SM_Shape != aCurMode)
925           {
926             GetPicker()->SetSelectionMode (anActor, aCurMode, Standard_False);
927           }
928           anIt.Next();
929         }
930         GetPicker()->SetSelectionMode (anActor, SM_Shape);
931       }
932
933       if (aMode != SM_Shape)
934       {
935         if (isTurnOn)
936         {
937           GetPicker()->SetSelectionMode (anActor, (IVtk_SelectionMode)aMode);
938           GetPicker()->SetSelectionMode (anActor, SM_Shape, Standard_False);
939           if (aMode == SM_Vertex)
940           {
941             GetPipeline( IVtkTools_ShapeObject::GetShapeSource(anActor)->GetShape()->GetId() )->SharedVerticesSelectionOn();
942           }
943         }
944         else
945         {
946           GetPicker()->SetSelectionMode (anActor, (IVtk_SelectionMode)aMode, Standard_False);
947           IVtk_SelectionModeList aList = GetPicker()->GetSelectionModes (anActor);
948           if (!aList.Size())
949           {
950             GetPicker()->SetSelectionMode(anActor, SM_Shape);
951           }
952           if (aMode == SM_Vertex)
953           {
954             GetPipeline( IVtkTools_ShapeObject::GetShapeSource(anActor)->GetShape()->GetId() )->SharedVerticesSelectionOff();
955           }
956         }
957       }
958       anIter.Next();
959     }
960   }
961
962   if (theArgNum == 4)
963   {
964     // Set sel mode for named object
965     const Standard_Integer aMode = Draw::Atoi (theArgs[2]);
966     Standard_Boolean isTurnOn = true;
967     if (aMode < 0 || aMode > 8 || !Draw::ParseOnOff (theArgs[3], isTurnOn))
968     {
969       Message::SendFail() << "Syntax error: only 0-8 selection modes are supported";
970       return 1;
971     }
972
973     TCollection_AsciiString aName = theArgs[1];
974     if (GetMapOfActors().IsBound2 (aName))
975     {
976       vtkSmartPointer<vtkActor> anActor = GetMapOfActors().Find2 (aName);
977       if (aMode == SM_Shape && isTurnOn)
978       {
979         IVtk_SelectionModeList aList = GetPicker()->GetSelectionModes (anActor);
980         IVtk_SelectionModeList::Iterator anIt (aList);
981         // Turn off all sel modes differed from SM_Shape
982         while (anIt.More())
983         {
984           IVtk_SelectionMode aCurMode = anIt.Value();
985           if (SM_Shape != aCurMode)
986           {
987             GetPicker()->SetSelectionMode (anActor, aCurMode, Standard_False);
988           }
989           anIt.Next();
990         }
991         GetPicker()->SetSelectionMode (anActor, SM_Shape);
992       }
993
994       if (aMode != SM_Shape)
995       {
996         if (isTurnOn)
997         {
998           GetPicker()->SetSelectionMode (anActor, (IVtk_SelectionMode)aMode);
999           GetPicker()->SetSelectionMode (anActor, SM_Shape, Standard_False);
1000           if (aMode == SM_Vertex)
1001           {
1002             GetPipeline( IVtkTools_ShapeObject::GetShapeSource(anActor)->GetShape()->GetId() )->SharedVerticesSelectionOn();
1003           }
1004         }
1005         else
1006         {
1007           GetPicker()->SetSelectionMode (anActor, (IVtk_SelectionMode)aMode, Standard_False);
1008           IVtk_SelectionModeList aList = GetPicker()->GetSelectionModes (anActor);
1009           if (!aList.Size())
1010           {
1011             GetPicker()->SetSelectionMode(anActor, SM_Shape);
1012           }
1013           if (aMode == SM_Vertex)
1014           {
1015             GetPipeline( IVtkTools_ShapeObject::GetShapeSource(anActor)->GetShape()->GetId() )->SharedVerticesSelectionOff();
1016           }
1017         }
1018       }
1019     }
1020   }
1021
1022   // Redraw window
1023   GetInteractor()->Render();
1024   return 0;
1025 }
1026
1027 //================================================================
1028 // Function  : VtkSetColor
1029 // Purpose   :
1030 //================================================================
1031 static Standard_Integer VtkSetColor (Draw_Interpretor& ,
1032                                      Standard_Integer theArgNb,
1033                                      const char** theArgVec)
1034 {
1035   if (!GetInteractor()
1036    || !GetInteractor()->IsEnabled())
1037   {
1038     Message::SendFail() << "Error: call ivtkinit before\n";
1039     return 1;
1040   }
1041
1042   NCollection_Sequence< vtkSmartPointer<vtkActor> > anActorSeq;
1043   Quantity_Color aQColor;
1044   bool hasColor = false;
1045   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
1046   {
1047     TCollection_AsciiString anArg (theArgVec[anArgIter]);
1048     vtkSmartPointer<vtkActor> anActor;
1049     if (hasColor)
1050     {
1051       Message::SendFail() << "Syntax error at '" << anArg << "'";
1052       return 1;
1053     }
1054     else if (GetMapOfActors().Find2 (anArg, anActor))
1055     {
1056       anActorSeq.Append (anActor);
1057     }
1058     else
1059     {
1060       Standard_Integer aNbParsed = Draw::ParseColor (theArgNb  - anArgIter,
1061                                                      theArgVec + anArgIter,
1062                                                      aQColor);
1063       if (aNbParsed == 0)
1064       {
1065         Message::SendFail() << "Syntax error at '" << anArg << "'";
1066         return 1;
1067       }
1068       anArgIter += aNbParsed - 1;
1069       hasColor = true;
1070     }
1071   }
1072   if (!hasColor || anActorSeq.IsEmpty())
1073   {
1074     Message::SendFail() << "Syntax error: wrong number of arguments";
1075     return 1;
1076   }
1077
1078   bool isSRGBAware = false;
1079 #ifdef HAVE_VTK_SRGB
1080   isSRGBAware = GetRenderer()->GetRenderWindow()->GetUseSRGBColorSpace();
1081 #endif
1082   const Graphic3d_Vec3 aColor = isSRGBAware ? (Graphic3d_Vec3 )aQColor : Quantity_Color::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec3 )aQColor);
1083   for (NCollection_Sequence< vtkSmartPointer<vtkActor> >::Iterator anActorIter (anActorSeq); anActorIter.More(); anActorIter.Next())
1084   {
1085     const vtkSmartPointer<vtkActor>& anActor = anActorIter.Value();
1086     vtkLookupTable* aTable = (vtkLookupTable* )anActor->GetMapper()->GetLookupTable();
1087     IVtkTools::SetLookupTableColor (aTable, MT_ShadedFace, aColor.r(), aColor.g(), aColor.b(), 1.0);
1088   }
1089
1090   GetInteractor()->Render();
1091   return 0;
1092 }
1093
1094 //================================================================
1095 // Function  : VtkSetTransparency
1096 // Purpose   :
1097 //================================================================
1098 static Standard_Integer VtkSetTransparency (Draw_Interpretor& ,
1099                                             Standard_Integer theArgNb,
1100                                             const char** theArgVec)
1101 {
1102   if (!GetInteractor()
1103    || !GetInteractor()->IsEnabled())
1104   {
1105     Message::SendFail() << "Error: call ivtkinit before\n";
1106     return 1;
1107   }
1108
1109   NCollection_Sequence< vtkSmartPointer<vtkActor> > anActorSeq;
1110   Standard_Real aTransparency = -1.0;
1111   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
1112   {
1113     TCollection_AsciiString anArg (theArgVec[anArgIter]);
1114     vtkSmartPointer<vtkActor> anActor;
1115     if (aTransparency >= 0.0)
1116     {
1117       Message::SendFail() << "Syntax error at '" << anArg << "'";
1118       return 1;
1119     }
1120     else if (GetMapOfActors().Find2 (anArg, anActor))
1121     {
1122       anActorSeq.Append (anActor);
1123     }
1124     else if (!Draw::ParseReal (theArgVec[anArgIter], aTransparency)
1125            || aTransparency < 0.0
1126            || aTransparency >= 1.0)
1127     {
1128       Message::SendFail() << "Syntax error at '" << anArg << "'";
1129       return 1;
1130     }
1131   }
1132   if (aTransparency < 0.0 || aTransparency >= 1)
1133   {
1134     Message::SendFail() << "Syntax error: wrong number of arguments";
1135     return 1;
1136   }
1137
1138   for (NCollection_Sequence< vtkSmartPointer<vtkActor> >::Iterator anActorIter (anActorSeq); anActorIter.More(); anActorIter.Next())
1139   {
1140     const vtkSmartPointer<vtkActor>& anActor = anActorIter.Value();
1141     anActor->GetProperty()->SetOpacity (1.0 - aTransparency);
1142   }
1143
1144   GetInteractor()->Render();
1145   return 0;
1146 }
1147
1148 //================================================================
1149 // Function  : VtkMoveTo
1150 // Purpose   : 
1151 // Draw args : ivtkmoveto x y
1152 //================================================================
1153 static Standard_Integer VtkMoveTo(Draw_Interpretor& theDI,
1154                                   Standard_Integer theArgNum,
1155                                   const char** theArgs)
1156 {
1157   if (!GetInteractor()
1158    || !GetInteractor()->IsEnabled())
1159   {
1160     Message::SendFail() << "Error: call ivtkinit before";
1161     return 1;
1162   }
1163   else if (theArgNum != 3)
1164   {
1165     Message::SendFail() << "Syntax error: expects 2 arguments";
1166     return 1;
1167   }
1168
1169   Standard_Integer anY = GetInteractor()->GetRenderWindow()->GetSize()[1] - atoi (theArgs[2]) - 1;
1170   GetInteractor()->MoveTo (atoi (theArgs[1]), anY);
1171
1172   gp_XYZ aPickPnt;
1173   GetInteractor()->Selector()->GetPickPosition (aPickPnt.ChangeData());
1174   theDI << aPickPnt.X() << " " << aPickPnt.Y() << " " << aPickPnt.Z();
1175   return 0;
1176 }
1177
1178 //================================================================
1179 // Function  : VtkSelect
1180 // Purpose   :
1181 //================================================================
1182 static Standard_Integer VtkSelect (Draw_Interpretor& ,
1183                                    Standard_Integer theArgNum,
1184                                    const char** theArgs)
1185 {
1186   if (!GetInteractor()
1187    || !GetInteractor()->IsEnabled())
1188   {
1189     Message::SendFail() << "Error: call ivtkinit before";
1190     return 1;
1191   }
1192   else if (theArgNum != 3)
1193   {
1194     Message::SendFail() << "Syntax error: expects 3 arguments";
1195     return 1;
1196   }
1197
1198   Standard_Integer anY = GetInteractor()->GetRenderWindow()->GetSize()[1] - atoi (theArgs[2]) - 1;
1199   GetInteractor()->MoveTo (atoi (theArgs[1]), anY);
1200   GetInteractor()->OnSelection();
1201   return 0;
1202
1203 }
1204
1205 //===================================================================
1206 // Fubction  : VtkViewProj
1207 // Purpose   :
1208 //===================================================================
1209 static Standard_Integer VtkViewProj (Draw_Interpretor& ,
1210                                      Standard_Integer theNbArgs,
1211                                      const char** theArgVec)
1212 {
1213   if (!GetInteractor()
1214    || !GetInteractor()->IsEnabled())
1215   {
1216     Message::SendFail() << "Error: call ivtkinit before";
1217     return 1;
1218   }
1219   else if (theNbArgs != 1)
1220   {
1221     Message::SendFail() << "Syntax error: wrong number of arguments";
1222     return 1;
1223   }
1224
1225   TCollection_AsciiString aCmd (theArgVec[0]);
1226   aCmd.LowerCase();
1227
1228   V3d_TypeOfOrientation aProj = V3d_Xpos;
1229   bool hasProjDir = false;
1230   if (aCmd == "ivtkaxo")
1231   {
1232     hasProjDir = true;
1233     aProj = V3d_TypeOfOrientation_Zup_AxoRight;
1234   }
1235   else if (aCmd == "ivtktop")
1236   {
1237     hasProjDir = true;
1238     aProj = V3d_TypeOfOrientation_Zup_Top;
1239   }
1240   else if (aCmd == "ivtkbottom")
1241   {
1242     hasProjDir = true;
1243     aProj = V3d_TypeOfOrientation_Zup_Bottom;
1244   }
1245   else if (aCmd == "ivtkfront")
1246   {
1247     hasProjDir = true;
1248     aProj = V3d_TypeOfOrientation_Zup_Front;
1249   }
1250   else if (aCmd == "ivtkback")
1251   {
1252     hasProjDir = true;
1253     aProj = V3d_TypeOfOrientation_Zup_Back;
1254   }
1255   else if (aCmd == "ivtkleft")
1256   {
1257     hasProjDir = true;
1258     aProj = V3d_TypeOfOrientation_Zup_Left;
1259   }
1260   else if (aCmd == "ivtkright")
1261   {
1262     hasProjDir = true;
1263     aProj = V3d_TypeOfOrientation_Zup_Right;
1264   }
1265
1266   if (hasProjDir)
1267   {
1268     const gp_Dir aBck = V3d::GetProjAxis (aProj);
1269     Graphic3d_Vec3d anUp (0.0, 0.0, 1.0);
1270     if (aProj == V3d_Zpos)
1271     {
1272       anUp.SetValues (0.0, 1.0, 0.0);
1273     }
1274     else if (aProj == V3d_Zneg)
1275     {
1276       anUp.SetValues (0.0, -1.0, 0.0);
1277     }
1278
1279     vtkCamera* aCam = GetRenderer()->GetActiveCamera();
1280     const double aDist = aCam->GetDistance();
1281
1282     Graphic3d_Vec3d aNewEye = Graphic3d_Vec3d (aBck.X(), aBck.Y(), aBck.Z()) * aDist;
1283     aCam->SetPosition (aNewEye.x(), aNewEye.y(), aNewEye.z());
1284     aCam->SetFocalPoint (0.0, 0.0, 0.0);
1285     aCam->SetViewUp (anUp.x(), anUp.y(), anUp.z());
1286     aCam->OrthogonalizeViewUp();
1287   }
1288
1289   GetRenderer()->ResetCamera();
1290   GetInteractor()->Render();
1291   return 0;
1292 }
1293
1294 //===================================================================
1295 // Fubction  : VtkDump
1296 // Purpose   :
1297 //===================================================================
1298 static Standard_Integer VtkDump (Draw_Interpretor& ,
1299                                  Standard_Integer theArgNum,
1300                                  const char** theArgs)
1301 {
1302   if (!GetInteractor()
1303    || !GetInteractor()->IsEnabled())
1304   {
1305     Message::SendFail() << "Error : call ivtkinit before";
1306     return 1;
1307   }
1308   else if (theArgNum < 2)
1309   {
1310     Message::SendFail() << "Syntax error: wrong number of parameters";
1311     return 1;
1312   }
1313
1314   vtkSmartPointer<vtkWindowToImageFilter> anImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
1315   anImageFilter->SetInput (GetInteractor()->GetRenderWindow());
1316   // Set custom buffer type
1317   if (theArgNum > 2)
1318   {
1319     TCollection_AsciiString aBufferType (theArgs[2]);
1320     aBufferType.LowerCase();
1321     if (aBufferType.IsEqual ("rgb"))
1322     {
1323       anImageFilter->SetInputBufferTypeToRGB();
1324     }
1325     else if (aBufferType.IsEqual ("rgba"))
1326     {
1327       anImageFilter->SetInputBufferTypeToRGBA();
1328     }
1329     else if (aBufferType.IsEqual ("depth"))
1330     {
1331       anImageFilter->SetInputBufferTypeToZBuffer();
1332     }
1333   }
1334   anImageFilter->Update();
1335
1336   // Set custom stereo projection options
1337   if (theArgNum > 5 && GetRenderer()->GetRenderWindow()->GetStereoRender())
1338   {
1339     Standard_CString aStereoProjStr = theArgs[5];
1340
1341     Standard_Integer aStereoType =  GetRenderer()->GetRenderWindow()->GetStereoType();
1342     if (strcasecmp (aStereoProjStr, "L"))
1343     {
1344       GetRenderer()->GetRenderWindow()->SetStereoTypeToLeft();
1345       GetRenderer()->GetRenderWindow()->StereoUpdate();
1346       anImageFilter->Update();
1347       GetRenderer()->GetRenderWindow()->SetStereoType (aStereoType);
1348     }
1349     else if (strcasecmp (aStereoProjStr, "R"))
1350     {
1351       GetRenderer()->GetRenderWindow()->SetStereoTypeToRight();
1352       GetRenderer()->GetRenderWindow()->StereoUpdate();
1353       anImageFilter->Update();
1354       GetRenderer()->GetRenderWindow()->SetStereoType (aStereoType);
1355     }
1356     else
1357     {
1358       Message::SendFail() << "Syntax error: unknown value for stereo projection";
1359       return 1;
1360     }
1361   }
1362
1363   // Set parameters for image writer
1364   vtkSmartPointer<vtkImageWriter> anImageWriter;
1365   TCollection_AsciiString aFilename (theArgs[1]);
1366   Standard_Integer anExtStart = aFilename.SearchFromEnd (TCollection_AsciiString("."));
1367   TCollection_AsciiString aFormat = (anExtStart == -1) ? TCollection_AsciiString("")
1368                                     : aFilename.SubString (anExtStart + 1, aFilename.Length());
1369   aFormat.LowerCase();
1370
1371   if (aFormat.IsEqual ("png"))
1372   {
1373     anImageWriter = vtkSmartPointer<vtkPNGWriter>::New();
1374   }
1375   else if (aFormat.IsEqual ("bmp"))
1376   {
1377     anImageWriter = vtkSmartPointer<vtkBMPWriter>::New();
1378   }
1379   else if (aFormat.IsEqual ("jpeg"))
1380   {
1381     anImageWriter = vtkSmartPointer<vtkJPEGWriter>::New();
1382   }
1383   else if (aFormat.IsEqual ("tiff"))
1384   {
1385     anImageWriter = vtkSmartPointer<vtkTIFFWriter>::New();
1386   }
1387   else if (aFormat.IsEqual ("pnm"))
1388   {
1389     anImageWriter = vtkSmartPointer<vtkPNMWriter>::New();
1390   }
1391   else // aFormat is unsupported or not set.
1392   {
1393     if (aFormat.IsEmpty())
1394     {
1395       Message::SendWarning() << "Warning: the image format is not set.\n"
1396             << "The image will be saved into PNG format.";
1397       anImageWriter = vtkSmartPointer<vtkPNGWriter>::New();
1398       aFormat = TCollection_AsciiString ("png");
1399       if (anExtStart != -1)
1400       {
1401         aFilename.Split (anExtStart);
1402       }
1403       else
1404       {
1405         aFilename += ".";
1406       }
1407       aFilename += aFormat;
1408     }
1409     else
1410     {
1411       Message::SendFail() << "Error: the image format " << aFormat << " is not supported";
1412       return 1;
1413     }
1414
1415   }
1416
1417   anImageWriter->SetFileName (aFilename.ToCString());
1418
1419   Standard_Integer aWidth = (theArgNum > 3) ? atoi (theArgs[3]) : 0;
1420   Standard_Integer aHeight = (theArgNum > 4) ? atoi (theArgs[4]) : 0;
1421   if (aWidth >= 0 || aHeight >= 0)
1422   {
1423     // Scale image
1424     vtkSmartPointer<vtkImageResize> anImageResize = vtkSmartPointer<vtkImageResize>::New();
1425 #if VTK_MAJOR_VERSION <= 5
1426     anImageResize->SetInput (anImageFilter->GetOutput());
1427 #else
1428     anImageResize->SetInputData (anImageFilter->GetOutput());
1429 #endif
1430
1431     anImageResize->SetOutputDimensions (aWidth, aHeight, 1);
1432     anImageResize->Update();
1433     anImageWriter->SetInputConnection (anImageResize->GetOutputPort());
1434   }
1435   else
1436   {
1437     anImageWriter->SetInputConnection (anImageFilter->GetOutputPort());
1438   }
1439   anImageWriter->Write();
1440   return 0;
1441 }
1442
1443 //===================================================================
1444 // Fubction  : VtkBackgroundColor
1445 // Purpose   :
1446 //===================================================================
1447 static Standard_Integer VtkBackgroundColor (Draw_Interpretor& ,
1448                                             Standard_Integer theArgNum,
1449                                             const char** theArgs)
1450 {
1451   if (!GetInteractor()
1452    || !GetInteractor()->IsEnabled())
1453   {
1454     Message::SendFail() << "Error: call ivtkinit before";
1455     return 1;
1456   }
1457
1458   Quantity_Color aQColor1;
1459   const Standard_Integer aNbParsed1 = Draw::ParseColor (theArgNum - 1, theArgs + 1, aQColor1);
1460   if (aNbParsed1 == 0)
1461   {
1462     Message::SendFail() << "Syntax error: wrong number of parameters";
1463     return 1;
1464   }
1465
1466   bool isSRGBAware = false;
1467 #ifdef HAVE_VTK_SRGB
1468   isSRGBAware = GetRenderer()->GetRenderWindow()->GetUseSRGBColorSpace();
1469 #endif
1470   const Graphic3d_Vec3 aColor1 = isSRGBAware ? (Graphic3d_Vec3 )aQColor1 : Quantity_Color::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec3 )aQColor1);
1471   GetRenderer()->SetGradientBackground(false);
1472   GetRenderer()->SetBackground (aColor1.r(), aColor1.g(), aColor1.b());
1473   if (theArgNum - 1 > aNbParsed1)
1474   {
1475     Quantity_Color aQColor2;
1476     const Standard_Integer aNbParsed2 = Draw::ParseColor (theArgNum - 1 - aNbParsed1, theArgs + 1 + aNbParsed1, aQColor2);
1477     if (aNbParsed2 == 0)
1478     {
1479       Message::SendFail() << "Syntax error: wrong number of parameters";
1480       return 1;
1481     }
1482
1483     const Graphic3d_Vec3 aColor2 = isSRGBAware ? (Graphic3d_Vec3 )aQColor2 : Quantity_Color::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec3 )aQColor2);
1484     GetRenderer()->SetBackground2 (aColor2.r(), aColor2.g(), aColor2.b());
1485     GetRenderer()->SetGradientBackground (true);
1486   }
1487
1488   GetInteractor()->Render();
1489   return 0;
1490 }
1491
1492 //================================================================
1493 // Function : Commands
1494 // Purpose  : 
1495 //================================================================
1496 void IVtkDraw::Commands (Draw_Interpretor& theCommands)
1497 {
1498   const char *group = "VtkViewer";
1499
1500   theCommands.Add("ivtkinit",
1501               "ivtkinit [leftPx topPx widthPx heightPx] [-srgb {on|off}] [-msaa NbSamples]"
1502       "\n\t\t: Creates the Vtk window."
1503       "\n\t\t:  -srgb Enable/disable sRGB colorspace; OFF by default."
1504       "\n\t\t:  -msaa Requests desired number of samples for multisampling buffer;"
1505       "\n\t\t:        0 by default meaning no MSAA.",
1506     __FILE__, VtkInit, group);
1507
1508   theCommands.Add("ivtkclose",
1509               "ivtkclose : Closes the Vtk window.",
1510     __FILE__, VtkClose, group);
1511
1512   theCommands.Add("ivtkrenderparams",
1513               "ivtkrenderparams [-depthPeeling NbLayers] [-shadows {on|off}]"
1514       "\n\t\t: Sets Vtk rendering parameters."
1515       "\n\t\t:  -shadows      Turn shadows on/off; OFF by default."
1516       "\n\t\t:  -depthPeeling Enable/disable depth peeling for rendering transparent objects"
1517       "\n\t\t:                with specified number of layers;"
1518       "\n\t\t:                0 by default meaning order-dependent transparency without depth peeling.",
1519     __FILE__, VtkRenderParams, group);
1520
1521   theCommands.Add("ivtkdisplay",
1522               "ivtkdisplay name1 [name2 ...]"
1523       "\n\t\t: Displays named objects in Vtk view.",
1524     __FILE__, VtkDisplay, group);
1525
1526   theCommands.Add("ivtkerase",
1527               "ivtkerase [name1 name2 ...]"
1528       "\n\t\t: Hides in Vtk renderer named objects or all objects.",
1529     __FILE__, VtkErase, group);
1530
1531   theCommands.Add("ivtkremove",
1532               "ivtkremove name1 [name2 ...]"
1533       "\n\t\t: Removes from Vtk renderer named objects.",
1534     __FILE__, VtkRemove, group);
1535
1536   theCommands.Add("ivtkclear",
1537               "ivtkclear : Removes all objects from Vtk renderer.",
1538     __FILE__, VtkRemove, group);
1539
1540   theCommands.Add("ivtksetdispmode",
1541               "ivtksetdispmode [name] mode={0|1}"
1542       "\n\t\t: Sets or unsets display mode 'mode' to the object with name 'name' or to all objects.",
1543     __FILE__, VtkSetDisplayMode, group);
1544
1545   theCommands.Add("ivtksetboundingdraw",
1546               "ivtksetboundingdraw [name] {on|off}"
1547       "\n\t\t: Sets or unsets boundaries drawing for shading display mode"
1548       "\n\t\t: to the object with name 'name' or to all objects.",
1549     __FILE__, VtkSetBoundaryDraw, group);
1550
1551   theCommands.Add("ivtksetselmode",
1552               "ivtksetselmode [name] mode {on|off}"
1553       "\n\t\t: Sets or unsets selection mode 'mode' to the object with name 'name'"
1554       "\n\t\t: or to the all displayed objects.",
1555     __FILE__, VtkSetSelectionMode, group);
1556
1557   theCommands.Add("ivtkmoveto",
1558               "ivtkmoveto x y"
1559       "\n\t\t: Moves position to the pixel with coordinates (x,y). The object on this position is highlighted.",
1560     __FILE__, VtkMoveTo, group);
1561
1562   theCommands.Add("ivtkselect",
1563               "ivtkselect x y"
1564       "\n\t\t: Selects object which correspond to the pixel with input coordinates (x,y).",
1565     __FILE__, VtkSelect, group);
1566
1567   theCommands.Add("ivtkfit",
1568               "ivtkfit : Fits all displayed objects into Vtk view.",
1569     __FILE__, VtkViewProj, group);
1570
1571   theCommands.Add("ivtkaxo",
1572               "ivtkaxo : Resets Vtk view orientation to axo",
1573     __FILE__, VtkViewProj, group);
1574
1575   theCommands.Add("ivtkfront",
1576               "ivtkfront : Resets Vtk view orientation to front",
1577     __FILE__, VtkViewProj, group);
1578
1579   theCommands.Add("ivtkback",
1580               "ivtkback : Resets Vtk view orientation to back",
1581     __FILE__, VtkViewProj, group);
1582
1583   theCommands.Add("ivtktop",
1584               "ivtktop : Resets Vtk view orientation to top",
1585     __FILE__, VtkViewProj, group);
1586
1587   theCommands.Add("ivtkbottom",
1588               "ivtkbottom : Resets Vtk view orientation to bottom",
1589     __FILE__, VtkViewProj, group);
1590
1591   theCommands.Add("ivtkleft",
1592               "ivtkleft : Resets Vtk view orientation to left",
1593     __FILE__, VtkViewProj, group);
1594
1595   theCommands.Add("ivtkright",
1596               "ivtkright : Resets Vtk view orientation to right",
1597     __FILE__, VtkViewProj, group);
1598
1599   theCommands.Add("ivtkdump",
1600               "ivtkdump <FullFilename>.{png|bmp|jpeg|tiff|pnm} [buffer={rgb|rgba|depth}]"
1601       "\n\t\t:          [width height] [stereoproj={L|R}]"
1602       "\n\t\t: Dumps contents of viewer window to PNG, BMP, JPEG, TIFF or PNM file.",
1603     __FILE__, VtkDump, group);
1604
1605   theCommands.Add("ivtkbgcolor",
1606               "ivtkbgcolor Color1 [Color2]"
1607       "\n\t\t: Sets uniform background color or gradient one if second triple of parameters is set.",
1608     __FILE__, VtkBackgroundColor, group);
1609
1610   theCommands.Add("ivtksetcolor",
1611               "ivtksetcolor name {ColorName|R G B}"
1612       "\n\t\t: Sets color to the object with name 'name'.",
1613     __FILE__, VtkSetColor, group);
1614
1615   theCommands.Add("ivtksettransparency",
1616               "ivtksettransparency name 0..1"
1617       "\n\t\t: Sets transparency to the object with name 'name'.",
1618     __FILE__, VtkSetTransparency, group);
1619 }
1620
1621 //================================================================
1622 // Function : Factory
1623 // Purpose  : 
1624 //================================================================
1625 void IVtkDraw::Factory (Draw_Interpretor& theDI)
1626 {
1627   // definition of Viewer Commands
1628   IVtkDraw::Commands (theDI);
1629 }
1630
1631 // Declare entry point PLUGINFACTORY
1632 DPLUGIN(IVtkDraw)