Введение в разработку картографических и геолокационных мобильных приложений с применением QtMobility.location

    Этот пост участвует в конкурсе „Умные телефоны за умные посты

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


    Речь пойдет о QtMobility.location. Кстати, изображенное на скриншоте приложение содержит менее страницы кода на QML и ни строчки на C++.




    Начать, наверное, стоит по традиции с минимального «Hello, World!!!» приложения. Однако этот «Hello, World!!!» несколько отличается от привычного. Это уже не писк только что вылупившегося птенца в темной неприветливой консоли, а скорее его маленький победный крик при перелете в соседний двор. Выглядит оно так (скриншот этого приложения был приведен выше):
    1. import QtQuick 1.1
    2. import QtMobility.location 1.2
    3.  
    4. Item {
    5.     id: page
    6.     anchors.fill: parent
    7.     focus: true
    8.  
    9. TitleBar { id: titleBar; appname: "Hello World"; z: 5; width: parent.width; height: 40; opacity: 0.8 }
    10.  
    11. Rectangle {
    12.         id: dataArea
    13.         anchors.top: titleBar.bottom
    14.         anchors.bottom: parent.bottom
    15.         width: parent.width
    16.         color: "#343434"
    17.         Map {
    18.             id: map
    19.             plugin: Plugin {
    20.                 name : "nokia"
    21.             }
    22.             anchors.fill: parent
    23.             size.width: parent.width
    24.             size.height: parent.height
    25.             zoomLevel: 6
    26.             center: Coordinate {latitude: 55; longitude: 73.12}
    27.             mapType: Map.StreetMap
    28.         } // map
    29.     }
    30. } // 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 и т.п. Эти элементы будут отображаться автоматически в указанной позиции. Их очень удобно использовать для установки различных меток на карте, отображения маршрутов, областей и всего, чего только может понадобиться.
    К примеру, вот так можно отобразить текст на карте в нужной нам позиции:
    1. MapText {
    2.                 id: texts
    3.                 coordinate: Coordinate {latitude: 54.914; longitude: 73.313}
    4.                 color: "yellow"
    5.                 text: "Samarka"
    6.                 font.pixelSize: 10
    7. }


    Или, вот так — желтым кружочком можно пометить на карте текущие координаты пользователя:
    1. MapCircle {
    2.     id: userPosition
    3.     color: "yellow"
    4.     radius: 10
    5.     center: userPositionSource.position.coordinate
    6. }


    Но чтобы пометить координаты пользователя, нужно сначала их узнать. С QtMobility это тоже делается элементарно. И поможет нам в этом QML PositionSource Element. Через него вы можете получить информацию о таких вещах, как ваши текущие координаты, высота над уровнем моря и скорость.



    Следующий кусок кода демонстрирует, что и как можно вытащить из этого элемента:
    1. import Qt 4.7
    2. import QtMobility.location 1.2
    3. Rectangle {
    4.     id: page
    5.     width: 350
    6.     height: 350
    7.     PositionSource {
    8.         id: positionSource
    9.         updateInterval: 1000
    10.         active: true
    11.         // nmeaSource: "nmealog.txt"
    12.     }
    13.     Column {
    14.         Text {text: "<==== PositionSource ====>"}
    15.         Text {text: "positioningMethod: " + printableMethod(positionSource.positioningMethod)}
    16.         Text {text: "nmeaSource: "         + positionSource.nmeaSource}
    17.         Text {text: "updateInterval: "     + positionSource.updateInterval}
    18.         Text {text: "active: "     + positionSource.active}
    19.         Text {text: "<==== Position ====>"}
    20.         Text {text: "latitude: "  + positionSource.position.coordinate.latitude}
    21.         Text {text: "longitude: "  + positionSource.position.coordinate.longitude}
    22.         Text {text: "altitude: "  + positionSource.position.coordinate.altitude}
    23.         Text {text: "speed: " + positionSource.position.speed}
    24.         Text {text: "timestamp: " + positionSource.position.timestamp}
    25.         Text {text: "altitudeValid: " + positionSource.position.altitudeValid}
    26.         Text {text: "longitudeValid: " + positionSource.position.longitudeValid}
    27.         Text {text: "latitudeValid: " + positionSource.position.latitudeValid}
    28.         Text {text: "speedValid: "     + positionSource.position.speedValid}
    29.     }
    30.     function printableMethod(method) {
    31.         if (method == PositionSource.SatellitePositioningMethod)
    32.             return "Satellite";
    33.         else if (method == PositionSource.NoPositioningMethod)
    34.             return "Not available"
    35.         else if (method == PositionSource.NonSatellitePositioningMethod)
    36.             return "Non-satellite"
    37.         else if (method == PositionSource.AllPositioningMethods)
    38.             return "All/multiple"
    39.         return "source error";
    40.     }
    41. }






    Еще меня заинтересовало, как получить глобальные координаты какого-либо объекта, уже отображенного на экране. Оказалось — с QtMobility это делается так же очень просто. Функция map.toCoordinate() переводит экранные координаты объекта в глобальные. Коснулись объекта на экране – получили координаты:
    1. onPressed: {
    2.   console.log('latitude = '+ (map.toCoordinate(Qt.point(mouse.x,mouse.y))).latitude);
    3.   console.log('longitude = '+ (map.toCoordinate(Qt.point(mouse.x,mouse.y))).longitude);
    4. }




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

    OVI Maps API Playground:
    Поделиться публикацией

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 10

      +2
      Какие ещё Pluginы существуют, особенно интересует, есть ли что-то для OSM?
      +2
      Спасибо за топик. Должен признаться, вы меня чуть опередили.
      Я пишу о разработке геолокационных сервисов для J2ME.
        +1
        И, кстати, тоже для конкурса.
        +1
        А что насчет получения сроки адреса по координатам и обратного действия? То есть как там с геокодингом?
        Плагин это умеет?
        Это очень важная штука без которой приложение с картой не более чем обычный бумажный атлас.
          +1
          Насколько я понимаю — в данный момент не выходя за пределы QML сделать этого не получится. По крайней мере я не нашел, как. Однако в процессе поиска нашел вот такой вот примерчик для QtQuick 2.0, в котором это всё делается в пределах одного .qml файла.
          +3
          А насколько это сейчас производительно? Помнится, когда был 1.1 нам пришлось отказаться от использования Map и вернуться к C++ карте, которая выводилась на декларативВью.
          Проблема была в том, что начинало все аццки тормозить при добавлении большого количества элементов на карту (например трек гпсный точек так на 2000 уже ощутимо тормозил на Nokia C7). При переносе этого всего на C++ естественно тормоза убрались (там это было вынесено в пейнт евент и по сути просто рисовалось примитивами, а не хранилось объектами, как в Qml).
          Вопрос, как сейчас с производительностью у карт в qml?
            0
            На сколько я знаю все так же как вы и описали, вот даже карточка заполненная, она применима и к Qml. Я тоже экспериментировал с большим количеством объектов и тоже наблюдал тормоза, поэтому сейчас используем C++/Qt Graphics View и Qt Mobility.
              0
              ох, то есть стало еще хуже. Понятно, спасибо
            0
            Вот вопрос у меня. На симуляторе всё работает, на апарате не пашет!
            Nokia 700.
            TARGET.CAPABILITY += NetworkServices ReadDeviceData Location
            сертификат девелопера есть, перед deploymentom приложение подписано.

            При попытке вывести positionSource.position.coordinate.latitude и positionSource.position.coordinate.longitude выводид NaN

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое