广义反射之哈哈镜原理

图形变换在Visual C++.NET图形图象编程中占有重要地位,它的重要应用之一——美术图案设计。而哈哈镜反射可以说可在一定程度上激发灵感,同时,也可编成游戏,不失为一种较好的创意,可以开发人(主要是幼儿)的想象力。

首先看一下平面镜反射的情况。为了方便理解,我们可以先简化为2维图形关于直线和点的对称变换。
例如:四边形以Y轴为对称轴做镜像变换:
程序设计
Void CMyView()
{static double x1[]={0.0,100.0,150.0,100.0,0.0};
static double y1[]={0.0,50.0,50.0,10.0,0.0};
static double x2[5],y2[5];
int i;
float x0,y0;
CClientDC *pdc=new CClientDC(this);
CPen pen;
Pen.Createpen(PS_SOLID,1,RGB(0,0xff,0xlf));
CPen *oldpen=(CPen*)pdc->SelectObject(&pen);
Pdc->MoveTo(scx(0),scy(-ymax/2));
Pdc->LineTo(scx(0),scy(ymax/2));
Pdc->MoveTo(scx(-x max/2),scy(0.0));
Pdc->LineTo(scx(xmax/2),scy(0.0));
for(i=0;i<=3;i++)
{ Pdc->MoveTo(scx(x1[i]),scy(y1[i]));
Pdc->LineTo(scx(x1[i+1]),scy(y1[i+1]));
}
Pdc->MoveTo(scx(x0),scy(0.0));
Pdc->LineTo(scx(0.0),scy(y0));
for(i=0;i<=4;i++)
{ taisho_y();
x2[i] =affinex(scx(x1[i]),scy(y1[i]),1.0);
y2[i] =affiney (scx(x1[i]),scy(y1[i]),1.0);
}
for(i=0;i<=3;i++)
{ Pdc->MoveTo(scx(x2[i]),scy(y2[i]));
Pdc->LineTo(scx(x2[i+1]),scy(y2[i+1]));
}
Pdc->DeleteDC();
}
对于广义对称轴为曲线的情况,为了方便实现,权且限制为连续函数的曲线,无非分为封闭曲线和非闭合曲线:对于闭合曲线,在考虑到其相对于对象图形的大小和位置,可将其看作两条非闭合曲线的组合。我们只需讨论非闭合连续函数曲线的情况。

对于非闭合连续函数曲线来说,我们可以将其回归本质——点的组合,通过对曲线上点的遍历,将其分解为具体算法的组合即可(由计算机的强大运算功能,很容易实现)。对于每一点来说,我们只需找到其在这点对应的斜率(因为我们事先假设其是连续函数,故斜率一定存在)即可,然后由此作此点的法线,看是否过给定的要做对称的对象图形(以后均定义为对象),若有交点只需将交点集合(可能是点或线段)作关于此点的对称即可(相当于一线段做关于以其一条垂线为对称轴的对称,很容易实现)。这样遍历完整条曲线后,其广义对称图形就出炉了。

这条作为广义对称轴的曲线实际根据其性质和对象的性质及它们相对的大小和位置,有时只有部分点可作有关对象(对应线段或点)的对称变换,我们成这样的点为有效点。相邻的有效点共同组成一段有效的光一对衬轴。这样有效广义对称轴的个数决定了对象扭曲对称后像的个数。


这只是在2维图形上求关于以给定连续曲线的广义对称图形,还不能达成哈哈镜的效果,我们可以将其扩展到3维空间,这时就有了哈哈镜的效果了。即选定曲面和三维物体,任定相对大小和位置下求其视觉效果。
我们不妨先简单的设想一下球面哈哈镜下和由曲线平移扩展成的平面镜下的3D物体的实像。再由这两种基本的哈哈镜扩展到任意连续曲面作为面镜。

如果将整个过程实现为软件,相信一定会有意想不到的惊喜。

山东大学微软技术俱乐部技术部
杜华睿
[返回][关闭]