feat: add syncpoint function
This commit is contained in:
@@ -19,7 +19,7 @@ include_directories(
|
||||
)
|
||||
|
||||
#set(VTK_DIR "D:/Libs/binary/VTK8.1.2/lib/cmake/vtk-8.2")
|
||||
set(VTK_DIR "D:/Libs/binary/VTK9.2.2/lib/cmake/vtk-9.2")
|
||||
set(VTK_DIR "D:/Libs/binary/VTK9.2.2win11/lib/cmake/vtk-9.2")
|
||||
set(Qt5_DIR "D:/Qt/Qt5.12.0/5.12.0/msvc2017_64/lib/cmake/Qt5")
|
||||
set(DCMTK_DIR "D:/Libs/binary/DCMTK/cmake")
|
||||
|
||||
|
||||
BIN
src/Icon/crosshair.png
Normal file
BIN
src/Icon/crosshair.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
@@ -58,6 +58,7 @@
|
||||
<file>Icon/Settings.png</file>
|
||||
<file>Icon/preset.png</file>
|
||||
<file>Icon/diameter.png</file>
|
||||
<file>Icon/crosshair.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/pqWidgets">
|
||||
<file>Icon/pq/pqBold24.png</file>
|
||||
|
||||
@@ -83,6 +83,7 @@ enum AnnotationActorType
|
||||
EllipseAnn,
|
||||
DiameterAnn,
|
||||
TextAnn,
|
||||
SyncPoint
|
||||
};
|
||||
enum AnnotationDeleteType{
|
||||
DeleteSelectedAnn,
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
#include <vtkObjectFactory.h>
|
||||
#include <vtkCollection.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkRenderWindowInteractor.h>
|
||||
|
||||
#include <vtkImageSlice.h>
|
||||
#include <vtkImageMapper3D.h>
|
||||
#include <vtkImageData.h>
|
||||
@@ -16,8 +18,11 @@
|
||||
#include <vtkCallbackCommand.h>
|
||||
#include <vtkImageProperty.h>
|
||||
#include <vtkPointData.h>
|
||||
#include <vtkBoundingBox.h>
|
||||
|
||||
|
||||
#include "Rendering/Core/DraggableActor.h"
|
||||
#include "Rendering/Measure/CrossCursorAnnotationActor.h"
|
||||
#include "Common/QGlobals.h"
|
||||
|
||||
vtkStandardNewMacro(ActorDraggableInteractorStyle)
|
||||
@@ -126,6 +131,9 @@ void ActorDraggableInteractorStyle::OnLeftButtonDown() {
|
||||
} else if (this->InteractionMode == VTKIS_IMAGE_SLICING) {
|
||||
this->StartSlice();
|
||||
}
|
||||
else if(this->InteractionMode == VTKIS_SYNCPOINT){
|
||||
this->StartSyncSlicePoint();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -175,6 +183,9 @@ void ActorDraggableInteractorStyle::OnLeftButtonUp() {
|
||||
case VTKIS_COLORMAP:
|
||||
this->EndColorMapping();
|
||||
break;
|
||||
case VTKIS_SYNCPOINT:
|
||||
this->EndSyncSlicePoint();
|
||||
break;
|
||||
}
|
||||
vtkInteractorStyleImage::OnLeftButtonUp();
|
||||
}
|
||||
@@ -219,6 +230,10 @@ void ActorDraggableInteractorStyle::OnMouseMove() {
|
||||
this->ColorMapping();
|
||||
this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
|
||||
break;
|
||||
case VTKIS_SYNCPOINT:
|
||||
this->SyncSlicePoint();
|
||||
this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
|
||||
break;
|
||||
|
||||
}
|
||||
vtkInteractorStyleImage::OnMouseMove();
|
||||
@@ -368,6 +383,74 @@ void ActorDraggableInteractorStyle::Slice() {
|
||||
this->InvokeEvent(SliceEvent, p);
|
||||
}
|
||||
|
||||
void ActorDraggableInteractorStyle::StartSyncSlicePoint()
|
||||
{
|
||||
this->StartState(VTKIS_SYNCPOINT);
|
||||
vtkNew<CrossCursorAnnotationActor> cross;
|
||||
|
||||
int *pos = this->Interactor->GetEventPosition();
|
||||
this->FindPokedRenderer(pos[0], pos[1]);
|
||||
this->CurrentRenderer->SetDisplayPoint(pos[0], pos[1], 0.0);
|
||||
this->CurrentRenderer->DisplayToWorld();
|
||||
cross->SetRenderer(this->CurrentRenderer);
|
||||
cross->Transform(pos[0] , pos[1] );
|
||||
dragProp = cross;
|
||||
this->InvokeEvent(StartSyncSlicePointEvent,nullptr);
|
||||
SyncSlicePoint();
|
||||
this->Interactor->Render();
|
||||
}
|
||||
|
||||
void ActorDraggableInteractorStyle::EndSyncSlicePoint()
|
||||
{
|
||||
if (this->State != VTKIS_SYNCPOINT) {
|
||||
return;
|
||||
}
|
||||
this->StopState();
|
||||
DraggableActor::SafeDownCast(dragProp)->SetRenderer(nullptr);
|
||||
// dragProp->Delete();
|
||||
dragProp = nullptr;
|
||||
this->InvokeEvent(EndSyncSlicePointEvent,nullptr);
|
||||
this->Interactor->Render();
|
||||
}
|
||||
|
||||
void ActorDraggableInteractorStyle::SyncSlicePoint()
|
||||
{
|
||||
int *pos = this->Interactor->GetEventPosition();
|
||||
this->FindPokedRenderer(pos[0], pos[1]);
|
||||
CrossCursorAnnotationActor::SafeDownCast(dragProp)->Transform(pos[0] , pos[1] );
|
||||
this->Interactor->Render();
|
||||
this->InvokeEvent(SyncSlicePointEvent,CrossCursorAnnotationActor::SafeDownCast(dragProp)->GetWorldSlicePoint());
|
||||
}
|
||||
|
||||
void ActorDraggableInteractorStyle::AdjustSyncCrossPoint(double* aPoint)
|
||||
{
|
||||
if(dragProp == nullptr)
|
||||
{
|
||||
if (CurrentRenderer == nullptr) return;
|
||||
if (aPoint == nullptr) return;
|
||||
if (CurrentImageSlice == nullptr) return;
|
||||
// if (box.ContainsPoint(aPoint))
|
||||
{
|
||||
vtkNew<CrossCursorAnnotationActor> cross;
|
||||
cross->SetRenderer(this->CurrentRenderer);
|
||||
cross->Transform(aPoint[0] , aPoint[1] );
|
||||
dragProp = cross;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (aPoint == nullptr)
|
||||
{
|
||||
DraggableActor::SafeDownCast(dragProp)->SetRenderer(nullptr);
|
||||
// dragProp->Delete();
|
||||
dragProp = nullptr;
|
||||
}
|
||||
else{
|
||||
CrossCursorAnnotationActor::SafeDownCast(dragProp)->Transform(aPoint[0] , aPoint[1] );
|
||||
this->Interactor->Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActorDraggableInteractorStyle::StartPan() {
|
||||
vtkInteractorStyle::StartPan();
|
||||
vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
|
||||
|
||||
@@ -115,6 +115,7 @@ vtkTypeMacro(ActorDraggableInteractorStyle, vtkInteractorStyleImage);
|
||||
{
|
||||
return CurrentImageSlice;
|
||||
}
|
||||
void AdjustSyncCrossPoint(double* aPoint);
|
||||
|
||||
|
||||
protected:
|
||||
@@ -170,6 +171,12 @@ protected:
|
||||
|
||||
void NoneStatePick();
|
||||
|
||||
void StartSyncSlicePoint();
|
||||
|
||||
void EndSyncSlicePoint() ;
|
||||
|
||||
void SyncSlicePoint();
|
||||
|
||||
void DispatchEvent();
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define VTKIS_DRAG 33
|
||||
#define VTKIS_MEASURE 36
|
||||
#define VTKIS_COLORMAP 37
|
||||
#define VTKIS_SYNCPOINT 38
|
||||
#define VTKIS_IMAGE_PAN 5
|
||||
#define VTKIS_IMAGE_ZOOM 6
|
||||
#define VTKIS_IMAGE_WINDOWLEVEL 7
|
||||
@@ -34,7 +35,10 @@ enum DraggableStyleEvents {
|
||||
RightButtonClickEvent,
|
||||
ScalarOpacityEvent,
|
||||
ScalarShiftEvent,
|
||||
AfterViewerClicked
|
||||
AfterViewerClicked,
|
||||
StartSyncSlicePointEvent,
|
||||
SyncSlicePointEvent,
|
||||
EndSyncSlicePointEvent
|
||||
};
|
||||
|
||||
|
||||
|
||||
72
src/src/Rendering/Measure/CrossCursorAnnotationActor.cpp
Normal file
72
src/src/Rendering/Measure/CrossCursorAnnotationActor.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "CrossCursorAnnotationActor.h"
|
||||
|
||||
#include "Rendering/Source/vtkCrossCursorSource.h"
|
||||
#include <vtkObjectFactory.h>
|
||||
#include <vtkRenderer.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkRenderWindowInteractor.h>
|
||||
#include <vtkActor2D.h>
|
||||
#include <vtkProperty2D.h>
|
||||
|
||||
|
||||
vtkStandardNewMacro(CrossCursorAnnotationActor)
|
||||
|
||||
CrossCursorAnnotationActor::CrossCursorAnnotationActor()
|
||||
: DraggableActor(){
|
||||
BaseDataPoints->SetNumberOfPoints(1);
|
||||
BaseDataPoints->SetPoint(0, 0, 0, 0);
|
||||
|
||||
renderPoints->SetNumberOfPoints(1);
|
||||
renderPoints->SetPoint(0, 0, 0, 0);
|
||||
|
||||
this->AddObserver(DraggableActorEvents::DragEvent, this, &CrossCursorAnnotationActor::selfDragCb);
|
||||
this->actor2D->GetProperty()->SetLineWidth(1.0);
|
||||
this->shadow2D->GetProperty()->SetLineWidth(2);
|
||||
this->shadow2D->SetVisibility(1);
|
||||
|
||||
}
|
||||
|
||||
CrossCursorAnnotationActor::~CrossCursorAnnotationActor() {
|
||||
|
||||
}
|
||||
|
||||
void CrossCursorAnnotationActor::SetWorldPosition1(double x, double y, double z) {
|
||||
BaseDataPoints->SetPoint(0, x, y, z);
|
||||
}
|
||||
|
||||
void CrossCursorAnnotationActor::BuildShape() {
|
||||
if (!BaseDataPoints->GetNumberOfPoints()) return;
|
||||
// RebuildRenderPoint();
|
||||
vtkNew<vtkCrossCursorSource> source;
|
||||
source->SetPoints(renderPoints);
|
||||
source->Update();
|
||||
renderData->DeepCopy(source->GetOutput());
|
||||
}
|
||||
|
||||
void CrossCursorAnnotationActor::SetRenderer(vtkRenderer *ren) {
|
||||
DraggableActor::SetRenderer(ren);
|
||||
}
|
||||
|
||||
void CrossCursorAnnotationActor::selfDragCb(vtkObject *, unsigned long, void *data) {
|
||||
vtkPoints *pts = static_cast<vtkPoints *>(data);
|
||||
double *pos = pts->GetPoint(0);
|
||||
|
||||
}
|
||||
|
||||
void CrossCursorAnnotationActor::onMeasureMouseMove(vtkRenderWindowInteractor *iren) {
|
||||
}
|
||||
|
||||
void CrossCursorAnnotationActor::Transform(float x, float y)
|
||||
{
|
||||
this->actor2D->SetDisplayPosition(x,y);
|
||||
MapScreenPointToWorld(x,y, this->Renderer, WorldSlicePoint);
|
||||
}
|
||||
|
||||
bool CrossCursorAnnotationActor::onMeasureLeftButtonDown(vtkRenderWindowInteractor *iren)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CrossCursorAnnotationActor::onMeasureLeftButtonUp(vtkRenderWindowInteractor *iren) {
|
||||
return false;
|
||||
}
|
||||
60
src/src/Rendering/Measure/CrossCursorAnnotationActor.h
Normal file
60
src/src/Rendering/Measure/CrossCursorAnnotationActor.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef OMEGAV_CROSSCURSORANNOTATIONACTOR_H
|
||||
|
||||
#define OMEGAV_CROSSCURSORANNOTATIONACTOR_H
|
||||
|
||||
|
||||
#include "Rendering/Core/DraggableActor.h"
|
||||
#include "Rendering/Measure/Measure.h"
|
||||
|
||||
|
||||
class CrossCursorAnnotationActor : public DraggableActor, public Measure {
|
||||
public:
|
||||
//@{
|
||||
/**
|
||||
* Standard methods for instances of this class.
|
||||
*/
|
||||
static CrossCursorAnnotationActor *New();
|
||||
|
||||
vtkTypeMacro(CrossCursorAnnotationActor, DraggableActor);
|
||||
|
||||
//@}
|
||||
void SetRenderer(vtkRenderer *ren) override;
|
||||
|
||||
void BuildShape() override;
|
||||
|
||||
void SetWorldPosition1(double x, double y, double z);
|
||||
|
||||
void SetWorldPosition1(double *pos) {
|
||||
SetWorldPosition1(pos[0], pos[1], pos[2]);
|
||||
}
|
||||
|
||||
void Transform(float x, float y) override;
|
||||
bool onMeasureLeftButtonDown(vtkRenderWindowInteractor *) override;
|
||||
|
||||
void onMeasureMouseMove(vtkRenderWindowInteractor *) override;
|
||||
|
||||
bool onMeasureLeftButtonUp(vtkRenderWindowInteractor *) override;
|
||||
|
||||
// NextMeasureMacro(LineAnnotationActor);
|
||||
|
||||
void ForceDelete() override {
|
||||
this->SetRenderer(nullptr);
|
||||
DraggableActor::Delete();
|
||||
}
|
||||
|
||||
vtkGetVector3Macro(WorldSlicePoint,vtkTypeFloat64);
|
||||
|
||||
protected:
|
||||
CrossCursorAnnotationActor();
|
||||
|
||||
|
||||
~CrossCursorAnnotationActor() override;
|
||||
|
||||
void selfDragCb(vtkObject *, unsigned long event, void *data);
|
||||
|
||||
double WorldSlicePoint[3] = {.0,.0,.0};
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //OMEGAV_CROSSCURSORANNOTATIONACTOR_H
|
||||
@@ -281,8 +281,8 @@ void EllipseAnnotationActor::drawCircle(double *p1, double *p2) {
|
||||
nIndex[0] = 1;
|
||||
nIndex[1] = 2;
|
||||
}
|
||||
int CenterX = (p1[nIndex[0]] + p2[nIndex[0]] ) / 2.0;
|
||||
int CenterY = (p1[nIndex[1]] + p2[nIndex[1]] ) / 2.0;
|
||||
double CenterX = (p1[nIndex[0]] + p2[nIndex[0]] ) / 2.0;
|
||||
double CenterY = (p1[nIndex[1]] + p2[nIndex[1]] ) / 2.0;
|
||||
double r1 = round(abs(p1[nIndex[0]] - p2[nIndex[0]]) / 2.0*100.0)/100;
|
||||
double r2 = round(abs(p1[nIndex[1]]- p2[nIndex[1]]) / 2.0*100.0)/100;
|
||||
|
||||
|
||||
@@ -274,11 +274,11 @@ void RoundAnnotationActor::drawCircle(double *p1, double *p2) {
|
||||
double r2 = round(abs(p1[nIndex[1]]- p2[nIndex[1]]) / 2.0*100.0)/100;
|
||||
double r = r1<r2?r1:r2;
|
||||
|
||||
int CenterX = (p1[nIndex[0]] + p2[nIndex[0]] ) / 2.0;
|
||||
double CenterX = (p1[nIndex[0]] + p2[nIndex[0]] ) / 2.0;
|
||||
if (abs(CenterX-p2[nIndex[0]])>r){
|
||||
CenterX = CenterX > p2[nIndex[0]]?(r+p2[nIndex[0]]):(p2[nIndex[0]]-r);
|
||||
}
|
||||
int CenterY = (p1[nIndex[1]] + p2[nIndex[1]] ) / 2.0;
|
||||
double CenterY = (p1[nIndex[1]] + p2[nIndex[1]] ) / 2.0;
|
||||
if (abs(CenterY-p2[nIndex[1]])>r){
|
||||
CenterY = CenterY > p2[nIndex[1]]?(r+p2[nIndex[1]]):(p2[nIndex[1]]-r);
|
||||
}
|
||||
|
||||
60
src/src/Rendering/Source/vtkCrossCursorSource.cpp
Normal file
60
src/src/Rendering/Source/vtkCrossCursorSource.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
#include "vtkCrossCursorSource.h"
|
||||
#include "vtkInformation.h"
|
||||
#include "vtkInformationVector.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
vtkStandardNewMacro(vtkCrossCursorSource)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
vtkCrossCursorSource::vtkCrossCursorSource() {
|
||||
this->Closed = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
vtkCrossCursorSource::~vtkCrossCursorSource() {}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int vtkCrossCursorSource::RequestData(vtkInformation * vtkNotUsed(request),
|
||||
vtkInformationVector ** vtkNotUsed(inputVector), vtkInformationVector *outputVector) {
|
||||
// get the info object
|
||||
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
||||
|
||||
// get the output
|
||||
vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
||||
vtkIdType numPoints = this->GetNumberOfPoints();
|
||||
// must have a mouse point point
|
||||
if (numPoints < 1) return 1;
|
||||
vtkNew<vtkPoints> pts;
|
||||
vtkNew<vtkCellArray> lines;
|
||||
double centerPt[3] = {0.0, 0.0, 0.0};
|
||||
this->Points->GetPoint(0, centerPt);
|
||||
vtkIdType pids[2];
|
||||
// pts->InsertNextPoint(centerPt[0]-10, centerPt[1], 0);
|
||||
// pts->InsertNextPoint(centerPt[0]+10, centerPt[1], 0);
|
||||
// lines->InsertNextCell(2, pids);
|
||||
// pts->InsertNextPoint(centerPt[0], centerPt[1]-5, 0);
|
||||
// pts->InsertNextPoint(centerPt[0], centerPt[1]+5, 0);
|
||||
// lines->InsertNextCell(2, pids);
|
||||
|
||||
|
||||
pids[0] = pts->InsertNextPoint(centerPt[0] - 3, centerPt[1], 0);
|
||||
pids[1] = pts->InsertNextPoint(centerPt[0] - 20, centerPt[1], 0);
|
||||
lines->InsertNextCell(2, pids);
|
||||
pids[0] = pts->InsertNextPoint(centerPt[0] + 3, centerPt[1], 0);
|
||||
pids[1] = pts->InsertNextPoint(centerPt[0] + 20, centerPt[1], 0);
|
||||
lines->InsertNextCell(2, pids);
|
||||
pids[0] = pts->InsertNextPoint(centerPt[0], centerPt[1] - 3, 0);
|
||||
pids[1] = pts->InsertNextPoint(centerPt[0], centerPt[1] - 20, 0);
|
||||
lines->InsertNextCell(2, pids);
|
||||
pids[0] = pts->InsertNextPoint(centerPt[0], centerPt[1] + 3, 0);
|
||||
pids[1] = pts->InsertNextPoint(centerPt[0], centerPt[1] + 20, 0);
|
||||
lines->InsertNextCell(2, pids);
|
||||
output->SetPoints(pts);
|
||||
output->SetLines(lines);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void vtkCrossCursorSource::PrintSelf(ostream &os, vtkIndent indent) {
|
||||
vtkPolyLineSource::PrintSelf(os, indent);
|
||||
}
|
||||
32
src/src/Rendering/Source/vtkCrossCursorSource.h
Normal file
32
src/src/Rendering/Source/vtkCrossCursorSource.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef OMEGAV_VTKCROSSCURSORSOURCE_H
|
||||
#define OMEGAV_VTKCROSSCURSORSOURCE_H
|
||||
|
||||
|
||||
#include <vtkPolyLineSource.h>
|
||||
|
||||
class vtkCrossCursorSource : public vtkPolyLineSource {
|
||||
public:
|
||||
/**
|
||||
* Construct cone with angle of 45 degrees.
|
||||
*/
|
||||
static vtkCrossCursorSource *New();
|
||||
|
||||
vtkTypeMacro(vtkCrossCursorSource, vtkPolyDataAlgorithm);
|
||||
|
||||
void PrintSelf(ostream &os, vtkIndent indent) override;
|
||||
protected:
|
||||
vtkCrossCursorSource();
|
||||
|
||||
~vtkCrossCursorSource() override;
|
||||
|
||||
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *) override;
|
||||
|
||||
private:
|
||||
vtkCrossCursorSource(const vtkCrossCursorSource &) = delete;
|
||||
|
||||
void operator=(const vtkCrossCursorSource &) = delete;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* OMEGAV_VTKCROSSCURSORSOURCE_H */
|
||||
@@ -313,7 +313,6 @@ void DICOMImageViewer::InstallPipeline() {
|
||||
if (!this->InteractorStyle) {
|
||||
this->InteractorStyle = ActorDraggableInteractorStyle::New();
|
||||
this->InteractorStyle->SetInteractionModeToImageSlicing();
|
||||
this->InteractorStyle->SetCurrentImageNumber(0);
|
||||
this->InteractorStyle->SetCornerAnnotation(cornerAnnotation);
|
||||
|
||||
this->InteractorStyle->AddObserver(DraggableStyleEvents::EndMeasureEvent,
|
||||
@@ -333,6 +332,12 @@ void DICOMImageViewer::InstallPipeline() {
|
||||
this->InteractorStyle->AddObserver(vtkCommand::EventIds::EndWindowLevelEvent, this,
|
||||
&DICOMImageViewer::raiseEvent);
|
||||
this->InteractorStyle->AddObserver(vtkCommand::EventIds::EndPanEvent, this, &DICOMImageViewer::raiseEvent);
|
||||
|
||||
this->InteractorStyle->AddObserver(DraggableStyleEvents::StartSyncSlicePointEvent, this, &DICOMImageViewer::raiseEvent);
|
||||
this->InteractorStyle->AddObserver(DraggableStyleEvents::SyncSlicePointEvent, this, &DICOMImageViewer::raiseEvent);
|
||||
|
||||
this->InteractorStyle->AddObserver(DraggableStyleEvents::EndSyncSlicePointEvent, this, &DICOMImageViewer::raiseEvent);
|
||||
|
||||
}
|
||||
|
||||
this->Interactor->SetInteractorStyle(this->InteractorStyle);
|
||||
@@ -467,7 +472,14 @@ void DICOMImageViewer::SetSlice(int slice) {
|
||||
}
|
||||
|
||||
int lastSliceNumber = this->ImageMapper->GetSliceNumber();
|
||||
if (InteractorStyle){
|
||||
if (slice == 0){
|
||||
InteractorStyle->SetCurrentRenderer(this->Renderer);
|
||||
InteractorStyle->SetCurrentImageNumber(0);
|
||||
}
|
||||
}
|
||||
if (lastSliceNumber == slice) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -496,10 +508,6 @@ void DICOMImageViewer::SetSlice(int slice) {
|
||||
// this->Render();
|
||||
UpdateTopLeftCornerInfo();
|
||||
if (InteractorStyle){
|
||||
if (slice == 0){
|
||||
InteractorStyle->SetCurrentRenderer(this->Renderer);
|
||||
InteractorStyle->SetCurrentImageNumber(0);
|
||||
}
|
||||
double direction = (double)(slice - lastSliceNumber);
|
||||
double focusPoint[5] = {.0, .0, .0 };
|
||||
GetSlicePoint(focusPoint);
|
||||
@@ -620,6 +628,33 @@ void DICOMImageViewer::SyncSliceWithFocus(double *point)
|
||||
UpdateTopLeftCornerInfo();
|
||||
}
|
||||
|
||||
void DICOMImageViewer::SyncSlicePointSameDirection(double *point) {
|
||||
if (point == nullptr){
|
||||
this->ActiveReferenceLine();
|
||||
this->InteractorStyle->AdjustSyncCrossPoint(nullptr);
|
||||
this->Render();
|
||||
}
|
||||
else{
|
||||
double focusPoint[4] = {point[0], point[1], point[2], 1.0};
|
||||
WorldToModelMatrix->MultiplyPoint(focusPoint, focusPoint);
|
||||
double f[3] = {.0, .0, .0};
|
||||
Renderer->GetActiveCamera()->GetFocalPoint(f);
|
||||
double bounds[6] = {.0, .0, .0, .0, .0, .0};
|
||||
ImageMapper->GetBounds(bounds);
|
||||
double displayPoint [3] ={.0};
|
||||
Renderer->SetWorldPoint(focusPoint);
|
||||
Renderer->WorldToDisplay();
|
||||
Renderer->GetDisplayPoint(displayPoint);
|
||||
f[SliceIJK] = focusPoint[SliceIJK];
|
||||
Renderer->GetActiveCamera()->SetFocalPoint(f);
|
||||
this->UnActiveReferenceLine();
|
||||
this->InteractorStyle->AdjustSyncCrossPoint(displayPoint);
|
||||
this->Render();
|
||||
UpdateTopLeftCornerInfo();
|
||||
Slice = ImageMapper->GetSliceNumber();
|
||||
}
|
||||
}
|
||||
|
||||
// zoom------------------------------------------------------------------------
|
||||
void DICOMImageViewer::SetZoomScale(double scale) {
|
||||
if (Renderer) {
|
||||
|
||||
@@ -373,6 +373,8 @@ public:
|
||||
return &raiser;
|
||||
}
|
||||
|
||||
void SyncSlicePointSameDirection(double *point);
|
||||
|
||||
void SyncSliceWithFocus(double *point);
|
||||
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ void ImageViewManager::add(DicomImageView *view) {
|
||||
|
||||
connect(view, &DicomImageView::onSlice,
|
||||
this, &ImageViewManager::viewSliced);
|
||||
connect(view, &DicomImageView::onSyncPointSlice,
|
||||
this, &ImageViewManager::viewSyncPoint);
|
||||
connect(view, &DicomImageView::onEndPan,
|
||||
this, &ImageViewManager::viewPaned);
|
||||
connect(view, &DicomImageView::onEndZoom,
|
||||
@@ -294,6 +296,20 @@ void ImageViewManager::viewSliced(DicomImageView *src, void *sliceData) {
|
||||
renderReferenceLine();
|
||||
}
|
||||
|
||||
void ImageViewManager::viewSyncPoint(DicomImageView *src, void * sliceData){
|
||||
//Sync slice Point
|
||||
if ( src->getImageViewer()->GetInteractorStyle()->GetInteractionMode() == VTKIS_SYNCPOINT){
|
||||
this->smartDo(nullptr,[](auto v, auto callData) {
|
||||
if (v->hasSeries()) {
|
||||
double *r = (double *) callData;
|
||||
v->syncSliceWithPoint(r);
|
||||
v->SyncScrollBar();
|
||||
}
|
||||
}, src, sliceData, ImageViewManager::SameSeries);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ImageViewManager::renderReferenceLine() {
|
||||
vtkPoints* pts = currentView->hasSeries() ? currentView->getSliceBoundPoints() : nullptr;
|
||||
smartDo([](auto v, auto callData) {
|
||||
|
||||
@@ -61,6 +61,8 @@ public:
|
||||
|
||||
void viewDoubleClicked(DicomImageView *view);
|
||||
|
||||
void viewSyncPoint(DicomImageView *src, void * sliceData);
|
||||
|
||||
void viewSliced(DicomImageView *src, void *sliceData);
|
||||
|
||||
void viewPaned(DicomImageView *src, void* offsetVector);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
#include <QCursor>
|
||||
|
||||
#include <vtkRenderer.h>
|
||||
#include <vtkCamera.h>
|
||||
#include <vtkInteractorStyleImage.h>
|
||||
@@ -488,6 +490,29 @@ void DicomImageView::dispatchEvent(vtkObject *, unsigned long eid, void *callDat
|
||||
emit onSlice(this, callData);
|
||||
break;
|
||||
}
|
||||
case (DraggableStyleEvents::StartSyncSlicePointEvent): {
|
||||
this->setCursor(Qt::BlankCursor);
|
||||
this->mImageViewer->Render();
|
||||
//invoke event
|
||||
break;
|
||||
}
|
||||
case (DraggableStyleEvents::SyncSlicePointEvent): {
|
||||
double * p = (double*)callData;
|
||||
double focalPoint[3]={0};
|
||||
focalPoint[0] = p[0];
|
||||
focalPoint[1] = p[1];
|
||||
focalPoint[2] = p[2];
|
||||
mImageViewer->TransformPointM2W(focalPoint);
|
||||
//invoke event
|
||||
emit onSyncPointSlice(this, focalPoint);
|
||||
break;
|
||||
}
|
||||
case (DraggableStyleEvents::EndSyncSlicePointEvent): {
|
||||
this->setCursor(Qt::ArrowCursor);
|
||||
//invoke event
|
||||
emit onSyncPointSlice(this, nullptr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -177,6 +177,10 @@ public:
|
||||
return this->mImageViewer->GetReconPlane() == view->mImageViewer->GetReconPlane();
|
||||
}
|
||||
|
||||
void syncSliceWithPoint(double *point) {
|
||||
mImageViewer->SyncSlicePointSameDirection(point);
|
||||
}
|
||||
|
||||
void syncSliceFocus(double *point) {
|
||||
mImageViewer->SyncSliceWithFocus(point);
|
||||
}
|
||||
@@ -220,6 +224,8 @@ signals:
|
||||
|
||||
void onSlice(DicomImageView *view, void *calldata);
|
||||
|
||||
void onSyncPointSlice(DicomImageView *view, void *calldata);
|
||||
|
||||
void onEndPan(DicomImageView *view, void * offsetVector);
|
||||
|
||||
void onEndZoom(DicomImageView *view, double* scaleFactor);
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace {
|
||||
const char *SYNC_MANUAL_URL = ":/InfiniteViewer/Icon/sync/sync_manual.png";
|
||||
const char *SYNC_AUTO_URL = ":/InfiniteViewer/Icon/sync/sync_auto.png";
|
||||
const char *SYNC_DIS_URL = ":/InfiniteViewer/Icon/sync/sync_dis.png";
|
||||
const int ACTION_COUNT = 8;
|
||||
const int ACTION_COUNT = 9;
|
||||
const ActionProperty MEASURE_ACTIIONS[ACTION_COUNT] = {
|
||||
{ ":/InfiniteViewer/Icon/distance.png", AnnotationActorType::RulerAnn},
|
||||
{ ":/InfiniteViewer/Icon/angle.png", AnnotationActorType::AngleAnn},
|
||||
@@ -26,7 +26,9 @@ namespace {
|
||||
{ ":/InfiniteViewer/Icon/arrow.png", AnnotationActorType::ArrowAnn},
|
||||
{ ":/InfiniteViewer/Icon/ellipse.png", AnnotationActorType::EllipseAnn},
|
||||
{ ":/InfiniteViewer/Icon/diameter.png", AnnotationActorType::DiameterAnn},
|
||||
{ ":/InfiniteViewer/Icon/text.png", AnnotationActorType::TextAnn}
|
||||
{ ":/InfiniteViewer/Icon/text.png", AnnotationActorType::TextAnn},
|
||||
{ ":/InfiniteViewer/Icon/crosshair.png", AnnotationActorType::SyncPoint}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -413,9 +415,13 @@ void DefaultToolBar::initMeasureButton() {
|
||||
QMenu *m;
|
||||
m = new QMenu(this);
|
||||
|
||||
for (int j = 0; j < ACTION_COUNT; ++j) {
|
||||
for (int j = 0; j < ACTION_COUNT-1; ++j) {
|
||||
ADD_MEASURE_ACTION(j);
|
||||
}
|
||||
|
||||
m->addAction(tr("Location Point"), this,[=](){
|
||||
emit modeChanged(38);
|
||||
});
|
||||
m->addSeparator();
|
||||
ADD_DEL_ACTION(tr("Delete selected"), AnnotationDeleteType::DeleteSelectedAnn);
|
||||
ADD_DEL_ACTION(tr("Delete all in current slice"), AnnotationDeleteType::DeleteSliceAnn);
|
||||
@@ -423,10 +429,7 @@ void DefaultToolBar::initMeasureButton() {
|
||||
mBtnMeasure->setPopupMode(QToolButton::MenuButtonPopup);
|
||||
mBtnMeasure->setMenu(m);
|
||||
|
||||
m->addSeparator();
|
||||
// m->addAction(tr("Localtion Point"), this,[=](){
|
||||
// emit modeChanged(38);
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
void DefaultToolBar::initFusionButton() {
|
||||
|
||||
@@ -261,6 +261,11 @@
|
||||
<source>Text</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="420"/>
|
||||
<source>Location Point</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="286"/>
|
||||
<source>Custom window width and level</source>
|
||||
@@ -297,112 +302,112 @@
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="420"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="424"/>
|
||||
<source>Delete selected</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="421"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="425"/>
|
||||
<source>Delete all in current slice</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="422"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="426"/>
|
||||
<source>Delete all in current series</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="434"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="435"/>
|
||||
<source>Fusion</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="440"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="441"/>
|
||||
<source>Cine</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="446"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="447"/>
|
||||
<source>Delete current series</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="452"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="453"/>
|
||||
<source>Transformations</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="460"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="461"/>
|
||||
<source>Rotate 90 CCW</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="461"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="462"/>
|
||||
<source>Rotate 90 CW</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="462"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="463"/>
|
||||
<source>Rotate 180</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="464"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="465"/>
|
||||
<source>Flip horizontal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="465"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="466"/>
|
||||
<source>Flip vertical</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="467"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="468"/>
|
||||
<source>Clear transformations</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="477"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="478"/>
|
||||
<source>MPR</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="480"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="481"/>
|
||||
<source>3D MPR</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="483"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="484"/>
|
||||
<source>Coronal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="484"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="485"/>
|
||||
<source>Sagittal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="485"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="486"/>
|
||||
<source>Axial</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="585"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="586"/>
|
||||
<source>Full screen</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="595"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="596"/>
|
||||
<source>Exit full screen mode</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="605"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="606"/>
|
||||
<source>Minimize</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="610"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="611"/>
|
||||
<source>Close</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -410,12 +415,12 @@
|
||||
<context>
|
||||
<name>DicomImageView</name>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ImageView/dicomimageview.cpp" line="221"/>
|
||||
<location filename="../src/UI/Widget/ImageView/dicomimageview.cpp" line="223"/>
|
||||
<source>Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ImageView/dicomimageview.cpp" line="222"/>
|
||||
<location filename="../src/UI/Widget/ImageView/dicomimageview.cpp" line="224"/>
|
||||
<source>Unable to read file %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
@@ -337,112 +337,117 @@
|
||||
<translation>测量工具</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="420"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="424"/>
|
||||
<source>Delete selected</source>
|
||||
<translation>删除选中</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="421"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="425"/>
|
||||
<source>Delete all in current slice</source>
|
||||
<translation>删除当前图像中所有测量</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="422"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="426"/>
|
||||
<source>Delete all in current series</source>
|
||||
<translation>删除当前序列所有图像</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="434"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="420"/>
|
||||
<source>Location Point</source>
|
||||
<translation>病灶定位</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="435"/>
|
||||
<source>Fusion</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="440"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="441"/>
|
||||
<source>Cine</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="446"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="447"/>
|
||||
<source>Delete current series</source>
|
||||
<translation>删除当前序列所有测量</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="452"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="453"/>
|
||||
<source>Transformations</source>
|
||||
<translation>翻页&旋转</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="460"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="461"/>
|
||||
<source>Rotate 90 CCW</source>
|
||||
<translation>逆时针旋转90度</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="461"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="462"/>
|
||||
<source>Rotate 90 CW</source>
|
||||
<translation>顺时针旋转90度</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="462"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="463"/>
|
||||
<source>Rotate 180</source>
|
||||
<translation>旋转180度</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="464"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="465"/>
|
||||
<source>Flip horizontal</source>
|
||||
<translation>水平翻转</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="465"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="466"/>
|
||||
<source>Flip vertical</source>
|
||||
<translation>垂直翻转</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="467"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="468"/>
|
||||
<source>Clear transformations</source>
|
||||
<translation>清除变换</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="477"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="478"/>
|
||||
<source>MPR</source>
|
||||
<translation>多平面重建</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="480"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="481"/>
|
||||
<source>3D MPR</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="483"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="484"/>
|
||||
<source>Coronal</source>
|
||||
<translation>冠状面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="484"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="485"/>
|
||||
<source>Sagittal</source>
|
||||
<translation>矢状面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="485"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="486"/>
|
||||
<source>Axial</source>
|
||||
<translation>横断面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="585"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="586"/>
|
||||
<source>Full screen</source>
|
||||
<translation>全屏</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="595"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="596"/>
|
||||
<source>Exit full screen mode</source>
|
||||
<translation>退出全屏</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="605"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="606"/>
|
||||
<source>Minimize</source>
|
||||
<translation>最小化</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="610"/>
|
||||
<location filename="../src/UI/Widget/ToolBar/DefaultToolBar.cpp" line="611"/>
|
||||
<source>Close</source>
|
||||
<translation>关闭</translation>
|
||||
</message>
|
||||
@@ -450,12 +455,12 @@
|
||||
<context>
|
||||
<name>DicomImageView</name>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ImageView/dicomimageview.cpp" line="221"/>
|
||||
<location filename="../src/UI/Widget/ImageView/dicomimageview.cpp" line="223"/>
|
||||
<source>Error</source>
|
||||
<translation>错误</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/UI/Widget/ImageView/dicomimageview.cpp" line="222"/>
|
||||
<location filename="../src/UI/Widget/ImageView/dicomimageview.cpp" line="224"/>
|
||||
<source>Unable to read file %1</source>
|
||||
<translation>无法读取文件 %1</translation>
|
||||
</message>
|
||||
|
||||
Reference in New Issue
Block a user