经纬度转换成屏幕坐标

article/2025/9/24 19:53:18

学期projet总结:
当把点的数据和线的数据读进来之后,为了画出地图还有最重要的一步就是把实际的经纬度转换成屏幕像素点的坐标。在找老师讨论之前,我在网上查资料,找到了下边链接的文章,并按照这个方法画出了地图。
相关文章链接

1月4号,新年后第一天上课,我去找导师让他看做出来的软件的效果,画出来的地图明显和他的不一样,他就把他的方法分享了。
他的方法的主要思路就是找到一个城市所有点里面经度和纬度最小的点作为坐标原点,然后求其他点到这个点的距离,这个距离是地理空间的实际距离,并以此算出坐标。因为屏幕的坐标原点在左上方,所有我计算的步骤如下

  1. 以经度最小值和纬度最大值作为坐标原点(minLongitude,maxLatitude)
  2. 求其他点到坐标原点的距离(实际地理空间距离),找出最大距离maxDistance
  3. 获取屏幕宽度和高度,求出斜对角线的长度,勾股定理
  4. 算出最大距离与屏幕斜对角线的比值,再乘以2作为换算比率,ratio
  5. 求出每个点相对于原点的x,y轴的距离,除以换算比率得到屏幕坐标

第2步,求两点间的实际地理空间距离,导师提供了一个算法,这个方法是把地球当成一个球面模型
这里写图片描述
假设地图上有A(ja,wa),B(jb,wb)两点,ja,wa是A点的经纬度,jb,wb是B点的经纬度。A和B两点的球面距离就是AB的弧长,AB弧长=地球半径*角AOB,O是地球球心。计算公式如下:
这里写图片描述

代码如下:

public static double distanceLongLat(double longitudeA, double longitudeB,double latitudeA, double latitudeB) {double longA = longitudeA * Math.PI / 180;double longB = longitudeB * Math.PI / 180;double latA = latitudeA * Math.PI / 180;double latB = latitudeB * Math.PI / 180;double deltaLong = longB - longA;//角AOBdouble radianAB = Math.acos(Math.sin(latA) * Math.sin(latB)+ Math.cos(latA) * Math.cos(latB) * Math.cos(deltaLong));//AB弧长return (radianAB * 6378000);
}

获取屏幕宽和高的代码如下:

//获得屏幕大小
Dimension   screensize   =   Toolkit.getDefaultToolkit().getScreenSize();
int screenWidth = (int)screensize.getWidth();
int screenHeight = (int)screensize.getHeight();

求距离坐标原点最远的点,求出换算比率。代码如下:

//求距离参照点最远的点
double maxDistance = distanceLongLat(minLongitude, ReadFile.longitude.get(0), maxLatitude, ReadFile.latitude.get(0));
for (int i = 0; i < ReadFile.longitude.size(); i++){maxDistance=Math.max(maxDistance,distanceLongLat(minLongitude,ReadFile.longitude.get(i), maxLatitude, ReadFile.latitude.get(i)));
}
//转换比率
double ratio = 2*maxDistance / Math.sqrt((screenWidth * screenWidth+ screenHeight * screenHeight));

将所有点的经纬度转换成屏幕像素坐标,并将转换后的坐标用一个ArrayList保存。代码如下:

public static ArrayList<Point> point = new ArrayList<Point>();//将经纬度转换成屏幕坐标   
for (int i = 0; i < ReadFile.longitude.size(); i++) {Point p = new Point();          p.x = (int) (distanceLongLat(minLongitude,ReadFile.longitude.get(i), maxLatitude, maxLatitude) / ratio);p.y = (int) (distanceLongLat(minLongitude, minLongitude,maxLatitude, ReadFile.latitude.get(i)) / ratio);point.add(p);
}

用point里保存的坐标就可以画地图了。画出来巴黎的地图如下:
这里写图片描述

在最后一步,把每个点的经纬度转换成屏幕坐标时,原理如下图:
这里写图片描述

O点是屏幕左上角,坐标原点,求B点的X,Y值,OB1的距离为X轴的值,OB2 的距离为Y轴的距离,然后再除以换算比率(ratio)适应屏幕大小。

以该方法画地图时,当点很多时,画的很慢。例如画旧金山时,点的数量达到了175000个!!!!而巴黎的数据,点的数量是29000个,柏林的点是60000个。所以画旧金山用时在7.5秒左右。然后我读到了美团网的一篇技术文章,链接如下
地理空间距离计算优化
用该文章介绍的“简化距离计算公式方法“,在画旧金山时可以提高到5.5秒左右。

我分析了一下,我的程序里有三个地方用到了求两点距离的代码,一是求最远距离,另外是求X,Y坐标,这三次计算都要算17.5W次,计算公式里面还有一个三角函数。美团网计算用户到商家的距离只计算一次。

该部分完整代码如下:

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.util.ArrayList;import com.vg.io.ReadFile;/*** 将经纬度转换成屏幕像素坐标**/public class LocationTransfer {public static ArrayList<Point> point = new ArrayList<Point>();public static double minLongitude = ReadFile.longitude.get(0);public static double maxLatitude = ReadFile.latitude.get(0);// change longitute and latitude to view pointpublic static void makeScreenPoint(String fileName) {for (int i = 0; i < ReadFile.longitude.size(); i++) {minLongitude = Math.min(minLongitude, ReadFile.longitude.get(i));maxLatitude = Math.max(maxLatitude, ReadFile.latitude.get(i));}/************************************************************///获得屏幕大小Dimension   screensize   =   Toolkit.getDefaultToolkit().getScreenSize();int screenWidth = (int)screensize.getWidth();int screenHeight = (int)screensize.getHeight();//求距离参照点最远的点double maxDistance = distanceLongLat(minLongitude, ReadFile.longitude.get(0), maxLatitude, ReadFile.latitude.get(0));for (int i = 0; i < ReadFile.longitude.size(); i++) {maxDistance = Math.max(maxDistance, distanceLongLat(minLongitude, ReadFile.longitude.get(i), maxLatitude, ReadFile.latitude.get(i)));}//转换比率double ratio = 2*maxDistance / Math.sqrt((screenWidth * screenWidth+ screenHeight * screenHeight));//将经纬度转换成屏幕坐标   for (int i = 0; i < ReadFile.longitude.size(); i++) {Point p = new Point();          p.x = (int) (distanceLongLat(minLongitude,ReadFile.longitude.get(i), maxLatitude, maxLatitude) / ratio);p.y = (int) (distanceLongLat(minLongitude, minLongitude,maxLatitude, ReadFile.latitude.get(i)) / ratio);point.add(p);}}//简化距离公式法public static double distanceLongLat( double lng1,double lng2,double lat1, double lat2) {double dx = lng1 - lng2; // 经度差值double dy = lat1 - lat2; // 纬度差值double b = (lat1 + lat2) / 2.0; // 平均纬度double Lx = dx * Math.PI/180 * 6367000.0 * Math.cos(b*Math.PI/180); // 东西距离double Ly = 6367000.0 * dy*Math.PI/180; // 南北距离return Math.sqrt(Lx * Lx + Ly * Ly);  // 用平面的矩形对角距离公式计算总距离}   
}

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

相关文章

Unity-世界坐标与屏幕坐标

transform.position.x和transform.position.y的值含义是世界坐标。 世界坐标与屏幕坐标有时一样&#xff0c;有时不同&#xff0c;这和Canvas的渲染模式有关。 Canvas共有三种渲染模式 Screen Space - Overlay (此模式UGUI层一直在最上面&#xff0c;其他例如粒子等物体一直…

Unity 世界坐标、屏幕坐标、UGUI 坐标 相互转换

Unity 世界坐标、屏幕坐标、UGUI 坐标 相互转换 坐标转换是游戏开发过程中必不可少的环节 看下图 世界坐标、屏幕坐标、UI 坐标 三种坐标系的转换过程&#xff0c;此文章中的 UI 坐标特指 UGUI 坐标 从上图可以看到&#xff0c;世界坐标 和 UI 坐标 需要通过 屏幕坐标作为中间…

Android得到控件在屏幕中的坐标

getLocationOnScreen ,计算该视图在全局坐标系中的x,y值,(注意这个值是要从屏幕顶端算起,也就是索包括了通知栏的高度)//获取在当前屏幕内的绝对坐标 getLocationInWindow ,计算该视图在它所在的widnow的坐标x,y值,//获取在整个窗口内的绝对坐标 (不是很理解= =、) …

安卓 获取屏幕坐标(点击屏幕获取坐标)

工具下载&#xff1a; 实现原理&#xff1a;创建一个背景透明的Activity, 点击屏幕时获取坐标信息并显示。在悬浮窗中调用该Activity&#xff0c;可以获取所有界面的坐标信息。 package sc.tool.screen;import sc.tool.component.ActivityComponent; import android.content.Co…

Unity世界坐标转换屏幕坐标(详解)

我们先通过简单的操作实现一下基础的UI跟随物体移动的功能&#xff0c;首先我们在场景中建立一个Canvas并且添加一个图片作为按钮&#xff0c;之后我们添加一个3d物体作为跟随目标&#xff0c;效果如下图所示 我们配置一下UICanvas的属性&#xff0c;书写对应的自定义类并添加至…

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

在我们的屏幕上&#xff0c;有一张地图&#xff0c;这张地图经过缩放、平移、旋转&#xff0c;最终地理坐标和屏幕坐标的关系大致如下图所示&#xff1a; 这种关系要怎么描述呢&#xff1f;我们可以假设地图是一张纸&#xff0c;而屏幕是一堵墙。只要我们有两个图钉&#xff0c…

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.选择一个简单的程序。…