/*========================================================================= 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 "vtkCellArray.h" #include "vtkCommand.h" #include "vtkContourWidget.h" #include "vtkCutter.h" #include "vtkDEMReader.h" #include "vtkImageData.h" #include "vtkImageDataGeometryFilter.h" #include "vtkImageResample.h" #include "vtkLinearContourLineInterpolator.h" #include "vtkLookupTable.h" #include "vtkOrientedGlyphContourRepresentation.h" #include "vtkPointData.h" #include "vtkPoints.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkPolyLine.h" #include "vtkPolyPlane.h" #include "vtkProperty.h" #include "vtkProperty2D.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkTextProperty.h" #include "vtkTriangleFilter.h" #include "vtkUnstructuredGrid.h" #include "vtkWarpScalar.h" #include "vtkXMLPolyDataWriter.h" #include "vtkXYPlotActor.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) { vtkIdType npts; const vtkIdType* ptIds; pd->GetLines()->GetCellAtId(0, npts, ptIds); vtkPolyLine* polyline = vtkPolyLine::New(); polyline->Initialize(static_cast(npts), ptIds, 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 in case, 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 lineInterpolator = vtkSmartPointer::New(); rep->SetLineInterpolator(lineInterpolator); // Create a polyplane to cut with vtkSmartPointer polyPlane = vtkSmartPointer::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; }