Navigation Icon Resize¶
In this guide you will learn how to change the size of the
navigation turn icons, displayed during a real or simulated navigation;
RoutingService
is used to compute a route and NavigationService
to start a real or simulated navigation on that route.
Change navigation icon rendering size¶
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¶
NavigationIconResize
demonstrates how to change the size of the
navigation turn icons, displayed during a real or simulated navigation.
The Compute route(s)
button causes the RoutingService
to
calculate a route between preset start (departure) and end (destination) points,
and render the route on the map.
The Start simulation
button starts the simulated navigation along
the resulting route using NavigationService
The turn icons are displayed using an initial size, such as 64x64 pixels.
Press the Increase icon size
button to increase the size of the icons
displayed.
How it works
In Qt, go to the File menu and select Open File or Project…
then browse to the NavigationIconResize example folder and open NavigationIconResize.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.
1import QtQuick 2.12
2import QtQuick.Controls 2.12
3import QtQuick.Layouts 1.12
4import QtQuick.Window 2.12
5import NavigationTurnIconSize 1.0
6import GeneralMagic 2.0
7
8Window {
9 visible: true
10 width: 640
11 height: 480
12 title: qsTr("Navigation Icon Resize Example")
In main.qml, we import the GeneralMagic QML plugin. Next, we need to make sure we allow online access, and that we are using the latest data.
1property var updater: ServicesManager.contentUpdater(ContentItem.Type.RoadMap)
2Component.onCompleted: {
3 //! [Set token safely]
4 ServicesManager.settings.token = __my_secret_token;
5 //! [Set token safely]
6 ServicesManager.settings.allowInternetConnection = true; // enable connection to online services
7
8 updater.autoApplyWhenReady = true;
9 updater.update();
10}
The __my_secret_token
property in the above QML code is set in C++
like this. In this example, in main.cpp
, replace YOUR_TOKEN
with your actual General Magic Maps API Key token string.
1// C++ code
2QQmlApplicationEngine engine;
3//...
4//! [Set API Key token safely]
5// go to https://developer.generalmagic.com to get your token
6engine.rootContext()->setContextProperty("__my_secret_token", "YOUR_API_KEY_TOKEN_STRING");
7//! [Set API Key token safely]
8
9engine.load(url);
In this example, it is possible to interactively increase and decrease the size of the navigation icons. A variable has to be defined in C++ to maintain the state of the current icon size. This variable must have get, set, and notify when value has changed functionality.
The class, of which this variable is an instance, is defined in
navturniconsize.h
1class NavigationTurnIconSize : public QObject {
2 Q_OBJECT
3 Q_PROPERTY(int navigationTurnIconSizePixels
4 READ navigationTurnIconSizePixels
5 WRITE setNavigationTurnIconSizePixels
6 NOTIFY navigationTurnIconSizePixelsChanged)
7public:
8 NavigationTurnIconSize() { m_sizePixels = 64; } //initial size
9 int navigationTurnIconSizePixels() const { return m_sizePixels; }
10 void setNavigationTurnIconSizePixels(int newValue) {
11 m_sizePixels = (newValue < m_minSizePixels) ? m_minSizePixels
12 : newValue > m_maxSizePixels ? m_maxSizePixels
13 : newValue; emit navigationTurnIconSizePixelsChanged(); }
14signals:
15 void navigationTurnIconSizePixelsChanged();
16private:
17 const int m_minSizePixels = 16;
18 const int m_maxSizePixels = 384;
19 int m_sizePixels;
20};
First, the e {NavigationTurnIconSize} class is registered in e {main.cpp} like this:
qmlRegisterType<NavigationTurnIconSize>("NavigationTurnIconSize", 1, 0, "NavigationTurnIconSize");
Then it is imported in qml code as seen in the above import statement in e {main.qml} like this:
import NavigationTurnIconSize 1.0
And finally an instance is defined like this:
1NavigationTurnIconSize {
2 id: myNavigationTurnIconSize
3}
To start a simulation/navigation there are three steps involved:
Compute the route(s)¶
1RoutingService {
2 id: routingService
3 type: Route.Type.Fastest
4 transportMode: Route.TransportMode.Car
5
6 waypoints: LandmarkList {
7 Landmark {
8 name: "start"
9 coordinates: Coordinates {
10 latitude: 52.37164
11 longitude: 4.88220
12 }
13 }
14 Landmark {
15 name: "waypoint1"
16 coordinates: Coordinates {
17 latitude: 52.37118
18 longitude: 4.88136
19 }
20 }
21 Landmark {
22 name: "waypoint2"
23 coordinates: Coordinates {
24 latitude: 52.37164
25 longitude: 4.88220
26 }
27 }
28 Landmark {
29 name: "stop"
30 coordinates: Coordinates {
31 latitude: 52.37118
32 longitude: 4.88136
33 }
34 }
35 }
36 onFinished: {
37 mapView.routeCollection.set(routeList);
38 mapView.centerOnRouteList(routeList);
39 }
40}
The first step is to declare a RoutingService
to be used for calculating the route(s).
A minimum of two Landmarks
are needed in a LandmarkList
where the first one is the departure and the last one is the
destination. There can be 0 or more intermediate waypoint
landmarks. In this case, there are 2 intermediate waypoints,
for a total of 4 landmarks through which the route must pass.
In the onFinished:
section, the resulting route list
is given to the MapView
instance, identified as mapView
to be rendered, and centerOnRouteList()
causes the camera
to fly to the rendered routes, at the appropriate altitude so
that they fit in the viewport.
1function distance(meters)
2{
3 return meters >= 1000 ? (meters / 1000.).toFixed(3) + " Km" : meters.toFixed(0) + " m";
4}
5NavigationService {
6 id: navigation
7 route: mapView.routeCollection.mainRoute
8 simulation: true // change it to false (default) to perform real turn by turn navigation
9 onActiveChanged: {
10 if (active) {
11 mapView.startFollowingPosition();
12 mapView.routeCollection.clear(true /*keepMainRoute*/);
13 }
14 }
15 onCurrentInstructionChanged: {
16 // WORKS ONLY with Qt 5.15.x or Qt 6.x
17 const nextspeedlimit = currentInstruction.nextSpeedLimitVariation();
18 console.log(nextspeedlimit.distance, nextspeedlimit.speed,
19 nextspeedlimit.coordinates.latitude, nextspeedlimit.coordinates.longitude);
20 }
21 onWaypointReached: console.log("WaypointReached :" + waypoint.name);
22 onDestinationReached: mapView.routeCollection.clear();
23 onNavigationError: {
24 console.log("NavigationError :" + error);
25 mapView.routeCollection.clear();
26 }
27 onNavigationRouteUpdated: {
28 console.log("RouteUpdated :" + route.summary);
29 mapView.routeCollection.add(route, true);
30 mapView.routeCollection.clear(true);
31 }
32}
The second step is to declare a NavigationService
to be used for the simulation/navigation.
Do simulation/navigation¶
1Button {
2 text: "Compute route(s)"
3 enabled: ServicesManager.settings.connected && !navigation.active
4 onClicked: routingService.update()
5}
6//! [RoutingNavigation compute routing]
7Button {
8 enabled: mapView.routeCollection.mainRoute.valid
9 text: navigation.active ? "Stop simulation" : "Start simulation"
10 onClicked: navigation.active = !navigation.active
11}
Within the MapView
block,
the Compute route(s)
button causes the RoutingService
to
calculate a route between preset start (departure) and end (destination) points,
and render the route on the map.
The Start simulation
button is enabled once a calculated route
has been set as the main route, and starts the simulated navigation along
the calculated route.
Show everything on a MapView
¶
1Rectangle {
2 color: Qt.rgba(.8, 1, 1, 0.6)
3 visible: navigation.active
4 anchors.top: parent.top
5 anchors.left: parent.left
6 anchors.right: parent.right
7 height: myNavigationTurnIconSize.navigationTurnIconSizePixels + rowlayout.anchors.margins
8 RowLayout {
9 id: rowlayout
10 anchors.fill: parent
11 anchors.margins: 10
12 DynamicIconView {
13 id: iconLeft
14 Layout.fillHeight: true
15 arrowInner: "blue"
16 arrowOuter: "cyan"
17 slotInner: "yellow"
18 slotOuter: "red"
19
20 iconSource: navigation.currentInstruction.nextTurnDynamicIcon
21 onWidthChanged: {
22 iconLeft.width = myNavigationTurnIconSize.navigationTurnIconSizePixels
23 iconLeft.height = myNavigationTurnIconSize.navigationTurnIconSizePixels
24 iconRight.width = myNavigationTurnIconSize.navigationTurnIconSizePixels
25 iconRight.height = myNavigationTurnIconSize.navigationTurnIconSizePixels
26 }
27 }
28 DynamicIconView {
29 id: iconRight
30 Layout.fillHeight: true
31 arrowInner: "cyan"
32 arrowOuter: "magenta"
33 slotInner: "white"
34 slotOuter: "magenta"
35
36 iconSource: navigation.currentInstruction.nextNextTurnDynamicIcon
37 }
38 }
39 Rectangle {
40 id: instructionRectangle
41 color: Qt.rgba(.7, 1, 1, 0.6)
42 visible: navigation.active
43 anchors.left: parent.left
44 anchors.right: parent.right
45 height: 20
46 RowLayout {
47 anchors.fill: parent
48 Label {
49 Layout.fillWidth: true
50 font.pixelSize: 16
51 text: navigation.currentInstruction.nextStreetName + " ("
52 + distance(navigation.currentInstruction.distanceToNextTurn) + ")";
53 }
54 Label {
55 font.pixelSize: 16
56 text: distance(navigation.currentInstruction.distanceToNextNextTurn)
57 }
58 }
59 }
60}
The last step is to follow the navigation/simulation on the routes shown on the map.
The above Rectangle
panels within the MapView
block, appear at the top of
the map during simulated navigation, and show a DynamicIconView
with the next
turn icon on the left, and the next next turn icon (the icon after the next turn)
on the right, as well as the remaining distance in meters to the next turn (left icon),
and to the turn after that (next next turn, the right icon).
1Button {
2 text: "Increase icon size"
3 onClicked: {
4 myNavigationTurnIconSize.navigationTurnIconSizePixels
5 = myNavigationTurnIconSize.navigationTurnIconSizePixels + 20
6 iconLeft.height = myNavigationTurnIconSize.navigationTurnIconSizePixels
7 iconLeft.width = myNavigationTurnIconSize.navigationTurnIconSizePixels
8 iconRight.height = myNavigationTurnIconSize.navigationTurnIconSizePixels
9 iconRight.width = myNavigationTurnIconSize.navigationTurnIconSizePixels
10 }
11}
12Button {
13 text: "Decrease icon size"
14 onClicked: {
15 myNavigationTurnIconSize.navigationTurnIconSizePixels
16 = myNavigationTurnIconSize.navigationTurnIconSizePixels - 20
17 iconLeft.height = myNavigationTurnIconSize.navigationTurnIconSizePixels
18 iconLeft.width = myNavigationTurnIconSize.navigationTurnIconSizePixels
19 iconRight.height = myNavigationTurnIconSize.navigationTurnIconSizePixels
20 iconRight.width = myNavigationTurnIconSize.navigationTurnIconSizePixels
21 }
22}
Finally, there are 2 buttons, to increase and decrease the icon size (in pixels, +/- 20 pixels) for both the left (next turn) and the right (next next turn) icons.
The value of the variable stored in C++ is increased/decreased, and
then it is read and set into the left icon width and height, as well
as the right icon width and height.
This also updates the transparent panel height to fit the icon size,
and the onWidthChanged: {}
callback is used to detect and update
the icon size changes immediately in the navigation icons currently rendered.