Главная

Очистка

Главная
География
Интерфейс
ТЗ
Начало
Очистка
Верификация
Описания
Эксперимент

Карта

Обработка по типам данных




Назад...   Далее...

Следуюший этап будет заключаться в отсеивании и "упаковке" почти структурированных данных. Это, разумеется, "геометрия": координаты узлов (lat/lon) и последовательность их следования в траекториях. Это вовсе не означает, что для этих данных работа по структуризации заканчивается - наоборот, она только начинается! Не забываем, что мы готовим сразу 7 серверных карт, последовательно увеличивая масштаб каждой из них в 8 раз. К тому же, перед нами стоит неявная (и очень нетривиальная) задача верификации этих данных. Но вначале нужно отделить мух от котлет, геометрию от описаний, и вот в описаниях начнётся уже настоящий кошмар!

Тип node

По нашей задумке, сами идентификаторы узлов отныне и будут содержать всю необходимую информацию о своих координатах. Но это уже после окончания обработки, а пока нам понадобятся "справочные" файлы для перевода нынешних ID узлов (именно они сейчас и указаны в данных типа way и relation) в новые идентификаторы. Здесь нас подстерегает опасность потери уникальности идентификатора (уникальность IDs в исходных данных разработчики БД вроде как гарантируют), причём с увеличением масштаба карты риск потери уникальности возрастает катастрофически! Так, если на нашу карту самого мелкого масштаба мы (теоретически) можем напихать чуть не триста триллионов уникальных объектов (если забьём ими под завязку дно морей и океанов, горы и пустыни), то на карту самого крупного масштаба их не поместится и пятидесяти тысяч, как бы мы ни изворачивались, то есть мы от почти нулевой вероятности потери уникальности приходим к практически стопроцентной! Что будем делать? Обеспечивать уникальность, разумеется! Как именно? Разберём подробнейшим образом "по месту", по мере появления конфликтов IDs у разных объектов, а пока поверьте на слово: обеспечим! Не верите? Ладно, даю набросок технологии: во-первых, литеральные объекты (а их подавляющее большинство) просто схлопываются в один, и это нормально: да, при этом координаты ломаной линии на самой грубой карте мы сможем задать лишь с точностью 10-15 километров, но если она описывает контур Африки, то мы и увидим именно Африку. Во-вторых, многие объекты на карты более крупного масштаба просто не переносятся - например, дома или даже мелкие города, реки, озёра. Ну и, наконец, если нам непременно нужно перенести на карту следующего масштаба налезающие друг на друга объекты, у нас всегда есть возможность разбивки их по слоям видимости (магазины, музеи, памятники, парки и т.д.), то есть даже объектов, привязанных к одной и той же точке карты, может быть великое множество. Убедил?

Алгоритм второго этапа обработки:

  1. Первичная (она же финальная) обработка узлов (тип node), то есть перевод координат "широта-долгота" в новый формат:
    • Весь земной шар разрезается на 56 плоских квадратных карт, а внутри каждой карты местоположение уточняется одним символом (как идентификатор дочернего квадрата 8*8).
    • Одновременно координаты объекта округляются до примерно полуметровой точности (на карте самого мелкого масштаба, то есть при длине идентификатора 9 символов).
    • При переводе координат в новый формат автоматически убираются ошибки вида: "узлы с разными ID, но с одинаковыми координатами". Как правило, это ошибки округления (в районе 5-6 знака после запятой), но не только. Также автоматически убираются ошибки вида: "узлы с одинаковым ID, но с разными координатами".
  2. Тип way: Здесь нас подстерегает небольшая неприятность: мы не можем тупо перевести исходные данные в формат ID_way+ID_node, поскольку сам порядок следования узлов в траектории тоже несёт информацию (ещё один привет реляционщикам!), и если мы разобьём траекторию на составные части (для удобства обработки) то собрать её вновь мы уже не сможем никогда. Поэтому нам нужно предварительно сохранить эту информацию, перевести её в данные (добавить в структуру третье поле number - порядковый номер узла в траектории), после чего мы можем обрабатывать эти элементы автономно. И первое что мы должны сделать - заменить старые идентификаторы узлов на новые: если мы это сделаем для всех траекторий (тип way), для всех узлов, входящих в отношения (тип relation) и для всех узлов (тип node), имеющих описания, то переводная таблица IDold+IDnew нам больше не будет нужна, и самая объёмная сейчас составляющая БД сразу уменьшится во много раз.
  3. Тип relation: Обработка почти такая же, как и для данных типа way: отделяем описания и переводим иерархический формат записи в реляционный, сохранив отдельным полем порядок следования дочерних элементов.
  4. Описания: У читателя может возникнуть резонный вопрос: а почему же мы сразу не выделили описания в отдельную группу, а вначали провели разделение по типам данных, а теперь снова их объёдиняем? Причина этого чисто "технологическая": главная задача первого этапа обработки - максимально уменьшить объём базы данных за минимально возможное число проходов с тем, чтобы сократить время обработки для всех последующих итераций за счёт уменьшения, в первую очередь, самых дорогих, файловых операций. Эта задача была успешно выполнена, и теперь отделение описаний объектов произойдёт намного быстрее, чем если бы мы занимались "мышиной вознёй" на первом этапе, перелопачивая гораздо большие объёмы данных.

Что-то я не понял... а что, и стандарта на формат base64 не существует?! Ладно, сделаем свой... будем, как и рекомендовано, использовать цифры и буквы латинского алфавита (большие и малые), а на два оставшихся символа возьмём "-" и "_", только кодировку сделаем так, чтобы коды этих символов шли строго по возрастанию - тогда обычная сортировка данных будет группировать их строго по возрастанию кодируемых этими символами реальных значений координат. Непонятно выразился? Тогда вот весь массив значений, при этом символ "-" соответствует нулю, а "z", соответственно, 63:
-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz

Забавным является наличие в некоторых описаниях тегов coordinate. Да-да, там приведены именно координаты узлов! Да, как раз те самые, которые даны и в основной структуре узла. Да, не всегда они совпадают. Да, в большинстве случаев рассогласование значений находится где-то в районе 5-6 знака после запятой, то есть это обычные ошибки округления. Да, в некоторых случаях (их, разумеется, ничтожное количество) ошибка задания координат более грубая. Мало того: иногда "дополнительные" координаты заданы двумя тегами: lat= и lon=, причём количество тегов, задающих широту не равно их числу, где указывается долгота! Этот пример я привёл для иллюстрации, какой гадюшник представляет собой свалка данных под названием OpenStreetMap. Спрашивается: зачем вы делаете все эти еженедельные и даже ежедневные дампы, если вы не удосуживаетесь годами (!) исправлять даже самые очевидные ошибки? Так что будем делать с "дополнительными" координатами узлов? Да выбросим их к чертям собачьим - только и всего! Ну, хорошо: соберём в отдельную группу идентификаторы тех узлов, у которых координаты заданы "дополнительно" в сопроводительной информации к узлам - может быть, кто-то захочет проинформировать разработчика, чтобы исправили ошибки в своей БД (мне лень).

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

Точка имеет параметры "широта" и "долгота" (в желаемых свойствах предлагается добавить третий параметр - "высота").
Вот уж нафиг! Вы что, собрались задавать рельеф в растровом формате?! Совсем сдурели? Только векторный! Тем более, что все эти изолинии принципиально ничем не отличаются от любых других с точки зрения обслуживающей математики. Кстати, дошло до меня, почему именно треугольники используются для трёхмерной графики: между двумя соседними изолиниями (то бишь ломаными) учень удобно укладываются именно треугольники. Дальше их красишь, как надо (имитируя освещенность, например), и... объём должен бы появиться. Впрочем, раз в базе объёма нет, то и нам он нафиг не нужен. Схема у нас гибкая, и рельеф (если он когда-нибудь вообще появится) спокойно подключается в любой момент как отдельный слой видимости.

А теперь немного поработаем с EAV. Наша задача - отрезать наиболее раздражающий мусор, и структурировать то, что может хоть как-то структурироваться. Обработку ведём, ориентируясь на типы данных, хотя общий принцип одинаковый: выдёргиваем из общей кучи данные под самыми популярными тегами, и отправляем их либо на свалку, либо в какое-то подобие структур. И даже не с тегами, а просто с данными! Кто, собственно, сказал, что метаданные расположены именно в тегах? Как говорится, должны, но не обязаны. Вот и проверим.

Как мы и предполагали, статистически значимыми элементами оказались вовсе не те, которые приведены в описании. Самым распространённым значением тега действительно является highway, с которым пытаются как-то конкурировать building и name - это понятно. Что под тегами source, created_by или note прячется мусор, который к самой карте не имеет никакого отношения и подлежит уничтожению - это тоже понятно (хотя объёмы мусора иногда поражают). Так, запись под тегом note:en с содержимым National-Land Numerical Information (Administrative area) 2007, MLIT Japan встретилась почти полмиллиона (!) раз (и примерно столько же по-японски, с тегом note:ja) - и это только в выборке! Со смысловым наполнением тегов с префиксом addr тоже более-менее понятно. Но скажите-ка мне: что это за жуткое количество префиксов вида NHD, tiger, KSJ2, naptan, TMC, openGeoDB, kms, osak, gnis и другие? Вам это о чём-то говорит? Мне вот кажется, что это рудиментарные ошмётки идентификаторов каких-то старых баз данных, которые были сюда когда-то засыпаны и палкой перемешаны. Вот, например, ешё почти полмиллиона подтверждений этой гипотезе: записи вида source=KSJ2. А вот и доказательство: это есть Japan KSJ2 Import. Впрочем, и без доказательств видно, что KSJ2 встречается, в основном, в описаниях объектов, расположенных в Азии, tiger "специализируется" на Северной Америке и т.д. Кстати, именно под префиксом KSJ2 и располагаются высмеянные чуть выше данные о координатах узлов: KSJ2:coordinate, KSJ2:lat и KSJ2:long, нередко в описании одного и того же узла. Для надёжности, видимо...

Столь же очевидно, что адрес надо приводить к иерархическому формату, а теги source, filename, identifier, reviewed и т.п. отправлять на помойку вместе с содержимым, незначимые префиксы обрезать, а популярные данные (foot=yes, access=private, waterway=stream, highway=secondary, building=house, oneway=no, surface=asphalt, power=tower, etc., etc., etc.) наоборот, переводить из наборов структур EAV в составные теги. Но этим мы займёмся лишь на следующем шаге - сейчас мы только уберём наиболее мозолящий глаза мусор, переведём данные в реляционный формат и удалим дубли.
Назад...   Далее...

28.03.2019 09:48
 
`