从纬度,经度转换为x,y

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从纬度,经度转换为x,y相关的知识,希望对你有一定的参考价值。

我想将GPS位置(纬度,经度)转换为x,y坐标。我找到了许多关于这个主题的链接并应用了它,但它没有给我正确的答案!

我按照这些步骤来测试答案:(1)首先,我采取两个位置并使用地图计算它们之间的距离。 (2)然后将两个位置转换为x,y坐标。 (3)然后再次计算x,y坐标中两点之间的距离,看它是否在点(1)给出了相同的结果。

我发现以下解决方案之一,但它没有给我正确的答案!

latitude = Math.PI * latitude / 180;
longitude = Math.PI * longitude / 180;

// adjust position by radians
latitude -= 1.570795765134; // subtract 90 degrees (in radians)

// and switch z and y 
xPos = (app.radius) * Math.sin(latitude) * Math.cos(longitude);
zPos = (app.radius) * Math.sin(latitude) * Math.sin(longitude);
yPos = (app.radius) * Math.cos(latitude);

我也试过这个link,但仍然不能与我合作!

任何帮助如何从(纬度,经度)转换为(x,y)?

谢谢,

答案

No exact solution exists

从球体到平面没有等距映射。将lat / lon坐标从球体转换为平面中的x / y坐标时,您无法希望此操作将保留所有长度。你必须接受某种变形。确实存在许多不同的地图投影,这可以在长度,角度和区域的保留之间实现不同的折衷。对于地球表面的小部分,transverse Mercator很常见。你可能听说过UTM。但是有many more

您引用的公式计算x / y / z,即3D空间中的点。但即便如此,你也无法自动获得正确的距离。球体表面上两点之间的最短距离将通过该球体,而地球上的距离大部分是表面之后的测地长度。所以他们会更长。

Approximation for small areas

如果要绘制的地球表面部分相对较小,则可以使用非常简单的近似值。您可以简单地使用水平轴x来表示经度λ,垂直轴y来表示纬度φ。但是,它们之间的比例不应该是1:1。相反,你应该使用cos(φ0)作为宽高比,其中φ0表示靠近地图中心的纬度。此外,要从角度(以弧度测量)转换为长度,您需要乘以地球的半径(在此模型中假定为球体)。

  • x =rλcos(φ0)
  • y =rφ

这是简单的equirectangular projection。在大多数情况下,您只能计算一次cos(φ0),这使得后续计算大量的点非常便宜。

另一答案

我想与您分享我是如何解决问题的。我已经像@MvG所说的那样使用了equirectangular投影,但是这种方法为你提供了与地球(或整个地图)相关的X和Y位置,这意味着你获得了全球位置。在我的情况下,我想转换一个小区域(约500平方米)的坐标,所以我将投影点与另外两个点相关联,获得全局位置并与本地(屏幕上)位置相关,如下所示:

首先,我在我想要投影的区域周围选择2个点(左上角和右下角),就像这张图片一样:

enter image description here

一旦我在lat和lng中有了全局参考区域,我就会对屏幕位置做同样的事情。包含此数据的对象如下所示。

//top-left reference point
var p0 = {
    scrX: 23.69,        // Minimum X position on screen
    scrY: -0.5,         // Minimum Y position on screen
    lat: -22.814895,    // Latitude
    lng: -47.072892     // Longitude
}
//bottom-right reference point
var p1 = {
    scrX: 276,          // Maximum X position on screen
    scrY: 178.9,        // Maximum Y position on screen
    lat: -22.816419,    // Latitude
    lng: -47.070563     // Longitude
}
var radius = 6.371;     //Earth Radius in Km

//## Now I can calculate the global X and Y for each reference point ##

// This function converts lat and lng coordinates to GLOBAL X and Y positions
function latlngToGlobalXY(lat, lng){
    //Calculates x based on cos of average of the latitudes
    let x = radius*lng*Math.cos((p0.lat + p1.lat)/2);
    //Calculates y based on latitude
    let y = radius*lat;
    return {x: x, y: y}
}
// Calculate global X and Y for top-left reference point
p0.pos = latlngToGlobalXY(p0.lat, p0.lng);
// Calculate global X and Y for bottom-right reference point
p1.pos = latlngToGlobalXY(p1.lat, p1.lng);

/*
* This gives me the X and Y in relation to map for the 2 reference points.
* Now we have the global AND screen areas and then we can relate both for the projection point.
*/

// This function converts lat and lng coordinates to SCREEN X and Y positions
function latlngToScreenXY(lat, lng){
    //Calculate global X and Y for projection point
    let pos = latlngToGlobalXY(lat, lng);
    //Calculate the percentage of Global X position in relation to total global width
    pos.perX = ((pos.x-p0.pos.x)/(p1.pos.x - p0.pos.x));
    //Calculate the percentage of Global Y position in relation to total global height
    pos.perY = ((pos.y-p0.pos.y)/(p1.pos.y - p0.pos.y));

    //Returns the screen position based on reference points
    return {
        x: p0.scrX + (p1.scrX - p0.scrX)*pos.perX,
        y: p0.scrY + (p1.scrY - p0.scrY)*pos.perY
    }
}

//# The usage is like this #

var pos = latlngToScreenXY(-22.815319, -47.071718);
$point = $("#point-to-project");
$point.css("left", pos.x+"em");
$point.css("top", pos.y+"em");

如您所见,我在javascript中创建了这个,但计算可以转换为任何语言。

PS:我将转换后的位置应用于id为“point-to-project”的html元素。为了在项目中使用这段代码,您应创建此元素(设置为绝对位置)或更改“使用”块。

另一答案

由于此页面显示在谷歌之上,而我搜索同样的问题,我想提供一个更实际的答案。 MVG的答案是正确的,但相当理论化。

我已经在javascript中为fitbit离子绘制了一个跟踪绘图应用程序。下面的代码是我如何解决这个问题。

//LOCATION PROVIDER
index.js
var gpsFix = false;
var circumferenceAtLat = 0;
function locationSuccess(pos){
  if(!gpsFix){
    gpsFix = true;
    circumferenceAtLat = Math.cos(pos.coords.latitude*0.01745329251)*111305;
  }
  pos.x:Math.round(pos.coords.longitude*circumferenceAtLat),
  pos.y:Math.round(pos.coords.latitude*110919), 
  plotTrack(pos);
}

plotting.js

plotTrack(position){

let x = Math.round((this.segments[i].start.x - this.bounds.minX)*this.scale);
let y = Math.round(this.bounds.maxY - this.segments[i].start.y)*this.scale; //heights needs to be inverted

//redraw?
let redraw = false;

//x or y bounds?
 if(position.x>this.bounds.maxX){
   this.bounds.maxX = (position.x-this.bounds.minX)*1.1+this.bounds.minX; //increase by 10%
   redraw = true;
 }
 if(position.x<this.bounds.minX){
   this.bounds.minX = this.bounds.maxX-(this.bounds.maxX-position.x)*1.1;
    redraw = true;
 };
 if(position.y>this.bounds.maxY){
   this.bounds.maxY = (position.y-this.bounds.minY)*1.1+this.bounds.minY; //increase by 10%
    redraw = true;
 }
 if(position.y<this.bounds.minY){
   this.bounds.minY = this.bounds.maxY-(this.bounds.maxY-position.y)*1.1;
    redraw = true;
 }
 if(redraw){
   reDraw();
 }
}


function reDraw(){

let xScale = device.screen.width / (this.bounds.maxX-this.bounds.minX);
let yScale = device.screen.height / (this.bounds.maxY-this.bounds.minY); 
if(xScale<yScale) this.scale = xScale; 
else this.scale = yScale;

//Loop trough your object to redraw all of them
}
另一答案

最好转换为utm坐标,并将其视为x和y。

import utm
u = utm.from_latlon(12.917091, 77.573586)

结果将是(779260.623156606,1429369.8665238516,43,'P')前两个可以被视为x,y坐标,43P是UTM区域,对于小区域(宽度高达668 km)可以忽略。

以上是关于从纬度,经度转换为x,y的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中将纬度和经度转换为 x,y?

将 x,y 转换为纬度和经度

在 iPhone 上将经度/纬度转换为 x/y

如何将屏幕 X 和 Y 转换为纬度和经度

将 X,Y 转换为纬度经度到 ESRI shapefile

PHP - 将纬度和经度转换为 x 和 y 坐标,而不使用任何库