#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
#include "vtkActor.h"
#include "vtkAppendPolyData.h"
#include "vtkButtonWidget.h"
#include "vtkCommand.h"
#include "vtkConeSource.h"
#include "vtkEllipticalButtonSource.h"
#include "vtkGlyph3D.h"
#include "vtkLookupTable.h"
#include "vtkNew.h"
#include "vtkPNGReader.h"
#include "vtkPlatonicSolidSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkProp3DButtonRepresentation.h"
#include "vtkProperty.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkSphereSource.h"
#include "vtkTIFFReader.h"
#include "vtkTestUtilities.h"
#include "vtkTesting.h"
#include "vtkTexturedButtonRepresentation.h"
#include "vtkTexturedButtonRepresentation2D.h"
#include <vtkBMPReader.h>
#include "vtkSmartPointer.h"
#include "vtkClipPolyData.h"
#include "vtkImplicitPlaneRepresentation.h"
#include "vtkImplicitPlaneWidget2.h"
#include "vtkInteractorEventRecorder.h"
#include "vtkLODActor.h"
#include "vtkPlane.h"
#include "vtkPolyData.h"
#include <vtkImplicitPlaneWidget.h>
#include "vtkSliderRepresentation2D.h"
#include "vtkSliderRepresentation3D.h"
#include "vtkSliderWidget.h"
#include "vtkWidgetEvent.h"
#include "vtkWidgetEventTranslator.h"
#include "vtkSphere.h"
#include <vtkImageData.h>
#include <vtkImageDataOutlineFilter.h>
#include <vtkImagePlaneWidget.h>
#include <vtkVolume16Reader.h>
#include <vtkImageMapToColors.h>
#include <vtkImageActor.h>
#include <vtkCellPicker.h>
#include "vtkMath.h"
#include "vtkMathUtilities.h"
#include <vtkImageMapper3D.h>
#include "vtkLogger.h"
#include <vtkCamera.h>
#include "vtkRegressionTestImage.h"
#include "vtkImageReslice.h"
#include "vtkInteractorStyleImage.h"
#include "vtkOutlineFilter.h"
#include "vtkPlaneSource.h"
#include "vtkResliceCursor.h"
#include "vtkResliceCursorActor.h"
#include "vtkResliceCursorLineRepresentation.h"
#include "vtkResliceCursorPolyDataAlgorithm.h"
#include "vtkResliceCursorThickLineRepresentation.h"
#include "vtkResliceCursorWidget.h"
#include "vtkSeedRepresentation.h"
#include "vtkSeedWidget.h"
#include "vtkPointHandleRepresentation2D.h"
#include <vtkProperty2D.h>
#include <vtkCompassRepresentation.h>
#include <vtkCompassWidget.h>
#include <vtkAnnotatedCubeActor.h>
#include "vtkDistanceRepresentation2D.h"
#include "vtkDistanceWidget.h"
#include "vtkAxisActor2D.h"
#include <vtkTextProperty.h>
#include <vtkMatrix4x4.h>
#include <vtkStreamingDemandDrivenPipeline.h>
#include <vtkInformation.h>
#include <iostream>
// The mouse motion callback, to turn "Slicing" on and off
class vtkImageInteractionCallback : public vtkCommand
{
public:
static vtkImageInteractionCallback* New() { return new vtkImageInteractionCallback; }
vtkImageInteractionCallback()
{
this->Slicing = 0;
this->ImageReslice = nullptr;
this->Interactor = nullptr;
}
void SetImageReslice(vtkImageReslice* reslice) { this->ImageReslice = reslice; }
vtkImageReslice* GetImageReslice() { return this->ImageReslice; }
void SetInteractor(vtkRenderWindowInteractor* interactor) { this->Interactor = interactor; }
vtkRenderWindowInteractor* GetInteractor() { return this->Interactor; }
void Execute(vtkObject*, unsigned long event, void*) override
{
vtkRenderWindowInteractor* interactor = this->GetInteractor();
int lastPos[2];
interactor->GetLastEventPosition(lastPos);
int currPos[2];
interactor->GetEventPosition(currPos);
if (event == vtkCommand::LeftButtonPressEvent)
{
this->Slicing = 1;
}
else if (event == vtkCommand::LeftButtonReleaseEvent)
{
this->Slicing = 0;
}
else if (event == vtkCommand::MouseMoveEvent)
{
if (this->Slicing)
{
vtkImageReslice* reslice = this->ImageReslice;
// Increment slice position by deltaY of mouse
int deltaY = lastPos[1] - currPos[1];
reslice->Update();
double sliceSpacing = reslice->GetOutput()->GetSpacing()[2];
vtkMatrix4x4* matrix = reslice->GetResliceAxes();
// move the center point that we are slicing through
double point[4];
double center[4];
point[0] = 0.0;
point[1] = 0.0;
point[2] = sliceSpacing * deltaY;
point[3] = 1.0;
matrix->MultiplyPoint(point, center);
matrix->SetElement(0, 3, center[0]);
matrix->SetElement(1, 3, center[1]);
matrix->SetElement(2, 3, center[2]);
interactor->Render();
}
else
{
vtkInteractorStyle* style =
vtkInteractorStyle::SafeDownCast(interactor->GetInteractorStyle());
if (style)
{
style->OnMouseMove();
}
}
}
}
private:
// Actions (slicing only, for now)
int Slicing;
// Pointer to vtkImageReslice
vtkImageReslice* ImageReslice;
// Pointer to the interactor
vtkRenderWindowInteractor* Interactor;
};
// The program entry point
int tutorial_reslice_1(int argc, char* argv[])
{
std::string rootDir = std::string(DATA_DIR);
std::string fullpath = rootDir + "headsq/quarter";
// Start by loading some data.
vtkSmartPointer<vtkImageReader2> reader = vtkSmartPointer<vtkImageReader2>::New();
reader->SetFilePrefix(fullpath.c_str());
reader->SetDataExtent(0, 63, 0, 63, 1, 93);
reader->SetDataSpacing(3.2, 3.2, 1.5);
reader->SetDataOrigin(0.0, 0.0, 0.0);
reader->SetDataScalarTypeToUnsignedShort();
reader->SetDataByteOrderToLittleEndian();
reader->UpdateWholeExtent();
// Calculate the center of the volume
reader->Update();
int extent[6];
double spacing[3];
double origin[3];
reader->GetOutputInformation(0)->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent);
reader->GetOutput()->GetSpacing(spacing);
reader->GetOutput()->GetOrigin(origin);
double center[3];
center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);
center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);
center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);
// Matrices for axial, coronal, sagittal, oblique view orientations
// static double axialElements[16] = {
// 1, 0, 0, 0,
// 0, 1, 0, 0,
// 0, 0, 1, 0,
// 0, 0, 0, 1 };
// static double coronalElements[16] = {
// 1, 0, 0, 0,
// 0, 0, 1, 0,
// 0,-1, 0, 0,
// 0, 0, 0, 1 };
static double sagittalElements[16] = {
0, 0, -1, 0, //
1, 0, 0, 0, //
0, -1, 0, 0, //
0, 0, 0, 1 //
};
// static double obliqueElements[16] = {
// 1, 0, 0, 0,
// 0, 0.866025, -0.5, 0,
// 0, 0.5, 0.866025, 0,
// 0, 0, 0, 1 };
// Set the slice orientation
vtkSmartPointer<vtkMatrix4x4> resliceAxes = vtkSmartPointer<vtkMatrix4x4>::New();
resliceAxes->DeepCopy(sagittalElements);
// Set the point through which to slice
resliceAxes->SetElement(0, 3, center[0]);
resliceAxes->SetElement(1, 3, center[1]);
resliceAxes->SetElement(2, 3, center[2]);
// Extract a slice in the desired orientation
vtkSmartPointer<vtkImageReslice> reslice = vtkSmartPointer<vtkImageReslice>::New();
reslice->SetInputConnection(reader->GetOutputPort());
reslice->SetOutputDimensionality(2);
reslice->SetResliceAxes(resliceAxes);
reslice->SetInterpolationModeToLinear();
// Create a greyscale lookup table
vtkSmartPointer<vtkLookupTable> table = vtkSmartPointer<vtkLookupTable>::New();
table->SetRange(0, 2000); // image intensity range
table->SetValueRange(0.0, 1.0); // from black to white
table->SetSaturationRange(0.0, 0.0); // no color saturation
table->SetRampToLinear();
table->Build();
// Map the image through the lookup table
vtkSmartPointer<vtkImageMapToColors> color = vtkSmartPointer<vtkImageMapToColors>::New();
color->SetLookupTable(table);
color->SetInputConnection(reslice->GetOutputPort());
// Display the image
vtkSmartPointer<vtkImageActor> actor = vtkSmartPointer<vtkImageActor>::New();
actor->GetMapper()->SetInputConnection(color->GetOutputPort());
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
vtkSmartPointer<vtkRenderWindow> window = vtkSmartPointer<vtkRenderWindow>::New();
window->AddRenderer(renderer);
// Set up the interaction
vtkSmartPointer<vtkInteractorStyleImage> imageStyle =
vtkSmartPointer<vtkInteractorStyleImage>::New();
vtkSmartPointer<vtkRenderWindowInteractor> interactor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetInteractorStyle(imageStyle);
window->SetInteractor(interactor);
window->Render();
vtkSmartPointer<vtkImageInteractionCallback> callback =
vtkSmartPointer<vtkImageInteractionCallback>::New();
callback->SetImageReslice(reslice);
callback->SetInteractor(interactor);
imageStyle->AddObserver(vtkCommand::MouseMoveEvent, callback);
imageStyle->AddObserver(vtkCommand::LeftButtonPressEvent, callback);
imageStyle->AddObserver(vtkCommand::LeftButtonReleaseEvent, callback);
// Start interaction
// The Start() method doesn't return until the window is closed by the user
interactor->Start();
return EXIT_SUCCESS;
}
constexpr char TestSliderWidgetMultipleViewportsLog[] = "# StreamVersion 1\n"
"EnterEvent 292 46 0 0 0 0 0\n"
"MouseMoveEvent 273 65 0 0 0 0 0\n"
"MouseMoveEvent 252 88 0 0 0 0 0\n"
"MouseMoveEvent 148 299 0 0 0 0 0\n"
"LeaveEvent 147 301 0 0 0 0 0\n"
"EnterEvent 145 299 0 0 0 0 0\n"
"MouseMoveEvent 145 299 0 0 0 0 0\n"
"MouseMoveEvent 115 190 0 0 0 0 0\n"
"LeftButtonPressEvent 115 190 0 0 0 0 0\n"
"StartInteractionEvent 115 190 0 0 0 0 0\n"
"LeftButtonReleaseEvent 115 190 0 0 0 0 0\n"
"EndInteractionEvent 115 190 0 0 0 0 0\n"
"RenderEvent 115 190 0 0 0 0 0\n"
"KeyPressEvent 115 190 0 0 114 1 r\n"
"CharEvent 115 190 0 0 114 1 r\n"
"RenderEvent 115 190 0 0 114 1 r\n"
"KeyReleaseEvent 115 190 0 0 114 1 r\n"
"MouseMoveEvent 194 163 0 0 0 0 r\n"
"MouseMoveEvent 195 163 0 0 0 0 r\n"
"LeftButtonPressEvent 195 163 0 0 0 0 r\n"
"RenderEvent 195 163 0 0 0 0 r\n"
"MouseMoveEvent 195 163 0 0 0 0 r\n"
"MouseMoveEvent 201 151 0 0 0 0 r\n"
"RenderEvent 201 151 0 0 0 0 r\n"
"LeftButtonReleaseEvent 201 151 0 0 0 0 r\n"
"RenderEvent 201 151 0 0 0 0 r\n"
"LeftButtonPressEvent 204 29 0 0 0 0 r\n"
"RenderEvent 204 29 0 0 0 0 r\n"
"RenderEvent 210 30 0 0 0 0 r\n"
"LeftButtonReleaseEvent 210 30 0 0 0 0 r\n"
"LeftButtonPressEvent 158 159 0 0 0 0 r\n"
"RenderEvent 158 159 0 0 0 0 r\n"
"LeftButtonReleaseEvent 169 138 0 0 0 0 r\n"
"RenderEvent 169 138 0 0 0 0 r\n"
"RenderEvent 169 138 0 0 0 0 r\n"
"MouseMoveEvent 251 159 0 0 0 0 r\n"
"LeftButtonPressEvent 251 159 0 0 0 0 r\n"
"StartInteractionEvent 251 159 0 0 0 0 r\n"
"TimerEvent 251 159 0 0 0 0 r\n"
"RenderEvent 251 159 0 0 0 0 r\n"
"TimerEvent 251 159 0 0 0 0 r\n"
"RenderEvent 251 159 0 0 0 0 r\n"
"TimerEvent 251 159 0 0 0 0 r\n"
"RenderEvent 251 159 0 0 0 0 r\n"
"TimerEvent 251 159 0 0 0 0 r\n"
"RenderEvent 251 159 0 0 0 0 r\n"
"LeftButtonReleaseEvent 251 159 0 0 0 0 r\n"
"EndInteractionEvent 251 159 0 0 0 0 r\n"
"RenderEvent 251 159 0 0 0 0 r\n"
"LeftButtonPressEvent 250 159 0 0 0 0 r\n"
"StartInteractionEvent 250 159 0 0 0 0 r\n"
"TimerEvent 250 159 0 0 0 0 r\n"
"RenderEvent 250 159 0 0 0 0 r\n"
"TimerEvent 250 159 0 0 0 0 r\n"
"RenderEvent 250 159 0 0 0 0 r\n"
"TimerEvent 250 159 0 0 0 0 r\n"
"RenderEvent 250 159 0 0 0 0 r\n"
"TimerEvent 250 159 0 0 0 0 r\n"
"RenderEvent 250 159 0 0 0 0 r\n"
"TimerEvent 250 159 0 0 0 0 r\n"
"RenderEvent 250 159 0 0 0 0 r\n"
"TimerEvent 250 159 0 0 0 0 r\n"
"RenderEvent 250 159 0 0 0 0 r\n"
"LeftButtonReleaseEvent 250 159 0 0 0 0 r\n"
"EndInteractionEvent 250 159 0 0 0 0 r\n"
"RenderEvent 250 159 0 0 0 0 r\n"
"LeftButtonPressEvent 250 159 0 0 0 0 r\n"
"RenderEvent 250 159 0 0 0 0 r\n"
"LeftButtonReleaseEvent 250 159 0 0 0 0 r\n"
"RenderEvent 250 159 0 0 0 0 r\n"
"LeftButtonPressEvent 209 30 0 0 0 0 r\n"
"RenderEvent 209 30 0 0 0 0 r\n"
"MouseMoveEvent 209 30 0 0 0 0 r\n"
"RenderEvent 209 30 0 0 0 0 r\n"
"MouseMoveEvent 210 30 0 0 0 0 r\n"
"RenderEvent 210 30 0 0 0 0 r\n"
"MouseMoveEvent 210 30 0 0 0 0 r\n"
"RenderEvent 210 30 0 0 0 0 r\n"
"MouseMoveEvent 211 30 0 0 0 0 r\n"
"RenderEvent 211 30 0 0 0 0 r\n"
"MouseMoveEvent 212 30 0 0 0 0 r\n"
"RenderEvent 212 30 0 0 0 0 r\n"
"MouseMoveEvent 214 30 0 0 0 0 r\n"
"RenderEvent 214 30 0 0 0 0 r\n"
"MouseMoveEvent 214 30 0 0 0 0 r\n"
"RenderEvent 214 30 0 0 0 0 r\n"
"MouseMoveEvent 215 30 0 0 0 0 r\n"
"RenderEvent 215 30 0 0 0 0 r\n"
"MouseMoveEvent 233 30 0 0 0 0 r\n"
"RenderEvent 233 30 0 0 0 0 r\n"
"LeftButtonReleaseEvent 233 30 0 0 0 0 r\n"
"MouseMoveEvent 204 30 0 0 0 0 r\n"
"LeftButtonPressEvent 204 30 0 0 0 0 r\n"
"RenderEvent 204 30 0 0 0 0 r\n"
"LeftButtonReleaseEvent 204 30 0 0 0 0 r\n"
"RenderEvent 204 30 0 0 0 0 r\n"
"RenderEvent 204 30 0 0 0 0 r\n"
"MouseMoveEvent 239 83 0 0 0 0 r\n";
// This does the actual work: updates the probe.
// Callback for the interaction
class vtkSliderMultipleViewportsCallback : public vtkCommand
{
public:
static vtkSliderMultipleViewportsCallback* New()
{
return new vtkSliderMultipleViewportsCallback;
}
void Execute(vtkObject* caller, unsigned long, void*) override
{
vtkSliderWidget* sliderWidget = reinterpret_cast<vtkSliderWidget*>(caller);
this->Glyph->SetScaleFactor(
static_cast<vtkSliderRepresentation*>(sliderWidget->GetRepresentation())->GetValue());
}
vtkSliderMultipleViewportsCallback()
: Glyph(nullptr)
{
}
vtkGlyph3D* Glyph;
};
int tutorial_slider_1(int argc, char* argv[])
{
// Create a mace out of filters.
//
vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
vtkSmartPointer<vtkConeSource> cone = vtkSmartPointer<vtkConeSource>::New();
vtkSmartPointer<vtkGlyph3D> glyph = vtkSmartPointer<vtkGlyph3D>::New();
glyph->SetInputConnection(sphereSource->GetOutputPort());
glyph->SetSourceConnection(cone->GetOutputPort());
glyph->SetVectorModeToUseNormal();
glyph->SetScaleModeToScaleByVector();
glyph->SetScaleFactor(0.25);
// The sphere and spikes are appended into a single polydata.
// This just makes things simpler to manage.
vtkSmartPointer<vtkAppendPolyData> apd = vtkSmartPointer<vtkAppendPolyData>::New();
apd->AddInputConnection(glyph->GetOutputPort());
apd->AddInputConnection(sphereSource->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> maceMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
maceMapper->SetInputConnection(apd->GetOutputPort());
vtkSmartPointer<vtkLODActor> maceActor = vtkSmartPointer<vtkLODActor>::New();
maceActor->SetMapper(maceMapper);
maceActor->VisibilityOn();
maceActor->SetPosition(1, 1, 1);
// Create the RenderWindow, Renderer and both Actors
//
vtkSmartPointer<vtkRenderer> ren1 = vtkSmartPointer<vtkRenderer>::New();
ren1->SetViewport(0, 0, 0.5, 1.0);
vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer(ren1);
vtkSmartPointer<vtkRenderer> ren2 = vtkSmartPointer<vtkRenderer>::New();
ren2->SetViewport(0.5, 0, 1.0, 1.0);
renWin->AddRenderer(ren2);
vtkSmartPointer<vtkRenderWindowInteractor> iren =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
iren->SetRenderWindow(renWin);
// VTK widgets consist of two parts: the widget part that handles event
// processing; and the widget representation that defines how the widget
// appears in the scene (i.e., matters pertaining to geometry).
vtkSmartPointer<vtkSliderRepresentation2D> sliderRep =
vtkSmartPointer<vtkSliderRepresentation2D>::New();
sliderRep->SetValue(0.25);
sliderRep->SetTitleText("Spike Size");
sliderRep->GetPoint1Coordinate()->SetCoordinateSystemToNormalizedDisplay();
sliderRep->GetPoint1Coordinate()->SetValue(0.1, 0.1);
sliderRep->GetPoint2Coordinate()->SetCoordinateSystemToNormalizedDisplay();
sliderRep->GetPoint2Coordinate()->SetValue(0.4, 0.1);
sliderRep->SetSliderLength(0.02);
sliderRep->SetSliderWidth(0.03);
sliderRep->SetEndCapLength(0.01);
sliderRep->SetEndCapWidth(0.03);
sliderRep->SetTubeWidth(0.005);
vtkSmartPointer<vtkSliderWidget> sliderWidget = vtkSmartPointer<vtkSliderWidget>::New();
sliderWidget->SetInteractor(iren);
sliderWidget->SetRepresentation(sliderRep);
sliderWidget->SetCurrentRenderer(ren2);
sliderWidget->SetAnimationModeToAnimate();
vtkSmartPointer<vtkSliderMultipleViewportsCallback> callback =
vtkSmartPointer<vtkSliderMultipleViewportsCallback>::New();
callback->Glyph = glyph;
sliderWidget->AddObserver(vtkCommand::InteractionEvent, callback);
ren1->AddActor(maceActor);
sliderWidget->EnabledOn();
vtkSmartPointer<vtkSliderRepresentation3D> sliderRep3D =
vtkSmartPointer<vtkSliderRepresentation3D>::New();
sliderRep3D->SetValue(0.25);
sliderRep3D->SetTitleText("Spike Size");
sliderRep3D->GetPoint1Coordinate()->SetCoordinateSystemToWorld();
sliderRep3D->GetPoint1Coordinate()->SetValue(0, 0, 0);
sliderRep3D->GetPoint2Coordinate()->SetCoordinateSystemToWorld();
sliderRep3D->GetPoint2Coordinate()->SetValue(2, 0, 0);
sliderRep3D->SetSliderLength(0.075);
sliderRep3D->SetSliderWidth(0.05);
sliderRep3D->SetEndCapLength(0.05);
vtkSmartPointer<vtkSliderWidget> sliderWidget3D = vtkSmartPointer<vtkSliderWidget>::New();
sliderWidget3D->GetEventTranslator()->SetTranslation(
vtkCommand::RightButtonPressEvent, vtkWidgetEvent::Select);
sliderWidget3D->GetEventTranslator()->SetTranslation(
vtkCommand::RightButtonReleaseEvent, vtkWidgetEvent::EndSelect);
sliderWidget3D->SetInteractor(iren);
sliderWidget3D->SetRepresentation(sliderRep3D);
sliderWidget3D->SetCurrentRenderer(ren2);
sliderWidget3D->SetAnimationModeToAnimate();
sliderWidget3D->EnabledOn();
sliderWidget3D->AddObserver(vtkCommand::InteractionEvent, callback);
// Add the actors to the renderer, set the background and size
//
ren1->SetBackground(0.1, 0.2, 0.4);
ren2->SetBackground(0.9, 0.4, 0.2);
renWin->SetSize(300, 300);
// render the image
//
iren->Initialize();
renWin->Render();
return vtkTesting::InteractorEventLoop(argc, argv, iren, TestSliderWidgetMultipleViewportsLog);
}