Welcome back to my blog 🙂
An email from Andre, the programmer on the gloriously pretty bunnibunni set me on the right track, although my revised technique is slightly different than his.
The new way
Ok, lets have another look at the problem.
What we actually want to have is a distance function; we'd like to know the distance from any given point to the exterior of the map in Figure 1 and Figure 4. Once we have this we can tell if we're inside or outside the map and also (with the addition of closet point on exterior) the shortest direction to the exterior and therefore contact normal.
The way to achieve this is actually quite simple. All you need to do is to take your candidate point and project it on to the edge of each circle. If the projected point lies inside another circle it is discarded, if not that is the closest point to the circle.
If all projected points lie inside another circle, the distance to the exterior is the closest distance to an exterior vertex (shown in green in Figure 1).
In Figure 2, the projected points (shown in blue) are inside another circle and so are discarded, leaving the closest distance to be the distance to the closer of the two external vertices.
In Figure 3, the projected point lies does not lie within another circle and therefore is the closest.
With this new method you don't need to worry about arc-lengths or even have to bother with any kind of cheating (as detailed in part 2) and indeed, you don't need to think about having a solver in order to resolve the collision because there is only one possible closest point returned - you can just use the simple technique i outlined in part 2.
Its just a much better way of doing things 🙂
Thank you to Andre for pointing me in the right direction...
There is no live example since it looks pretty much identical to the previous version. But, i've uploaded the code for you to inspect here - should be a lot easier to follow. BreakingOutOfTheGrid2.zip