Frage

Dieses Wochenende habe ich ein paar Minuten Zeit, einen Algorithmus Dreschen zusammen, die in einer Position übernehmen würde (in Grad) und geben einen String für die Himmelsrichtung (ich verwende es in einem Android Kompass Anwendung Ich verwende). Was ich am Ende mit, war dies:

private String headingToString(Float heading)
{
    String strHeading = "?";
    Hashtable<String, Float> cardinal = new Hashtable<String, Float>();
    cardinal.put("North_1", new Float(0));
    cardinal.put("Northeast", new Float(45));
    cardinal.put("East", new Float(90));
    cardinal.put("Southeast", new Float(135));
    cardinal.put("South", new Float(180));
    cardinal.put("Southwest", new Float(225));
    cardinal.put("West", new Float(270));
    cardinal.put("Northwest", new Float(315));
    cardinal.put("North_2", new Float(360));

    for (String key: cardinal.keySet())
    {
        Float value = cardinal.get(key);
        if (Math.abs(heading - value) < 30)
        {
            strHeading = key;
            if (key.contains("North_"))
            {
                strHeading = "North";
            }
            break;
        }
    }
    return strHeading;
}

Meine Frage ist, ist dies der beste Weg, dies zu tun? Es muss schon viele Male zuvor getan hat, obwohl ich habe nicht eine Suche nach Beispielen, die im Internet noch nicht getan. Haben andere Menschen versucht, diese und fand eine sauberere Lösung?

Bearbeiten für Den Reverand des Thilo, shinjin die und Chrstoffer Antworten:

Die Lösung

public static String headingToString2(double x)
{
    String directions[] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"};
    return directions[ (int)Math.round((  ((double)x % 360) / 45)) ];
}
War es hilfreich?

Lösung

Das ist in Ordnung in den meisten Fällen, obwohl es und optimierte zu machen (IMO) cleaner, was Sie tun können, ist eine Funktion findet den Eingang Überschrift einen in der Karte verwendet, bezieht.

Zum Beispiel: (Ich bin ziemlich sicher, das ist richtig, aber Sie werden es überprüfen möchten)

45* (int)Math.round((  ((double)x % 360) / 45))

Was das bedeutet ist zuerst x % 360 stellt sicher, ist die Überschrift innerhalb eines gültigen Bereichs. dann

45 * round(.../45)

findet das nächste Vielfache von 45.

Jetzt ist Ihre Karte ändern sein

  HashMap<Integer, String> map = new HashMap<Integer, String>()
  map.put(0, "North")
  map.put(45, "Northeast")
  etc...

So, jetzt wird Ihr Algorithmus eine schnelle mathemtical Berechnung anstatt durch die Karte laufen. Darüber hinaus müssen Sie nicht als Hashtable hier, da es Konstrukte für die Gleichzeitigkeit liefert (wenn ich mich richtig erinnere) und in Ihrem Fall wäre es tatsächlich zu einem Leistungsabfall.

Wieder einmal können die Leistungseinbußen für Ihre Bedürfnisse völlig vernachlässigbar sein.

Bearbeiten für Thilo und shinjin Vorschläge:

Statt um 45 multipliziert wird, nur hält den Rest der Gleichung, die Sie für 0-7 Werte gibt, und eine Reihe von Saiten machen.

String directions[] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"}
return directions[ (int)Math.round((  ((double)x % 360) / 45)) % 8 ]

und Sie haben Ihr Problem in zwei Linien gelöst.

Ein Hinweis: Modul wird nicht korrekt für negative Zahlen arbeiten. Wenn unser Eingang Überschrift negativ ist, müssen Sie es positiv zuerst machen.

Andere Tipps

Die meisten Antworten hier sind um 22,5 Grad für ihre 45-Grad-Intervallen ab und Karte z.B. 0-45 als N, und nicht [337,5 bis 360], [0-22,5] N. Sie müssen, bevor Sie die Mathematik zu korrigieren, dies kompensieren.

Hier ist eine Lösung, die Anwendungen 22,5-Grad-Intervallen, wie Sie für Windrichtungen sehen könnten:

  private String formatBearing(double bearing) {
    if (bearing < 0 && bearing > -180) {
      // Normalize to [0,360]
      bearing = 360.0 + bearing;
    }
    if (bearing > 360 || bearing < -180) {
      return "Unknown";
    }

    String directions[] = {
      "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
      "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW",
      "N"};
    String cardinal = directions[(int) Math.floor(((bearing + 11.25) % 360) / 22.5)];
    return cardinal + " (" + formatBearing.format(bearing) + " deg)";
  }

Sie könnten vielleicht hinzufügen, um 15 Grad nach vorne North_1 und North_2 zu vermeiden.

Die vorherigen Beispiele sind nicht genau, hier ist eine genauere Lösung in JavaScript.

function getCardinalDirection(input) {
    var directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"];
    var index = Math.floor( ((input-22.5)%360) / 45 );
    return directions[index+1];
}

in Java:

String _directions[] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"};

public String getHeading(int hea) {
  return _directions[(int)Math.floor((hea % 360) / 45)];
}

"java" Fall u müssen eine Klasse erstellen müssen.

in javascript:

var _directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];

function getDirection (hea) {
  return _directions[Math.floor((hea % 360) / 45)];
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top