一、前言
Qt的瀏覽器控件的交互機制非常方便,所以在在線地圖的時候可以對每個區域的經緯度座標集合發給Qt程序,讓他去存儲到文件,在實際的測試過程中,發現有部分地圖有多個封閉的曲線的,比如散落的島嶼和飛地,這些可不能遺漏呢,所以存儲經緯度座標信息,要按照數組的形式存儲,最開始做的時候按照一個字符串集合存儲的,後面發現部分地方少了甚至不規則,原來是有多個曲線集合,解析的時候根據數組來實例化不規則線條的類即可。
在線地圖默認只能精確到縣城,如果還要更精確的話,就需要自己手動調整邊界點拉動好,然後主動獲取當前邊界點的經緯度座標集合,存儲起來,這就需要一開始設定一個基本的邊界點的形狀,開啓允許編輯屬性,然後自行去調整好位置,最後單擊獲取邊界點座標,保存文件即可,如果需要很多的鄉鎮的輪廓圖,那隻能很有耐心的慢慢的調整獲取咯,當然這種無聊的沒有技術含量的事情也可以交給小姑娘去做啦。
之前做獲取邊界點的時候,主要採用的是在線地圖的方式,因爲在線地圖中直接內置了函數可以根據行政區域的名稱來自動獲取邊界,其實這些邊界就是一些點座標集合連接起來的平滑線,然後形成的輪廓圖,這種方式有個弊端就是隻能在線的時候使用,而我們大部分的應用場景應該是離線的,甚至很多設備永遠是離線的,根本不可能去聯網獲取信息,但是又想要這個各省市區域的輪廓圖怎辦呢,只能事先拿到下載到這些需要的輪廓圖文件纔行,這些文件存儲的就是經緯度座標集合,在離線地圖中只需要定義不規則線條繪製傳入這些經緯度座標集合即可。
二、功能特點
- 定時器排隊下載省市輪廓圖點座標集合存儲到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 frmMapBoundary::getBoundary()
{
//判斷當前索引對應的省會的複選框有沒有勾選,沒有勾選則找到下一個勾選的
int count = names.count();
while (indexMain < count - 1 && !cks.at(indexMain)->isChecked()) {
indexMain++;
indexSub = 0;
}
//到了最後一個省會的索引,停止定時器
if (indexMain == count || !cks.at(indexMain)->isChecked()) {
on_btnStop_clicked();
return;
}
//下載到省會的最後一個縣,索引自動跳到下一個省會
QStringList list = names.at(indexMain);
if (indexSub == list.count()) {
indexMain++;
indexSub = 0;
getBoundary();
return;
}
QString name = list.at(indexSub);
addBoundary(name);
indexSub++;
//更新進度條
int value = bars.at(indexMain)->value();
bars.at(indexMain)->setValue(value + 1);
ui->txtTip->setText(name);
}
void frmMapBoundary::addBoundary()
{
//開啓編輯狀態
QString name = ui->cboxName->currentText();
addBoundary(name, true);
}
void frmMapBoundary::addBoundary(const QString &name, bool edit)
{
currentName = name;
QString js = QString("addBoundary('%1', true, %2)").arg(name).arg(edit ? "true" : "false");
runJs(js);
}
void frmMapBoundary::saveBoundary(const QString &fileName, const QVariant &data)
{
//傳過來的是行政區劃的邊界點座標集合,存儲到js文件
//可能會有多個數據,比如臺灣的金門島,都是獨立的區域形狀,存入數組
QStringList boundarys;
QStringList list = data.toString().split("|");
foreach (QString points, list) {
boundarys << QString("{'points': '%1'}").arg(points);
}
//最終js文件內容數據
QString boundary = QString("var boundarys = [%1]").arg(boundarys.join(", "));
QFile file(fileName);
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QTextStream out(&file);
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
out.setCodec("utf-8");
#endif
out << boundary;
}
}
void frmMapBoundary::clear()
{
//先進度條全部置爲0
indexMain = indexSub = 0;
ui->txtTip->setText("等待下載...");
foreach (QProgressBar *bar, bars) {
bar->setValue(0);
}
}
void frmMapBoundary::receiveDataFromJs(const QString &type, const QVariant &data)
{
if (data.isNull()) {
return;
}
//qDebug() << "frmMapBoundary" << type << data;
if (type == "boundary") {
//開啓了定時器則按照目錄存放
QString fileName = QString("%1/citypointjs/%2.js").arg(ConfigPath).arg(currentName);
if (timerDown->isActive()) {
QString provinceName = cks.at(indexMain)->text();
QString path = QString("%1/citypointjs/%2").arg(ConfigPath).arg(provinceName);
QDir dir(path);
if (!dir.exists()) {
dir.mkdir(path);
}
fileName = QString("%1/%2.js").arg(path).arg(currentName);
}
saveBoundary(fileName, data);
} else if (type == "newboundary") {
//拖動可編輯的邊界以後讀取到的邊界點
QString fileName = ui->txtFileName->text().trimmed();
fileName = QString("%1/citypointjs/%2.js").arg(ConfigPath).arg(fileName);
saveBoundary(fileName, data);
}
}