distance from given point to given ellipse

后端 未结 7 1954
抹茶落季
抹茶落季 2021-02-05 08:07

I have an ellipse, defined by Center Point, radiusX and radiusY, and I have a Point. I want to find the point on the ellipse that is closest to the given point. In the illustrat

7条回答
  •  长发绾君心
    2021-02-05 08:23

    Here is the code translated to C# implemented from this paper to solve for the ellipse: http://www.geometrictools.com/Documentation/DistancePointEllipseEllipsoid.pdf

    Note that this code is untested - if you find any errors let me know.

        //Pseudocode for robustly computing the closest ellipse point and distance to a query point. It
        //is required that e0 >= e1 > 0, y0 >= 0, and y1 >= 0.
        //e0,e1 = ellipse dimension 0 and 1, where 0 is greater and both are positive.
        //y0,y1 = initial point on ellipse axis (center of ellipse is 0,0)
        //x0,x1 = intersection point
    
        double GetRoot ( double r0 , double z0 , double z1 , double g )
        {
            double n0 = r0*z0;
            double s0 = z1 - 1; 
            double s1 = ( g < 0 ? 0 : Math.Sqrt(n0*n0+z1*z1) - 1 ) ;
            double s = 0;
            for ( int i = 0; i < maxIter; ++i ){
                s = ( s0 + s1 ) / 2 ;
                if ( s == s0 || s == s1 ) {break; }
                double ratio0 = n0 /( s + r0 );
                double ratio1 = z1 /( s + 1 );
                g = ratio0*ratio0 + ratio1*ratio1 - 1 ;
                if (g > 0) {s0 = s;} else if (g < 0) {s1 = s ;} else {break ;}
            }
            return s;
        }
        double DistancePointEllipse( double e0 , double e1 , double y0 , double y1 , out double x0 , out double x1)
        {
            double distance;
            if ( y1 > 0){
                if ( y0 > 0){
                    double z0 = y0 / e0; 
                    double z1 = y1 / e1; 
                    double g = z0*z0+z1*z1 - 1;
                    if ( g != 0){
                        double r0 = (e0/e1)*(e0/e1);
                        double sbar = GetRoot(r0 , z0 , z1 , g);
                        x0 = r0 * y0 /( sbar + r0 );
                        x1 = y1 /( sbar + 1 );
                        distance = Math.Sqrt( (x0-y0)*(x0-y0) + (x1-y1)*(x1-y1) );
                        }else{
                            x0 = y0; 
                            x1 = y1;
                            distance = 0;
                        }
                    }
                    else // y0 == 0
                        x0 = 0 ; x1 = e1 ; distance = Math.Abs( y1 - e1 );
            }else{ // y1 == 0
                double numer0 = e0*y0 , denom0 = e0*e0 - e1*e1;
                if ( numer0 < denom0 ){
                        double xde0 = numer0/denom0;
                        x0 = e0*xde0 ; x1 = e1*Math.Sqrt(1 - xde0*xde0 );
                        distance = Math.Sqrt( (x0-y0)*(x0-y0) + x1*x1 );
                    }else{
                        x0 = e0; 
                        x1 = 0; 
                        distance = Math.Abs( y0 - e0 );
                }
            }
            return distance;
        }
    

提交回复
热议问题