如何使用模型数据绘制地图折线段

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