Этот пост участвует в конкурсе „Умные телефоны за умные посты“
Никогда ранее не приходилось участвовать в разработке картографических и геолокационных мобильных приложений, поэтому эта конкурсная тема мне стала интересна как в плане профессионального роста, так и в плане обычного человеческого любопытства. Я, естественно, подозревал, что QtQuick значительно облегчит мне задачу изучения сабжа, но он в очередной раз приятно удивил элегантной простотой решения задачи.

Речь пойдет о QtMobility.location. Кстати, изображенное на скриншоте приложение содержит менее страницы кода на QML и ни строчки на C++.
Начать, наверное, стоит по традиции с минимального «Hello, World!!!» приложения. Однако этот «Hello, World!!!» несколько отличается от привычного. Это уже не писк только что вылупившегося птенца в темной неприветливой консоли, а скорее его маленький победный крик при перелете в соседний двор. Выглядит оно так (скриншот этого приложения был приведен выше):
Основной интересующий здесь нас элемент – это, конечно же, элемент Map. Расскажу о нем более подробно. Он отвечает за загрузку и отображение карты. Основная работа в этом элементе совершается плагином, описываемым элементом Plugin.
Свойство center – координаты центра отображаемой карты. Чтобы «перепрыгнуть» в новую локацию на карте — достаточно лишь поменять значения свойства center у элемента Map. Передвигаться по карте можно не только скачкообразно, но и плавно, используя функцию map.pan(dx, dy). dx, dy – смещение влево\вправо и верх\вниз относительно предыдущей позиции.
zoomLevel отвечает за масштаб карты. Меняя значение этого свойства можно уменьшать\увеличивать масштаб. Минимальное и максимальное значения вычитываются из свойств minimumZoomLevel и maximumZoomLevel.
mapType — это тип карты. Доступны следующие виды:
• Map.StreetMap
• Map.SatelliteMapDay
• Map.SatelliteMapNight
• Map.TerrainMap
• Map.HybridMap
• Map.TransitMap
• Map.GrayStreetMap
• Map.MobileStreetMap
• Map.MobileTerrainMap
• Map.MobileHybridMap
• Map.MobileTransitMap
• Map.MobileGrayStreetMap
Для корректного отображения тип карты должен, конечно же, поддерживаться провайдером.
На скриншоте выше использован тип карты Map.StreetMap.
На скриншоте ниже — Map.SatelliteMapDay:

В качестве дочерних сущностей элемента Map на карту могут быть добавлены различные элементы, такие как MapRectangle, MapCircle, MapText, MapImage, MapPolygon, MapPolyline и т.п. Эти элементы будут отображаться автоматически в указанной позиции. Их очень удобно использовать для установки различных меток на карте, отображения маршрутов, областей и всего, чего только может понадобиться.
К примеру, вот так можно отобразить текст на карте в нужной нам позиции:
Или, вот так — желтым кружочком можно пометить на карте текущие координаты пользователя:
Но чтобы пометить координаты пользователя, нужно сначала их узнать. С QtMobility это тоже делается элементарно. И поможет нам в этом QML PositionSource Element. Через него вы можете получить информацию о таких вещах, как ваши текущие координаты, высота над уровнем моря и скорость.

Следующий кусок кода демонстрирует, что и как можно вытащить из этого элемента:

Еще меня заинтересовало, как получить глобальные координаты какого-либо объекта, уже отображенного на экране. Оказалось — с QtMobility это делается так же очень просто. Функция map.toCoordinate() переводит экранные координаты объекта в глобальные. Коснулись объекта на экране – получили координаты:
В заключении хотелось бы вкратце упомянуть о знакомстве с OVI Maps API. Посредством OVI Maps API можно легко организовать в приложении поиск локации по ее названию и много-много всего остального. К примеру, на скриншоте ниже задаются точки “A” и ”B” и OVI Maps API выдает маршрут от одной к другой. Карты в нем управляются посредством JavaScript. А как известно — лучший друг QML – это JavaScript, который можно напрямую встраивать в код. Таким образом, связка QML – JavaScript — OVI Maps API мне показалась очень мощным инструментом для создания картографических и геолокационных мобильных приложений любой сложности. А QtQuick в очередной раз продемонстрировал всю свою мощь и грациозную простоту.
OVI Maps API Playground:

Никогда ранее не приходилось участвовать в разработке картографических и геолокационных мобильных приложений, поэтому эта конкурсная тема мне стала интересна как в плане профессионального роста, так и в плане обычного человеческого любопытства. Я, естественно, подозревал, что QtQuick значительно облегчит мне задачу изучения сабжа, но он в очередной раз приятно удивил элегантной простотой решения задачи.

Речь пойдет о QtMobility.location. Кстати, изображенное на скриншоте приложение содержит менее страницы кода на QML и ни строчки на C++.
Начать, наверное, стоит по традиции с минимального «Hello, World!!!» приложения. Однако этот «Hello, World!!!» несколько отличается от привычного. Это уже не писк только что вылупившегося птенца в темной неприветливой консоли, а скорее его маленький победный крик при перелете в соседний двор. Выглядит оно так (скриншот этого приложения был приведен выше):
- import QtQuick 1.1
- import QtMobility.location 1.2
-
- Item {
- id: page
- anchors.fill: parent
- focus: true
-
- TitleBar { id: titleBar; appname: "Hello World"; z: 5; width: parent.width; height: 40; opacity: 0.8 }
-
- Rectangle {
- id: dataArea
- anchors.top: titleBar.bottom
- anchors.bottom: parent.bottom
- width: parent.width
- color: "#343434"
- Map {
- id: map
- plugin: Plugin {
- name : "nokia"
- }
- anchors.fill: parent
- size.width: parent.width
- size.height: parent.height
- zoomLevel: 6
- center: Coordinate {latitude: 55; longitude: 73.12}
- mapType: Map.StreetMap
- } // map
- }
- } // page
Основной интересующий здесь нас элемент – это, конечно же, элемент Map. Расскажу о нем более подробно. Он отвечает за загрузку и отображение карты. Основная работа в этом элементе совершается плагином, описываемым элементом Plugin.
Свойство center – координаты центра отображаемой карты. Чтобы «перепрыгнуть» в новую локацию на карте — достаточно лишь поменять значения свойства center у элемента Map. Передвигаться по карте можно не только скачкообразно, но и плавно, используя функцию map.pan(dx, dy). dx, dy – смещение влево\вправо и верх\вниз относительно предыдущей позиции.
zoomLevel отвечает за масштаб карты. Меняя значение этого свойства можно уменьшать\увеличивать масштаб. Минимальное и максимальное значения вычитываются из свойств minimumZoomLevel и maximumZoomLevel.
mapType — это тип карты. Доступны следующие виды:
• Map.StreetMap
• Map.SatelliteMapDay
• Map.SatelliteMapNight
• Map.TerrainMap
• Map.HybridMap
• Map.TransitMap
• Map.GrayStreetMap
• Map.MobileStreetMap
• Map.MobileTerrainMap
• Map.MobileHybridMap
• Map.MobileTransitMap
• Map.MobileGrayStreetMap
Для корректного отображения тип карты должен, конечно же, поддерживаться провайдером.
На скриншоте выше использован тип карты Map.StreetMap.
На скриншоте ниже — Map.SatelliteMapDay:

В качестве дочерних сущностей элемента Map на карту могут быть добавлены различные элементы, такие как MapRectangle, MapCircle, MapText, MapImage, MapPolygon, MapPolyline и т.п. Эти элементы будут отображаться автоматически в указанной позиции. Их очень удобно использовать для установки различных меток на карте, отображения маршрутов, областей и всего, чего только может понадобиться.
К примеру, вот так можно отобразить текст на карте в нужной нам позиции:
- MapText {
- id: texts
- coordinate: Coordinate {latitude: 54.914; longitude: 73.313}
- color: "yellow"
- text: "Samarka"
- font.pixelSize: 10
- }
Или, вот так — желтым кружочком можно пометить на карте текущие координаты пользователя:
- MapCircle {
- id: userPosition
- color: "yellow"
- radius: 10
- center: userPositionSource.position.coordinate
- }
Но чтобы пометить координаты пользователя, нужно сначала их узнать. С QtMobility это тоже делается элементарно. И поможет нам в этом QML PositionSource Element. Через него вы можете получить информацию о таких вещах, как ваши текущие координаты, высота над уровнем моря и скорость.

Следующий кусок кода демонстрирует, что и как можно вытащить из этого элемента:
- import Qt 4.7
- import QtMobility.location 1.2
- Rectangle {
- id: page
- width: 350
- height: 350
- PositionSource {
- id: positionSource
- updateInterval: 1000
- active: true
- // nmeaSource: "nmealog.txt"
- }
- Column {
- Text {text: "<==== PositionSource ====>"}
- Text {text: "positioningMethod: " + printableMethod(positionSource.positioningMethod)}
- Text {text: "nmeaSource: " + positionSource.nmeaSource}
- Text {text: "updateInterval: " + positionSource.updateInterval}
- Text {text: "active: " + positionSource.active}
- Text {text: "<==== Position ====>"}
- Text {text: "latitude: " + positionSource.position.coordinate.latitude}
- Text {text: "longitude: " + positionSource.position.coordinate.longitude}
- Text {text: "altitude: " + positionSource.position.coordinate.altitude}
- Text {text: "speed: " + positionSource.position.speed}
- Text {text: "timestamp: " + positionSource.position.timestamp}
- Text {text: "altitudeValid: " + positionSource.position.altitudeValid}
- Text {text: "longitudeValid: " + positionSource.position.longitudeValid}
- Text {text: "latitudeValid: " + positionSource.position.latitudeValid}
- Text {text: "speedValid: " + positionSource.position.speedValid}
- }
- function printableMethod(method) {
- if (method == PositionSource.SatellitePositioningMethod)
- return "Satellite";
- else if (method == PositionSource.NoPositioningMethod)
- return "Not available"
- else if (method == PositionSource.NonSatellitePositioningMethod)
- return "Non-satellite"
- else if (method == PositionSource.AllPositioningMethods)
- return "All/multiple"
- return "source error";
- }
- }

Еще меня заинтересовало, как получить глобальные координаты какого-либо объекта, уже отображенного на экране. Оказалось — с QtMobility это делается так же очень просто. Функция map.toCoordinate() переводит экранные координаты объекта в глобальные. Коснулись объекта на экране – получили координаты:
- onPressed: {
- console.log('latitude = '+ (map.toCoordinate(Qt.point(mouse.x,mouse.y))).latitude);
- console.log('longitude = '+ (map.toCoordinate(Qt.point(mouse.x,mouse.y))).longitude);
- }
В заключении хотелось бы вкратце упомянуть о знакомстве с OVI Maps API. Посредством OVI Maps API можно легко организовать в приложении поиск локации по ее названию и много-много всего остального. К примеру, на скриншоте ниже задаются точки “A” и ”B” и OVI Maps API выдает маршрут от одной к другой. Карты в нем управляются посредством JavaScript. А как известно — лучший друг QML – это JavaScript, который можно напрямую встраивать в код. Таким образом, связка QML – JavaScript — OVI Maps API мне показалась очень мощным инструментом для создания картографических и геолокационных мобильных приложений любой сложности. А QtQuick в очередной раз продемонстрировал всю свою мощь и грациозную простоту.
OVI Maps API Playground:
