MFC+Direct2D简化坐标缩放

背景

问题由来

在参考1这篇文章里写了GDI下坐标缩放的情况,这里记录下再Direct2D绘图引擎下的缩放操作。

环境配置

参考文章2

几个概念

参考上一篇文章的说明配图
MFC+Direct2D简化坐标缩放_第1张图片
MFC+Direct2D简化坐标缩放_第2张图片

实现功能

1.所有图形初始缩放在默认视图框架内
2.(0,0)位置位于视图左下角
3.可以从屏幕坐标反推出原始数据坐标
4.使用Direct2D技术,在保持抗锯齿效果的同时,绘图效率和GDI差不多

思路及代码

流程图

Created with Raphaël 2.1.0

计算等效初始坐标

1.遍历原始坐标获得XMAX,YMAX,XMIN,YMIN.
2.获得视窗访问WIDTH,HEIGHT.
3.计算初始缩放比率SCALE,计算方法为:

if(YMAXYMINHEIGHT>XMAXXMINWIDTH),SCALE=HEIGHTYMAXYMIN

if(YMAXYMINHEIGHT<XMAXXMINWIDTH),SCALE=WIDTHXMAXXMIN

同时得到绘图范围

RANGEX=(XMAXXMIN)SCALE

RANGEY=(YMAXYMIN)SCALE

4.计算等效初始坐标,计算方法为:

xnew=(xoldXMIN)SCALE

ynew=(yoldYMIN)SCALE+RANGEY

其中乘以负的缩放系数并加上绘图范围的Y值是为了将坐标调整为y正向向上,左下角为(0,0)
5.反推原始数据
为了从屏幕坐标反推得到原始数据,必须传入视图滚动条位置信息ScrollPT及视图缩放系数Zoom(注意不是初始缩放系数SCALE)
计算方法为:

xold=xscreen+ScrollPT.xZoomSCALE+XMIN

yold=yscreen+ScrollPT.yZoomRANGEYSCALE+YMIN

代码

//.h文件 
//一些结构定义
typedef std::vector<CPoint> vPT; 
typedef D2D1_POINT_2F DPoint;
typedef std::vector<DPoint> vDPT; 
typedef D2D1::Matrix3x2F Matrix;
typedef struct _InitOffset
{//初始化时显示参数
    int nXOffset;
    int nYOffset;
    double dInitScale;
    CSize range;
    _InitOffset()
    {
        nXOffset = 0;
        nYOffset = 0;
        dInitScale = 1.0;
        range.cx = 1;
        range.cy = 1;
    }
}InitOffset;

typedef struct _ZoomOffset
{//初始显示完成之后缩放时显示参数
    CPoint ScrolPT;
    double dZoom;
    _ZoomOffset()
    {
        ScrolPT = CPoint(0,0);
        dZoom = 1.0;
    }
}ZoomOffset;
typedef struct _ScreenPara
{//显示参数
    InitOffset initoffset;
    ZoomOffset zoomoffset;
inline  CPoint GetOriginPTFromScreenPT(CPoint ScreenPT)
    {
        CPoint PT;
        PT.x = (ScreenPT.x + zoomoffset.ScrolPT.x) / (zoomoffset.dZoom * initoffset.dInitScale) 
            + initoffset.nXOffset ;
        PT.y = ((ScreenPT.y  + zoomoffset.ScrolPT.y) / zoomoffset.dZoom - initoffset.range.cy) / 
            -initoffset.dInitScale + initoffset.nYOffset;
        return(PT);
    }
inline  CSize GetZoomRange(void)
    {
        return(CSize(initoffset.range.cx * zoomoffset.dZoom,
            initoffset.range.cy * zoomoffset.dZoom));
    }
}ScreenPara;

extern ScreenPara g_ScreenPara;
//.cpp
//鼠标滚轮缩放
BOOL CScaleD2DView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    // TODO: Add your message handler code here and/or call default
    double m_dScale = g_ScreenPara.zoomoffset.dZoom;
    m_dScale += 0.1 * zDelta/ 120;
    if(m_dScale <= 0.2)  
    {   
        m_dScale = 0.2; 
    }         
    if(m_dScale >= 2.0)  
    {
        m_dScale = 2.0; 
    }
    g_ScreenPara.zoomoffset.dZoom = m_dScale;
    SetScrollSizes(MM_TEXT, g_ScreenPara.GetZoomRange());
    Invalidate();
    return CScrollView::OnMouseWheel(nFlags, zDelta, pt);
}

结果

MFC+Direct2D简化坐标缩放_第3张图片

参考

1.MFC+GDI简化坐标平移缩放
2.Direct2D+MFC学习笔记
3.Direct2D教程(外篇)环境配置

你可能感兴趣的:(缩放,mfc,Direct2D)