目录
系统运行截图
所使用的技术
前端
后端
Geoserver
数据库
输入一个城市,比如乌鲁木齐,就会生成一个黄色的圆环,并且直接定位到那边!
点击左下角的table内的数据,也可以定位:
这里地图界面是飞过去的,来个动态图(这里GIF针数,不太好):
这里目前提供了web版的系统,本人新电脑还没到,等到了,就准备写一个C++|Qt版本的本地GIS定位系统,目前的电脑坚持了5年了,系统重来没有恢复过,现在已经不太好使用了,等新电脑来到时候就可以出一个C++版本的本地GIS定位系统!
这里后端使用的是java的spring boot;
前端框架是vue-cli,输入框等表格使用的element ui。找到地带后黄色的圈使用的是echarts,地图在web显示使用的是leaflet。
这里前后端是分离的。前端使用axios向后端请求数据。
本地GIS使用Geoserver作为服务器。而地图素材使用全能电子地图下载器,下载的 谷歌 地图。
地理坐标等相关信息存储在mysql数据库中。
这里使用的大框架是vue-cli,控件等使用的element ui,找到地带后黄色的圈使用的是echarts,地图在web显示使用的是leaflet。
这里点一下关键的知识点,把leaflet官方的WMTS瓦块地图插件在vue cli中使用
/***
* 插件移植开始
*/
$L.TileLayer.WMTS = $L.TileLayer.extend({
defaultWmtsParams: {
service: 'WMTS',
request: 'GetTile',
version: '1.0.0',
layer: '',
style: '',
tilematrixset: '',
format: 'image/jpeg'
},
initialize: function (url, options) { // (String, Object)
this._url = url;
let lOptions= {};
let cOptions = Object.keys(options);
cOptions.forEach(element=>{
lOptions[element.toLowerCase()]=options[element];
});
let wmtsParams = $L.extend({}, this.defaultWmtsParams);
let tileSize = lOptions.tileSize || this.options.tileSize;
if (lOptions.detectRetina && $L.Browser.retina) {
wmtsParams.width = wmtsParams.height = tileSize * 2;
} else {
wmtsParams.width = wmtsParams.height = tileSize;
}
for (let i in lOptions) {
// all keys that are in defaultWmtsParams options go to WMTS params
if (wmtsParams.hasOwnProperty(i) && i!="matrixIds") {
wmtsParams[i] = lOptions[i];
}
}
this.wmtsParams = wmtsParams;
this.matrixIds = options.matrixIds||this.getDefaultMatrix();
$L.setOptions(this, options);
},
onAdd: function (map) {
this._crs = this.options.crs || map.options.crs;
$L.TileLayer.prototype.onAdd.call(this, map);
},
getTileUrl: function (coords) { // (Point, Number) -> String
let tileSize = this.options.tileSize;
let nwPoint = coords.multiplyBy(tileSize);
nwPoint.x+=1;
nwPoint.y-=1;
let sePoint = nwPoint.add(new $L.Point(tileSize, tileSize));
let zoom = this._tileZoom;
let nw = this._crs.project(this._map.unproject(nwPoint, zoom));
let se = this._crs.project(this._map.unproject(sePoint, zoom));
let tilewidth = se.x-nw.x;
let ident = this.matrixIds[zoom].identifier;
let tilematrix = this.wmtsParams.tilematrixset + ":" + ident;
let X0 = this.matrixIds[zoom].topLeftCorner.lng;
let Y0 = this.matrixIds[zoom].topLeftCorner.lat;
let tilecol=Math.floor((nw.x-X0)/tilewidth);
let tilerow=-Math.floor((nw.y-Y0)/tilewidth);
let url = $L.Util.template(this._url, {s: this._getSubdomain(coords)});
return url + $L.Util.getParamString(this.wmtsParams, url) + "&tilematrix=" + tilematrix + "&tilerow=" + tilerow +"&tilecol=" + tilecol;
},
setParams: function (params, noRedraw) {
$L.extend(this.wmtsParams, params);
if (!noRedraw) {
this.redraw();
}
return this;
},
getDefaultMatrix : function () {
/**
* the matrix3857 represents the projection
* for in the IGN WMTS for the google coordinates.
*/
let matrixIds3857 = new Array(22);
for (let i= 0; i<22; i++) {
matrixIds3857[i]= {
identifier : "" + i,
topLeftCorner : new $L.LatLng(20037508.3428,-20037508.3428)
};
}
return matrixIds3857;
}
});
$L.tileLayer.wmts = function (url, options) {
return new $L.TileLayer.WMTS(url, options);
};
/***
* 插件移植结束
*/
这里要记得导入:
import "leaflet/dist/leaflet.css"
import $L from "leaflet"
后面是使用axios向后端请求数据
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
axios.get('http://127.0.0.1:8080/ChinaCity/SingleCity?cityName=' + this.ruleForm.cityName).then((res) =>{
//console.log(res);
let emitData = {id: -1, x: -1, y: -1};
emitData.id = res.data.data.id;
emitData.x = res.data.data.x;
emitData.y = res.data.data.y;
// console.log(emitData)
this.$emit('GoGIS', emitData);
});
}
});
}
}
这里要注意跨域的问题,解决跨域的问题方法很多,在此不再再说明。
后端使用的Java的Spring boot,其他可以用浏览器,使用ORM技术,使得开发简单,具体使用的持久层框架为JPA。
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/***
* 中国城市地理坐标
*/
@Entity
@Data
@Table(name = "china_city")
public class ChinaCity {
@Id
@Column(name = "id")
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "coordX")
private Float coordX;
@Column(name = "coordY")
private Float coordY;
public ChinaCity() {
}
public ChinaCity(Integer id, String name, Float coordX, Float coordY) {
this.id = id;
this.name = name;
this.coordX = coordX;
this.coordY = coordY;
}
}
这里来试试请求
乌鲁木齐的请求:
数据从哪里来的,具体将会在数据库中提到!
这里使用了Geoserver搭建了一个中国地图的GIS服务:
这里采用的是谷歌EPSG900913的坐标系统,如何去搭建以及如何下载地图,参考本人这篇博文:
https://blog.csdn.net/qq78442761/article/details/100581622
在这里,本人就不再重复说明了!
这里的数据库数据是从百度中下载的,自己稍微修改了下:
但百度上的不太靠谱,有错别字,而且精度不太好,小数点后面的位数太少了!
然后本人写了一个C++的小程序,把这个文件,直接导入到了MySQL数据库,具体如下:
#include
#include
#include
#include
#include
#include
#include
struct CityData;
static QVector cityVec;
struct CityData{
QString name = "null";
float x = -1.0;
float y = -1.0;
};
void insertToMySQL(){
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("XXX.XXX.XXX.XXX");
db.setDatabaseName("XXXX");
db.setUserName("XXX");
db.setPassword("XXX");
if(!db.open()){
qDebug() << "The database opend failed : " << db.lastError().text();
return;
}
for(int i = 0; i < cityVec.size(); i++){
QSqlQuery query;
QString sql = QString("insert into giscoord.chinacity(name, coordX, coordY) values('%1', %2, %3)")
.arg(cityVec[i]->name).arg(cityVec[i]->x).arg(cityVec[i]->y);
if(!query.exec(sql)){
qDebug() << query.lastError().text();
}
}
qDebug() << "insert over!";
db.close();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile file("C:\\Users\\Administrator\\Desktop\\demo2.csv");
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
return -1;
}
while(!file.atEnd()){
QStringList listStr = QString::fromLocal8Bit(file.readLine()).remove("\n").split(",");
CityData *city = new CityData;
city->name = listStr[0].toUtf8();
city->x = listStr[1].toFloat();
city->y = listStr[2].toFloat();
cityVec.append(city);
}
file.close();
insertToMySQL();
for(int i = 0; i < cityVec.size(); i++){
delete cityVec[i];
}
cityVec.clear();
qDebug() << "programme over!";
return a.exec();
}