最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt編寫(xiě)地圖實(shí)現(xiàn)實(shí)時(shí)動(dòng)態(tài)軌跡效果

 更新時(shí)間:2022年02月10日 16:26:03   作者:feiyangqingyun  
實(shí)時(shí)動(dòng)態(tài)軌跡主要是需要在地圖上動(dòng)態(tài)顯示GPS的運(yùn)動(dòng)軌跡,也是編寫(xiě)地圖時(shí)一個(gè)重要的功能。本文將利用Qt實(shí)現(xiàn)這一功能,需要的可以參考一下

一、前言

實(shí)時(shí)動(dòng)態(tài)軌跡經(jīng)歷過(guò)很多個(gè)版本的迭代,此功能最初是一個(gè)客戶定制的,主要是需要在地圖上動(dòng)態(tài)顯示GPS的運(yùn)動(dòng)軌跡,有個(gè)應(yīng)用場(chǎng)景就是一個(gè)帶有監(jiān)控的車子,實(shí)時(shí)在運(yùn)動(dòng)中,后臺(tái)可以接收到經(jīng)緯度信息,需要繪制對(duì)應(yīng)的軌跡,相當(dāng)于這些攝像機(jī)點(diǎn)位是動(dòng)態(tài)移動(dòng)的,這樣就可以觀測(cè)到攝像機(jī)的實(shí)時(shí)位置信息,雙擊攝像機(jī)還可以彈出畫(huà)面實(shí)時(shí)預(yù)覽,很直觀。

GPS運(yùn)動(dòng)軌跡這個(gè)功能,也需要用到j(luò)s的知識(shí),其實(shí)就是封裝一個(gè)js函數(shù),繪制對(duì)應(yīng)的線條路徑,這個(gè)軌跡點(diǎn)可能包括的信息有經(jīng)度、緯度、速度、時(shí)間、是否標(biāo)記、時(shí)間等信息,寫(xiě)個(gè)結(jié)構(gòu)體封裝下,方便后期拓展,是否標(biāo)記的含義是是否改點(diǎn)同時(shí)作為一個(gè)設(shè)備點(diǎn)添加,分段線的含義。

后面陸續(xù)增加了可以設(shè)置旋轉(zhuǎn)角度、可以過(guò)濾坐標(biāo)點(diǎn)這兩個(gè)要點(diǎn),設(shè)置旋轉(zhuǎn)角度采用的是內(nèi)置的setRotation函數(shù),流程是先從一堆覆蓋物中通過(guò)唯一標(biāo)識(shí)比如name找到當(dāng)前要移動(dòng)的點(diǎn),然后對(duì)這個(gè)標(biāo)注點(diǎn)調(diào)用setRotation設(shè)置要旋轉(zhuǎn)的角度值,所以這里衍生了另外一個(gè)需求,如何計(jì)算兩個(gè)點(diǎn)之間的旋轉(zhuǎn)角度值,這個(gè)值必須是提前計(jì)算好的,這就要用到數(shù)學(xué)知識(shí)了,用atan2來(lái)計(jì)算,同時(shí)做矯正。

二、功能特點(diǎn)

定時(shí)器排隊(duì)下載省市輪廓圖點(diǎn)坐標(biāo)集合存儲(chǔ)到JS文件。

支持一個(gè)行政區(qū)域多個(gè)不規(guī)則區(qū)域下載。

自動(dòng)計(jì)算行政區(qū)域的下載輪廓數(shù)量。

可精確選擇省份、市區(qū)、縣城,也可直接輸入行政區(qū)域的名稱。

可以設(shè)置下載間隔、隨時(shí)開(kāi)始下載和停止下載。

提供編輯邊界功能,可以直接在地圖上編輯好不規(guī)則區(qū)域的點(diǎn)集合,然后獲取邊界點(diǎn)集合數(shù)據(jù),這個(gè)可以用來(lái)自己繪制區(qū)域拿到數(shù)據(jù),比如某個(gè)鄉(xiāng)鎮(zhèn)甚至某個(gè)小區(qū)的行政區(qū)域數(shù)據(jù),很牛逼。

三、體驗(yàn)地址

體驗(yàn)地址:https://pan.baidu.com/s/15ZKAlptW-rDcNq8zlzdYLg  提取碼:uyes 文件名:bin_map.zip

國(guó)內(nèi)站點(diǎn):https://gitee.com/feiyangqingyun

國(guó)際站點(diǎn):https://github.com/feiyangqingyun

四、效果圖

五、相關(guān)代碼

void frmMapGps::receiveDataFromJs(const QString &type, const QVariant &data)
{
    if (data.isNull()) {
        return;
    }

    //qDebug() << "frmMapGps" << type << data;
    QString result = data.toString();
    if (type == "point") {
        if (ui->ckSelectAddr->isChecked()) {
            //判斷哪里勾選了就設(shè)置到哪里
            QString point = WebHelper::getLngLat2(result);
            //判斷哪里勾選了就設(shè)置到哪里
            if (ui->rbtnStartAddr->isChecked()) {
                ui->txtStartAddr->setText(point);
            } else {
                ui->txtEndAddr->setText(point);
            }
        }
    } else if (type == "routepoints") {
        //將查詢路徑轉(zhuǎn)換成經(jīng)緯度坐標(biāo)點(diǎn)集合數(shù)據(jù)顯示
        routeDatas.clear();
        ui->tableWidgetSource->clearContents();
        //可能會(huì)有多個(gè)路徑集合,目前測(cè)試下來(lái)都是一個(gè)路徑集合
        QStringList datas = result.split("|");
        foreach (QString data, datas) {
            QStringList points = data.split(";");
            routeDatas << points;
            int count = points.count();
            ui->tableWidgetSource->setRowCount(count);
            for (int i = 0; i < count; ++i) {
                addItem(ui->tableWidgetSource, i, points.at(i));
            }
        }

        setInfo(0, 0, 0);
    }
}

void frmMapGps::runJs(const QString &js)
{
    web->runJs(js);
}

void frmMapGps::on_btnSearchData_clicked()
{
    QString startAddr = ui->txtStartAddr->text().trimmed();
    QString endAddr = ui->txtEndAddr->text().trimmed();
    baidu->setRotueInfo(2, 0, startAddr, endAddr);
    this->loadMap();
}

void frmMapGps::moveMarker()
{
    QTableWidget *tableWidget = getTableWidget();
    int row = tableWidget->currentRow();
    int count = tableWidget->rowCount();
    if (row >= 0 && row < count) {
        //找出和上一個(gè)點(diǎn)之間的角度
        int angle = 0;
        QString point = tableWidget->item(row, 1)->data(Qt::UserRole).toString();
        //第一個(gè)點(diǎn)和最后一個(gè)點(diǎn)不用處理
        if (row > 0 && row < count - 1) {
            //上一個(gè)點(diǎn)坐標(biāo)
            QString point2 = tableWidget->item(row - 1, 1)->data(Qt::UserRole).toString();
            //計(jì)算當(dāng)前上一個(gè)點(diǎn)和當(dāng)前點(diǎn)的旋轉(zhuǎn)角度
            angle = WebHelper::getAngle(point2, point);
        }

        //執(zhí)行移動(dòng)設(shè)備點(diǎn)函數(shù),參數(shù)帶旋轉(zhuǎn)角度
        QString js = QString("moveMarker('%1', '%2', %3)").arg(name).arg(point).arg(angle);
        runJs(js);

        //重新繪制軌跡點(diǎn)
        if (ui->cboxMoveMode->currentIndex() == 0) {
            //清空之前的軌跡點(diǎn)
            js = QString("deleteOverlay('Polyline')");
            runJs(js);

            //取出第一個(gè)點(diǎn)到當(dāng)前焦點(diǎn)所在行的點(diǎn)組成已經(jīng)走過(guò)的軌跡點(diǎn)集合重新繪制
            QStringList points;
            for (int i = 0; i <= row; ++i) {
                points << tableWidget->item(i, 1)->data(Qt::UserRole).toString();
            }

            js = QString("addPolyline('%1')").arg(points.join("|"));
            runJs(js);
        }

        //顯示當(dāng)前第幾個(gè)數(shù)據(jù)
        setInfo(angle, row + 1, count);
        tableWidget->setCurrentCell(row + 1, 0);
    } else {
        on_btnTestData_clicked();
    }
}

void frmMapGps::on_btnTestData_clicked()
{
    QTableWidget *tableWidget = getTableWidget();
    if (ui->btnTestData->text() == "模擬軌跡") {
        //限制最小數(shù)量
        if (tableWidget->rowCount() < 2) {
            return;
        }

        //第一步: 添加一個(gè)標(biāo)記
        name = ui->txtDeviceName->text().trimmed();
        if (name.isEmpty()) {
            name = "馬航MH370";
        }

        //圖片文件在可執(zhí)行文件下的config/device目錄
        QString icon = "./device/device_airplane.png";
        int size = 60;
        QString js = QString("addMarker('%1', '', '', '', 60, '%1', 0, 0, '%2', %3)").arg(name).arg(icon).arg(size);
        runJs(js);

        //第二步: 移到第一個(gè)點(diǎn)
        tableWidget->setFocus();
        tableWidget->setCurrentCell(0, 0);
        ui->btnTestData->setText("停止模擬");
        ui->tabWidget->setTabEnabled(ui->tableWidgetSource->isVisible() ? 1 : 0, false);

        //第三步: 啟動(dòng)定時(shí)器并立即執(zhí)行一次
        int index = ui->cboxMoveInterval->currentIndex();
        timer->start(ui->cboxMoveInterval->itemData(index).toInt());
        moveMarker();
    } else {
        //清空標(biāo)記
        QString js = QString("deleteMarker('%1')").arg(name);
        runJs(js);

        //停止定時(shí)器
        timer->stop();
        ui->btnTestData->setText("模擬軌跡");
        ui->tabWidget->setTabEnabled(ui->tableWidgetSource->isVisible() ? 1 : 0, true);
    }
}

void frmMapGps::on_btnCheckData_clicked()
{
    if (timer->isActive()) {
        return;
    }

    //第一步: 計(jì)算總數(shù),求平均值=實(shí)際總數(shù)/預(yù)期總數(shù)+1,預(yù)期總數(shù)>=實(shí)際總數(shù)則不用處理
    int countSource = ui->tableWidgetSource->rowCount();
    int countTarget = ui->txtPointCount->text().trimmed().toInt();
    if (countTarget >= countSource) {
        QUIHelper::showMessageBoxError("目標(biāo)點(diǎn)數(shù)不能大于等于原數(shù)據(jù)點(diǎn)數(shù)!");
        ui->txtPointCount->setFocus();
        return;
    }

    //第二步: 根據(jù)平均值挨個(gè)取出值
    QStringList points;
    int avg = countSource / countTarget + 1;
    for (int i = 0; i < countSource; i += avg) {
        QString point = ui->tableWidgetSource->item(i, 1)->data(Qt::UserRole).toString();
        points << point;
    }

    //必須加上末尾這個(gè)作為結(jié)束,如果剛好除盡則不用
    QString point = ui->tableWidgetSource->item(countSource - 1, 1)->data(Qt::UserRole).toString();
    if (points.last() != point) {
        points << point;
    }

    //第三步: 將數(shù)據(jù)重新填入篩選數(shù)據(jù)列表
    int count = points.count();
    ui->tableWidgetTarget->clearContents();
    ui->tableWidgetTarget->setRowCount(count);
    for (int i = 0; i < count; ++i) {
        addItem(ui->tableWidgetTarget, i, points.at(i));
    }

    ui->tabWidget->setCurrentIndex(1);
}

void frmMapGps::on_btnDrawData_clicked()
{
    if (routeDatas.count() == 0) {
        QUIHelper::showMessageBoxError("請(qǐng)先單擊查詢路線獲取路線的坐標(biāo)點(diǎn)集合!");
        return;
    }

    //清空之前的軌跡點(diǎn)
    runJs("deleteOverlay('Polyline')");

    //將收到的路徑點(diǎn)集合分線段繪制
    foreach (QStringList data, routeDatas) {
        QString points = data.join("|");
        QString js = QString("addPolyline('%1', '#ff0000')").arg(points);
        runJs(js);
    }
}

以上就是Qt編寫(xiě)地圖實(shí)現(xiàn)實(shí)時(shí)動(dòng)態(tài)軌跡效果的詳細(xì)內(nèi)容,更多關(guān)于Qt地圖實(shí)時(shí)動(dòng)態(tài)軌跡的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++ CTreeview的checkbox使用方法

    C++ CTreeview的checkbox使用方法

    這篇文章主要介紹了C++ CTreeview的checkbox使用方法的相關(guān)資料,需要的朋友可以參考下
    2015-06-06
  • C語(yǔ)言異常處理機(jī)制案例講解

    C語(yǔ)言異常處理機(jī)制案例講解

    這篇文章主要介紹了C語(yǔ)言異常處理機(jī)制案例講解,本文講解了異常處理機(jī)制所用的函數(shù)和具體的代碼實(shí)現(xiàn)等,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C++ STL庫(kù)應(yīng)用匯總

    C++ STL庫(kù)應(yīng)用匯總

    在本篇文章里小編給大家整理的是關(guān)于C++ STL庫(kù)應(yīng)用集合,有需要的朋友們可以參考下。
    2020-03-03
  • 解決c++?error:crosses?initialization?of?問(wèn)題

    解決c++?error:crosses?initialization?of?問(wèn)題

    最近在寫(xiě)代碼的時(shí)候,碰到了?crosses?initialization?of?...?的問(wèn)題,只因我在?switch?的某個(gè)?case?分支下定義了一個(gè)變量,于是乎便將這個(gè)問(wèn)題整理一下,需要的朋友可以參考下
    2023-03-03
  • C++字符串提取和分割的多種方法

    C++字符串提取和分割的多種方法

    在C++編程中,字符串處理是一個(gè)常見(jiàn)的任務(wù),尤其是在需要從字符串中提取特定數(shù)據(jù)時(shí),本文將詳細(xì)探討如何使用C++標(biāo)準(zhǔn)庫(kù)中的工具來(lái)提取和分割字符串,并分析不同方法的適用場(chǎng)景和優(yōu)缺點(diǎn),我們將通過(guò)多個(gè)示例代碼逐步講解,幫助讀者掌握字符串處理的技巧,需要的朋友可以參考下
    2025-03-03
  • PTA刷題C語(yǔ)言編程順序顛倒輸出實(shí)現(xiàn)

    PTA刷題C語(yǔ)言編程順序顛倒輸出實(shí)現(xiàn)

    本篇文章是在刷PTA題目是遇到的一道題,給定一句話,要求將句中所有單詞順序顛倒輸出,本文來(lái)帶你解答,有需要的朋友可以借鑒參考下
    2021-09-09
  • C語(yǔ)言舉例講解i++與++i之間的區(qū)別

    C語(yǔ)言舉例講解i++與++i之間的區(qū)別

    這篇文章主要介紹了C語(yǔ)言中i++和++i的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • qt獲取當(dāng)前時(shí)間(QDateTime、QTime、QDate)

    qt獲取當(dāng)前時(shí)間(QDateTime、QTime、QDate)

    本文主要介紹了qt獲取當(dāng)前時(shí)間(QDateTime、QTime、QDate),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • C語(yǔ)言例題講解指針與數(shù)組

    C語(yǔ)言例題講解指針與數(shù)組

    在C語(yǔ)言和C++等語(yǔ)言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲(chǔ)類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來(lái)指向若干個(gè)字符串,使字符串處理更加方便、靈活
    2022-07-07
  • C語(yǔ)言rand和srand函數(shù)使用方法介紹

    C語(yǔ)言rand和srand函數(shù)使用方法介紹

    rand()函數(shù)用來(lái)產(chǎn)生隨機(jī)數(shù),但是,rand()的內(nèi)部實(shí)現(xiàn)是用線性同余法實(shí)現(xiàn)的,是偽隨機(jī)數(shù),由于周期較長(zhǎng),因此在一定范圍內(nèi)可以看成是隨機(jī)的。srand()用來(lái)設(shè)置rand()產(chǎn)生隨機(jī)數(shù)時(shí)的隨機(jī)數(shù)種子。參數(shù)seed是整數(shù),通常可以利用time(0)或geypid(0)的返回值作為seed
    2023-02-02

最新評(píng)論

崇礼县| 墨脱县| 共和县| 石阡县| 枝江市| 武鸣县| 东方市| 两当县| 宜城市| 万盛区| 山丹县| 马关县| 酒泉市| 同德县| 洪江市| 高唐县| 灵丘县| 旬邑县| 改则县| 隆回县| 奉贤区| 浑源县| 岐山县| 苍山县| 昌图县| 陆河县| 清苑县| 十堰市| 黄浦区| 曲松县| 滨州市| 邻水| 定南县| 山西省| 闽清县| 榆中县| 镶黄旗| 新安县| 江陵县| 天等县| 米易县|