Frage

Ich möchte auf einer Google-Karte anzeigen einen Pfeil an meinem Standort anzuzeigen, dass zeigt meine Richtung relativ zu einem Zielort (statt nach Norden).

a) Ich habe nördlich berechnet die Sensorwerte aus dem Magnetometer und Beschleunigungsmesser. Ich weiß, dass dies richtig ist, weil es Linien mit dem Kompass auf der Google Map-Ansicht verwendet werden.

b) Ich habe die anfänglichen Lager von meinem Standort zum Zielort berechnet unter Verwendung myLocation.bearingTo (destLocation);

Ich vermisse den letzten Schritt; Aus diesen beiden Werten (a & b) welcher Formel verwende ich die Richtung zu bekommen, in dem das Telefon in Bezug auf den Zielort zeigt?

Jede mögliche Hilfe schätzen für einen verwirrten Geist!

War es hilfreich?

Lösung

Ok, ich dachte, diese aus. Für alle anderen versuchen, dies zu tun, müssen Sie:

a) Überschrift: Ihre Überschrift aus dem Hardware-Kompass. Dies ist in Grad östlich von magnetic Norden

b) Lager: das Lager von Ihrem Standort zum Zielort. Dies ist in Grad östlich von true Norden.

myLocation.bearingTo(destLocation);

c) Deklination: die Differenz zwischen geografischem und magnetischem Nordpol

Die Überschrift, die aus dem Magnetometer + accelermometer zurückgegeben wird, ist in Grad östlich von true (magnetisch) Nord (-180 bis +180), so müssen Sie den Unterschied zwischen dem Norden und dem magnetischen Norden für Ihren Standort zu erhalten. Dieser Unterschied ist variabel je nachdem, wo man auf der Erde ist. Sie können erhalten durch GeomagneticField Klasse.

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()
      );
      ...
   }
}

Bewaffnet mit diesen berechnen Sie den Winkel des Pfeils auf der Karte zeichnen zu zeigen, wo Sie in Bezug auf Ihr Zielobjekt stehen, anstatt wahre Norden.

Zuerst passen Sie Ihre Überschrift mit der Deklination:

heading += geoField.getDeclination();

Zweitens müssen Sie die Richtung versetzen, in dem das Telefon (Überschrift) steht vor dem Zielort nicht wahr Norden. Dies ist der Teil, dass ich steckenbleib auf. Die Überschrift Wert aus dem Kompass zurück gibt Ihnen einen Wert, der beschreibt, wo der magnetische Norden (in Grad östlich des wahren Norden) in Bezug auf, wo das Telefon zeigt. So zum Beispiel wenn der Wert -10 wissen Sie, dass der magnetische Norden 10 Grad auf der linken Seite ist. Das Lager gibt Ihnen den Winkel Ihres Ziel in Grad östlich des wahren Norden. So, nachdem Sie für die Deklination kompensiert haben, können Sie die Formel verwenden unten um das gewünschte Ergebnis zu erhalten:

heading = myBearing - (myBearing + heading); 

Sie wollen dann von Grad konvertieren östlich von wahrem Norden (-180 bis +180) in der normalen Grad (0 bis 360):

Math.round(-heading / 360 + 180)

Andere Tipps

@Damian - Die Idee ist sehr gut, und ich stimme mit Antwort, aber wenn ich den Code verwendet wurde, hatte ich falsche Werte, so dass ich dies schrieb auf meinem eigenen (jemand gesagt, das gleiche in Ihren Kommentaren). Zählen Überschrift mit der Deklination ist gut, denke ich, aber später habe ich etwas wie folgt aus:

heading = (bearing - heading) * -1;

anstelle von Damians Code:

heading = myBearing - (myBearing + heading); 

und -180 bis 180 für 0 bis 360 zu ändern:

      private float normalizeDegree(float value){
          if(value >= 0.0f && value <= 180.0f){
              return value;
          }else{
              return 180 + (180 + value);
          }

und dann, wenn Sie Ihren Pfeil drehen möchten Sie Code wie folgt verwenden können:

      private void rotateArrow(float angle){

            Matrix matrix = new Matrix();
            arrowView.setScaleType(ScaleType.MATRIX);
            matrix.postRotate(angle, 100f, 100f);
            arrowView.setImageMatrix(matrix);
      }

wo arrowView ist ImageView mit Pfeil Bild und 100f Parameter in postRotate ist PivX und pivY).

Ich hoffe, dass ich jemanden helfen.

In diesem einem Pfeil auf Kompass zeigt die Richtung von Ihrem Standort zu Kaaba ( Ziel Lage )

Sie können einfache Verwendung bearingTo in diesem way.bearing geben Ihnen den direkten Winkel von Ihrem Standort zu Zielort

  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 geben Ihnen einen Bereich von -180 bis 180, die Dinge ein wenig verwirren. Wir müssen diesen Wert in einen Bereich konvertieren von 0 bis 360 die richtige Rotation zu erhalten.

Dies ist eine Tabelle von dem, was wir wirklich wollen, zu vergleichen, was bearingTo gibt uns

+-----------+--------------+
| bearingTo | Real bearing |
+-----------+--------------+
| 0         | 0            |
+-----------+--------------+
| 90        | 90           |
+-----------+--------------+
| 180       | 180          |
+-----------+--------------+
| -90       | 270          |
+-----------+--------------+
| -135      | 225          |
+-----------+--------------+
| -180      | 180          |
+-----------+--------------+

, so dass wir diesen Code nach bearTo hinzuzufügen haben

// If the bearTo is smaller than 0, add 360 to get the rotation clockwise.

  if (bearTo < 0) {
    bearTo = bearTo + 360;
    //bearTo = -100 + 360  = 260;
}

Sie müssen die SensorEventListener und seine Funktionen implementiert (onSensorChanged, onAcurracyChabge) und schreiben Sie alle den Code in onSensorChanged

Komplette Code ist hier für die Richtung der Qibla Kompass

 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;
}

xml-Code ist hier

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/flag_pakistan">
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/heading"
    android:textColor="@color/colorAccent"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="100dp"
    android:layout_marginTop="20dp"
    android:text="Heading: 0.0" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/heading"
android:scaleType="centerInside"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true">

<ImageView
    android:id="@+id/imageCompass"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:scaleType="centerInside"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:src="@drawable/images_compass"/>

<ImageView
    android:id="@+id/needle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:scaleType="centerInside"
    android:src="@drawable/arrow2"/>
</RelativeLayout>
</RelativeLayout>

Ich bin kein Experte in Kartenlesen / Navigation und so weiter, aber sicher ‚Richtungen‘ bin absolut und nicht relativ oder in Wirklichkeit sind sie in Bezug auf N oder S, die selbst festgelegt sind / absolut.

Beispiel: eine imaginäre Linie zwischen Ihnen gezogen Angenommen, und Ihrem Ziel entspricht mit ‚absoluten‘ SE (ein Lager von 135 Grad relativ zum magnetischen N). Nehmen wir nun an Ihr Telefon NW zeigt - wenn Sie eine imaginäre Linie von einem imaginären Objekt am Horizont zu Ihrem Ziel ziehen, wird es durch Ihren Standort passieren und einen Winkel von 180 Grad. Jetzt 180 Grad im Sinne eines Kompasses bezieht sich eigentlich auf S, aber das Ziel ist nicht ‚durch S‘ des imaginären Objekts Ihr Telefon zeigt auf, und außerdem, wenn Sie zu diesem imaginären Punkt an, Ihr Ziel wäre immer noch sein SE von wo Sie bewegt.

In Wirklichkeit ist die 180-Grad-Linie sagt Ihnen, tatsächlich das Ziel ‚hinter sich‘ in Bezug auf die Art und Weise das Telefon (und vermutlich auch Sie) zeigen.

Having said that, aber wenn von der imaginären Punkt zu Ihrem Ziel, den Winkel einer Linie Berechnen (durch Ihre Position vorbei), um einen Zeiger auf Ihr Ziel zu ziehen ist, was Sie wollen ... einfach subtrahieren die (absolute ) Peilung des Ziels aus der absoluten Peilung des imaginären Objekts und eine Negation ignorieren (falls vorhanden). z.B. NW - SE 315 -. 135 = 180, so dass die Zeiger auf Punkt des Bildschirms am Boden zeichnen anzeigt ‚hinter dir‘

EDIT: ich die Mathematik bekam etwas falsch ... subtrahiert die kleiner des Lagers von dem größeren dann das Ergebnis subtrahiert von 360 um den Winkel zu erhalten, in dem den Zeiger auf dem Bildschirm zu zeichnen.

Wenn Sie auf der gleichen Zeitzone sind

Convert GPS UTM

http://www.ibm.com/developerworks/java/library/j-coordconvert/ http://stackoverflow.com/questions/176137/java-convert-lat-lon-to-utm

UTM-Koordinaten erhalten Sie ein simples X Y 2D

Berechnen Sie den Winkel zwischen den beiden UTM-Standorten

http://forums.groundspeak.com/GC/index.php?showtopic=146917

Dies gibt die Richtung, als ob man nach Norden sucht

Also, was Sie im Zusammenhang drehen sich Nord subtrahieren nur diesen Winkel

Wenn beide Punkt einen UTM-45 ° Grad-Winkel hat, und Sie sind 5 ° östlich von Norden, Ihr Pfeil auf 40º von Norden Punkt

Hier ist, wie ich es getan haben:

Canvas g = new Canvas( compass );
Paint p = new Paint( Paint.ANTI_ALIAS_FLAG );

float rotation = display.getOrientation() * 90;

g.translate( -box.left, -box.top );
g.rotate( -bearing - rotation, box.exactCenterX(), box.exactCenterY() );
drawCompass( g, p );
drawNeedle( g, p );

Ich weiß, das ist ein wenig alt, aber im Interesse der Leute wie mich von Google, die keine vollständige Antwort hier gefunden haben. Hier sind einige Auszüge aus meiner Anwendung, die die Pfeile innerhalb einer benutzerdefinierten Listenansicht setzen ....

Location loc;   //Will hold lastknown location
Location wptLoc = new Location("");    // Waypoint location 
float dist = -1;
float bearing = 0;
float heading = 0;
float arrow_rotation = 0;

LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);

if(loc == null) {   //No recent GPS fix
    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setAltitudeRequired(false);
    criteria.setBearingRequired(true);
    criteria.setCostAllowed(true);
    criteria.setSpeedRequired(false);
    loc = lm.getLastKnownLocation(lm.getBestProvider(criteria, true));
}

if(loc != null) {
    wptLoc.setLongitude(cursor.getFloat(2));    //Cursor is from SimpleCursorAdapter
    wptLoc.setLatitude(cursor.getFloat(3));
    dist = loc.distanceTo(wptLoc);
    bearing = loc.bearingTo(wptLoc);    // -180 to 180
    heading = loc.getBearing();         // 0 to 360
    // *** Code to calculate where the arrow should point ***
    arrow_rotation = (360+((bearing + 360) % 360)-heading) % 360;
}

ich bereit, es zu wetten, vereinfacht werden könnte, aber es funktioniert! LastKnownLocation wurde verwendet, da dieser Code von neuem SimpleCursorAdapter.ViewBinder war ()

OnLocationChanged enthält einen Aufruf an notifyDataSetChanged ();

Code auch von neuem SimpleCursorAdapter.ViewBinder (), um Satz Bilddrehung und listrow Farben (nur in einem einzigen column Geist Sie angewandt) ...

LinearLayout ll = ((LinearLayout)view.getParent());
ll.setBackgroundColor(bc); 
int childcount = ll.getChildCount();
for (int i=0; i < childcount; i++){
    View v = ll.getChildAt(i);
    if(v instanceof TextView) ((TextView)v).setTextColor(fc);
    if(v instanceof ImageView) {
        ImageView img = (ImageView)v;
        img.setImageResource(R.drawable.ic_arrow);
        Matrix matrix = new Matrix();
        img.setScaleType(ScaleType.MATRIX);
        matrix.postRotate(arrow_rotation, img.getWidth()/2, img.getHeight()/2);
        img.setImageMatrix(matrix); 
}

Falls Sie mich fragen, ich habe weg mit den magnetischen Sensor Dramen, war der Ärger in meinem Fall nicht wert. Ich hoffe, dass jemand dies als nützlich findet, wie ich in der Regel tun, wenn Google bringt mich zu Stackoverflow!

Hier ist der Code für die Berechnung der Lagerwinkel zwischen zwei Punkten:

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);
}

Aufruf zur Funktion:

float angle = CalculateBearingAngle(lat1, lon1, lat2, lon2);

Terminologie: Der Unterschied zwischen geografischem und magnetischem Norden wird als „Variation“ bezeichnet nicht Deklination. Der Unterschied zwischen dem, was Ihr Kompass liest und die magnetische Überschrift als „Abweichung“ bekannt und variiert mit der Überschrift. Ein Kompass swing identifiziert Gerätefehler und erlaubt Korrekturen angewendet werden, wenn das Gerät in Korrektur eingebaut hat. Ein magnetischer Kompass wird eine Abweichung Karte aufweisen, die die Gerätefehler auf jeder Position beschreibt.

Deklination: Ein Begriff in Astro-Navigation verwendet: Deklination ist wie Länge. Er berichtet, wie weit ein Stern vom Himmelsäquator ist. Um die Deklination eines Sterns zu finden eine Stunde Kreis „gerade nach unten“ vom Sterne zum Himmelsäquator folgen. Der Winkel vom Sterne zum Himmelsäquator entlang des Stundenkreises ist die Deklination des Sterns.

Ich bin in dem Prozess der Bezifferung jetzt, aber es scheint, als ob die Mathematik abhängt, wo Sie und Ihr Ziel sind auf der Erde relativ zu wahren und magnetischen Norden. Zum Beispiel:

float thetaMeThem = 0.0;
if (myLocation.bearingTo(targetLocation) > myLocation.getBearing()){ 
     thetaMeThem = myLocation.bearingTo(targetLocation) - azimuth + declination;} 

Siehe Sensor.TYPE_ORIENTATION für Azimut.

Siehe getDeclination () für Deklination

Dies setzt voraus, Deklination negativ (westlich des wahren Norden) und theirBearing> yourBearing.

Wenn Deklination positiv und yourBearing> theirBearing eine weitere Option:

float thetaMeThem = 0.0;
if (myLocation.bearingTo(targetLocation) < myLocation.getBearing()){ 
     thetaMeThem = azimuth - (myLocation.bearingTo(targetLocation) - declination);} 

Ich habe dies nicht vollständig getestet, aber das Spiel mit den Winkeln auf dem Papier habe mich hier.

Dies ist der beste Weg, Bearing vom Standort Objekt auf Google Map erkennen: ->

 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);

Die Formel wird das Lager geben die Koordinaten des Startpunkt bis zum Endpunkt mit

scroll top