📄 fmwndvr.cpp
字号:
// FMWndVR.cpp : implementation file//////////////////////////////////////////////////////////////////////////// Title: Interface for VR window control//////////////////////////////////////////////////////////////////////////// Author: H.W.Gye, H.S.Kim, H.Lee and H.Hong// 138-dong 417-ho Seoul National University// San 56-1 Shinlim-dong Kwanak-gu Seoul, Korea// Email. //// Date :// Update ://////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// include//////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "fusion.h"#include <math.h>#include "FusionGlobal.h"#include "FusionEnum.h"#include "FusionDefine.h"#include "VolumeData.h"#include "Matrix4D.h"#include "VoxelShader.h"#include "VRRayCastingAgent.h"#include "RayCastingFusionAgent.h"#include "RayCastingCommonInfo.h"#include "RigidReg3DAgent.h"#include "RigidReg3DInfo.h"#include "Transform3DInfo.h"#include "FMWndVR.h"#include "FMDocVR.h"#include "FMWndLocalizer.h"#include "FMWnd3DMPR.h"#include "Registration.h"#include "DlgMixing.h"#include "DlgRegistReport.h"#include "DlgMode.h"#include "AnnotationObject.h"//////////////////////////////////////////////////////////////////////// define//////////////////////////////////////////////////////////////////////#define DESTROY_CLASS_INSTANCE(ci) {if(ci) {delete ci; ci=NULL;}}#define MOUSE_SCALE_FACTOR 6#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif//////////////////////////////////////////////////////////////////////// declaration//////////////////////////////////////////////////////////////////////#define COLOR_REF_NODULE RGB(255, 0, 0)#define COLOR_FLOAT_NODULE RGB(0, 0, 255)#define RADIUS 5HANDLE g_hVRThreadKillEvent;RxVRRayCastingAgent *RxFMWndVR::m_pVRRefAgent = NULL;RxVRRayCastingAgent *RxFMWndVR::m_pVRFltAgent = NULL;RxRayCastingFusionAgent *RxFMWndVR::m_pVRFusAgent = NULL;RxRayCastingCommonInfo *RxFMWndVR::m_pVRRefInfo = NULL;RxRayCastingCommonInfo *RxFMWndVR::m_pVRFltInfo = NULL;RxMatrix4D RxFMWndVR::m_mxView;RxMatrix4D RxFMWndVR::m_mxRefView;RxMatrix4D RxFMWndVR::m_mxRotation;RxMatrix4D RxFMWndVR::m_mxRegistration;CPoint RxFMWndVR::m_ptPan = CPoint(0,0);HANDLE RxFMWndVR::m_hVRThread = NULL;CWinThread *RxFMWndVR::m_pVRThread = NULL;RxRigidReg3DAgent *RxFMWndVR::m_pRigidReg3DAgent = NULL;RxRigidReg3DInfo *RxFMWndVR::m_pRigidReg3DInfo = NULL;RxTransform3DInfo *RxFMWndVR::m_pTransform = NULL;RxTransform3DInfo *RxFMWndVR::m_pTransformRight = NULL;RxTransform3DInfo *RxFMWndVR::m_pTransformLeft = NULL;RxxRegistration g_Reg;//////////////////////////////////////////////////////////////////////// RxFMWndVRRxFMWndVR::RxFMWndVR(UINT nSeries) : RxFMWnd3DOutline(nSeries){ m_bNeedToRender = FALSE; m_szWindow = CSize(0,0); m_ptOld = CPoint(0,0); m_ptDown = CPoint(0,0); m_pbyFinalImage = NULL; m_pVRThread = NULL; m_lMeasure.RemoveAll(); if(m_nSeries == RXSERIES_REF) { m_pVRRefAgent = new RxVRRayCastingAgent(RXSERIES_REF); m_pVRRefInfo = new RxRayCastingCommonInfo; m_pVRRefInfo->m_iState = 1; // ref } else if(m_nSeries == RXSERIES_FLT) { m_pVRFltAgent = new RxVRRayCastingAgent(RXSERIES_FLT); m_pVRFltInfo = new RxRayCastingCommonInfo; m_pVRFltInfo->m_iState = 0; // flt } else if(m_nSeries == RXSERIES_COM) { m_pVRFusAgent = new RxRayCastingFusionAgent; m_mxView.LoadIdentity(); m_mxRefView.LoadIdentity(); // rotation init. m_mxRotation.LoadIdentity(); m_mxRotation.Rotate(0, 90); g_hVRThreadKillEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); } if(m_nSeries == RXSERIES_COM) { m_pRigidReg3DAgent = new RxRigidReg3DAgent; m_pRigidReg3DInfo = new RxRigidReg3DInfo; m_pTransform = new RxTransform3DInfo; m_pTransformRight = new RxTransform3DInfo; m_pTransformLeft = new RxTransform3DInfo; } InitRigidRegistration(); m_pDlgMixing = NULL; m_bNeedRecalVolume = FALSE; m_bRegistrationDone = FALSE;}RxFMWndVR::~RxFMWndVR(){ KillRenderThread(); if(m_nSeries == RXSERIES_REF) { DESTROY_CLASS_INSTANCE(m_pVRRefAgent); DESTROY_CLASS_INSTANCE(m_pVRRefInfo); } else if (m_nSeries == RXSERIES_FLT) { DESTROY_CLASS_INSTANCE(m_pVRFltAgent); DESTROY_CLASS_INSTANCE(m_pVRFltInfo); } else if (m_nSeries == RXSERIES_COM) { DESTROY_CLASS_INSTANCE(m_pVRFusAgent); } if(m_nSeries == RXSERIES_COM) { DESTROY_CLASS_INSTANCE(m_pRigidReg3DAgent); DESTROY_CLASS_INSTANCE(m_pRigidReg3DInfo); DESTROY_CLASS_INSTANCE(m_pTransform); DESTROY_CLASS_INSTANCE(m_pTransformRight); DESTROY_CLASS_INSTANCE(m_pTransformLeft); } ClearAnnotationList();}BEGIN_MESSAGE_MAP(RxFMWndVR, RxFMWnd3DOutline) //{{AFX_MSG_MAP(RxFMWndVR) ON_WM_PAINT() ON_WM_SIZE() ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_CREATE() ON_WM_DESTROY() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_SETCURSOR() ON_WM_MOUSEWHEEL() ON_COMMAND(IDTB_DISTANCE, OnDistance) ON_UPDATE_COMMAND_UI(IDTB_DISTANCE, OnUpdateDistance) ON_COMMAND(IDTB_AREA, OnArea) ON_UPDATE_COMMAND_UI(IDTB_AREA, OnUpdateArea) ON_COMMAND(IDTB_VOLUME, OnVolume) ON_UPDATE_COMMAND_UI(IDTB_VOLUME, OnUpdateVolume) ON_COMMAND(IDTB_REGIST_REPORT, OnRegistMode) ON_UPDATE_COMMAND_UI(IDTB_REGIST_REPORT, OnUpdateRegistReport) //}}AFX_MSG_MAP ON_COMMAND(IDFM_VR_BTN_MIXING, OnBtnMixing) ON_COMMAND(IDFM_LOCAL_BTN_MIN, OnBtnMin) ON_COMMAND(IDFM_LOCAL_BTN_MAX, OnBtnMax) ON_COMMAND_RANGE(IDFM_VR_ORIENT_A, IDFM_VR_ORIENT_F, OnOrientBtn) ON_NOTIFY(EN_CHANGED_INT, IDF_BOTTOM_ED_ZOOM, OnChangedZoomFactor) ON_NOTIFY(NM_DLG_MIXING_APPLY, IDD_MIXING_BTN_APPLY, OnDlgApplyMixing) ON_NOTIFY(NM_DLG_MIXING_CANCEL, IDD_MIXING_BTN_APPLY, OnDlgCancelMixing)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////// RxFMWndVR message handlers and virtual functions (H.S.Kim)/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 1. window message handlersint RxFMWndVR::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (RxFMWnd3DOutline::OnCreate(lpCreateStruct) == -1) return -1; if(m_nSeries == RXSERIES_COM) { m_pDlgMixing = new RxDlgMixing(this); m_pDlgMixing->Create(IDD_DLG_COMMON); } return 0;}void RxFMWndVR::OnDestroy() { RxFMWnd3DOutline::OnDestroy(); if(m_pDlgMixing) { m_pDlgMixing->DestroyWindow(); delete m_pDlgMixing; } }void RxFMWndVR::OnActivateWnd(BOOL bActivate, CWnd *pCurWnd, CWnd *pOldWnd){ RxFMWnd3DOutline::OnActivateWnd(bActivate, pCurWnd, pOldWnd); if(bActivate) { RxFrameBottom *pFrameBottom = RxGetFrameBottom(); pFrameBottom->EnableWindowing(-1, FALSE); pFrameBottom->SetZoomFactor(theFMDocVR.m_iVRZoomFactor); }}////////////////////////////////////////////// 1.1 WM_PAINT message handler and draw functionsvoid RxFMWndVR::OnPaint() { CPaintDC dc(this); // device context for painting RedrawWnd(m_bNeedToRender); // this flag is a TRUE, only WM_SIZE message if(m_bNeedToRender) m_bNeedToRender = FALSE; // Do not call RxFMWnd3DOutline::OnPaint() for painting messages}void RxFMWndVR::RedrawWnd(BOOL bNeedToRender){ // calculate volume data BOOL bRenderSuccess = FALSE; if(bNeedToRender) { TRACE(_T("\nneed to render true")); bRenderSuccess = RenderVolume(); if(!bRenderSuccess) return; } else { TRACE(_T("\nneed to render false")); } CDC *pDC = GetDC(); CDC dcMem; dcMem.CreateCompatibleDC(pDC); CBitmap bmpMem, *pOldBitmap; bmpMem.CreateCompatibleBitmap(pDC, m_szWindow.cx, m_szWindow.cy); pOldBitmap = dcMem.SelectObject(&bmpMem); int nTBCurMode = RxGetFrameMain()->GetTBCurMode(); // volume image output DrawVolume(&dcMem); // draw bounding box DrawBoundingBoxWhole(&dcMem); DrawBoundingBoxCrop(&dcMem); if(nTBCurMode == BTN_3DMPR_BASIC) DrawMPRLine(&dcMem); DrawOrientationCube(&dcMem);// DrawLungNodule(&dcMem); DrawScaleBar(&dcMem); DrawAnnotation(&dcMem); if(m_nSeries == RXSERIES_REF || m_nSeries == RXSERIES_FLT) DrawPatientInfo(&dcMem); // transformation output DrawTransOutput(&dcMem); pDC->BitBlt(0, 0, m_szWindow.cx, m_szWindow.cy, &dcMem, 0, 0, SRCCOPY); dcMem.SelectObject(pOldBitmap); bmpMem.DeleteObject(); dcMem.DeleteDC(); ReleaseDC(pDC); // thread start if(bNeedToRender) { m_pVRThread = AfxBeginThread(VRThreadFunc, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); ASSERT(m_pVRThread); ::DuplicateHandle(GetCurrentProcess(), m_pVRThread->m_hThread, GetCurrentProcess(), &m_hVRThread, 0L, FALSE, DUPLICATE_SAME_ACCESS); m_pVRThread->ResumeThread(); }}void RxFMWndVR::DrawVolume(CDC *pDC){ TRACE(_T("\nimage ptr=%p\n"),m_pbyFinalImage); if(!m_pbyFinalImage) return; CBitmap *pBitmap = pDC->GetCurrentBitmap(); BITMAP bm; pBitmap->GetBitmap(&bm); pBitmap->SetBitmapBits(bm.bmWidthBytes*bm.bmHeight, m_pbyFinalImage);}void RxFMWndVR::DrawAnnotation(CDC *pDC){ CPen Pen(PS_SOLID, 2, RGB(0,135,195)); CPen *OldPen = (CPen *)pDC->SelectObject(&Pen); CBrush brush, *pOldBrush; brush.CreateStockObject(NULL_BRUSH); pOldBrush = pDC->SelectObject(&brush); RxMatrix4D mxView; double fVoxelLength=0; int x=0,y=0; if(m_nSeries == RXSERIES_REF) { mxView = m_pVRRefInfo->m_mxViewing; fVoxelLength = RxGetVolumeData(RXSERIES_REF)->GetVoxelLength(); } else if(m_nSeries == RXSERIES_FLT) { mxView = m_pVRFltInfo->m_mxViewing; fVoxelLength = RxGetVolumeData(RXSERIES_FLT)->GetVoxelLength(); } POSITION pos = m_lMeasure.GetHeadPosition(); int size=m_lMeasure.GetCount(); CPen pen; while(pos != NULL) { CString str; RxMeasurement *pElement = (RxMeasurement *)m_lMeasure.GetNext(pos); pDC->SetBkColor(pElement->color); pen.CreatePen(PS_SOLID, 1, pElement->color); pDC->SelectObject(&pen); int iOffsetX = pElement->ptTextOffset.x; int iOffsetY = pElement->ptTextOffset.y; if(pElement->nType == VOLUME) { if(pElement->fMeasurement < 0) { pen.DeleteObject(); continue; } RxVolume *pVolume = (RxVolume *)pElement; RxVect4D vecObject(pVolume->x, pVolume->y, pVolume->z); RxVect4D vecImage = mxView * vecObject; x = ROUNDOFF(vecImage.m[0]); y = ROUNDOFF(vecImage.m[1]); CPen linePen(PS_SOLID, 2, pElement->color); CPen *pOldPen = (CPen *)pDC->SelectObject(&linePen); pDC->Ellipse(x-2, y-2, x+2, y+2); pDC->SelectObject(pOldPen); linePen.DeleteObject(); str.Format(_T("%2.2f"),pElement->fMeasurement); pDC->TextOut(x+iOffsetX, y+iOffsetY, str); pDC->MoveTo(x+iOffsetX, y+iOffsetY); pDC->LineTo(x, y); } else if(pElement->nType == AREA) { RxArea *pArea = (RxArea *)pElement; if(!pArea->bValid) { pen.DeleteObject(); continue; } RxVect4D vecObject(pArea->x, pArea->y, pArea->z); RxVect4D vecImage = mxView * vecObject; x = ROUNDOFF(vecImage.m[0]); y = ROUNDOFF(vecImage.m[1]); int nWidth = int(pArea->a * theFMDocVR.m_iVRZoomFactor * 0.01 / fVoxelLength); int nHeight = int(pArea->b * theFMDocVR.m_iVRZoomFactor * 0.01 / fVoxelLength); CPen linePen(PS_SOLID, 2, pElement->color); CPen *pOldPen = (CPen *)pDC->SelectObject(&linePen); pDC->Ellipse(x-nWidth, y-nHeight, x+nWidth, y+nHeight); pDC->SelectObject(pOldPen); linePen.DeleteObject(); if(pArea->fMeasurement) { ASSERT(iOffsetX); double k = (double)iOffsetY/iOffsetX; // y = kx double dx = nWidth*nHeight/sqrt(nWidth*nWidth*k*k+nHeight*nHeight); // crossing point dx = dx * abs(iOffsetX) / (iOffsetX); // consider negative double dy = dx*k; int iDx = ROUNDOFF(dx); int iDy = ROUNDOFF(dy); str.Format(_T("%2.2f"),pArea->fMeasurement); pDC->TextOut(x+iOffsetX, y+iOffsetY, str); pDC->MoveTo(x+iOffsetX, y+iOffsetY); pDC->LineTo(x+iDx, y+iDy); } } else if(pElement->nType == LINE) { RxLine *pLine = (RxLine *)pElement; if(!pLine->bValid) { pen.DeleteObject(); continue; } CPoint ptFrom, ptTo; if(pLine->iTo[0] < 0) { // 弊府绰 吝
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -