最好用一个例子解释问题:
http://dl.dropbox.com/u/1013446/distortedcoordinatespace.exe
将小红方拖放到右边的小方块内。 它对应于左侧大四边形的红色方块。 你也可以拖动左边大四边形的四个角来看它是如何占据广场内空间的扭曲版本的。
给定正方形的4个点的绝对坐标和正方形内任意点的坐标,将点的坐标重新映射到任意四边形是很简单的事情。
我想要的是能够从任意四边形开始,并且能够做同样的事情,将四边形转换为任何其他4边形状,但保持点的相对扭曲位置,
所以给定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积分公式表示 我们地区的整体(这是 4个分段积分的总和 我们知道怎么做)f(z)/(2 *π* i *(z - z0))是一个非常好的功能,将匹配我们的原始 在边界上发挥作用。
该功能究竟做了什么?
答案 0 :(得分:3)
(我的第一步是对此的自然看似公式的复杂推导。但后来我意识到有一个远远好得多的解决方案。如果我在过去20年中使用过复杂分析,我会记得更早。)
执行此操作的正确方法是应用Cauchy Integral Formula。通过此,您可以将任何多边形映射到任何其他多边形。如果多边形不自相交,它将边界发送到边界,内部发送到内部。映射还具有优良的属性conformal,这意味着角度得以保留。我的意思是,如果一对曲线在您的区域中相交,那么它们将被映射到以相同角度相交的一对曲线。 (埃舍尔的许多图纸都是基于共形映射。)
足够炒作。你怎么做呢?我会解释一下,假设你对复杂的分析一无所知。我将使用一些微积分术语,但即使你根本不知道任何微积分,你也应该能够遵循我的指示。由于我假设很少,所以解释必须有点长。对不起,我很抱歉。
真实平面中的每个点(x, y)
都可以视为复数z = x + iy
。我们可以使用通常的代数规则和i * i = -1
这一事实来添加和复用复数。另外请注意1 = (x + iy) * (x - iy)/(x2 + y2)
,如果我们允许1/z = (x - iy)/(x2 + y2)
,我们可以分开。因此,我们拥有所有通常的算术规则。
但我们可以做得更好。我们可以做微积分。特别是我们可以绕曲线做path integrals。沿曲线的函数的积分是该函数在该曲线中的点上的一种加权平均值。您可以阅读一般如何操作。但在这种情况下,这是如何做到的。
假设起始区域有角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的积分。要评估该积分,最简单的方法是使用Simpson's Rule进行数值积分。要执行此操作,请选择奇数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 Integral Formula表示我们区域周围的积分(这是我们知道怎么做的4个分段积分的总和)f(z)/(2 * π * i * (z - z0))
是一个非常好的函数,它将匹配我们原来的函数边界。我不会介绍所有关于它的“非常好”的事情,但我上面提到的conformal是其中的一部分。
现在我们使用什么功能f
?假设我们的区域被映射到角落为Q1, Q2, Q3, Q4
的区域。我们希望第一个路径块映射到第二个路径段。因此,我们希望f((1-s)P1 + sP2)
为(1-s)Q1 + sQ2
。这告诉我们如何在我们需要完成积分的所有点上计算f
。
现在,你问,你怎么扭转它?这很简单。只需反转两个多边形的作用,并计算反向变换!这带来了非常好的单元测试。您应该定义几个奇怪的区域,在中间选择一个点,并验证如果您从第一个映射到第二个,然后再返回到最近您开始的位置。如果你通过了那个测试,那么你可能没有犯错。
最后我的一般多边形声明怎么样?好吧,我们将路径定义为线性遍历的四个部分。更高度的多边形在其路径上只有更多的碎片,但是否则计算以完全相同的方式完成。
答案 1 :(得分:-1)
找到了解决方案。我不得不说,它比我预期的要复杂得多:
假设正方形或四边形有四个角:
AB
CD
你需要一个插值因子:x轴为xt,y轴为yt,所以
如果定义线性插值公式:
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 * c.x * a.y) - (d.x * a.y) - (2 * a.x c.y)+(b.x c.y) - (c.x * b.y)+(a.x * d.y) - (a.y * p.x)+(c.y * p.x)+ (b.y p.x) - (d.y p.x)+(a.x p.y) - (b.x p.y) - (c.x * p.y)+(d.x * p.y) - Sqrt(-4 *((c.x * a.y) - (d.x *) a.y) - (a.x * c.y)+(b.x * c.y) - (c.x * b.y)+(d.x * b.y)+(a.x d.y) - (b.x d.y))*((c.x * a.y) - (a.x * c.y) - (ay * px)+(cy * px)+(ax * py) - (cx * py))+(( - 2 * cx ay)+(dx ay)+(2 * ax cy) - (bx c.y)+(c.x * b.y) - (a.x * d.y)+(a.y * p.x) - (c.y * p.x) - (b.y * p.x)+(d.y * p.x) - (a.x * p.y)+(b.x * p.y)+ (c.x * p.y) - (d.x p.y))^ 2))/(2 ((c.x * a.y) - (d.x * a.y) - (a.x * c.y) +(b.x * c.y) - (c.x * b.y)+(d.x * b.y)+(a.x * d.y) - (b.x * d.y)))
一旦你有了
yt=(p.x-lerp(a.x,b.x,('xt')))/(lerp(c.x,d.x,('xt'))-lerp(a.x,b.x,('xt')))