⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imagemap.cpp

📁 Visual C++_ 600 编程学习捷径
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ImageMap.cpp: implementation of the CImageMap class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ImageTest.h"
#include "ImageMap.h"
#include "dib.h"
#include <math.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CImageMap::CImageMap()
{
	m_dZoomAmount = 1.5;
	m_dZoomFactor = 1.0;
	m_dZoomOrigin = 1.0;
	m_dScale      = 1.0;
	m_dScaleAll   = 1.0;
	m_dScaleOrigin= 1.0;
	m_nShiftSize  = 50;
	m_dOffsetX    = 0.0;
	m_dOffsetY    = 0.0;

	m_x1  = m_y1  = m_x2  = m_y2  = 0;
	m_cx  = m_cy  = 0;

	m_bSetMBRC     = FALSE;
	m_bIsLoadMap   = FALSE;
	m_hWnd         = NULL;
	m_pOldBitmap   = NULL;
	m_pDib         = NULL;                 
	m_lImageWidth  = 0;              //图像宽度
	m_lImageHeight = 0;              //图像高度
	memset(&m_rcRect, 0, sizeof(m_rcRect));
}

CImageMap::~CImageMap()
{
	UnloadMap();
}

//加载地图数据
int CImageMap::LoadMapFile(LPCTSTR filename)
{
	if(m_bIsLoadMap)//如果已加载地图
	{
		if(m_strMapFile == filename)//如果已加载该地图
			return 1;
		UnloadMap();//卸载先前地图
	}
	
	CString szExt = filename;
	int id = szExt.ReverseFind(_T('.'));
	if(id == -1)
	{
		MessageBox(NULL, _T("文件无效!"), NULL, MB_OK);
		return 0;
	}
	CString left = szExt.Left(id);
	szExt = szExt.Right(szExt.GetLength() - id - 1);
	szExt.MakeUpper();
	if(szExt == _T("BMP")) //bmp type
	{
		m_pDib = new CDib;
		if(!m_pDib->ReadDIBFile(filename))
		{
			MessageBox(NULL, _T("加载地图错误!"), NULL, MB_OK);
			delete m_pDib;
			m_pDib = NULL;
			return 0;
		}
		m_lImageWidth  = m_pDib->GetWidth();  //图像宽度
		m_lImageHeight = m_pDib->GetHeight(); //图像高度
	}
	else
	{
		CString output = _T("不支持") + szExt;
		output += _T("类型!");
		MessageBox(NULL, output, _T("错误"), MB_OK);
		return 0;
	}

	id = left.ReverseFind(_T('\\'));
	m_strMapName = left.Right(left.GetLength() - id - 1);
	m_strMapFile = filename;

	if(m_pDib->m_bIsImageMap)//如果地图文件中有地图范围
	{
		m_rcRect.x1 =  m_pDib->m_x1;
		m_rcRect.x2 =  m_pDib->m_x2;
		m_rcRect.y1 = -m_pDib->m_y1;
		m_rcRect.y2 = -m_pDib->m_y2;
		//调整包围矩形,使左上角顶点坐标最小
		if(m_rcRect.y1 > m_rcRect.y2)
		{
			float tempy = m_rcRect.y1;
			m_rcRect.y1 = m_rcRect.y2;
			m_rcRect.y2 = tempy;
		}
		if(m_rcRect.x1 > m_rcRect.x2)
		{
			float tempx = m_rcRect.x1;
			m_rcRect.x1 = m_rcRect.x2;
			m_rcRect.x2 = tempx;
		}
		InitialParam(m_rcRect); //初始化参数
		m_dScaleOrigin = m_pDib->m_dScale; 

		m_dScale = m_dScaleOrigin;
		double x1 = 0, y1 = 0;
		double x2 = m_cx, y2 = m_cy;
		m_dZoomFactor = m_dZoomOrigin * m_dScale/m_dScaleAll;
		ScreenToMap(&x1, &y1);
		ScreenToMap(&x2, &y2);
		double x = (m_rcRect.x1 + m_rcRect.x2)/2;
		double y = (m_rcRect.y1 + m_rcRect.y2)/2;
		
		m_dOffsetX = x - fabs(x2 - x1);
		m_dOffsetY = y - fabs(y2 - y1);

		m_bSetMBRC = TRUE;
	}

	m_bIsLoadMap = TRUE;

	return 1;
}

/* 设置地图的边界和比例尺,在DrawMap之前调用 */
void CImageMap::SetMapMBRC(double left, double top, double right, double bottom, double dScale)
{
	m_rcRect.x1 =  (float)left;
	m_rcRect.x2 =  (float)right;
	m_rcRect.y1 = -(float)top;
	m_rcRect.y2 = -(float)bottom;
	//调整包围矩形,使左上角顶点坐标最小
	if(m_rcRect.y1 > m_rcRect.y2)
	{
		float tempy = m_rcRect.y1;
		m_rcRect.y1 = m_rcRect.y2;
		m_rcRect.y2 = tempy;
	}
	if(m_rcRect.x1 > m_rcRect.x2)
	{
		float tempx = m_rcRect.x1;
		m_rcRect.x1 = m_rcRect.x2;
		m_rcRect.x2 = tempx;
	}
	InitialParam(m_rcRect); //初始化参数
	m_dScaleOrigin = dScale; 

	m_dScale = m_dScaleOrigin;
	double x1 = 0, y1 = 0;
	double x2 = m_cx, y2 = m_cy;
	m_dZoomFactor = m_dZoomOrigin * m_dScale/m_dScaleAll;
	ScreenToMap(&x1, &y1);
	ScreenToMap(&x2, &y2);
	double x = (m_rcRect.x1 + m_rcRect.x2)/2;
	double y = (m_rcRect.y1 + m_rcRect.y2)/2;
	
	m_dOffsetX = x - fabs(x2 - x1);
	m_dOffsetY = y - fabs(y2 - y1);

	m_bSetMBRC = TRUE;

	if(!m_strMapFile.IsEmpty() &&m_pDib)
	{
		CFile cf;
		if(cf.Open(m_strMapFile, CFile::modeReadWrite))
		{
			m_pDib->m_x1 = (float)fabs(left);
			m_pDib->m_y1 = (float)fabs(top);
			m_pDib->m_x2 = (float)fabs(right);
			m_pDib->m_y2 = (float)fabs(bottom);
			m_pDib->m_dScale = (float)fabs(dScale);
			if(m_pDib->m_bIsImageMap)
				cf.Seek(-long(sizeof(float)*5), CFile::end);
			else
				cf.SeekToEnd();
			cf.Write(&m_pDib->m_x1, sizeof(float));
			cf.Write(&m_pDib->m_y1, sizeof(float));
			cf.Write(&m_pDib->m_x2, sizeof(float));
			cf.Write(&m_pDib->m_y2, sizeof(float));
			cf.Write(&m_pDib->m_dScale, sizeof(float));
			cf.Close();

			m_pDib->m_bIsImageMap = TRUE;
		}
		else 
		{
			MessageBox(NULL, _T("写文件错误,请检查文件是否是只读类型!"), _T("错误"), MB_OK);
		}
	}
}

BOOL CImageMap::IsSetMapMBRC(void)
{
	if(m_pDib && m_pDib->m_bIsImageMap)
		return TRUE;

	return FALSE;
}

void CImageMap::UnloadMap()//卸载地图
{
	m_bIsLoadMap = FALSE;
	m_strMapFile.Empty();
	m_strMapName.Empty();
	m_bSetMBRC = FALSE;

	if(m_pDib)
		delete m_pDib;
	m_pDib = NULL;

	if(m_hWnd)
	{
		HDC dc = GetDC(m_hWnd);
		CRect rc;
		GetClientRect(m_hWnd, &rc);
		PatBlt(dc, rc.left, rc.top, rc.right, rc.bottom, WHITENESS);
		ReleaseDC(m_hWnd, dc);
	}
}

void CImageMap::SetMapHwnd(HWND hWnd)
{
	m_hWnd = hWnd;
}

void CImageMap::SetClientRect(long x1, long y1, long x2, long y2)
{
	m_x1 = x1;
	m_y1 = y1;
	m_x2 = x2;
	m_y2 = y2;

	//计算屏幕中心点坐标
	m_cx = (m_x1 + m_x2)/2;
	m_cy = (m_y1 + m_y2)/2;

	/* 如果内存DC已经存在,则重新创建新的*/
	if(m_memDC.GetSafeHdc() != NULL)
	{
		m_memDC.SelectObject(m_pOldBitmap);
		m_memDC.DeleteDC();

		CDC *pdc = NULL;
		HDC hdc = NULL;

		if(m_hWnd)
		{
			//获取窗口显示DC
			hdc = GetDC(m_hWnd); 
			pdc = CDC::FromHandle(hdc);
		}

		m_memDC.CreateCompatibleDC(pdc);//如果pdc=NULL,则创建和屏幕DC兼容的DC
		if(m_Bitmap.GetSafeHandle())
		{
			m_Bitmap.DeleteObject();
			m_Bitmap.CreateCompatibleBitmap(pdc, m_x2 - m_x1, m_y2 - m_y1);//创建空白内存位图
		}
		m_pOldBitmap = m_memDC.SelectObject(&m_Bitmap); 

		ReleaseDC(m_hWnd, hdc);

		DrawMap();
	}
}

void CImageMap::SetClientRect(LPRECT rc)
{
	if(rc == NULL) return;

	SetClientRect(rc->left, rc->top, rc->right, rc->bottom);
}

void CImageMap::InitialParam(MBRECT mbrc)
{
	if(mbrc.x2 == mbrc.x1 || mbrc.y2 == mbrc.y1) return;

	double blcx = (m_x2 - m_x1)/(mbrc.x2 - mbrc.x1);
	double blcy = (m_y2 - m_y1)/(mbrc.y2 - mbrc.y1);

	HDC hdc = GetDC(m_hWnd);
	//厘米/像素,每英寸=2.54厘米
	double cmp = 2.54/GetDeviceCaps(hdc, LOGPIXELSX);
	ReleaseDC(m_hWnd, hdc);

	if(blcx > blcy) //取较小的一个作为比例基数
	{
		m_dZoomOrigin = blcy;
		double cm = (m_y2 - m_y1) * cmp;
		m_dScaleAll = Distance(mbrc.x1, mbrc.y1, mbrc.x2, mbrc.y2)/cm;
	}
	else 
	{
		m_dZoomOrigin = blcx;
		double cm = (m_x2 - m_x1) * cmp;
		m_dScaleAll = Distance(mbrc.x1, mbrc.y1, mbrc.x2, mbrc.y2)/cm;
	}

	m_dOffsetX = mbrc.x1;
	m_dOffsetY = mbrc.y1;
	m_dZoomFactor = m_dZoomOrigin;
	m_dScale = m_dScaleAll;

	double x1 = m_x1;
	double y1 = m_y1;
	double x2 = m_x2;
	double y2 = m_y2;
	ScreenToMap(&x1, &y1);
	ScreenToMap(&x2, &y2);
	
	m_dOffsetX = mbrc.x1 + (mbrc.x2 - mbrc.x1)/2 - (x2 - x1)/2;
	m_dOffsetY = mbrc.y1 + (mbrc.y2 - mbrc.y1)/2 - (y2 - y1)/2;
}

void CImageMap::ScreenToMap(double *x, double *y)
{
	*x =  m_dOffsetX + *x / m_dZoomFactor;
	*y =  m_dOffsetY + *y / m_dZoomFactor;
}

void CImageMap::MapToScreen(double *x, double *y)
{
	*x = (*x - m_dOffsetX) * m_dZoomFactor;
	*y = (*y - m_dOffsetY) * m_dZoomFactor;
}

//地图坐标转换为图像坐标
void CImageMap::MapToImage(double *x, double *y)    
{
	*x = (*x - m_rcRect.x1) * m_lImageWidth/(m_rcRect.x2 - m_rcRect.x1);
	*y = (*y - m_rcRect.y1) * m_lImageHeight/(m_rcRect.y2 - m_rcRect.y1); 
}

//图像坐标转换为地图坐标
void CImageMap::ImageToMap(double *x, double *y)    
{
	*x = *x * (m_rcRect.x2 - m_rcRect.x1)/m_lImageWidth + m_rcRect.x1;
	*y = *y * (m_rcRect.y2 - m_rcRect.y1)/m_lImageHeight + m_rcRect.y1;
}

//屏幕坐标转换为图像坐标
void CImageMap::ScreenToImage(long *x, long *y) 
{
	double tx = *x;
	double ty = *y;
	ScreenToMap(&tx, &ty);
	MapToImage(&tx, &ty);
	*x = (long)tx;
	*y = (long)ty;
}

//图像坐标转换为屏幕坐标
void CImageMap::ImageToScreen(long *x, long *y) 
{
	double tx = *x;
	double ty = *y;
	ImageToMap(&tx, &ty);
	MapToScreen(&tx, &ty);
	*x = (long)tx;
	*y = (long)ty;
}

void CImageMap::Draw(CDC *pdc, CRect& rcInvalid) //刷新地图
{
	if(m_memDC.m_hDC && pdc && m_bIsLoadMap)
	{
		pdc->BitBlt(rcInvalid.left, rcInvalid.top, rcInvalid.Width(), rcInvalid.Height(),
			&m_memDC, rcInvalid.left, rcInvalid.top, SRCCOPY);
	}
	else if(pdc) //未加载地图时用白色填充
		pdc->PatBlt(m_x1, m_y1, m_x2 - m_x1, m_y2 - m_y1, WHITENESS);
}

void CImageMap::DrawMap(CDC *pdc)
{
	//绘制地图........
	if(m_pDib && pdc && m_bSetMBRC)
	{
		long x1 = m_x1, y1 = m_y1;
		long x2 = m_x2, y2 = m_y2;
		ScreenToImage(&x1, &y1);
		ScreenToImage(&x2, &y2);
		if(x1 < 0) x1 = 0;
		if(y1 < 0) y1 = 0;
		if(x2 >= m_lImageWidth)
			x2 = m_lImageWidth - 1;
		if(y2 >= m_lImageHeight)
			y2 = m_lImageHeight - 1;

		CRect rcDc(x1, y1, x2, y2);
		ImageToScreen(&rcDc.left, &rcDc.top);
		ImageToScreen(&rcDc.right, &rcDc.bottom);
		rcDc.NormalizeRect();

		//如果图像是倒序存储
		if(m_lImageHeight > 0)
		{
			y1 = m_lImageHeight - y1 - 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -