#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; }