我正在开发AS3 AIR for Android应用程序。 “我的问题是:给定一个GPS位置,我想找回运动方向(北,西,西,西南,南,东,东,东北)”
我想了解如何使用2种不同的GPS读数来推断出旅行方向的代码。然后我想将这些数据用于360度。
我想我理解如何获得像北方,南方,东方和西方这样的大方向。 我会得到2个独立的GPS读数并比较类似的东西......
在第一次或第二次GPS读数中查看X是否更大。 在第一次或第二次GPS读数中查看Y是否更大。 由此我应该能够看到总体方向。 比较X1和X2的差异与Y1和Y2的差异。那么你可以看到用户最多的方向。然后显示方向。
我不确定如何获取数据并将其用于像罗盘一样的360解释......任何人都可以帮忙吗?
工作代码--------------------------------------------- ----------------------------------
package
{
import flash.display.Sprite;
// Geolocation sensor stuff
import flash.sensors.Geolocation;
import flash.events.GeolocationEvent;
//Timer setup stuff for setting frequesncy of GPS Update
import flash.utils.Timer;
import flash.events.TimerEvent;
// Sprite and Textfield display
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
public class FlashTest extends Sprite
{
//Variable to check if current or prior Geolocation Event fired
private var gpsCheck:int = 1;
public var dLon:Number
//latitude and longitude in degrees (RAW info from Geolocation)
public var gpsLat1:Number
public var gpsLon1:Number
private var gpsLat2:Number
private var gpsLon2:Number
public var bearing:Number
// Latitude and longitude in radians converted from Degrees
public var gpsLat1R:Number
public var gpsLon1R:Number
private var gpsLat2R:Number
private var gpsLon2R:Number
private var yy:Number
private var xx:Number
public function FlashTest()
{
// Text box for displaying results
var my_txt:TextField = new TextField();
my_txt.wordWrap=true;
my_txt.width = 300;
my_txt.height = 300;
addChild(my_txt);
/*
//If GPS is on device create Geolocation object named "my_geo"
//Request updates from my_geo every 2000 milliseconds. Run onGeoUpdate function
//when Event is triggered. After that create the text box for displaying data.
if (Geolocation.isSupported)
{
var my_geo:Geolocation = new Geolocation();
my_geo.setRequestedUpdateInterval(2000);
my_geo.addEventListener(GeolocationEvent.UPDATE, onGeoUpdate);
var my_txt:TextField = new TextField();
my_txt.wordWrap=true;
my_txt.width = 300;
my_txt.height = 300;
addChild(my_txt);
}
// If GPS is not supported on device display "No GPS Signal"
else
{
addChild(my_txt);
my_txt.wordWrap=true;
my_txt.width = 300;
my_txt.height = 300;
addChild(my_txt);
my_txt.text = "No GPS Signal ";
}
*/
// False GPS reading being passed for testing
//COMMENT THESE LINES OUT STARTING HERE---
gpsLat1 = 42.1234584;
gpsLon1 = -83.1234577;
gpsLat2 = 42.1234583;
gpsLon2 = -83.1234577;
// END OF WHAT SHOULD BE COMMENTED OUT---
// Equations to convert all RAW Geolocation information over to radians
gpsLat1R = gpsLat1 * Math.PI / 180;
gpsLon1R = gpsLon1 * Math.PI / 180;
gpsLat2R = gpsLat2 * Math.PI / 180;
gpsLon2R = gpsLon2 * Math.PI / 180;
// The rest of the math
dLon = gpsLon1 - gpsLon2;
yy = Math.sin(dLon) * Math.cos(gpsLat2R);
xx = Math.cos(gpsLat1R) * Math.sin(gpsLat2R) - Math.sin(gpsLat1R) * Math.cos(gpsLat2R) * Math.cos(dLon);
bearing = Math.atan2(yy, xx) * 180 / Math.PI;
// Run The Geoupdate function
onGeoUpdate();
// onGeoUpdate basically displays the information that was collected and converted.
// This is where you will put what you want the code to do with the results
function onGeoUpdate():void
{
my_txt.text = "My Latitude is "+gpsLat1+ " and my Longitude is "+gpsLon1+
"My 2nd Latitude is "+gpsLat2+" and my 2nd Longitude is "+gpsLon2+
" Bearing is " +bearing;
}
}
}
}
答案 0 :(得分:6)
您需要的公式(适用于lon1
,lon2
经度,以及lat1
,lat2
两个点的纬度)在很多地方都有 - 例如, http://www.movable-type.co.uk/scripts/latlong.html。数学是这样的(把它转换成你最喜欢的语言......):
dLon = lon2 - lon1;
y = sin(dLon) * cos(lat2);
x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) *cos(dLon);
bearing = atan2(y, x) * 180 / Pi;
注意:atan2
会将结果减少为[-pi,pi]之间的值。乘以180/pi
后,数字将在[-180,180]之间。为了获得0到360之间的值,您可以这样做,例如:
if (bearing < 0) bearing += 360;
我希望您能填写所需的任何其他详细信息,以便为您服务。
编辑我已经使用你给出的数字来编写一些代码:这是Matlab,但它应该是非常易读的:
% bearings
lat1 = 42.1234584;
lat2 = 42.1234583;
lon1 = -83.1234577;
lon2 = -83.1234510;
% convert to radians:
g2r = pi/180;
lat1r = lat1 * g2r;
lat2r = lat2 * g2r;
lon1r = lon1 * g2r;
lon2r = lon2 * g2r;
dlonr = lon2r - lon1r;
y = sin(dlonr) * cos(lat2r);
x = cos(lat1r)*sin(lat2r) - sin(lat1r) * cos(lat2r)*cos(dlonr);
% compute bearning and convert back to degrees:
bearing = atan2(y, x) / g2r;
fprintf(1,'x: %+.3e\ny: %+.3e\nbearing: %.3f\n', x, y, bearing);
这导致输出:
x: -1.745e-09
y: +8.673e-08
bearing: 91.153
正如你所看到的,x
和y
很小 - 它们代表了你移动的“地球周长的一小部分”(东部约3.5米,似乎...... )。您应该能够使用这些数字调试您的实现。
请注意GPS可能具有较差的“绝对”精度(在您的情况下,不确定度> 100 m),但仍具有良好的“相对”精度(它测量两个位置之间的差异比100米)。
答案 1 :(得分:2)
如果您使用的是位置API,那么当您的位置发生变化时,您会得到一个回调,为您提供一个Location对象,您可以将bearing
的方向从0-360度移动
答案 2 :(得分:0)
我使用了“breadcrumb”解决方案。
我将addchild mc添加到我当前的位置。当我移动时,新的mc与之前的mc进行比较。
所以首先我在固定的地图上找到我的坐标,然后找到我的“你在这里”。然后在我移动时放置面包屑......然后比较那些面包屑以找到标题。
// geolocation
function onGeoUpdate(event:GeolocationEvent):void{
MapHolder.Star.x = MapHolder.Map.x + (event.longitude - (Min_Longitude)) / ((Max_Longitude) - (Min_Longitude)) * 940;
MapHolder.Star.y = MapHolder.Map.y + 800 - (event.latitude - Min_Latitude) / (Max_Latitude - Min_Latitude) * 800;
/// then create new and previous
var MapHolderStarxold = MapHolder.Star.x;
var MapHolderStaryold = MapHolder.Star.y;
///breadcrumbs
var randomMc:Number = Math.floor(Math.random()*myArray.length);
var mc:MovieClip = new myArray[randomMc];
MapHolder.addChild(mc);
mc.x = MapHolder.Star.x;
mc.y = MapHolder.Star.y;
MapHolder.dirArrow.x = MapHolderStarxold;
MapHolder.dirArrow.y = MapHolderStaryold;
//// MapHolder.Star point
// find out mouse coordinates to find out the angle
var cyB:Number = mc.y - MapHolder.dirArrow.y;
var cxB:Number = mc.x - MapHolder.dirArrow.x;
// find out the angle
var RadiansB:Number = Math.atan2(cyB,cxB);
// convert to degrees to rotate
var DegreesB:Number = RadiansB * 180 / Math.PI;
// rotate
MapHolder.dirArrow.rotation = DegreesB; }