图片浏览器开发日志-11(图片动画显示之开关门算法实现)

按:像PowerPoint那样对图片进行显示,可以增强显示效果,使图片显示比较有趣。准备将PowerPoint中的典型动画显示都实现。本文将实现一个简单的开个门效果的动画显示。

效果示例和算法的推导

效果如图所示:动画开始后,画面像一扇门一样关闭和打开。
在这里插入图片描述
在这里插入图片描述

下面进行算法的推导。
开个门的实际情形就是门的一端位置不变,而其余部分,逐渐从横向和纵深两个方向变短,门的上下边延长线交于视点。根据透视的原理,可以得到下面的几何图示。
在这里插入图片描述Vp 为灭点, ABCD为原始图像(关闭的门),A’B’CD 为转动的图像,我们只要计算出A’B’ 的长度以及A’D子平面ABCD上的正投影的长度,就可以利用我们上一节的简单透视函数计算出A’B’CD在ABCD上图像(即投影或者眼睛看到的效果)。我们假定VP到ABCD平面的距离是Vd,根据相似三角形以及角B’CB(两个面的夹角,并非是这个角,我们暂且用它表示!!),可以得到
A’B = AB*(Vd-ADsin(角B’CB))/Vd
DJ = AD
Cos(角B’CB)

有了这两个数据,我们就可以得到转动到某个角度的图像,适当循环计算得到一些列图像。
补充说明:平面VpDC和ABCD的夹角是图像转到90度时对应的透视图中的最大角度。

示例代码

根据上述公式得到函数如下:

// src: the source image
// bOpenDoor: close door or open door demo 
// times: displaying times
// interval: interval between the two displaying of the image, ms 
// dir: LTDU , the four directions
// ctrWnd: the CWnd* of the control in which the image will be displayed
void CImgShape::showPerspectiveImage(CImage &src, bool bOpenDoor, int times, float interval, CString dir, CWnd *ctrWnd)
{
    
    
	int iTopL;
	CImage dst;
	CRect rect;
	ctrWnd->GetClientRect(&rect);
	CDC* pDc = ctrWnd->GetDC();
	int H, W;
		
	if (dir == "U" || dir == "D") {
    
    
		W = src.GetWidth();
		H= src.GetHeight();
	}
	else {
    
    
		H = src.GetWidth();
		W = src.GetHeight();
	}

	float maxRotateAngle;
	int tanVal = 6;// i.e. Vd explained above 
	maxRotateAngle = atan(tanVal);// the maximum angle between the square mentioned above
	float viewDistance = W/2 * tanVal;//tan(maxRotateAngle)

	float step = maxRotateAngle/times;

	for (int i = 0; i < times; i++) {
    
    
		float rotateAngle = step*i;
		if (!bOpenDoor) {
    
    
			rotateAngle = step * (times - i - 1);
		}
		int th = cos(rotateAngle)*H;
		int tw= sin(rotateAngle)*H;
		iTopL = (viewDistance - tw)/ viewDistance*W;
		perspectiveImage(src, th, iTopL, dir, dst);//refer to the previous chapter please
		
		
		dst.Draw(pDc->m_hDC,
			rect.left,
			0,
			rect.Width(),
			rect.Height());
		Sleep(interval);
	}
	ctrWnd->ReleaseDC(pDc);

}

说明:上述函数中支持四个方向的旋转,因此HW的值做了根据参数 dir 做了相应的调整。

调用示例:

CImgShape is;
	is.showPerspectiveImage(m_pImgTabDlg->m_myImg, !false, 40, 25, L"R", m_pImgTabDlg->GetDlgItem(IDC_STATIC_IMG2));

(上述边角关系是本人简单推断的结果,并没有参照有关资料,可能会有一些疏漏,但是基本效果经过实际检验,好像是正确的。恳请高手指点)

猜你喜欢

转载自blog.csdn.net/Uman/article/details/105474832