Quote: "I'm sure there's a method that returns the 0.0-1.0 percentage of where the line intersects "
That's the easy part.
Quote: "this is just an eyeball guess but i think the angle between the center of the circle and where it meets the line is a right angle"
Correct, the normal of the line to the circle would make the shortest distance between the two.
I think I just needed some sleep. Dot product kept yelling in my head last night but I wasn't sure how/where to use it. I think I got it now.
When the circle hits the line, it forms a right triangle, one leg being a normal from the line and equal to the radius of the circle. Create two vectors, one being the direction of travel for the circle and the other the line normal, call these A and B. Take the dot product of the two vectors and divide by the product of the vector lengths to find the angle between them.
Now we know two parts of the triangle that's formed in this problem. The angle and the length of the adjacent leg (radius). Using good old SOHCAHTOA, you can then calculate the length of the hypotenuse. The equation can be simplified so we don't even need to use cosine. Now, starting at the intersection point of the two lines, traverse back along the direction vector of the circle by a distance equal to the hypotenuse. This new point is where the circle will hit the line along it's path.
To find the actual point of contact, take this new point and subtract (or add, depending on direction of movement and normal) the line normal times the radius of the circle. You now have all points along the line you need to then easily calculate a time index of intersection, if you still need it at this point.
Here's some dirty code for an example. (There's plenty of stuff in it that's not even used)
setVirtualResolution(800,600)
Type Point2D
x as float
y as float
EndType
A as Point2D
B as Point2D
C as Point2D
D as Point2D
E as Point2D
F as Point2D
G as Point2D
H as Point2D
`A.x = 40
`A.y = 30
B.x = 400
B.y = 300
C.x = 350
C.y = 75
D.x = 50
D.y = 500
radius = 30
scale# = 1.0 / radius
do
A.x = getRawMouseX()
A.y = getRawMouseY()
`v# = sqrt((B.x-A.x)^2 + (B.y-A.y)^2)
drawCircle(A.x, A.y, radius,0,255,0)
drawCircle(B.x, B.y, radius,0,255,255)
drawLine(A.x, A.y, B.x, B.y, 200,200,200)
drawLine(C.x, C.y, D.x, D.y, 255,255,0)
`E.x = A.x * scale# : E.y = A.y * scale#
`F.x =
`G.x = C.x * scale# : G.y = C.y * scale#
`H.x = D.x * scale# : H.y = D.y * scale#
t# = lineIntersection(A, B, C, D)
// line normal
nx# = -(d.y-c.y)
ny# = (d.x-c.x)
s# = sqrt(nx#*nx# + ny#*ny#)
nx# = nx# / s#
ny# = ny# / s#
// direction normal
dx# = b.x - a.x
dy# = b.y - a.y
d# = sqrt(dx#^2 + dy#^2)
dx# = dx# / d#
dy# = dy# / d#
// line/wall
drawLine(c.x, c.y, c.x+nx#*20,c.y+ny#*20, 255,255,0)
// finds closet point on line to starting circle position
x = D.x - C.x
y = D.y - C.y
n# = ((A.x - C.x) * x) + ((A.y - C.y) * y)
d# = x^2 + y^2
u# = N# / d#
if u# >= 0 and u# <= 1
ix# = C.x + (D.x-C.x)*u#
iy# = C.y + (D.y-C.y)*u#
`k# = sqrt((ix#-A.x)^2 + (iy#-A.y)^2)
`drawCircle(ix#, iy#, 5, 0,255,0)
`e# = A.x - ix#
`f# = A.y - iy#
`dist# = sqrt(e#^2 + f#^2)
endif
`ix# = fx# - nx#*radius
`iy# = fy# - ny#*radius
Alen# = radius
Blen# = sqrt((C.x - zx#)^2 + (C.y-zy#)^2)
alphaX# = B.x - A.x
alphaY# = B.y - A.y
betaX# = -nx#*radius
betaY# = -ny#*radius
Alen# = sqrt((B.x - A.x)^2 + (B.y - A.y)^2)
Blen# = radius
dp# = alphaX#*betaX# + alphaY#*betaY#
a# = (dp# / (Alen#*Blen#))
h# = radius / (a#)
// intersection of two lines
zx# = A.x + (B.x-A.x)*t#
zy# = A.y + (B.y-A.y)*t#
drawCircle(zx#, zy#, 4, 255,0,0)
fx# = zx# - dx#*h#
fy# = zy# - dy#*h#
drawCircle(fx#, fy#, radius, 255,0,255)
ix# = fx# - nx#*radius
iy# = fy# - ny#*radius
drawCircle(ix#, iy#, 5, 0,255,0)
if getRawKeyPressed(27) = 1 then end
Sync()
loop
function drawCircle(x, y, radius, r,g,b)
x1 = x+radius
y1 = y
for i = 0 to 360 step 10
x2 = x + cos(i)*radius
y2 = y + sin(i)*radius
drawLine(x1, y1, x2, y2, r,g,b)
x1 = x2
y1 = y2
next i
endfunction
rem Returns time value along line AB for intersection with line CD
function lineIntersection(A as Point2D, B as Point2D, C as Point2D, D as Point2D)
n# = ((D.x-C.x) * (A.y-C.y)) - ((D.y-C.y) * (A.x-C.x))
d# = ((D.y-C.y) * (B.x-A.x)) - ((D.x-C.x) * (B.y-A.y))
t# = n# / d#
endfunction t#
"I like offending people, because I think people who get offended should be offended." - Linus Torvalds