1. 程式人生 > >記錄一下演算法:點到線段的距離計算。

記錄一下演算法:點到線段的距離計算。

C#版

 public double PointLine_Disp(double xx, double yy, double x1, double y1, double x2, double y2)
        {
            double a, b, c, ang1, ang2, ang, m;
            double result = 0;
            //分別計算三條邊的長度
            a = Math.Sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy));
            if (a == 0)
                return -1;
            b = Math.Sqrt((x2 - xx) * (x2 - xx) + (y2 - yy) * (y2 - yy));
            if (b == 0)
                return -1;
            c = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
            //如果線段是一個點則退出函式並返回距離
            if (c == 0)
            {
                result = a;
                return result;
            }
            //如果點(xx,yy到點x1,y1)這條邊短
            if (a < b)
            {
                //如果直線段AB是水平線。得到直線段AB的弧度
                if (y1 == y2)
                {
                    if (x1 < x2)
                        ang1 = 0;
                    else
                        ang1 = Math.PI;
                }
                else
                {
                    m = (x2 - x1) / c;
                    if (m - 1 > 0.00001)
                        m = 1;
                    ang1 = Math.Acos(m);
                    if (y1 >y2)
                        ang1 = Math.PI*2  - ang1;//直線(x1,y1)-(x2,y2)與折X軸正向夾角的弧度
                }
                m = (xx - x1) / a;
                if (m - 1 > 0.00001)
                    m = 1;
                ang2 = Math.Acos(m);
                if (y1 > yy)
                    ang2 = Math.PI * 2 - ang2;//直線(x1,y1)-(xx,yy)與折X軸正向夾角的弧度
               
                ang = ang2 - ang1;
                if (ang < 0) ang = -ang;
               
                if (ang > Math.PI) ang = Math.PI * 2 - ang;
                //如果是鈍角則直接返回距離
                if (ang > Math.PI / 2)
                    return a;
                else
                    return a * Math.Sin(ang);
            }
            else//如果(xx,yy)到點(x2,y2)這條邊較短
            {
                //如果兩個點的縱座標相同,則直接得到直線斜率的弧度
                if (y1 == y2)
                    if (x1 < x2)
                        ang1 = Math.PI;
                    else
                        ang1 = 0;
                else
                {
                    m = (x1 - x2) / c;
                    if (m - 1 > 0.00001)
                        m = 1;
                    ang1 = Math.Acos(m);
                    if (y2 > y1)
                        ang1 = Math.PI * 2 - ang1;
                }
                m = (xx - x2) / b;
                if (m - 1 > 0.00001)
                    m = 1;
                ang2 = Math.Acos(m);//直線(x2-x1)-(xx,yy)斜率的弧度
                if (y2 > yy)
                    ang2 = Math.PI * 2 - ang2;
                ang = ang2 - ang1;
                if (ang < 0) ang = -ang;
                if (ang > Math.PI) ang = Math.PI * 2 - ang;//交角的大小
                //如果是對角則直接返回距離
                if (ang > Math.PI / 2)
                    return b;
                else
                    return b * Math.Sin(ang);//如果是銳角,返回計算得到的距離
            }

        }

JS版

<script type="text/javascript">
     function PointLine_Disp(xx, yy, x1, y1, x2, y2)
     {
        var a, b, c, ang1, ang2, ang, m;
            var result = 0;
            //分別計算三條邊的長度
            a = Math.sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy));
            if (a == 0)
                return -1;
            b = Math.sqrt((x2 - xx) * (x2 - xx) + (y2 - yy) * (y2 - yy));
            if (b == 0)
                return -1;
            c = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
            //如果線段是一個點則退出函式並返回距離
            if (c == 0)
            {
                result = a;
                return result;
            }
            //如果點(xx,yy到點x1,y1)這條邊短
            if (a < b)
            {
                //如果直線段AB是水平線。得到直線段AB的弧度
                if (y1 == y2)
                {
                    if (x1 < x2)
                        ang1 = 0;
                    else
                        ang1 = Math.PI;
                }
                else
                {
                    m = (x2 - x1) / c;
                    if (m - 1 > 0.00001)
                        m = 1;
                    ang1 = Math.acos(m);
                    if (y1 >y2)
                        ang1 = Math.PI*2  - ang1;//直線(x1,y1)-(x2,y2)與折X軸正向夾角的弧度
                }
                m = (xx - x1) / a;
                if (m - 1 > 0.00001)
                    m = 1;
                ang2 = Math.acos(m);
                if (y1 > yy)
                    ang2 = Math.PI * 2 - ang2;//直線(x1,y1)-(xx,yy)與折X軸正向夾角的弧度
               
                ang = ang2 - ang1;
                if (ang < 0) ang = -ang;
               
                if (ang > Math.PI) ang = Math.PI * 2 - ang;
                //如果是鈍角則直接返回距離
                if (ang > Math.PI / 2)
                    return a;
                else
                    return a * Math.sin(ang);
            }
            else//如果(xx,yy)到點(x2,y2)這條邊較短
            {
                //如果兩個點的縱座標相同,則直接得到直線斜率的弧度
                if (y1 == y2)
                    if (x1 < x2)
                        ang1 = Math.PI;
                    else
                        ang1 = 0;
                else
                {
                    m = (x1 - x2) / c;
                    if (m - 1 > 0.00001)
                        m = 1;
                    ang1 = Math.acos(m);
                    if (y2 > y1)
                        ang1 = Math.PI * 2 - ang1;
                }
                m = (xx - x2) / b;
                if (m - 1 > 0.00001)
                    m = 1;
                ang2 = Math.acos(m);//直線(x2-x1)-(xx,yy)斜率的弧度
                if (y2 > yy)
                    ang2 = Math.PI * 2 - ang2;
                ang = ang2 - ang1;
                if (ang < 0) ang = -ang;
                if (ang > Math.PI) ang = Math.PI * 2 - ang;//交角的大小
                //如果是對角則直接返回距離
                if (ang > Math.PI / 2)
                    return b;
                else
                    return b * Math.sin(ang);//如果是銳角,返回計算得到的距離
            }
     }


</script>