Алгоритм кардинального направления в Java
В этот уик-энд я проведу несколько минут, объединив алгоритм, который возьмет заголовок (в градусах) и вернет String для кардинального направления (я использую его в приложении андроида-компаса, которое я использую). В результате я оказался следующим:
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;
}
Мой вопрос: это лучший способ сделать это? Это, должно быть, было сделано много раз, хотя я еще не проводил поиск примеров в Интернете. Попробовали ли другие люди и нашли более аккуратное решение?
Изменить для ответов Reverand Thilo, 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)) ];
}
Ответы
Ответ 1
В большинстве случаев это прекрасно, хотя чтобы оптимизировать его и (IMO), вы можете найти функцию, которая связывает заголовок ввода с используемым на карте.
Например:
(Я уверен, что это правильно, но вы хотите проверить его)
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...
Итак, теперь ваш алгоритм становится быстрым математическим вычислением, а не повторением через карту. Кроме того, здесь вам не нужно как Hashtable, поскольку он предоставляет конструкции для concurrency (если я правильно помню), и в вашем случае это фактически приведет к снижению производительности.
Снова поражение производительности может быть совершенно незначительным для ваших нужд.
Изменить для предложений Тило и Синьцзинь:
Вместо того, чтобы умножить на 45, просто сохраните остальную часть уравнения, которая дает вам значения для 0-7 и создайте массив ваших строк.
String directions[] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"}
return directions[ (int)Math.round(( ((double)x % 360) / 45)) % 8 ]
и ваша проблема решена в двух строках.
Одно примечание: модуль не будет работать правильно для отрицательных чисел. Если наш заголовок ввода отрицательный, сначала вам нужно сделать его положительным.
Ответ 2
Большинство ответов здесь отключены на 22,5 градуса для их 45-градусных интервалов и, например, карты. 0-45 как N, а не [337.5-360], [0-22.5] до N. Вам нужно компенсировать, прежде чем делать математику, чтобы исправить это.
Здесь используется решение, использующее интервалы 22,5 градуса, например, вы можете видеть направление ветра:
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)";
}
Ответ 3
Возможно, вы можете добавить 15 градусов вперед, чтобы избежать North_1 и North_2.
Ответ 4
Предыдущие примеры неточны, вот более точное решение в 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];
}
Ответ 5
в 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" вам необходимо создать класс.
в javascript:
var _directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];
function getDirection (hea) {
return _directions[Math.floor((hea % 360) / 45)];
};