Reslice hair cross rolling done.

This commit is contained in:
Krad
2022-12-29 09:55:22 +08:00
parent 2120dd2432
commit 5d51716405
9 changed files with 239 additions and 32 deletions

View File

@@ -29,7 +29,7 @@ ResliceImageInteractorStyle::~ResliceImageInteractorStyle() {
void ResliceImageInteractorStyle::OnMouseMove() {
switch (this->State) {
case VTKIS_NONE:
case VTKIS_NONE:{
if (triggerEvent)
{
this->InvokeEvent(vtkCommand::UserEvent+20,Interactor->GetEventPosition());
@@ -37,6 +37,7 @@ void ResliceImageInteractorStyle::OnMouseMove() {
}
NoneStatePick();
break;
}
case VTKIS_POSITION_PROP: {
this->Interactor->Render();
auto cursor = ResliceCursorLegendActor::SafeDownCast(this->CurrentProp);
@@ -44,8 +45,6 @@ void ResliceImageInteractorStyle::OnMouseMove() {
}
default:
vtkInteractorStyleImage::OnMouseMove();
}
}

View File

@@ -136,10 +136,10 @@ void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) {
renderer->DisplayToWorld();
renderer->GetWorldPoint(HandlePoint);
HandleUpdated = false;
ControlPoint->SetPosition(Handle2DPoint[0] - 0.5, Handle2DPoint[1] - .5);
ControlPointSenseArea->SetPosition(Handle2DPoint[0], Handle2DPoint[1] - .5);
return;
}
ControlPoint->SetPosition(Handle2DPoint[0] - 0.5, Handle2DPoint[1] - .5);
ControlPointSenseArea->SetPosition(Handle2DPoint[0], Handle2DPoint[1] - .5);
//cross hair
double vector[3] = {.0, .0, .0};
vtkMath::Cross(GetSliceDirectionVector(), GetProjectDirectionVector(), vector);
@@ -180,7 +180,10 @@ void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) {
for (int i = 0; i < 2; ++i) {
// line point loop
for (const auto &pt : pts) {
if (pointIdx >= 2)return;
if (pointIdx >= 2){
LoadTime.Modified();
return;
}
if (IntersectLine2D(p0, v1, pt, screenVectors[i], intersectPoint)) {
int pcV = (int) intersectPoint.getValue(i);
if (pcV >= -1 && pcV <= size[i] + 1) {
@@ -291,7 +294,7 @@ void ResliceCursorLegendActor::ApplyRoll(vtkRenderer * renderer) {
ReferenceCursor->SetSliceDirectionVector(newVector);
}
vtkMath::Cross(newVector, GetProjectDirectionVector(), newVector);
SetSliceDirectionVector(newVector);
this->SetSliceDirectionVector(newVector);
}
void ResliceCursorLegendActor::ApplyMove(vtkRenderer * renderer) {
@@ -315,7 +318,7 @@ void ResliceCursorLegendActor::ApplyMove(vtkRenderer * renderer) {
double intersectPoint[4]={.0,.0,.0,1.};
if (vtkPlane::IntersectWithLine(pt1, pt2, ProjectDirectionVector, SlicePoint,x,intersectPoint))
{
SetSlicePoint(intersectPoint);
this->SetSlicePoint(intersectPoint);
if (ReferenceCursor){
ReferenceCursor->SetSlicePoint(intersectPoint);
}
@@ -335,9 +338,9 @@ void ResliceCursorLegendActor::InvokeDragEvent() {
}
void ResliceCursorLegendActor::UpdateCursor3DPoint(vtkRenderer * renderer) {
double pt1[3] = {.0, .0, .0};
double pt1[4] = {.0, .0, .0,.0};
linePolyData->GetPoints()->GetPoint(0, pt1);
double pt2[3] = {.0, .0, .0};
double pt2[4] = {.0, .0, .0, .0};
linePolyData->GetPoints()->GetPoint(1, pt2);
double worldPt1[4] = {.0,.0,.0,1.};
double worldPt2[4] = {.0,.0,.0,1.};
@@ -358,7 +361,6 @@ void ResliceCursorLegendActor::UpdateCursor3DPoint(vtkRenderer * renderer) {
1.0};
double newPt1[4] = {.0,.0,.0,1.};
int ret = plane->IntersectWithLine(worldPt1,wpt_end,t,newPt1);
if (ret == 0 ) vtkErrorMacro("no intersect!");
double wpt_end2[4] = {worldPt2[0] + 10000.0 * ProjectDirectionVector[0],
worldPt2[1] + 10000.0 * ProjectDirectionVector[1],
@@ -366,9 +368,8 @@ void ResliceCursorLegendActor::UpdateCursor3DPoint(vtkRenderer * renderer) {
1.0};
double newPt2[4] = {.0,.0,.0,1.};
ret = plane->IntersectWithLine(worldPt2,wpt_end2,t,newPt2);
if (ret == 0 ) vtkErrorMacro("no intersect!");
double vector[3] = {newPt2[0]-newPt1[0],newPt2[1]-newPt1[1],newPt2[2]-newPt1[2]};
double vector[3] = {worldPt2[0]-worldPt1[0],worldPt2[1]-worldPt1[1],worldPt2[2]-worldPt1[2]};
vtkMath::Cross(vector, GetProjectDirectionVector(), vector);
SetSliceDirectionVector(vector);
this->SetSliceDirectionVector(vector);
}

View File

@@ -0,0 +1,75 @@
//
// Created by Krad on 2022/12/28.
//
#include "ResliceSquareLegendActor.h"
#include <vtkObjectFactory.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper2D.h>
#include <vtkActor2D.h>
#include <vtkProperty2D.h>
#include <vtkPolyData.h>
#include <vtkPolygon.h>
#include <vtkPoints.h>
#include <vtkRenderer.h>
vtkStandardNewMacro(ResliceSquareLegendActor)
void ResliceSquareLegendActor::BuildShape(vtkRenderer *renderer) {
int* sizes = renderer->GetSize();
Square->SetDisplayPosition(sizes[0]-20,sizes[1]-20);
}
void ResliceSquareLegendActor::ReleaseGraphicsResources(vtkWindow * window) {
Square->ReleaseGraphicsResources(window);
}
int ResliceSquareLegendActor::RenderOverlay(vtkViewport *viewport) {
auto renderer = vtkRenderer::SafeDownCast(viewport);
if (renderer){
BuildShape(renderer);
return Square->RenderOverlay(viewport);
}
return 0;
}
ResliceSquareLegendActor::ResliceSquareLegendActor() {
this->PickableOff();
Square = vtkActor2D::New();
Square->Register(this);
Square->Delete();
vtkNew<vtkPolyDataMapper2D> mapper;
vtkNew<vtkPolyData> polydata;
vtkNew<vtkPoints> pts;
pts->SetNumberOfPoints(4);
pts->SetPoint(0,0,0,0);
pts->SetPoint(1,18,0,0);
pts->SetPoint(2,18,18,0);
pts->SetPoint(3,0,18,0);
polydata->SetPoints(pts);
vtkNew<vtkPolygon> polygon;
polygon->GetPointIds()->SetNumberOfIds(4);
polygon->GetPointIds()->SetId(0,0);
polygon->GetPointIds()->SetId(1,1);
polygon->GetPointIds()->SetId(2,2);
polygon->GetPointIds()->SetId(3,3);
vtkNew<vtkCellArray> cells;
cells->InsertNextCell(polygon);
polydata->SetPolys(cells);
mapper->SetInputData(polydata);
Square->SetMapper(mapper);
Square->GetProperty()->SetLineWidth(0);
Square->GetProperty()->SetPointSize(0);
}
ResliceSquareLegendActor::~ResliceSquareLegendActor() {
}
vtkProperty2D *ResliceSquareLegendActor::GetProperty() {
return Square->GetProperty();
}

View File

@@ -0,0 +1,70 @@
//
// Created by Krad on 2022/12/28.
//
#ifndef OMEGAV_RESLICESQUARELEGENDACTOR_H
#define OMEGAV_RESLICESQUARELEGENDACTOR_H
#include <vtkProp.h>
class vtkRenderer;
class vtkActor2D;
class vtkProperty2D;
class ResliceSquareLegendActor : public vtkProp {
public:
//@{
/**
* Standard methods for instances of this class.
*/
static ResliceSquareLegendActor *New();
vtkTypeMacro(ResliceSquareLegendActor, vtkProp);
virtual void BuildShape(vtkRenderer *renderer);
//@{
/**
* Methods to make this class behave as a vtkProp.
*/
double *GetBounds() VTK_SIZEHINT(6) override { return nullptr; }
void GetActors(vtkPropCollection *) override {}
void GetVolumes(vtkPropCollection *) override {}
void ShallowCopy(vtkProp *prop) override {};
void ReleaseGraphicsResources(vtkWindow *) override;
/**
* Method use to make this actor render in 2D scene;
* @param viewport
* @return render is success
*/
int RenderOverlay(vtkViewport *viewport) override;
int RenderOpaqueGeometry(vtkViewport *vtkNotUsed(viewport)) override { return 0; }
int RenderTranslucentPolygonalGeometry(vtkViewport *vtkNotUsed(viewport)) override { return 0; }
int RenderVolumetricGeometry(vtkViewport *vtkNotUsed(viewport)) override { return 0; }
vtkTypeBool HasTranslucentPolygonalGeometry() override { return 0; }
vtkProperty2D* GetProperty();
protected:
ResliceSquareLegendActor();
~ResliceSquareLegendActor() override;
private:
ResliceSquareLegendActor(const ResliceSquareLegendActor &) = delete;
void operator=(const ResliceSquareLegendActor &) = delete;
vtkActor2D * Square;
};
#endif //OMEGAV_RESLICESQUARELEGENDACTOR_H

View File

@@ -17,6 +17,7 @@
#include <vtkProperty2D.h>
#include "Rendering/Legend/ResliceCursorLegendActor.h"
#include "Rendering/Legend/ResliceSquareLegendActor.h"
#include "Interaction/ResliceImageInteractorStyle.h"
vtkStandardNewMacro(ResliceImageViewer);
@@ -30,6 +31,7 @@ ResliceImageViewer::ResliceImageViewer()
, Mapper(vtkImageResliceMapper::New())
, cursor1(ResliceCursorLegendActor::New())
, cursor2(ResliceCursorLegendActor::New())
, Square(ResliceSquareLegendActor::New())
, Actor(vtkImageSlice::New())
, OrientationMatrix(vtkMatrix4x4::New())
, DefaultOrientation(0)
@@ -141,6 +143,7 @@ void ResliceImageViewer::SetInputData(vtkImageData *in) {
void ResliceImageViewer::Render() {
if (RenderWindow && Interactor){
if (FirstRender){
//some first render logic
FirstRender = false;
Renderer->AddActor2D(cursor1);
Renderer->AddActor2D(cursor2);
@@ -156,6 +159,7 @@ void ResliceImageViewer::Render() {
cursor1->GetProperty()->SetColor(0,0,1);
sliceDirection2[1] = 1.0;
cursor2->GetProperty()->SetColor(0,1,0);
Square->GetProperty()->SetColor(1,0,0);
break;
}
case 1:{
@@ -163,6 +167,8 @@ void ResliceImageViewer::Render() {
cursor1->GetProperty()->SetColor(1,0,0);
sliceDirection2[2] = 1.0;
cursor2->GetProperty()->SetColor(0,0,1);
Square->GetProperty()->SetColor(0,1,0);
break;
}
case 2:{
@@ -170,6 +176,7 @@ void ResliceImageViewer::Render() {
cursor1->GetProperty()->SetColor(1,0,0);
sliceDirection2[1] = 1.0;
cursor2->GetProperty()->SetColor(0,1,0);
Square->GetProperty()->SetColor(0,0,1);
break;
}
}
@@ -178,12 +185,14 @@ void ResliceImageViewer::Render() {
cursor1->SetSliceDirectionVector(sliceDirection1);
cursor2->SetSliceDirectionVector(sliceDirection2);
this->InteractorStyle->AddObserver(vtkCommand::UserEvent+20,this,&ResliceImageViewer::updateHandle);
this->InteractorStyle->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageViewer::updateSliceCursor);
this->InteractorStyle->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageViewer::EndDrag);
this->RenderWindow->AddObserver(vtkCommand::WindowResizeEvent,this,&ResliceImageViewer::handleResize);
cursor1->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll);
cursor1->AddObserver(ResliceCursorLegendActor::MOVE,this, &ResliceImageViewer::handleMove);
cursor2->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll);
cursor2->AddObserver(ResliceCursorLegendActor::MOVE,this, &ResliceImageViewer::handleMove);
//some first render logic
Renderer->AddActor2D(Square);
Render();
return;
}
@@ -260,7 +269,13 @@ void ResliceImageViewer::ChangeSliceNormal(double *normal) {
double focalPt[3] = {.0, .0, .0};
camera->GetFocalPoint(focalPt);
vtkMath::Normalize(normal);
camera->SetPosition(focalPt[0]+30.0*normal[0],focalPt[1]+30.0*normal[1],focalPt[2]+30.0*normal[2]);
double proj [3]={.0 ,.0 ,.0};
camera->GetDirectionOfProjection(proj);
double a = proj[0] * normal[0] + proj[1]* normal[1] + proj[2] * normal[2];
double step = 30.0;
if (a>0)step = step*-1.0;
// vtkErrorMacro("proj:"<<proj[0]<<","<<proj[1]<<","<<proj[2]<<"; normal:"<<normal[0]<<", "<<normal[1]<<", "<<normal[2]);
camera->SetPosition(focalPt[0]+step*normal[0],focalPt[1]+step*normal[1],focalPt[2]+step*normal[2]);
camera->OrthogonalizeViewUp();
Renderer->ResetCameraClippingRange();
}
@@ -269,7 +284,19 @@ void ResliceImageViewer::ChangeSlicePoint(double *point) {
}
void ResliceImageViewer::updateSliceCursor() {
void ResliceImageViewer::UpdateSliceCursor() {
cursor1->SetProjectDirectionVector(Renderer->GetActiveCamera()->GetDirectionOfProjection());
cursor1->UpdateCursor3DPoint(Renderer);
cursor2->SetProjectDirectionVector(Renderer->GetActiveCamera()->GetDirectionOfProjection());
cursor2->UpdateCursor3DPoint(Renderer);
Renderer->Render();
}
void ResliceImageViewer::EndDrag() {
this->InvokeEvent(ResliceCursorLegendActor::END_DRAG);
}
void ResliceImageViewer::handleResize() {
cursor1->Modified();
cursor2->Modified();
}

View File

@@ -25,6 +25,8 @@ class vtkMatrix4x4;
class ResliceCursorLegendActor;
class ResliceSquareLegendActor;
class ResliceImageViewer :public vtkObject {
public:
static ResliceImageViewer *New();
@@ -47,6 +49,9 @@ public:
void ChangeSlicePoint(double * point);
void ChangeSliceNormal(double * normal);
void EndDrag();
void UpdateSliceCursor();
protected:
ResliceImageViewer();
@@ -57,13 +62,13 @@ protected:
virtual void UnInstallPipeline();
void updateHandle(vtkObject* sender, unsigned long eventID, void* callData);
void updateSliceCursor();
private:
ResliceImageViewer(const ResliceImageViewer &) = delete;
void operator=(const ResliceImageViewer &) = delete;
void handleRoll();
void handleMove();
void handleResize();
vtkRenderWindow *RenderWindow;
vtkRenderer *Renderer;
@@ -73,6 +78,7 @@ private:
vtkImageResliceMapper* Mapper;
ResliceCursorLegendActor* cursor1;
ResliceCursorLegendActor* cursor2;
ResliceSquareLegendActor* Square;
vtkImageSlice* Actor;
vtkMatrix4x4* OrientationMatrix;
int DefaultOrientation;

View File

@@ -7,6 +7,7 @@
#include <vtkCommand.h>
#include "Rendering/Viewer/ResliceImageViewer.h"
#include "Rendering/Legend/ResliceCursorLegendActor.h"
ResliceImageManager::ResliceImageManager(QObject *parent) : QObject(parent) {
@@ -30,26 +31,53 @@ void ResliceImageManager::SetViewer(int index, ResliceImageViewer *viewer) {
}
void ResliceImageManager::InitEvents() {
viewerA->AddObserver(vtkCommand::UserEvent+1000,this,&ResliceImageManager::RollCallback);
viewerS->AddObserver(vtkCommand::UserEvent+1000,this,&ResliceImageManager::RollCallback);
viewerC->AddObserver(vtkCommand::UserEvent+1000,this,&ResliceImageManager::RollCallback);
viewerA->AddObserver(ResliceCursorLegendActor::ROLL,this,&ResliceImageManager::RollCallback);
viewerS->AddObserver(ResliceCursorLegendActor::ROLL,this,&ResliceImageManager::RollCallback);
viewerC->AddObserver(ResliceCursorLegendActor::ROLL,this,&ResliceImageManager::RollCallback);
viewerA->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageManager::EndDrag);
viewerS->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageManager::EndDrag);
viewerC->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageManager::EndDrag);
}
void ResliceImageManager::RollCallback(vtkObject *sender, unsigned long eventID, void *data) {
auto viewer = ResliceImageViewer::SafeDownCast(sender);
if (viewer){
if (viewer!=viewerA){
viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection1());
viewerA->Render();
}
if (viewer!=viewerC){
if (viewer==viewerA){
viewerC->ChangeSliceNormal(viewer->GetCursorSliceDirection1());
viewerC->Render();
}
if (viewer!=viewerS){
viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection1());
viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection2());
viewerS->Render();
}
if (viewer==viewerC){
viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection1());
viewerA->Render();
viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection2());
viewerS->Render();
}
if (viewer==viewerS){
viewerC->ChangeSliceNormal(viewer->GetCursorSliceDirection2());
viewerC->Render();
viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection1());
viewerA->Render();
}
}
}
void ResliceImageManager::EndDrag(vtkObject *sender, unsigned long eventID, void *data) {
auto viewer = ResliceImageViewer::SafeDownCast(sender);
if (viewer){
if (viewer!=viewerA){
viewerA->UpdateSliceCursor();
viewerA->Render();
}
if (viewer!=viewerC){
viewerC->UpdateSliceCursor();
viewerC->Render();
}
if (viewer!=viewerS){
viewerS->UpdateSliceCursor();
viewerS->Render();
}
}
}

View File

@@ -28,6 +28,7 @@ private:
ResliceImageViewer * viewerC;
void RollCallback(vtkObject* sender, unsigned long eventID, void* data);
void EndDrag(vtkObject* sender, unsigned long eventID, void* data);
};

View File

@@ -8,7 +8,6 @@
#include <QVBoxLayout>
#include <QGuiApplication.h>
#include <QVTKOpenGLNativeWidget.h>
#include <QGridLayout>
#include <QMenuBar>
#include <QSplitter>
@@ -69,6 +68,7 @@ MPRResliceWindow::MPRResliceWindow(QWidget *parent, Qt::WindowFlags f) : QDialog
manager->SetViewer(1,mViewerC);
manager->SetViewer(2,mViewerS);
manager->InitEvents();
}
MPRResliceWindow::~MPRResliceWindow() {