c# - Circle line segment collision on corners -


i found 2 amazing tutorials how detect , handle circle vs line segment collision.

seb.ly
tuts plus

and implemented in c# without problems. solution because clean , simple 1 understand.
there not explained how handle collisions on line ends/corners.
whats best way add feature?

on left side illustrated how function behave far. on right how want behave. cases 1 , 2 working great, how want. in case 3 circle not collide. have implement on right side. don't know how work. enter image description here
far have this:

// line defined 2 points. // circle define point , radius. public static bool circlevsline(circle circle, vector2d circledirection, ref vector2d circlesolved, line line) {     // circle position before movement.     vector2d circle0 = circle.position;      // circle position after movement.     vector2d circle1 = circle.position + circledirection;      vector2d linedirection = line.position1 - line.position0;     vector2d linenormal = new vector2d(linedirection.y, -linedirection.x).normalized();      vector2d circle0toline0direction = line.position0 - circle0;     vector2d circle1toline0direction = line.position0 - circle1;      // calculate distance line before movement.     double circle0distancetoline = vector2d.dot(linenormal, circle0toline0direction);      // calculate distance line after movement.     double circle1distancetoline = vector2d.dot(linenormal, circle1toline0direction);      // time when circle radius equals distance line.     double t = (circle.radius - circle0distancetoline) / (circle1distancetoline - circle0distancetoline);      // if true collision on endless line occured.     if (t >= 0 && t <= 1)     {         // epsilon small double number prevent bugs caused rounding errors.         circlesolved = circle0 + circledirection * t - linenormal * epsilon;          vector2d line0toplayersolved = circlesolved - line.position0;         vector2d line1toplayersolved = circlesolved - line.position1;          // if true collision happened on line sgment.         if (vector2d.dot(linedirection, line0toplayersolved) >= 0 && vector2d.dot(linedirection, line1toplayersolved) < 0)         {             return true;         }     }      // no collision circle can moved.     circlesolved = circle1;     return false; } 

the first part of code assumes infinite line. then, second part tries correct first decision. however, not possible examples show. need take line length account in first step.

first, analyze line endpoints. want find parameter t circle touches endpoint:

|| circle0 + t * circledirection - endpoint || == r 

the solution is:

discriminant = 4 * (dot(circle0, circledirection) - dot(circledirection, endpoint))^2                -4 * circledirection^2 * (circle0^2 - 2 * dot(circle0, endpoint) + endpoint^2 - r^2)  t = ( -dot(circle0, circledirection) + dot(circledirection, endpoint)        -1/2 * sqrt(discriminant) ) / circledirection^2 

the notation somevector^2 denotes vector's squared length. if discriminant negative, circle never touch end point. then, either pass line or hit somewhere in middle. code can handle case, skip this. basically, check, case , continue.

if discriminant positive, circle can touch endpoint. if t greater 1, not happen in current simulation time step. can ignore it. if between 0 , 1, have act.

first, have check if end point stop circle or line segment. can check projecting circle center onto line:

circlecollisionposition = circle0 + t * circledirection directiontocollisionposition = circlecollisionposition - line.position0 s = dot(directiontocollisionposition, linedirection) / linedirection.squaredlength 

now, if s between 0 , 1, circle stopped line segment. not 1 of endpoints. then, can recalculate t infinite line (as did in code). if s smaller 0, circle stopped first endpoint , should use t first endpoint. if s greater 1, circle stopped second endpoint , should use according t. if 1 endpoint yields s < 0 , 1 s > 1, use smaller of both t.

then continue calculating circlesolved did in code. end position of circle not move more. subsequent check not necessary anymore, because has taken place.


Comments

Popular posts from this blog

javascript - Slick Slider width recalculation -

jsf - PrimeFaces Datatable - What is f:facet actually doing? -

angular2 services - Angular 2 RC 4 Http post not firing -