Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 [source] circle - line segment collision detection
Index -> Programming, Turing -> Turing Submissions
View previous topic Printable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
zylum




PostPosted: Mon May 08, 2006 11:35 pm   Post subject: [source] circle - line segment collision detection

this is something I recently started working on. it still needs work with collisions at the vertices but that shouldnt be too hard to take care of. this could be useful if you want to make a pinball game.

code:
View.Set ("offscreenonly,graphics:600;600,nobuttonbar")

type Point :
    record
        x, y : real
    end record

fcn closestPoint (p1, p2, p3 : Point) : Point
    var ret : Point
    var u : real := ((p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y)) / Math.Distance (p1.x, p1.y, p2.x, p2.y) ** 2
    ret.x := p1.x + u * (p2.x - p1.x)
    ret.y := p1.y + u * (p2.y - p1.y)
    if ret.x < min (p1.x, p2.x) then
        if p1.x < p2.x then
            ret := p1
        else
            ret := p2
        end if
    elsif ret.x > max (p1.x, p2.x) then
        if p1.x > p2.x then
            ret := p1
        else
            ret := p2
        end if
    end if
    result ret
end closestPoint

fcn dist (p1, p2 : Point) : real
    result Math.Distance (p1.x, p1.y, p2.x, p2.y)
end dist

fcn whatAngle (x1, y1, x2, y2 : real) : real
    var dx, dy, ratio, angle : real
    dx := x2 - x1
    dy := y2 - y1
    if dx not= 0 then
        ratio := dy / dx
    else
        ratio := dy / 0.00001
    end if
    angle := arctand (abs (ratio))
    if dx < 0 then
        angle := 180 - angle
    end if
    if dy < 0 then
        angle := 360 - angle
    end if
    result round (angle)
end whatAngle

proc drawLine (p1, p2 : Point)
    Draw.Line (round (p1.x), round (p1.y), round (p2.x), round (p2.y), black)
    Draw.FillOval (round (p1.x), round (p1.y), 3, 3, white)
    Draw.Oval (round (p1.x), round (p1.y), 3, 3, black)
    Draw.FillOval (round (p2.x), round (p2.y), 3, 3, white)
    Draw.Oval (round (p2.x), round (p2.y), 3, 3, black)
end drawLine

const POINTS := 8
const RADIUS := 20
const GRAVITY := 0.001

var points : array 1 .. POINTS of Point
for i : 1 .. POINTS
    %points (i).y := Rand.Int (maxy div 2 - 10, maxy div 2 + 10) - 100
    %points (i).x := (maxx / (POINTS - 1)) * (i - 1)
    points (i).x := cosd ((-i + 1) * (180 / (POINTS - 1))) * (maxx div 2) + maxx div 2
    points (i).y := sind ((-i + 1) * (180 / (POINTS - 1))) * (maxx div 2) + maxy div 2
end for

var p, d, V, P, Z : Point
var vx, vy, angle, mag, s : real := 0
p.x := maxx
p.y := maxy div 2 + 50
Z.x := 0
Z.y := 0
vx := -0.3

loop
    for i : 1 .. POINTS - 1
        drawLine (points (i), points (i + 1))
        Draw.Oval (round (p.x), round (p.y), RADIUS, RADIUS, black)
        d := closestPoint (points (i), points (i + 1), p)
        if dist (p, d) <= RADIUS then
            s := Math.Distance (0, 0, vx, vy)

            angle := whatAngle (0, 0, -vx, -vy) - (whatAngle (points (i + 1).x, points (i + 1).y, points (i).x, points (i).y) + 90)
            angle := (whatAngle (points (i + 1).x, points (i + 1).y, points (i).x, points (i).y) + 90) - angle

            vx := cosd (angle) * s
            vy := sind (angle) * s
        end if
        %drawLine (p, closestPoint (points (i), points (i + 1), p))
    end for

    if p.x <= RADIUS| p.x >= maxx - RADIUS then
        p.x := max (RADIUS, min (maxx - RADIUS, p.x))
        vx *= -1
    elsif p.y >= maxy - RADIUS then
        p.x := maxy - RADIUS
        vy *= -1
    end if

    p.x += vx
    p.y += vy
    vy -= GRAVITY

    locate (1, 1)
    put "X: ", p.x, " Y: ", p.y
    put "VX: ", vx, " VY: ", vy
    put angle

    View.Update
    cls
end loop
Sponsor
Sponsor
Sponsor
sponsor
[Gandalf]




PostPosted: Mon May 08, 2006 11:51 pm   Post subject: (No subject)

Very nice! What else is there to say... No gaping bugs that I can see. Smile

Just one thing... And I may be being completely ignorant to say this since I have not taken the time to understand your code, but... Could not such a collision be detected via Math.DistancePointLine()?

Here is the code for that function (inside the Math module) just in case:
code:
    %
    % Calculate the distance between a point and a line segment
    %
    function DistancePointLine (px, py, x1, y1, x2, y2 : real) : real
        var lineSize : real := Distance (x1, y1, x2, y2)
        if lineSize = 0 then
            result Distance (px, py, x1, y1)
        end if

        var u : real := ((px - x1) * (x2 - x1) +
            (py - y1) * (y2 - y1)) / (lineSize * lineSize)

        if u < 0.0 then
            result Distance (px, py, x1, y1)
        elsif u > 1.0 then
            result Distance (px, py, x2, y2)
        else
            var ix : real := x1 + u * (x2 - x1)
            var iy : real := y1 + u * (y2 - y1)
            result Distance (px, py, ix, iy)
        end if
    end DistancePointLine
jamonathin




PostPosted: Tue May 09, 2006 9:50 am   Post subject: (No subject)

This is very cool. I too haven't taken too much time in trying to figure it out (maybe you could comment a little Very Happy). From this model you could almost make a pinball game, except for the simple fact that this model represents a perfect machine and never seems to die down. As a matter of fact, lets speed things up and go:

vy -= GRAVITY * 100

It's . . more than perfect!!! AMAZING!! lol

Very well done zylum. Claping
zylum




PostPosted: Tue May 09, 2006 2:45 pm   Post subject: (No subject)

hmm... i didnt know that function exists Laughing. but wow, they use the exact same method that i use, the only difference is that i return the point that is closest to the ball.. this helps me with the collision reaction. also, they uses a slightly different method than me to check whether the point is on the line segment..
Display posts from previous:   
   Index -> Programming, Turing -> Turing Submissions
View previous topic Tell A FriendPrintable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 4 Posts ]
Jump to:   


Style:  
Search: