如何编写函数将画布上的点映射到实际平面上的点
我正在用Python写一个简单的Mandelbrot可视化程序,显示在pygame的屏幕上。对于600乘600的屏幕上的每一个像素,我都在判断这个像素(x, y)作为一个复数,是否属于Mandelbrot集合。
问题是,我从(0, 0)开始,遍历到(600, 600),而大部分区域其实都不在这个集合里。所以我加了一个缩放因子来放大,但我现在只是在绘制右上角的部分。我想找到一种方法,让我的绘图总是围绕0+0i这个点居中。
我想做的是找到一种方法,把这个600平方像素的画布映射到实际的坐标平面上,x轴的范围是[-2, 2],y轴的范围是[2, -2]。这样的话,比如复数0+0i就会映射到屏幕上的(300, 300)这个位置。这样,我的绘图就总是能保持居中。
3 个回答
其实我会采取一种更灵活的方法,写代码时让它支持比较随意的映射。不过如果你想要严格按照你的要求来做,可以试试下面的代码:
x = (float(pix_x) + 0.5 - 300.0) / 150.0
然后对 y
也做同样的处理。这段代码把每个像素看作是屏幕上那对点的中心,但把像素的角落映射到 (+-2, +-2) 的位置。这是把整个视口映射到复平面上一个正方形的最“正确”的方法。不过这样做的一个缺点是,你可能会错过一些重要的数字,比如0、实数线或者虚数线。
class Mapper:
def __init__(self, old_ul, old_lr, new_ul, new_lr):
self.old_ul = old_ul
self.old_lr = old_lr
self.new_ul = new_ul
self.new_lr = new_lr
self.old_diff = Point(old_lr.x - old_ul.x,
old_ul.y - old_lr.y)
self.new_diff = Point(new_lr.x - new_ul.x,
new_ul.y - new_lr.y)
def map(self, pt):
nx = (self.old_lr.x+pt.x) * (self.new_diff.x / self.old_diff.x) + self.new_ul.x
ny = (self.old_ul.y+pt.y) * (self.new_diff.y / self.old_diff.y) + self.new_lr.y
return Point(nx, ny)
def main(args):
pixelToReal = Mapper(Point(0, 0), Point(600, 600), Point(-2, 2), Point(2, -2))
realToPixel = Mapper(Point(-2, 2), Point(2, -2), Point(0, 0), Point(600, 600))
print(pixelToReal.map(Point(300,300))) # prints 0.0,0.0
print(realToPixel.map(pixelToReal.map(Point(300,300)))) # prints 300,300
for x in range(0,630, 30):
for y in range(0,630, 30):
print(pixelToReal.map(Point(x,y)))
Mapper的构造函数需要四个参数:原始的左上角和右下角坐标,以及新的左上角和右下角坐标。Mapper.map()这个方法的作用是把一个点从原来的空间转换到新的空间里。
你想为你的数据创建一个窗口。这个窗口的宽度是600像素,高度也是600像素。像素坐标的范围是(0, 0)到(600, 600)。你可以这样做:
Point coordFromPixelLocation (pixelX, pixelY, pixelWidth, pixelHeight, minCoordX, maxCoordX, minCoordY, maxCoordY)
{
xPercent = pixelX / pixelWidth;
yPercent = pixelY / pixelHeight;
newX = minCoordX + (maxCoordX - minCoordX) * xPercent;
newY = minCoordY + (maxCoordY - minCoordY) * yPercent;
return Point (newX, newY);
}
这里的pixelX和pixelY是你想要转换到更小范围的像素坐标。pixelWidth和pixelHeight分别是你窗口的宽度和高度。minCoordX/Y和maxCoordX/Y是从(-2,-2)到(2,2)的值。