1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: TestPickingManagerWidgets.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 /*==============================================================================
17
18 Library: MSVTK
19
20 Copyright (c) Kitware Inc.
21
22 Licensed under the Apache License, Version 2.0 (the "License");
23 you may not use this file except in compliance with the License.
24 You may obtain a copy of the License at
25
26 http://www.apache.org/licenses/LICENSE-2.0.txt
27
28 Unless required by applicable law or agreed to in writing, software
29 distributed under the License is distributed on an "AS IS" BASIS,
30 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 See the License for the specific language governing permissions and
32 limitations under the License.
33
34 ==============================================================================*/
35
36 //
37 // This example tests the PickingManager using different widgets and associated
38 // pickers:
39 // * vtkBalloonWidget
40 // * vtkBoxWidget
41 // * vtkImplicitPlaneWidget2
42 // By default the Picking Manager is enabled.
43 // Press 'Ctrl' to switch the activation of the Picking Manager.
44 // Press 'o' to enable/disable the Optimization on render events.
45
46 #include "vtkActor.h"
47 #include "vtkAppendPolyData.h"
48 #include "vtkBalloonRepresentation.h"
49 #include "vtkBalloonWidget.h"
50 #include "vtkBoxWidget.h"
51 #include "vtkCamera.h"
52 #include "vtkClipPolyData.h"
53 #include "vtkCommand.h"
54 #include "vtkConeSource.h"
55 #include "vtkCylinderSource.h"
56 #include "vtkGlyph3D.h"
57 #include "vtkImplicitPlaneRepresentation.h"
58 #include "vtkImplicitPlaneWidget2.h"
59 #include "vtkInteractorStyleTrackballCamera.h"
60 #include "vtkLODActor.h"
61 #include "vtkNew.h"
62 #include "vtkPickingManager.h"
63 #include "vtkPlane.h"
64 #include "vtkPolyData.h"
65 #include "vtkPolyDataMapper.h"
66 #include "vtkPropPicker.h"
67 #include "vtkProperty.h"
68 #include "vtkRenderWindow.h"
69 #include "vtkRenderWindowInteractor.h"
70 #include "vtkRenderer.h"
71 #include "vtkSmartPointer.h"
72 #include "vtkSphereSource.h"
73
74 //------------------------------------------------------------------------------
75 class vtkBalloonPickCallback : public vtkCommand
76 {
77 public:
New()78 static vtkBalloonPickCallback* New() { return new vtkBalloonPickCallback; }
Execute(vtkObject * caller,unsigned long,void *)79 void Execute(vtkObject* caller, unsigned long, void*) override
80 {
81 vtkPropPicker* picker = reinterpret_cast<vtkPropPicker*>(caller);
82 vtkProp* prop = picker->GetViewProp();
83 if (prop != nullptr)
84 {
85 this->BalloonWidget->UpdateBalloonString(prop, "Picked");
86 }
87 }
88
89 vtkBalloonWidget* BalloonWidget;
90 };
91
92 //------------------------------------------------------------------------------
93 // Updates the vtkPlane implicit function.
94 // This in turn causes the pipeline to update and clip the object.
95 // Callback for the interaction
96 class vtkTIPW2Callback : public vtkCommand
97 {
98 public:
New()99 static vtkTIPW2Callback* New() { return new vtkTIPW2Callback; }
Execute(vtkObject * caller,unsigned long,void *)100 void Execute(vtkObject* caller, unsigned long, void*) override
101 {
102 vtkImplicitPlaneWidget2* planeWidget = reinterpret_cast<vtkImplicitPlaneWidget2*>(caller);
103 vtkImplicitPlaneRepresentation* rep =
104 reinterpret_cast<vtkImplicitPlaneRepresentation*>(planeWidget->GetRepresentation());
105 rep->GetPlane(this->Plane);
106 this->Actor->VisibilityOn();
107 }
108
vtkTIPW2Callback()109 vtkTIPW2Callback()
110 : Plane(nullptr)
111 , Actor(nullptr)
112 {
113 }
114 vtkPlane* Plane;
115 vtkActor* Actor;
116 };
117
118 //------------------------------------------------------------------------------
119 // Press 'Ctrl' to switch the activation of the Picking Manager.
120 // Press 'o' to switch the activation of the optimization based on the render
121 // events.
122 class vtkEnableManagerCallback : public vtkCommand
123 {
124 public:
New()125 static vtkEnableManagerCallback* New() { return new vtkEnableManagerCallback; }
126
Execute(vtkObject * caller,unsigned long,void *)127 void Execute(vtkObject* caller, unsigned long, void*) override
128 {
129 vtkRenderWindowInteractor* iren = static_cast<vtkRenderWindowInteractor*>(caller);
130
131 if ((vtkStdString(iren->GetKeySym()) == "Control_L" ||
132 vtkStdString(iren->GetKeySym()) == "Control_R") &&
133 iren->GetPickingManager())
134 {
135 if (!iren->GetPickingManager()->GetEnabled())
136 {
137 std::cout << "PickingManager ON !" << std::endl;
138 iren->GetPickingManager()->EnabledOn();
139 }
140 else
141 {
142 std::cout << "PickingManager OFF !" << std::endl;
143 iren->GetPickingManager()->EnabledOff();
144 }
145 }
146 // Enable/Disable the Optimization on render events.
147 else if (vtkStdString(iren->GetKeySym()) == "o" && iren->GetPickingManager())
148 {
149 if (!iren->GetPickingManager()->GetOptimizeOnInteractorEvents())
150 {
151 std::cout << "Optimization on Interactor events ON !" << std::endl;
152 iren->GetPickingManager()->SetOptimizeOnInteractorEvents(true);
153 }
154 else
155 {
156 std::cout << "Optimization on Interactor events OFF !" << std::endl;
157 iren->GetPickingManager()->SetOptimizeOnInteractorEvents(false);
158 }
159 }
160 }
161
162 vtkEnableManagerCallback() = default;
163 };
164
165 //------------------------------------------------------------------------------
166 // Test Picking Manager with a several widgets
167 //------------------------------------------------------------------------------
TestPickingManagerWidgets(int vtkNotUsed (argc),char * vtkNotUsed (argv)[])168 int TestPickingManagerWidgets(int vtkNotUsed(argc), char* vtkNotUsed(argv)[])
169 {
170 // Create the RenderWindow, Renderer and both Actors
171 //
172 vtkNew<vtkRenderer> ren1;
173 vtkNew<vtkRenderWindow> renWin;
174 renWin->AddRenderer(ren1);
175
176 vtkNew<vtkRenderWindowInteractor> iren;
177 vtkNew<vtkInteractorStyleTrackballCamera> irenStyle;
178 iren->SetRenderWindow(renWin);
179 iren->SetInteractorStyle(irenStyle);
180
181 // Instantiate a picker and link it to the ballonWidgetCallback
182 vtkNew<vtkPropPicker> picker;
183 vtkNew<vtkBalloonPickCallback> pcbk;
184 picker->AddObserver(vtkCommand::PickEvent, pcbk);
185 iren->SetPicker(picker);
186
187 /*--------------------------------------------------------------------------*/
188 // PICKING MANAGER
189 /*--------------------------------------------------------------------------*/
190 // Callback to switch between the managed and non-managed mode of the
191 // Picking Manager
192 vtkNew<vtkEnableManagerCallback> callMode;
193 iren->AddObserver(vtkCommand::KeyPressEvent, callMode);
194
195 /*--------------------------------------------------------------------------*/
196 // BALLOON WIDGET
197 /*--------------------------------------------------------------------------*/
198 // Create a test pipeline
199 vtkNew<vtkSphereSource> ss;
200 vtkNew<vtkPolyDataMapper> mapper;
201 mapper->SetInputConnection(ss->GetOutputPort());
202 vtkNew<vtkActor> sph;
203 sph->SetMapper(mapper);
204
205 vtkNew<vtkCylinderSource> cs;
206 vtkNew<vtkPolyDataMapper> csMapper;
207 csMapper->SetInputConnection(cs->GetOutputPort());
208 vtkNew<vtkActor> cyl;
209 cyl->SetMapper(csMapper);
210 cyl->AddPosition(5, 0, 0);
211
212 vtkNew<vtkConeSource> coneSource;
213 vtkNew<vtkPolyDataMapper> coneMapper;
214 coneMapper->SetInputConnection(coneSource->GetOutputPort());
215 vtkNew<vtkActor> cone;
216 cone->SetMapper(coneMapper);
217 cone->AddPosition(0, 5, 0);
218
219 // Create the widget
220 vtkNew<vtkBalloonRepresentation> rep;
221 rep->SetBalloonLayoutToImageRight();
222
223 vtkNew<vtkBalloonWidget> widget;
224 widget->SetInteractor(iren);
225 widget->SetRepresentation(rep);
226 widget->AddBalloon(sph, "This is a sphere", nullptr);
227 widget->AddBalloon(cyl, "This is a\ncylinder", nullptr);
228 widget->AddBalloon(cone, "This is a\ncone,\na really big.", nullptr);
229 pcbk->BalloonWidget = widget;
230
231 /*--------------------------------------------------------------------------*/
232 // BOX WIDGET
233 /*--------------------------------------------------------------------------*/
234 vtkNew<vtkBoxWidget> boxWidget;
235 boxWidget->SetInteractor(iren);
236 boxWidget->SetPlaceFactor(1.25);
237
238 // Create the mass actor
239 vtkNew<vtkConeSource> cone1;
240 cone1->SetResolution(6);
241 vtkNew<vtkSphereSource> sphere;
242 sphere->SetThetaResolution(8);
243 sphere->SetPhiResolution(8);
244 sphere->SetCenter(5, 5, 0);
245 vtkNew<vtkGlyph3D> glyph;
246 glyph->SetInputConnection(sphere->GetOutputPort());
247 glyph->SetSourceData(cone1->GetOutput());
248 glyph->SetVectorModeToUseNormal();
249 glyph->SetScaleModeToScaleByVector();
250 glyph->SetScaleFactor(0.25);
251
252 vtkNew<vtkAppendPolyData> append;
253 append->AddInputData(glyph->GetOutput());
254 append->AddInputData(sphere->GetOutput());
255
256 vtkNew<vtkPolyDataMapper> maceMapper;
257 maceMapper->SetInputConnection(append->GetOutputPort());
258
259 vtkNew<vtkActor> maceActor;
260 maceActor->SetMapper(maceMapper);
261
262 /*--------------------------------------------------------------------------*/
263 // Multiple ImplicitPlane Widgets
264 /*--------------------------------------------------------------------------*/
265 // Create a mace out of filters.
266 //
267 vtkNew<vtkSphereSource> sphereImpPlane;
268 vtkNew<vtkConeSource> coneImpPlane;
269 vtkNew<vtkGlyph3D> glyphImpPlane;
270 glyphImpPlane->SetInputConnection(sphereImpPlane->GetOutputPort());
271 glyphImpPlane->SetSourceConnection(coneImpPlane->GetOutputPort());
272 glyphImpPlane->SetVectorModeToUseNormal();
273 glyphImpPlane->SetScaleModeToScaleByVector();
274 glyphImpPlane->SetScaleFactor(0.25);
275 glyphImpPlane->Update();
276
277 // The sphere and spikes are appended into a single polydata.
278 // This just makes things simpler to manage.
279 vtkNew<vtkAppendPolyData> apdImpPlane;
280 apdImpPlane->AddInputData(glyphImpPlane->GetOutput());
281 apdImpPlane->AddInputData(sphereImpPlane->GetOutput());
282
283 vtkNew<vtkPolyDataMapper> maceMapperImpPlane;
284 maceMapperImpPlane->SetInputConnection(apdImpPlane->GetOutputPort());
285
286 vtkNew<vtkActor> maceActorImpPlane;
287 maceActorImpPlane->SetMapper(maceMapperImpPlane);
288 maceActorImpPlane->AddPosition(0, 0, 0);
289 maceActorImpPlane->VisibilityOn();
290
291 // This portion of the code clips the mace with the vtkPlanes
292 // implicit function. The clipped region is colored green.
293 vtkNew<vtkPlane> plane;
294 vtkNew<vtkClipPolyData> clipper;
295 clipper->SetInputConnection(apdImpPlane->GetOutputPort());
296 clipper->SetClipFunction(plane);
297 clipper->InsideOutOn();
298
299 vtkNew<vtkPolyDataMapper> selectMapper;
300 selectMapper->SetInputConnection(clipper->GetOutputPort());
301
302 vtkNew<vtkActor> selectActor;
303 selectActor->SetMapper(selectMapper);
304 selectActor->GetProperty()->SetColor(0, 1, 0);
305 selectActor->VisibilityOff();
306 selectActor->AddPosition(0, 0, 0);
307 selectActor->SetScale(1.01, 1.01, 1.01);
308
309 // The SetInteractor method is how 3D widgets are associated with the render
310 // window interactor. Internally, SetInteractor sets up a bunch of callbacks
311 // using the Command/Observer mechanism (AddObserver()).
312 vtkNew<vtkTIPW2Callback> impPlaneCallback;
313 impPlaneCallback->Plane = plane;
314 impPlaneCallback->Actor = selectActor;
315
316 // First ImplicitPlaneWidget (Green)
317 vtkNew<vtkImplicitPlaneRepresentation> impPlaneRep;
318 impPlaneRep->SetPlaceFactor(1.);
319 impPlaneRep->SetOutlineTranslation(0);
320 impPlaneRep->SetScaleEnabled(0);
321 impPlaneRep->PlaceWidget(glyphImpPlane->GetOutput()->GetBounds());
322 impPlaneRep->SetEdgeColor(0., 1., 0.);
323 impPlaneRep->SetNormal(1, 0, 1);
324
325 vtkNew<vtkImplicitPlaneWidget2> planeWidget;
326 planeWidget->SetInteractor(iren);
327 planeWidget->SetRepresentation(impPlaneRep);
328 planeWidget->On();
329
330 planeWidget->AddObserver(vtkCommand::InteractionEvent, impPlaneCallback);
331 planeWidget->AddObserver(vtkCommand::UpdateEvent, impPlaneCallback);
332
333 // Second ImplicitPlaneWidget (Red)
334 vtkNew<vtkImplicitPlaneRepresentation> impPlaneRep2;
335 impPlaneRep2->SetOutlineTranslation(0);
336 impPlaneRep2->SetScaleEnabled(0);
337 impPlaneRep2->SetPlaceFactor(1.);
338 impPlaneRep2->PlaceWidget(glyphImpPlane->GetOutput()->GetBounds());
339 impPlaneRep2->SetEdgeColor(1., 0., 0.);
340
341 vtkNew<vtkImplicitPlaneWidget2> planeWidget2;
342 planeWidget2->SetInteractor(iren);
343 planeWidget2->SetRepresentation(impPlaneRep2);
344 planeWidget2->On();
345
346 /*--------------------------------------------------------------------------*/
347 // Rendering
348 /*--------------------------------------------------------------------------*/
349 // Add the actors to the renderer, set the background and size
350 ren1->AddActor(sph);
351 ren1->AddActor(cyl);
352 ren1->AddActor(cone);
353 ren1->AddActor(maceActorImpPlane);
354 ren1->AddActor(selectActor);
355 ren1->AddActor(maceActor);
356 ren1->SetBackground(0.1, 0.2, 0.4);
357 renWin->SetSize(600, 600);
358
359 // Configure the box widget
360 boxWidget->SetProp3D(maceActor);
361 boxWidget->PlaceWidget();
362
363 // render the image
364 iren->Initialize();
365 double extent[6] = { -2, 7, -2, 7, -1, 1 };
366 ren1->ResetCamera(extent);
367 renWin->Render();
368 widget->On();
369 boxWidget->On();
370 iren->Start();
371
372 return EXIT_SUCCESS;
373 }
374