Reputation: 63
I have a script that asks you to enter a number n and after that asks you to enter n number of (x,y) points.
At the end the script sort (x,y) points with respect to x
What I need is to detect collinear points and remove them so script will have only points at general position.
For example:
Input
10
8 16
2 16
5 9
9 16
15 18
3 17
8 10
3 12
10 17
5 17
Output
2 16
3 12
5 9
5 17
8 10
9 16
10 17
15 18
My Script is this:
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
int n,m;
class punto{
private:
int x;
int y;
public:
punto();
~punto(){}
void setx(int xn){ x = xn;}
void sety(int yn) { y = yn; }
void printcoord();
friend bool compare_x(const punto& lhs, const punto& rhs);
friend bool compare_y(const punto& lhs, const punto& rhs);
};
punto::punto()
{
x=0;
y=0;
}
void punto:: printcoord()
{
cout << x << " " << y << endl;
}
bool compare_x(const punto& lhs, const punto& rhs) {
if (lhs.x == rhs.x)
return lhs.y < rhs.y;
return lhs.x < rhs.x;
}
int main()
{
vector<punto> list;
int x;
int y;
punto *p1;
cin >>n;
for(int contador=0; contador<n; contador++){
if(contador<n){
cin >> x;
cin >> y;
p1=new punto;
p1->setx(x);
p1->sety(y);
list.push_back(*p1);
cin.get();
}
}
vector<punto>::iterator it;
std::sort(list.begin(), list.end(), compare_x);
for ( it = list.begin(); it != list.end(); ++it ) {
it->printcoord();
}
return 0;
}
As you can see I'm missing a function to determine collinear points and remove them.
I would really appreciate any help!
Upvotes: 1
Views: 1668
Reputation: 119
Use dot product. Let a, b, c be three points. If all three points lie on the same line, then the vector b-a and the vector c-a will have a dot product of |b-a||c-a|.
This is due to the fact that cos(angle(bac))=dot(b-a,c-a)/(mag(b-a)*mag(c-a)). If they are collinear, then the angle is zero. The cosine for zero is one, so dot(b-a,c-a)==mag(b-a)*mag(c-a) means they are collinear.
If your linear algebra skills are rusty or non-existent, then here's a refresher
dot(w,v) = w.x*v.x + w.y*v.y
mag(v)=sqrt(v.x*v.x + v.y*v.y)
The trick is to remove the costly square root function somehow. Squaring both sides, you have
mag^2(v)=v.x*v.x+v.y*v.y
cos^2(0)=1^2=1
dot^2(w,v)=(w.x*v.x + w.y*v.y)*(w.x*v.x + w.y*v.y)
just do a check
if( (v.x*v.x + v.y*v.y)*(w.x*w.x + w.y*w.y)) == (w.x*v.x + w.y*v.y)*(w.x*v.x + w.y*v.y) )
Upvotes: 1