1

2 つの線分が交差しているかどうか、交差しているかどうかを確認するために、以下のコードをいくつか書きました。入力として、各行の両端の (x,y) 座標があります。正しく動作しているように見えましたが、現在、線 A (532.87,787.79)(486.34,769.85) と線 B (490.89,764.018)(478.98,783.129) のシナリオでは、線が (770.136, 487.08) で交差すると言われています。絶対に交わらないでください。

以下のコードで何が間違っているのか、誰にもわかりませんか?

double                      dy[2], dx[2], m[2], b[2];
double                      xint, yint, xi, yi;
WsqT_Location_Message       *location_msg_ptr = OPC_NIL;

FIN (intersect (<args>));

dy[0] = y2 - y1;
dx[0] = x2 - x1;
dy[1] = y4 - y3;
dx[1] = x4 - x3;

m[0] = dy[0] / dx[0];
m[1] = dy[1] / dx[1];
b[0] = y1 - m[0] * x1;
b[1] = y3 - m[1] * x3;

if (m[0] != m[1])
{
    //slopes not equal, compute intercept
    xint = (b[0] - b[1]) / (m[1] - m[0]);
    yint = m[1] * xint + b[1];

    //is intercept in both line segments?
    if ((xint <= max(x1, x2)) && (xint >= min(x1, x2)) &&
        (yint <= max(y1, y2)) && (yint >= min(y1, y2)) &&
        (xint <= max(x3, x4)) && (xint >= min(x3, x4)) &&
        (yint <= max(y3, y4)) && (yint >= min(y3, y4)))
    {
        if (xi && yi)
        {
            xi = xint;
            yi = yint;

            location_msg_ptr = (WsqT_Location_Message*)op_prg_mem_alloc(sizeof(WsqT_Location_Message));

            location_msg_ptr->current_latitude = xi;
            location_msg_ptr->current_longitude = yi;
        }

        FRET(location_msg_ptr);
    }
}

FRET(location_msg_ptr);
}
4

1 に答える 1

0

ポイントとラインに追加のディメンションを追加することに基づいた、ラインとその交点に関する非常に優れたシンプルな理論があります。この理論では、1 行のコードで 2 つの点から線を作成でき、1 行のコードで線の交点を計算できます。さらに、無限遠の点と無限遠の線は実数で表すことができます。

点 [x, y] が [x, y, 1] として表され、直線 ax+by+c=0 が [a, b, c] として表される同次表現について聞いたことがあるでしょうか? 点 [x, y, w] の一般的な同次表現のデカルト座標への遷移は [x/w, y/w] です。この小さなトリックにより、無限遠 ([1, 0, 0] など) での線の表現や、点 1 に似た線表現の作成など、すべての違いが生まれます。これにより、多数の線/点操作の式に優れた対称性が導入され、プログラミングで使用する必要があります。例えば、

ベクトル積を介して線の交点を見つけるのは非常に簡単です

p = l1xl2

同様の方法で、2 点から線を作成できます。

l=p1xp2

OpenCV のコードでは、次のようになります。

line = p1.cross(p2);
p = line1.cross(line2);

ここで考慮すべき重要なケース (ゼロや平行線による除算など) はないことに注意してください。私のポイントは、線と点に関するこの洗練された理論を利用するようにコードを書き直すことをお勧めします。

最後に、openCV を使用しない場合は、3D ポイント クラスを使用して、次のような独自の外積関数を作成できます。

template<typename _Tp> inline Point3_<_Tp> Point3_<_Tp>::cross(const Point3_<_Tp>& pt) const
{
    return Point3_<_Tp>(y*pt.z - z*pt.y, z*pt.x - x*pt.z, x*pt.y - y*pt.x);
}
于 2014-03-03T19:17:24.803 に答える