1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4 
5   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
6   All rights reserved.
7   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 
15 
16 // This tests vtkVisibleCellSelector, vtkExtractSelectedFrustum,
17 // vtkRenderedAreaPicker, and vtkInteractorStyleRubberBandPick.
18 //
19 // The command line arguments are:
20 // -I        => run in interactive mode; unless this is used, the program will
21 //              not allow interaction and exit
22 
23 #include "vtkTestUtilities.h"
24 #include "vtkRegressionTestImage.h"
25 
26 #include "vtkRenderer.h"
27 #include "vtkRenderWindow.h"
28 #include "vtkRenderWindowInteractor.h"
29 #include "vtkSphereSource.h"
30 #include "vtkActor.h"
31 #include "vtkInteractorStyleRubberBandPick.h"
32 #include "vtkCommand.h"
33 #include "vtkHardwareSelector.h"
34 #include "vtkSelection.h"
35 #include "vtkIdTypeArray.h"
36 #include "vtkRenderedAreaPicker.h"
37 #include "vtkCamera.h"
38 #include "vtkImageActor.h"
39 #include "vtkPointData.h"
40 #include "vtkPlaneSource.h"
41 #include "vtkElevationFilter.h"
42 #include "vtkBitArray.h"
43 #include "vtkGlyph3DMapper.h"
44 #include "vtkSelection.h"
45 #include "vtkSelectionNode.h"
46 #include <cassert>
47 
48 static vtkRenderer *renderer = nullptr;
49 
50 class MyEndPickCommand : public vtkCommand
51 {
52 public:
MyEndPickCommand()53   MyEndPickCommand()
54   {
55     this->Renderer=nullptr; // no reference counting
56     this->Mask=nullptr; // no reference counting
57     this->DataSet=nullptr;
58   }
59 
~MyEndPickCommand()60   ~MyEndPickCommand() override
61   {
62     // empty
63   }
64 
Execute(vtkObject * vtkNotUsed (caller),unsigned long vtkNotUsed (eventId),void * vtkNotUsed (callData))65   void Execute(vtkObject *vtkNotUsed(caller),
66     unsigned long vtkNotUsed(eventId),
67     void *vtkNotUsed(callData)) override
68   {
69     assert("pre: renderer_exists" && this->Renderer!=nullptr);
70 
71     vtkHardwareSelector *sel = vtkHardwareSelector::New();
72     sel->SetFieldAssociation(vtkDataObject::FIELD_ASSOCIATION_CELLS);
73     sel->SetRenderer(renderer);
74 
75     double x0 = renderer->GetPickX1();
76     double y0 = renderer->GetPickY1();
77     double x1 = renderer->GetPickX2();
78     double y1 = renderer->GetPickY2();
79     sel->SetArea(static_cast<unsigned int>(x0),
80       static_cast<unsigned int>(y0),
81       static_cast<unsigned int>(x1),
82       static_cast<unsigned int>(y1));
83 
84     vtkSelection *res = sel->Select();
85 
86 #if 1
87     cerr << "x0 " << x0 << " y0 " << y0 << "\t";
88     cerr << "x1 " << x1 << " y1 " << y1 << endl;
89     res->Print(cout);
90 #endif
91 
92     // Reset the mask to false.
93     vtkIdType numPoints = this->Mask->GetNumberOfTuples();
94     for (vtkIdType i=0; i < numPoints; i++)
95     {
96       this->Mask->SetValue(i,false);
97     }
98 
99     vtkSelectionNode *glyphids = res->GetNode(0);
100     if (glyphids!=nullptr)
101     {
102       vtkAbstractArray *abs=glyphids->GetSelectionList();
103       if(abs==nullptr)
104       {
105         cout<<"abs is null"<<endl;
106       }
107       vtkIdTypeArray *ids=vtkArrayDownCast<vtkIdTypeArray>(abs);
108       if(ids==nullptr)
109       {
110         cout<<"ids is null"<<endl;
111       }
112       else
113       {
114         // modify mask array with selection.
115         vtkIdType numSelPoints = ids->GetNumberOfTuples();
116         for (vtkIdType i =0; i < numSelPoints; i++)
117         {
118           vtkIdType value = ids->GetValue(i);
119           if (value >=0 && value < numPoints)
120           {
121             cout << "Turn On: " << value << endl;
122             this->Mask->SetValue(value,true);
123           }
124           else
125           {
126             cout << "Ignoring: " << value << endl;
127           }
128         }
129       }
130     }
131     this->DataSet->Modified();
132 
133     sel->Delete();
134     res->Delete();
135   }
136 
SetRenderer(vtkRenderer * r)137   void SetRenderer(vtkRenderer *r)
138   {
139     this->Renderer=r;
140   }
141 
GetRenderer() const142   vtkRenderer *GetRenderer() const
143   {
144     return this->Renderer;
145   }
146 
SetMask(vtkBitArray * m)147   void SetMask(vtkBitArray *m)
148   {
149     this->Mask=m;
150   }
SetDataSet(vtkDataSet * ds)151   void SetDataSet(vtkDataSet* ds)
152   {
153     this->DataSet = ds;
154   }
155 
156 protected:
157   vtkRenderer *Renderer;
158   vtkBitArray *Mask;
159   vtkDataSet *DataSet;
160 };
161 
TestGlyph3DMapperCellPicking(int argc,char * argv[])162 int TestGlyph3DMapperCellPicking(int argc, char* argv[])
163 {
164   int res=1;
165   vtkPlaneSource *plane=vtkPlaneSource::New();
166   plane->SetResolution(res,res);
167   vtkElevationFilter *colors=vtkElevationFilter::New();
168   colors->SetInputConnection(plane->GetOutputPort());
169   plane->Delete();
170   colors->SetLowPoint(-1,-1,-1);
171   colors->SetHighPoint(0.5,0.5,0.5);
172 
173   vtkSphereSource *squad=vtkSphereSource::New();
174   squad->SetPhiResolution(4);
175   squad->SetThetaResolution(6);
176 
177   vtkGlyph3DMapper *glypher=vtkGlyph3DMapper::New();
178   glypher->SetInputConnection(colors->GetOutputPort());
179   colors->Delete();
180   glypher->SetScaleFactor(1.5);
181   glypher->SetSourceConnection(squad->GetOutputPort());
182   squad->Delete();
183 
184   // selection is performed on actor1
185   vtkActor *glyphActor1=vtkActor::New();
186   glyphActor1->SetMapper(glypher);
187   glypher->Delete();
188   glyphActor1->PickableOn();
189 
190   // result of selection is on actor2
191   vtkActor *glyphActor2=vtkActor::New();
192   glyphActor2->PickableOff();
193   colors->Update(); // make sure output is valid.
194   vtkDataSet *selection=colors->GetOutput()->NewInstance();
195   selection->ShallowCopy(colors->GetOutput());
196 
197   vtkBitArray *selectionMask=vtkBitArray::New();
198   selectionMask->SetName("mask");
199   selectionMask->SetNumberOfComponents(1);
200   selectionMask->SetNumberOfTuples(selection->GetNumberOfPoints());
201   // Initially, everything is selected
202   vtkIdType i=0;
203   vtkIdType c=selectionMask->GetNumberOfTuples();
204   while(i<c)
205   {
206       selectionMask->SetValue(i,true);
207       ++i;
208   }
209   selection->GetPointData()->AddArray(selectionMask);
210   selectionMask->Delete();
211 
212   vtkGlyph3DMapper *glypher2=vtkGlyph3DMapper::New();
213   //  glypher->SetNestedDisplayLists(0);
214   glypher2->SetMasking(1);
215   glypher2->SetMaskArray("mask");
216 
217   glypher2->SetInputData(selection);
218   glypher2->SetScaleFactor(1.5);
219   glypher2->SetSourceConnection(squad->GetOutputPort());
220   glyphActor2->SetMapper(glypher2);
221   glypher2->Delete();
222 
223   // Standard rendering classes
224   renderer = vtkRenderer::New();
225   vtkRenderWindow *renWin = vtkRenderWindow::New();
226   renWin->AddRenderer(renderer);
227   renWin->SetMultiSamples(0);
228   vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
229   iren->SetRenderWindow(renWin);
230 
231   //set up the view
232   renderer->SetBackground(0.2,0.2,0.2);
233   renWin->SetSize(600,300);
234 
235   //use the rubber band pick interactor style
236   vtkRenderWindowInteractor* rwi = renWin->GetInteractor();
237   vtkInteractorStyleRubberBandPick *rbp =
238     vtkInteractorStyleRubberBandPick::New();
239   rwi->SetInteractorStyle(rbp);
240 
241   vtkRenderedAreaPicker *areaPicker = vtkRenderedAreaPicker::New();
242   rwi->SetPicker(areaPicker);
243 
244   renderer->AddActor(glyphActor1);
245   renderer->AddActor(glyphActor2);
246   glyphActor2->SetPosition(2,0,0);
247   glyphActor1->Delete();
248   glyphActor2->Delete();
249 
250   //pass pick events to the VisibleGlyphSelector
251   MyEndPickCommand *cbc=new MyEndPickCommand;
252   cbc->SetRenderer(renderer);
253   cbc->SetMask(selectionMask);
254   cbc->SetDataSet(selection);
255   rwi->AddObserver(vtkCommand::EndPickEvent,cbc);
256   cbc->Delete();
257 
258   ////////////////////////////////////////////////////////////
259 
260   //run the test
261 
262   renderer->ResetCamera();
263   renderer->GetActiveCamera()->Zoom(2.0);
264 
265   renWin->Render();
266   // areaPicker->AreaPick(0, 0, 241, 160, renderer);
267   areaPicker->AreaPick(233, 120, 241, 160, renderer);
268   cbc->Execute(nullptr, 0, nullptr);
269   renWin->Render();
270 
271   int retVal = vtkRegressionTestImage( renWin );
272   if ( retVal == vtkRegressionTester::DO_INTERACTOR)
273   {
274     iren->Start();
275   }
276 
277   // Cleanup
278   renderer->Delete();
279   renWin->Delete();
280   iren->Delete();
281   rbp->Delete();
282   areaPicker->Delete();
283   selection->Delete();
284   return !retVal;
285 }
286