Hola, descubrimos la respuesta a lo que necesitas, desplázate y la verás aquí.
Solución:
Ok, me di cuenta de esto. Para cualquier otra persona que intente hacer esto, necesita:
a) rumbo: tu rumbo de la brújula de hardware. Esto es en grados al este de magnético norte
b) rumbo: el rumbo desde su ubicación hasta la ubicación de destino. Esto es en grados al este de cierto norte.
myLocation.bearingTo(destLocation);
c) declinación: la diferencia entre el norte verdadero y el norte magnético
El rumbo que devuelve el magnetómetro + acelermómetro está en grados al este del norte (magnético) verdadero (-180 a +180), por lo que debe obtener la diferencia entre el norte y el norte magnético para su ubicación. Esta diferencia es variable dependiendo de dónde se encuentre en la tierra. Puede obtenerlo usando la clase 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()
);
...
Armado con estos, calcula el ángulo de la flecha para dibujar en su mapa para mostrar hacia dónde se enfrenta en relación con su objeto de destino en lugar del norte verdadero.
Primero ajuste su rumbo con la declinación:
heading += geoField.getDeclination();
En segundo lugar, debe compensar la dirección en la que el teléfono mira (rumbo) desde el destino objetivo en lugar del norte verdadero. Esta es la parte en la que me quedé atascado. El valor de rumbo devuelto por la brújula le da un valor que describe dónde está el norte magnético (en grados al este del norte verdadero) en relación con el lugar hacia donde apunta el teléfono. Entonces, por ejemplo, si el valor es -10, sabrá que el norte magnético está 10 grados a su izquierda. El rumbo le da el ángulo de su destino en grados al este del norte verdadero. Entonces, después de haber compensado la declinación, puede usar la fórmula a continuación para obtener el resultado deseado:
heading = myBearing - (myBearing + heading);
Luego, querrá convertir de grados al este del norte verdadero (-180 a +180) a grados normales (0 a 360):
Math.round(-heading / 360 + 180)
@Damian: la idea es muy buena y estoy de acuerdo con la respuesta, pero cuando usé su código tenía valores incorrectos, así que escribí esto por mi cuenta (alguien dijo lo mismo en sus comentarios). Contar el rumbo con la declinación es bueno, creo, pero luego usé algo así:
heading = (bearing - heading) * -1;
en lugar del código de Damian:
heading = myBearing - (myBearing + heading);
y cambiando -180 a 180 de 0 a 360:
private float normalizeDegree(float value){
if(value >= 0.0f && value <= 180.0f)
return value;
else
return 180 + (180 + value);
y luego, cuando desee rotar la flecha, puede usar un código como este:
private void rotateArrow(float angle)
Matrix matrix = new Matrix();
arrowView.setScaleType(ScaleType.MATRIX);
matrix.postRotate(angle, 100f, 100f);
arrowView.setImageMatrix(matrix);
dónde arrowView
es ImageView
con imagen de flecha y parámetros 100f en postRotate
es pivX y pivY).
Espero ayudar a alguien.
En este, una flecha en la brújula muestra la dirección desde su ubicación hasta Kaaba(ubicación de destino)
puede usar simplemente BearingTo de esta manera. Bearing le dará el ángulo directo desde su ubicación hasta la ubicación de destino
Location userLoc=new Location("service Provider");
//get longitudeM Latitude and altitude of current location with gps class and set 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 le dará un rango de -180 a 180, lo que confundirá un poco las cosas. Necesitaremos convertir este valor en un rango de 0 a 360 para obtener la rotación correcta.
Esta es una tabla de lo que realmente queremos, comparado con lo que Bear To nos da
+-----------+--------------+
| bearingTo | Real bearing |
+-----------+--------------+
| 0 | 0 |
+-----------+--------------+
| 90 | 90 |
+-----------+--------------+
| 180 | 180 |
+-----------+--------------+
| -90 | 270 |
+-----------+--------------+
| -135 | 225 |
+-----------+--------------+
| -180 | 180 |
+-----------+--------------+
así que tenemos que agregar este código después de 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;
debe implementar SensorEventListener y sus funciones (onSensorChanged, onAcurracyChabge) y escribir todo el código dentro de onSensorChanged
El código completo está aquí para la dirección de la brújula 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 setting
float bearTo=userLoc.bearingTo(destinationLoc);
//bearTo = The angle from true north to the destination location from the point we're your currently standing.(asal image k N se destination taak angle )
//head = The angle that you've rotated your phone from true north. (jaise image lagi hai wo true north per hai ab phone jitne rotate yani jitna image ka n change hai us ka angle hai ye)
GeomagneticField geoField = new GeomagneticField( Double.valueOf( userLoc.getLatitude() ).floatValue(), Double
.valueOf( userLoc.getLongitude() ).floatValue(),
Double.valueOf( userLoc.getAltitude() ).floatValue(),
System.currentTimeMillis() );
head -= geoField.getDeclination(); // converts magnetic north into true north
if (bearTo < 0)
bearTo = bearTo + 360;
//bearTo = -100 + 360 = 260;
//This is where we choose to point it
float direction = bearTo - head;
// If the direction is smaller than 0, add 360 to get the rotation clockwise.
if (direction < 0)
direction = direction + 360;
tvHeading.setText("Heading: " + Float.toString(degree) + " degrees" );
RotateAnimation raQibla = new RotateAnimation(currentDegreeNeedle, direction, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
raQibla.setDuration(210);
raQibla.setFillAfter(true);
arrow.startAnimation(raQibla);
currentDegreeNeedle = direction;
// create a rotation animation (reverse turn degree degrees)
RotateAnimation ra = new RotateAnimation(currentDegree, -degree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// how long the animation will take place
ra.setDuration(210);
// set the animation after the end of the reservation status
ra.setFillAfter(true);
// Start the animation
image.startAnimation(ra);
currentDegree = -degree;
@Override
public void onAccuracyChanged(Sensor sensor, int i)
@Nullable
@Override
public IBinder onBind(Intent intent)
return null;
el código xml está aquí
Te mostramos las reseñas y valoraciones de los lectores
Si te animas, puedes dejar un post acerca de qué le añadirías a este artículo.