一、前言
之前做擷取邊界點的時候,主要采用的是線上地圖的方式,因為線上地圖中直接内置了函數可以根據行政區域的名稱來自動擷取邊界,其實這些邊界就是一些點坐标集合連接配接起來的平滑線,然後形成的輪廓圖,這種方式有個弊端就是隻能線上的時候使用,而我們大部分的應用場景應該是離線的,甚至很多裝置永遠是離線的,根本不可能去聯網擷取資訊,但是又想要這個各省市區域的輪廓圖怎辦呢,隻能事先拿到下載下傳到這些需要的輪廓圖檔案才行,這些檔案存儲的就是經緯度坐标集合,在離線地圖中隻需要定義不規則線條繪制傳入這些經緯度坐标集合即可。
Qt的浏覽器控件的互動機制非常友善,是以在線上地圖的時候可以對每個區域的經緯度坐标集合發給Qt程式,讓他去存儲到檔案,在實際的測試過程中,發現有部分地圖有多個封閉的曲線的,比如散落的島嶼,這些可不能遺漏呢,是以存儲經緯度坐标資訊,要按照數組的形式存儲,最開始做的時候按照一個字元串集合存儲的,後面發現部分地方少了甚至不規則,原來是有多個曲線集合,解析的時候根據數組來執行個體化不規則線條的類即可。
線上地圖預設隻能精确到縣城,如果還要更精确的話,就需要自己手動調整邊界點拉動好,然後主動擷取目前邊界點的經緯度坐标集合,存儲起來,這就需要一開始設定一個基本的邊界點的形狀,開啟允許編輯屬性,然後自行去調整好位置,最後單擊擷取邊界點坐标,儲存檔案即可,如果需要很多的鄉鎮的輪廓圖,那隻能很有耐心的慢慢的調整擷取咯,當然這種無聊的沒有技術含量的事情也可以交給小姑娘去做啦。
二、功能特點
- 同時支援線上地圖和離線地圖兩種模式。
- 同時支援webkit核心、webengine核心、IE核心。
- 支援設定多個标注點,資訊包括名稱、位址、經緯度。
- 可設定地圖是否可單擊、拖動、滑鼠滾輪縮放。
- 可設定協定版本、秘鑰、主題樣式、中心坐标、中心城市、地理編碼位置等。
- 可設定地圖縮放比例和級别,縮略圖、比例尺、路況資訊等控件的可見。
- 支援地圖互動,比如滑鼠按下擷取對應位置的經緯度。
- 支援查詢路線,可設定起點位置、終點位置、路線模式、路線方式、路線方案(最少時間、最少換乘、最少步行、不乘地鐵、最短距離、避開高速)。
- 可顯示點線面工具,可直接在地圖上劃線、點、矩形、圓形等。
- 可設定行政區劃,指定某個城市區域繪制圖層,線上地圖自動輸出行政區劃邊界點集合到js檔案給離線地圖使用。
- 可靜态或者動态添加多個覆寫物。支援點、折線、多邊形、矩形、圓形、弧線、點聚合等。
- 函數接口友好和統一,使用簡單友善,就一個類。
- 支援js動态互動添加點、删除點、清空點、重置點,不需要重新整理頁面。
- 支援任意Qt版本、任意系統、任意編譯器。
三、體驗位址
- 國内站點: https://gitee.com/feiyangqingyun
- 國際站點: https://github.com/feiyangqingyun
- 個人首頁: https://blog.csdn.net/feiyangqingyun
- 知乎首頁: https://www.zhihu.com/people/feiyangqingyun/
四、效果圖

五、相關代碼
QStringList MapBoundary::getResult(const QByteArray &data, quint8 type, const QString &provinceName, const QString &cityName)
{
//處理資料
QStringList result;
if (type == 1 && provinceName.isEmpty()) {
return result;
} else if (type == 2 && (provinceName.isEmpty() || cityName.isEmpty())) {
return result;
}
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
//采用qt内置的json方法解析
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error == QJsonParseError::NoError) {
QJsonObject rootObj = jsonDoc.object();
//qDebug() << rootObj.keys();
if (rootObj.contains("province")) {
QJsonArray province = rootObj.value("province").toArray();
for (int i = 0; i < province.count(); i++) {
QJsonObject subObj = province.at(i).toObject();
if (subObj.contains("name")) {
QString name = subObj.value("name").toString();
if (type == 0) {
result << name;
} else if (type == 1) {
if (name == provinceName) {
QJsonArray city = subObj.value("city").toArray();
for (int j = 0; j < city.count(); j++) {
QJsonObject nodeObj = city.at(j).toObject();
if (nodeObj.contains("cityname")) {
QString cityname = nodeObj.value("cityname").toString();
result << cityname;
}
}
//退出查找
break;
}
} else if (type == 2) {
if (name == provinceName) {
bool exist = false;
QJsonArray city = subObj.value("city").toArray();
for (int j = 0; j < city.count(); j++) {
QJsonObject nodeObj = city.at(j).toObject();
if (nodeObj.contains("cityname")) {
QString cityname = nodeObj.value("cityname").toString();
if (cityname == cityName) {
QJsonArray countyname = nodeObj.value("countyname").toArray();
for (int k = 0; k < countyname.count(); k++) {
QString county = countyname.at(k).toString();
//資料中帶了縣城所在鎮,要過濾
if (!county.endsWith("鎮")) {
result << county;
}
}
exist = true;
break;
}
}
}
//退出查找
if (exist) {
break;
}
}
}
}
}
}
}
#else
//采用字元串分割方法解析
QString temp = data;
QStringList provice = temp.split("\n");
QString name, cityname;
for (int i = 0; i < provice.count(); i++) {
QString value = provice.at(i);
if (value.contains("\"name\"")) {
name = getValue(value);
if (type == 0) {
result << name;
}
} else if (value.contains("\"cityname\"")) {
cityname = getValue(value);
bool exist = false;
if (name == provinceName) {
exist = true;
}
if (type == 1) {
//檢測到是目前省份則來提取市區
if (exist) {
result << cityname;
//當是新的省份以後立即退出
if (name != provinceName) {
break;
}
}
}
} else if (value.contains("\"countyname\"")) {
if (type == 2) {
if (name == provinceName && cityname == cityName) {
QString county = getValue(value);
county = county.mid(1, county.length() - 2);
QStringList countys = county.split(" ");
foreach (QString county, countys) {
//資料中帶了縣城所在鎮,要過濾
if (!county.endsWith("鎮")) {
result << county;
}
}
break;
}
}
}
}
#endif
return result;
}