如何使用模型数据绘制地图折线段
How to use model data to draw mappolyline segments
我想绘制对应于表示机场跑道的线段的折线图,坐标由模型提供。
这是预期的结果:
主要提供机场和跑道的数据(芝加哥实际上有18条跑道,这里只记录2条,为了简化):
#include "airportsmodel.h"
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
AirportsModel apModel;
Airport KORD = Airport("KORD","CHICAGO O'HARE INTL",41.97732,-87.90801,680);
KORD.addRunway(Runway("04L",42,41.98166,-87.91392,656));
KORD.addRunway(Runway("22R",222,41.99754,-87.89637,648));
apModel.addAirport(KORD);
QQmlApplicationEngine engine;
engine.addImportPath(QStringLiteral(":/imports"));
engine.rootContext()->setContextProperty("airportsModel", &apModel);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
QObject::connect(&engine, SIGNAL(quit()), qApp, SLOT(quit()));
QObject *item = engine.rootObjects().first();
Q_ASSERT(item);
return app.exec();
}
这里是机场 class,整合了 class 条跑道。 mappolyline 的有用坐标由 rwPosition () return 编辑。 NameRunway() 和 runwayQfu() 将用于识别匹配的坐标对以绘制完整的跑道。
#ifndef AIRPORT_H
#define AIRPORT_H
#include <QGeoCoordinate>
#include <QString>
class Runway
{
public:
Runway(QString name, int qfu, double latitude, double longitude, double elevation)
: m_name(name), m_qfu(qfu)
{
m_position.setLatitude(latitude);
m_position.setLongitude(longitude);
m_position.setAltitude(elevation);
}
QString nameRunway() const {
return m_name;
}
int runwayQfu() const {
return m_qfu;
}
QGeoCoordinate rwPosition() const{
return m_position;
}
private:
QGeoCoordinate m_position;
QString m_name;
int m_qfu;
};
class Airport
{
public:
Airport(QString code, QString name, double latitude, double longitude, double elevation)
:m_code(code), m_name(name) {
m_position.setLatitude(latitude);
m_position.setLongitude(longitude);
m_position.setAltitude(elevation);
}
QGeoCoordinate apPosition() const{
return m_position;
}
QString oaciCode() const {
return m_code;
}
QString airportName() const {
return m_name;
}
void addRunway(const Runway &runway){
m_runwayList << runway;
}
const QList<Runway> &listRunways() const {
return m_runwayList;
}
private:
QGeoCoordinate m_position;
QString m_code;
QString m_name;
QList<Runway> m_runwayList;
};
#endif // AIRPORT_H
我认为模型应该 return 机场跑道的完整列表。在模型中由 rwRole 负责处理。
#ifndef AIRPORTSMODEL_H
#define AIRPORTSMODEL_H
#include "airport.h"
#include <QAbstractListModel>
#include <QDebug>
class AirportsModel : public QAbstractListModel
{
Q_OBJECT
public:
AirportsModel(QObject *parent = Q_NULLPTR):QAbstractListModel(parent){
}
enum AirportsRoles{rwRole = Qt::UserRole + 1};
void addAirport(const Airport &point){
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_apList << point;
endInsertRows();
}
Q_INVOKABLE int rowCount(const QModelIndex & parent = QModelIndex()) const{
Q_UNUSED(parent)
return m_apList.count();
}
QVariant data(const QModelIndex & index, int role=Qt::DisplayRole) const {
if (index.row() < 0 || index.row() >= m_apList.count())
return QVariant();
const Airport &point = m_apList[index.row()];
if (role == rwRole){
QList<QGeoCoordinate> rwCoord;
const auto &runwayList = point.listRunways();
foreach (const Runway &runwayLabeled, runwayList)
{
rwCoord << runwayLabeled.rwPosition();
qDebug() << "runway : " << runwayLabeled.nameRunway()<< " qfu : " << runwayLabeled.runwayQfu() << " coordinate : " << runwayLabeled.rwPosition();
}
return QVariant::fromValue(rwCoord);
}
return QVariant();
}
protected:
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[rwRole] = "runways";
return roles;
}
private:
QList<Airport> m_apList;
};
#endif // AIRPORTSMODEL_H
我的问题是如何利用 returned 跑道列表 (rwCoord) 以及此行中显示的路径:路径:来自 main.qml 此处的 [runways]:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtPositioning 5.5
import QtLocation 5.6
Window {
width: 700
height: 500
visible: true
title: qsTr("Test MapPolyline for airport")
id: win
Map {
id: mapOfWorld
anchors.centerIn: parent;
anchors.fill: parent
zoomLevel: 12
plugin: Plugin {name: "osm"}
center: QtPositioning.coordinate(41.97732, -87.90801)//KORD
MapItemView {
model: airportsModel
delegate: Marker{
// path: [runways]
path: [
{latitude: 41.98166, longitude: -87.91392},
{latitude: 41.99754,longitude: -87.89637}
]
}
}
}
}
这里直接输入一对坐标路径就可以正常工作,当然不是目的
标记。 qml是一个简单的mappolyline,当一个机场超过2条跑道时,将添加一个功能来收集不同的坐标对。
import QtQuick 2.5
import QtLocation 5.6
MapPolyline {
line.color: "darkBlue"
line.width: 5
}
所以,总结一下:
按照 class 机场的设计,return 属于机场的所有跑道的 Qlist 是正确的(更好的)方法吗?
如果是,我如何将此列表用于qml部分并将跑道添加到路径以绘制代表线段?
非常感谢您的帮助。
如果你想让路线被识别,你必须return一个QVariantList
,而不是QList<QGeoCoordinate>
:
QVariant data(const QModelIndex & index, int role=Qt::DisplayRole) const {
if (index.row() < 0 || index.row() >= m_apList.count())
return QVariant();
const Airport &point = m_apList[index.row()];
if (role == rwRole){
QVariantList rwCoord;
const auto &runwayList = point.listRunways();
for(const Runway &runwayLabeled: runwayList)
{
rwCoord << QVariant::fromValue(runwayLabeled.rwPosition());
//qDebug() << "runway : " << runwayLabeled.nameRunway()<< " qfu : " << runwayLabeled.runwayQfu() << " coordinate : " << runwayLabeled.rwPosition();
}
return rwCoord; //; QVariant::fromValue(rwCoord);
}
return QVariant();
}
然后不用括号直接通过跑道:
delegate: Marker{
path: runways
}
您可以在下面找到完整的测试代码link
我想绘制对应于表示机场跑道的线段的折线图,坐标由模型提供。
这是预期的结果:
#include "airportsmodel.h"
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
AirportsModel apModel;
Airport KORD = Airport("KORD","CHICAGO O'HARE INTL",41.97732,-87.90801,680);
KORD.addRunway(Runway("04L",42,41.98166,-87.91392,656));
KORD.addRunway(Runway("22R",222,41.99754,-87.89637,648));
apModel.addAirport(KORD);
QQmlApplicationEngine engine;
engine.addImportPath(QStringLiteral(":/imports"));
engine.rootContext()->setContextProperty("airportsModel", &apModel);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
QObject::connect(&engine, SIGNAL(quit()), qApp, SLOT(quit()));
QObject *item = engine.rootObjects().first();
Q_ASSERT(item);
return app.exec();
}
这里是机场 class,整合了 class 条跑道。 mappolyline 的有用坐标由 rwPosition () return 编辑。 NameRunway() 和 runwayQfu() 将用于识别匹配的坐标对以绘制完整的跑道。
#ifndef AIRPORT_H
#define AIRPORT_H
#include <QGeoCoordinate>
#include <QString>
class Runway
{
public:
Runway(QString name, int qfu, double latitude, double longitude, double elevation)
: m_name(name), m_qfu(qfu)
{
m_position.setLatitude(latitude);
m_position.setLongitude(longitude);
m_position.setAltitude(elevation);
}
QString nameRunway() const {
return m_name;
}
int runwayQfu() const {
return m_qfu;
}
QGeoCoordinate rwPosition() const{
return m_position;
}
private:
QGeoCoordinate m_position;
QString m_name;
int m_qfu;
};
class Airport
{
public:
Airport(QString code, QString name, double latitude, double longitude, double elevation)
:m_code(code), m_name(name) {
m_position.setLatitude(latitude);
m_position.setLongitude(longitude);
m_position.setAltitude(elevation);
}
QGeoCoordinate apPosition() const{
return m_position;
}
QString oaciCode() const {
return m_code;
}
QString airportName() const {
return m_name;
}
void addRunway(const Runway &runway){
m_runwayList << runway;
}
const QList<Runway> &listRunways() const {
return m_runwayList;
}
private:
QGeoCoordinate m_position;
QString m_code;
QString m_name;
QList<Runway> m_runwayList;
};
#endif // AIRPORT_H
我认为模型应该 return 机场跑道的完整列表。在模型中由 rwRole 负责处理。
#ifndef AIRPORTSMODEL_H
#define AIRPORTSMODEL_H
#include "airport.h"
#include <QAbstractListModel>
#include <QDebug>
class AirportsModel : public QAbstractListModel
{
Q_OBJECT
public:
AirportsModel(QObject *parent = Q_NULLPTR):QAbstractListModel(parent){
}
enum AirportsRoles{rwRole = Qt::UserRole + 1};
void addAirport(const Airport &point){
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_apList << point;
endInsertRows();
}
Q_INVOKABLE int rowCount(const QModelIndex & parent = QModelIndex()) const{
Q_UNUSED(parent)
return m_apList.count();
}
QVariant data(const QModelIndex & index, int role=Qt::DisplayRole) const {
if (index.row() < 0 || index.row() >= m_apList.count())
return QVariant();
const Airport &point = m_apList[index.row()];
if (role == rwRole){
QList<QGeoCoordinate> rwCoord;
const auto &runwayList = point.listRunways();
foreach (const Runway &runwayLabeled, runwayList)
{
rwCoord << runwayLabeled.rwPosition();
qDebug() << "runway : " << runwayLabeled.nameRunway()<< " qfu : " << runwayLabeled.runwayQfu() << " coordinate : " << runwayLabeled.rwPosition();
}
return QVariant::fromValue(rwCoord);
}
return QVariant();
}
protected:
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[rwRole] = "runways";
return roles;
}
private:
QList<Airport> m_apList;
};
#endif // AIRPORTSMODEL_H
我的问题是如何利用 returned 跑道列表 (rwCoord) 以及此行中显示的路径:路径:来自 main.qml 此处的 [runways]:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtPositioning 5.5
import QtLocation 5.6
Window {
width: 700
height: 500
visible: true
title: qsTr("Test MapPolyline for airport")
id: win
Map {
id: mapOfWorld
anchors.centerIn: parent;
anchors.fill: parent
zoomLevel: 12
plugin: Plugin {name: "osm"}
center: QtPositioning.coordinate(41.97732, -87.90801)//KORD
MapItemView {
model: airportsModel
delegate: Marker{
// path: [runways]
path: [
{latitude: 41.98166, longitude: -87.91392},
{latitude: 41.99754,longitude: -87.89637}
]
}
}
}
}
这里直接输入一对坐标路径就可以正常工作,当然不是目的
标记。 qml是一个简单的mappolyline,当一个机场超过2条跑道时,将添加一个功能来收集不同的坐标对。
import QtQuick 2.5
import QtLocation 5.6
MapPolyline {
line.color: "darkBlue"
line.width: 5
}
所以,总结一下: 按照 class 机场的设计,return 属于机场的所有跑道的 Qlist 是正确的(更好的)方法吗? 如果是,我如何将此列表用于qml部分并将跑道添加到路径以绘制代表线段?
非常感谢您的帮助。
如果你想让路线被识别,你必须return一个QVariantList
,而不是QList<QGeoCoordinate>
:
QVariant data(const QModelIndex & index, int role=Qt::DisplayRole) const {
if (index.row() < 0 || index.row() >= m_apList.count())
return QVariant();
const Airport &point = m_apList[index.row()];
if (role == rwRole){
QVariantList rwCoord;
const auto &runwayList = point.listRunways();
for(const Runway &runwayLabeled: runwayList)
{
rwCoord << QVariant::fromValue(runwayLabeled.rwPosition());
//qDebug() << "runway : " << runwayLabeled.nameRunway()<< " qfu : " << runwayLabeled.runwayQfu() << " coordinate : " << runwayLabeled.rwPosition();
}
return rwCoord; //; QVariant::fromValue(rwCoord);
}
return QVariant();
}
然后不用括号直接通过跑道:
delegate: Marker{
path: runways
}
您可以在下面找到完整的测试代码link