我正在编写一个AR应用程序,其中用户可以从这样的船长的角度看到船
javascript - 在JavaScript中将经纬度映射到Canvas点-LMLPHP

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

我已经阅读了Haversine和Bearing公式,但无法弄清楚如何使用它们完成我想要的操作。我知道用户正在看的船的纬度和经度,并尝试使用它们来计算另一艘船的Canvas点,但是我无法使其正常工作。有任何想法吗?

最佳答案

在相机视图中寻找现实世界的对象。

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

问题

图片据我所知显示了问题。 javascript - 在JavaScript中将经纬度映射到Canvas点-LMLPHP

我们有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-35mm当量,并且知道CCD的相对尺寸,您可以找到FOVvar FOV = 2 * Math.atan((CCD.width / 2) / fl),但这是有问题的,因为现代手机的厚度小于10mm,并且CCD很小,实际尺寸是多少?

您可以使用漫长而复杂的过程来确定FOV,而无需了解相机的内部尺寸,但很容易查看电话规格。

现在,让我们假设摄像机的FOV为67度(1.17弧度)。如果摄像机的分辨率为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


了解像素视场

   var shipBPixelsFromCenter = (FOV / 1280) * shipBAt;

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


并做了。

10-04 22:38