pg数据库初探-河北省-县级行政区划
之前在Cesium三维地球开发时,经常在河北上方做功能测试。无意间发现河北相对与别的省份来说,县级行政区划个数特别的多。
河北省面积约19万平方千米,至2017年未辖11地级市,47个市辖区、20个县级市、95县及6个自治县,共121个县级行政区划,是我国县级行政单位最多的省份之一!比相邻的河南及山东两省数量都多!河北中南部地区县城密集,平均20~30km左右的间距,该地区开发历史较早,地形平坦,南部又为赵国故地,历史悠久,自然县级行政区划就多了!相反,河北北部由于受地形(冀北高原山地)、及开发较晚等影响,市县很少,人口也较少!
从这两张图可以看出河北主要的县级行政区划主要集中在太行山以西的华北平原上。
综合考虑大概有这几方面的原因:
- 平原地形是基础——水土条件好,农业基础好;
- 山前大道是关键——河北省太行山前这片区域,就成了早期华北平原上最安全的地带;
- 历史文化太厚重——华北平原是中华文化发源地。
现在抛开历史和地理因素的影响,单纯的从GIS角度考虑。这么多的县级行政区划点做聚类的展示,使用PostGIS数据库中的Voronoi多边形分析。在多个点的影响下,如何对行政区进行等面积的划分。
对河北省数据进行处理,得到县级行政区划的点数据、河北省级行政区划面
(感谢遥想公瑾大神的搬运)
导入到pg数据库中->
使用ST_GeneratePoints函数将河北省面数据插入点(插入点的数量自己控制)->
使用ST_ClusterKMeans方法将这些转换后的点聚合成k簇->
使用ST_Centroid方法求出每一簇中心点->
将求出的均值中心作为ST_VoronoiPolygons方法的输入参数,可以计算出每个点映射出的Polygon面->
使用ST_Intersection将这些映射的面和初始化的Polygon做切割处理。
这一番操作就可以将河北省的面进行Voronoi多边形的切割。
CREATE TABLE hebei_points AS SELECT (ST_Dump(ST_GeneratePoints(geom, 1000))).geom AS geom FROM hebei;
CREATE TABLE hebei_pts_clustered AS SELECT geom, ST_ClusterKMeans(geom, 10) over () AS cluster FROM hebei_points;
CREATE TABLE hebei_centers AS SELECT cluster, ST_Centroid(ST_collect(geom)) AS geom FROM hebei_pts_clustered GROUP BY cluster;
CREATE TABLE hebei_voronoi AS SELECT (ST_Dump(ST_VoronoiPolygons(ST_collect(geom)))).geom AS geom FROM hebei_centers;
CREATE TABLE hebei_divided AS SELECT ST_Intersection(a.geom, b.geom) AS geom FROM hebei a CROSS JOIN hebei_voronoi b;
对数据进行地图的展示
在地图展示部分选用的是Leaflet的聚类展示。大量点数据展示,使用聚类展示更加简洁明了。
展示效果:
同时加载了切分后的面数据。
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>河北县级行政</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
<link rel="stylesheet" href="css/screen.css" />
<link rel="stylesheet" href="css/MarkerCluster.css" />
<link rel="stylesheet" href="css/MarkerCluster.Default.css" />
<script src="js-src/leaflet.markercluster-src.js"></script>
<script src="JSON/pointJson.js"></script>
<script src="JSON/hebei_divided.js"></script>
<style>
#map,html,body{
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
</body>
<script type="text/javascript">
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
//attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
});
var heBei_xian = L.tileLayer.wms("http://localhost:8088/geoserver/hebei/wms",{
layers: 'hebei:hebei_xian',
format: 'image/png',
transparent: true,
zoom: 15
});
var heBei_xian = L.tileLayer.wms("http://localhost:8088/geoserver/hebei/wms",{
layers: 'hebei:hebei_xian',
format: 'image/png',
transparent: true
});
var heBei_V = L.tileLayer.wms("http://localhost:8088/geoserver/hebei_N/wms",{
layers: 'hebei_N:hebei_divided',
format: 'image/png',
transparent: true
});
var heBei = L.tileLayer.wms("http://localhost:8088/geoserver/hebei/wms",{
layers: 'hebei:hebei_divided',
format: 'image/png',
transparent: true
});
var map = L.map('map');
map.addLayer(tiles);
map.addLayer(heBei_V);
map.addLayer(heBei_xian);
map.addLayer(heBei);
var markers = L.markerClusterGroup();
var geoJsonLayer = L.geoJson(geoJsonSample, {
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.NAME);
}
});
markers.addLayer(geoJsonLayer);
//设置加载GeoJSON面的格式
var myStyle = {
"color": "#b3b4ff",
"weight": 3,
"opacity": 0.8
};
L.geoJSON(divided, {
style: myStyle
}).addTo(map);
map.addLayer(markers);
map.fitBounds(markers.getBounds());
var baseLayers = {
"河北Vorino155切分": heBei_V,
"河北Vorino10切分": heBei,
"河北县级行政区划": heBei_xian
};
L.control.layers(baseLayers).addTo(map);
map.setView(new L.LatLng(38.827739,115.448818),6);
</script>
</html>