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