I'll check it out when I get home. Can't really compile it at work.
Any reason why you're redefining your own Point structure instead of just using sf::Vector2 like I suggested?
typedef sf::Vector2<double> Point;
sf::Vector provides all the operator overloads so you didn't have to rewrite all of that.
EDIT:
I just got home and tried it.
My LineVsCircleCollision function as I posted it works fine. You must have converted something incorrectly when you "translated" it to use your Point struct. When you use sf::Vector's overloaded operators it works fine.
This code below works in that 300,600 case.
Didn't figure out what's wrong with your Check function yet. I'll keep looking.
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <cmath>
#include <iostream>
#pragma comment(lib,"sfml-graphics-s-d.lib")
#pragma comment(lib,"sfml-system-s-d.lib")
#pragma comment(lib,"sfml-window-s-d.lib")
using std::cout;
using std::endl;
typedef sf::Vector2<double> Point;
bool Check(Point & Point1, Point & Point2, Point & Circle, double radius)
{
Point linevector; // LineA is our origin point
linevector.x = Point2.x - Point1.x;
linevector.y = Point2.x - Point1.x;
Point circlevector; // same
circlevector.x = Circle.x - Point1.x;
circlevector.y = Circle.y - Point1.y;
// now if we atan2, we'll get the proper angle
double circangle = atan2(circlevector.y,circlevector.x);
double lineangle = atan2(linevector.y,linevector.x);
double angle = circangle - lineangle;
cout<<"angle = "<<angle<<" radians, "<<angle *180/3.14<<" degrees"<<endl;
if(angle < 0)
{
angle *= -1;
cout<<"changed by multiplication"<<endl;
cout<<"angle = "<<angle<<" radians, "<<angle *180/3.14<<" degrees"<<endl;
}
double distance_circle_point = sqrt( pow(Point1.x - Circle.x,2) + pow(Point1.y - Circle.y,2) );
cout<<"distance_circle_point = "<<distance_circle_point<<endl;
double distance = sin(angle) * distance_circle_point;
cout<<"distance = "<<distance<<endl;
cout<<endl<<endl;
if(distance <= radius)
return true;
return false;
}
// Dot product / Perpendicular dot product
inline double Dot(const Point& a,const Point& b) { return (a.x*b.x) + (a.y*b.y); }
inline double PerpDot(const Point& a,const Point& b) { return (a.y*b.x) - (a.x*b.y); }
bool LineVsCircleCollision(const Point& lineA,const Point& lineB,const Point& circle,double radius)
{
Point line(lineB - lineA); // the line vector
Point circ(circle - lineA); // the vector of the origin line point to the circle center
// project the circle vector onto the line vector
double proj = Dot(line,circ) / Dot(line,line);
{ // remove this block if the line extends infinitely
if(proj < 0) proj = 0;
else if(proj > 1) proj = 1;
}
// apply the projected position to our vector, and offset it by our origin
Point nearest = (line * proj) + lineA;
// 'nearest' is now the point on the line nearest the circle
// see if the distance between this point and the circle center is greater than the radius.
// if the radius is larger, the circle intersects
Point dist = circle - nearest; // the vector between the circle and the nearest point on the line
return Dot(dist,dist) <= (radius*radius);
}
int main()
{
sf::RenderWindow App(sf::VideoMode(800, 600, 32), "animation");
double radius = 30;
Point p1(100,100), p2(300,600), circle(433,300);
while (App.IsOpened())
{
sf::Event Event;
while (App.GetEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
// Escape key : exit
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
App.Close();
}
if (App.GetInput().IsKeyDown(sf::Key::Up))
circle.y-=2;
if (App.GetInput().IsKeyDown(sf::Key::Down))
circle.y+=2;
if (App.GetInput().IsKeyDown(sf::Key::Right))
circle.x+=2;
if (App.GetInput().IsKeyDown(sf::Key::Left))
circle.x-=2;
App.Clear();
if(LineVsCircleCollision(p1,p2,circle,radius))
App.Draw(sf::Shape::Circle(20, 20, 20, sf::Color(0,255,0)));
if(Check(p1,p2,circle,radius))
App.Draw(sf::Shape::Circle(60, 20, 20, sf::Color(255,0,0)));
App.Draw(sf::Shape::Line(p1.x, p1.y, p2.x, p2.y, 1, sf::Color(0,255,128)));
App.Draw(sf::Shape::Circle(circle.x, circle.y, radius, sf::Color(255,128,0)));
App.Display();
sf::Sleep(0.025f);
}
return EXIT_SUCCESS;
}
EDIT AGAIN:
Found your conversion error:
bool LineVsCircleCollision(const Point& lineA,const Point& lineB,const Point& circle,double radius)
{
Point line; // the line vector
line.x = lineB.x - lineA.x;
line.y = lineB.x - lineA.x; // <- should be lineB.y - lineA.y
But of course it's easier if you just keep the sf::Vector2<double> bit.
?FINAL? EDIT:
You made the same mistake in your Check function:
bool Check(Point & Point1, Point & Point2, Point & Circle, double radius)
{
Point linevector; // LineA is our origin point
linevector.x = Point2.x - Point1.x;
linevector.y = Point2.x - Point1.x; // <-- should be .y, not .x
After making that change, Check() seems to work assuming the line extends infinitely in each direction.
PS:
- Using pow() to square stuff should be a sin. Instead of doing pow(x,2), just do (x*x) or write your own square function that does (x*x). Using pow is like driving a small nail with a sledgehammer.
- Note how my function takes no expensive trig calculations, works with line segments, and is much simpler. That's the magic of linear algebra. I'm happy to explain how it all works if you're interested. Just let me know.