/*========================================================================= Program: Visualization Toolkit Module: TestQQuickVTKRenderItemWidget.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // Description // Tests QQuickVTKRenderItem #include "QQuickVTKInteractiveWidget.h" #include "QQuickVTKRenderItem.h" #include "QQuickVTKRenderWindow.h" #include "vtkActor.h" #include "vtkAppendPolyData.h" #include "vtkCamera.h" #include "vtkClipPolyData.h" #include "vtkCommand.h" #include "vtkConeSource.h" #include "vtkGenericOpenGLRenderWindow.h" #include "vtkGlyph3D.h" #include "vtkImplicitPlaneRepresentation.h" #include "vtkImplicitPlaneWidget2.h" #include "vtkInteractorEventRecorder.h" #include "vtkNew.h" #include "vtkPNGWriter.h" #include "vtkPlane.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkProperty.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkSphereSource.h" #include "vtkTestUtilities.h" #include "vtkTesting.h" #include "vtkWindowToImageFilter.h" #include #include #include #include #include #include class TestQQuickVTKRenderItemWidgetCallback : public vtkCommand { public: static TestQQuickVTKRenderItemWidgetCallback* New() { return new TestQQuickVTKRenderItemWidgetCallback; } void Execute(vtkObject* caller, unsigned long, void*) override { vtkImplicitPlaneWidget2* planeWidget = reinterpret_cast(caller); vtkImplicitPlaneRepresentation* rep = reinterpret_cast(planeWidget->GetRepresentation()); rep->GetPlane(this->Plane); this->Actor->VisibilityOn(); } TestQQuickVTKRenderItemWidgetCallback() : Plane(nullptr) , Actor(nullptr) { } vtkPlane* Plane; vtkActor* Actor; }; int TestQQuickVTKRenderItemWidget(int argc, char* argv[]) { cout << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << endl; QQuickVTKRenderWindow::setupGraphicsBackend(); QApplication app(argc, argv); QQmlApplicationEngine engine; qDebug() << "QML2_IMPORT_PATH:" << engine.importPathList(); engine.load(QUrl("qrc:///TestQQuickVTKRenderItemWidget.qml")); QObject* topLevel = engine.rootObjects().value(0); QQuickWindow* window = qobject_cast(topLevel); window->show(); // Fetch the QQuick window using the standard object name set up in the constructor QQuickVTKRenderWindow* qquickvtkWindow = topLevel->findChild("QQuickVTKRenderWindow"); // Fetch the QQuick item using the object name set up in the qml file QQuickVTKRenderItem* coneItem = topLevel->findChild("ConeView"); // Create a cone pipeline and add it to the view vtkNew actor; vtkNew mapper; vtkNew cone; mapper->SetInputConnection(cone->GetOutputPort()); actor->SetMapper(mapper); coneItem->renderer()->AddActor(actor); coneItem->renderer()->SetBackground(0.5, 0.5, 0.7); coneItem->renderer()->SetBackground2(0.7, 0.7, 0.7); coneItem->renderer()->SetGradientBackground(true); coneItem->update(); // Fetch the QQuick item using the object name set up in the qml file QQuickVTKRenderItem* widgetItem = topLevel->findChild("WidgetView"); // Create a mace out of filters. // vtkNew sphere; vtkNew glyph; glyph->SetInputConnection(sphere->GetOutputPort()); glyph->SetSourceConnection(cone->GetOutputPort()); glyph->SetVectorModeToUseNormal(); glyph->SetScaleModeToScaleByVector(); glyph->SetScaleFactor(0.25); // The sphere and spikes are appended into a single polydata. // This just makes things simpler to manage. vtkNew apd; apd->AddInputConnection(glyph->GetOutputPort()); apd->AddInputConnection(sphere->GetOutputPort()); vtkNew maceMapper; maceMapper->SetInputConnection(apd->GetOutputPort()); vtkNew maceActor; maceActor->SetMapper(maceMapper); maceActor->VisibilityOn(); // This portion of the code clips the mace with the vtkPlanes // implicit function. The clipped region is colored green. vtkNew plane; vtkNew clipper; clipper->SetInputConnection(apd->GetOutputPort()); clipper->SetClipFunction(plane); clipper->InsideOutOn(); vtkNew selectMapper; selectMapper->SetInputConnection(clipper->GetOutputPort()); vtkNew selectActor; selectActor->SetMapper(selectMapper); selectActor->GetProperty()->SetColor(0, 1, 0); selectActor->VisibilityOff(); selectActor->SetScale(1.01, 1.01, 1.01); // The SetInteractor method is how 3D widgets are associated with the render // window interactor. Internally, SetInteractor sets up a bunch of callbacks // using the Command/Observer mechanism (AddObserver()). vtkNew myCallback; myCallback->Plane = plane; myCallback->Actor = selectActor; vtkNew rep; vtkNew planeWidget; planeWidget->SetRepresentation(rep); planeWidget->AddObserver(vtkCommand::InteractionEvent, myCallback); QQuickVTKInteractiveWidget* qquickVTKWidget = new QQuickVTKInteractiveWidget(window); qquickVTKWidget->setWidget(planeWidget); qquickVTKWidget->setEnabled(true); widgetItem->renderer()->AddActor(maceActor); widgetItem->renderer()->AddActor(selectActor); widgetItem->addWidget(qquickVTKWidget); widgetItem->update(); // Wait a little for the application and window to be set up properly QEventLoop loop; QTimer::singleShot(100, &loop, SLOT(quit())); loop.exec(); // Once the application is up, adjust the camera, widget reps, etc. widgetItem->renderer()->ResetCamera(); rep->SetPlaceFactor(1.25); rep->PlaceWidget(glyph->GetOutput()->GetBounds()); widgetItem->renderer()->GetActiveCamera()->Azimuth(20); vtkNew vtktesting; vtktesting->AddArguments(argc, argv); if (vtktesting->IsInteractiveModeSpecified()) { return QApplication::exec(); } // Capture a screenshot of the item vtkSmartPointer im = qquickvtkWindow->captureScreenshot(); std::string validName = std::string(vtktesting->GetValidImageFileName()); std::string::size_type slashPos = validName.rfind('/'); if (slashPos != std::string::npos) { validName = validName.substr(slashPos + 1); } std::string tmpDir = vtktesting->GetTempDirectory(); std::string vImage = tmpDir + "/" + validName; vtkNew w; w->SetInputData(im); w->SetFileName(vImage.c_str()); w->Write(); int retVal = vtktesting->RegressionTest(vImage, 10); switch (retVal) { case vtkTesting::FAILED: case vtkTesting::NOT_RUN: return EXIT_FAILURE; } return EXIT_SUCCESS; }