/*=========================================================================
Program: Visualization Toolkit
Module: vtkResliceCursorWidget.cxx
Copyright © 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 “vtkResliceCursorWidget.h”
#include “vtkResliceCursorLineRepresentation.h”
#include “vtkCommand.h”
#include “vtkResliceCursor.h”
#include “vtkCallbackCommand.h”
#include “vtkRenderWindowInteractor.h”
#include “vtkObjectFactory.h”
#include “vtkRenderer.h”
#include “vtkRenderWindow.h”
#include “vtkWidgetEventTranslator.h”
#include “vtkWidgetCallbackMapper.h”
#include “vtkEvent.h”
#include “vtkWidgetEvent.h”
#include “vtkImageData.h”
#include “vtkInteractorStyleImage.h”
#include “vtkImageMapToWindowLevelColors.h”
vtkStandardNewMacro(vtkResliceCursorWidget);
//----------------------------------------------------------------------------
vtkResliceCursorWidget::vtkResliceCursorWidget()
{
// Set the initial state
this->WidgetState = vtkResliceCursorWidget::Start;
this->ModifierActive = 0;
//设置微件的回调,将鼠标左键按下事件转换为 vtkWidgetEvent::Select,这个事件
//没有设置修改器(修改器就是指有没有按住shift ctrl这种,)
//直接调用的方法就是vtkResliceCursorWidget::SelectAction),这是一个静态方法。
//vtkWidgetEvent::Select这个在这个cpp中没有用到,不知道在这个cpp里的作用,
//但是如果你想在类外面给微件添加回调,可以添加这个事件,等于左键按下
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonPressEvent,
vtkEvent::NoModifier, 0, 0, nullptr,
vtkWidgetEvent::Select,
this, vtkResliceCursorWidget::SelectAction);
//这里就加了一个Control修改器,同样都是左键按下,如果按了ctrl那么执行的就是
// vtkResliceCursorWidget::RotateAction 这个
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonPressEvent,
vtkEvent::ControlModifier, 0, 0, nullptr,
vtkWidgetEvent::Rotate,
this, vtkResliceCursorWidget::RotateAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonReleaseEvent,
vtkWidgetEvent::EndSelect,
this, vtkResliceCursorWidget::EndSelectAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::RightButtonPressEvent,
vtkWidgetEvent::Resize,
this, vtkResliceCursorWidget::ResizeThicknessAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::RightButtonReleaseEvent,
vtkWidgetEvent::EndResize,
this, vtkResliceCursorWidget::EndSelectAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::MouseMoveEvent,
vtkWidgetEvent::Move,
this, vtkResliceCursorWidget::MoveAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::KeyPressEvent,
vtkEvent::NoModifier, 111, 1, “o”,
vtkWidgetEvent::Reset,
this, vtkResliceCursorWidget::ResetResliceCursorAction);
this->ManageWindowLevel = 1;
}
//----------------------------------------------------------------------------
vtkResliceCursorWidget::~vtkResliceCursorWidget() = default;
//----------------------------------------------------------------------
void vtkResliceCursorWidget::SetEnabled(int enabling)
{
this->Superclass::SetEnabled(enabling);
}
//创建默认表达
//----------------------------------------------------------------------
void vtkResliceCursorWidget::CreateDefaultRepresentation()
{
if ( ! this->WidgetRep )
{
this->WidgetRep = vtkResliceCursorLineRepresentation::New();
}
}
//根据鼠标目前位置状态,来为鼠标设置外观,
//-------------------------------------------------------------------------
void vtkResliceCursorWidget::SetCursor(int cState)
{
switch (cState)
{
case vtkResliceCursorRepresentation::OnAxis1:
case vtkResliceCursorRepresentation::OnAxis2:
this->RequestCursorShape(VTK_CURSOR_HAND);
break;
case vtkResliceCursorRepresentation::OnCenter:
if (vtkEvent::GetModifier(this->Interactor) != vtkEvent::ControlModifier)
{
this->RequestCursorShape(VTK_CURSOR_SIZEALL);
}
break;
case vtkResliceCursorRepresentation::Outside:
default:
this->RequestCursorShape(VTK_CURSOR_DEFAULT);
}
}
//暂时还没看mip相关
//-------------------------------------------------------------------------
void vtkResliceCursorWidget::ResizeThicknessAction(vtkAbstractWidget *w)
{
vtkResliceCursorWidget self = reinterpret_cast<vtkResliceCursorWidget>(w);
vtkResliceCursorRepresentation rep =
reinterpret_cast<vtkResliceCursorRepresentation>(self->WidgetRep);
int X = self->Interactor->GetEventPosition()[0];
int Y = self->Interactor->GetEventPosition()[1];
rep->ComputeInteractionState(X, Y, self->ModifierActive);
if ( self->WidgetRep->GetInteractionState()
== vtkResliceCursorRepresentation::Outside ||
rep->GetResliceCursor()->GetThickMode() == 0 )
{
return;
}
rep->SetManipulationMode(vtkResliceCursorRepresentation::ResizeThickness);
self->GrabFocus(self->EventCallbackCommand);
double eventPos[2];
eventPos[0] = static_cast(X);
eventPos[1] = static_cast(Y);
self->WidgetRep->StartWidgetInteraction(eventPos);
// We are definitely selected
self->WidgetState = vtkResliceCursorWidget::Active;
self->SetCursor(self->WidgetRep->GetInteractionState());
// Highlight as necessary
self->WidgetRep->Highlight(1);
self->EventCallbackCommand->SetAbortFlag(1);
self->StartInteraction();
self->InvokeEvent(vtkCommand::StartInteractionEvent,nullptr);
self->Render();
self->InvokeAnEvent();
// Show the thickness in “mm”
rep->ActivateText(1);
}
//-------------------------------------------------------------------------
void vtkResliceCursorWidget::EndResizeThicknessAction(vtkAbstractWidget *)
{
}
//这里等于左键按下事件,这里是一个静态函数,没有this指针,但是这里通过传参的方
//法弄了一个self指针
//-------------------------------------------------------------------------
void vtkResliceCursorWidget::SelectAction(vtkAbstractWidget *w)
{
vtkResliceCursorWidget self = reinterpret_cast<vtkResliceCursorWidget>(w);
vtkResliceCursorRepresentation rep =
reinterpret_cast<vtkResliceCursorRepresentation>(self->WidgetRep);
int X = self->Interactor->GetEventPosition()[0];
int Y = self->Interactor->GetEventPosition()[1];
//这里判断有没有按住shif或者ctrl之类的
self->ModifierActive = vtkEvent::GetModifier(self->Interactor);
rep->ComputeInteractionState(X, Y, self->ModifierActive);
//下面就是根据不同状态触发不同事件
if ( self->WidgetRep->GetInteractionState()
== vtkResliceCursorRepresentation::Outside )
{
if (self->GetManageWindowLevel() && rep->GetShowReslicedImage())
{
self->StartWindowLevel();
}
else
{
rep->SetManipulationMode(vtkResliceCursorRepresentation::None);
return;
}
}
else
{
rep->SetManipulationMode(vtkResliceCursorRepresentation::PanAndRotate);
}
if (rep->GetManipulationMode() == vtkResliceCursorRepresentation::None)
{
return;
}
self->GrabFocus(self->EventCallbackCommand);
double eventPos[2];
eventPos[0] = static_cast(X);
eventPos[1] = static_cast(Y);
self->WidgetRep->StartWidgetInteraction(eventPos);
// We are definitely selected
self->WidgetState = vtkResliceCursorWidget::Active;
self->SetCursor(self->WidgetRep->GetInteractionState());
// Highlight as necessary
self->WidgetRep->Highlight(1);
self->EventCallbackCommand->SetAbortFlag(1);
self->StartInteraction();
//最后根据vtkCommand::StartInteractionEvent去执行对应事件
self->InvokeEvent(vtkCommand::StartInteractionEvent,nullptr);
self->Render();
self->InvokeAnEvent();
}
//按住ctrl执行的事件两轴同时旋转
//-------------------------------------------------------------------------
void vtkResliceCursorWidget::RotateAction(vtkAbstractWidget *w)
{
vtkResliceCursorWidget self = reinterpret_cast<vtkResliceCursorWidget>(w);
vtkResliceCursorRepresentation rep =
reinterpret_cast<vtkResliceCursorRepresentation>(self->WidgetRep);
int X = self->Interactor->GetEventPosition()[0];
int Y = self->Interactor->GetEventPosition()[1];
self->ModifierActive = vtkEvent::GetModifier(self->Interactor);
rep->ComputeInteractionState(X, Y, self->ModifierActive);
if ( self->WidgetRep->GetInteractionState()
== vtkResliceCursorRepresentation::Outside )
{
return;
}
rep->SetManipulationMode(vtkResliceCursorRepresentation::RotateBothAxes);
self->GrabFocus(self->EventCallbackCommand);
double eventPos[2];
eventPos[0] = static_cast(X);
eventPos[1] = static_cast(Y);
self->WidgetRep->StartWidgetInteraction(eventPos);
// We are definitely selected
self->WidgetState = vtkResliceCursorWidget::Active;
self->SetCursor(self->WidgetRep->GetInteractionState());
// Highlight as necessary
self->WidgetRep->Highlight(1);
self->EventCallbackCommand->SetAbortFlag(1);
self->StartInteraction();
self->InvokeEvent(vtkCommand::StartInteractionEvent,nullptr);
self->Render();
self->InvokeAnEvent();
}
//-------------------------------------------------------------------------
void vtkResliceCursorWidget::MoveAction(vtkAbstractWidget *w)
{
vtkResliceCursorWidget self = reinterpret_cast<vtkResliceCursorWidget>(w);
vtkResliceCursorRepresentation rep =
reinterpret_cast<vtkResliceCursorRepresentation>(self->WidgetRep);
// compute some info we need for all cases
int X = self->Interactor->GetEventPosition()[0];
int Y = self->Interactor->GetEventPosition()[1];
// Set the cursor appropriately
if ( self->WidgetState == vtkResliceCursorWidget::Start )
{
self->ModifierActive = vtkEvent::GetModifier(self->Interactor);
int state = self->WidgetRep->GetInteractionState();
rep->ComputeInteractionState(X, Y, self->ModifierActive );
self->SetCursor(self->WidgetRep->GetInteractionState());
if ( state != self->WidgetRep->GetInteractionState() )
{
self->Render();
}
return;
}
// Okay, adjust the representation
double eventPosition[2];
eventPosition[0] = static_cast(X);
eventPosition[1] = static_cast(Y);
self->WidgetRep->WidgetInteraction(eventPosition);
// Got this event, we are finished
self->EventCallbackCommand->SetAbortFlag(1);
self->InvokeEvent(vtkCommand::InteractionEvent,nullptr);
self->Render();
self->InvokeAnEvent();
}
//-------------------------------------------------------------------------
void vtkResliceCursorWidget::EndSelectAction(vtkAbstractWidget *w)
{
vtkResliceCursorWidget self = static_cast<vtkResliceCursorWidget>(w);
vtkResliceCursorRepresentation rep =
reinterpret_cast<vtkResliceCursorRepresentation>(self->WidgetRep);
if ( self->WidgetState != vtkResliceCursorWidget::Active )
{
return;
}
int X = self->Interactor->GetEventPosition()[0];
int Y = self->Interactor->GetEventPosition()[1];
double eventPos[2];
eventPos[0] = static_cast(X);
eventPos[1] = static_cast(Y);
self->WidgetRep->EndWidgetInteraction(eventPos);
// return to initial state
self->WidgetState = vtkResliceCursorWidget::Start;
self->ModifierActive = 0;
// Highlight as necessary
self->WidgetRep->Highlight(0);
// Remove any text displays. We are no longer active.
rep->ActivateText(0);
// stop adjusting
self->ReleaseFocus();
self->EventCallbackCommand->SetAbortFlag(1);
self->EndInteraction();
self->InvokeEvent(vtkCommand::EndInteractionEvent,nullptr);
self->WidgetState = vtkResliceCursorWidget::Start;
rep->SetManipulationMode(vtkResliceCursorRepresentation::None);
self->Render();
self->InvokeAnEvent();
}
//-------------------------------------------------------------------------
void vtkResliceCursorWidget::ResetResliceCursorAction(vtkAbstractWidget *w)
{
vtkResliceCursorWidget self = reinterpret_cast<vtkResliceCursorWidget>(w);
self->ResetResliceCursor();
// Render in response to changes
self->Render();
// Invoke a reslice cursor event
self->InvokeEvent( vtkResliceCursorWidget::ResetCursorEvent, nullptr );
}
//重置状态
//-------------------------------------------------------------------------
void vtkResliceCursorWidget::ResetResliceCursor()
{
vtkResliceCursorRepresentation rep =
reinterpret_cast<vtkResliceCursorRepresentation>(this->WidgetRep);
if (!rep->GetResliceCursor())
{
return; // nothing to reset
}
// Reset the reslice cursor
rep->GetResliceCursor()->Reset();
rep->InitializeReslicePlane();
}
//----------------------------------------------------------------------------
void vtkResliceCursorWidget::StartWindowLevel()
{
vtkResliceCursorRepresentation rep =
reinterpret_cast<vtkResliceCursorRepresentation>(this->WidgetRep);
int X = this->Interactor->GetEventPosition()[0];
int Y = this->Interactor->GetEventPosition()[1];
// Okay, make sure that the pick is in the current renderer
if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
{
rep->SetManipulationMode(vtkResliceCursorRepresentation::None);
return;
}
rep->SetManipulationMode(vtkResliceCursorRepresentation::WindowLevelling);
rep->ActivateText(1);
rep->ManageTextDisplay();
}
//----------------------------------------------------------------------------
void vtkResliceCursorWidget::InvokeAnEvent()
{
// We invoke the appropriate event. In cases where the cursor is moved
// around, or rotated, also have the reslice cursor invoke an event.
//每个widget,都绑定了rep,这里就是根据绑定的rep来执行对应事件
vtkResliceCursorRepresentation rep =
reinterpret_cast<vtkResliceCursorRepresentation>(this->WidgetRep);
if (rep)
{
int mode = rep->GetManipulationMode();
if (mode == vtkResliceCursorRepresentation::WindowLevelling)
{
this->InvokeEvent(WindowLevelEvent,nullptr);
}
else if (mode == vtkResliceCursorRepresentation::PanAndRotate)
{
this->InvokeEvent(ResliceAxesChangedEvent,nullptr);
rep->GetResliceCursor()->InvokeEvent(ResliceAxesChangedEvent,nullptr);
}
else if (mode == vtkResliceCursorRepresentation::RotateBothAxes)
{
this->InvokeEvent(ResliceAxesChangedEvent,nullptr);
rep->GetResliceCursor()->InvokeEvent(ResliceAxesChangedEvent,nullptr);
}
else if (mode == vtkResliceCursorRepresentation::ResizeThickness)
{
this->InvokeEvent(ResliceThicknessChangedEvent,nullptr);
rep->GetResliceCursor()->InvokeEvent(ResliceAxesChangedEvent,nullptr);
}
}
}
//----------------------------------------------------------------------------
void vtkResliceCursorWidget::PrintSelf(ostream& os, vtkIndent indent)
{
//Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
this->Superclass::PrintSelf(os,indent);
os << indent << "ManageWindowLevel: " << this->ManageWindowLevel << endl;
// this->ModifierActive;
// this->WidgetState;
}