diff --git a/src/Cxx.md b/src/Cxx.md index 58fea3881d30e4c62ab0def197b544f83a4f392b..0046562ea888a81206b3bb0e1a5dfa2883aad7cc 100644 --- a/src/Cxx.md +++ b/src/Cxx.md @@ -913,6 +913,7 @@ See [this tutorial](http://www.vtk.org/Wiki/VTK/Tutorials/3DDataTypes) for a bri [SceneBounds](/Cxx/Visualization/SceneBounds)| vtkRenderer |Get the bounds of the whole scene. [SelectWindowRegion](/Cxx/Visualization/SelectWindowRegion)| vtkInteractorStyleRubberBand2D |Select a region of a window. [StreamLines](/Cxx/Visualization/StreamLines) | vtkStreamTracer | Streamlines. +[StreamlinesWithLineWidget](/Cxx/VisualizationAlgorithms/StreamlinesWithLineWidget)| vtkCallbackCommand vtkLineWidget | Using the vtkLineWidget to produce streamlines in the combustor dataset. The StartInteractionEvent turns the visibility of the streamlines on; the InteractionEvent causes the streamlines to regenerate themselves. [TensorAxes](/Cxx/VisualizationAlgorithms/TensorAxes)| vtkPointLoad vtkTensorGlyph | Display the scaled and oriented principal axes of the stress tensor. [TensorEllipsoids](/Cxx/VisualizationAlgorithms/TensorEllipsoids)| vtkPointLoad vtkTensorGlyph | Display the scaled and oriented principal axes as tensor ellipsoids representing the stress tensor. [TensorGlyph](/Cxx/Visualization/TensorGlyph)| vtkTensorGlyph | Draw a rotated/scaled glyph at each point. diff --git a/src/Cxx/VisualizationAlgorithms/CMakeLists.txt b/src/Cxx/VisualizationAlgorithms/CMakeLists.txt index 86acab87a2f14bc9cb84b804607916c8cac0a92e..00bbafa97de3b95a414ba099f388ae8dc3ec3c08 100644 --- a/src/Cxx/VisualizationAlgorithms/CMakeLists.txt +++ b/src/Cxx/VisualizationAlgorithms/CMakeLists.txt @@ -47,6 +47,7 @@ set(NEEDS_ARGS OfficeTube SpikeFran SplatFace + StreamlinesWithLineWidget VelocityProfile WarpCombustor ) @@ -130,6 +131,9 @@ add_test(${KIT}-SpikeFran ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests add_test(${KIT}-SplatFace ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests TestSplatFace ${DATA}/fran_cut.vtk -E 50) +add_test(${KIT}-StreamlinesWithLineWidget ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests + TestStreamlinesWithLineWidget ${DATA}/combxyz.bin ${DATA}/combq.bin 10 1) + add_test(${KIT}-VelocityProfile ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests TestVelocityProfile ${DATA}/combxyz.bin ${DATA}/combq.bin) diff --git a/src/Cxx/VisualizationAlgorithms/StreamlinesWithLineWidget.cxx b/src/Cxx/VisualizationAlgorithms/StreamlinesWithLineWidget.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2560cf295b58188f4b174dc40a71550e43e05d38 --- /dev/null +++ b/src/Cxx/VisualizationAlgorithms/StreamlinesWithLineWidget.cxx @@ -0,0 +1,286 @@ +/* +Modified from VTK/Examples/GUI/Python/StreamlinesWithLineWidget.py. +This program encompasses the functionality of +StreamlinesWithLineWidget.tcl and LineWidget.tcl. + + Produce streamlines in the combustor dataset. + +This example demonstrates how to use the vtkLineWidget to seed and +manipulate streamlines. Two line widgets are created. The first is invoked +by pressing 'i', the second by pressing 'L' (capital). Both can exist +together. + +If the fourth parameter is non-zero: + 1) The third parameter value is changed to 25. + 2) The camera position and first line widget are positioned differently. + 3) The streamlines are displayed running from the first line widget. + 4) The second line widget is still available. +This is used to test the code. + +*/ + +#include <vtkActor.h> +#include <vtkCallbackCommand.h> +#include <vtkCamera.h> +#include <vtkLineWidget.h> +#include <vtkMultiBlockDataSet.h> +#include <vtkMultiBlockPLOT3DReader.h> +#include <vtkNamedColors.h> +#include <vtkPolyData.h> +#include <vtkPolyDataMapper.h> +#include <vtkProperty.h> +#include <vtkRenderWindow.h> +#include <vtkRenderWindowInteractor.h> +#include <vtkRenderer.h> +#include <vtkRibbonFilter.h> +#include <vtkRungeKutta4.h> +#include <vtkSmartPointer.h> +#include <vtkStreamTracer.h> +#include <vtkStructuredGrid.h> +#include <vtkStructuredGridOutlineFilter.h> + +namespace +{ + +class EnableActorCallback : public vtkCommand +{ +public: + static EnableActorCallback* New() { return new EnableActorCallback; } + void Execute(vtkObject* /*caller*/, unsigned long, void*) override + { + this->actor->VisibilityOn(); + } + EnableActorCallback() + : actor(nullptr) + { + } + vtkActor* actor; +}; + +// The Line Widget callback. +class LWCallback : public vtkCommand +{ +public: + static LWCallback* New() { return new LWCallback; } + void Execute(vtkObject* caller, unsigned long, void*) override + { + vtkLineWidget* lineWidget = reinterpret_cast<vtkLineWidget*>(caller); + lineWidget->GetPolyData(this->polyData); + this->renWin->Render(); + } + LWCallback() + : polyData(nullptr) + , renWin(nullptr) + { + } + vtkPolyData* polyData; + vtkRenderWindow* renWin; +}; +} + +int main(int argc, char* argv[]) +{ + if (argc < 3) + { + std::cout << "Usage: " << argv[0] + << " filename1 filename2 [numOfStreamLines] [illustration]" + << std::endl; + std::cout << "where: filename1 is combxyz.bin and filename2 is combq.bin." + << std::endl; + std::cout + << " numOfStreamLines is the number of streamlines, default 25" + << std::endl; + std::cout << " illustration, if non-zero, reproduce Fig 7-39 of the " + "VTK Textbook." + << std::endl; + return EXIT_FAILURE; + } + auto numOfStreamLines = 25; + auto illustration = 0; + std::string fileName1 = argv[1]; + std::string fileName2 = argv[2]; + if (argc > 3) + { + numOfStreamLines = atoi(argv[3]); + } + if (argc > 4) + { + illustration = atoi(argv[4]); + numOfStreamLines = 25; + } + + vtkSmartPointer<vtkNamedColors> colors = + vtkSmartPointer<vtkNamedColors>::New(); + + // Start by loading some data. + vtkSmartPointer<vtkMultiBlockPLOT3DReader> pl3d = + vtkSmartPointer<vtkMultiBlockPLOT3DReader>::New(); + pl3d->SetXYZFileName(fileName1.c_str()); + pl3d->SetQFileName(fileName2.c_str()); + pl3d->SetScalarFunctionNumber(100); // Density + pl3d->SetVectorFunctionNumber(202); // Momentum + pl3d->Update(); + + vtkStructuredGrid* pl3d_output = + vtkStructuredGrid::SafeDownCast(pl3d->GetOutput()->GetBlock(0)); + + // Create the Renderer, RenderWindow and RenderWindowInteractor. + vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New(); + vtkSmartPointer<vtkRenderWindow> renWin = + vtkSmartPointer<vtkRenderWindow>::New(); + renWin->AddRenderer(ren); + vtkSmartPointer<vtkRenderWindowInteractor> iren = + vtkSmartPointer<vtkRenderWindowInteractor>::New(); + iren->SetRenderWindow(renWin); + + // Needed by: vtkStreamTracer and vtkLineWidget. + vtkSmartPointer<vtkPolyData> seeds = vtkSmartPointer<vtkPolyData>::New(); + vtkSmartPointer<vtkActor> streamline = vtkSmartPointer<vtkActor>::New(); + vtkSmartPointer<vtkPolyData> seeds2 = vtkSmartPointer<vtkPolyData>::New(); + vtkSmartPointer<vtkActor> streamline2 = vtkSmartPointer<vtkActor>::New(); + + // The line widget is used seed the streamlines. + vtkSmartPointer<vtkLineWidget> lineWidget = + vtkSmartPointer<vtkLineWidget>::New(); + lineWidget->SetResolution(numOfStreamLines); + lineWidget->SetInputData(pl3d_output); + lineWidget->GetPolyData(seeds); + if (illustration != 0) + { + lineWidget->SetAlignToNone(); + lineWidget->SetPoint1(0.974678, 5.073630, 31.217961); + lineWidget->SetPoint2(0.457544, -4.995921, 31.080175); + } + else + { + lineWidget->SetAlignToYAxis(); + } + lineWidget->ClampToBoundsOn(); + lineWidget->PlaceWidget(); + + lineWidget->SetInteractor(iren); + + // Associate the line widget with the interactor and setup the callbacks. + vtkSmartPointer<LWCallback> GenerateStreamlines = + vtkSmartPointer<LWCallback>::New(); + GenerateStreamlines->polyData = seeds; + GenerateStreamlines->renWin = renWin; + vtkSmartPointer<EnableActorCallback> BeginInteraction = + vtkSmartPointer<EnableActorCallback>::New(); + BeginInteraction->actor = streamline; + lineWidget->AddObserver(vtkCommand::StartInteractionEvent, BeginInteraction); + lineWidget->AddObserver(vtkCommand::InteractionEvent, GenerateStreamlines); + + // The second line widget is used seed more streamlines. + vtkSmartPointer<vtkLineWidget> lineWidget2 = + vtkSmartPointer<vtkLineWidget>::New(); + lineWidget2->SetResolution(numOfStreamLines); + lineWidget2->SetInputData(pl3d_output); + lineWidget2->GetPolyData(seeds2); + lineWidget2->SetKeyPressActivationValue('L'); + lineWidget2->SetAlignToZAxis(); + lineWidget->ClampToBoundsOn(); + lineWidget2->PlaceWidget(); + + lineWidget2->SetInteractor(iren); + + // Associate the line widget with the interactor and setup the callbacks. + vtkSmartPointer<LWCallback> GenerateStreamlines2 = + vtkSmartPointer<LWCallback>::New(); + GenerateStreamlines2->polyData = seeds2; + GenerateStreamlines2->renWin = renWin; + vtkSmartPointer<EnableActorCallback> BeginInteraction2 = + vtkSmartPointer<EnableActorCallback>::New(); + BeginInteraction2->actor = streamline2; + lineWidget2->AddObserver(vtkCommand::StartInteractionEvent, + BeginInteraction2); + lineWidget2->AddObserver(vtkCommand::InteractionEvent, GenerateStreamlines2); + + // Here we set up two streamlines. + vtkSmartPointer<vtkRungeKutta4> rk4 = vtkSmartPointer<vtkRungeKutta4>::New(); + vtkSmartPointer<vtkStreamTracer> streamer = + vtkSmartPointer<vtkStreamTracer>::New(); + streamer->SetInputData(pl3d_output); + streamer->SetSourceData(seeds); + streamer->SetMaximumPropagation(100); + streamer->SetInitialIntegrationStep(0.2); + streamer->SetIntegrationDirectionToForward(); + streamer->SetComputeVorticity(1); + streamer->SetIntegrator(rk4); + vtkSmartPointer<vtkRibbonFilter> rf = vtkSmartPointer<vtkRibbonFilter>::New(); + rf->SetInputConnection(streamer->GetOutputPort()); + rf->SetWidth(0.1); + rf->SetWidthFactor(5); + vtkSmartPointer<vtkPolyDataMapper> streamMapper = + vtkSmartPointer<vtkPolyDataMapper>::New(); + streamMapper->SetInputConnection(rf->GetOutputPort()); + streamMapper->SetScalarRange(pl3d_output->GetScalarRange()); + streamline->SetMapper(streamMapper); + streamline->VisibilityOff(); + + vtkSmartPointer<vtkStreamTracer> streamer2 = + vtkSmartPointer<vtkStreamTracer>::New(); + streamer2->SetInputData(pl3d_output); + streamer2->SetSourceData(seeds2); + streamer2->SetMaximumPropagation(100); + streamer2->SetInitialIntegrationStep(0.2); + streamer2->SetIntegrationDirectionToForward(); + streamer2->SetComputeVorticity(1); + streamer2->SetIntegrator(rk4); + vtkSmartPointer<vtkRibbonFilter> rf2 = + vtkSmartPointer<vtkRibbonFilter>::New(); + rf2->SetInputConnection(streamer2->GetOutputPort()); + rf2->SetWidth(0.1); + rf2->SetWidthFactor(5); + vtkSmartPointer<vtkPolyDataMapper> streamMapper2 = + vtkSmartPointer<vtkPolyDataMapper>::New(); + streamMapper2->SetInputConnection(rf2->GetOutputPort()); + streamMapper2->SetScalarRange(pl3d_output->GetScalarRange()); + streamline2->SetMapper(streamMapper2); + streamline2->VisibilityOff(); + + // Get an outline of the data set for context. + vtkSmartPointer<vtkStructuredGridOutlineFilter> outline = + vtkSmartPointer<vtkStructuredGridOutlineFilter>::New(); + outline->SetInputData(pl3d_output); + vtkSmartPointer<vtkPolyDataMapper> outlineMapper = + vtkSmartPointer<vtkPolyDataMapper>::New(); + outlineMapper->SetInputConnection(outline->GetOutputPort()); + vtkSmartPointer<vtkActor> outlineActor = vtkSmartPointer<vtkActor>::New(); + outlineActor->GetProperty()->SetColor(colors->GetColor3d("Black").GetData()); + outlineActor->SetMapper(outlineMapper); + + // Add the actors to the renderer, set the background and size. + ren->AddActor(outlineActor); + ren->AddActor(streamline); + ren->AddActor(streamline2); + renWin->SetSize(512, 512); + vtkCamera* cam = ren->GetActiveCamera(); + if (illustration != 0) + { + // We need to directly display the streamlines in this case. + lineWidget->EnabledOn(); + streamline->VisibilityOn(); + lineWidget->GetPolyData(seeds); + renWin->Render(); + + cam->SetClippingRange(14.216207, 68.382915); + cam->SetFocalPoint(9.718210, 0.458166, 29.399900); + cam->SetPosition(-15.827551, -16.997463, 54.003120); + cam->SetViewUp(0.616076, 0.179428, 0.766979); + ren->SetBackground(colors->GetColor3d("Silver").GetData()); + } + else + { + cam->SetClippingRange(3.95297, 50); + cam->SetFocalPoint(9.71821, 0.458166, 29.3999); + cam->SetPosition(2.7439, -37.3196, 38.7167); + cam->SetViewUp(-0.16123, 0.264271, 0.950876); + ren->SetBackground(colors->GetColor3d("Silver").GetData()); + } + + iren->Initialize(); + renWin->Render(); + iren->Start(); + return EXIT_SUCCESS; +} diff --git a/src/Cxx/VisualizationAlgorithms/StreamlinesWithLineWidget.md b/src/Cxx/VisualizationAlgorithms/StreamlinesWithLineWidget.md new file mode 100644 index 0000000000000000000000000000000000000000..54936e6e1db1f338c917e7765f16a3bef0fb1b08 --- /dev/null +++ b/src/Cxx/VisualizationAlgorithms/StreamlinesWithLineWidget.md @@ -0,0 +1,17 @@ +### Description +#### Produce streamlines in the combustor dataset. + +This example demonstrates how to use the vtkLineWidget to seed and +manipulate streamlines. Two line widgets are created. The first is invoked +by pressing '**i**', the second by pressing '**L**' (capital). Both can exist +together. + +If the fourth parameter is non-zero, it is used to generate an image with streamlines: + 1) The third parameter value is changed to 25. + 2) The camera position and first line widget are positioned differently. + 3) The streamlines are displayed running from the first line widget. + 4) The second line widget is still available. + +In the C++ version, note how we handle callbacks by first implementing a class, then instantiating it and then passing references to the needed variables to it. Finally we add it as an observer. + +For the Python version the process is slightly different. We simply define a function with references to the needed variables from the outer scope (or they could be global). Finally add it as an observer. diff --git a/src/Python.md b/src/Python.md index 20ed2ef921d04cf98c0db431486f3d025dacaff7..b8981a6bd9b313ab5f2433d7d1e57188da06b5d7 100644 --- a/src/Python.md +++ b/src/Python.md @@ -199,6 +199,7 @@ This section includes examples of manipulating meshes. [QuadraticSurface](/Python/Visualization/QuadraticSurface) | vtkQuadric | [SphereTexture](/Python/Visualization/SphereTexture) | vtkTextureMapToSphere | Apply an ImageData texture to an sphere [Streamlines](/Python/Visualization/Streamlines) | vtkStreamLine | Seed streamlines with vectors from a structured grid +[StreamlinesWithLineWidget](/Python/VisualizationAlgorithms/StreamlinesWithLineWidget)| vtkCallbackCommand vtkLineWidget | Using the vtkLineWidget to produce streamlines in the combustor dataset. The StartInteractionEvent turns the visibility of the streamlines on; the InteractionEvent causes the streamlines to regenerate themselves. [TensorAxes](/Python/VisualizationAlgorithms/TensorAxes)| vtkPointLoad vtkTensorGlyph | Display the scaled and oriented principal axes of the stress tensor. [TensorEllipsoids](/Python/VisualizationAlgorithms/TensorEllipsoids)| vtkPointLoad vtkTensorGlyph | Display the scaled and oriented principal axes as tensor ellipsoids representing the stress tensor. [TextSource](/Python/Visualization/TextSource) | vtkTextSource | diff --git a/src/Python/VisualizationAlgorithms/StreamlinesWithLineWidget.md b/src/Python/VisualizationAlgorithms/StreamlinesWithLineWidget.md new file mode 100644 index 0000000000000000000000000000000000000000..54936e6e1db1f338c917e7765f16a3bef0fb1b08 --- /dev/null +++ b/src/Python/VisualizationAlgorithms/StreamlinesWithLineWidget.md @@ -0,0 +1,17 @@ +### Description +#### Produce streamlines in the combustor dataset. + +This example demonstrates how to use the vtkLineWidget to seed and +manipulate streamlines. Two line widgets are created. The first is invoked +by pressing '**i**', the second by pressing '**L**' (capital). Both can exist +together. + +If the fourth parameter is non-zero, it is used to generate an image with streamlines: + 1) The third parameter value is changed to 25. + 2) The camera position and first line widget are positioned differently. + 3) The streamlines are displayed running from the first line widget. + 4) The second line widget is still available. + +In the C++ version, note how we handle callbacks by first implementing a class, then instantiating it and then passing references to the needed variables to it. Finally we add it as an observer. + +For the Python version the process is slightly different. We simply define a function with references to the needed variables from the outer scope (or they could be global). Finally add it as an observer. diff --git a/src/Python/VisualizationAlgorithms/StreamlinesWithLineWidget.py b/src/Python/VisualizationAlgorithms/StreamlinesWithLineWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..4f21a0f3757cb2d42c669e6ecefc620f89586cce --- /dev/null +++ b/src/Python/VisualizationAlgorithms/StreamlinesWithLineWidget.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python + +""" +Modified from VTK/Examples/GUI/Python/StreamlinesWithLineWidget.py. +This program encompasses the functionality of + StreamlinesWithLineWidget.tcl and LineWidget.tcl. +""" + +import vtk + + +def main(): + colors = vtk.vtkNamedColors() + + fileName1, fileName2, numOfStreamLines, illustration = get_program_parameters() + if illustration: + numOfStreamLines = 25 + + # Start by loading some data. + pl3d = vtk.vtkMultiBlockPLOT3DReader() + pl3d.SetXYZFileName(fileName1) + pl3d.SetQFileName(fileName2) + pl3d.SetScalarFunctionNumber(100) # Density + pl3d.SetVectorFunctionNumber(202) # Momentum + pl3d.Update() + + pl3d_output = pl3d.GetOutput().GetBlock(0) + + # Create the Renderer, RenderWindow and RenderWindowInteractor. + ren = vtk.vtkRenderer() + renWin = vtk.vtkRenderWindow() + renWin.AddRenderer(ren) + iren = vtk.vtkRenderWindowInteractor() + iren.SetRenderWindow(renWin) + + # Needed by: vtkStreamTracer and vtkLineWidget. + seeds = vtk.vtkPolyData() + streamline = vtk.vtkActor() + seeds2 = vtk.vtkPolyData() + streamline2 = vtk.vtkActor() + + # The line widget is used seed the streamlines. + lineWidget = vtk.vtkLineWidget() + lineWidget.SetResolution(numOfStreamLines) + lineWidget.SetInputData(pl3d_output) + lineWidget.GetPolyData(seeds) + if illustration: + lineWidget.SetAlignToNone() + lineWidget.SetPoint1(0.974678, 5.073630, 31.217961) + lineWidget.SetPoint2(0.457544, -4.995921, 31.080175) + else: + lineWidget.SetAlignToYAxis() + lineWidget.ClampToBoundsOn() + lineWidget.PlaceWidget() + + # Callback functions that actually generate streamlines. + def EnableActorCallback(obj, event): + # global streamline + streamline.VisibilityOn() + + def GenerateStreamlinesCallback(obj, event): + # global seeds, renWin + obj.GetPolyData(seeds) + renWin.Render() + + # Associate the line widget with the interactor and setup callbacks. + lineWidget.SetInteractor(iren) + lineWidget.AddObserver("StartInteractionEvent", EnableActorCallback) + lineWidget.AddObserver("InteractionEvent", GenerateStreamlinesCallback) + + # The second line widget is used seed more streamlines. + lineWidget2 = vtk.vtkLineWidget() + lineWidget2.SetResolution(numOfStreamLines) + lineWidget2.SetInputData(pl3d_output) + lineWidget2.GetPolyData(seeds2) + lineWidget2.SetKeyPressActivationValue('L') + lineWidget2.SetAlignToZAxis() + lineWidget.ClampToBoundsOn() + lineWidget2.PlaceWidget() + + def EnableActorCallback2(obj, event): + # global streamline2 + streamline2.VisibilityOn() + + def GenerateStreamlinesCallback2(obj, event): + # global seeds2, renWin + obj.GetPolyData(seeds2) + renWin.Render() + + lineWidget2.SetInteractor(iren) + lineWidget2.AddObserver("StartInteractionEvent", EnableActorCallback2) + lineWidget2.AddObserver("EndInteractionEvent", GenerateStreamlinesCallback2) + + # Here we set up two streamlines. + rk4 = vtk.vtkRungeKutta4() + streamer = vtk.vtkStreamTracer() + streamer.SetInputData(pl3d_output) + streamer.SetSourceData(seeds) + streamer.SetMaximumPropagation(100) + streamer.SetInitialIntegrationStep(0.2) + streamer.SetIntegrationDirectionToForward() + streamer.SetComputeVorticity(1) + streamer.SetIntegrator(rk4) + rf = vtk.vtkRibbonFilter() + rf.SetInputConnection(streamer.GetOutputPort()) + rf.SetWidth(0.1) + rf.SetWidthFactor(5) + streamMapper = vtk.vtkPolyDataMapper() + streamMapper.SetInputConnection(rf.GetOutputPort()) + streamMapper.SetScalarRange(pl3d_output.GetScalarRange()) + streamline.SetMapper(streamMapper) + streamline.VisibilityOff() + + streamer2 = vtk.vtkStreamTracer() + streamer2.SetInputData(pl3d_output) + streamer2.SetSourceData(seeds2) + streamer2.SetMaximumPropagation(100) + streamer2.SetInitialIntegrationStep(0.2) + streamer2.SetIntegrationDirectionToForward() + streamer2.SetComputeVorticity(1) + streamer2.SetIntegrator(rk4) + rf2 = vtk.vtkRibbonFilter() + rf2.SetInputConnection(streamer2.GetOutputPort()) + rf2.SetWidth(0.1) + rf2.SetWidthFactor(5) + streamMapper2 = vtk.vtkPolyDataMapper() + streamMapper2.SetInputConnection(rf2.GetOutputPort()) + streamMapper2.SetScalarRange(pl3d_output.GetScalarRange()) + streamline2.SetMapper(streamMapper2) + streamline2.VisibilityOff() + + # Get an outline of the data set for context. + outline = vtk.vtkStructuredGridOutlineFilter() + outline.SetInputData(pl3d_output) + outlineMapper = vtk.vtkPolyDataMapper() + outlineMapper.SetInputConnection(outline.GetOutputPort()) + outlineActor = vtk.vtkActor() + outlineActor.GetProperty().SetColor(colors.GetColor3d("Black")) + outlineActor.SetMapper(outlineMapper) + + # Add the actors to the renderer, set the background and size. + ren.AddActor(outlineActor) + ren.AddActor(streamline) + ren.AddActor(streamline2) + renWin.SetSize(512, 512) + cam = ren.GetActiveCamera() + if illustration: + # We need to directly display the streamlines in this case. + lineWidget.EnabledOn() + streamline.VisibilityOn() + lineWidget.GetPolyData(seeds) + renWin.Render() + + cam.SetClippingRange(14.216207, 68.382915) + cam.SetFocalPoint(9.718210, 0.458166, 29.399900) + cam.SetPosition(-15.827551, -16.997463, 54.003120) + cam.SetViewUp(0.616076, 0.179428, 0.766979) + ren.SetBackground(colors.GetColor3d("Silver")) + else: + cam.SetClippingRange(3.95297, 50) + cam.SetFocalPoint(9.71821, 0.458166, 29.3999) + cam.SetPosition(2.7439, -37.3196, 38.7167) + cam.SetViewUp(-0.16123, 0.264271, 0.950876) + ren.SetBackground(colors.GetColor3d("Silver")) + + iren.Initialize() + renWin.Render() + iren.Start() + + +def get_program_parameters(): + import argparse + description = 'Produce streamlines in the combustor dataset.' + epilogue = ''' + Produce streamlines in the combustor dataset. + +This example demonstrates how to use the vtkLineWidget to seed and +manipulate streamlines. Two line widgets are created. The first is invoked +by pressing 'i', the second by pressing 'L' (capital). Both can exist +together. + +If the fourth parameter is non-zero, it is used to generate + an image with streamlines: + 1) The third parameter value is changed to 25. + 2) The camera position and first line widget are positioned differently. + 3) The streamlines are displayed running from the first line widget. + 4) The second line widget is still available. + + ''' + parser = argparse.ArgumentParser(description=description, epilog=epilogue, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('filename1', help='combxyz.bin.') + parser.add_argument('filename2', help='combq.bin.') + parser.add_argument('numOfStreamLines', default=25, type=int, nargs='?', help='The number of stream lines.') + parser.add_argument('illustration', default=0, type=int, nargs='?', + help='If non-zero, reproduce Fig 7-39 of the VTK Textbook.') + args = parser.parse_args() + return args.filename1, args.filename2, args.numOfStreamLines, args.illustration + + +if __name__ == '__main__': + main()