Add 3D Reslice MPR free rotate.

This commit is contained in:
Krad
2023-03-16 11:08:20 +08:00
parent 011ca20207
commit 90b4398661
8 changed files with 142 additions and 6 deletions

View File

@@ -232,3 +232,49 @@ void ResliceImageInteractorStyle::WindowLevel() {
void ResliceImageInteractorStyle::SetMode(int mode) { void ResliceImageInteractorStyle::SetMode(int mode) {
this->InteractionMode = mode; this->InteractionMode = mode;
} }
void ResliceImageInteractorStyle::Rotate()
{
if (this->CurrentRenderer == nullptr)
{
return;
}
vtkRenderWindowInteractor* rwi = this->Interactor;
int dx = rwi->GetEventPosition()[0] - rwi->GetLastEventPosition()[0];
int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1];
const int* size = this->CurrentRenderer->GetRenderWindow()->GetSize();
double delta_elevation = -20.0 / size[1];
double delta_azimuth = -20.0 / size[0];
double rxf = dx * delta_azimuth * this->MotionFactor;
double ryf = dy * delta_elevation * this->MotionFactor;
vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
camera->Azimuth(rxf);
camera->Elevation(ryf);
camera->OrthogonalizeViewUp();
if (this->AutoAdjustCameraClippingRange)
{
this->CurrentRenderer->ResetCameraClippingRange();
}
if (rwi->GetLightFollowCamera())
{
this->CurrentRenderer->UpdateLightsGeometryToFollowCamera();
}
if (this->HandleObservers &&
this->HasObserver(vtkCommand::RotateEvent)) {
this->InvokeEvent(vtkCommand::RotateEvent, this);
}
rwi->Render();
}
void ResliceImageInteractorStyle::EndRotate() {
this->InvokeEvent(vtkCommand::EndRotateEvent);
vtkInteractorStyle::EndRotate();
}

View File

@@ -37,6 +37,11 @@ public:
this->State = VTKIS_NONE; this->State = VTKIS_NONE;
} }
vtkSetMacro(CurrentImageProperty, vtkImageProperty*); vtkSetMacro(CurrentImageProperty, vtkImageProperty*);
void Rotate() override;
void EndRotate() override;
protected: protected:
ResliceImageInteractorStyle(); ResliceImageInteractorStyle();

View File

@@ -129,7 +129,13 @@ void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) {
if(dragging){ if(dragging){
Drag(renderer); Drag(renderer);
} }
auto style = vtkInteractorStyle::SafeDownCast(renderer->GetRenderWindow()->GetInteractor()->GetInteractorStyle());
if (style){
//avoid 3d rotate update
if (style->GetState() == VTKIS_ROTATE) return;
}
if (LoadTime.GetMTime()>MTime.GetMTime() && LoadTime.GetMTime()>renderer->GetActiveCamera()->GetMTime()) return; if (LoadTime.GetMTime()>MTime.GetMTime() && LoadTime.GetMTime()>renderer->GetActiveCamera()->GetMTime()) return;
if (StopUpdateFlag) return;
//handle disk //handle disk
if (HandleUpdated) { if (HandleUpdated) {
renderer->SetDisplayPoint(Handle2DPoint[0], Handle2DPoint[1], 0); renderer->SetDisplayPoint(Handle2DPoint[0], Handle2DPoint[1], 0);
@@ -187,8 +193,15 @@ void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) {
if (IntersectLine2D(p0, v1, pt, screenVectors[i], intersectPoint)) { if (IntersectLine2D(p0, v1, pt, screenVectors[i], intersectPoint)) {
int pcV = (int) intersectPoint.getValue(i); int pcV = (int) intersectPoint.getValue(i);
if (pcV >= -1 && pcV <= size[i] + 1) { if (pcV >= -1 && pcV <= size[i] + 1) {
linePolyData->GetPoints()->SetPoint(pointIdx++, (int) intersectPoint.X + 0.05, //避免double计算精度导致的极小的移动产生的hair cross振动
(int) intersectPoint.Y + 0.05, 0); double oldPt[3] = {.0, .0, .0};
linePolyData->GetPoints()->GetPoint(pointIdx, oldPt);
double newPt[3] = {(int) intersectPoint.X + 0.05,
(int) intersectPoint.Y + 0.05, .0};
if (vtkMath::Distance2BetweenPoints(oldPt,newPt)>0.9){
linePolyData->GetPoints()->SetPoint(pointIdx, newPt);
}
pointIdx++;
} }
} }
} }

View File

@@ -105,6 +105,13 @@ public:
} }
} }
void StopUpdate(){
StopUpdateFlag = true;
}
void BeginUpdate(){
StopUpdateFlag = false;
}
void ActiveControlPointOn(); void ActiveControlPointOn();
void ActiveControlPointOff(); void ActiveControlPointOff();
@@ -144,6 +151,7 @@ private:
bool dragging = false; bool dragging = false;
bool Moving = false; bool Moving = false;
bool Rolling = false; bool Rolling = false;
bool StopUpdateFlag = false;
int DragStartPosition[2] = {0,0}; int DragStartPosition[2] = {0,0};
double Handle2DPoint[2] = {.0, .0, }; double Handle2DPoint[2] = {.0, .0, };
double SliceDirectionVector[3] = {.0, .0, .0}; double SliceDirectionVector[3] = {.0, .0, .0};

View File

@@ -198,6 +198,8 @@ void ResliceImageViewer::Render() {
this->InteractorStyle->AddObserver(SliceEvent,this, &ResliceImageViewer::SliceCallback); this->InteractorStyle->AddObserver(SliceEvent,this, &ResliceImageViewer::SliceCallback);
this->InteractorStyle->AddObserver(vtkCommand::WindowLevelEvent,this, &ResliceImageViewer::WindowLevelCallback); this->InteractorStyle->AddObserver(vtkCommand::WindowLevelEvent,this, &ResliceImageViewer::WindowLevelCallback);
this->InteractorStyle->AddObserver(vtkCommand::EndWindowLevelEvent,this, &ResliceImageViewer::EndWindowLevelCallback); this->InteractorStyle->AddObserver(vtkCommand::EndWindowLevelEvent,this, &ResliceImageViewer::EndWindowLevelCallback);
this->InteractorStyle->AddObserver(vtkCommand::RotateEvent,this, &ResliceImageViewer::EndRotateCallback);
// this->InteractorStyle->AddObserver(vtkCommand::EndRotateEvent,this, &ResliceImageViewer::EndRotateCallback);
this->RenderWindow->AddObserver(vtkCommand::WindowResizeEvent,this,&ResliceImageViewer::handleResize); this->RenderWindow->AddObserver(vtkCommand::WindowResizeEvent,this,&ResliceImageViewer::handleResize);
cursor1->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll); cursor1->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll);
@@ -494,3 +496,25 @@ void ResliceImageViewer::WindowLevelCallback() {
(int)Actor->GetProperty()->GetColorWindow()); (int)Actor->GetProperty()->GetColorWindow());
annotation->SetText(5, buff); annotation->SetText(5, buff);
} }
void ResliceImageViewer::EndRotateCallback() {
auto camera = Renderer->GetActiveCamera();
cursor1->SetProjectDirectionVector(camera->GetDirectionOfProjection());
cursor2->SetProjectDirectionVector(camera->GetDirectionOfProjection());
cursor1->UpdateCursor3DPoint(this->Renderer);
cursor2->UpdateCursor3DPoint(this->Renderer);
this->InvokeEvent(vtkCommand::RotateEvent);
}
void ResliceImageViewer::ChangeCursorVector(double * vector1, double * vector2) {
auto camera = Renderer->GetActiveCamera();
cursor1->SetProjectDirectionVector(camera->GetDirectionOfProjection());
cursor2->SetProjectDirectionVector(camera->GetDirectionOfProjection());
cursor1->SetSliceDirectionVector(vector1);
cursor2->SetSliceDirectionVector(vector2);
}
double* ResliceImageViewer::GetSliceNormal() {
return Renderer->GetActiveCamera()->GetDirectionOfProjection();
}

View File

@@ -61,6 +61,10 @@ public:
void ChangeSliceNormal(double * normal); void ChangeSliceNormal(double * normal);
void ChangeCursorVector(double * vector1, double * vector2);
double* GetSliceNormal();
void EndDrag(); void EndDrag();
void UpdateSliceCursor(); void UpdateSliceCursor();
@@ -77,6 +81,8 @@ public:
void EndWindowLevelCallback(); void EndWindowLevelCallback();
void EndRotateCallback();
void GetWindowLevel(double* windowLeveL); void GetWindowLevel(double* windowLeveL);
void SetWindowLevel(double* windowLeveL); void SetWindowLevel(double* windowLeveL);

View File

@@ -50,6 +50,9 @@ void ResliceImageManager::InitEvents() {
viewerA->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); viewerA->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback);
viewerS->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); viewerS->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback);
viewerC->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); viewerC->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback);
viewerA->AddObserver(vtkCommand::RotateEvent,this,&ResliceImageManager::RotateCallback);
viewerS->AddObserver(vtkCommand::RotateEvent,this,&ResliceImageManager::RotateCallback);
viewerC->AddObserver(vtkCommand::RotateEvent,this,&ResliceImageManager::RotateCallback);
} }
void ResliceImageManager::RollCallback(vtkObject *sender, unsigned long eventID, void *data) { void ResliceImageManager::RollCallback(vtkObject *sender, unsigned long eventID, void *data) {
@@ -143,3 +146,33 @@ void ResliceImageManager::WindowLevelCallback(vtkObject *sender, unsigned long e
} }
} }
void ResliceImageManager::RotateCallback(vtkObject *sender, unsigned long eventID, void *data) {
auto viewer = ResliceImageViewer::SafeDownCast(sender);
if (viewer){
if (viewer==viewerA){
viewerC->ChangeSliceNormal(viewer->GetCursorSliceDirection2());
viewerC->ChangeCursorVector(viewer->GetCursorSliceDirection1(),viewer->GetSliceNormal());
viewerC->Render();
viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection1());
viewerS->ChangeCursorVector(viewer->GetSliceNormal(),viewer->GetCursorSliceDirection2());
viewerS->Render();
}
if (viewer==viewerC){
viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection2());
viewerA->ChangeCursorVector(viewer->GetCursorSliceDirection1(),viewer->GetSliceNormal());
viewerA->Render();
viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection1());
viewerS->ChangeCursorVector(viewer->GetSliceNormal(),viewer->GetCursorSliceDirection2());
viewerS->Render();
}
if (viewer==viewerS){
viewerC->ChangeSliceNormal(viewer->GetCursorSliceDirection2());
viewerC->ChangeCursorVector(viewer->GetCursorSliceDirection1(),viewer->GetSliceNormal());
viewerC->Render();
viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection1());
viewerA->ChangeCursorVector(viewer->GetSliceNormal(),viewer->GetCursorSliceDirection2());
viewerA->Render();
}
}
}

View File

@@ -32,6 +32,7 @@ private:
void MoveCallback(vtkObject* sender, unsigned long eventID, void* data); void MoveCallback(vtkObject* sender, unsigned long eventID, void* data);
void ClickCallback(vtkObject* sender, unsigned long eventID, void* data); void ClickCallback(vtkObject* sender, unsigned long eventID, void* data);
void WindowLevelCallback(vtkObject* sender, unsigned long eventID, void* data); void WindowLevelCallback(vtkObject* sender, unsigned long eventID, void* data);
void RotateCallback(vtkObject* sender, unsigned long eventID, void* data);
// void SliceCallback(vtkObject* sender, unsigned long eventID, void* data); // void SliceCallback(vtkObject* sender, unsigned long eventID, void* data);
void EndDrag(vtkObject* sender, unsigned long eventID, void* data); void EndDrag(vtkObject* sender, unsigned long eventID, void* data);
}; };