воскресенье, 13 мая 2012 г.

Определение направление радиус-вектора от одной точки к другой точки

Допустим, у нас есть две точки, например, центр города и отель.

Нам нужно определить, в каком направлении нужно двигаться, чтобы при движении из центра города попасть в отель. Координаты центра города и отеля нам известны.
Для решения задачи:
  1. Ставим точку центра города на бумажке.
  2. Строим через эту точку вертикальную и горизонтальную линии (оси x и y координат)
  3. Строим конечную точку (отель)
  4. Определяем в какой зоне координат находится конечная точка (в --, ++, -+, +-)
  5. Далее определяем угол между осью x и y
  6. Смотрим чему равен угол, < 45 - 45/2, > 45 + 45/2 или находится между
Тем самым мы поймем в какой зоне находится наша точка - по северному, западному, южному, восточному направлению или северно-западному, северо-восточному, юго-западному, юго-восточному ли находится отель.

Код на языке python:

import math


def get_direction_name((lng_city, lat_city), (lng_hotel, lat_hotel)):
    direction = get_direction((lng_city, lat_city), (lng_hotel, lat_hotel))
    name = dict(DIRECTIONS)[direction]
    return name


def get_direction((lng_city, lat_city), (lng_hotel, lat_hotel)):

    diff_lat = lat_hotel - lat_city
    diff_lng = lng_hotel - lng_city

    if math.fabs(diff_lng) > 180:
        diff_lng -= 360*diff_lng/math.fabs(diff_lng)


    is_mm = (diff_lat < 0) and (diff_lng < 0) and 1 or 0
    is_pp = (diff_lat > 0) and (diff_lng > 0) and 1 or 0
    is_mp = (diff_lat > 0) and (diff_lng < 0) and 1 or 0
    is_pm = (diff_lat < 0) and (diff_lng > 0) and 1 or 0

    if diff_lng:
        arg = math.fabs(diff_lat/diff_lng)
        degree = math.atan(arg)*180/math.pi
    else:
        degree = 90

    on_diagonal = 45 - 45.0/2 < degree < 45 + 45.0/2 and 1 or 0
    below_diagonal = degree < 45 - 45.0/2 and 1 or 0
    above_diagonal = degree > 45 + 45.0/2 and 1 or 0

    print is_pp, is_mm, is_pm, is_mp, on_diagonal, below_diagonal, above_diagonal

    direction_key = '{0}-{1}-{2}-{3}-{4}-{5}-{6}'.format(
        is_pp, is_mm, is_pm, is_mp, on_diagonal, below_diagonal, above_diagonal,
    )
    direction = _direction_map[direction_key]
    return direction

NORTH_EAST = 'north-east'
NORTH_WEST = 'north-west'
SOUTH_EAST = 'south-east'
SOUTH_WEST = 'south-west'
NORTH = 'north'
SOUTH = 'south'
EAST = 'east'
WEST = 'west'

DIRECTIONS = [
   (NORTH_EAST, _(u'северо-восток')),
   (NORTH_WEST, _(u'северо-запад')),
   (SOUTH_EAST, _(u'юго-восток')),
   (SOUTH_WEST, _(u'юго-запад')),
   (NORTH, _(u'север')),
   (SOUTH, _(u'юг')),
   (EAST, _(u'восток')),
   (WEST, _(u'запад')),
]

# Key: is_pp-is_mm-is_pm-is_mp-on_diagonal-below_diagonal-above_diagonal
_direction_map = {
    '1-0-0-0-1-0-0': NORTH_EAST,
    '1-0-0-0-0-1-0': EAST,
    '1-0-0-0-0-0-1': NORTH,
    '0-1-0-0-1-0-0': SOUTH_WEST,
    '0-1-0-0-0-1-0': WEST,
    '0-1-0-0-0-0-1': SOUTH,
    '0-0-1-0-1-0-0': SOUTH_EAST,
    '0-0-1-0-0-1-0': EAST,
    '0-0-1-0-0-0-1': SOUTH,
    '0-0-0-1-1-0-0': NORTH_WEST,
    '0-0-0-1-0-1-0': WEST,
    '0-0-0-1-0-0-1': NORTH,
}

Комментариев нет:

Отправить комментарий