地理坐标(经纬度坐标)和屏幕坐标(xy坐标)间的转换

article/2025/9/24 20:33:17

在我们的屏幕上,有一张地图,这张地图经过缩放、平移、旋转,最终地理坐标和屏幕坐标的关系大致如下图所示:

这种关系要怎么描述呢?我们可以假设地图是一张纸,而屏幕是一堵墙。只要我们有两个图钉,我们就能把纸定在墙上。我们把这两个点称为锚点。锚点在屏幕坐标系上的坐标是(x1,y1)和(x2,y2),对应在地理坐标系上的坐标是(lon1,lat1)和(lon2,lat2)。

那现在的问题就变成了,已知两个锚点的坐标,

(1)地理坐标转屏幕坐标:已知任意一点的地理坐标(lon,lat),求它在屏幕上的坐标(x,y)

(2)屏幕坐标转地理坐标:已知任意一点的屏幕坐标(x,y),求它的经纬度坐标(lon,lat)

转换算法

1、地理坐标平面化

首先是地理坐标的平面化转化。在一个小范围内(例如是方圆几公里内),我们可以假设地面是平的,而不是弯的。如果经纬度都用弧度表示,那么1纬度对应的长度是:

1lat_len=R*lat

其中R是地球半径。

而相同经度间的距离会随着纬度的增加而减少,在lat这一纬度下,1经度对应的长度是:

1lon_len=R*lon*cos(lat)

那么,(lon,lat)这个坐标平面化后的坐标就是:(R*lon*cos(lat),R*lat)

2、向量法

由已知点和未知点组成两组向量:

由于坐标系转换是线性变换,所以两组向量有以下特性:

(1)两向量在不同的坐标系中的长度比是相同的。

(2)两向量在不同的坐标系中的夹角是相同的。

根据上面两个特性,我们可列出方程组:

设向量1为(dx1,dy1),(dlon1,dlat1),向量2为(dx2,dy2),(dlon2,dlat2),

其中dx1=x2-x1,dy1=y2-y1,dlon1=lon2-lon1,dlat1=lat2-lat1

dx2=x-x1,dy2=y-y1,dlon2=lon-lon1,dlat2=lat-lat1,

然后k1=norm(dx1,dy1),k2=norm(dlon1,dlat1),k3=norm(dx2,dy2),k4=norm(dlon2,dlat2)

有方程组:

(1)k1/k2 = k3/k4

(2)(dx1*dlon1+dy1*dlat1)/k1/k2 = (dx2*dlon2+dy2*dlat2)/k3/k4

通过解上面的方程组,我们就能得到未知和屏幕坐标或未知的地理坐标。

3、C#代码实现

地理坐标转屏幕坐标:

double lon_cos = Math.Cos(lat2 * Math.PI / 180);double m = (lon2 - lon1) * lon_cos;
double n = (lat2 - lat1);
double p = (lon - lon1) * lon_cos;
double q = (lat - lat1);double M = x2 - x1;
double N = y2 - y1;double a = (p * p + q * q) * (M * M + N * N) / (m * m + n * n);
double b = (m * p + q * n) * norm(M, N) * Math.Sqrt(a) / (norm(m, n) * norm(p, q));double c = Math.Sqrt(b * b * N * N - (M * M + N * N) * (b * b - a * M * M));double Q1 = (b * N + c) / (M * M + N * N);
double Q2 = (b * N - c) / (M * M + N * N);double P1 = (b - Q1 * N) / M;
double P2 = (b - Q2 * N) / M;double x_1 = P1 + x1;
double y_1 = Q1 + y1;
double x_2 = P2 + x1;
double y_2 = Q2 + y1;double judge1 = (x_1 - x1) * (y2 - y1) - (y_1 - y1) * (x2 - x1);
double judge2 = (x_2 - x1) * (y2 - y1) - (y_2 - y1) * (x2 - x1);
double judge = (lon - lon1) * (lat2 - lat1) - (lat - lat1) * (lon2 - lon1);double x = 0;
double y = 0;
if (judge * judge1 < 0)
{x = x_1;y = y_1;
}
else
{x = x_2;y = y_2;
}

屏幕坐标转地理坐标:

double lon_cos = Math.Cos(lat2 * Math.PI / 180);double m = (lon2 - lon1) * lon_cos;
double n = (lat2 - lat1);double M = x2 - x1;
double N = y2 - y1;
double P = x - x1;
double Q = y - y1;double a = (P * P + Q * Q) * (m * m + n * n) / (M * M + N * N);
double b = (M * P + Q * N) * norm(m, n) * Math.Sqrt(a) / (norm(M, N) * norm(P, Q));double c = Math.Sqrt(b * b * n * n - (m * m + n * n) * (b * b - a * m * m));double q1 = (b * n + c) / (m * m + n * n);
double q2 = (b * n - c) / (m * m + n * n);double p1 = (b - q1 * n) / m;
double p2 = (b - q2 * n) / m;double lon_1 = p1 / lon_cos + lon1;
double lat_1 = q1 + lat1;
double lon_2 = p2 / lon_cos + lon1;
double lat_2 = q2 + lat1;double judge1 = (lon_1 - lon1) * (lat2 - lat1) - (lat_1 - lat1) * (lon2 - lon1);
double judge2 = (lon_2 - lon1) * (lat2 - lat1) - (lat_2 - lat1) * (lon2 - lon1);
double judge = (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1);double lon = 0;
double lat = 0;
if (judge * judge1 < 0)
{lon = lon_1;lat = lat_1;
}
else
{lon = lon_2;lat = lat_2;
}

 


http://chatgpt.dhexx.cn/article/uKjyUpd6.shtml

相关文章

Windows的三种坐标系:屏幕坐标系,非客户区坐标系,客户区坐标系

1. 屏幕坐标系&#xff1a;以屏幕的左上角为原点&#xff0c;如图所示GetWindowRect() 函数获得的 RECT 就是以屏幕坐标系算的。 2. 非客户区坐标系(窗口坐标系)包括标题栏的部分。GetWindowDC 返回的设备环境就是基于此坐标系&#xff0c;一般只在 WM_NCPAINT 消息中使用。 3.…

Unity世界坐标系、本地坐标系、屏幕坐标系、视口坐标系

Unity中的坐标系 世界坐标系本地坐标系屏幕坐标系视口坐标系各个坐标系相互转换的API 世界坐标系 原点&#xff1a;世界的中心 轴向&#xff1a;世界坐标系的三个轴向是固定的 相关API: transform.position;transform.rotation; 四元数transform.eulerAngles; 欧拉角transfor…

Unity世界坐标转换屏幕坐标(概览)

这些天做的项目中&#xff0c;有一个世界坐标转换屏幕坐标的功能&#xff0c;具体需求如下 在3d场景中&#xff0c;部分物体可以进行点击交互&#xff0c;如果某个物体可以点击&#xff0c;就在屏幕上对应位置&#xff0c;添加一个Button&#xff0c;也就是把场景中物体的坐标转…

手机屏幕坐标

整个坐标系是以手机屏幕左上角为原点&#xff08;0,0&#xff09;&#xff0c;如果在屏幕没有滑动之前&#xff0c;这一理解肯定是ok的&#xff0c;但在滑屏之后&#xff0c;就会产生很多歧义和混淆&#xff0c;原因在于使用过程当中&#xff0c;很多方法的参数并非是参照屏幕&…

计算机屏幕坐标系

常用的屏幕坐标系有如下图所示的两种&#xff1a;

Android屏幕、坐标系、Padding、Margin

一、屏幕 二、坐标系分类 1、屏幕坐标系 该坐标系是以屏幕的左上角为原点(0, 0), 水平向右代表 x 方向的正方向&#xff0c; 垂直向下代表 y方向的正方向。而触控事件中&#xff0c;使用getRawX()和getRawY()方法。获取的坐标就是以这个坐标系为标准下的坐标值。 2、布局坐标…

屏幕坐标转换分析

1.屏幕坐标以像素为单位&#xff0c;地图坐标通常以米为单位&#xff0c;CAD制图默认以毫米为单位。 DPI是“dot per inch”的缩写。顾名思义&#xff0c;就是指在每英寸长度内的点数。 通常&#xff0c;我们都使用dpi来作为扫描器和打印机的解析度单位&#xff0c;数值越高表示…

屏幕坐标系和视口坐标系

一.屏幕坐标系1.屏幕坐标系: 手机屏幕或者电脑屏幕的一个坐标系。2.屏幕坐标是以像素来定义的, 屏幕左下角为原点(0,0), 右上角为(Screen.width,Screen.height), width是屏幕的宽度, height是屏幕的高度, Z值是摄像机世界坐标取反,并且以相机的世界单位来衡量的。3.屏幕坐标和相…

vs2010中出现lnk2019和lnk1120错误

非常令人难受的是&#xff0c;今天在配置Cocos2d-x的时候&#xff0c;配置完突然出现这个问题&#xff0c;我以为VS2010给我弄崩了&#xff0c;吓得我瞬间慌了 不过研究了好几篇文章才发现这个一点关系都没有。 下面说一下到底出了什么问题&#xff1a; 创建项目的时候选错了&…

LNK2001:无法解析的外部符号,LNK1120:一个无法解析的外部命令

写了个画图程序&#xff0c;边写边调试&#xff0c;运行时发现出现了这个。检查发现原因是在头文件定义了A函数&#xff0c;在.cpp中没有实现&#xff0c;于是在.cpp中将函数写出来 头文件定义了&#xff0c;但函数没有具体出现&#xff0c;编译器无法解析&#xff0c;实现一下…

新手编程VS2019出现 error LNK2019 LNK1120 报错

新手编程VS2019出现 error LNK2019 LNK1120 报错 我也是新手&#xff0c;出现这个问题我很纳闷&#xff0c;明明代码语法什么的都没错&#xff0c;但是就是报了这个错误 于是我在网上查了半天的解决方法&#xff0c;大多都是说建项目的时候出问题&#xff0c;但是不管我怎么重…

lnk1120如何解决,致命错误LNK1120:4个未解决的外部

I am new to game developing, i am interesed in Goldsrc(Valves early engine). I found source code of Counter-Strike 1.6 (Modified Goldsrc) and tried to compile it with VS2013. 解决方案 Generally, this error comes when you call something that is not defined.…

fatal error LNK1120: 1 个无法解析的外部命令 的解决办法

question&#xff1a; vs2012编c程序的时候&#xff0c;出现了fatal error LNK1120: 1 个无法解析的外部命令 但是编译的时候是没有任何问题的 Answer&#xff1a; 没有写主函数&#xff0c;所以你能进行编译的时候通过&#xff0c;而进行最终ctrlf5的时候会出现这个问题…

c语言中延时的作用,在c语言中如何实现延时功能?

实现原理&#xff1a;Sleep()延迟函数。 条件&#xff1a; 1.需要引入头文件#include 和#include 。 2.Sleep()函数内部必须有参数&#xff0c;里面填整数&#xff0c;表示毫秒。 实现步骤&#xff1a; 1.新建控制台程序&#xff0c;设置工程名和路径。 2.选择一个简单的程序。…

【Linux C/C++ 延时(延迟)函数比较】介绍Linux系统中常用的延时函数sleep、usleep、nanosleep、select和std::sleep_for()的区别和使用场景

首先&#xff0c;需要了解各个睡眠函数的作用和使用场景。 sleep函数用于让进程休眠指定的秒数&#xff0c;适用于需要较长时间的休眠场景&#xff1b;usleep函数用于让进程休眠指定的微秒数&#xff0c;适用于需要较短时间的休眠场景&#xff0c;不精确&#xff1b;nanosleep函…

单片机:延时函数的理解

在实现单片机功能的时候&#xff0c;经常会用到延时函数&#xff0c;那么延时函数的原理也是非常有必要了解的。一般我们写延时函数的时候&#xff0c;默认的晶振频率fosc12MHZ&#xff0c;而机器周期T12/fosc1us。 这里我们来写一个10ms的延时函数&#xff1a; void delay_10…

c/c++语言中的延时操作

大家在编程的过程中可能需要用到一些延时操作&#xff0c;比如说在使用控制台编程时&#xff0c;程序运行的时候DOS窗口会一闪而过&#xff0c;这样就会导致看不到程序在Dos界面运行的结果&#xff0c;这样有些小伙伴就纳闷了&#xff1a;怎样使得Dos窗口一直停留呢&#xff1f…

C\C++中计时、延时函数

C\C标准库中提供了两种计时函数clock()和time()。其用法如下&#xff1a; &#xff08;1&#xff09;clock()函数用法 void timeConsume() {double start,stop,durationTime;start clock();/*...代码片段*/stop clock();durationTime ((double)(stop-start))/CLK_TCK;cout…

c语言中,关于延迟函数的理解

对于延迟&#xff0c;有些c基础的人都能够做到用for或while来实现 例如&#xff1a; #include <stdio.h>int main() {int i, j, k;for (i 1; i < 1000; i){for (j 1; j < 1000; j){for (k 1; k < 1000; k){}}}printf("hello\n");return 0; }1234…

延时函数

延时函数 什么是延时函数 所谓延时函数就是在函数中设置了几个空操作的动作&#xff0c;每次操作都需要消耗一定的时间&#xff0c;动作结束了&#xff0c;就会跳出延时函数继续做其他事情了。 为什么要延时 为了使CPU某些芯片的时序而采用的一些机制&#xff0c;比如独立按…