Инженерски журнал

Как Mapsake е построил своят офлайн Travel Gazetteer

Преобразуването на координатата на снимка в държава, регион, град и аеродром изисква повече от квадратна връзка с най-близкото място. Ето как Mapsake комбинира отворени данни за места, геометрия на границите, детерминистични правила и локално индексиране.

От 12 минута за четене.
Mapsake Atlas показва подробна карта на света, която се състои от пакетираните географски граници

Координата все още не е място.

Снимка от пътешествие може да съдържа географска ширина и дължина с впечатляваща прецизност. Тези два числа все пак не казват дали камерата е била в Япония, в префектура Кьото, в град Кьото или в международния аеропорт Кансай по пътя за дома. Mapsake изисква тази иерархия преди точка да може да стане полезна записка за пътуване.

Компонентът, който отговаря на тези въпроси, е газетер: структуриран каталог на имена на географски места. Mapsake включва своя газетер в приложението, заедно с границите, използвани за чертане и тестване на държави и първо ниво региони. Търсене, ръчно маркиране, импорт на снимки, истории за места, статистика за Паспорт, постижения и дори няколко прегледа на приятели всички зависят от него.

Това би било по-лесно да се изпрати всяка координата към веб-геокодер. То би направило също така по-бавна импорт на голяма снимка, зависеща от мрежата, по-трудно повторяема и по-малко приватна. Офлайн-рахосто изискваше повече инженерство на старта, но то даде на Mapsake стабилна географска лексика, която работи по същия начин на самолет, в къщата и години след промени в изходните данни.

Това е историята за това как беше изграден този слой, къде точките и линиите не съвпадат и защо „най-близкият град“ е само началото на правилен отговор.

Четири отворени данни, четири различни работи

Няма едно източник, в който да се съдържа всичко, което Mapsake е нужно, затова пътеводителят събира четири вида отворени данни:

  • GeoNames предоставя държави, първо ниво административни региони, населени места, стабилни идентификатори, алтернативни имена, координати и население.
  • OurAirports предоставя аеродроми, кодове IATA и ICAO, имена, общини и координати.
  • Природна Земя предоставя държава и admin-1 геометрия на границите, както и полезни точки за картографски етикети.
  • Малък слой, притежаван от Mapsake, записва решения за продукта, като например поддържани режими за брой държави, псевдоними и корекции, които не могат да бъдат изведени безопасно от обобщен източник.

Всяка източник е добър в нещо различно. GeoNames знае, че град принадлежи на регион и страна, но координатата на град е точка, а не граница. Natural Earth знае къде е начертан полигон, но идентификаторите на функциите не винаги съвпадат добре с GeoNames. OurAirports знае, че KLAX и LAX са същия аеродром, но не е иерархия на всички места около аеродрома.

Скриптовете за създаване свалят и кешират файловете от горната част, ги нормализират, проверяват връзките и извеждат два комитирани артефакта: само за четене SQLite база данни и упростен GeoJSON геометрия. Приложението изпраща тези резултати. То не сваля база данни на света при първото стартиране или зависи от източниците да са онлайн по време на пътуване.

Публикуването на генерирани артефакти също прави изхода върху изхода. Изпратеното изпълнение има известна географска световна. Повдигането на източниците е намеса в кода, която може да се тества и провери, а не е незабележима промяна на страната, която променя картата на някого нощта.

Преднамерено скучна база данни SQLite.

Първият газетер съдържаше 252 държави, 3,861 региони, 33,744 градове и 4,564 аеродрома в около 14 MB. Той използваше библиотеката SQLite, която вече беше налична в операционната система и малък локален оберт, вместо да добавя по-голяма рамка за база данни.

Схемата е намерена директно. Континентите съдържат страни. Страните съдържат региони. Регионите съдържат градове. Аеродромите носят кодове на страни и координати. Стабилни идентификатори на източници стават идентификатори, които се съхраняват с марка Mapsake: ISO alpha-2 за страна, код на административен код от GeoNames за регион, ID от GeoNames за град и код IATA за аеродром.

Mapsake също преобразува и разчитаемото име и родословие във всяка запазена бележка. Тази дублиране е полезна. Личният пътешествен запис трябва да остане четлив, ако по-късно газетиерът промени името на място, изтрие записа или не е наличен при износяване. Идентификаторът поддържа съвпадение; снимката запазва потребителските данни самостоятелно.

SQLite е добър за този тип работа, защото базата данни се генерира веднъж и се извлича много пъти. Поддържа индекси, транзакции по време на създаването и търсене на текст без допълнителен процес. Приложението отваря пакетния файл само за четене, така че няма риски от миграция на референтните данни и няма възможност да се повреди при прекъсната запис.

Търсенето е повече от просто съдържание(text)

Ръчното маркиране започва с едно поле за търсене, което покрива континенти, държави, региони, градове и аеродроми. Търсенето на „san“ трябва да намери значимите градове преди редки записи; „LAX“ трябва да намери аеродрома; и име, въведено без диакритични знакове, трябва да работи все още.

Създаването създава таблица FTS5 с показване на имена, избрани алтернативни имена, кодове, произход, координати, вид и стойност за важност. Unicode tokenizer премахва диакритични знаци за съвпадение. При въвеждане на заявка, Mapsake премахва разлики в големината и диакритичните знаци, премахва символи, които могат да се превърнат в текстова синтаксиса, добавя предварително съвпадение към всеки токен и ранжира точните имена пред предварителните и общите съвпадения.

Важността разбиват останалите връзки. Континентите и страните не трябва да изчезнат под съществено име на селота. Населението на градовете дава разумен тежище на големи места. Големите аеродроми се класират по-високо от малките, когато текстовият съвпадение е иначе съпоставим.

Възможните имена са намерени с цел ограничаване. GeoNames може да предостави много дълъг многоезичен списък за популярно място. Копирането на всяко написане в индекса на устройството ще добави шум и големина. Строителът съхранява ограничено, дедуплицирано множество от полезни варианти и запазва оригиналното име за показване отделно от неговата обработена форма за търсене.

Резултатите от търсенето връщат същия GazetteerPlace модел, използван при иерархичното прегледване. Потребителят може да търси директно или да преглежда континенти, страни, региони и градове без да създава два географски системи, които може да се разминават.

Линиите отговарят на различен въпрос от точките

Най-ранният разрешител на снимки избира най-близкия град и наследява държавата и региона на този град. В гъстите райони това често изглежда перфектно. Близо до границата може да бъде грешно по начин, който е трудно да се забележи.

Представете си снимка, която е била направена точно вътре в Montana, когато най-близкото населено място в базата данни е от другата страна на линията в Норт Дакота. Изчислението за най-близкия град работи правилно, но резултатът не е административното място, където е била направена снимката. Същата проблема се появява на международни граници, близо до енклави и през водата, където редката космическа линия няма близко населено място.

Държавна геометрия отговаря за съдържание вместо за близост. Пътуване декодира природната земя на страната и admin-1 полигони, проверява дали кръговете съдържат координатата и използва този резултат, за да защити определянето на страната и региона. След това може да търси най-близкия град, ограничаван до страната или региона на полигон.

Това създава полезно разделяне на трудовете:

  1. Многоъгълникът за включване определя административната зона.
  2. Газетиерската иерархия предлага стабилни идентификатори и имена.
  3. Ограничено търсене на най-близкия град осигурява полезна локалност, без да преминава границата, която току-що е била установена.
  4. Проверка на близък летище добавя само летище във внимателно ограничено разстояние.

Нищо от данните за линията или директорията на мястото не е достатъчно самостоятелно. Вместе те превръщат координатата в защитима верига

Проверката на admin-1 разкри системни несъответствия

Полигоните на страните и регионите са дошли от различни слоеве на Natural Earth, и идентификаторите на слоя региони не съвпадаха винаги с GeoNames. Някои грешки бяха очевидни, докато други произвеждаха правдоподобни, но грешни запълнения.

Един ранен преобразувателен калкулус определил геометрията на Quebec за Нова Шотландия. Други функции бяха недоста с код, пренесени кодове от съседна система или представени административни единици по-различно от газетерията. Визуално погледнатата световна карта не можеше да намери всички тези грешки надеждно.

Заместващите състояния обработват градовете като оракул. За всяка кандидатна полигон, той задава коя регионна газета на региона, която всъщност се намира вътре в него. Съществуващите кодове на Natural Earth се валидират, а не се приемат на вера. Фичерите, които не преминават валидацията, могат да бъдат преместени пространствено, раздели или изключени. Генерираното изходно съдържание използва точните идентификатори на региона, които са вече налични в SQLite.

Това е практически форма на кръстен тест на набори данни. Полигон, който твърди, че е регион, трябва да съдържа убедителен пример от градове, които твърдят същия регион. Когато двете източника не съставят съгласие, изграждането произвежда доказателства вместо да избира тихо който и да е стойност, която е заредена първо.

Същата проверка откри специални случаи, като населени зависимости, свързани към геометрията на родния страна. Mapsake поправя малък брой от тези случаи, така че снимката да може да се отрази в същата страна, която разбира газетерът и настройките за броя на страните.

По-ясни линии без изпращане на изходната мащабна световна карта

Първият Atlas използваше 1:110 милиона странен слой от Natural Earth. Беше компактен и бърз, но ръбовете станаха видимо груби, когато Mapsake добави по-близки карти, истории за места и регионално разглеждане.

Мапата по-късно се премести в 1:10 милионни слой. Този източник е много по-подробен, така че пакетирането и рендерингът му без промени биха увеличили запазенето, разкодирането, конструирането на слой и работата по прерисуване. Потокът за събиране опростява всеки кръг с Douglas-Peucker при приблизително 0.004-градусна толеранция, след което закръгля координатите до стабилна прецизност.

Полученият файл на държавата е около 6.5 MB. Той запазва полезни подробности за ръба на океана на нивото на зума, което Mapsake показва, докато премахва върховете, които биха паднали на ефективно същите пиксели. Admin-1 геометрията минава през сходен път на валидация и опростяване.

Упрощаването има ограничение за точност: по-малък полигон трябва да отговаря все още на същите решения за реални координати на снимки. Позният benchmark fixtures нарочно разполагат точки около границите и сравняват оптимизираното тестване с фиксирано референчно. По-бързи линии са полезни само когато отговарят все още на същия въпрос за включване.

Разширявайки от 34,000 до 234,000 градове

Първата база данни използваше градове от GeoNames с население над 15,000. Това поддържа пакета компактен, но оставяше селското пътуване, малки острови, пътни градове и много домашни адреси с ненужно отдалечено етикет.

Mapsake по-късно е приета GeoNames градове500, обхващайки населени места с приблизително 500 жители, както и административни центрове. Таблицата с градове се увеличи приблизително седем пъти, до около 234,000 записа, а пакетираната база данни се увеличи от приблизително 14 MB до приблизително 69 MB.

Тази търговия се направи след премахването на App Clip. Платформата на Clip беше най-силната причина да ограничава базата данни. Веднъж когато основното приложение беше единственото потребителско, по-добърото покритие беше по-ценен от запазването на изкуствената граница на малки градове.

Пълният текстов индекс остава изборен за алтернативни имена на малки места, а браузингът на региони все още ограничава какво извежда едновременно. Датата може да е широка без да изисква всяка екран да материализира целия таблица.

Покритие е най-важното място, където мрежевата геокодерка би била най-ненадеждна. Малка общност в отдалечена поездка не трябва да бъде маркирана като град часове оттам само защото компактната наблюдателна система я пропусна.

Най-близкия град става общ проблем при споделяне

Първоначалната заявка за най-близък град разширяваше правоъгълна област по географска ширина и дължина, караше SQLite да изчислява претеглено разстояние за всеки кандидат, създаваше временно сортиране и връщаше най-близкия ред. Тя беше лесна за разбиране и достатъчно точна, но библиотека с 82,000 снимки превръщаше малкия разход за всяка заявка в секунди повтаряща се работа при импортиране, спомени, извеждане на картата и Constellations.

Първото подобряване добави узърт 0.4-градусен преглед пред по-широки резервни опции. Плотни локации обикновено намериха град от значително по-малък кандидатен набор. Мемоизацията и запазената географска клетка кеш също спряха близките снимки да повтарят идентична работа.

По-голямото подобряване зарежда числени координати на градовете 234,000 в индекс, сортиран по широта в паметта. Двоично търсене намира сечението вътре в текущия широтен прозорец, ограничена цикъл проверява долготата и теглението на разстоянието, и само победителят ред се извлича от SQLite. Малък кеш от записи поддържа повтарящите се победители на ниско ниво.

Поведението на разширяване не се промени. Оптимизираната функция все още избира най-близкото град в първия непразен прозорец за търсене, включително детерминистичен разбив на равенства. Само копие от стария път SQL за сравнение проверява стотици координати с тежки граници за точна идентичност.

На симулатора, среден най-близкия град брой падна от 2.11 секунди до 5.2 милисекунди. Реален iPhone изпълнение падна от 3.06 секунди до 6.35 милисекунди. Тези печалби достигнаха няколко функции, защото gazetteer е общ инфраструктурен ресурс, а не частен имплементационен детайл на екрана за импортиране.

Намерен проблем с точността на еднократната полигон

Гаранцията за еквивалентност на производителност разкри грешка, която съществувала преди оптимизацията. Някои admin-1 полигони се пресичат по дизайна, особено първокласни региони вътре в обвивка. Берлин и Бранденбург, Сеул и Геонги, и Киев и неговия облак са примери.

Старият тест за удар се приемаше която съвпадаща полигон се появяваше първо в Swift-дикт. Поредицата на итерацията в диктът се променя между процеси, така че същата координата може да придобие различна област след рестартиране на приложението.

Mapsake сега подрежда сега пресичащи се кандидати според площта на многоъгълника и дава победа на най-малкия, най-специфичен елемент. Референтната реализация следва същия принцип. 82,000-фото фиксирано в криокамера трябва да произвежда нула разлика между студен и топъл път до оптимизация на геометрията.

Този бъг е добър напомняне, че „вътре в полигон“ не е винаги въпрос с „да/не“. Географските данни съдържат енклави, вложени столици, пресичане на антимеридиан, мултиполигони, дупки, спорни граници и източници. Детерминистичната политика е толкова важна, колкото и алгоритъмът за проверка на точка в полигон.

Offline е функция за поверителност и продуктова функция

Импортът на снимки на Mapsake може да разреши голяма библиотека без да изпраща координатите си към трети страни геокодиращи услуги. Това защитава чувствителните пътувания и домашни местоположения, премахва цените за всяко изискване, избягва ограниченията и прави напредъка предсказуем.

Това прави редактирането кохерентно. Ръчното търсене, импортиране на снимки, карти на паспорт, постижения, снимки на приятели, съвпадение на печати и истории за места говорят на едно и също език, защото използват еднакви стабилни идентификатори на места. Летище, импортирано от лог на полето, може да се дедуплицира със същото летище, открито близо до снимка. Град, намерен чрез търсене, може да съвпада с града, използван от Then & Now.

Пакетът не се счита за перфектен или постоянен. Атрибуциите към източниците са видими в приложението. Скриптовете за създаване са запазени до кода. Известните корекции са изрични. Фиксърите за сравнение защитават поведението в трудни координати. Повтарянето на географската световна база данни е събитие за изданието с проверяеми последствия.

Какво бих запазил, ако го бях изградил отново

Най-дълготрайвите избори не бяха индивидуални алгоритми. Те бяха границите между отговорности:

  • Използвайте точки за имена, стабилни идентичности, търсене и иерархия.
  • Използвайте линии и полигонали за ограничаване.
  • Генерирайте само за четене продукт артефакт вместо да разбирате четири външни формата на телефона.
  • Запазете четима снимка с потребителски данни, като запазите идентификатора на източника за съвпадение.
  • Уверете се, че общият офлайн път е детерминиран преди да го направите бързо.
  • Запазете бавна референтна имплементация достатъчно дълго време, за да докажете еквивалентността на оптимизираното изходно състояние.

Gazetteerът започна като ранна функция за търсене. Той стана една от най-важните системи на Mapsake, защото почти всяка по-развита функция накрая трябва да отговори на същия прост въпрос: какво е това място?

Получаването на правилния отговор означава да приемеш, че географията не е една база данни или едно умно запитване. Това е внимателно споразумение между имена, точки, линии, продуктни правила и пътувания, които човек очаква да разпознае.

Иконата на приложението Mapsake

Самостоятелен разработчик на Mapsake, писан от продукта, картата, приватността и работата по Apple-платформата зад приложението.

Създайте вашия атлас

Начнете със историята си от пътуванията, която вече имате

Mapsake е безплатна, изисква без Mapsake акаунт за основна употреба и запазва поддържаните съпоставки на снимки на устройството.

Получете Mapsake безплатно