В предыдущей статье я рассматривал API статических карт Google. Рядом с этой темой, буквально «впритык», располагается геокодирование. Что это за зверь? Цитирую:
«Geocoding is the process of converting addresses (like «1600 Amphitheatre Parkway, Mountain View, CA») into geographic coordinates (like latitude 37.423021 and longitude –122.083739), which you can use to place markers or position the map»
А если нормальным языком, то геокодирование — процесс превращения строкового почтового (не путать с электронной почтой :) ) адреса в координаты. А также, обратный процесс.
Описание API лежит на гугле, к сожалению, пока не переведенное, хотя в адресе присутствует код языка.
Итак, приступим.
Прямое геокодирование
Идем по этой ссылке. Результатом оказывается XML документ. Смотрим на него внимательно. Ветки документа содержат информацию о найденных объектах и их координатах. Дело за малым — сформировать URL, закинуть запрос, считать ответ и разобрать XML. «За чем же дело встало?» (жизненная цитата)
Строка запроса состоит из трех параметров:
Скачиваем пример и смотрим в код:
|
Для хранения результатов обработки XML я создал класс.
|
И складировал результаты в TObjectList. Если уж совсем заморачиваться, то «по уму» нужно написать хранилище для результатов, но почему то мне было лень.
Надеюсь, я достаточно подробно прокомментировал код, и нет необходимости его расписывать. В результате, мы имеем список точек с координатами и подробным адресом. Если кому–то понадобится точное разложение по городам, улицам и домам, то не составляет большого труда разобрать подчиненные ветки документа, детализация достаточно подробная.
Со списком точек я поступил следующим образом — вывел в ListView и отобразил на карте. Если кто–нибудь ковырял самостоятельно описание статических карт на сайте гугла, приведенное в предыдущей статье, то там есть возможность вывода нескольких точек на одной карте. Я добавил следующую функцию:
|
Разница с уже имевшейся функцией GetMap во входных параметрах — списке точек для отображения. Вот что получилось:
Почему–то я всегда думал, что улиц Ленина в России больше. И знаю пару неотмеченных городов на карте в которых она есть. Кстати, это отличный тест гугла на наличие карт городов — есть улица/проспект Ленина, Октября, Революции и ещё немного названий — есть и подробная карта. И следствие — Сибирь у гугла не отобразилась, значит городов там нет!
Кстати, а есть ли жизнь за МКАДом? :)
Танцы с бубнами вокруг кодировок
Гугл принимает и отдает данные в формате UTF–8. Этот факт упомянут в описании. К сожалению, не всё так просто. При посылке запроса с указанием языка в URL возвращаемые данные не принимаются в TXMLDocument, русские символы ему, видите ли, не нравятся. Если перевести URL в UTF–8, тогда документ принимается. Но в большинстве случаев часть адресных строк содержат английские названия. Так Дворцовая площадь становится Palace Embankment. Не вполне допустимая ситуация для использования софта пользователями, не знакомыми с языком потенциального противника. При этом, посылая аналогичный запрос из любого браузера, данные приходят по–русски. Приходит мысль, что собачко порылось в HTTP заголовках. Т.к. гугль знает всё (чё, правда? :), решение найдено в добавлении заголовка «Accept–Language: ru» в вызов функции InternetOpenURL. Тогда гугль начинает присылать данные по–русски, НО! в виндовой кодировке. Тут опять больше всех надо становится TXMLDocument–у. В XML указано UTF–8, а реально 1251. Ну, наше дело маленькое, пользуем функцию AnsiToUtf8, и будет нам счастье. Результаты танцев смотрим в функциях GetInetFile и StreamToUtf8Stream.
Обратное геокодирование
Допустим, что у нас есть мобильный объект и нам известны его координаты. Необходимо получить ближайший адрес к точке, по возможности конечно. Адрес «Баренцево море», например, несет слабую смысловую нагрузку, поэтому не для любой точки можно провести процедуру обратного геокодирования с получением почтового адреса.
Обратное геокодирование возможно построением двух типов запросов. В запросе можно указывать координаты в параметре «q» и запрос не отличается от вышеописанного. Но эта функция не документирована. Честный же способ заключается в использовании параметра ll — «latitude, longitude». Пробуем следующую ссылку. Мы видим данные адреса по координатам.
Получение данных выглядит следующим образом:
|
Отобразим полученное дерево на TreeView. Чтобы не перегружать статью, я не буду приводить заполнение дерева, можно посмотреть исходники.
Структура XML документа содержит узлы «Placemark». Узлы содержат информацию о точке по слоям карты. Самый первый узел «Placemark» содержит наиболее подробную информацию об адресе точки (верхний слой). Прикрутим получение адреса к примеру получения картинки карты из предыдущей статьи.
|
В результате в строке состояния окна появится адрес точки, отображаемой на карте, на первой вкладке: