Thursday, 26 January 2012

Circle-line intersection

Yesterday's method for determining whether a circle crosses a line can also be used to find where the crossing points are. The approach uses the distance calculated in the hitLine function with some simple circle geometry.

If the line crosses the circle it does so in two places. These are on the circle's circumference, so are r away from the centre, where r is the circle's radius. Together with the centre of the circle they form an isosceles triangle, OAB in the diagram below (from Wikipedia). This can be split into two right-angled triangles, such as the upper triangle OCA. One of the sides is the radius r while the other is the distance calculated as in the hitLine function. So the third side can be calculated using Pythagoras' theorem.

This can then be used to find the point A, using the calculated lengths with the line properties, as follows.

    function hitLineWhere(x1:Number, y1:Number,
        x2:Number, y2:Number):void {
        // calculate the unit vector along the line
        var dX:Number = x1 - x2;
        var dY:Number = y1 - y2;
        var len:Number = Math.sqrt(dX * dX + dY * dY);
        var recip:Number = 1 / len;
        dX *= recip;
        dY *= recip;
        // perp dot product to get line-centre distance
        var fDist:Number (x1 - fX) * dY - (y1 - fY) * dx);
        if (Math.abs(fDist) < fR) {
            // calculate the other side of the triangle
            var fSide:Number = Math.sqrt(fR * fR - fDist * fDist);
            x2 = fX + fDist * dY + fSide * dX;
            y2 = fY - fDist * dX + fSide * dY;
            x3 = fX + fDist * dY - fSide * dX;
            y3 = fY - fDist * dX - fSide * dY;

This function store the two intersection points (x2y2) and (x3, y3), in variables which could be class member variables. Alternately a class could be used. As before dX and dY can be calculated beforehand and stored, maybe in a line class.

No comments:

Post a Comment