Intersection between a line and a sphere

前端 未结 8 2446
无人及你
无人及你 2021-02-09 05:51

I\'m trying to find the point of intersection between a sphere and a line but honestly, I don\'t have any idea of how to do so. Could anyone help me on this one ?

8条回答
  •  广开言路
    2021-02-09 06:32

    I believe there is an inaccuracy in the solution by Markus Jarderot. Not sure what the problem is, but I'm pretty sure I translated it faithfully to code, and when I tried to find the intersection of a line segment known to cross into a sphere, I got a negative discriminant (no solutions).

    I found this: http://www.codeproject.com/Articles/19799/Simple-Ray-Tracing-in-C-Part-II-Triangles-Intersec, which gives a similar but slightly different derivation.

    I turned that into the following C# code and it works for me:

        public static Point3D[] FindLineSphereIntersections( Point3D linePoint0, Point3D linePoint1, Point3D circleCenter, double circleRadius )
        {
            // http://www.codeproject.com/Articles/19799/Simple-Ray-Tracing-in-C-Part-II-Triangles-Intersec
    
            double cx = circleCenter.X;
            double cy = circleCenter.Y;
            double cz = circleCenter.Z;
    
            double px = linePoint0.X;
            double py = linePoint0.Y;
            double pz = linePoint0.Z;
    
            double vx = linePoint1.X - px;
            double vy = linePoint1.Y - py;
            double vz = linePoint1.Z - pz;
    
            double A = vx * vx + vy * vy + vz * vz;
            double B = 2.0 * (px * vx + py * vy + pz * vz - vx * cx - vy * cy - vz * cz);
            double C = px * px - 2 * px * cx + cx * cx + py * py - 2 * py * cy + cy * cy +
                       pz * pz - 2 * pz * cz + cz * cz - circleRadius * circleRadius;
    
            // discriminant
            double D = B * B - 4 * A * C;
    
            if ( D < 0 )
            {
                return new Point3D[ 0 ];
            }
    
            double t1 = ( -B - Math.Sqrt ( D ) ) / ( 2.0 * A );
    
            Point3D solution1 = new Point3D( linePoint0.X * ( 1 - t1 ) + t1 * linePoint1.X,
                                             linePoint0.Y * ( 1 - t1 ) + t1 * linePoint1.Y,
                                             linePoint0.Z * ( 1 - t1 ) + t1 * linePoint1.Z );
            if ( D == 0 )
            {
                return new Point3D[] { solution1 };
            }
    
            double t2 = ( -B + Math.Sqrt( D ) ) / ( 2.0 * A );
            Point3D solution2 = new Point3D( linePoint0.X * ( 1 - t2 ) + t2 * linePoint1.X,
                                             linePoint0.Y * ( 1 - t2 ) + t2 * linePoint1.Y,
                                             linePoint0.Z * ( 1 - t2 ) + t2 * linePoint1.Z );
    
            // prefer a solution that's on the line segment itself
    
            if ( Math.Abs( t1 - 0.5 ) < Math.Abs( t2 - 0.5 ) )
            {
                return new Point3D[] { solution1, solution2 };
            }
    
            return new Point3D[] { solution2, solution1 };
        }
    

提交回复
热议问题