C#解决方案在纬度/经度折线上找到最接近的点

时间:2019-05-10 05:47:12

标签: c#

我需要C#解决方案来解决我在Javascript中拥有的某些代码,该代码需要一组形成区域或区域的纬度和经度位置。以及对象X和Y的位置,并返回距对象最近点的X和Y。这段代码在Javascript中可以完美地工作,但是由于我现在正在用C#重写我的工作,因此我无法找到一个可行的解决方案,该解决方案可以执行此功能。

下面是Javascript函数,它带有2个参数pXy(这是您所在位置的X和Y位置)和aXys(这是X和Y位置组成的数组的折线)。

    var getClosestPointOnLines = function(pXy, aXys) {

        var minDist;
        var fTo;
        var fFrom;
        var x;
        var y;
        var i;
        var dist;

        if (aXys.length > 1) {

            for (var n = 1 ; n < aXys.length ; n++) {

                if (aXys[n].x != aXys[n - 1].x) {
                    var a = (aXys[n].y - aXys[n - 1].y) / (aXys[n].x - aXys[n - 1].x);
                    var b = aXys[n].y - a * aXys[n].x;
                    dist = Math.abs(a * pXy.x + b - pXy.y) / Math.sqrt(a * a + 1);
                }
                else
                    dist = Math.abs(pXy.x - aXys[n].x)

                // length^2 of line segment 
                var rl2 = Math.pow(aXys[n].y - aXys[n - 1].y, 2) + Math.pow(aXys[n].x - aXys[n - 1].x, 2);

                // distance^2 of pt to end line segment
                var ln2 = Math.pow(aXys[n].y - pXy.y, 2) + Math.pow(aXys[n].x - pXy.x, 2);

                // distance^2 of pt to begin line segment
                var lnm12 = Math.pow(aXys[n - 1].y - pXy.y, 2) + Math.pow(aXys[n - 1].x - pXy.x, 2);

                // minimum distance^2 of pt to infinite line
                var dist2 = Math.pow(dist, 2);

                // calculated length^2 of line segment
                var calcrl2 = ln2 - dist2 + lnm12 - dist2;

                // redefine minimum distance to line segment (not infinite line) if necessary
                if (calcrl2 > rl2)
                    dist = Math.sqrt(Math.min(ln2, lnm12));

                if ((minDist == null) || (minDist > dist)) {
                    if (calcrl2 > rl2) {
                        if (lnm12 < ln2) {
                            fTo = 0;//nearer to previous point
                            fFrom = 1;
                        }
                        else {
                            fFrom = 0;//nearer to current point
                            fTo = 1;
                        }
                    }
                    else {
                        // perpendicular from point intersects line segment
                        fTo = ((Math.sqrt(lnm12 - dist2)) / Math.sqrt(rl2));
                        fFrom = ((Math.sqrt(ln2 - dist2)) / Math.sqrt(rl2));
                    }
                    minDist = dist;
                    i = n;
                }
            }

            var dx = aXys[i - 1].x - aXys[i].x;
            var dy = aXys[i - 1].y - aXys[i].y;

            x = aXys[i - 1].x - (dx * fTo);
            y = aXys[i - 1].y - (dy * fTo);

        }

        return { 'x': x, 'y': y, 'i': i, 'fTo': fTo, 'fFrom': fFrom };
    }

如何在C#中复制以上内容?

1 个答案:

答案 0 :(得分:0)

感谢xdtTransform。我没有使用Visual Studio,所以没有意识到Ctrl + Space。安装后,我已经设法自己转换了代码。我已将其包含在此处,以供将来从中受益的任何人。

我从一堂课开始,掌握了这些点的纬度和经度详细信息。


namespace Classes
{
    public class AppGeoPoint
    {
        public double X { get; set; }
        public double Y { get; set; }
    }
}

然后将函数转换为


        public static Classes.AppGeoPoint getClosestPointOnLines(Classes.AppGeoPoint pXy, Classes.AppGeoPoint[] aXys)
        {

            double? minDist = null;
            double fTo = 0.0;
            double fFrom;
            double x = 0.0;
            double y = 0.0;
            int i = 0;
            double dist;

            if (aXys.Length > 1)
            {

                for (var n = 1; n < aXys.Length; n++)
                {

                    if (aXys[n].X != aXys[n - 1].X)
                    {
                        var a = (aXys[n].Y - aXys[n - 1].Y) / (aXys[n].X - aXys[n - 1].X);
                        var b = aXys[n].Y - a * aXys[n].X;
                        dist = Math.Abs(a * pXy.X + b - pXy.Y) / Math.Sqrt(a * a + 1);
                    }
                    else
                        dist = Math.Abs(pXy.X - aXys[n].X);

                    // length^2 of line segment 
                    double rl2 = Math.Pow(aXys[n].Y - aXys[n - 1].Y, 2) + Math.Pow(aXys[n].X - aXys[n - 1].X, 2);

                    // distance^2 of pt to end line segment
                    double ln2 = Math.Pow(aXys[n].Y - pXy.Y, 2) + Math.Pow(aXys[n].X - pXy.X, 2);

                    // distance^2 of pt to begin line segment
                    double lnm12 = Math.Pow(aXys[n - 1].Y - pXy.Y, 2) + Math.Pow(aXys[n - 1].X - pXy.X, 2);

                    // minimum distance^2 of pt to infinite line
                    double dist2 = Math.Pow(dist, 2);

                    // calculated length^2 of line segment
                    double calcrl2 = ln2 - dist2 + lnm12 - dist2;

                    // redefine minimum distance to line segment (not infinite line) if necessary
                    if (calcrl2 > rl2)
                        dist = Math.Sqrt(Math.Min(ln2, lnm12));

                    if ((minDist == null) || (minDist > dist))
                    {
                        if (calcrl2 > rl2)
                        {
                            if (lnm12 < ln2)
                            {
                                fTo = 0;//nearer to previous point
                                fFrom = 1;
                            }
                            else
                            {
                                fFrom = 0;//nearer to current point
                                fTo = 1;
                            }
                        }
                        else
                        {
                            // perpendicular from point intersects line segment
                            fTo = ((Math.Sqrt(lnm12 - dist2)) / Math.Sqrt(rl2));
                            fFrom = ((Math.Sqrt(ln2 - dist2)) / Math.Sqrt(rl2));
                        }
                        minDist = dist;
                        i = n;
                    }
                }

                var dx = aXys[i - 1].X - aXys[i].X;
                var dy = aXys[i - 1].Y - aXys[i].Y;

                x = aXys[i - 1].X - (dx * fTo);
                y = aXys[i - 1].Y - (dy * fTo);

            }

            return new Classes.AppGeoPoint { X = x, Y = y };
        }

然后,最后,构建一个数组列表并检查最接近的点


            Classes.AppGeoPoint YourLocation= new Classes.AppGeoPoint { X = 50.83737, Y = -1.07428 };
            Classes.AppGeoPoint[] AreaCheck = new[] {
                new Classes.AppGeoPoint { X = 50.847550000000005, Y = -1.0863200000000002 },
                new Classes.AppGeoPoint { X = 50.83975, Y = -1.0859800000000002 },
                new Classes.AppGeoPoint { X = 50.83845, Y = -1.06487 },
                new Classes.AppGeoPoint { X = 50.84723, Y = -1.0645200000000001 }
            };

            Classes.AppGeoPoint ReturnVal = getClosestPointOnLines(YourLocation, AreaCheck);

            Console.WriteLine("X " + ReturnVal.X);
            Console.WriteLine("Y " + ReturnVal.Y);

ReturnVal.X和ReturnVal.Y将返回最接近的点的纬度和经度。

希望这对其他人有帮助。