Кардинальный алгоритм направления в Java

В эти выходные я провожу несколько минут, перегружая вместе алгоритм, который взял бы в заголовке (в градусах) и возвратил бы Строку для кардинального направления (я использую его в приложении компаса андроида, которое я использую). То, с чем я закончил, было этим:

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

Мой вопрос, действительно ли это - лучший способ сделать это? Это, должно быть, делалось много раз прежде, хотя я еще не сделал поиска примеров в сети. Какие-либо другие люди попробовали это и нашли более опрятное решение?

Редактирование для Thilo Reverand, ответы shinjin и Chrstoffer:

Решение

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)) ];
}
15
задан MattyW 26 January 2010 в 03:54
поделиться

2 ответа

Это нормально в большинстве случаев, хотя для того, чтобы сделать его оптимизированным и (IMO) Cleaner, что вы можете сделать, это найти функцию, чтобы связать входную заголовок к одному использованному на карте.

Например: (Я уверен, что это правильно, но вы захотите проверить его)

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

, что это делает первым x% 360 , гарантирует, что заголовок находится в пределах действительного диапазона. Тогда

45 * round(.../45)

находит ближе всего 45.

Теперь измените вашу карту, чтобы быть

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

Итак, теперь ваш алгоритм становится быстрым математическим расчетом, а не итерацией через карту. Кроме того, вам не нужно, так как здесь не нужно, так как он предоставляет конструкции для параллелизма (если я правильно запомню), и в вашем случае это фактически приведет к снижению производительности.

Еще раз, удар производительности может быть полностью незначительным для ваших потребностей.

Редактировать предложения Thilo и Shinjin:

Вместо умножения на 45, просто держите оставшуюся часть уравнения, что дает вам значения для 0-7 и сделать массив ваших строк.

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

И вы получили свою проблему, решенную в двух строках.

Одно примечание: модуль не будет работать правильно для отрицательных чисел. Если наш входной заголовок отрицателен, вам нужно сделать его положительным первым.

30
ответ дан 1 December 2019 в 01:10
поделиться

Вы можете добавить 15 градусов вперед, чтобы избежать North_1 и North_2.

0
ответ дан 1 December 2019 в 01:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: