四边形内一点的相对位置

时间:2015-02-23 14:21:43

标签: math geometry computational-geometry

我试图找到确定四边形内一个点的相对位置的最简单方法。已知的是(见图)xy坐标系中点1,2,3,4和5的位置:x1,y1,x2,y2,x3,y3,x4,y4,x5,y5。

enter image description here

还知道ξ-η坐标系中点1,2,3和4的位置(见图)。

根据这些数据,我想确定第5点的ξ和η是什么。

结果

感谢所有光临的人!我发现@dbc和@agentp的解决方案类似。此外,我发现这个解决方案比@MBo的透视变换解决方案更好,因为我不必计算矩阵的逆矩阵(Ax = B - > x = inv(A)* B)。

我得到以下结果:

u = 0.5 * (ξ + 1)
v = 0.5 * (η + 1)

在我的情况下,所有点都在矩形内,因此u> 0且v> 0。

enter image description here

4 个答案:

答案 0 :(得分:2)

这看起来像标准的有限元参数化 (这个问题并没有指定特定的映射,但我想有人可能对这个特定情况感兴趣)

 {x, y}  == (
             (1 - eta) (1 - ci) {p1x, p1y}  +
             (1 - eta) (1 + ci) {p2x, p2y}   + 
             (1 + eta) (1 + ci) {p3x, p3y} +
             (1 + eta) (1 - ci) {p4x, p4y} )/4

这可以用{eta,ci}的封闭形式来解决,但是这个表达非常难以发布。

在实践中,计算这些常量:

 ax = p1x + p2x + p3x + p4x
 bx = p1x - p2x - p3x + p4x
 cx = p1x + p2x - p3x - p4x
 dx = p1x - p2x + p3x - p4x
 ay = p1y + p2y + p3y + p4y
 by = p1y - p2y - p3y + p4y
 cy = p1y + p2y - p3y - p4y;
 dy = p1y - p2y + p3y - p4y;

解决eta的这个二次方:

 (ax by - bx ay) - 4 (by  x - bx y) +
  eta (dx ay - cx by + bx  cy - ax dy + 4 (x dy - dx y)) +
  eta^2 (cx dy - dx cy) == 0

然后将ci作为:

 ci = ((-ax + eta cx + 4 x)/(-bx + eta dx))

如果多边形没有太扭曲,则其中一个解决方案将满足-1<eta<1-1<ci<1

答案 1 :(得分:2)

这里有2d bilinear blended surface。为简单起见,让我们将其坐标更改为从0到1的范围:

u = 0.5 * (ξ + 1)
v = 0.5 * (η + 1)

在这种情况下,表面评估器可以表示为

F(u, v) = P1 + u * (P2 - P1) + v * ((P4 + u * (P3 - P4)) - (P1 + u * (P2 - P1)))

即,对于给定的u,构造一条通过以下两点的线:

Pv0 = P1 + u * (P2 - P1);
Pv1 = P4 + u * (P3 - P4);

然后在给定的v

之间进行插值
F(u, v) = Pv0 + v * (Pv1 - Pv0)

您所寻求的是价值(u,v)F(u, v) = P5。当从uPv0的行经过Pv1时,这将在给定的P5时发生,当P5 - Pv0Pv1 - Pv0平行时会发生 - 即当他们的2d cross为零时:

cross2d(P5 - Pv0, Pv1 - Pv0) = 0

cross2d(P5                 - (P1 + u * (P2 - P1)),  
        P4 + u * (P3 - P4) - (P1 + u * (P2 - P1))) = 0

现在,两个2d向量A ⨯ B的{​​{3}}由Ax*By - Ay*Bx给出,因此等式变为

(x5 - (x1 + u * (x2 - x1))) * (y4 + u * (y3 - y4) - (y1 + u * (y2 - y1))) - (y5 - (y1 + u * (y2 - y1))) * (x4 + u * (x3 - x4) - (x1 + u * (x2 - x1))) = 0

2d cross,我们

    u^2 * (x1*y3 - x1*y4 - x2*y3 + x2*y4 + (-x3)*y1 + x3*y2 + x4*y1 - x4*y2)
  + u *   (-x1*y3 + 2*x1*y4 - x1*y5 - x2*y4 + x2*y5 + x3*y1 - x3*y5 - 2*x4*y1 + x4*y2 + x4*y5 + x5*y1 - x5*y2 + x5*y3 - x5*y4)
  +       (-x1*y4 + x1*y5 + x4*y1 - x4*y5 - x5*y1 + x5*y4)
= 0

现在这是u上的二次方程,并且可以是Expanding this expression out and collecting collecting together terms in u。请注意,如果四边形的顶部和底部边缘平行,则二次方形成为线性方程;你的二次方程求解器必须处理这个。

        double a = (x1 * y3 - x1 * y4 - x2 * y3 + x2 * y4 + (-x3) * y1 + x3 * y2 + x4 * y1 - x4 * y2);
        double b = (-x1 * y3 + 2 * x1 * y4 - x1 * y5 - x2 * y4 + x2 * y5 + x3 * y1 - x3 * y5 - 2 * x4 * y1 + x4 * y2 + x4 * y5 + x5 * y1 - x5 * y2 + x5 * y3 - x5 * y4);
        double c = (-x1 * y4 + x1 * y5 + x4 * y1 - x4 * y5 - x5 * y1 + x5 * y4);

        double[] solutions = Quadratic.Solve(a, b, c);

可能有多个解决方案。对于退化的四边形,可能也没有解决方案。

解决u的值后,找到等效的v非常简单。给定点

Pv0 = P1 + u * (P2 - P1);
Pv1 = P4 + u * (P3 - P4);

你寻求v这样

v * (Pv1 - Pv0) = P5 - Pv0;

选择坐标索引0或1,使|(Pv1 - Pv0)[index]| 最大化。 (如果两个坐标几乎为零,那么放弃 - 这个特定的u没有解决方案。然后设置

v = (P5 - Pv0)[index] / (Pv1 - Pv0)[index];

最后,如果您有更多的解决方案,请选择混合的[u, v]边界内的解决方案。然后最后设置

ξ = 2 * u - 1;
η = 2 * v - 1;

答案 2 :(得分:1)

你需要计算一个透视变换矩阵,它将4个源四边形点映射到4个目的地四边形(example)more mathemathics),然后将这个变换应用于第5个点的坐标(乘法)矩阵乘坐标矢量)

答案 3 :(得分:1)

参考@blaz的自我答案(请将@blaze,@ dbc和@agentp的答案付诸表决)

对于每个不愿意手动复制公式的人,这里的公式为C#代码:

    double v_sqrt = Math.Sqrt(
        4 * (
        (x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4)) * (x4 * (-1 * y + y1) + x1 * (y - y4) + x * (-1 * y1 + y4)) +
        Math.Pow(
        (x3 * y - x4 * y - x3 * y1 + 2 * x4 * y1 - x4 * y2 + x1 * (y + y3 - 2 * y4) + x2 * (-1 * y + y4) + x * (-1 * y1 + y2 - y3 + y4))
        , 2)
        );

    double u_sqrt = Math.Sqrt(
            4 * ((x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4))
            * (
                x4 * (-1 * y + y1) + x1 * (y - y4) + x * (-1 * y1 + y4)
            ) +
            Math.Pow(
            (x3 * y - x4 * y - x3 * y1 + 2 * x4 * y1 - x4 * y2 + x1 * (y + y3 - 2 * y4) + x2 * (-1 * y + y4) + x * (-1 * y1 + y2 - y3 + y4))
            , 2)
        );

    double k = 1 / (2 * ((x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4)));
    double l = 1 / (2 * ((x1 - x4) * (y2 - y3) - (x2 - x3) * (y1 - y4)));

    ///////////////////////////////////////////////////////////////////////////////////////////////
    double v1 = l *
        (x2 * y - x3 * y + x4 * y + x * y1 - 2 * x2 * y1 + x3 * y1 - x * y2 - x4 * y2 + x * y3 - x1 * (y - 2 * y2 + y3) - x * y4 + x2 * y4 +
        v_sqrt);

    ///////////////////////////////////////////////////////////////////////////////////////////////
    double u1 = -1 * k *
        (-x2 * y + x3 * y - x * y1 - x3 * y1 + 2 * x4 * y1 + x * y2 - x4 * y2 - x * y3 + x1 * (y + y3 - 2 * y4) + x * y4 + x2 * y4 +
        u_sqrt);

    double v2 = -1 * l *
        (x1 * y + x3 * y - x4 * y - x * y1 - 2 * x3 * y1 + x * y2 - -2 * x1 * y2 + x4 * y2 - x * y3 + x1 * y3 + x * y4 - x2 * (y - 2 * y1 + y4) +
        v_sqrt);

    /////////////////////////////////////////////////////////////////////////////////////////////////
    double u2 = k *
        (x2 * y - x3 * y + x4 * y + x * y1 + x3 * y1 - 2 * x4 * y1 - x * y2 + x4 * y2 + x * y3 - x1 * (y + y3 - 2 * y4) - x * y4 - x2 * y4 +
        u_sqrt);

在大多数情况下,它是u1和v1,因此不需要计算其他的。

我用它在一张纸上校准Pegasus Air-Pen设备(超声波触控笔)的坐标。如果第1点到第5点的坐标也是> = 0。

,它的效果最好

Sry将此作为答案发布,但评论时间过长,我认为这对我来说是有用的帮助。