Решил попрактиковаться в программирование под Android на Qt. В качестве темы выбрал GPS трекер.
Набор функций этого трекера:
- снимать измерения с GPS приемника;
- экспортировать трек в GPX (GPS eXchange Format);
- выводить трек на карту;
- выводить время в пути, длину пути, среднюю скорость.
Под катом будет приведен пример работы с картой в QtQuick.
Plugin, PluginParameter и Map
Базовые типы находятся в модуле Qt Location. Qt Location в качестве бакенда может использовать:
Работа с конкретным поставщиком карт помещена в плагины(Plugin), которые настраиваются через параметры(PluginParameter).
Минимальный пример:
Plugin {
id: plugin
preferred: ["here", "osm"]
required: Plugin.AnyMappingFeatures | Plugin.AnyGeocodingFeatures
}
Map {
plugin: plugin
width: ...
height:...
}
Поначалу использовал просто Open Street Map:
Plugin {
id: plugin
name: "osm"
}
По умолчанию поставщиком OSM карт является MapQuest, который с недавних пор ввели ключ разработчика. Тут встал вопрос о переходе на что-то другое.
Open Street Map Plugin
В документации перечислены поддержка:
- MapQuest;
- ThunderForest;
- OpenStreetMap и сообщество.
Для того, что бы воспользоваться последним пунктом нужно выполнить два условия:
Задать параметр osm.mapping.host:
Plugin {
id: mapPlugin
name: "osm"
PluginParameter {
name: "osm.mapping.host";
value: "http://a.tile.openstreetmap.org/"
}
}
Карте указать использовать тип карт MapType.CustomMap.
Для любителей магии:
Map {
id: map
plugin: mapPlugin
activeMapType: map.supportedMapTypes[7]
}
Что бы не надеяться на позицию элемента в списке supportedMapTypes, можно сделать так:
Map {
id: map
plugin: mapPlugin
zoomLevel: 16
width: item.width
height:item.height
property MapPolyline track
}
Timer {
interval: 100; running: true; repeat: false
onTriggered: {
for(var i = 0;
i < map.supportedMapTypes.length;
++i){
if(map.supportedMapTypes[i].style
=== MapType.CustomMap){
map.activeMapType = map.supportedMapTypes[i];
}
}
}
}
Трек
Для рисования трека взял элемент MapPolyline, при этом создаю его динамически, для очищения карты:
function start() {
mapItem.clearMapItems();
mapItem.track = Qt.createQmlObject('import QtLocation 5.6; MapPolyline {}', item);
mapItem.track.line.width = 6;
mapItem.track.line.color = 'red';
mapItem.addMapItem(mapItem.track);
}
function appendCoordinate(position){
mapItem.center = position;
mapItem.track.addCoordinate(position)
}
Map {
id: mapItem
plugin: mapPlugin
zoomLevel: 16
width: item.width
height:item.height
property MapPolyline track
}
При старте очищаю карту, создаю трек и помещаю на карту. При добавлении новой координаты центр карты перемещается в указанную позицию и удлиняется трек.
Результат:
Код доступен на GitHub
Комментарии (11)
Zifix
21.07.2016 15:30+1Статья полезная, но стиль кода местами старается собрать все возможные способы ухудшения читабельности:
Timer { interval: 100; running: true; repeat: false onTriggered: { for(var i = 0; i < map.supportedMapTypes.length; ++i){ if(map.supportedMapTypes[i].style === MapType.CustomMap){ map.activeMapType = map.supportedMapTypes[i]; } } } } vs Timer { interval: 100 running: true onTriggered: { var n = map.supportedMapTypes.length; for (var i = 0; i < n; ++i) { if (map.supportedMapTypes[i].style === MapType.CustomMap) { map.activeMapType = map.supportedMapTypes[i]; } } } }
vasylll95
21.07.2016 15:34А реализация з оффлайн картами возможна?
RPG18
21.07.2016 15:35По этой теме есть отдельная статья Кратко от том как сделать свой Qt geoservice plugin
Antervis
22.07.2016 05:46скорее нет чем да. Qt карты поддерживают только тайлы, векторную реализацию проще с нуля сделать, чем через плагины Qt. В Qml Map нет даже поддержки вращения…
Разве что создавать тайлы из векторных данных на лету, но лично я воспринимаю это скорее как костыль чем API
sundaywizard
22.07.2016 21:12Спасибо. Ваш пост вышел очень вовремя и оказался очень полезным. А вы не знаете, почему потребовалось делать фокусы, вместо того, что написать что-то вроде activeMapType: Map.CustomMap?
RPG18
22.07.2016 21:15Пробовал по всякому, да же так:
activeMapType: MapType{ style: Map.CustomMap }
Но что-то не получилось.
ittakir
Трек записывается в фоне?
Какая при этом нагрузка на проц?
Где хранятся точки, и что будет, если приложение будет убито системой?
Как часто пишем на диск?
Вобщем, довольно много вопросов возникает, если хочется сделать действительно удобное приложение.
RPG18
Не в фоне. Нагрузку на проц не мерил. Точки записываются в бинарный лог. Лог файл создается через QTemporaryFile.
Измерения собираю каждые 5 секунд, если координаты валидные и расстояние между точками больше 10 метров, то происходит добавление в трек.