2

这个问题最好用一个例子来解释:

http://dl.dropbox.com/u/1013446/distortedcoordinatespace.exe

将红色小方块拖放到右侧小方块内。它对应于左侧大四边形中的红色正方形。您还可以拖动左侧大四边形的 4 个角,以查看它如何占据正方形内空间的扭曲版本。

给定正方形 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)。然后柯西积分公式说,f(z)/(2 * π * i * (z - z0)) 的我们区域周围的积分(这是我们知道如何做的 4 个分段积分的总和)确实是很好的函数,它将与我们在边界上的原始函数相匹配。

该功能究竟做了什么?

4

2 回答 2

3

(我的第一遍是对一个看起来很自然的公式的复杂推导。但后来我意识到有一个更好的解决方案。如果我在过去 20 年使用复杂分析,我会更早记得。)

正确的方法是应用柯西积分公式。有了这个,您可以将任何多边形映射到任何其他多边形。如果多边形不自相交,它会将边界发送到边界,将内部发送到内部。该映射还将具有保形的优良特性,这意味着角度被保留。我的意思是,如果一对曲线在您的区域相交,那么它们将被映射到一对以相同角度相交的曲线。(埃舍尔的许多绘图都是基于保形映射。)

足够的炒作。你怎么做呢?我会解释它,假设你对复杂分析一无所知。我将使用一些微积分术语,但即使您根本不知道任何微积分,您也应该能够按照我的指示进行操作。由于我假设很少,因此解释必须有点长。我很抱歉。

实平面上的每一点(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)over的路径积分是 的 0 到 1 的积分。要评估该积分,最简单的方法是使用辛普森法则进行数值积分。为此,请选择一个奇数,并为这些值分配模式中的权重。(端点是 1,其他所有点在 4 和 2 之间交替。)现在计算每个点,乘以权重,然后将它们加在一起。然后除以魔法值。结果大约是您的积分。(随着增长,这个近似值的误差是。在你的情况下,如果你采取(P1, P2)f((1-s)P1 + sP2)(P2 - P1)ns = 0, 1/n, 2/n, ..., (n-1)/n, 11, 4, 2, 4, 2, ..., 2, 4, 1f((1-s)P1 + sP2)(P2 - P1)3 * (n-1)nO(1/n4)n = 21那么近似值应该足以将像素映射到正确的像素,除了边界附近的一些像素。再大一点,问题区域就会变小。就在边缘,您需要一侧像素数的倍数以使误差变小。)

好的,所以我们可以进行路径积分。那有什么价值呢?好吧,假设我们在我们所在地区的某个地方随机取一个点。假设 在路径上定义。然后柯西积分公式说我们区域周围的积分(这是我们知道如何做的 4 个分段积分的总和)是一个非常好的函数,它将与边界上的原始函数相匹配。我不会深入讨论它的所有“非常好的”事情,但我上面所说的关于保形的内容就是其中的一部分。z0 = x + iyf(z)f(z)/(2 * π * i * (z - z0))

现在我们使用什么功能f?那么假设我们的区域被映射到一个有角的区域。我们希望第一个路径片段映射到第二个路径片段。所以我们想成为。这告诉我们如何计算积分所需的所有点。Q1, Q2, Q3, Q4f((1-s)P1 + sP2)(1-s)Q1 + sQ2f

现在,你问,你如何扭转它?这很简单。只需反转两个多边形的作用,并计算反向变换!这带来了一个非常好的单元测试。您应该定义几个奇怪的区域,在中间选择一个点,并验证如果您从第一个映射到第二个然后再返回,您是否会接近您开始的位置。如果您通过了该测试,那么您可能没有犯任何错误。

最后,我提出的一般多边形声明呢?好吧,我们将路径定义为线性遍历的四个部分。更高阶的多边形只是在其路径上有更多片段,但除此之外,计算以完全相同的方式完成。

于 2011-03-24T01:46:12.250 回答
-1

找到了解决方案。我不得不说,这比我预期的要复杂得多:

假设正方形或四边形有四个角:

AB
CD

您需要一个插值因子:xt 表示 x 轴,yt 表示 y 轴,这样

如果你定义一个线性插值公式:

lerp(j,k,t)
{
     return (t*(k-j))+j;
}

ABCD四边形内的点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) - (ay* px) + (cy* px) + (ax* py) - (cx* py)) + ((-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))^2))/(2 ((cx* ay) - (dx* ay) - (ax* cy) + (bx* cy) - (cx* by) + (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')))
于 2011-03-24T05:18:50.113 回答