Qt編寫地圖綜合應用60-覆蓋物座標和搜尋
阿新 • • 發佈:2022-03-13
一、前言
地圖應用中有時候需要開啟懸浮工具欄,使用者可以直接在地圖上繪製矩形、多邊形、圓形、線條等,於是需要提供一個函式介面,能夠獲取到使用者繪製的這些圖形形狀對應的資訊。比如座標點、圓形的中心點和半徑、所有圖形的路徑Path座標點集合,這些資訊都是以經緯度座標的形式。一般封裝的類似功能的js函式一般有三種要求,第一種傳入空值則表示找出所有覆蓋物,第二種傳入型別則找出所有該型別的覆蓋物比如矩形,第三種傳入物件名稱則找出符合該名稱的。從一堆覆蓋物中找到符合指定型別的覆蓋物,這個對於初學者是難點,可以通過map.getOverlays()拿到所有的覆蓋物,最開始我想的策略是如何拿到對應一個覆蓋物的型別,後面發現toString()可以獲取到[object Marker] [object Circle] [object Overlay]字樣,於是針對這個去過濾型別,後面發現js通用關鍵字instanceof也可以實現這個功能,比如if (overlay instanceof BMap.Circle)就可以判斷當前覆蓋物是否是圓形。
地圖模組中很多個地方都用到了將getPath函式獲取到的路徑轉換成座標點集合字串傳出去,比如發給Qt程式處理,所以封裝了一個通用的轉換函式,專門將路徑轉成字串的座標點集合,經度和緯度之間用英文逗號 , 隔開,做個座標之間用英文分號 ; 隔開,多個不同的引數值用英文豎槓 | 隔開,這個統一的規則在所有函式和互動中都通用。比如在早期的webkit核心的瀏覽器控制元件中,就無法將陣列的陣列傳出來,於是就要轉成萬能的字串組合資料。
二、功能特點
1 省市區域地圖封裝類功能特點
- 同時支援閃爍點圖、遷徙圖、區域地圖、世界地圖、儀表盤等。
- 可以設定標題、提示資訊、背景顏色、文字顏色、線條顏色、區域顏色等各種顏色。
- 可設定城市的名稱、值、經緯度 集合。
- 可設定地圖的放大倍數、是否允許滑鼠滾輪縮放。
- 內建世界地圖、全國地圖、省份地圖、地區地圖,可以精確到縣,所有地圖全部離線使用。
- 內建了各省市json資料檔案轉js檔案功能,如有資料更新自行轉換即可,支援單個檔案轉換和一鍵轉換所有檔案。
- 內建了從json檔案或者js檔案獲取該區域的所有名稱和經緯度資訊集合的功能,可以通過該方法獲取到資訊用來顯示。
- 依賴瀏覽器元件顯示地圖,提供的demo支援webkit/webengine/miniblink/ie 多種方式載入網頁。
- 採用miniblink瀏覽器核心打通了Qt5.6及後續版本+mingw編譯器缺少瀏覽器模組的遺憾,使得整個專案支援所有Qt版本,親測4.7到6.2等任意版本。
- 閃爍點遷徙圖等設定的點支援單獨設定顏色。
- 提供介面直接獲取點選的點相關資訊,方便程式聯動處理。
- 拓展性極強,可以依葫蘆畫瓢自行增加各種精美的echarts元件,做出牛逼的效果。
- 內建的儀表盤元件提供互動功能,demo演示中包含了對應的程式碼。
- 函式介面友好和統一,使用簡單方便,就一個類。
- 支援任意Qt版本、任意系統、任意編譯器。
2 百度地圖封裝類功能特點
- 同時支援線上地圖和離線地圖兩種模式。
- 同時支援webkit核心、webengine核心、miniblink核心、IE核心。
- 支援設定多個標註點,資訊包括名稱、地址、經緯度。
- 可設定地圖是否可單擊、拖動、滑鼠滾輪縮放。
- 可設定協議版本、祕鑰、主題樣式、中心座標、中心城市、地理編碼位置等。
- 可設定地圖縮放比例和級別,縮圖、比例尺、路況資訊等控制元件的可見。
- 支援地圖互動,比如滑鼠按下獲取對應位置的經緯度。
- 支援查詢路線,可設定起點位置、終點位置、路線模式、路線方式、路線方案(最少時間、最少換乘、最少步行、不乘地鐵、最短距離、避開高速)。
- 可顯示點線面工具,可直接在地圖上劃線、點、矩形、圓形等。
- 可設定行政區劃,指定某個城市區域繪製圖層,線上地圖自動輸出行政區劃邊界點集合到js檔案給離線地圖使用。
- 可靜態或者動態新增多個覆蓋物。支援點、折線、多邊形、矩形、圓形、弧線、點聚合等。
- 提供函式介面處理經緯度解析成地址和地址解析成經緯度座標。
- 提供的demo直接可以單獨選點執行對應的處理比如路線查詢。
- 可以拿到路線查詢到的點座標資訊集合,比如用於機器人座標導航等。
- 封裝了豐富的函式比如刪除指定點和所有點,刪除指定覆蓋物和所有覆蓋物等。
- 標註點彈框資訊可以自定義內容,標準html格式。
- 標註點單擊事件可選 0-不處理 1-自己彈框 2-傳送訊號。
- 標註點可設定動畫效果 0-不處理 1-跳動 2-墜落
- 標註點可設定本地圖片檔案等。
- 函式介面友好和統一,使用簡單方便,就一個類。
- 支援js動態互動新增點、刪除點、清空點、重置點,不需要重新整理頁面。
- 支援任意Qt版本、任意系統、任意編譯器。
3 離線地圖下載類功能特點
- 多執行緒同步下載多級別瓦片地圖,不卡介面。
- 內建多個離線地圖下載請求地址,自動隨機選擇一個傳送請求。
- 下載地圖型別同時支援街道圖和衛星圖。
- 自動計算可視區域或者行政區域的下載瓦片數量。
- 下載的級別可以自定義範圍和選擇。
- 每個瓦片下載完成都發送訊號通知,引數包括下載用時。
- 可設定下載最大超時時間,超過了則丟棄跳到下一個下載任務。
- 實時顯示下載進度,以及當前級別已經下載的瓦片數和總瓦片數。
- 下載過程中可以停止下載,下載完成自動統計總用時。
- 內建經緯度和螢幕座標互相轉換函式。
- 目前支援百度地圖,其他地圖比如谷歌地圖、騰訊地圖、高德地圖可以定製。
- 函式介面友好和統一,使用簡單方便,就一個類。
- 支援任意Qt版本、任意系統、任意編譯器。
4 省市輪廓下載類功能特點
- 定時器排隊下載省市輪廓圖點座標集合儲存到JS檔案。
- 支援一個行政區域多個不規則區域下載。
- 自動計算行政區域的下載輪廓數量。
- 可精確選擇省份、市區、縣城,也可直接輸入行政區域的名稱。
- 可以設定下載間隔、隨時開始下載和停止下載。
- 提供編輯邊界功能,可以直接在地圖上編輯好不規則區域的點集合,然後獲取邊界點集合資料,這個可以用來自己繪製區域拿到資料,比如某個鄉鎮甚至某個小區的行政區域資料,很牛逼。
三、體驗地址
- 體驗地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取碼:o05q 檔名:bin_map.zip
- 國內站點:https://gitee.com/feiyangqingyun
- 國際站點:https://github.com/feiyangqingyun
- 個人主頁:https://blog.csdn.net/feiyangqingyun
- 知乎主頁:https://www.zhihu.com/people/feiyangqingyun/
四、效果圖
五、相關程式碼
void MapBaiDu::addLocalSearch(QStringList &list)
{
//全域性搜尋物件 結果可選顯示在地圖中還是非同步通知
#if 1
list << QString(" var searchOptions = {renderOptions:{map: map}};");
#else
list << QString(" var searchOptions = {");
list << QString(" onSearchComplete: function(results) {");
list << QString(" if (local.getStatus() != BMAP_STATUS_SUCCESS) {");
list << QString(" return;");
list << QString(" }");
list << QString(" var result = [];");
list << QString(" var count = results.getCurrentNumPois();");
list << QString(" for (var i = 0; i < count; ++i) {");
list << QString(" var poi = results.getPoi(i);");
list << QString(" var point = poi.point.lng + ',' + poi.point.lat;");
list << QString(" result.push(point + ';' + poi.title + ';' + poi.address + ';' + poi.url);");
list << QString(" }");
list << QString(" receiveData('searchresult', result.join('|'));");
list << QString(" }");
list << QString(" };");
#endif
list << QString(" var local = new %1.LocalSearch(map, searchOptions);").arg(mapFlag);
list << QString(" local.setSearchCompleteCallback(function(results) {");
list << QString(" ");
list << QString(" });");
//通用搜索方法
//text: 搜尋的關鍵字 支援多個可以用 | 隔開
list << QString(" function search(text) {");
list << QString(" var texts = text.split('|');");
list << QString(" local.search(texts);");
list << QString(" }");
//矩形區域搜尋
list << QString(" function searchInBounds(text, start, end) {");
list << QString(" var texts = text.split('|');");
list << QString(" if (!start || !end) {");
list << QString(" local.searchInBounds(texts, map.getBounds());");
list << QString(" return;");
list << QString(" }");
list << QString(" var bs = new %1.Bounds(getPoint(start), getPoint(end));").arg(mapFlag);
list << QString(" local.searchInBounds(texts, bs);");
list << QString(" }");
//圓形區域搜尋
list << QString(" function searchNearby(text, center, radius) {");
list << QString(" var texts = text.split('|');");
list << QString(" local.searchNearby(texts, getPoint(center), radius);");
list << QString(" }");
}
void MapBaiDu::getOverlayInfo(QStringList &list)
{
//獲取覆蓋物資訊 type = Marker Polyline 等
list << QString(" function getOverlayInfo(type) {");
list << QString(" var allOverlay = map.getOverlays();");
list << QString(" var count = allOverlay.length;");
list << QString(" for (var i = 0; i < count; ++i) {");
list << QString(" var overlay = allOverlay[i];");
//過濾不可見的
list << QString(" if (!overlay.isVisible()) {");
list << QString(" continue;");
list << QString(" }");
//拿到覆蓋物型別對應字串 toString() 以後的值是 [object Marker] [object Circle] [object Overlay]
list << QString(" var objType = overlay.toString();");
list << QString(" objType = objType.substr(8, objType.length - 9);");
//過濾標註點和懸停工具
list << QString(" if (objType == 'Marker' || objType == 'Overlay') {");
list << QString(" continue;");
list << QString(" }");
//如果指定了覆蓋物型別則過濾掉不符合型別的
list << QString(" if (type.length > 0 && objType != type) {");
list << QString(" continue;");
list << QString(" }");
list << QString(" var path = overlay.getPath();");
list << QString(" var points = getPathPoints(path);");
//不同型別的有不同的資訊 下面演示的是另外一種過濾方法 instanceof
list << QString(" var info = objType;");
list << QString(" if (overlay instanceof %1.Circle) {").arg(mapFlag);
list << QString(" var center = overlay.getCenter();");
list << QString(" var point = center.lng + ',' + center.lat;");
list << QString(" var radius = overlay.getRadius();");
list << QString(" info = objType + '|' + point + '|' + radius + '|' + points.join(';')");
list << QString(" } else {");
list << QString(" info = objType + '|' + points.join(';')");
list << QString(" }");
list << QString(" receiveData('overlayinfo', info);");
list << QString(" }");
list << QString(" }");
}