📜 ⬆️ ⬇️

Introduction to the development of cartographic and geolocation mobile applications using QtMobility.location

This post participates in the competition " Smart phones for smart posts "

I have never had to participate in the development of cartographic and geolocation mobile applications, so this competitive topic became interesting to me both in terms of professional growth and in terms of ordinary human curiosity. Naturally, I suspected that QtQuick would greatly facilitate my task of studying a subject, but once again he was pleasantly surprised by the elegant simplicity of solving the problem.


It's about QtMobility.location . By the way, the application depicted in the screenshot contains less than a page of code in QML and not a line in C ++.

')


It’s probably worth starting according to tradition from the minimal “Hello, World !!!” application. However, this “Hello, World !!!” is somewhat different from the usual. This is no longer the squeak of a newly hatched chick in a dark inhospitable console, but rather his little triumphant cry when he flies into a neighboring yard. It looks like this (a screenshot of this application was shown above):
  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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
  19. 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
  20. 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
  21. 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
  22. 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
  23. 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
  24. 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
  25. 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
  26. 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
  27. 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

The main element that interests us here is, of course, the Map element. I will tell about it in more detail. He is responsible for loading and displaying the map. The main work in this element is done by the plugin, described by the Plugin element.

The center property is the coordinates of the center of the displayed map. In order to “jump over” to a new location on the map, it is enough just to change the values ​​of the center property of the Map element. You can move around the map not only hopping, but also smoothly, using the map.pan function (dx, dy) . dx, dy - offset to the left \ right and up \ down relative to the previous position.

zoomLevel is responsible for the map scale. By changing the value of this property, you can zoom in / out. The minimum and maximum values ​​are read from the minimumZoomLevel and maximumZoomLevel properties .

mapType is a type of map. The following types are available:
• Map.StreetMap
• Map.SatelliteMapDay
• Map.SatelliteMapNight
• Map.TerrainMap
• Map.HybridMap
• Map.TransitMap
• Map.GrayStreetMap
• Map.MobileStreetMap
• Map.MobileTerrainMap
• Map.MobileHybridMap
• Map.MobileTransitMap
• Map.MobileGrayStreetMap
To display correctly, the type of card must, of course, be supported by the provider.

In the screenshot above, Map.StreetMap is used .
In the screenshot below - Map.SatelliteMapDay :




As the child entities of the Map element, various elements can be added to the map, such as MapRectangle, MapCircle, MapText, MapImage, MapPolygon, MapPolyline , etc. These items will be displayed automatically in the specified position. They are very convenient to use to set different labels on the map, display routes, areas and everything you might need.
For example, this is how you can display text on a map in the position we need:
  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. }


Or, like this, you can mark the current user coordinates on the map with a yellow circle:
  1. MapCircle {
  2. id: userPosition
  3. color: "yellow"
  4. radius: 10
  5. center: userPositionSource.position.coordinate
  6. }


But in order to mark the coordinates of the user, you must first know them. With QtMobility, this is also done elementarily. And help us in this QML PositionSource Element . Through it, you can get information about things like your current coordinates, altitude and speed.



The following piece of code demonstrates what and how to get out of this 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. }






I was also interested in how to get the global coordinates of an object already displayed on the screen. It turned out - with QtMobility it is also very simple. The map.toCoordinate () function translates the object's screen coordinates into global ones. Touched the object on the screen - got the coordinates:
  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. }




In conclusion, I would like to briefly mention acquaintance with the OVI Maps API . Using the OVI Maps API, you can easily organize in the application a search for a location by its name and a lot of other things. For example, in the screenshot below, the points “A” and ”B” are set and the OVI Maps API gives a route from one to another. Maps in it are managed by javascript. And as you know - the best friend of QML is JavaScript, which can be directly embedded in the code. Thus, a bunch of QML - JavaScript - OVI Maps API seemed to me a very powerful tool for creating cartographic and geolocation mobile applications of any complexity. And QtQuick once again demonstrated all its power and graceful simplicity.

OVI Maps API Playground:

Source: https://habr.com/ru/post/133447/


All Articles