/*========================================================================= Program: Visualization Toolkit Module: TestDistanceWidget.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. =========================================================================*/ #include "vtkSmartPointer.h" #include "vtkActor.h" #include "vtkCamera.h" #include "vtkCommand.h" #include "vtkContourWidget.h" #include "vtkPolyPlane.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkCutter.h" #include "vtkProperty.h" #include "vtkProperty2D.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkContourWidget.h" #include "vtkTextProperty.h" #include "vtkDEMReader.h" #include "vtkXYPlotActor.h" #include "vtkUnstructuredGrid.h" #include "vtkPolyLine.h" #include "vtkPoints.h" #include "vtkOrientedGlyphContourRepresentation.h" #include "vtkLookupTable.h" #include "vtkImageDataGeometryFilter.h" #include "vtkWarpScalar.h" #include "vtkTriangleFilter.h" #include "vtkImageResample.h" #include "vtkImageData.h" #include "vtkCellArray.h" #include "vtkLinearContourLineInterpolator.h" #include "vtkXMLPolyDataWriter.h" #include "vtkRegressionTestImage.h" #include "vtkTestUtilities.h" // -------------------------------------------------------------------------- // Callback for the widget interaction class vtkTestPolyPlaneCallback : public vtkCommand { public: static vtkTestPolyPlaneCallback *New() { return new vtkTestPolyPlaneCallback; } void Execute(vtkObject *caller, unsigned long, void*) override { vtkContourWidget *widget = reinterpret_cast(caller); vtkContourRepresentation *rep = vtkContourRepresentation:: SafeDownCast(widget->GetRepresentation()); vtkPolyData *pd = rep->GetContourRepresentationAsPolyData(); // If less than 2 points, we can't define a polyplane.. if (pd->GetPoints()->GetNumberOfPoints() >= 2) { vtkPolyLine *polyline = vtkPolyLine::New(); polyline->Initialize( pd->GetNumberOfPoints(), pd->GetLines()->GetPointer()+1, pd->GetPoints() ); this->PolyPlane->SetPolyLine( polyline ); polyline->Delete(); this->Cutter->SetCutFunction(this->PolyPlane); } } vtkTestPolyPlaneCallback() : PolyPlane(nullptr),Cutter(nullptr) {}; vtkPolyPlane * PolyPlane; vtkCutter * Cutter; }; // -------------------------------------------------------------------------- int TestPolyPlane( int argc, char *argv[] ) { // Read height field. char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/SainteHelens.dem"); vtkSmartPointer demReader = vtkSmartPointer::New(); demReader->SetFileName(fname); delete [] fname; // Resample (left incase, we want to subsample, supersample) vtkSmartPointer resample = vtkSmartPointer::New(); resample->SetInputConnection(demReader->GetOutputPort()); resample->SetDimensionality(2); resample->SetAxisMagnificationFactor(0,0.25); resample->SetAxisMagnificationFactor(1,0.25); // Extract geometry vtkSmartPointer surface = vtkSmartPointer::New(); surface->SetInputConnection(resample->GetOutputPort()); // Convert to triangle mesh vtkSmartPointer triangleFilter = vtkSmartPointer::New(); triangleFilter->SetInputConnection( surface->GetOutputPort() ); triangleFilter->Update(); // Warp vtkSmartPointer warp = vtkSmartPointer::New(); warp->SetInputConnection(triangleFilter->GetOutputPort()); warp->SetScaleFactor(1); warp->UseNormalOn(); warp->SetNormal(0, 0, 1); // Update the pipeline until now. warp->Update(); // Define a LUT mapping for the height field double lo = demReader->GetOutput()->GetScalarRange()[0]; double hi = demReader->GetOutput()->GetScalarRange()[1]; vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetHueRange(0.6, 0); lut->SetSaturationRange(1.0, 0); lut->SetValueRange(0.5, 1.0); // Create Renderer, Render window and interactor vtkSmartPointer ren1 = vtkSmartPointer::New(); vtkSmartPointer ren2 = vtkSmartPointer::New(); vtkSmartPointer renWin = vtkSmartPointer::New(); renWin->SetMultiSamples(0); renWin->AddRenderer( ren1); renWin->AddRenderer( ren2); vtkSmartPointer iren = vtkSmartPointer::New(); iren->SetRenderWindow( renWin); // Render the height field vtkSmartPointer demMapper = vtkSmartPointer::New(); demMapper->SetInputConnection(warp->GetOutputPort()); demMapper->SetScalarRange(lo, hi); demMapper->SetLookupTable(lut); vtkSmartPointer demActor = vtkSmartPointer::New(); demActor->SetMapper(demMapper); ren1->AddActor(demActor); // Create a contour widget on ren1 vtkSmartPointer contourWidget = vtkSmartPointer::New(); contourWidget->SetInteractor(iren); vtkOrientedGlyphContourRepresentation *rep = vtkOrientedGlyphContourRepresentation::SafeDownCast( contourWidget->GetRepresentation()); rep->GetLinesProperty()->SetColor(1, 0.2, 0); rep->GetLinesProperty()->SetLineWidth(3.0); // Use no interpolation (default is bezier). vtkSmartPointer< vtkLinearContourLineInterpolator > lineInterpolator = vtkSmartPointer< vtkLinearContourLineInterpolator >::New(); rep->SetLineInterpolator(lineInterpolator); // Create a polyplane to cut with vtkSmartPointer< vtkPolyPlane > polyPlane = vtkSmartPointer< vtkPolyPlane >::New(); // Create a cutter vtkSmartPointer cutter = vtkSmartPointer::New(); cutter->SetInputConnection(warp->GetOutputPort()); // Callback to update the polyplane when the contour is updated vtkSmartPointer cb = vtkSmartPointer::New(); cb->PolyPlane = polyPlane; cb->Cutter = cutter; vtkPolyData * data = warp->GetPolyDataOutput(); double* range = data->GetPointData()->GetScalars()->GetRange(); // plot the height field vtkSmartPointer profile = vtkSmartPointer::New(); profile->AddDataSetInputConnection(cutter->GetOutputPort()); profile->GetPositionCoordinate()->SetValue( 0.05, 0.05, 0); profile->GetPosition2Coordinate()->SetValue( 0.95, 0.95, 0); profile->SetXValuesToArcLength(); profile->SetNumberOfXLabels( 6 ); profile->SetTitle( "Profile Data "); profile->SetXTitle( "Arc length"); profile->SetYTitle( "Height"); profile->SetYRange( range[0], range[1] ); profile->GetProperty()->SetColor( 0, 0, 0); profile->GetProperty()->SetLineWidth( 2); profile->SetLabelFormat("%g"); vtkTextProperty* tprop = profile->GetTitleTextProperty(); tprop->SetColor(0.02,0.06,0.62); tprop->SetFontFamilyToArial(); profile->SetAxisTitleTextProperty(tprop); profile->SetAxisLabelTextProperty(tprop); profile->SetTitleTextProperty(tprop); ren1->SetBackground( 0.1, 0.2, 0.4); ren1->SetViewport( 0, 0, 0.5, 1); ren2->SetBackground( 1, 1, 1); ren2->SetViewport( 0.5, 0, 1, 1); renWin->SetSize( 800, 500); // Set up an interesting viewpoint ren1->ResetCamera(); ren1->ResetCameraClippingRange(); vtkCamera* camera = ren1->GetActiveCamera(); camera->SetViewUp(0.796081, -0.277969, 0.537576); camera->SetParallelScale(10726.6); camera->SetFocalPoint(562412, 5.11456e+06, 1955.44); camera->SetPosition(544402, 5.11984e+06, 31359.2); ren1->ResetCamera(); ren1->ResetCameraClippingRange(); // Create some default points contourWidget->On(); // First remove all nodes. rep->ClearAllNodes(); rep->AddNodeAtWorldPosition(560846, 5.12018e+06, 2205.95); rep->AddNodeAtWorldPosition(562342, 5.11663e+06, 3630.72); rep->AddNodeAtWorldPosition(562421, 5.11321e+06, 3156.75); rep->AddNodeAtWorldPosition(565885, 5.11067e+06, 2885.73); contourWidget->SetWidgetState(vtkContourWidget::Manipulate); // Execute the cut cb->Execute(contourWidget,0,nullptr); vtkXMLPolyDataWriter *pWriter = vtkXMLPolyDataWriter::New(); pWriter->SetInputConnection(cutter->GetOutputPort()); cutter->Update(); pWriter->SetFileName("CutPolyPlane.vtp"); pWriter->Write(); pWriter->SetInputConnection(warp->GetOutputPort()); pWriter->SetFileName("Dataset.vtp"); pWriter->Write(); pWriter->SetInputData(rep->GetContourRepresentationAsPolyData()); pWriter->SetFileName("Contour.vtp"); pWriter->Write(); pWriter->Delete(); // Observe and update profile when contour widget is interacted with contourWidget->AddObserver(vtkCommand::InteractionEvent,cb); // Render the image iren->Initialize(); ren2->AddActor2D( profile); renWin->Render(); ren1->ResetCamera(); int retVal = vtkRegressionTestImage( renWin ); if ( retVal == vtkRegressionTester::DO_INTERACTOR) { iren->Start(); } return !retVal; }