在Android中计算罗盘方位/前往位置

盛年不重来,一日难再晨,及时当勉励,岁月不待人。这篇文章主要讲述在Android中计算罗盘方位/前往位置相关的知识,希望能为你提供帮助。
我想在谷歌地图视图上的我的位置显示一个箭头,显示我相对于目的地位置(而不是北方)的方向。
a)我使用磁力计和加速度计的传感器值计算了北方。我知道这是正确的,因为它与谷歌地图视图中使用的指南针对齐。
b)我使用myLocation.bearingTo(destLocation)计算了从我的位置到目的地位置的初始方位;
我错过了最后一步; 从这两个值(a和b)我用什么公式来得出手机相对于目的地位置的方向?
感谢任何有关心灵的帮助!
答案好的,我想出来了。对于其他试图这样做的人,你需要:
a)航向:从硬件指南针前进。这是磁北以东的度数
b)轴承:轴承从您的位置到目的地。这是在真北的东边。

myLocation.bearingTo(destLocation);

c)赤纬:真北和磁北之间的差异
从磁力计+加速度计返回的航向是真(磁)北(-180到+180)以东的度数,所以你需要得到北和磁北的区别。这种差异是可变的,取决于你在地球上的位置。您可以使用GeomagneticField类获取。
GeomagneticField geoField; private final LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { geoField = new GeomagneticField( Double.valueOf(location.getLatitude()).floatValue(), Double.valueOf(location.getLongitude()).floatValue(), Double.valueOf(location.getAltitude()).floatValue(), System.currentTimeMillis() ); ... } }

有了这些,您可以计算在地图上绘制的箭头的角度,以显示您相对于目标对象所面对的位置,而不是真正的北方。
首先用赤纬调整你的标题:
heading += geoField.getDeclination();

其次,您需要从目标目的地而不是真北偏移手机朝向(航向)的方向。这是我被困住的部分。从罗盘返回的航向值为您提供一个值,该值描述磁北向(相对于手机指向的位置的真北的度数)。所以例如如果值为-10,则表示磁北向左侧10度。轴承为您提供目的地的角度,以真北为东。因此,在您补偿了赤纬后,您可以使用下面的公式来获得所需的结果:
heading = myBearing - (myBearing + heading);

然后,您将要从真北(-180到+180)以东的度数转换为正常度数(0到360):
Math.round(-heading / 360 + 180)

另一答案这是在Google地图上检测来自位置对象的方位的最佳方法: - >
float targetBearing=90; Location endingLocation=new Location("ending point"); Location startingLocation=new Location("starting point"); startingLocation.setLatitude(mGoogleMap.getCameraPosition().target.latitude); startingLocation.setLongitude(mGoogleMap.getCameraPosition().target.longitude); endingLocation.setLatitude(mLatLng.latitude); endingLocation.setLongitude(mLatLng.longitude); targetBearing = startingLocation.bearingTo(endingLocation);

另一答案以下是计算两点之间轴承角度的代码:
public float CalculateBearingAngle(double lat1,double lon1, double lat2, double lon2){ double Phi1 = Math.toRadians(lat1); double Phi2 = Math.toRadians(lat2); double DeltaLambda = Math.toRadians(lon2 - lon1); double Theta = atan2((sin(DeltaLambda)*cos(Phi2)), (cos(Phi1)*sin(Phi2) - sin(Phi1)*cos(Phi2)*cos(DeltaLambda))); return (float)Math.toDegrees(Theta); }

征集功能:
float angle = CalculateBearingAngle(lat1, lon1, lat2, lon2);

另一答案公式将使用起点坐标到终点see给出方位
以下代码将为您提供轴承(角度在0-360之间)
private double bearing(Location startPoint, Location endPoint) { double longitude1 = startPoint.getLongitude(); double latitude1 = Math.toRadians(startPoint.getLatitude()); double longitude2 = endPoint.getLongitude(); double latitude2 = Math.toRadians(endPoint.getLatitude()); double longDiff = Math.toRadians(longitude2 - longitude1); double y = Math.sin(longDiff) * Math.cos(latitude2); double x = Math.cos(latitude1) * Math.sin(latitude2) - Math.sin(latitude1) * Math.cos(latitude2) * Math.cos(longDiff); return Math.toDegrees(Math.atan2(y, x));

}
这对我有用,希望它也会对其他人有用
另一答案【在Android中计算罗盘方位/前往位置】@Damian- 这个想法非常好,我同意答案,但是当我使用你的代码时我的错误值,所以我自己写了这个(有人在你的评论中说了同样的话)。我想,计算带有赤纬的标题是好的,但后来我使用了类似的东西:
heading = (bearing - heading) * -1;

而不是达米安的代码:
heading = myBearing - (myBearing + heading);

并将-180更改为180表示0到360:
private float normalizeDegree(float value){ if(value > = 0.0f & & value < = 180.0f){ return value; }else{ return 180 + (180 + value); }

然后当你想旋转你的箭头时你可以使用这样的代码:
private void rotateArrow(float angle){Matrix matrix = new Matrix(); arrowView.setScaleType(ScaleType.MATRIX); matrix.postRotate(angle, 100f, 100f); arrowView.setImageMatrix(matrix); }

其中arrowView是带有箭头图片的ImageViewpostRotate中的100f参数是枢轴和旋转)。
我希望我会帮助别人。
另一答案在此指南针上的箭头显示从您的位置到Kaaba的方向(目的地位置)
你可以通过这种方式简单地使用bearing.bearing将给你从你的位置到目的地的直接角度
Location userLoc=new Location("service Provider"); //get longitudeM Latitude and altitude of current location with gps class andset in userLoc userLoc.setLongitude(longitude); userLoc.setLatitude(latitude); userLoc.setAltitude(altitude); Location destinationLoc = new Location("service Provider"); destinationLoc.setLatitude(21.422487); //kaaba latitude setting destinationLoc.setLongitude(39.826206); //kaaba longitude setting float bearTo=userLoc.bearingTo(destinationLoc);

bearingTo会给你-180到180的范围,这会让事情有点混乱。我们需要将此值转换为0到360的范围才能获得正确的旋转。
这是我们真正想要的表格,与轴承给我们的内容相比较
+-----------+--------------+ | bearingTo | Real bearing | +-----------+--------------+ | 0| 0| +-----------+--------------+ | 90| 90| +-----------+--------------+ | 180| 180| +-----------+--------------+ | -90| 270| +-----------+--------------+ | -135| 225| +-----------+--------------+ | -180| 180| +-----------+--------------+

所以我们必须在bearTo之后添加这段代码
// If the bearTo is smaller than 0, add 360 to get the rotation clockwise.if (bearTo < 0) { bearTo = bearTo + 360; //bearTo = -100 + 360= 260; }

你需要实现SensorEventListener及其函数(onSensorChanged,onAcurracyChabge)并写入onSensorChanged中的所有代码
完整的代码在这里为Qibla指南针方向
public class QiblaDirectionCompass extends Service implements SensorEventListener{ public static ImageView image,arrow; // record the compass picture angle turned private float currentDegree = 0f; private float currentDegreeNeedle = 0f; Context context; Location userLoc=new Location("service Provider"); // device sensor manager private static SensorManager mSensorManager ; private Sensor sensor; public static TextView tvHeading; public QiblaDirectionCompass(Context context, ImageView compass, ImageView needle,TextView heading, double longi,double lati,double alti ) {image = compass; arrow = needle; // TextView that will tell the user what degree is he heading tvHeading = heading; userLoc.setLongitude(longi); userLoc.setLatitude(lati); userLoc.setAltitude(alti); mSensorManager =(SensorManager) context.getSystemService(SENSOR_SERVICE); sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); if(sensor!=null) { // for the system's orientation sensor registered listeners mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME); //SensorManager.SENSOR_DELAY_Fastest }else{ Toast.makeText(context,"Not Supported", Toast.LENGTH_SHORT).show(); } // initialize your android device sensor capabilities this.context =context; @Override public void onCreate() { // TODO Auto-generated method stub Toast.makeText(context, "Started", Toast.LENGTH_SHORT).show(); mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME); //SensorManager.SENSOR_DELAY_Fastest super.onCreate(); }@Override public void onDestroy() { mSensorManager.unregisterListener(this); Toast.makeText(context, "Destroy", Toast.LENGTH_SHORT).show(); super.onDestroy(); } @Override public void onSensorChanged(SensorEvent sensorEvent) {Location destinationLoc = new Location("service Provider"); destinationLoc.setLatitude(21.422487); //kaaba latitude setting destinationLoc.setLongitude(39.826206); //kaaba longitude s

    推荐阅读