如何计算地球上以GPS坐标为中心的圆上的点?

如何计算地球上以GPS坐标为中心的圆上的点?,gps,kml,Gps,Kml,用KML画一个圆 如何获取地球上某个点的GPS坐标(比如十进制格式),并生成近似于以该点为圆心的圆的多边形坐标 具有20多个数据点的多边形看起来像一个圆。数据点越多,圆圈越好看 我正在写一个程序,将生成KML,不知道如何计算多边形顶点的坐标 数据输入示例: 纬度、经度、圆半径(英尺)、数据点数 26.128477,-80.105149500,20我不知道这是否是最简单的解决方案,它假设世界是一个球体 定义: R是球体(即地球)的半径 r是圆的半径(单位相同) t是长度为r的大圆弧在球体中心所对的

用KML画一个圆

如何获取地球上某个点的GPS坐标(比如十进制格式),并生成近似于以该点为圆心的圆的多边形坐标

具有20多个数据点的多边形看起来像一个圆。数据点越多,圆圈越好看

我正在写一个程序,将生成KML,不知道如何计算多边形顶点的坐标

数据输入示例:

纬度、经度、圆半径(英尺)、数据点数


26.128477,-80.105149500,20

我不知道这是否是最简单的解决方案,它假设世界是一个球体

定义:

R是球体(即地球)的半径

r是圆的半径(单位相同)

t是长度为r的大圆弧在球体中心所对的角度,因此t=r/r弧度

现在假设球体的半径为1,并以原点为中心

C是表示圆心的单位向量

想象一个绕北极的圆,考虑圆的平面从地球中心到北极的线相交的点。显然,这一点将位于北极以下的某个地方

K是对应的“低于”C的点(即圆的平面与C相交的点),因此K=cos(t)C

s是在三维空间(即不在球体上)测量的圆半径,因此s=sin(t)

现在我们想要点在三维空间的圆上,中心为K,半径为s,位于穿过并垂直于K的平面上

(忽略旋转内容)说明如何找到平面的基向量(即与法线K或C正交的向量)。使用叉积找到第二个

把这些基向量称为U和V

// Pseudo-code to calculate 20 points on the circle
for (a = 0; a != 360; a += 18)
{
    // A point on the circle and the unit sphere
    P = K + s * (U * sin(a) + V * cos(a))
}
将每个点转换为球坐标,就完成了

由于无聊,我用C#编码了这个。结果是可信的:它们在一个圆圈里,位于球体上。大多数代码实现了表示向量的
结构。实际计算非常简单

using System;

namespace gpsCircle
{
    struct Gps
    {
        // In degrees
        public readonly double Latitude;
        public readonly double Longtitude;

        public Gps(double latitude, double longtitude)
        {
            Latitude = latitude;
            Longtitude = longtitude;
        }

        public override string ToString()
        {
            return string.Format("({0},{1})", Latitude, Longtitude);
        }

        public Vector ToUnitVector()
        {
            double lat = Latitude / 180 * Math.PI;
            double lng = Longtitude / 180 * Math.PI;

            // Z is North
            // X points at the Greenwich meridian
            return new Vector(Math.Cos(lng) * Math.Cos(lat), Math.Sin(lng) * Math.Cos(lat), Math.Sin(lat));
        }
    }

    struct Vector
    {
        public readonly double X;
        public readonly double Y;
        public readonly double Z;

        public Vector(double x, double y, double z)
        {
            X = x;
            Y = y;
            Z = z;
        }

        public double MagnitudeSquared()
        {
            return X * X + Y * Y + Z * Z;
        }

        public double Magnitude()
        {
            return Math.Sqrt(MagnitudeSquared());
        }

        public Vector ToUnit()
        {
            double m = Magnitude();

            return new Vector(X / m, Y / m, Z / m);
        }

        public Gps ToGps()
        {
            Vector unit = ToUnit();
            // Rounding errors
            double z = unit.Z;
            if (z > 1)
                z = 1;

            double lat = Math.Asin(z);

            double lng = Math.Atan2(unit.Y, unit.X);

            return new Gps(lat * 180 / Math.PI, lng * 180 / Math.PI);
        }

        public static Vector operator*(double m, Vector v)
        {
            return new Vector(m * v.X, m * v.Y, m * v.Z);
        }

        public static Vector operator-(Vector a, Vector b)
        {
            return new Vector(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
        }

        public static Vector operator+(Vector a, Vector b)
        {
            return new Vector(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
        }

        public override string ToString()
        {
            return string.Format("({0},{1},{2})", X, Y, Z);
        }

        public double Dot(Vector that)
        {
            return X * that.X + Y * that.Y + Z * that.Z;
        }

        public Vector Cross(Vector that)
        {
            return new Vector(Y * that.Z - Z * that.Y, Z * that.X - X * that.Z, X * that.Y - Y * that.X);
        }

        // Pick a random orthogonal vector
        public Vector Orthogonal()
        {
            double minNormal = Math.Abs(X);
            int minIndex = 0;
            if (Math.Abs(Y) < minNormal)
            {
                minNormal = Math.Abs(Y);
                minIndex = 1;
            }
            if (Math.Abs(Z) < minNormal)
            {
                minNormal = Math.Abs(Z);
                minIndex = 2;
            }

            Vector B;
            switch (minIndex)
            {
                case 0:
                    B = new Vector(1, 0, 0);
                    break;
                case 1:
                    B = new Vector(0, 1, 0);
                    break;
                default:
                    B = new Vector(0, 0, 1);
                    break;
            }

            return (B - minNormal * this).ToUnit();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Phnom Penh
            Gps centre = new Gps(11.55, 104.916667);

            // In metres
            double worldRadius = 6371000;
            // In metres
            double circleRadius = 1000;

            // Points representing circle of radius circleRadius round centre.
            Gps[] points  = new Gps[20];

            CirclePoints(points, centre, worldRadius, circleRadius);
        }

        static void CirclePoints(Gps[] points, Gps centre, double R, double r)
        {
            int count = points.Length;

            Vector C = centre.ToUnitVector();
            double t = r / R;
            Vector K = Math.Cos(t) * C;
            double s = Math.Sin(t);

            Vector U = K.Orthogonal();
            Vector V = K.Cross(U);
            // Improve orthogonality
            U = K.Cross(V);

            for (int point = 0; point != count; ++point)
            {
                double a = 2 * Math.PI * point / count;
                Vector P = K + s * (Math.Sin(a) * U + Math.Cos(a) * V);
                points[point] = P.ToGps();
            }
        }
    }
}
使用系统;
名称空间gpsCircle
{
结构Gps
{
//度
公共只读双纬度;
公众只读双长;
公共Gps(双纬度、双经度)
{
纬度=纬度;
长度=长度;
}
公共重写字符串ToString()
{
返回string.Format(({0},{1})”,纬度,长度;
}
公共向量ToUnitVector()
{
双纬度=纬度/180*Math.PI;
双液化天然气=longtude/180*Math.PI;
//Z是北方
//格林威治子午线的X点
返回新向量(Math.Cos(lng)*Math.Cos(lat),Math.Sin(lng)*Math.Cos(lat),Math.Sin(lat));
}
}
结构向量
{
公共只读双X;
公共只读双Y;
公共只读双Z;
公共向量(双x,双y,双z)
{
X=X;
Y=Y;
Z=Z;
}
公共双震级平方()
{
返回X*X+Y*Y+Z*Z;
}
公共双震级()
{
返回Math.Sqrt(magnitySquared());
}
公共向量ToUnit()
{
双m=量级();
返回新向量(X/m,Y/m,Z/m);
}
公共Gps ToGps()
{
向量单位=ToUnit();
//舍入误差
双z=单位z;
如果(z>1)
z=1;
双板条=数学Asin(z);
双液化天然气=数学常数2(单位Y,单位X);
返回新Gps(lat*180/Math.PI,lng*180/Math.PI);
}
公共静态向量运算符*(双m,向量v)
{
返回新向量(m*v.X,m*v.Y,m*v.Z);
}
公共静态向量运算符-(向量a,向量b)
{
返回新向量(a.X-b.X,a.Y-b.Y,a.Z-b.Z);
}
公共静态向量运算符+(向量a、向量b)
{
返回新向量(a.X+b.X,a.Y+b.Y,a.Z+b.Z);
}
公共重写字符串ToString()
{
返回string.Format(({0},{1},{2})”,X,Y,Z);
}
公共双点(即向量)
{
返回X*that.X+Y*that.Y+Z*that.Z;
}
公共向量交叉(向量表示)
{
返回新向量(Y*that.Z-Z*that.Y,Z*that.X-X*that.Z,X*that.Y-Y*that.X);
}
//选择一个随机正交向量
公共向量正交()
{
double minNormal=Math.Abs(X);
int minIndex=0;
if(数学绝对值(Y)