У меня есть график, и каждый узел имеет свое местоположение в виде пары (x, y)
, Я хочу сравнить евклидово расстояние двух узлов и назначить новое свойство или тег в соответствии с их расстоянием.
Далее я хочу проверить, находятся ли они близко друг к другу, потому что они будут иметь схожие свойства и поскольку два узла, расположенные далеко друг от друга, имеют гораздо меньшее сходство.
Например: если есть node1 (1, 1)
а также node2(1, 2)
они почти соседи и имеют сильное сходство. Но node3(51, 48)
далеко от node1
а также node2
,
Один из способов — проверить каждый интервал расстояния между двумя узлами:
if(dist == a)
map<pair<node, node>, taga>
if(dist == b)
map<pair<node, node>, tagb>
if(dist == c)
map<pair<node, node>, tagc>
.
.
.
if(dist == z)
map<pair<node, node>, tagz>
Каков наилучший способ поставить эти интервалы? Я думаю, что приведенный выше алгоритм требует много условий, если график большой и распределен по площади.
Теги могут быть весом узлов или ребер, соединяющих их, поэтому ближайшие узлы могут иметь одинаковый вес.
Есть ли эффективный подход?
Если я правильно понимаю ваш вопрос, вы хотите проверить близость между двумя точками (позициями), которые могут или не могут быть далеко друг от друга.
Сначала проверьте эту функцию:
int get_distance(std::pair<int, int> const pos_a, std::pair<int, int> const pos_b)
{
auto const distance_x = pos_a.first >= pos_b.first ? pos_a.first - pos_b.first : pos_b.first - pos_a.first;
auto const distance_y = pos_a.second >= pos_b.second ? pos_a.second - pos_b.second : pos_b.second - pos_a.second;
if (distance_x != 0 && distance_y != 0)
return int(round(sqrt(distance_x * distance_x + distance_y * distance_y)));
if (distance_x == 0)
return distance_y;
return distance_x;
}
Здесь он вычисляет расстояние между двумя точками, вычитая его с наибольшим числом (отсюда два начальных выражения), и используемый оператор является Троичный оператор. (Нажмите на ссылку, если вы не знаете, что это такое)
Третья строка — это оператор if, оценивающий, являются ли оба полученных расстояния ненулевая потому что если они есть, то они находятся на одной линии по вертикали или по горизонтали …
Если оба являются ненулевая числа, затем сумма квадратного корня из квадратов расстояния x и y округляется до ближайшего целого числа, а затем приводится к целому числу (так как тип возвращаемого значения ИНТ)
С другой стороны, если любой из них является нуль число (следовательно, на одной линии), то расстояние Икс или же Y будет возвращено соответственно на основе оси линии (вертикальной или горизонтальной, следовательно, distance_x == 0
а также distance_y == 0
)
Теперь для вашей другой проблемы, а именно Близость, о которой упоминалось выше, можно объявить перечислителем, который хранит значение для такого рода вещей …
Пример:
enum Distance { DISTANCE_VERY_CLOSE = 1, DISTANCE_CLOSE, DISTANCE_RELATIVELY_CLOSE, DISTANCE_RELATIVELY_FAR, DISTANCE_FAR, DISTANCE_VERY_FAR, DISTANCE_EXTREMELY_FAR };
Затем этот перечислитель будет отслеживать расстояние для вас, так что вам просто нужно использовать этот макрос для преобразования целого числа в
Distance
(Перечислитель) …
#define TO_DISTANCE(distance) ((distance) > 7 ? Distance(7) : Distance(distance))
Это простой макрос, который просто приводит целое число к счетчику и приводит цифру 7, если расстояние больше 7 (следовательно,
DISTANCE_EXTREMELY_FAR
). Однако вы можете пойти дальше и добавить больше в перечислитель, если хотите. (Только не забудьте изменить значение 7 на последнееenum
член имеет)
Пример использования вышеуказанного метода:
int main()
{
auto const dist = TO_DISTANCE(get_distance(std::make_pair(20, 20), std::make_pair(30, 30)));
accuracy *= dist; // Multiplying accuracy to distance (Hence, increases)
// Note: The accuracy needs to be at least 1 or more for this to work...
// You can check the "closeness" like this...
if (dist == DISTANCE_FAR)
std::cout << "They are far away from each other" << std::endl;
// Some other code goes here ...
return 0;
}
С уважением,
Ruks.
Других решений пока нет …