我在下面写了一些代码来检查两个线段是否相交,以及它们是否告诉我在哪里。作为输入,我有每行两端的(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);
}
答案 0 :(得分:0)
关于线和它们的交叉点有一个绝对伟大而简单的理论,它基于为点和线添加额外的尺寸。在该理论中,可以使用一行代码从两个点创建一条线,并且可以使用一行代码计算线交点。此外,Infinity处的点和Infinity处的线可以用实数表示。
当点[x,y]表示为[x,y,1]并且线ax + + + c = 0表示为[a,b,c]时,您可能听说过均匀表示? 对于点[x,y,w]的一般均匀表示,转换到笛卡尔坐标是[x / w,y / w]。这个小技巧会产生所有不同,包括无穷远处的线条表示(例如[1,0,0]),并使线条表示看起来类似于第一点。这为很多线/点操作的公式引入了一个很好的对称性,并且是一个 绝对必须在编程中使用。例如,
通过矢量积
很容易找到线交点p = l1xl2
可以从两个点创建一条线是类似的方式:
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);
}