将纬度和经度映射到JavaScript中的Canvas点

时间:2017-06-08 08:53:55

标签: javascript canvas html5-canvas location

我正在编写一个AR应用程序,用户可以从船长的角度看到这样的船 enter image description here

我想使用其他船只的坐标(如左边的坐标)使用Canvas在图像顶部绘制船只。我遇到的问题是将纬度,经度映射到Canvas点。

我已经阅读了有关Haversine和Bearing公式但我无法弄清楚如何使用它们来做我想要的事情。我知道用户正在查看的船的纬度和经度,并尝试使用它们来计算另一艘船的Canvas点,但我无法让它工作。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

在相机视图中查找真实世界对象。

这是最简单的答案,因为有许多未知因素会影响结果。

问题

图像说明了我理解的问题。 enter image description here

我们有3艘船(寻找解决方案所需的最低要求),标有红色A,B,C。我们知道每艘船的纬度和经度。当它们靠近时,不需要校正由于经度会聚引起的任何失真。

绿线表示相机的视图,图像通过镜头投影到CCD上(A线上方的绿线)然后将twp灰线投影到船下方的相机屏幕上。

三角剖分和三角形。

从经度我们可以找到每艘船到另一艘船的距离,给出了三角形边长的长度。

var ships = {
    A : { lat : ?, long : ? },
    B : { lat : ?, long : ? },
    C : { lat : ?, long : ? },
}
var AB = Math.hypot(ships.A.lat - ships.B.lat, ships.A.long - ships.B.long);
var BC = Math.hypot(ships.C.lat - ships.B.lat, ships.C.long - ships.B.long);
var CA = Math.hypot(ships.A.lat - ships.C.lat, ships.A.long - ships.C.long);

插图三角形显示了如何根据边的长度找到角的角度。

为此我们在角度pheta

之后
var pheta = Math.acos(BC * BC - AB * AB + CA * CA) / (-2 * AB * CA));

相机的视野。

现在我们需要一些额外的信息。这是相机的视野(在图像中为绿线和红色FOV)。您必须找到您正在使用的相机的详细信息。

典型的手机相机的焦距(fl)相当于24-35毫米,并且相对而言知道CCD尺寸,您可以找到FOV var FOV = 2 * Math.atan((CCD.width / 2) / fl)但这有问题因为现代手机的厚度不到10mm,CCD很小,实际尺寸是多少?

您可以使用一个漫长而复杂的过程来确定FOV而不知道相机的内部尺寸,但很容易查找手机规格。

现在让我们假设相机的FOV为67deg(1.17radians)。如果相机的分辨率为1280并且我们忽略镜头失真,并保持相机垂直并与目标处于同一水平,我们可以通过它们之间的角度计算两艘船之间的距离(以像素为单位)。

var FOV = 1.17; // radians the Field of View of the camera
var pixels = (1.17 / 1280) * pheta; // 1280 is horizontal resolution of display

所以现在我们在相机上的两艘船之间有像素距离。假设它们适合相机,我们错过了一些更重要的信息。

轴承

我们需要知道相机指向轴承的方向。只有当我们有了这个,我们才能找到船只。因此,假设手机上的GPS为您提供实时轴承。我们需要的是对其中一艘船的承载。

我不得不深入挖掘我的档案以找到它,它没有任何来源或反抗,因此只能按原样提供。所有它都是Haversin所以假设这是使用的方法。

经过一番进一步的挖掘后,我发现原始源代码很可能来自Calculate distance, bearing and more between Latitude/Longitude points

function deg2rad(angle) {  return angle * 0.017453292519943295 }
function rad2deg(angle) {  return angle / 0.017453292519943295 }
//return bearing in radians.
function getBearing(lat1,lon1,lat2,lon2){
    var earth = 6371e3; 
    var lat1 = lat1.toRadians();
    var lat2 = lat2.toRadians();
    var lon1 = lon1.toRadians();
    var lon2 = lon2.toRadians();
    var latD = lat2-lat1;
    var lonD = lon2-lon1;
    var a = Math.sin(latD / 2) * Math.sin(latD / 2) +  Math.cos(lat1 ) * Math.cos(lat2) *  Math.sin(lonD / 2) * Math.sin(lonD / 2);
    var c = 2 * Math.atan2( Math.sqrt(a),  Math.sqrt(1-a) );
    return earth * c;
}

所以现在你可以从你那里获得一艘船的轴承。用它和你的方位来找出你和它之间的角度差异。

   var yourBearing = ?; // in radians
   var shipBBearing = getBearing(ships.A.lat, ships.A.long, ships.B.lat, ships.B.long);

现在获得角度差异

   var shipBAt = yourBearing - shipBBearing

知道像素FOV

   var shipBPixelsFromCenter = (FOV / 1280) * shipBAt;

   var shipBXpos = 1280 / 2 - shipBPixelsFromCenter;
   // and from above the dif in pixels between ships is
   var shipCXpos = shipBXpos + pixels.

完成了。