如何计算以GPS坐标为中心的地球上的圆点? [英] How to calculate points on a circle on the globe centred on GPS coordinates?

查看:121
本文介绍了如何计算以GPS坐标为中心的地球上的圆点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在KML中绘制一个圆圈



您如何获取地球上某点的GPS坐标(例如以十进制度的格式)并生成多边形的坐标近似以该点为中心的圆圈?

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



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

数据输入示例:

纬度,经度,圆半径(以英尺为单位),NumberOfDataPoints



26.128477,-80.105149,500,20

解决方案

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



定义:

R是半径(即地球)。

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

p> t是球体中心长度为r的大圆弧所对的角度,所以t = r / R弧度。现在假设球体具有半径1,并以原点为中心。



C是代表圆的中心的单位向量。

想像一下北波尔的一个圆圈e并考虑圆的平面与从地球中心到北极的直线相交的点。显然,这一点将在北极之下。



K是C下的对应点(即圆的平面与C相交的点),所以K = cos (t)C

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

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

这个答案(忽略旋转的东西)解释了如何找到平面的基向量(即一个向量与正常的K或C)。使用交叉产品找到第二个。



调用这些基向量U和V.

  //伪代码计算圆上的20个点
(a = 0; a!= 360; a + = 18)
{
// A点在圆上和单位球面
P = K + s *(U * sin(a)+ V * cos(a))
}

将每个点转换为球坐标并完成。



在C#中。结果是合理的:他们在一个圈子里,躺在球体上。大多数代码实现了代表矢量的 struct 。实际计算非常简单。

  using System; 

namespace gpsCircle
{
struct Gps
{
//度数
public readonly double Latitude;
public readonly double Longitude;

公共Gps(双纬度,双倍经度)
{
纬度=纬度;
Longitude =经度;

$ b $ public override string ToString()
{
return string.Format(({0},{1}),Latitude,Longitude);
}

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

// Z是北
//格林威治子午线上的X点
返回新的矢量(Math.Cos(lng)* Math.Cos(lat),Math.Sin (lng)* Math.Cos(lat),Math.Sin(lat));
}
}

结构向量
{
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();

返回新的矢量(X / m,Y / m,Z / m);
}

public Gps ToGps()
{
Vector unit = ToUnit();
//舍入错误
double z = unit.Z;
if(z> 1)
z = 1;

double lat = Math.Asin(z);

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

返回新的Gps(lat * 180 / Math.PI,lng * 180 / Math.PI);


public static Vector *(double m,Vector v)
{
return new Vector(m * vX,m * vY,m * vZ) ;
}

public static Vector-(Vector a,Vector b)
{
return new Vector(aX - bX,aY - bY,aZ - bZ) ;


公共静态向量运算符+(向量a,向量b)
{
返回新向量(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点(向量表示)
{
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);
}

//选择一个随机正交向量
public Vector Orthogonal()
{
double minNormal = Math.Abs​​(X);
int minIndex = 0;如果(Math.Abs​​(Y)< minNormal)
{
minNormal = Math.Abs​​(Y);
minIndex = 1; (Z) {
minNormal = Math.Abs​​(Z);
}

minIndex = 2;
}

向量B;
switch(minIndex)
{
case 0:
B = new Vector(1,0,0);
休息;
案例1:
B =新的向量(0,1,0);
休息;
默认值:
B =新向量(0,0,1);
休息;
}

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



类程序
{
static void Main(string [] args)
{
// Phnom Penh
Gps中心=新Gps(11.55,104.916667);

//以米为单位
double worldRadius = 6371000;
//以米为单位
double circleRadius = 1000;

//代表半径circleRadius圆心的圆点。
Gps [] points = new Gps [20];

CirclePoints(点,中心,worldRadius,circleRadius);
}

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

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

向量U = K.Orthogonal();
向量V = K.Cross(U);
//改进正交性
U = K.Cross(V);

for(int point = 0; point!= count; ++ point)
{
double a = 2 * Math.PI * point / count;
向量P = K + s *(Math.Sin(a)* U + Math.Cos(a)* V);
points [point] = P.ToGps();
}
}
}
}


Draw a circle in KML

How do you take the GPS coordinates of a point on the globe (say in decimal degree format) and generate the coordinates for a polygon approximating a circle centred on that point?

A polygon with 20+ data points looks like a circle. The more data points - the better looking the circle.

I am writing a program that will generate KML and dont know how to calculate the coordinates of the polygon vertices.

Example of data inputs:

Latitude, Longitude, Circle radius (in feet), NumberOfDataPoints

26.128477, -80.105149, 500, 20

解决方案

I don't know if this is the simplest solution and it assumes the world is a sphere.

Define:

R is the radius of the sphere (i.e. the earth).

r is the radius of the circle (in the same units).

t is the angle subtended by a great-circle arc of length r at the centre of the sphere so t=r/R radians.

Now suppose the sphere has radius 1 and is centred at the origin.

C is a unit vector representing the centre of the circle.

Imagine a circle round the North pole and consider the point where the plane of the circle intersects the line from the centre of the earth to the North pole. Clearly this point will be somewhere below the North pole.

K is the corresponding point "below" C (i.e. where the plane of your circle intersects C) so K=cos(t)C

s is the radius of the circle measured in 3D space (i.e. not on the sphere) so s=sin(t)

Now we want points on the circle in 3D space with centre K, radius s and lying in the plane passing through and perpendicular to K.

This answer (ignore the rotation stuff) explains how to find a basis vector for the plane (i.e. a vector orthogonal to the normal K or C). Use the cross product to find a second.

Call these basis vectors U and 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))
}

Convert each point to spherical coordinates and you are done.

Being bored, I coded this up in C#. The results are plausible: they are in a circle and lie on the sphere. Most of the code implements a struct representing a vector. The actual calculation is very simple.

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();
            }
        }
    }
}

这篇关于如何计算以GPS坐标为中心的地球上的圆点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆