I wish to create the compass / arrow exactly like the one we see in AroundMe Mobile App that point exactly to a pin to the map accordingly with my mobile position and update the arrow when I move the phone.
我想要创建一个与我们在AroundMe移动应用中看到的完全一样的罗盘/箭头,它精确地指向地图上的一个pin,并在移动电话时更新箭头。
I'm getting crazy to understand exactly how to do that and I can not find any guide or tutorial that explain a bit it.
我简直要疯了,我不知道该怎么做,也找不到任何能解释它的指南或教程。
What I found online is a bearing function and I created a directive around it:
我在网上找到的是一个轴承功能,我围绕它创建了一个指令:
app.directive('arrow', function () {
function bearing(lat1, lng1, lat2, lng2) {
var dLon = (lng2 - lng1);
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
var rad = Math.atan2(y, x);
var brng = toDeg(rad);
return (brng + 360) % 360;
}
function toRad(deg) {
return deg * Math.PI / 180;
}
function toDeg(rad) {
return rad * 180 / Math.PI;
}
return {
restrict: 'E',
link: function (scope, element, attrs) {
var arrowAngle = bearing(scope.user.position.lat, scope.user.position.lng, attrs.lat, attrs.lng);
element.parent().css('transform', 'rotate(' + arrowAngle + 'deg)');
}
};
});
It seems to update the arrow in a direction but unfortunately it is not the right direction because it is not calculated using also the mobile magneticHeading
position.
它似乎是在向一个方向上更新箭头,但不幸的是,它不是正确的方向,因为它不是用移动磁化的位置来计算的。
So I added the ngCordova
plugin for Device Orientation to get the magneticHeading
and now I don't know exactly how to use it and where in the bearing
function.
所以我添加了ngCordova插件用于设备定位以获得磁化,现在我不知道如何使用它以及轴承的位置。
$cordovaDeviceOrientation.getCurrentHeading().then(function(result) {
var magneticHeading = result.magneticHeading;
var arrowAngle = bearing(scope.user.position.lat, scope.user.position.lng, attrs.lat, attrs.lng, magneticHeading);
element.parent().css('transform', 'rotate(' + arrowAngle + 'deg)');
});
I tried to add it in the return statement:
我试图将它添加到返回语句中:
return (brng - heading) % 360;
or:
或者:
return (heading - ((brng + 360) % 360));
Implementing this code with a watcher I see the arrow moving but not in the exact position... For example from my position and the pin the arrow should point to N and it is pointing to E.
用一个观察者来实现这段代码,我看到箭头在移动,但不是在正确的位置。例如,从我的位置和大头针箭头指向N,它指向E。
Always looking online I can not find any tutorial / question to find the bearing between a lat/lng point
and a magnetingHeading
.
我总是在网上找,我找不到任何教程/问题来找到一个lat/lng点和一个磁化点之间的轴承。
Maybe I'm close to the solution but I can not go ahead alone.
也许我已经接近解决方案了,但我不能独自前行。
I also tried to search for a mathematical formulas but even there is a huge pain to understand and implement it.
我也尝试去寻找一个数学公式,但是即使是要理解和实现它也是非常痛苦的。
I hope you can help.
我希望你能帮忙。
1 个解决方案
#1
1
It's hard to give a plain answer to this question because a lot depends on the actual graphical representation. For instance, in what direction do you point where rotate(0deg)
.
对于这个问题,很难给出一个简单的答案,因为这在很大程度上取决于实际的图形表示。例如,你指向哪个方向旋转(0deg)。
I can explain the formula you've found, which might help you to clear the issue yourself. The hard part is the following:
我可以解释你找到的公式,可以帮助你自己解决问题。难点在于:
var dLon = (lng2 - lng1);
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
var rad = Math.atan2(y, x);
What you see here is Haversines formula (https://en.wikipedia.org/wiki/Haversine_formula). Normally one could suffice with two sets of coordinates and calculate the angle between them. When working with latitude and longitude this will not work because the earth is not a flat surface. The first three lines are Haversine and the result (x
and y
) are coordinates on the unit circle
(https://en.wikipedia.org/wiki/Unit_circle)
这里看到的是Haversines公式(https://en.wikipedia.org/wiki/Haversine_formula)。通常一个可以满足两组坐标并计算它们之间的夹角。当使用纬度和经度时,这将不起作用,因为地球不是一个平坦的表面。前三行是Haversine,结果(x和y)是单位圆上的坐标(https://en.wikipedia.org/wiki/Unit_circle)
The next step is to calculate the angle from the point on this unit circle to the center. We can use the arctangant
for this. Javascript has a helper function atan2
which simplifies this process. The result is simple the angle of your point towards the center of the circle. In other words, your position towards your point of interest. The result is in radians and needs to be converted to degrees. (https://en.wikipedia.org/wiki/Atan2)
下一步是计算从这个单位圆到中心的角度。我们可以用arctangant表示。Javascript有一个帮助函数atan2,它简化了这个过程。结果很简单,你的点朝向圆的中心的角度。换句话说,你对自己兴趣点的立场。结果是弧度,需要转换成度数。(https://en.wikipedia.org/wiki/Atan2)
A simplified version with a flat coordinate system would look like this:
使用平面坐标系的简化版本如下:
var deltaX = poi.x - you.x;
var deltaY = you.y - poi.y;
var rotation = toDeg(Math.atan2(deltaX, deltaY));
bearingElement.css('transform', 'rotate(' + rotation + 'deg)');
Where poi
is the Point of Interest and you
is your position.
poi是你的兴趣点,你是你的位置。
To compensate for your own rotation, you need to substract your own rotation. In the above sample the result would become:
为了补偿你自己的旋转,你需要减去你自己的旋转。在上述样本中,结果将为:
var deltaX = poi.x - you.x;
var deltaY = you.y - poi.y;
var rotation = toDeg(Math.atan2(deltaX, deltaY));
rotation -= you.rotation;
bearingElement.css('transform', 'rotate(' + rotation + 'deg)');
I've made a Plunckr in which you can see a simple flat coordinate system. You can move and rotate you
and the point of interest
. The arrow inside 'you' will always point towards the poi
, even if you rotate 'you'. This is because we compensate for our own rotation.
我做了一个简单的平面坐标系。你可以移动和旋转你和兴趣点。“你”里面的箭头总是指向poi,即使你旋转“你”。这是因为我们补偿了自己的旋转。
https://plnkr.co/edit/OJBGWsdcWp3nAkPk4lpC?p=preview
https://plnkr.co/edit/OJBGWsdcWp3nAkPk4lpC?p=preview
Note in the Plunckr that the 'zero'-position is always to the north. Check your app to see your 'zero'-position. Adjust it accordingly and your script will work.
请注意,“零”的位置总是指向北方。检查你的应用程序,看看你的“零”位置。相应地调整它,您的脚本就会工作。
Hope this helps :-)
希望这有助于:-)
#1
1
It's hard to give a plain answer to this question because a lot depends on the actual graphical representation. For instance, in what direction do you point where rotate(0deg)
.
对于这个问题,很难给出一个简单的答案,因为这在很大程度上取决于实际的图形表示。例如,你指向哪个方向旋转(0deg)。
I can explain the formula you've found, which might help you to clear the issue yourself. The hard part is the following:
我可以解释你找到的公式,可以帮助你自己解决问题。难点在于:
var dLon = (lng2 - lng1);
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
var rad = Math.atan2(y, x);
What you see here is Haversines formula (https://en.wikipedia.org/wiki/Haversine_formula). Normally one could suffice with two sets of coordinates and calculate the angle between them. When working with latitude and longitude this will not work because the earth is not a flat surface. The first three lines are Haversine and the result (x
and y
) are coordinates on the unit circle
(https://en.wikipedia.org/wiki/Unit_circle)
这里看到的是Haversines公式(https://en.wikipedia.org/wiki/Haversine_formula)。通常一个可以满足两组坐标并计算它们之间的夹角。当使用纬度和经度时,这将不起作用,因为地球不是一个平坦的表面。前三行是Haversine,结果(x和y)是单位圆上的坐标(https://en.wikipedia.org/wiki/Unit_circle)
The next step is to calculate the angle from the point on this unit circle to the center. We can use the arctangant
for this. Javascript has a helper function atan2
which simplifies this process. The result is simple the angle of your point towards the center of the circle. In other words, your position towards your point of interest. The result is in radians and needs to be converted to degrees. (https://en.wikipedia.org/wiki/Atan2)
下一步是计算从这个单位圆到中心的角度。我们可以用arctangant表示。Javascript有一个帮助函数atan2,它简化了这个过程。结果很简单,你的点朝向圆的中心的角度。换句话说,你对自己兴趣点的立场。结果是弧度,需要转换成度数。(https://en.wikipedia.org/wiki/Atan2)
A simplified version with a flat coordinate system would look like this:
使用平面坐标系的简化版本如下:
var deltaX = poi.x - you.x;
var deltaY = you.y - poi.y;
var rotation = toDeg(Math.atan2(deltaX, deltaY));
bearingElement.css('transform', 'rotate(' + rotation + 'deg)');
Where poi
is the Point of Interest and you
is your position.
poi是你的兴趣点,你是你的位置。
To compensate for your own rotation, you need to substract your own rotation. In the above sample the result would become:
为了补偿你自己的旋转,你需要减去你自己的旋转。在上述样本中,结果将为:
var deltaX = poi.x - you.x;
var deltaY = you.y - poi.y;
var rotation = toDeg(Math.atan2(deltaX, deltaY));
rotation -= you.rotation;
bearingElement.css('transform', 'rotate(' + rotation + 'deg)');
I've made a Plunckr in which you can see a simple flat coordinate system. You can move and rotate you
and the point of interest
. The arrow inside 'you' will always point towards the poi
, even if you rotate 'you'. This is because we compensate for our own rotation.
我做了一个简单的平面坐标系。你可以移动和旋转你和兴趣点。“你”里面的箭头总是指向poi,即使你旋转“你”。这是因为我们补偿了自己的旋转。
https://plnkr.co/edit/OJBGWsdcWp3nAkPk4lpC?p=preview
https://plnkr.co/edit/OJBGWsdcWp3nAkPk4lpC?p=preview
Note in the Plunckr that the 'zero'-position is always to the north. Check your app to see your 'zero'-position. Adjust it accordingly and your script will work.
请注意,“零”的位置总是指向北方。检查你的应用程序,看看你的“零”位置。相应地调整它,您的脚本就会工作。
Hope this helps :-)
希望这有助于:-)