#include "vtkSmartPointer.h" #include "vtkActor.h" #include "vtkBrokenLineWidget.h" #include "vtkCamera.h" #include "vtkCommand.h" #include "vtkDataSetMapper.h" #include "vtkExtractSelection.h" #include "vtkInformation.h" #include "vtkLinearSelector.h" #include "vtkMultiBlockDataSet.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkProgrammableFilter.h" #include "vtkProperty.h" #include "vtkRegressionTestImage.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkTextActor.h" #include "vtkTextProperty.h" #include "vtkUnstructuredGrid.h" #include "vtkUnstructuredGridReader.h" #include "vtkTestUtilities.h" #include // Callback for the broken line widget interaction class vtkBLWCallback : public vtkCommand { public: static vtkBLWCallback* New() { return new vtkBLWCallback; } void Execute(vtkObject* caller, unsigned long, void*) override { // Retrieve polydata line vtkBrokenLineWidget* line = reinterpret_cast(caller); line->GetPolyData(Poly); // Update linear extractor with current points this->Selector->SetPoints(Poly->GetPoints()); // Update selection from mesh this->Extractor->Update(); vtkMultiBlockDataSet* outMB = vtkMultiBlockDataSet::SafeDownCast(this->Extractor->GetOutput()); vtkUnstructuredGrid* selection = vtkUnstructuredGrid::SafeDownCast(outMB->GetBlock(0)); this->Mapper->SetInputData(selection); // Update cardinality of selection std::ostringstream txt; txt << "Number of selected elements: " << (selection ? selection->GetNumberOfCells() : 0); this->Text->SetInput(txt.str().c_str()); } vtkBLWCallback() : Poly(nullptr) , Selector(nullptr) , Extractor(nullptr) , Mapper(nullptr) , Text(nullptr) { } vtkPolyData* Poly; vtkLinearSelector* Selector; vtkExtractSelection* Extractor; vtkDataSetMapper* Mapper; vtkTextActor* Text; }; int TestBrokenLineWidget(int argc, char* argv[]) { // Create render window and interactor vtkSmartPointer win = vtkSmartPointer::New(); win->SetMultiSamples(0); win->SetSize(600, 300); vtkSmartPointer iren = vtkSmartPointer::New(); iren->SetRenderWindow(win); iren->Initialize(); // Create 2 viewports in window vtkSmartPointer ren1 = vtkSmartPointer::New(); ren1->SetBackground(.4, .4, .4); ren1->SetBackground2(.8, .8, .8); ren1->GradientBackgroundOn(); ren1->SetViewport(0., 0., .5, 1.); win->AddRenderer(ren1); vtkSmartPointer ren2 = vtkSmartPointer::New(); ren2->SetBackground(1., 1., 1.); ren2->SetViewport(.5, 0., 1., 1.); win->AddRenderer(ren2); // Create a good view angle vtkCamera* camera = ren1->GetActiveCamera(); camera->SetFocalPoint(.12, 0., 0.); camera->SetPosition(.38, .3, .15); camera->SetViewUp(0., 0., 1.); ren2->SetActiveCamera(camera); // Read 3D unstructured input mesh char* fileName = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/AngularSector.vtk"); vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName(fileName); delete[] fileName; reader->Update(); // Create mesh actor to be rendered in viewport 1 vtkSmartPointer meshMapper = vtkSmartPointer::New(); meshMapper->SetInputConnection(reader->GetOutputPort()); vtkSmartPointer meshActor = vtkSmartPointer::New(); meshActor->SetMapper(meshMapper); meshActor->GetProperty()->SetColor(.23, .37, .17); meshActor->GetProperty()->SetRepresentationToWireframe(); ren1->AddActor(meshActor); // Create multi-block mesh for linear extractor reader->Update(); vtkUnstructuredGrid* mesh = reader->GetOutput(); vtkSmartPointer meshMB = vtkSmartPointer::New(); meshMB->SetNumberOfBlocks(1); meshMB->GetMetaData(static_cast(0))->Set(vtkCompositeDataSet::NAME(), "Mesh"); meshMB->SetBlock(0, mesh); // Create broken line widget, attach it to input mesh vtkSmartPointer line = vtkSmartPointer::New(); line->SetInteractor(iren); line->SetInputData(mesh); line->SetPriority(1.); line->KeyPressActivationOff(); line->PlaceWidget(); line->ProjectToPlaneOff(); line->On(); line->SetHandleSizeFactor(1.2); // Create list of points to define broken line vtkSmartPointer points = vtkSmartPointer::New(); points->InsertNextPoint(.23, .0, .0); points->InsertNextPoint(.0, .0, .0); points->InsertNextPoint(.23, .04, .04); line->InitializeHandles(points); // Extract polygonal line and then its points vtkSmartPointer linePD = vtkSmartPointer::New(); line->GetPolyData(linePD); vtkSmartPointer lineMapper = vtkSmartPointer::New(); lineMapper->SetInputData(linePD); vtkSmartPointer lineActor = vtkSmartPointer::New(); lineActor->SetMapper(lineMapper); lineActor->GetProperty()->SetColor(1., 0., 0.); lineActor->GetProperty()->SetLineWidth(2.); ren2->AddActor(lineActor); // Create selection along broken line defined by list of points vtkSmartPointer selector = vtkSmartPointer::New(); selector->SetInputData(meshMB); selector->SetPoints(points); selector->IncludeVerticesOff(); selector->SetVertexEliminationTolerance(1.e-12); // Extract selection from mesh vtkSmartPointer extractor = vtkSmartPointer::New(); extractor->SetInputData(0, meshMB); extractor->SetInputConnection(1, selector->GetOutputPort()); extractor->Update(); vtkMultiBlockDataSet* outMB = vtkMultiBlockDataSet::SafeDownCast(extractor->GetOutput()); vtkUnstructuredGrid* selection = vtkUnstructuredGrid::SafeDownCast(outMB->GetBlock(0)); // Create selection actor vtkSmartPointer selMapper = vtkSmartPointer::New(); selMapper->SetInputData(selection); vtkSmartPointer selActor = vtkSmartPointer::New(); selActor->SetMapper(selMapper); selActor->GetProperty()->SetColor(0., 0., 0.); selActor->GetProperty()->SetRepresentationToWireframe(); ren2->AddActor(selActor); // Annotate with number of elements vtkSmartPointer txtActor = vtkSmartPointer::New(); std::ostringstream txt; txt << "Number of selected elements: " << (selection ? selection->GetNumberOfCells() : 0); txtActor->SetInput(txt.str().c_str()); txtActor->SetTextScaleModeToViewport(); txtActor->SetNonLinearFontScale(.2, 18); txtActor->GetTextProperty()->SetColor(0., 0., 1.); txtActor->GetTextProperty()->SetFontSize(18); ren2->AddActor(txtActor); // Invoke callback on polygonal line to interactively select elements vtkSmartPointer cb = vtkSmartPointer::New(); cb->Poly = linePD; cb->Selector = selector; cb->Extractor = extractor; cb->Mapper = selMapper; cb->Text = txtActor; line->AddObserver(vtkCommand::InteractionEvent, cb); // Render and test win->Render(); int retVal = vtkRegressionTestImage(win); if (retVal == vtkRegressionTester::DO_INTERACTOR) { iren->Start(); } return !retVal; }