在写这个问题之前,我读了一篇类似于 SO 的文章,但我有兴趣了解我的问题到底是什么。
我正在编写代码来确定折线是否自相交。
如果多段线的至少两个链接相交(在它们的内部点),则称为自相交。
首先,我编写了一个函数来确定两个相交线段的交点。在那里我使用学校直线公式y = kx + b。
然后是函数 f,在这里我检查 2 个线段的每 2 个点是否相交。原则上,一切正常,但是当折线的某些部分不完全相交时,代码会中断,而只是“接触”该折线的其他部分。例如,在测试中: 测试:
4
0 0
2 2
2 1
1 1
编码:
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("input.txt");
ofstream fout("output.txt");
class peresec{
public:
double x,y;
};
int intersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
{
double k1, k2, b1, b2, x, y, tmp;
if(x1>=x2) {tmp=x1; x1=x2; x2=tmp; tmp=y1; y1=y2; y2=tmp;}
if(x3>=x4) {tmp=x3; x3=x4; x4=tmp; tmp=y3; y3=y4; y4=tmp;}
if(y1==y2) k1=0; else k1 = ( y2 - y1 ) / ( x2 - x1 );
if(y3==y4) k2=0; else k2 = ( y4 - y3 ) / ( x4 - x3 );
if(k1 == k2) return 0;
b1=y1-k1*x1;
b2=y3-k2*x3;
x = (b2-b1)/(k1-k2);
y = k1*x + b1;
if(x1<=x && x3<=x && x2>=x && x4>=x && !((x==x1 && y==y1) || (x==x2 && y==y2) || (x==x3 && y==y3) || (x==x4 && y==y4)))
{return 1;}
else
return 0;
}
void f(peresec *a, int n)
{
int flag;
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
{
flag=intersect(a[i].x, a[i].y, a[(i + 1) % n].x, a[(i + 1) % n].y, a[j].x, a[j].y, a[(j + 1) % n].x, a[(j + 1) % n].y);
if(flag==1) {fout << 1; return;}
}
if(flag == 0){fout << 0; return;}
}
int main()
{
long long count;
peresec *a;
if( !(fin >> count)){fout<<0; return 0;}
fin.seekg(0);
fin >> count;
if(count == 0) {fout<<0; return 0;}
a = new peresec[count];
for(int i = 0; i < count; i++){ fin >> a[i].x; fin >> a[i].y;}
f(a,count);
return 0;
}
此外,在这段代码遇到故障后,我决定更改 intersect 函数的逻辑并执行以下操作:
bool intersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
{
double v1, v2, v3, v4;
v1=(x4-x3)*(y1-y3)-(y4-y3)*(x1-x3);
v2=(x4-x3)*(y2-y3)-(y4-y3)*(x2-x3);
v3=(x2-x1)*(y3-y1)-(y2-y1)*(x3-x1);
v4=(x2-x1)*(y4-y1)-(y2-y1)*(x4-x1);
if((v1*v2<0) && (v3*v4<0)) return true;
else return false;
}
但即使在这里,代码也会在这个测试中中断。应该显示 1,否则显示 0。因为如果交叉,应该显示 1。
问题很可能出在函数的循环中f
以及我经过哪些顶点。我已经尝试了一切。
你能解释为什么代码会中断吗???
<=
改为使用第二个代码<
并更改循环,以便不检查相邻段。检查:测试返回最后一个点 (4.3) 的 0 和最后一个点 (1.1) 或 (2.0) 的 1