球面上的三维坐标转换为纬度和经度

45

我有以下信息:

存在一个以原点 (0,0,0) 为中心、半径为 R 的球体。在进行光线和球体的交点计算后,我得到了一个存在于球体上的三维空间中的点 (XYZ)。(该点是直线穿过球体表面的精确位置。)

我想要为我的程序计算 XYZ 点所在球体的纬度和经度,但是我无法轻易地想出(或者在谷歌上搜到)实现这一目标的方法。

简言之,我要编写的函数如下:

public static LatLon FromVector3(Vector3 position, float sphereRadius)
{
    return Latitude and Longitude
}

请问有人知道如何做到这一点吗?参考这个维基SVG文件可能会有帮助:地理坐标

更新:

感谢所有提供帮助的答案,最终我选择了这个代码:

 public static LatLon FromVector3(Vector3 position, float sphereRadius)
    {
        float lat = (float)Math.Acos(position.Y / sphereRadius); //theta
        float lon = (float)Math.Atan(position.X / position.Z); //phi
        return new LatLon(lat, lon);
    }

现在我得想想哪个答案对我帮助最大要选择接受 :P。


你使用的是哪种坐标系?使用球极坐标系而不是x、y、z坐标系。 - S L
我提到的XYZ坐标,只是普通的3D坐标,与球面坐标没有任何关系:http://ecommprojects.com/seo/Ahmed-Zewails-4d-Telescope/xyz-coordinates.png - Roy T.
2
我发现在使用SceneKit时,为了获得正确的经纬度符号,需要以下操作:float latitude = -((float)acosf(result.localCoordinates.y / sphereRadius) - M_PI_2); //theta float longitude = M_PI - ((float)atan2f(result.localCoordinates.z, result.localCoordinates.x));/ //phi if (longitude > M_PI) { longitude = longitude - (2.0 * M_PI); } - PKCLsoft
7个回答

38

我认为从x、y、z(3D坐标系统)中找到球极坐标应该不难。

  1. 如果在表面上,r始终是常数。

    enter image description here

  2. (90 - θ) 是你的纬度(负数意味着它在底部),因为它是从顶部测量的

    enter image description here

  3. φ 是你的经度。(但对于经度系统还不太确定)

    enter image description here

另外,请查看维基百科上的这张图表。

enter image description here


哇,感谢您整洁地布局答案,我现在就测试一下。如果一切顺利,我会稍后接受它 :)。 - Roy T.
1
我使用这些公式得到了非常奇怪的结果,所以恐怕这不是解决方案。 - Roy T.
1
nvm,你是正确的。我没有看你的图片,你使用了Z = up,而我使用了Y = up。此外,你交换了纬度和经度。 - Roy T.

13
lat=atan2(z,sqrt(x*x+y*y))
lng=atan2(y,x)
使用 atan2() 函数计算公式更加方便。你不需要添加/减去 pi/2 或关心不同象限的符号问题或除以零。
在北半球,lat 将 >0。
在南半球,lat 将 <0。
在东半球,lng 将 >0。
在西半球,lng 将 <0。

你的纬度似乎正常,但是你的经度非常不稳定。 - Roy T.
@Roy T.:可能取决于两个轴中哪一个是x-和-y。尝试交换x-和y轴(您没有完全指定坐标系)。 - Curd

11

这个使用Javascript/THREE.js的方法对我很有帮助:

var lat = 90 - (Math.acos(y / RADIUS_SPHERE)) * 180 / Math.PI;
var lon = ((270 + (Math.atan2(x , z)) * 180 / Math.PI) % 360) -180;

您是否愿意帮我找出其相反的方法?我有经度、纬度和半径,我正在尝试找到THREE.Vector3的{x,y,z}值。 - Motionharvest
1
在我的案例中,我不得不更改 lon 的计算如下: var lon = ((270 + (Math.atan2(x , z)) * 180 / Math.PI) % 360) -360; - ppareja
RADIUS_SPHERE是什么? - Donny V.
这是地球半径吗?6378140。 - Donny V.

0
r=sqrt(x^2+y^2+z^2)  
phi = arccos(sqrt(x^2+y^2)/r)*sign(y)  
lambda = arccos(x/sqrt(x^2+y^2))  
latitude = 180/pi * phi  
longitude = 180/pi * lambda 

你可能需要稍微调整一下符号


0

这只是草稿式的工作,但是:

Lat = arctan(z/(sqrt(x^2+y^2)))

Long = arccos(sqrt(x^2+y^2)/x)

0

在尝试使用经纬度在球体上放置物体的简单解决方案后,我设计了一个简单的类来让你使用three.js实现它。

var earth = new THREE.GeoSpatialMap(geometry, material);
earth.setTexturesEdgeLongitude(-180.806168);

for (i = 0; i < continentData.length; i += step) {

    var lat = continentData[i];
    var lng = continentData[i + 1];

    var light = new THREE.PointLight(0x0099ff);
    var plant = new org.good.ecology.Plant();
    plant.scale.x = plant.scale.y = plant.scale.z = Math.random() * 3;

    console.log("Adding symbol at: " + lat + " : " + lng);
    earth.addGeoSymbol(
        new THREE.GeoSpatialMap.GeoSymbol(plant, {
            phi: lat,
            lambda: lng
        })
    );


    plant.lookAt(earth.position);

}

https://github.com/scottbyrns/Three.js-Geospatial-Mapping


0

编辑 - 重新阅读您的问题后,我的答案不一定适用,但我将其保留供参考。

这取决于您想要多精确以及您将使用结果的目的。没有单一的纬度和经度系统,例如WGS84(美国GPS)或ETRS89(欧洲GPS)略有不同,并且随着大西洋扩大而分歧越来越大。

http://www.ordnancesurvey.co.uk/oswebsite/gps/information/coordinatesystemsinfo/guidecontents/guide5.html

http://www.ordnancesurvey.co.uk/oswebsite/gps/information/coordinatesystemsinfo/guidecontents/guide6.html

最后,这应该直接回答了你的问题。

http://www.ordnancesurvey.co.uk/oswebsite/gps/information/coordinatesystemsinfo/guidecontents/guideb.html

或者

http://www.ordnancesurvey.co.uk/oswebsite/gps/docs/convertingcoordinates3D.pdf


1
我在游戏中使用球坐标来表示一个完美的球体,以避免使用真实世界中的复杂性 :) - Roy T.
我意识到在发布后,我真的应该好好读一下问题。过去我做了很多这样的事情,所以当看到经纬度时就开始发表自己的见解。 - Jaydee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接