使用Viewport缩放 [英] Zooming using Viewport

查看:246
本文介绍了使用Viewport缩放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一些旧代码,这些代码在使用设备上下文从CDialog继承的对话框中绘制图片。我被要求允许用户放大图片。



我抓住图片中的鼠标左键并使用鼠标左键点击的坐标,我认为是在客户端坐标中,设置缩放图片应居中的点。每次点击都会将图片放大1.1倍。



我遇到的问题是这个中心点正在漂移。缩放图片越多,缩放点变得偏离中心越多。当我将缩放系数设置为1.0时,它似乎工作正常,并且图片集中在鼠标左键点上。



我无法看到我出错的地方,我尝试过各种方式改变我的方法,但我无法做到这一点。

我已经复制了我认为与此相关的位,整个方法似乎太大而无法粘贴在这里。

我添加到原始代码中的唯一位(工作正常)是位标记为ZOOMING,m_zoom_factor,m_new_offset_x和m_new_offset_y。



Hi, I am working on some old code that draws a picture in a dialog that inherits from CDialog using the device context. I have been asked to allow the user to zoom in on the picture.

I am catching the left mouse click in the picture and using the coordinates of this left mouse click, which I presume are in the client coords, to set the point at which the zoomed picture should be centred. Each click magnifies the picture by a factor of 1.1.

The problem I have is that this centre point is drifting. The more the picture is zoomed, the more off-centre the zoom point becomes. When I set the zoom factor to 1.0 it seems to work fine, and the picture centralises on the point of the left mouse click.

I cannot see where I am going wrong, I have tried changing my method in every way I can but I cannot get this right.
I have copied the bit which I think is relevant here, the whole method seems to be too big to paste here.
The only bits I have added to the original code (which worked fine) are the bit labelled ZOOMING , m_zoom_factor, m_new_offset_x and m_new_offset_y.

GetClientRect(&client_rect);
float viewport_width_offset = 40.0;
float viewport_height_offset = 40.0;
viewport_width = client_rect.Width() - viewport_width_offset;
viewport_height = client_rect.Height() - viewport_width_offset;

// ZOOMING
double move_picture_centre_x = 0.0;
double move_picture_centre_y = 0.0;
if(m_zooming)
{
         m_zoom_factor *= 1.1;
	// first, map the zoom point (which is in client coords) to viewport coords
	m_zoom_point.x = m_zoom_point.x - viewport_width_offset/2.0;
	m_zoom_point.y = m_zoom_point.y - viewport_height_offset/2.0;

	// second, translate the zoom point to the centre of the viewport and zoom it
	move_picture_centre_x = m_zoom_factor * (viewport_width/2.0 - m_zoom_point.x);
	move_picture_centre_y = m_zoom_factor * (viewport_height/2.0 - m_zoom_point.y);

	m_new_offset_x += move_picture_centre_x;
	m_new_offset_y += move_picture_centre_y;
		
	m_zooming = false;
}

// set mapping mode to allow for x and y axes to be scaled and set independently
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetViewportExt(viewport_width * m_zoom_factor, -viewport_height * m_zoom_factor);
pDC->SetViewportOrg(viewport_width_offset/2.0 + m_new_offset_x, client_rect.Height() - viewport_height_offset/2.0 + m_new_offset_y);	 



我花了将近两天的时间无处可去:(


I've spent nearly two days getting nowhere on this :(

推荐答案

在我看来(虽然我没有运行你的代码)错误在行:

In my opinion (although I haven't run your code) the error is in the lines:
move_picture_centre_x = m_zoom_factor * (viewport_width/2.0 - m_zoom_point.x);
move_picture_centre_y = m_zoom_factor * (viewport_height/2.0 - m_zoom_point.y);



这里你不想乘以缩放因子,因为这是你想要移动视口的数量,你的鼠标坐标和视口中心都是在视图端口坐标中。



然后在更改视口端口范围时,必须对视口端口应用另一个校正。当您增加视口端口范围时通过x因子,之前显示在视口中心的图像细节将移动到右上角(因为您的视图端口o rigin在左下角)。要将其移回中心,您必须将视图端口原点移动金额:


Here you don't want to multiply with the zoom factor as this is the amount you want to move your view port and both, your mouse coords and the view port center are both in view port coordinates.

Then you have to apply yet another correction to the view port origin when you change the view port extents. When you increase the view port extents by a factor of x then the image detail that was formerly shown in the center of the view port will move to the upper right (because your view port origin is in the lower left corner). To move it back to the center you have to shift the view port origin by the amount:

m_new_offset_x -= (m_zoom_factor-1.0) * (viewport_width/2.0 - oldViewPortOrg_x)
m_new_offset_y -= (m_zoom_factor-1.0) * (viewport_height/2.0 - oldViewPortOrg_y)



这应该可以解决问题。



请注意,在代码的第5行中有一点复制粘贴错误,该错误应以view_port_height_offset结尾。 (只要两个偏移量相同,都不会做太多。)



您可能还想尝试一些不同的行为。不要将点击点带到窗口的中心,而是保留您在鼠标下单击的图像细节。这样你可以在同一个地方多次点击放大到某个位置。



还有另一个评论:还有另一种方法来计算新的视口来源和范围:

- 首先计算鼠标下点的图像坐标

- 然后计算该点应出现在窗口中的位置(中心或鼠标坐标)

- 确定新的缩放系数

- 然后根据上述步骤计算的坐标计算变换。这通常会导致代码更容易理解


That should do the trick.

Note that you have a little copy-paste error in line 5 of your code, which should end in view_port_height_offset. (Doesn't do much as long as both offsets are the same).

You might also want to try a somewhat different behaviour. Don't bring the click point to the center of the window, but keep the image detail that you click on under the mouse. That way you can click multiple times on the same spot to zoom into a certain location.

And yet another comment: There is another way of computing the new view port origin and extents:
- First calculate the image coordinates of the point under the mouse
- Then calculate where that point should appear in your window (center or mouse coordinates)
- Determine the new zoom factor
- Then calculate the transformation from the coordinates calculated in the above steps. That generally leads to code that easier to understand


这篇关于使用Viewport缩放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆