Вычислив направление по компасу


У меня есть заголовок, который представляет собой целое число и от него я хотел бы выяснить направление по компасу (север, северо-восток,...) и возвращает соответствующий значок. Я чувствую, что я, вероятно, уже в самое чистое решение, но я бы очень хотела оказаться неправой.

public GetHeadingImage(string iconName, int heading){
        if (IsNorthHeading(heading))
            return iconName  + "n" + ICON_FILE_EXTENTION;
        if (IsNorthEastHeading(heading))
            return iconName + "ne" + ICON_FILE_EXTENTION;
        if (IsEastHeading(heading))
            return iconName + "e" + ICON_FILE_EXTENTION;
        /*A bunch more lines*/
}
private bool IsNorthHeading(int heading)
{
    return heading < 23 || heading > 337;
}
/* A bunch more extracted test methods*/


7614
13
c#
задан 14 марта 2011 в 08:03 Источник Поделиться
Комментарии
6 ответов

Простое решение-это хорошее решение:

public GetHeadingImage(string iconName, int heading){
var directions = new string[] {
"n", "ne", "e", "se", "s", "sw", "w", "nw", "n"
};

var index = (heading + 23) / 45;
return iconName + directions[index] + ICON_FILE_EXTENSION;
}

26
ответ дан 15 марта 2011 в 02:03 Источник Поделиться

Небольшое предложение: GetHeadingImage() имеет много повторяющегося кода.

Почему не что-то вроде:

public GetHeadingImage(string iconName, int heading){
return iconName + GetHeadingName(heading) + ICON_FILE_EXTENTION;
}

Тогда вы могли бы иметь заголовок, логика просто внутри GetHeadingName().

7
ответ дан 14 марта 2011 в 08:03 Источник Поделиться

Две вещи: 1) экстракт GetCompasDirection как отдельный метод, который возвращает перечисление 2) создать коллекцию углы и соответствующие заголовки, чтобы удалить большое это...разделу методы:

public enum CompasDirection
{
North,
NorthEast,
// other directions
}

public CompasDirection GetCompasDirection(int heading)
{
// directions in clock-wise order:
var directionUpperLimitAngles = new [] {
Tuple.Create(CompasDirection.North, 22),
Tuple.Create(CompasDirection.NorthEast, 67),
Tuple.Create(CompasDirection.East, 112),
// other directions,
Tuple.Create(CompasDirection.North, 360), // north again
};

return directionUpperLimitAngles.Last(d => d.Item2 <= heading).Item1;
}

public string GetHeadingImage(string imageName, int heading)
{
var directionToIconSuffixMapping = new Dictionary<CompasDirection, string> {
{ CompasDirection.North, "n"},
{ CompasDirection.NorthEast, "ne"},
// other directions
};
var direction = GetCompasDirection(heading);
return iconName + directionToIconSuffixMapping[direction] + ICON_FILE_EXTENTION;
}

Вот некоторые детали можно упростить (например, вы можете убрать второй словарь и просто назвать свой значок файлы соответственно членам перечисление).

Данный подход с направлением-заголовок таблицы, если я правильно помню, я взял из Макконнелл-это код завершения

Обновление: заменил внутренний отдельный класс с кортежами

3
ответ дан 14 марта 2011 в 08:03 Источник Поделиться

Другая альтернатива:

public enum Direction
{
North = 0,
NorthEast = 1,
East = 2,
SouthEast = 3,
South = 4,
SouthWest = 5,
West = 6,
NorthWest = 7
}

public static class DirectionExtensions
{
private static readonly Dictionary<Direction, string>
mapping = new Dictionary<Direction, string>
{
{ Direction.North, "n" },
{ Direction.NorthEast, "ne" },
{ Direction.East, "e" },
{ Direction.SouthEast, "se" },
{ Direction.South, "s" },
{ Direction.SouthWest, "sw" },
{ Direction.West, "w" },
{ Direction.NorthWest, "nw" }
};

public static bool IncludesHeading(this Direction direction, int heading)
{
var adjusted = (heading + 22) % 360;
var adjMin = (int) direction * 45;
var adjMax = adjMin + 44;
return (adjusted >= adjMin && adjusted <= adjMax);
}

public static string GetSuffix(this Direction direction)
{
return mapping[direction];
}
}

Оставляет свой способ чтения такой:

public string GetHeadingImage(string imageName, int heading)
{
Direction[] directions = ((Direction[]) Enum.GetValues(typeof(Direction)));
var match = directions.First(d => d.IncludesHeading(heading));
return imageName + match.GetSuffix() + ICON_FILE_EXTENTION;
}

[Редактировать: принимая, что на один шаг дальше]

Заменить расширение IncludesHeading с

public static IntDirectionExtensions
{
public static Direction GetDirection(this int heading)
{
var adjusted = (heading + 22) % 360;
var sector = adjusted / 45;
return (Direction)sector;
}
}

И теперь вы можете упростить ваш метод

public string GetHeadingImage(string imageName, int heading)
{
return imageName + heading.GetDirection().GetSuffix() + ICON_FILE_EXTENTION;
}

[Правка 2: Еще одна идея]

Другая вещь, которую вы могли бы сделать, это сопоставить суффикс через отражения, который я думаю, выглядит лучше, но это наверное менее эффективно

public enum Direction
{
[IconSuffix("n")] North = 0,
[IconSuffix("ne")] NorthEast = 1,
[IconSuffix("e")] East = 2,
[IconSuffix("se")] SouthEast = 3,
[IconSuffix("s")] South = 4,
[IconSuffix("sw")] SouthWest = 5,
[IconSuffix("w")] West = 6,
[IconSuffix("nw")] NorthWest = 7
}

public class IconSuffixAttribute : Attribute
{
public string Suffix { get; private set; }
public IconSuffixAttribute(string suffix)
{
Suffix = suffix;
}
}

Заменив расширение GetSuffix (и ныне не существующей словарь сопоставления) с

public static string GetSuffix(this Direction direction)
{
var suffix = from m in typeof(Direction).GetMember(direction.ToString())
from a in m.GetCustomAttributes(typeof(IconSuffixAttribute), false)
select ((IconSuffixAttribute) a).Suffix;
return suffix.First();
}

Все остальное остается таким же.

2
ответ дан 15 марта 2011 в 01:03 Источник Поделиться

Вы могли бы упростить решение путем объединения Севера и юга письма с востока/запада письмо и таким образом избежать необходимости IsNorthEastHeading и тому подобное.

string northsouth = (heading < 23 || heading > 337) ? "n" :
(heading > 157 && heading < 203) ? "s" :
"";
string eastwest = ...
return iconName + northsouth + eastwest + ICON_FILE_EXTENTION;

Стоит ли добавлять все эти дополнительные методы или введения перечисления? Лично я предпочитаю этот метод три линии все большего предлагаемых решений.

2
ответ дан 9 августа 2012 в 06:08 Источник Поделиться

Именования (несовершеннолетних): что-то, возможно, более конкретный домен за границы сектора ("влево"? и "правильно"? относительные углы) может быть вместо того, чтобы называться радиальными. Каждый радиальные, по крайней мере, [авиационной] навигация называется '#именованные числа радиальных# радиальная', такие как '025 радиально, или обычно просто по номеру, 'в 025' (читается как ноль два пять). Возможно, это поможет свести к минимуму магических чисел, объявив свои границы как им радиальные константы.

Чтобы идти дальше, поскольку вы деления компаса в равных частях, или разделы, можно создать постоянные/неизменяемые объекты-значения, которые описывают эти разделы. 'CardinalDirection' (Н Е С Ш) с государственными добытчиками левой лучевой и левой лучевых является пересмотренный навскидку предложение. Ординалы являются следующие направления подразделений (СВ ЮВ Юз СЗ).

Надеюсь, что это помогает уточнить модель лучше.

1
ответ дан 15 марта 2011 в 03:03 Источник Поделиться