In addition to the answers above, you have to be careful with division by zero errors.
These will come about if one of the lines is verticle (ie ax# = bx# and or cx# = dx#) or if the lines are parallel (mab# = mcb#).
I played around with Sixty Squares' code, making vetical lines or parallel lines and although it didn't crash the program, it did come up with incorrect answers for the intersect point. I changed the coordinates to the following:
ax#=5
ay#=5
bx#=5
by#=425
cx#=10
cy#=450
dx#=10
dy#=0
and it gave an intersect point of 0,5, which is impossible as the lines are parallel.
Obviously if the lines are parellel then there can not be an intersection but if one of the lines is vertical the two lines still intersect so you need to account for this in your code.
Example: if ax# = bx# then the line ab is vertical which means the x intersect will be equal to ax# (or bx#)
Also, the maths apply to lines of infinite length and so will return an intersection even if the lines themselves do not actually cross. This may or may not be an issue depending on what you're doing.
I looked at this same problem earlier this year and decided that using a simillar method to determining point in triangle can also be used for two lines crossing:
`This is a 2d demo that determines if 2 lines have interesected each other
`By 29 Games
`21 December 2010
`Move the mouse to drag one of the lines
sync on
`first line
ax# = 300 : ay# = 100
bx# = 300 : by# = 300
`second line start point
cx# = 150 : cy# = 400
do
cls
`second line end point based on mouse position
dx# = mousex()
dy# = mousey()
`this determines if the two lines have crossed
if LINES_CROSS(ax#,ay#,bx#,by#, cx#,cy#,dx#,dy#) = 1
ink rgb(250,0,0),0
else
ink rgb(0,250,0),0
endif
`draw lines
line ax#,ay#, bx#,by#
line cx#,cy#, dx#,dy#
set cursor 0,0
print "Move mouse to pull line into position"
print "Lines will go red if they cross"
sync
loop
function LINES_CROSS(ax#,ay#,bx#,by#, cx#,cy#,dx#,dy#):
`this simply makes use of the same side function and determines if two line have crossed
`note that this can be used without having to calculate the intersect point of the two lines
`also avoids any division by zero errors.
if POINTS_ON_SAME_SIDE(ax#,ay#, bx#,by#, cx#,cy#,dx#,dy#) = 0
if POINTS_ON_SAME_SIDE(cx#,cy#, dx#,dy#, ax#,ay#,bx#,by#) = 0
yes = 1
else
yes = 0
endif
else
yes = 0
endif
endfunction yes
function POINTS_ON_SAME_SIDE(px#,py#, rx#,ry#, sx#,sy#,fx#,fy#)
`this function determines if point p is on same side of line sf as point r
psi# = px# - sx#: psj# = py# - sy# :`vector ps
fsi# = fx# - sx#: fsj# = fy# - sy# :`vector fs
rsi# = rx# - sx#: rsj# = ry# - sy# :`vector rs
fs_cross_ps# = fsi#*psj# - psi#*fsj# :`cross product of vectors fs and rs
fs_cross_rs# = fsi#*rsj# - rsi#*fsj# :`cross product of vectors fs and rs
if fs_cross_ps# > 0 then fs_cross_ps# = 1 else fs_cross_ps# = -1
if fs_cross_rs# > 0 then fs_cross_rs# = 1 else fs_cross_rs# = -1
if fs_cross_ps# = fs_cross_rs# then yes = 1 else yes = 0
endfunction yes
The important bit in the code is the function "POINTS_ON_SAME_SIDE", which was originally written as part of some point in triangle code (the basic theory for how this works can be found here http://www.blackpawn.com/texts/pointinpoly/default.html).
Note that this doesn't actually determine the intersect.
However, using the exact same maths as everyone else, code for determining the intersect can be added:
`This is a 2d demo that determines if 2 lines have interesected each other
`then determines the point intersect if the lines have crossed.
`By 29 Games
`21 December 2010
`Move the mouse to drag one of the lines
sync on
`first line
ax# = 300 : ay# = 100
bx# = 300 : by# = 300
`second line start point
cx# = 150 : cy# = 400
do
cls
`end point of line based on mouse position
dx# = mousex()
dy# = mousey()
`this determines if the two lines have crossed
if LINES_CROSS(ax#,ay#,bx#,by#, cx#,cy#,dx#,dy#) = 1
ink rgb(250,0,0),0
`these calculate the coordinates of the intertsection
ix# = X_INTERSECT_AB_CD_ON_XZ(ax#,ay#,bx#,by#, cx#,cy#,dx#,dy#)
iy# = Z_INTERSECT_AB_CD_ON_XZ(ax#,ay#,bx#,by#, cx#,cy#,dx#,dy#)
`draw circle at intersect point
circle ix#,iy#,10
else
ink rgb(0,250,0),0
endif
`draw lines
line ax#,ay#, bx#,by#
line cx#,cy#, dx#,dy#
set cursor 0,0
print "Move mouse to pull line into position"
print "Lines will go red if they cross"
sync
loop
function LINES_CROSS(ax#,ay#,bx#,by#, cx#,cy#,dx#,dy#):
`this simply makes use of the same side function and determines if two line have crossed
`note that this can be used without having to calculate the intersect point of the two lines
`also avoids any division by zero errors.
if POINTS_ON_SAME_SIDE(ax#,ay#, bx#,by#, cx#,cy#,dx#,dy#) = 0
if POINTS_ON_SAME_SIDE(cx#,cy#, dx#,dy#, ax#,ay#,bx#,by#) = 0
yes = 1
else
yes = 0
endif
else
yes = 0
endif
endfunction yes
function POINTS_ON_SAME_SIDE(px#,py#, rx#,ry#, sx#,sy#,fx#,fy#)
`this function determines if point p is on same side of line sf as point r
psi# = px# - sx#: psj# = py# - sy# :`vector ps
fsi# = fx# - sx#: fsj# = fy# - sy# :`vector fs
rsi# = rx# - sx#: rsj# = ry# - sy# :`vector rs
fs_cross_ps# = fsi#*psj# - psi#*fsj# :`cross product of vectors fs and rs
fs_cross_rs# = fsi#*rsj# - rsi#*fsj# :`cross product of vectors fs and rs
if fs_cross_ps# > 0 then fs_cross_ps# = 1 else fs_cross_ps# = -1
if fs_cross_rs# > 0 then fs_cross_rs# = 1 else fs_cross_rs# = -1
if fs_cross_ps# = fs_cross_rs# then yes = 1 else yes = 0
endfunction yes
function X_INTERSECT_AB_CD_ON_XZ(ax#,az#,bx#,bz#, cx#,cz#,dx#,dz#)
`if line ab is parallel with x axis
if az# = bz#
`calculate slope of cd
mcd# = (dx#-cx#)/(dz#-cz#)
`caclulate x intersect
ex# = mcd#*(az# - cz#) + cx#
endif
`if line ab is parallel with z axis
if ax# = bx#
ex# = ax#
endif
`if line cd is parallel with x axis
if cz# = dz#
`calculate slope of ab
mab# = (bx#-ax#)/(bz#-az#)
`calculate x intersect
ex# = mab#*(cz# - az#) + ax#
endif
`if line cd is parallel with x axis
if cx# = dx#
ex# = cx#
endif
`if line ab and line cd are not parallel to x axis
if ax# <> bx# and az# <> bz# and cx# <> dx# and cz# <> dz#
`calculate slope of ab
mab# = (bx#-ax#)/(bz#-az#)
`calculate slope of cd
mcd# = (dx#-cx#)/(dz#-cz#)
`calculate intermediate values (due to possible bug in DBC)
dif_aa# = (ax#/mab#) - (cx#/mcd#)
dif_bb# = cz# - az#
dif_mm# = (1/mab#) - (1/mcd#)
`caclulate x intersect
ex# = (dif_aa# + dif_bb#) / dif_mm#
endif
endfunction ex#
function Z_INTERSECT_AB_CD_ON_XZ(ax#,az#,bx#,bz#, cx#,cz#,dx#,dz#)
`if line ab is parallel with x axis
if az# = bz#
`caclulate z intersect
ez# = az#
endif
`if line cd is parallel with x axis
if cz# = dz#
`caclulate z intersect
ez# = cz#
endif
`if line ab and line cd are not parallel to x axis
if az# <> bz# and cz# <> dz#
`calculate slope of ab
mab# = (bx#-ax#)/(bz#-az#)
`calculate slope of cd
mcd# = (dx#-cx#)/(dz#-cz#)
`calculate intermediate values (due to possible bug in DBC)
dif_aa# = (mab#*az#) - (mcd#*cz#)
dif_bb# = cx# - ax#
dif_mm# = mab# - mcd#
`caclulate x intersect
ez# = (dif_aa# + dif_bb#) / dif_mm#
endif
endfunction ez#
You may note that I use X and Z coordinates as this code was originally for 3D maths collision and I have calculated the slopes to match how angles are measured on the XZ plane but it work perfectly well in 2D (Z just becomes Y).
Just to pre-empt any off topic debate, rather than have a single function and global variables to calculate the intersect point, I've used two functions which is just my style (I prefer to be able to copy and paste functions without having to worry about global variables) and I appreciate that this may not be the most effecient way of going about things