扭曲网格中的坐标

发布于 2024-09-03 09:35:42 字数 728 浏览 4 评论 0 原文

我在 2D 系统中有一个网格,就像前图中的网格一样,其中给出了所有点 A、B、C、D、A'、B'、C'、D'(这意味着我知道各自的 x 和 y)坐标)。

我需要计算网格扭曲时A(新)、B(新)、C(新)和D(新)的x和y坐标(以便A'移动到A'(新), B' 移动到 B'(新),C' 移动到 C'(新),D' 移动到 D'(新)。

扭曲的发生方式是,网格线均被分成等长的子线(这意味着,例如 AB 被分成等长的 5 个部分 |AB|/5 和 A(new)B( new)被分成5个等长的部分|A(new)B(new)|/5)。

扭曲是通过 Sandy 3D Flash 引擎 的 DistortImage 类完成的。 (我的实际任务是使用此类扭曲图像,其中手柄不位于图像的角落 就像在这个演示中,但在其中的某个地方)。

替代文本 http://www.gefragt.de/ Distorted_grid.png

I have a grid in a 2D system like the one in the before image where all points A,B,C,D,A',B',C',D' are given (meaning I know the respective x- and y-coordinates).

I need to calculate the x- and y-coordinates of A(new), B(new), C(new) and D(new) when the grid is distorted (so that A' is moved to A'(new), B' is moved to B'(new), C' is moved to C'(new) and D' is moved to D'(new)).

The distortion happens in a way in which the lines of the grid are each divided into sub-lines of equal length (meaning for example that AB is divided into 5 parts of the equal length |AB|/5 and A(new)B(new) is divided into 5 parts of the equal length |A(new)B(new)|/5).

The distortion is done with the DistortImage class of the Sandy 3D Flash engine. (My practical task is to distort an image using this class where the handles are not positioned at the corners of the image like in this demo but somewhere within it).

alt text http://www.gefragt.de/distorted_grid.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

拒绝两难 2024-09-10 09:35:42

我无法给您完整的答案,但我很确定您会在 Paul S. Heckbert 的“纹理映射和图像变形基础”中找到它:http://www.cs.cmu.edu/~ph/texfund/texfund.pdf (在附录中包含源代码适用于所有类型的映射)

I can't give you the full answer, but I am pretty sure you will find it in "Fundamentals of Texture Mapping and Image Warping" by Paul S. Heckbert: http://www.cs.cmu.edu/~ph/texfund/texfund.pdf (in the appendix it contains source code for all kinds of mappings)

荒人说梦 2024-09-10 09:35:42

对我来说这看起来像是一个线性变换。我们知道这一点是因为原始图中的任何一条线也是转换后图中的一条线(这对于您提供的演示并不总是正确的,但如果您遵循您在问题中给出的方向并且不允许凹顶点,则将是正确的) 。我确实相信 AS3 内置了对变换矩阵操作的支持。如果没有,您可以自己实施。

[ x' ]  =   [ a b ] x [ x ]
[ y' ]      [ c d ]   [ y ]

这些是矩阵。第一个是向量(你的最终点),它等于某个 2x2 矩阵乘以向量(你的原始点)

如果你不熟悉矩阵乘法,这可以简化为:

x' = a*x + b*y
y' = c*x + b*y

任何线性变换都可以是由 a、b、c 和 d 的二乘二矩阵表示。为它们中的每一个选择数字,你就得到了一个线性变换。那么如何找到 a、b、c 和 d 的值来得出您的值呢?

对于四个未知数,您需要四个方程。如果您查看上面的方程,您会发现一个点(“向量”)及其变换将为您提供两个方程。所以...我们需要两点。正如您稍后将看到的,以未变换形式 (m,0) 和 (0,n) 选取点(即一个沿 x 轴,另一个沿 y 轴)会很有用。

在您的示例中,这些很容易找到!他们是 B 和 D(如果 A 或 C 是​​您的原籍)!

我将使用稍微不同的符号:“素数”表示点的转换版本。

B => B'
B_x => B'_x
B_y => B'_y

如果你知道B和D的前后坐标,你就可以找到你的变换矩阵a,b,c,d。

设置方程:

B'_x = a * B_x + b * B_y
B'_y = c * B_x + d * B_y

D'_x = a * D_x + b * D_y
D'_y = c * D_x + d * D_y

现在,假设 B 是 x 轴点,形式为 (B_x,0)。假设 D 是 y 轴点,形式为 (0,D_y)。如果相反,则交换它们。在这里,我们假设您的原点是 A = (0,0),就像在大多数 Flash 应用程序中一样。

设置 B_y = 0 和 D_x = 0,我们得到:

B'_x = a * B_x + b * 0
B'_y = c * B_x + d * 0
D'_x = a * 0   + b * D_y
D'_y = c * 0   + d * D_y

使用代数的力量,我们发现:

a = B'_x / B_x
c = B'_y / B_x
b = D'_x / D_y
d = D'_y / D_y

所以,简而言之:

如果你知道原始点:(原始 x 和 y 轴上的顶点)

M = (M_x, 0)
N = (0  , N_x)

及其变换/扭曲点

M' = (M'_x, M'_y)
N' = (N'_x, N'_y)

(这样 M => M' 和 N => N')

然后计算并存储这四个变量:

a = M'_x / M_x
b = N'_x / N_y
c = M'_y / M_x
d = N'_y / N_y

最后:

(x, y)  =>  ( a*x + b*y , c*x + d*y )

编辑:好的,我完成了一些任意角手柄转换,并意识到我跳了当我假设你的变换是线性的时得出结论。上面的方程仅在两种情况下才是线性的:

  1. 您的新网格是一些旋转的平行四边形 (你原来是一个正方形,“正常”网格)
  2. 你的(0,0)原点的位置不会改变。

现在,我不确定您允许手柄定位的自由度是多少,但也许您可以限制它们,以便您的网格空间始终遵循旋转平行四边形的形式。

This looks like a linear transformation to me. We know this because any line in the original graph is also a line in the transformed graph (this is not always true of the demo you gave, but will be true if you follow the directions you gave in your question and not allow concave vertices). I do believe that AS3 has built-in support for transformation matrix manipulations. If not, you can implement them yourself.

[ x' ]  =   [ a b ] x [ x ]
[ y' ]      [ c d ]   [ y ]

These are matrices. The first is a vector (your final point), and that equals a certain 2x2 matrix multiplied by a vector (your original point)

If you're not familiar with matrix multiplication, this can be simplified out to be:

x' = a*x + b*y
y' = c*x + b*y

Any linear transformation can be represented by that two-by-two matrix of a, b, c, and d. Pick numbers for each of them, and you get a linear transformation. So how do you find the values of a, b, c, and d that will give you yours?

For four unknowns, you need four equations. If you look at the equations above, you'll see that one point ("vector") and its transformation will give you two equations. So...we need two points. As you'll see later, it'll be useful to pick points in the un-transformed form (m,0) and (0,n) (ie, one along your x axis, and the other along your y axis).

In your example, these are easy to find! They are B and D (if A or C is your origin)!

I'll be using a bit different notation: "primes" for transformed versions of points.

B => B'
B_x => B'_x
B_y => B'_y

If you know the before and the after coordinates of B and D, you can find your transformation matrix a,b,c,d.

Setting up your equations:

B'_x = a * B_x + b * B_y
B'_y = c * B_x + d * B_y

D'_x = a * D_x + b * D_y
D'_y = c * D_x + d * D_y

Now, let's say that B is your x-axis point, in form (B_x,0). Say D is your y-axis point, in form (0,D_y). If this is opposite, switch them. Here, we assume that your origin is A = (0,0), like in most Flash apps.

Setting B_y = 0 and D_x = 0, we get:

B'_x = a * B_x + b * 0
B'_y = c * B_x + d * 0
D'_x = a * 0   + b * D_y
D'_y = c * 0   + d * D_y

Using the powers of algebra, we find:

a = B'_x / B_x
c = B'_y / B_x
b = D'_x / D_y
d = D'_y / D_y

So, in short:

If you know original points: (the vertices on the original x and y axis)

M = (M_x, 0)
N = (0  , N_x)

and their transformed/distorted points

M' = (M'_x, M'_y)
N' = (N'_x, N'_y)

(so that M => M' and N => N')

then calculate and store these four variables:

a = M'_x / M_x
b = N'_x / N_y
c = M'_y / M_x
d = N'_y / N_y

and finally:

(x, y)  =>  ( a*x + b*y , c*x + d*y )

edit: Okay, I ran through a few of your arbitrary-corner-handle transformation, and realized that I jumped to conclusions when I assumed that your transformation was linear. The equations above will only be linear under two conditions:

  1. Your new grid is the shape of some rotated parallelogram (and you original is a square, 'normal' grid)
  2. The position of your (0,0) origin point does not change.

Now, I'm not sure what degrees of freedom you are allowing your handles to be positioned by, but perhaps you can restrain them so that your gridspace always follows the form of a rotated parallelogram.

沫离伤花 2024-09-10 09:35:42

让 (u,v) 代表“纹理”坐标。无论网格扭曲如何,您的手柄都会保持相同的纹理坐标。

因此,在纹理空间中, A=(0,0) B=(1,0) C=(1,1) D=(0,1) A'=(au,av) B'=(bu,bv) ...

我们可以从纹理空间转换到像素空间。

P(u,v) = A*(1-u)(1-v) + Bu*(1-v) + Cuv + D*( 1-u)*v

(u,v 是纹理坐标,A、B、C、D 是指像素坐标)

所以,如果你的句柄 A' 被定义为具有纹理坐标 (.35,.15),那么A' 在像素空间中的位置由 P(.35,.15) 给出。

现在,假设用户拖动手柄 A'。我们需要求解 A 的新位置。B、C、D 保持不变。这只是简单的代数。

A' = A*(1-au)*(1-av) + B*au*(1-av) + C*au*av + D*(1-au)*av
A' - B*au*(1-av) - C*au*av - D*(1-au)*av = A*(1-au)*(1-av)
A = (A' - B*au*(1-av) - C*au*av - D*(1-au)*av) / ((1-au)*(1-av))

还不错。相同的过程获取其他句柄的公式。这是我的 C# 代码。当 8 个“拇指”中的任何一个被拖动时,它就会被调用:

     double au = .35, av = .15; // texture coordinates of A'
     double bu = .8, bv = .2;   // texture coordinates of B'
     double cu = .8, cv = .6;   // texture coordinates of C'
     double du = .2, dv = .9;   // texture coordinates of D'

     // if we're dragging A' (AA), then move A, etc.
     if (sender == ThumbAA) A = (AA - B*au*(1-av) - C*au*av - D*(1-au)*av) / ((1-au)*(1-av));
     if (sender == ThumbBB) B = (BB - A*(1-bu)*(1-bv) - C*bu*bv - D*(1-bu)*bv) / (bu*(1-bv));
     if (sender == ThumbCC) C = (CC - A*(1-cu)*(1-cv) - B*cu*(1-cv) - D*(1-cu)*cv) / (cu*cv);
     if (sender == ThumbDD) D = (DD - A*(1-du)*(1-dv) - B*du*(1-dv) - C*du*dv) / ((1-du)*dv);

     // update position of A', B', C', D'   
     AA = A*(1-au)*(1-av) + B*au*(1-av) + C*au*av + D*(1-au)*av;
     BB = A*(1-bu)*(1-bv) + B*bu*(1-bv) + C*bu*bv + D*(1-bu)*bv;
     CC = A*(1-cu)*(1-cv) + B*cu*(1-cv) + C*cu*cv + D*(1-cu)*cv;
     DD = A*(1-du)*(1-dv) + B*du*(1-dv) + C*du*dv + D*(1-du)*dv;

我的演示应用程序的视频:
http://screencast.com/t/NDU2ZWRj

这并不能回答您有关重新定位 4 的确切问题同时处理。那是你真正想要的吗?另外,如果您的手柄的纹理坐标未预先确定,请告诉我。您可以从像素坐标转换为纹理坐标,但它更复杂。

Let (u,v) represent "texture" coordinates. Your handles stay at the same texture coordinates regardless of grid distortions.

So, in texture space, A=(0,0) B=(1,0) C=(1,1) D=(0,1) A'=(au,av) B'=(bu,bv) ...

We can convert from texture space to pixel space.

P(u,v) = A*(1-u)(1-v) + Bu*(1-v) + Cuv + D*(1-u)*v

(u,v are texture coordinates, and A, B, C, D refer to pixel coordinates)

So, if your handle A' is defined to have texture coordinate (.35,.15), then the position of A' in pixel space is given by P(.35,.15).

Now, say the user drags handle A'. We need to solve for the new location of A. B,C,D remain fixed. It's just simple algebra.

A' = A*(1-au)*(1-av) + B*au*(1-av) + C*au*av + D*(1-au)*av
A' - B*au*(1-av) - C*au*av - D*(1-au)*av = A*(1-au)*(1-av)
A = (A' - B*au*(1-av) - C*au*av - D*(1-au)*av) / ((1-au)*(1-av))

Not too bad. The same process gets formulas for the other handles. Here is my C# code. It gets called when any of the 8 "Thumbs" get dragged:

     double au = .35, av = .15; // texture coordinates of A'
     double bu = .8, bv = .2;   // texture coordinates of B'
     double cu = .8, cv = .6;   // texture coordinates of C'
     double du = .2, dv = .9;   // texture coordinates of D'

     // if we're dragging A' (AA), then move A, etc.
     if (sender == ThumbAA) A = (AA - B*au*(1-av) - C*au*av - D*(1-au)*av) / ((1-au)*(1-av));
     if (sender == ThumbBB) B = (BB - A*(1-bu)*(1-bv) - C*bu*bv - D*(1-bu)*bv) / (bu*(1-bv));
     if (sender == ThumbCC) C = (CC - A*(1-cu)*(1-cv) - B*cu*(1-cv) - D*(1-cu)*cv) / (cu*cv);
     if (sender == ThumbDD) D = (DD - A*(1-du)*(1-dv) - B*du*(1-dv) - C*du*dv) / ((1-du)*dv);

     // update position of A', B', C', D'   
     AA = A*(1-au)*(1-av) + B*au*(1-av) + C*au*av + D*(1-au)*av;
     BB = A*(1-bu)*(1-bv) + B*bu*(1-bv) + C*bu*bv + D*(1-bu)*bv;
     CC = A*(1-cu)*(1-cv) + B*cu*(1-cv) + C*cu*cv + D*(1-cu)*cv;
     DD = A*(1-du)*(1-dv) + B*du*(1-dv) + C*du*dv + D*(1-du)*dv;

video of my demo app:
http://screencast.com/t/NDU2ZWRj

This doesn't answer your exact question about repositioning 4 handles at the same time. Is that what you really want? Also, let me know if your handles' texture coordinates aren't predetermined. You can convert from pixel to texture coordinates, but it is more complicated.

〆凄凉。 2024-09-10 09:35:42

您确定要了解手柄的所有内容吗?在示例中,手柄用作动画剪辑上绘图的参考点,它们与图像或其上的失真没有任何关系。如果您只想将处理程序放在图像内,那么您只需要偏移点计算值(例如,topRightCorner = new Point(pointb.x +10, point.y - 10) )

如果您确实想计算精确点,那么您可以尝试从处理程序调用 localToGlobal(new Point(this.x, this.y)) 来确定它在哪里(因此也适用于它的翻译)。否则你将不得不处理变换矩阵并准确地计算出该类如何计算其三角形。

有关变换矩阵的非常好的指南,请参见此处:senoular.com

祝你好运

Are you sure that you want to be getting into all of this for handles? in the examples the handles are there to act as reference points on the movieclip for drawing, they are not related in any way to the image or the distortion apon it. if you are wanting to just have the handlers inside the image then you would just need to offset the point calculation value (topRightCorner = new Point(pointb.x +10, point.y - 10) for example)

if you are really wanting to get into calculating exact points then you can try doing a call to localToGlobal(new Point(this.x, this.y)) from a handler to work out where it is (and therefore the translation that has been applied to it). otherwise you are going to have to deal with transformation matricies and work out exactly how the class calculates its triangles.

for a very good guide to transformation matricies, see here: senoular.com

good luck

誰ツ都不明白 2024-09-10 09:35:42

您是否需要算法角度的帮助(转换等),或者您是否正在寻求有关如何专门使用 Sandy 3D flash 引擎实现转换的帮助?

Do you want help from algorithmic point of view (Transformations etc) or are you looking for help on how to achieve transformations specifically using Sandy 3D flash engine?

望笑 2024-09-10 09:35:42

您可能会想出一些办法,但我怀疑您或您的用户会喜欢这个结果。

要了解原因,请选择图像内部的一个点。假设您想将其向上移动一点。您可以通过移动四个角中的任意一个来做到这一点(在演示中尝试一下)。这意味着如果你想在那里放一个手柄并将其向上移动,四个角将以某种组合移动。很可能拐角不会达到您想要的效果。例如,所有四个都可以向上移动相同的量,从而产生纯粹的平移并且没有扭曲。或者一个角可能会移动,但可能不是您期望的那样。解决方案有无数种,而且您选择的解决方案很可能不是您(或其他人)所期望的。

顺便说一下,演示中使用的失真方法是“双线性插值”。将手柄放在角落可能是控制它的最佳方法。

You could probably figure something out, but I doubt that you or your users are going to like the result.

To see why, select a point in the interior of the image. Say you want to move it upwards by a bit. You can do that by moving any one of the four corners (try it in the demo). That means if you wanted to put a handle there and move it upwards, the four corners would move in some combination. Most likely the corners would not do what you want. For example, all four of them could move up by the same amount, resulting in a pure translation and no warp. Or a single corner could move, but maybe not the one you expected. There are an infinity of solutions, and most likely the one you choose is not the one you (or somebody else) is expecting.

The distortion method being used in the demo, by the way, is "bilinear interpolation". Having the handles at the corners is probably the best way to control it.

生寂 2024-09-10 09:35:42

你说的是 2D 系统,但你应用的失真是 3D 失真(当然,尽管投影回 2D)——这是故意的吗?

一般来说,我实际上不确定是否可以在没有更多关于正在使用的透视投影的信息的情况下计算 A'new 的新位置,而不仅仅是 ABCD 的新位置。毕竟,透视投影夸大了附近的距离并压缩了远处的距离,其程度取决于距焦点(相当于 FOV)的距离。

无论如何,首先重用投影所需计算的任何内容都是最简单的 - 如果您可以获得原始变换矩阵和透视变换,您可以直接将它们应用于 A' B' 和 D'以及。

You speak of a 2D system, yet the distortion you're applying is a 3D distortion (albeit projected back down into 2d, of course) - is that intentional?

In general, I'm not actually sure it's possibly to compute A'new's new location without more information about the perspective projection being using than just ABCD's new locations. After all, perspective projection exaggerates nearby distances and compresses distant ones - and the degree to which it does this depends on the distance from the focal point (equivalently, the FOV).

It'd be easiest, in any case, to reuse whatever needed to be computed for the projection in the first place - if you can get the original transformation matrix and perspective transform, you can straightforwardly apply those to A' B' and D' as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文