Map Coverage MultiPoint Interactive¶
In this guide you will learn how to check map coverage for a single lon,lat coordinate point, or a list of lon,lat coordinate points, interactively selected on the map by the user.
To see an example using programmatically defined coordinate points, see the l MapCoverageMultiPoint example.
Check if map tiles are on the device¶
First, get an API key token, see the Getting Started guide.
Qt should be installed to continue.The Maps SDK for Qt should be installed, see the Setup Maps SDK for Qt guide.
Overview¶
MapCoverageMultiPointInteractive
demonstrates how easy it is
to use MapView
to display an interactive map, and add markers
interactively by pressing and holding on the map until a list of
nearby points of interest appears, and then either select one, or
click outside the popup list to cancel. If a POI is selected,
a marker appears at its coordinates, which is displayed as an icon
on the map. The icon is a circle with transparency, so the map
shows through it.
Then the map coverage is checked for these coordinates, and the
results are displayed on screen.
Also, the markers can be used as waypoints for rendering a route.
There are two types of markers: sketches-type markers and regular markers.
The sketches-type markers cannot be grouped, and all of them are
displayed regardless of the zoom level.
A custom icon image can be configured for rendering the icons.
If no image is configured, a blue filled circle will be used as the icon.
Sketches-type markers are the type of markers used in this example.
To see an example using both sketches-type (non-grouping) icons,
and grouping marker icons, see the MarkersProgrammatic
example.
Setting the custom icon image for sketches-type markers - see qml.qrc and main.qml:
markerRenderSettings.icon = ServicesManager.createIconFromFile("qrc:/violetcircle.png");
Alternatively, instead of using a custom icon image, sketches-type markers can also be rendered on the map using the predefined red- green- or blue- filled circles, specified by enum value - see main.qml:
markerRenderSettings.icon = ServicesManager.createIconFromId(Icon.GreenBall);
The custom icon images, such as png images, optionally with transparency, and map styles, if any, must be located in the project directory and configured in the qml.qrc file, shown below:
1<RCC>
2 <qresource prefix="/">
3 <file>main.qml</file>
4 <file>violetcircle.png</file>
5 </qresource>
6</RCC>
How it works
In Qt, go to the File menu and select Open File or Project…
then browse to the MapCoverageMultiPointInteractive example folder and open MapCoverageMultiPointInteractive.pro
You may want to have a look at Setting your API Key to see how to open and configure a project and set your API Key.
Adding markers to the map interactively¶
First, a LandmarkList
is defined to hold the user-selected points:
1//the following block is used only to enable autocenter on landmark group
2//and to render a route between the individual landmarks/waypoints/icons;
3//also, the map coverage check uses this list of landmarks;
4
5LandmarkList {
6 id: routingWaypoints
7}
A SearchService
is defined to carry out reverse geocoding, to find
points of interest around the location that the user long-pressed on the map:
1SearchService {
2 // Reverse geocoding takes as input a location on the map (lon,lat coordinates),
3 // in this case, interactively selected by the user, and gives as output a list
4 // of points of interest located near the selected position, 3 items in this example.
5
6 id: reverseGeocoding
7 searchMapPOIs: true
8 searchAddresses: true
9 limit: 10
10 thresholdDistance: 500
11
12 // The list of 3 points of interest located near the selected position
13 // is shown here in a popup, giving the user the option to select one of them
14 // to be added as a waypoint for a route, or simply click outside the popup to close it.
15
16 onSearchCompleted: addWaypointPopup.open()
17}
A TapHandler
is used to obtain the coordinates of the location the user
long-pressed on the map, implementing the e onLongPressed event, and carry out
the reverse geocoding search, to find POIs around the selected coordinate.
The onTapped
event is also defined, to show on screen the x,y screen coordinates
and the corresponding lon,lat coordinates of any point clicked on the map, for
reference.
1TapHandler {
2 grabPermissions: PointerHandler.CanTakeOverFromAnything
3 onTapped: {
4 let coordinates = mapView.wgsForScreen(point.pressPosition);
5 console.log("x,y (" + point.pressPosition.x + ", " + point.pressPosition.y + ")"
6 + " lon, lat " + coordinates.longitude + ", " + coordinates.latitude);
7 lonlatPositionDisplay.text = "x,y (" + point.pressPosition.x + ", " + point.pressPosition.y + ")"
8 + " lon, lat " + coordinates.longitude + ", " + coordinates.latitude;
9 }
10 onLongPressed: {
11 if (!useReverseGeocoding.checked) {
12 // This adds a waypoint to the route by long-tapping
13 // (tapping and holding for about a second)
14 // a given location directly on the map.
15 // First, create a landmark that can hold a route waypoint.
16
17 //Creates a landmark that is owned by the routingWaypoints, for efficiency.
18 //This is required because
19 //routingWaypoints.append(lmk);
20 //will clone the landmark unless the owner is the routingWaypoints list itself.
21
22 let lmk = ServicesManager.createLandmark(routingWaypoints);
23
24 // Next, add the map coordinates from the tap location to the waypoint.
25
26 lmk.coordinates = mapView.wgsForScreen(point.pressPosition);
27
28 // Finally, add the waypoint to the list from which the route is generated.
29
30 console.log("Waypoint added #########");
31 routingWaypoints.append(lmk);
32 show_waypoint_landmarks_on_map();
33 return;
34 }
35 if (point.pressPosition.x + addWaypointPopup.width > mapView.width)
36 addWaypointPopup.x = point.pressPosition.x - addWaypointPopup.width;
37 else
38 addWaypointPopup.x = point.pressPosition.x
39
40 if (point.pressPosition.y + addWaypointPopup.height > mapView.height)
41 addWaypointPopup.y = point.pressPosition.y - addWaypointPopup.height;
42 else
43 addWaypointPopup.y = point.pressPosition.y
44
45 reverseGeocoding.coordinates = mapView.wgsForScreen(point.pressPosition);
46 reverseGeocoding.search();
47 }
48}
Finally, a Popup
is shown, containing up to 3 points of interest found around
the coordinates the user long-pressed on the map; if there are more than 3 points
of interest, the popup list is scrollable. If one of the items in the list is
clicked, it is added to the routingWaypoints
otherwise the selection can be
cancelled by clicking outside the popup, to try again in a different location:
1Popup {
2 // This shows the results of the reverse geocoding in a popup.
3 id: addWaypointPopup
4 modal: true
5 focus: true
6 closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
7 width: 300
8 height: 200
9 ListView {
10 id: searchList
11 anchors.fill: parent
12 anchors.margins: 1
13 clip: true
14 model: reverseGeocoding
15 delegate: Item {
16 height: row.height
17 RowLayout {
18 id: row
19 IconView {
20 iconSource: landmark.icon
21 Layout.maximumHeight: row.height
22 Layout.maximumWidth: row.height
23 width: height
24 height: row.height
25 }
26 ColumnLayout {
27 Layout.fillHeight: true
28 Layout.fillWidth: true
29 Text {
30 Layout.fillWidth: true
31 text: landmark.name + " ("
32 + distance(landmark.coordinates.distance(reverseGeocoding.coordinates)) + ")"
33 wrapMode: Text.WrapAnywhere
34 }
35 Text {
36 Layout.fillWidth: true
37 text: landmark.description
38 font.italic: true
39 wrapMode: Text.WrapAnywhere
40 }
41 }
42 TapHandler {
43 target: row
44 onTapped: {
45 // This adds a waypoint to the route by selecting
46 // an item from the popup list of reverse geocoding results.
47 addWaypointPopup.close()
48 routingWaypoints.append(landmark)
49 show_waypoint_landmarks_on_map();
50 }
51 }
52 }
53 }
54 }
55}
Although the selected POI is added to the routingWaypoints
it is not
rendered on the map. To give visual feedback, the selected waypoints are added
to a marker list which are then rendered on the map by setting the marker list
in the sketches-type markers using the function show_waypoint_landmarks_on_map()
1function show_waypoint_landmarks_on_map()
2{
3 //show landmarks on map as point markers
4 //a markercoordlist is created, and the coordinates of each interactively selected
5 //waypoint/landmark is added to the markercoordlist which is used to render the
6 //sketches-type markers on the map for visual feedback;
7 let markercoordlist = ServicesManager.createMarker();
8 for (let n = 0; n < routingWaypoints.length; n++) {
9 let lmkit = routingWaypoints.get(n)
10 markercoordlist.append(lmkit.coordinates);
11 }
12 //the marker render settings contain configuration such as size and icon image
13 let markerRenderSettings = ServicesManager.createMarkerRenderSettings();
14 //sketches-type markers - cannot be grouped;
15 //let marker = ServicesManager.createMarker();
16 markerRenderSettings.imageSize = 32;
17 //the following line sets a custom icon image;
18 //choose one icon image line and uncomment it;
19 //the icon image is configured in qml.qrc, and located in the project directory;
20 //if an icon image is not set, markers will be shown as blue dots;
21 markerRenderSettings.icon = ServicesManager.createIconFromFile("qrc:/violetcircle.png");
22 //markerRenderSettings.icon = ServicesManager.createIconFromId(Icon.RedBall);
23 //markerRenderSettings.icon = ServicesManager.createIconFromId(Icon.GreenBall);
24 //markerRenderSettings.icon = ServicesManager.createIconFromId(Icon.BlueBall);
25 console.log(markerRenderSettings);
26
27 //SKETCHES-type markers - cannot be grouped, all markers are rendered at all zoom levels;
28 //render on the map the coordinate points for which map coverage is checked
29 let sketchlist = mapView.markerCollection.getExtendedList(MarkerList.Type.Point);
30 sketchlist.clear(); //clear previous markers so list does not grow with duplicates
31 sketchlist.append(markercoordlist, markerRenderSettings);
32
33 //print some debug info to the console
34 console.log("marker sketchlist len:" + sketchlist.length + " icon coords:" + sketchlist.get(0).length);
35 console.log("marker len:"+markercoordlist.length+" renderset:"+markerRenderSettings);
36
37 //center on list of waypoints/landmarks
38 if (routingWaypoints.length > 1)
39 {
40 mapView.centerOnGeographicArea(routingWaypoints.boundingBox)
41 }
42 return markercoordlist;
43}
Single point map coverage¶
1//////////////////////////////////////////////////////////////////////////////////
2//check map coverage for one point - (latitude,longitude) coordinate
3//////////////////////////////////////////////////////////////////////////////////
4let onecoord = markercoordlist.get(0) //the first coord in the list, at index 0:lat,lon,alt
5let mapcover = ServicesManager.mapDetails.coverage(onecoord);
6let coverageResult = "Single coordinate point map coverage result: ";
7switch ( mapcover )
8{
9case MapDetails.Unknown:
10 coverageResult = coverageResult + "MapDetails.Unknown"; break;
11case MapDetails.Offline:
12 coverageResult = coverageResult + "MapDetails.Offline"; break;
13case MapDetails.OnlineNoData:
14 coverageResult = coverageResult + "MapDetails.OnlineNoData"; break;
15case MapDetails.OnlineTile:
16 coverageResult = coverageResult + "MapDetails.OnlineTile"; break;
17default:
18 coverageResult = coverageResult + "default case - undefined"; break;
19}
20singleCoordMapCoverage.text = coverageResult;
21console.log(coverageResult);
To check map coverage at one specific lon,lat coordinate,
define the coordinate, onecoord
in this case, which simply takes
the first user-selected point on the map (at index 0) and then call
ServicesManager.mapDetails.coverage(onecoord);
, and finally
process the result as shown above.
The coverage result is shown on screen (in blue text),
and also logged in the console output.
Multiple point map coverage¶
The coordinates are added to the routing waypoint list interactively as shown above, and then they are copied into a marker coordinate list:
let markercoordlist = show_waypoint_landmarks_on_map();
so they can be passed to the map coverage verification function.
1//////////////////////////////////////////////////////////////////////////////////
2//check map coverage for multiple coordinates
3//////////////////////////////////////////////////////////////////////////////////
4let mapcovermulti = ServicesManager.mapDetails.coverageCoordList(markercoordlist)
5coverageResult = "Multiple coordinate points map coverage result: ";
6switch ( mapcovermulti )
7{
8case MapDetails.Unknown:
9 coverageResult = coverageResult + "MapDetails.Unknown"; break;
10case MapDetails.Offline:
11 coverageResult = coverageResult + "MapDetails.Offline"; break;
12case MapDetails.OnlineNoData:
13 coverageResult = coverageResult + "MapDetails.OnlineNoData"; break;
14case MapDetails.OnlineTile:
15 coverageResult = coverageResult + "MapDetails.OnlineTile"; break;
16default:
17 coverageResult = coverageResult + "default case - undefined"; break;
18}
19multiCoordsMapCoverage.text = coverageResult;
20console.log(coverageResult);
To check map coverage for a list of lon,lat coordinates,
define the coordinate list using a marker as shown above,
markercoordlist
in this case, is copied from the interactively
selected routing waypoint list, and then call
ServicesManager.mapDetails.coverageCoordList(markercoordlist)
,
and finally process the result as shown above.
The coverage result is shown on screen (in blue text),
and also logged in the console output.
Country code and map coverage¶
The following for loop code block demonstrates how to get the country code
from a lon,lat coordinate using ServicesManager.mapDetails.countryCode()
and how to get country map coverage status from a country code using
ServicesManager.mapDetails.countryCoverage()
as well as the country name
from the country code, and print the results along with the index and lon,lat
coordinates to the application console output window.
1//////////////////////////////////////////////////////////////////////////////////
2// for each coordinate in the list, print in the console output:
3// index, map coverage status, country code, coordinate(lon,lat), country name
4//////////////////////////////////////////////////////////////////////////////////
5let countrycode = "";
6for (let idx = 0; idx < markercoordlist.length; idx++) {
7 countrycode = ServicesManager.mapDetails.countryCode(markercoordlist.get(idx))
8 let mapcountrycover = ServicesManager.mapDetails.countryCoverage(countrycode)
9 coverageResult = "Country coverage result by coordinate point: ";
10 switch ( mapcountrycover )
11 {
12 case MapDetails.Unknown:
13 coverageResult = coverageResult + "MapDetails.Unknown"; break;
14 case MapDetails.Offline:
15 coverageResult = coverageResult + "MapDetails.Offline"; break;
16 case MapDetails.OnlineNoData:
17 coverageResult = coverageResult + "MapDetails.OnlineNoData"; break;
18 case MapDetails.OnlineTile:
19 coverageResult = coverageResult + "MapDetails.OnlineTile"; break;
20 default:
21 coverageResult = coverageResult + "default case - undefined"; break;
22 }
23 console.log("[" + idx + "] " + coverageResult + " " + countrycode + " ("
24 + markercoordlist.get(idx).longitude + ", " + markercoordlist.get(idx).latitude
25 + ") " + ServicesManager.mapDetails.countryName(countrycode))
26}
Sample console output:
1qml: Single coordinate point map coverage result: MapDetails.OnlineNoData
2qml: Multiple coordinate points map coverage result: MapDetails.OnlineNoData
3qml: [0] Country coverage result by coordinate point: MapDetails.OnlineNoData CHE (8.92530625, 46.074485) Switzerland
4qml: [1] Country coverage result by coordinate point: MapDetails.OnlineNoData ITA (9.2410453125, 46.173598125) Italy
5qml: [2] Country coverage result by coordinate point: MapDetails.OnlineNoData ITA (9.29047125, 46.0163665625) Italy
Rendering a route¶
Optionally, a route can be rendered using the markers as waypoints, in the order in which they were added (interactively selected on the map).
1RoutingService {
2 id: routingService
3 type: Route.Type.Fastest
4 transportMode: Route.TransportMode.Car
5 // The list of waypoints is made available to the routing service.
6 waypoints: routingWaypoints
7 onFinished: {
8 map.routeCollection.set(routeList);
9 map.centerOnRouteList(routeList);
10 }
11}
A RoutingService is defined, used in this example only to
compute and render a route plotted using the list of waypoints/landmarks
in the order in which they were added to the list;
this block is not required to autocenter on the landmark group.
Set internet connection to true in the Component.onCompleted
block
for route computation and rendering to work.
1Button {
2 anchors.left: parent.left
3 anchors.bottom: parent.bottom
4 enabled: routingWaypoints.length > 1
5 text: qsTr("Render route")
6 background: Rectangle {
7 opacity: parent.hovered ? 1 : 0.5
8 color: enabled ? parent.down ? "#aa00aa" :
9 (parent.hovered ? "#0000ff" : "#2000ff") : "#aaaaaa"
10 }
11 palette { buttonText: "#ffffff"; }
12 onClicked: {
13 //render route when button is clicked only if there are min 2 waypoints in the list;
14 if (routingWaypoints.length > 1)
15 {
16 //compute and render a route plotted using list of waypoints/landmarks
17 //in the order in which they were added
18 //center on route plotted from list of waypoints/landmarks
19 routingService.update()
20 }
21 }
22}
Click the Render route
button to compute and render the route, once at
least 2 waypoints have been selected, because a route consists of at least
2 waypoints, where the first is the departure point and the last is the
destination.
Click the Clear route
button to remove the route from the map.
Removing sketches-type markers¶
The route and/or sketches-type markers can be removed from the map separately.
1Button {
2 text: "Clear sketches-type markers/waypoints"
3 background: Rectangle {
4 opacity: parent.hovered ? 1 : 0.5
5 color: enabled ? parent.down ? "#aa00aa" :
6 (parent.hovered ? "#0000ff" : "#2000ff") : "#aaaaaa"
7 }
8 palette { buttonText: "#ffffff"; }
9 onClicked: {
10 //show how to clear sketches-type marker icons from the map;
11 //clear the list of points used for centering on the bounding box
12 //containing all points/landmarks/waypoints/markers/icons;
13
14 routingWaypoints.clear();
15
16 //also clear the markerlist used for rendering the points on the map;
17 //the same set of coordinates is in each of these lists, so both must
18 //be cleared;
19
20 let sketchlist = mapView.markerCollection.getExtendedList(MarkerList.Type.Point);
21 sketchlist.clear();
22 }
23}
Removing the sketches-type markers is done by again getting a pointer
to the built-in sketches-type marker list, and using the clear()
function.
The corresponding routingWaypoints
list, used to render the
route or center on the group of markers, or both, is also cleared.
The same set of coordinates is in each of these lists,
so both must be cleared.
Also, the button changes color to blue and becomes opaque when the mouse
hovers over it for visual feedback.