将坐标从一个畸变的坐标系转换到另一个
这个问题最好用一个例子来解释:
http://dl.dropbox.com/u/1013446/distortedcoordinatespace.exe
将小红色方块拖放到右边的小方块内。 它对应于左边大四边形的红色方块。 您还可以拖动左侧大四边形的四个角,以查看它如何占据正方形内空间的扭曲版本。
给定一个正方形的四个点的绝对坐标以及正方形内任意点的坐标,将点的坐标重新映射到一个任意的四边形是很简单的。
我想要的是能够以任意的四边形开始,并能够做同样的事情,将四边形变换为任何其他四边形,但保持点的相对扭曲位置,
所以考虑到2个不规则四边形A和B中的每一个的4个绝对坐标,如何将C点的坐标转换为绝对坐标?
也很有帮助,我会在这里错过任何这些转换将被称为的术语,因为我想更多地了解它们
好吧,我试图实施btilly的解决方案,这是我迄今为止:
#include<complex>
#define cf complex<float>
cf i=sqrt(complex<float>(-1));
cf GetZ(float x,float y)
{
return cf(x)+(cf(y)*i);
}
cf GetPathIntegral(cf p1,cf p2,cf q1,cf q2, int n)
{
cf sum;
for (int index=0;index<=n;index++)
{
cf s=cf(float(index)/float(n));
cf weight;
if (index==0||index==n)
weight=1;
else if(index%2)
weight=4;
else weight =2;
sum+=(((cf(1)-s)*q1)+(s*q2))*(p2-p1)*weight;
}
return sum/cf((3.0*(n-1.0)));
}
在我从这里前进之前,我想确保我目前为止是......
另外,这一段让我困惑了一下:
好的,我们可以做路径积分。 那是什么价值? 那么假设我们在我们地区的某个地方有一个随机点z0 = x + iy。 假设f(z)在路径上定义。 然后Cauchy积分公式说明f(z)/(2 *π* i *(z-z0))的区域周围的积分(这是我们知道如何做的4个分段积分的总和)是一个真正的很好的功能,这将匹配我们在边界上的原始功能。
函数做了什么?
(我的第一个传球是一个自然而然的表达式的复杂推导,但后来我意识到有一个更好的解决方案,如果我在过去的20年中使用了复杂分析,那么我早就会记得这一点。)
正确的做法是应用Cauchy积分公式。 有了这个,你可以将任何多边形映射到任何其他多边形。 如果多边形不是自相交的,则它将边界发送到边界,内部发送到内部。 该映射也将具有共形的优异属性,这意味着角度得以保留。 我的意思是,如果一对曲线在你的区域相交,那么它们将被映射到一对以相同角度相交的曲线。 (埃舍尔的许多绘图都是基于共形映射的。)
足够的炒作。 你怎么做呢? 我会解释它,假设你对复杂分析一无所知。 我将使用一些微积分术语,但即使您根本不知道任何微积分,您也应该能够遵循我的指导。 由于我假设这么少,所以解释必须很长。 我很抱歉。
真实平面中的每个点(x, y)
都可以看作一个复数z = x + iy
。 我们可以使用通常的代数规则和i * i = -1
的事实来添加和乘上复数。 此外注意1 = (x + iy) * (x - iy)/(x2 + y2)
所以如果我们让1/z = (x - iy)/(x2 + y2)
因此我们拥有所有通常的算术规则。
但我们可以做得比这更好。 我们可以做微积分。 特别是我们可以在曲线周围进行路径积分。 沿着曲线的函数的积分是该函数在该曲线上的点的加权平均。 你可以阅读如何做到这一点。 但在这种情况下,如何做到这一点。
假设起始区域具有角落P1, P2, P3, P4
。 区域周围的路径由四条线段(P1, P2), (P2, P3), (P3, P4), (P4, P1)
。 我会谈谈如何处理第一条线段。 其他人是相似的。
f(z)
在(P1, P2)
上的路径积分是f((1-s)P1 + sP2)(P2 - P1)
从0到1的积分。 为了评估积分,最简单的事情就是使用辛普森规则进行数值积分。 要做到这一点,选择一个奇数n
并为值s = 0, 1/n, 2/n, ..., (n-1)/n, 1
分配他们权重模式1, 4, 2, 4, 2, ..., 2, 4, 1
。 (终点为1,其他所有部分在4和2之间交替)。现在为每个点计算f((1-s)P1 + sP2)(P2 - P1)
,乘以权重,并将它们加在一起。 然后除以魔法值3 * (n-1)
。 结果大约是你的积分。 (随着n
增加,这个近似值的误差是O(1/n4)
。在你的情况下,如果你取n = 21
那么近似值应该足够好以便将像素映射到正确的像素,除了边界附近的一些像素,让它稍大一点,问题区域会变小,在边缘你需要一边的像素数的倍数,以使错误变小。)
好的,我们可以做路径积分。 那是什么价值? 那么假设我们在我们地区的某个地方有一个随机点z0 = x + iy
。 假设f(z)
在路径上定义。 然后Cauchy积分公式说明f(z)/(2 * π * i * (z - z0))
区域周围的积分(这是我们知道如何做的4个分段积分的总和f(z)/(2 * π * i * (z - z0))
是一个真正的很好的功能,将与我们在边界上的原始功能相匹配。 我不会涉及所有关于它的“非常好”的事情,但我上面关于共形的描述就是其中的一部分。
现在什么功能f
我们如何使用? 那么假设我们的地区正在映射到角落Q1, Q2, Q3, Q4
。 我们希望第一个路径片映射到第二个路径片。 所以我们希望f((1-s)P1 + sP2)
为(1-s)Q1 + sQ2
。 这告诉我们如何计算f
在所有我们需要做我们的积分点。
现在,你问,你如何扭转它? 这很简单。 只需扭转两个多边形的角色,并计算逆向变换! 这带来了非常好的单元测试。 你应该定义几个奇怪的区域,在中间选择一个点,并验证如果你从第一个映射到第二个,并且再次返回,你会接近你开始的位置。 如果你通过了这个测试,那么你可能没有犯错。
最后,我做出的一般多边形声明呢? 那么我们将我们的路径定义为我们线性遍历的四部分。 更高程度的多边形只有更多的路径,否则计算完全以相同的方式完成。
找到了解决方案。 我不得不说,这比我预期的要复杂得多:
假设一个正方形或四边形有四个角落:
AB
CD
你需要一个插值因子:xt表示x轴,yt表示y轴
如果你定义了一个线性插值公式:
lerp(j,k,t)
{
return (t*(k-j))+j;
}
ABCD quad内的点p被定义为:
p.x=lerp(lerp(a.x,b.x,xt),lerp(c.x,d.x,xt),yt)
和
p.y=lerp(lerp(a.y,c.y,yt),lerp(b.y,d.y,yt),xt)
那么你需要定义的值是xt和yt
xt =((2 * cx * ay) - (dx * ay) - (2 * ax cy)+(bx cy) - (cx * by)+(ax * dy) - (ay * px)+(cy * px)+(by px) - (dy px)+(ax py) - (bx py) - (cx * py)+(dx * py)-sqrt(-4 *((cx * ay) - (dx * ay) - (ax * cy)+(bx * cy) - (cx * by)+(dx * by)+(ax dy) - (bx dy))*((cx * ay) - (ax * cy) - (ax * px)+(cy * px)+(ax * py) - (cx * py))+((-2 * cx ay)+(dx ay)+(2 * ax cy) - )+(cx * by) - (ax * dy)+(ay * px) - (cy * px) - (by * px)+(dy * px) - (ax * py)+(bx * py)+ (cx * py) - (dx py))^ 2))/(2((cx * ay) - (dx * ay) - (ax * cy)+(bx * cy) - dx * by)+(ax * dy) - (bx * dy)))
一旦你有了
yt=(p.x-lerp(a.x,b.x,('xt')))/(lerp(c.x,d.x,('xt'))-lerp(a.x,b.x,('xt')))
链接地址: http://www.djcxy.com/p/64011.html
上一篇: transforming coordinates from one distorted coordinate system to another