Circle line-segment collision detection algorithm?

前端 未结 28 1765
被撕碎了的回忆
被撕碎了的回忆 2020-11-22 06:38

I have a line from A to B and a circle positioned at C with the radius R.

\"Image\"

What is a good alg

28条回答
  •  轮回少年
    2020-11-22 06:57

    Here is my solution in TypeScript, following the idea that @Mizipzor suggested (using projection):

    /**
     * Determines whether a line segment defined by a start and end point intersects with a sphere defined by a center point and a radius
     * @param a the start point of the line segment
     * @param b the end point of the line segment
     * @param c the center point of the sphere
     * @param r the radius of the sphere
     */
    export function lineSphereIntersects(
      a: IPoint,
      b: IPoint,
      c: IPoint,
      r: number
    ): boolean {
      // find the three sides of the triangle formed by the three points
      const ab: number = distance(a, b);
      const ac: number = distance(a, c);
      const bc: number = distance(b, c);
    
      // check to see if either ends of the line segment are inside of the sphere
      if (ac < r || bc < r) {
        return true;
      }
    
      // find the angle between the line segment and the center of the sphere
      const numerator: number = Math.pow(ac, 2) + Math.pow(ab, 2) - Math.pow(bc, 2);
      const denominator: number = 2 * ac * ab;
      const cab: number = Math.acos(numerator / denominator);
    
      // find the distance from the center of the sphere and the line segment
      const cd: number = Math.sin(cab) * ac;
    
      // if the radius is at least as long as the distance between the center and the line
      if (r >= cd) {
        // find the distance between the line start and the point on the line closest to
        // the center of the sphere
        const ad: number = Math.cos(cab) * ac;
        // intersection occurs when the point on the line closest to the sphere center is
        // no further away than the end of the line
        return ad <= ab;
      }
      return false;
    }
    
    export function distance(a: IPoint, b: IPoint): number {
      return Math.sqrt(
        Math.pow(b.z - a.z, 2) + Math.pow(b.y - a.y, 2) + Math.pow(b.x - a.x, 2)
      );
    }
    
    export interface IPoint {
      x: number;
      y: number;
      z: number;
    }
    

提交回复
热议问题