Про те, що вашому додатку необхідні дані позиціонування, необхідно явно вказати в розділі Capabilities файлу Package.appxmanifest. Після цього Windows 8 запитує підтвердження у користувача при першому запуску програми.
Як правило, дані Geolocator використовуються в поєднанні з картами. У Windows 8 немає вбудованого елемента управління для карт Bing, але ви можете завантажити інструментарій, який дозволить додати цей елемент в додаток. Для цього вам знадобиться реєстраційний ключ, який можна отримати на сайті www.bingmapsportal.com.
Але в наступній програмі я піду іншим шляхом. На екрані буде відображатися карта, що повертається в залежності від орієнтації планшета. Поворот дозволяє поєднати північ карти з фактичним північчю (або тим напрямом, який планшет вважає північним). Замість елемента управління для карт Bing я використовую SOAP-службу карт Bing для завантаження окремих плиток і їх об'єднання в карту. При цьому вам також знадобиться реєстраційний ключ.
Нижче наведено файл XAML. Всі плитки, що утворюють карту, розміщуються на панелі Canvas з ім'ям imageCanvas. Зверніть увагу на перетворення RotateTransform для повороту Canvas щодо центру:
Служба підтримує два типи запитів: GetMapUriAsync і GetImageryMetadataAsync. Запит першого типу дозволяє отримати статичну карту конкретного місця. Проте я вибрав другий тип, який повертає інформацію для завантаження окремих «плиток», з яких потім збирається повна карта.
Всі звернення до веб-службі виконуються виключно в обробнику Loaded. Необхідно зробити два виклики: для отримання метаданих карт для дорожнього і супутникового режиму. Інформація зберігається в двох примірниках локального класу з ім'ям ViewParams. Найважливішою частиною метаданих є шаблон URI для завантаження окремих плиток карти. Клас ViewParams також містить поля для мінімального і максимального рівня збільшення, але я знаю, що рівень збільшення змінюється в діапазоні від 1 до 21. Ви побачите, що в інших частинах коду також передбачається, що верхня межа рівня збільшення дорівнює 21:
Завантаження метаданих двох режимів здійснюється двома асинхронними викликами, які не залежать одне від одного, а отже, можуть виконуватися одночасно. Ця ситуація ідеально підходить для застосування методу Task.WaitAll, що очікує завершення декількох об'єктів Task.
Коли обидва звернення до веб-службі завершаться успіхом, програма запускає класи Geolocator і Inclinometer. Клас Inclinometer використовується виключно для отримання відхилення, за яким здійснюється поворот карти і стрілки, що позначає північ:
Після завершення обробника Loaded у програми з'являються два шаблони URI, які можуть використовуватися для завантаження окремих плиток карти. Плитки, з яких складаються карти Bing, являють собою квадратні растрові зображення зі стороною 256 пікселів. Кожна плитка зв'язується з певною широтою, довготою і рівнем збільшення і містить частину карти світу в поширеною проекції Меркатора.
На рівні збільшення 1 вся Земля (а точніше, частина земної поверхні в області між 85,05 ° північної і південної широти) накривається чотирма плитками.
До числах на плитках ми ще повернемося. Кожна плитка являє собою квадрат зі стороною 256 пікселів, так що на кожен піксель припадає близько 49 миль:
На рівні збільшення 2 вся Земля накривається 16 плитками:
Ці плитки теж являють собою квадрати зі стороною 256 пікселів, так що на екваторі кожен піксель відповідає приблизно 24 миль.
Кожна плитка з рівнем збільшення 1 покриває таку ж область, як чотири плитки з рівнем збільшення 2. Розбиття триває за тим же принципом: з рівнем збільшення 3 карта складається з 64 плиток, з рівнем збільшення 4 - з 256 плиток і так далі аж до рівня 21, на якому (принаймні теоретично) Земля накривається більш ніж 4 трильйонами плиток - 2 мільйони але горизонталі і 2 мільйони по вертикалі, з дозволом до 3 дюймів на піксель на екваторі.
Як розумно організувати зберігання такої кількості плиток? Слід врахувати, що плитка ідентифікується трьома показниками - широтою, довготою і рівнем збільшення, а для максимальної ефективності в наданні даних плиток через веб-службу плитки, накривають одну область, повинні зберігається на серверах поблизу один від одного.
Тут необхідна ретельно продумана схема нумерації. Кожній плитці призначається унікальний квадроключ (quadkey). Шаблони URI, отримані від веб-служби карт Bing, містять «», який заповнюється посиланням на реальну плитку. На двох наведених схемах квадроключі конкретних плиток вказуються в лівому верхньому кутку. Початкові нулі важливі! Кількість цифр в квадроключей дорівнює рівню збільшення, тобто плитки з рівнем збільшення 21 ідентифікуються квадроключамі, що складаються з 21 цифри.
Квадроключ складається тільки з цифр 0,1,2 і 3, тобто квадроключі насправді представляють собою числа, записані в системі числення з основою 4. У двійковій системі числення цифри 0,1,2 і 3 представляються у вигляді 00,01,10 і 11. Перший біт визначає вертикальну, а другий - горизонтальну координату. Таким чином, біти відповідають «сплетіння» довготи і широти.
Як ви вже бачили, кожна плитка з рівнем збільшення 1 відповідає чотирьом пліткам з рівнем збільшення 2; ці плитки можна розглядати в контексті відносин «батько / нащадок». Квадроключ нащадка завжди починається з тих самих цифр, що й квадроключ батька, але до них додається ще одна цифра в залежності від місцезнаходження нащадка щодо батька. Квадроключ батька можна визначити по квадроключу нащадка простим відсіканням останньої цифри.
Щоб використовувати веб-службу карт Bing, необхідно обчислити квадроключ за широтою та довготою. Код наведеного нижче методу GetLongitudeAndLatitude демонструє перший крок - перетворення широти і довготи від Geolocator в відносні значення типу double в діапазоні від 0 до 1, а потім в цілі значення:
Значення BITRES, рівне 29, складається з 21 біта в квадроключе рівня збільшення 21 і 8 бітів розміру плитки; таким чином, ці цілі значення визначають широту і довготу з точністю до найближчого пікселя плитки з максимальним збільшенням. Обчислення integerLongitude тривіально, але integerLatitude обчислюється більш складно, тому що в проекції Меркатора відбувається стиснення широт при видаленні від екватора.
Приклад: центр Центрального парку в Нью-Йорку має довготу -73,965368 і широту 40,783271. Відносні значення double (до декількох розрядів) рівні 0,29454 і 0,37572. 29-розрядні цілі значення (наведені в двійковому вигляді і згруповані по чотири розряду для зручності читання) виглядають так:
Припустимо, нам потрібна широта і довгота на рівні збільшення 12. Для цього слід відокремити старші 12 розрядів цілих значень довготи і широти. (Будьте уважні! Угруповання цифр при цьому змінюється.)
Щоб два довічних числа утворили квадроключ, їх необхідно об'єднати в число в системі числення з основою 4. Зробити це в програмному коді без безпосереднього перебору бітів не вдасться, але для наочності можна просто подвоїти все біти широти і скласти два значення так, як якщо б вони були записані по підставі 4:
Отриманий квадроключ підставляється на місце заповнювач «» в шаблонах URI, отриманих від веб-служби. Побудований таким чином URI ідентифікує квадратне растрове зображення зі стороною 256 пікселів.
Нижче наведено фрагмент RotatingMap, який будує квадроключ по усіченим цілочисельним значенням широти і довготи. Для ясності логіка була розділена: спочатку будується довге ціле число, а потім рядок:
Квадроключ ідентифікує плитку, яка містить потрібну широту і довготу, але місце з точними значеннями широти і довготи знаходиться десь в цьому файлі. Місцезнаходження пікселя в плитці може бути визначено по 8 цифр цілих широти і довготи, наступних за цифрами, необхідними для квадроключа.
Робота добігає кінця. Так як вся сторінка повинна бути закрита квадратними плитками зі стороною 256 пікселів, а поточна позиція знаходиться в центрі екрану десь в межах центральної плитки, обробник SizeChanged визначає, скільки плиток знадобиться, а отже, скільки елементів Image необхідно створити. Ім'я поля sqrtNumTiles означає «квадратний корінь з кількості плиток». Для екрану 1366 x 768 пікселів його значення дорівнюватиме 9. Загальна кількість плиток (і елементів Image) дорівнює квадрату цієї величини, тобто 81:
Справжня робота виконується в методі RefreshDisplay. Він перебирає елементи Image і визначає квадроключ (а отже, і URI) для кожного елемента:
Залишається розглянути код, що відноситься до кнопок в рядку додатка. Кнопки збільшення і зменшення блокуються і знову стають доступними в залежності від мінімального і максимального рівня збільшення для поточного режиму, хоча (як я вже згадував) інші частини програми «знають», що максимальний рівень збільшення дорівнює 21:
Знайомі області карти після повороту виглядають незвично - як, наприклад, острів Манхеттен на наступному знімку:
Але якщо ви стоїте в незнайомому місці з планшетом і намагаєтеся розібратися, де опинилися, обертання карти разом з вашим переміщенням може бути дуже корисним. Можливо, коли-небудь мітки з назвами міст і вулиць теж будуть автоматично повертатися.