I am writing code to determine if a polyline is self-intersecting or not.
If at least two links of a polyline intersect (at their internal points), it is called self-intersecting.
To begin with, I write a function to determine the intersection of two intersect segments. There I use the school straight line formula y = kx + b.
And then the function f, where I check every 2 points of 2 segments for intersection. In principle, everything works, but the code breaks when some part of the polyline does not exactly intersect, but simply "touches" some other segment of this polyline. For example, as in the test:
Test:
4
0 0
2 2
2 1
1 1
Code:
#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;
}
Then, having experienced a failure on this code, I decided to change the logic of the intersect function and did something like:
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;
}
But even here the code breaks on this test. Should output 1 if there is a self-intersection, otherwise 0.
Most likely the problem is in the for loop in the function f
. I've already tried everything.
I also tried this:
for (int i = 0; i < n - 1; i ++)
for (int j = i + 2; i < n; j ++)
Unfortunately, it did not help.
Can you explain why the code breaks???