Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Collision between line and ball problem  (Read 12751 times)

0 Members and 1 Guest are viewing this topic.

reDo

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Collision between line and ball problem
« on: May 31, 2011, 08:21:50 pm »
I am trying to make my own collision detection between line and ball but it doesnt working correctly. Green circle should be shown only when it is collision. Please can someone chcek my code?  :roll:
My collision detection plan:

bug that I mentioned

Code: [Select]
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <cmath>
#include <iostream>

using std::cout;
using std::endl;

struct point
{
    float x;
    float y;
    float distance;
};

bool Check(point & Point, float CircX, float CircY)
{
    float CircAngle = atan2(CircY,CircX);
    cout<<"CircAngle = "<<CircAngle<<" radians, "<<CircAngle*180/3.14<<" degrees"<<endl;

    float PointAngle = atan2(Point.y,Point.x);
    cout<<"PointAngle = "<<PointAngle<<" radians, "<<PointAngle*180/3.14<<" degrees"<<endl;

    float angle = CircAngle - PointAngle;
    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;
    }

    float distance_circle_point = sqrt( pow(Point.x - CircX,2) + pow(Point.y - CircY,2) );
    cout<<"distance_circle_point = "<<distance_circle_point<<endl;

    float distance = sin(angle) * distance_circle_point;
    cout<<"distance = "<<distance<<endl;

    cout<<endl<<endl;

    if(distance <= 20)
        return true;

    return false;
}

int main()
{
    sf::RenderWindow App(sf::VideoMode(800, 600, 32), "animation");

    float x=400, y=300;

    point p1 = {100,100}, p2 = {300,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))
            y-=2;

        if (App.GetInput().IsKeyDown(sf::Key::Down))
            y+=2;

        if (App.GetInput().IsKeyDown(sf::Key::Right))
            x+=2;

        if (App.GetInput().IsKeyDown(sf::Key::Left))
            x-=2;

        App.Clear();

        if(Check(p1,x,y))
           App.Draw(sf::Shape::Circle(20, 20, 20, sf::Color(0,255,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(x, y, 20, sf::Color(255,128,0)));
        App.Display();
        sf::Sleep(0.025f);
    }


    return EXIT_SUCCESS;
}

OniLinkPlus

  • Hero Member
  • *****
  • Posts: 500
    • View Profile
Collision between line and ball problem
« Reply #1 on: June 01, 2011, 12:32:03 am »
The most efficient way to do it would probably be to use a specialized Separating Axis Theorem implementation.
If it's an infinite line, then translate the circle parallel to the line until either the x or y coordinate is 0, then check if the distance of the circle's center from the origin is less than or equal to the radius of the circle. If it is, there's a collision. Otherwise, no collision.
I use the latest build of SFML2

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Collision between line and ball problem
« Reply #2 on: June 01, 2011, 05:01:02 am »
I don't see where you're using p2 in your Check function.  You only have one of the line points and the circle point.  There's no way the function could possibly work with just that.

EDIT:  you also don't have the diameter/radius of the circle...

reDo

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Collision between line and ball problem
« Reply #3 on: June 01, 2011, 06:29:25 am »
I cant understand why it is not working because math is good I think
Please tell me where is mistake in code please  :roll:
Better explained plan, I know the line is not infinite on plan but in code it is

little modificated source
Code: [Select]
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <cmath>
#include <iostream>

using std::cout;
using std::endl;

struct point
{
    float x;
    float y;
    float distance;
};

bool Check(point & Point, float CircX, float CircY, float radius)
{
    float CircAngle = atan2(CircY,CircX);
    cout<<"CircAngle = "<<CircAngle<<" radians, "<<CircAngle*180/3.14<<" degrees"<<endl;

    float PointAngle = atan2(Point.y,Point.x);
    cout<<"PointAngle = "<<PointAngle<<" radians, "<<PointAngle*180/3.14<<" degrees"<<endl;

    float angle = CircAngle - PointAngle;
    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;
    }

    float distance_circle_point = sqrt( pow(Point.x - CircX,2) + pow(Point.y - CircY,2) );
    cout<<"distance_circle_point = "<<distance_circle_point<<endl;

    float distance = sin(angle) * distance_circle_point;
    cout<<"distance = "<<distance<<endl;

    cout<<endl<<endl;

    if(distance <= radius)
        return true;

    return false;
}

int main()
{
    sf::RenderWindow App(sf::VideoMode(800, 600, 32), "animation");

    float x=400, y=300, radius = 30;

    point p1 = {0,0}, p2 = {500,600};

    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))
            y-=2;

        if (App.GetInput().IsKeyDown(sf::Key::Down))
            y+=2;

        if (App.GetInput().IsKeyDown(sf::Key::Right))
            x+=2;

        if (App.GetInput().IsKeyDown(sf::Key::Left))
            x-=2;

        App.Clear();

        if(Check(p1,x,y,radius) || Check(p2,x,y,radius))
           App.Draw(sf::Shape::Circle(20, 20, 20, sf::Color(0,255,0)));
        App.Draw(sf::Shape::Line(p1.x, p1.y, p2.x, p2.y, 2, sf::Color(0,255,255)));
        App.Draw(sf::Shape::Circle(x, y, radius, sf::Color(255,128,0)));
        App.Display();
        sf::Sleep(0.025f);
    }


    return EXIT_SUCCESS;
}

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Collision between line and ball problem
« Reply #4 on: June 01, 2011, 07:09:34 am »
Quote
1.  get first point angle (one is enough because the line is infinite and the second point has the same angle)


This isn't true.  A line is defined by two points.  If you only have 1 point, the line could be moving in any direction and it'd be impossible to determine.

You need either a second point or an angle to specify the orientation of the line.  Without this it's impossible to know what line you have.

Your function does not have this.  It's trying to solve a problem that it doesn't have enough information to solve.  How could you possibly be getting that "angle" in your diagram without knowing a second point on the line?

EDIT:

I would solve the problem with something like this:





EDIT 2:

Here's some (untested) code that should do the trick.  Again note:  untested.

Code: [Select]

// handy Point typedef
typedef sf::Vector2<double>     Point;

// Perpendicular dot product
inline double PerpDot(const Point& a,const Point& b)                    { return (a.y*b.x) - (a.x*b.y); }

// Line vs. Line Segment Collision
bool LineVsSegmentCollision(const Point& lineA,const Point& lineB,const Point& segA,const Point& segB)
{
    // the vector of the line
    Point line( lineB - lineA );

    // vectors from one point of the line to each line segment
    Point A( segA - lineA );
    Point B( segB - lineA );

    // segment intersects with the line if each endpoint is on opposing sides of the line.
    //  which side the endpoint is on can be determined by examining the sign of the perpdot product
    return (PerpDot(line,A) < 0) != (PerpDot(line,B) < 0);
}

// Line vs. Circle Collision
bool LineVsCircleCollision(const Point& lineA,const Point& lineB,const Point& circle,double radius)
{
    //we need to get a line segment that is of length equal to the diameter of the circle
    //  centered on the circle's center point
    //  and perpendicular to the line
    // Step 1)  Get a unit vector of the line
    Point unit( lineB - lineA );
    double linelength = sqrt( (unit.x * unit.x) + (unit.y * unit.y) );
    unit /= linelength;


    // now make the unit vector perpendicular
    //  a perpendicular line is:
    //  x = y'
    //  y = -x'
    double x = unit.x;
    unit.x = unit.y;
    unit.y = -x;

    // now extend the unit vector by our radius
    unit *= radius;

    // the line segment is now 'circle' extending out in each direction by 'unit'
    Point a = circle + unit;
    Point b = circle - unit;

    // now that we have the line segment, hand the job off to LineVsSegmentCollision
    return LineVsSegmentCollision(lineA,lineB,a,b);
}


EDIT 3:  fixed LineVsSegmentCollision

reDo

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Collision between line and ball problem
« Reply #5 on: June 01, 2011, 04:15:19 pm »
I dont know vector stuff like dot product and so on, so I have to learn it but I thought my solution will solve that problem . :(

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Collision between line and ball problem
« Reply #6 on: June 01, 2011, 04:38:03 pm »
Quote
I dont know vector stuff like dot product and so on, so I have to learn it


You should learn it.  Especially if you want to do this kind of math.  It really makes it much, much easier.  Dot product and perpendicular dot product are really quite magical, and they're not that complicated.

Quote
but I think my solution will solve that problem


It should work fine if you get the information correct.

The thing is you're not referencing an origin point in your calculations.  You're just using an arbitrary line point and the circle's center.  Therefore your angles are probably wrong.

Look at what you're doing here:
Code: [Select]

bool Check(point & Point, float CircX, float CircY, float radius)
{
    float CircAngle = atan2(CircY,CircX);
    cout<<"CircAngle = "<<CircAngle<<" radians, "<<CircAngle*180/3.14<<" degrees"<<endl;

    float PointAngle = atan2(Point.y,Point.x);
    cout<<"PointAngle = "<<PointAngle<<" radians, "<<PointAngle*180/3.14<<" degrees"<<endl;


To get PointAngle you're just calling atan2 with the Point.y and Point.x.  This won't work.  atan2 gets the angle based on the origin (origin point = 0,0).

To illustrate that:



If you want this to work, you need to give the lines you're projecting new origins.  Basically you want to move the origin to a point on the line.  You do this by subtracting the desired origin point from the target point, which gets you the line's vector.   This is why you need two line points:

Code: [Select]

Point linevector = LineB - LineA;  // LineA is our origin point
Point circlevector = Circle - LineA;  // same

// now if we atan2, we'll get the proper angle
double circangle = atan2(circlevector.y,circlevector.x);
double lineangle = atan2(linevector.y,linevector.x);

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Collision between line and ball problem
« Reply #7 on: June 01, 2011, 08:30:15 pm »
Can't you use dot product to find the closest point on the line from the circle ?

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Collision between line and ball problem
« Reply #8 on: June 01, 2011, 08:33:27 pm »
Possibly.  It's probably not as simple as just a single dot product, but I'm sure there's a way to figure it out.  I'd have to think about it some more.


Also @ OP:

Note that everything I've been doing is based on the collision line being infinite.  If the collision line is a finite line segment, then that problem is an entirley different beast and you shouldn't be wasting your time solving for an infinite line.

So which are you looking for?

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Collision between line and ball problem
« Reply #9 on: June 01, 2011, 09:34:49 pm »

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Collision between line and ball problem
« Reply #10 on: June 02, 2011, 07:04:14 am »
oh duh... yeah just project onto the line.

That's much simpler.  And faster... no trig functions needed and only 1 division!

Again untested:
Code: [Select]

// 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);
}



EDIT:  I wonder if the OP is even still interested?

reDo

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Collision between line and ball problem
« Reply #11 on: June 02, 2011, 08:49:30 pm »
I tried both ways from Disch, it works only when it has 45, 90, 135, ...  angles :( , I just tried it and dont know how it works , but you can improve it if you want
Code: [Select]
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <cmath>
#include <iostream>

using std::cout;
using std::endl;

struct Point
{
    double x;
    double y;
};

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;    // the line vector
    line.x = lineB.x - lineA.x;
    line.y = lineB.x - lineA.x;

    Point circ;     // the vector of the origin line point to the circle center
    circ.x = circle.x - lineA.x;
    circ.y = circle.y - lineA.y;


    // 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;
    nearest.x = line.x * proj + lineA.x;
    nearest.y = line.y * proj + lineA.y;

    // '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; // the vector between the circle and the nearest point on the line
    dist.x = circle.x - nearest.x;
    dist.y = circle.y - nearest.y;


    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,300}, circle = {400,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;
}

bug with Check function Point2 x = 300, Point 2 y = 300
http://imageshack.us/photo/my-images/849/error1z.jpg/

LineVsCircleCollision and Check functions OK Point2 x = 300, Point 2 y = 300
http://imageshack.us/photo/my-images/851/error2i.jpg/

both functions's bug Point2 x = 300, Point 2 y = 600
http://imageshack.us/photo/my-images/830/error3u.jpg/

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Collision between line and ball problem
« Reply #12 on: June 02, 2011, 11:45:35 pm »
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?

Code: [Select]
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.

Code: [Select]

#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:

Code: [Select]
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:

Code: [Select]

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.

reDo

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Collision between line and ball problem
« Reply #13 on: June 03, 2011, 05:42:18 am »
I am really happy with this kind of help, thanks a milion for your patience and time spent with this.  :D Yes I wanna to learn it, I am learning it from http://www.tonypa.pri.ee/vectors/start.html
and then I wanna learn from here
http://www.metanetsoftware.com/technique/tutorialA.html
If I found some problem I will write here or directly to you.
 :wink:

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Collision between line and ball problem
« Reply #14 on: June 03, 2011, 06:51:36 am »
Dot product is very simple.  It's kind of magical in a way.

As you can see from my code:
Code: [Select]

Dot( a, b )
{
  return (a.x * b.x) + (a.y * b.y);
}


Perpendicular dot product is the same idea, only you take a vector perpendicular to a (or b):

Code: [Select]

PerpDot( a, b )
{
  return (a.y*b.x) - (a.x*b.y);
}


Now... what makes this significant is that:

Dot(a,b) == cos(theta) * length(a) * length(b)
and
PerpDot(a,b) == sin(theta) * length(a) * length(b)

(where theta is the angle between a,b)

This can be useful for any number of things.  For example, if you want to find out if two lines are parallel, you can just do a perpdot on their vectors (if they're parallel, sin(theta) will be 0, therefore the perpdot will also be 0)

In my function I used Dot to do projection, which "projects" a point onto a vector.

Projection is easiest to visualize like you're looking at a TV or monitor.  Here's a diagram to illustrate:



In my code I projected A onto B with the below:

Code: [Select]
double proj = Dot(A,B) / Dot(B,B);

But how does that work?

Well remember that Dot(A,B) = cos(theta) * len(A) * len(B)
So that means that the above can be simplified:

Code: [Select]
Dot(A,B)   cos(theta) * len(A) * len(B)    cos(theta) * len(A)                
________ = ____________________________ =  ___________________
Dot(B,B)     cos(0) * len(B) * len(B)           1 * len(B)


                len(A)
 = cos(theta) * ______
                len(B)


cos(theta) * len(A) is how far along the desired axis our vector extends.  And dividing it by len(B) scales it down to be relative to the target vector (our TV screen).

This means that if the projected point is lying on our target vector, the above calculation would have given us a value between 0..1


The rest of my function should be pretty self explanitory.  Let me know if you need any further clarification.