查找两条线段是否在C++相交
Find whether two line segments intersect or not in C++
我编写了以下程序来找出两条线段是否相交。在某些情况下,该程序似乎无法正常工作。有人可以帮我纠正我哪里出错了吗?
bool FindLineIntersection(double start1[2], double end1[2], double start2[2], double end2[2])
{
float denom = ((end1[0] - start1[0]) * (end2[1] - start2[1])) - ((end1[1] - start1[1]) * (end2[0] - start2[0]));
// AB & CD are parallel
if (denom == 0)
return false;
float numer = ((start1[1] - start2[1]) * (end2[0] - start2[0])) - ((start1[0] - start2[0]) * (end2[1] - start2[1]));
float r = numer / denom;
float numer2 = ((start1[1] - start2[1]) * (end1[0] - start1[0])) - ((start1[0] - start2[0]) * (end1[1] - start1[1]));
float s = numer2 / denom;
if ((r < 0 || r > 1) || (s < 0 || s > 1))
return false;
return true;
}
你想找到两条线a
和b
的交点[P]
:
[P] = [A] + [a]*r = [B] + [b] * s
这会产生线性方程:
[a]*r - [b]*s = [S] - [R]
或
| ax -bx | | r | |Sx - Rx|
| | * | | = | |
| ay -by | | s | |Sy - Ry|
从你的行列式来看,这不是你要解决的方程式。我认为您的函数应如下所示:
bool intersection(double start1[2], double end1[2],
double start2[2], double end2[2])
{
float ax = end1[0] - start1[0]; // direction of line a
float ay = end1[1] - start1[1]; // ax and ay as above
float bx = start2[0] - end2[0]; // direction of line b, reversed
float by = start2[1] - end2[1]; // really -by and -by as above
float dx = start2[0] - start1[0]; // right-hand side
float dy = start2[1] - start1[1];
float det = ax * by - ay * bx;
if (det == 0) return false;
float r = (dx * by - dy * bx) / det;
float s = (ax * dy - ay * dx) / det;
return !(r < 0 || r > 1 || s < 0 || s > 1);
}
编辑二:上面介绍的算法非常粗糙。它正确计算以非零角度相互交叉的两个线段的交点。以下问题未解决:
共线性。当主行列式为零时,方向矢量是平行的。要检查两条线段是否共线,请测试一个方向向量的交叉积与两个起点的差值是否为零:
ax * dy - ay * dx == 0
共线性并不一定意味着线段重叠。为此,第二条曲线的凝视点和终点的系数
r
必须与区间[0, 1]
重叠。零长度段。这里,零长度线段的系数不确定,主行列式为零。算法可以检查长度并确定退化赛格曼特的起点是否在另一个。
两个零长度段。测试点是否相等或确定点可以重合,但不能相交。
精度。这里的代码只测试零,这在使用浮点坐标时通常不是一个好主意。测试可能应该针对明智选择的 epsilon 进行:
if (fabs(det) < epsilon) ...
稳健的线相交算法应该可以满足这些情况。正如他们所说,这是留给读者的练习。
编辑:我已将逻辑转换为Javascript,以便直观地检查函数。(我在此过程中发现了两个错误,我已经修复了这些错误。为了您的互动交叉乐趣,将下面的网页复制到一个 html 文件中,并在可以解释 HTML5 画布的浏览器中运行它。一对线是随机生成的,它们在相交时应为红色,否则应为灰色。重新加载以重新滚动。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Intersect!</title>
<script type="text/javascript">
function point(cx, a)
{
cx.fillRect(a[0] - 3, a[1] - 3, 7, 7);
}
function line(cx, a, b)
{
cx.beginPath();
cx.moveTo(a[0], a[1]);
cx.lineTo(b[0], b[1]);
cx.stroke();
}
function uni(x) {
return (Math.random() * x) | 0;
}
window.onload = function() {
var cv = document.getElementById("c");
var cx = cv.getContext("2d");
var a1 = [uni(500), uni(500)];
var a2 = [uni(500), uni(500)];
var b1 = [uni(500), uni(500)];
var b2 = [uni(500), uni(500)];
if (intersect(a1, a2, b1, b2)) {
cx.strokeStyle = "crimson";
cx.fillStyle = "crimson";
} else {
cx.strokeStyle = "slategray";
cx.fillStyle = "slategray";
}
point(cx, a1);
point(cx, a2);
point(cx, b1);
point(cx, b2);
line(cx, a1, a2);
line(cx, b1, b2);
}
</script>
<style type="text/css">
</style>
</head>
<body>
<canvas id="c" width="500" height="500">Kann nix.</canvas>
</body>
</html>
相关文章:
- 如何从 3D 曲面网格中删除自相交三角形?
- 如何计算两条线段的相交位置
- 如何在数组中查找相交元素
- 使用裁剪器库在线和多边形之间相交
- 如何在双向图中找到两条不相交的路径?
- 顶点对之间具有两条边不相交路径的数量
- 线段相交(仅交叉,无接触)
- GEOS叠加相交操作
- 相交折线(不是闭合的,但可能是)和射线JS或C++
- 与子字符串相比,两个字符串集之间的相交
- 检查由三个 3D 点组成的平面是否与立方体相交
- 两个不相交区间最小总和
- 使用C 中的内在函数计算相交
- 检查Ofray是否与OfemEshface相交
- 3D线段和平面相交 - 续
- 查找两个分段线性函数的相交
- 相对于向量对象的两个成员,找到两个向量的相交的有效方法
- 给定许多垂直或水平段及其终点的坐标(x1,x2,y1,y2),我们有多少个相交
- 在CGAL中与多边形相交时的前提条件异常
- C 使用STD相交集合并将其保存在另一组中