Qt/C++路徑軌跡回放/回放每個點訊號/回放結束訊號/拿到移動的座標點經緯度

飞扬青云發表於2024-10-24

一、前言說明

在使用百度地圖的路書功能中,並沒有提供移動的訊號以及移動結束的訊號,但是很多時候都期望拿到移動的哪裡了以及移動結束的訊號,以便做出對應的處理,比如結束後需要觸發一些對應的操作。經過搜尋發現很多人都有這個需求,需要在js檔案中加上一點程式碼才行,也就是在start開始的時候傳入兩個回撥函式movestep和moveend,在js檔案對應移動標註點的地方觸發這個回撥,在移動到末尾的時候再去觸發moveend訊號,這個回撥引數中可以帶上對應的物件以及座標經緯度值。為什麼還要帶上物件或者唯一標識呢,因為可能有多個移動的點,需要這個唯一標識區分是誰發出來的。還有個注意點是,既然是改動過的js檔案了,那肯定不能再引用網路地址上的那個js檔案,就需要引用本地的改過的js檔案。

關於路書功能,每個地圖核心都有自己獨特的實現方法和訊號,比如高德地圖提供的是moving訊號,引數是走過的路徑,並沒有當前路徑點,需要從這個路徑集合中取末尾這個才是當前路徑點,也可以透過呼叫標註點marker.getPosition方法來獲取。天地圖只提供了passOneNode事件,每移動一個點就觸發一次,帶了三個引數lnglat表示當前經緯度,index表示當前點索引, length表示當前路徑點的長度數量,那怎麼判斷移動結束了呢,只需要判斷index和length相等就行。騰訊地圖就比較友善,兩個事件都提供了,而且引數也是能拿到經緯度值。

二、功能特點

2.1 地圖功能

  1. 支援多種地圖核心,預設採用百度地圖,可選高德地圖、天地圖、騰訊地圖、谷歌地圖等。
  2. 同時支援線上地圖和離線地圖兩種模式,離線地圖方便在不聯網的場景中使用。
  3. 支援各種地圖控制元件的啟用,比如地圖導航、地圖型別、縮圖、比例尺、全景導航、實時路況、繪圖工具、結果皮膚等。
  4. 支援多種地圖功能的動態啟用禁用,比如地圖拖曳、鍵盤操作、滾輪縮放、雙擊放大、連續縮放、地圖測距等。
  5. 提供眾多js函式介面用於互動,引數極其豐富,能夠想到的應用場景需求都有。
  6. 統一的訊號槽機制,地圖中的結果統一訊號傳送出去,收到後根據type型別區分。
  7. 支援地圖互動,比如滑鼠按下獲取對應位置的經緯度。單擊標註點彈出對應點的資訊。
  8. 支援新增標註、刪除標註、移動標註、清空標註。
  9. 標註點可以指定圖示圖片和尺寸,支援gif動圖,支援指定以圖片中心對齊還是底部中心對齊。可以設定旋轉角度,帶富文字提示資訊。
  10. 標註點事件支援單擊發訊號通知和自己彈框顯示資訊。
  11. 提供地址轉座標和座標轉地址介面。
  12. 支援各種圖形繪製,包括折線圖、多邊形、矩形、圓形、弧線等。
  13. 可顯示懸浮的繪圖工具欄,直接在地圖上劃線、標註點、矩形、圓形等。
  14. 支援各種區域搜尋,比如矩形區域、圓形區域,可以按照關鍵字匹配將搜尋結果顯示在地圖中。
  15. 可動態新增離線的行政區邊界點資料。可以搜尋行政區劃並獲取該區域的邊界點資料。資料可以儲存到檔案以便離線使用。
  16. 支援點聚合功能,多個小標註點合併到一個大標註點,防止點密集導致互動不友好。
  17. 可以新增海量點,每個點都可以單擊獲取對應座標和資訊。
  18. 所有的覆蓋物資訊比如標註點、矩形、多邊形、折線圖等,都可以主動獲取對應的資訊比如座標點和路徑等。
  19. 支援路徑規劃,支援公交路線、自駕路線、步行路線、騎行路線,不同查詢支援不同策略,可選最少時間、最少換乘、不走高架等。
  20. 路徑規劃結果可以顯示在地圖中,也可以獲取到路徑點座標集合。這個資料可以儲存到檔案,以便發給機器人或者無人機做導航用來軌跡移動。
  21. 可以設定不同的地圖檢視比如街道圖、衛星圖、混合圖。
  22. 可以設定不同的樣式,比如午夜藍、青草綠等樣式風格。
  23. 可以設定地圖的旋轉角度和傾斜角度。
  24. 提供經緯度座標糾偏轉換功能,比如傳入的GPS座標需要轉換到百度地圖座標或者高德地圖座標。各種座標系轉換全部離線函式,支援地球座標系WGS-84、火星座標系GCJ-02、百度座標系BD-09之間的互相轉換,涵蓋了各種地圖的座標系。
  25. 提供動態軌跡點移動功能,按照給定的經緯度座標集合平滑移動。
  26. 同時支援qwidget和qml,支援編譯到安卓系統執行。

2.2 其他功能

  1. 提供離線地圖下載模組,可以選擇不同的地圖核心比如百度地圖或者谷歌地圖,不同的地圖型別比如下載街道圖還是衛星圖,不同的地圖層級,多執行緒極速下載。
  2. 表格行實時顯示對應的瓦片下載進度,有下載超時時間,重試次數,每個瓦片下載完成都傳送訊號通知,引數包括下載用時。
  3. 提供省市輪廓圖下載模組,自動下載各個地區的輪廓圖,儲存到指令碼檔案或者文字檔案。
  4. 支援手動調整不同區域的輪廓邊界,調整後可以主動獲取調整後的邊界點集合。
  5. 提供動態點位示例,手動在地圖上選點並新增標註,附帶自定義的資訊比如速度和時間等。
  6. 提供海量點位示例,批次新增標註點、點聚合、海量點。用於測試環境中支援的最大點位效能。
  7. 提供動態軌跡示例,在地圖上滑鼠按下選擇起點和終點後,查詢路線,獲取路徑軌跡點,模擬軌跡平滑移動。可以篩選資料將過多的路徑點篩選到設定的點數。
  8. 提供軌跡回放示例,按照指定的軌跡點列表回放,也可以匯入軌跡點資料進行回放。同時支援在街道圖、衛星圖、混合圖中回放軌跡。
  9. 提供省市區域地圖示例,採用echart元件,同時支援閃爍點圖、遷徙圖、區域地圖、世界地圖、儀表盤等。可以設定標題、提示資訊、背景顏色、文字顏色、線條顏色、區域顏色等各種顏色。
  10. 省市區域地圖示例,內建世界地圖、全國地圖、省份地圖、地區地圖,可以精確到縣,所有地圖全部離線使用。可設定城市的名稱、值、經緯度集合。
  11. 內建通用瀏覽器元件,同時支援webkit/webengine/miniblink等核心。提供網頁控制元件示例,演示開啟網頁和本地網頁檔案。
  12. 支援任意Qt版本、任意系統、任意編譯器。

三、相關連結

  1. 體驗地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取碼:o05q 檔名:bin_map.zip
  2. 國內站點:https://gitee.com/feiyangqingyun
  3. 國際站點:https://github.com/feiyangqingyun

四、效果圖

五、相關程式碼

void MapObjFun::addLine(QStringList &html)
{
    //新增軌跡線條/將移動物件的線條設定成新建的線條/引數point表示首個點
    html << QString("  function addLine(flag, point, color, weight, opacity, arrow) {");
    html << QString("    deletePolyline(flag);");
    html << QString("    initPolyline(flag, point, color, weight, opacity, arrow);");
    html << QString("    var polyline = findOverlay(polylines, flag);");
    html << QString("    var index = findMove(flag);");
    html << QString("    if (index >= 0) {");
    html << QString("      moves[index].line = polyline;");
    html << QString("    }");
    html << QString("  }");
}

void MapObjFun::moveEvent(QStringList &html)
{
    //移動每步回撥
    html << QString("  function moveStep(obj, pos) {");
    html << QString("    var point = getPointString(pos);");
    html << QString("    receiveData('movestep', obj.flag + '|' + point);");
    //檢視當前移動物件是否存在折線屬性/存在則表示當前需要跟隨繪製線條
    html << QString("    var line = obj.line;");
    html << QString("    if (line) {");
    html << QString("      addDataByLine(line, point);");
    html << QString("    }");
    html << QString("  }");

    //移動結束回撥
    html << QString("  function moveEnd(obj) {");
    html << QString("    receiveData('moveend', obj.flag);");
    html << QString("  }");
}

void MapObjFun::findMove(QStringList &html)
{
    //查詢移動物件
    html << QString("  function findMove(flag) {");
    html << QString("    for (var i = 0; i < moves.length; ++i) {");
    html << QString("      if (flag == moves[i].flag) {");
    html << QString("        return i;");
    html << QString("      }");
    html << QString("    }");
    html << QString("    return -1;");
    html << QString("  }");

    //設定移動物件
    html << QString("  function setMove(move, flag, clear) {");
    html << QString("    move.flag = flag;");
    html << QString("    move.clear = clear;");
    html << QString("    var index = findMove(flag);");
    html << QString("    if (index >= 0) {");
    html << QString("      deleteMoveMarker(flag);");
    html << QString("      moves[index] = move;");
    html << QString("    } else {");
    html << QString("      moves.push(move);");
    html << QString("    }");
    html << QString("  }");
}

void MapObjFun::doMove(QStringList &html)
{
    QString start = "start";
    QString pause = "pause";
    QString next = "start";
    QString stop = "stop";
    QString show = "show()";
    if (mapCore == MapCore_GaoDe) {
        start = "moveAlong";
        pause = "pauseMove";
        next = "resumeMove";
        stop = "stopMove";
    } else if (mapCore == MapCore_TengXun) {
        start = "moveAlong";
        pause = "pauseMove";
        next = "resumeMove";
        stop = "stopMove";
        show = "setVisible(true)";
    } else if (mapCore == MapCore_Google) {
        start = "moveAlong";
        pause = "pauseMove";
        next = "resumeMove";
        stop = "stopMove";
        show = "setVisible(true)";
    }

    //執行移動動作/停止移動後主動刪除對應的標註/不同地圖核心開始的方法不一樣
    html << QString("  function doMove(flag, action) {");
    html << QString("    var index = findMove(flag);");
    html << QString("    if (index < 0) {return}");
    html << QString("    var move = moves[index];");
    html << QString("    if (action == 'start') {");
    html << QString("      if (move.data) {");
    html << QString("        move.%1;").arg(show);
    html << QString("        move.%1(move.data, move.option);").arg(start);
    html << QString("      } else {");
    html << QString("        move.%1(moveStep, moveEnd);").arg(start);
    html << QString("      }");
    html << QString("    } else if (action == 'pause') {");
    html << QString("      move.%1();").arg(pause);
    html << QString("    } else if (action == 'next') {");
    html << QString("      move.%1(moveStep, moveEnd);").arg(next);
    html << QString("    } else if (action == 'stop') {");
    html << QString("      move.%1();").arg(stop);
    html << QString("      if (move.clear) {");
    html << QString("        deleteMoveMarker(flag);");
    html << QString("        deletePolyline(flag);");
    html << QString("      }");
    html << QString("    }");
    html << QString("  }");

    //開始移動/暫停移動/繼續移動/停止移動
    html << QString("  function moveStart(flag) {");
    html << QString("    doMove(flag, 'start');");
    html << QString("  }");
    html << QString("  function movePause(flag) {");
    html << QString("    doMove(flag, 'pause');");
    html << QString("  }");
    html << QString("  function moveNext(flag) {");
    html << QString("    doMove(flag, 'next');");
    html << QString("  }");
    html << QString("  function moveStop(flag) {");
    html << QString("    doMove(flag, 'stop');");
    html << QString("  }");
}

相關文章