-1

我想ZoomTool在便携式应用程序中做类似的事情Global Mapper。您知道当用户左键单击图像时,应用程序将缩放到用户单击的位置,如果右键单击,应用程序将缩小用户单击的位置。所以我采用了COpenGLControl 类并对其进行了一些自定义,以使其适合 2D 图像渲染。这是完整的自定义课程,但如果您不感兴趣,则无需下载。我将解释重要的部分。

如果用户将鼠标放在窗口上然后左键单击,则 用于模拟类似的代码ZoomTool将放大到单击的位置Global mapper portable application

void COpenGLControl::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_fPosX = (float)point.x;
m_fPosY = (float)point.y;
if (nFlags & MK_LBUTTON)
    m_fZoom = 1.1*m_fZoom;
OnDraw(NULL);
CWnd::OnLButtonDown(nFlags, point);
}  

如果用户将鼠标放在窗口上然后右键单击,则用于模拟类似的代码ZoomToolGlobal mapper portable application缩小单击的位置

void COpenGLControl::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_fPosX = (float)point.x;
m_fPosY = (float)point.y;
if (nFlags & MK_RBUTTON)
    m_fZoom = 0.9*m_fZoom;
OnDraw(NULL);
CWnd::OnRButtonDown(nFlags, point);
}  

用于在坐标系上应用变换的代码

void COpenGLControl::OnDraw(CDC *pDC)
{
wglMakeCurrent(hdc,hrc);
// If the current view is perspective...
glLoadIdentity();
glScalef(m_fZoom,m_fZoom,1.0);
glTranslatef(m_fPosX, m_fPosY, 0.0f);
wglMakeCurrent(NULL, NULL);
}  

我在缩放部分没有问题,只是在功能OnLButtonDownOnRButtonDown翻译部分有问题。该程序不会放大或缩小用户的点击位置。
我的意思是我希望函数有这种行为:

例如,当我单击位置 (350,460) 时,该点应该到达窗口的中心,就像ZoomToFullExtent我设置m_fPosXm_fPosY等于零时的函数一样,点 (0,0) 到达窗口的中心
事实上我以为glTranslatef(m_fPosX,m_fPosY,0)将点转换(m_fPosX,m_fPosY)到窗口的中心,但似乎不是真的
你能帮我解决问题并在放大后将点击点转换到窗口的中心吗?

看看我想在图片中模拟什么:

这是全局映射程序,我想缩放到红色圆圈指定的区域:在此处输入图像描述 所以我单击顶部的缩放工具并左键单击图片中的该区域。您会看到该区域位于窗口的中心,
在此处输入图像描述
但在我使用 提供的代码中glTranslatef,单击的位置不会到达窗口的中心。缩放到特定点时转到中心的适当代码是什么?


几乎是最终的答案

从@Andon M.Coleman 那里得到了这个想法,我最终以这种形式编写了代码:

void COpenGLControl::OnSize(UINT nType, int cx, int cy)
{
wglMakeCurrent(hdc, hrc);
CWnd::OnSize(nType, cx, cy);

if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;
oglWindowWidth = cx;
oglWindowHeight = cy;
// Map the OpenGL coordinates.
glViewport(0, 0, oglWindowWidth, oglWindowHeight);

// Projection view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set our current view perspective
glOrtho(-oglWindowWidth/2, oglWindowWidth/2, -oglWindowHeight/2,oglWindowHeight/2, 1, -1);
// Model view
glMatrixMode(GL_MODELVIEW);
wglMakeCurrent(NULL, NULL);
}  

void COpenGLControl::OnDraw(CDC *pDC)
{
// TODO: Camera controls
wglMakeCurrent(hdc,hrc);
glLoadIdentity();
gluLookAt(0,0,1,0,0,0,0,1,0);
glTranslatef(m_fPosX, m_fPosY, 0.0f);
glScalef(m_fZoom,m_fZoom,1.0);
wglMakeCurrent(NULL, NULL);
}  

void COpenGLControl::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (WantToUseZoomTool)
{
    if (nFlags & MK_LBUTTON)
    {
        m_fZoom = 1.1f*m_fZoom;
        m_fZoomInverse = 1/m_fZoom;
        int diffX = (int)(point.x - oglWindowWidth/2);
        int diffY = (int)(point.y - oglWindowHeight/2);
        m_fPosX -= (float)diffX;
        m_fPosY += (float)diffY;
    }
    OnDraw(NULL);
}
CWnd::OnLButtonDown(nFlags, point);
}  

void COpenGLControl::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (WantToUseZoomTool)
{
    if (nFlags & MK_RBUTTON)
    {
        m_fZoom = 0.9f*m_fZoom;
        m_fZoomInverse = 1/m_fZoom;
        int diffX = (int)(point.x - oglWindowWidth/2);
        int diffY = (int)(point.y - oglWindowHeight/2);
        m_fPosX -= (float)diffX;
        m_fPosY += (float)diffY;
    }
    OnDraw(NULL);
}
CWnd::OnRButtonDown(nFlags, point);
}  

diffX如果我这样做,似乎没有必要除以diffY比例因子,图像将完全从场景中消失。代码几乎完美地运行良好,除了稍微远离窗口中心,我认为这是因为在翻译后立即缩放,因为当我删除这些行时:

        m_fZoom = 1.1f*m_fZoom;
        m_fZoomInverse = 1/m_fZoom;  
        m_fZoom = 0.9f*m_fZoom;
        m_fZoomInverse = 1/m_fZoom;  

我看到我点击的每个点都准确地指向中心。有什么帮助来增强代码以消除那些轻微的位移?

4

2 回答 2

1

你应该有足够的信息来解决这个问题,你有你的原点 ( m_fPosX,m_fPosY) 和一个比例因子 (m_fZoom )。当需要放大以光标位置为中心的图像时,您可以计算光标与屏幕中心的距离(例如 CursorPos - WindowDimensions / 2)除以您的比例因子并将其添加到原点。

最初您的比例因子为 1.0,但当您放大/缩小时,它显然会增长。只要您在缩放之前进行翻译,这应该可以工作。

于 2013-08-26T22:52:20.410 回答
0
 m_fZoom = 1.1f*m_fZoom;
    m_fZoomInverse = 1/m_fZoom;  
    m_fZoom = 0.9f*m_fZoom;
    m_fZoomInverse = 1/m_fZoom;

请注意,在 1.1 之后再次放大和缩小时乘以 0.9 不会使您回到原始大小。即 0.9 * 1.1 = 0.99 != 1 (这当然会变得更糟,你继续的时间越长......)。

于 2013-11-05T12:37:32.480 回答