目录
前言
一、基础数据
1、地震基础信息
2、全国行政村
二、Java后台服务设计
1、实体类设计
2、Mapper类设计
3、控制器设计
三、前端展示
1、初始化图例
3、行政村点查询及标记
总结
地震等自然灾害目前还是依然不能进行准确的预测,当强烈度的地震发生时,其破坏性往往是极大的,给人民群众带来极大的损失。通常,在地震发生之后,应急救援部门会组织相应的救援,在救援的时候往往会根据震中位置以及地震的强度而不一样。这里不过多阐述如何进行灾害的应急救援。作为一名地理信息开发人员,我们可否基于GIS,为相关部门提供一定的信息基础和决策支持。
这里根据全国的行政村级点位数据,通过根据地震的震中位置,根据距离震中的位置,比如1公里范围,1.0公里-3.5公里,3.5公里到5公里等(这里的距离区间设置只是一种参考,实际情况下肯定要考虑其它的因素)。
本文将结合地震信息数据,基于SpringBoot框架开发,PostGis数据库作为空间数据库,Leaflet作为WebGIS可视化组件,重点讲解如何进行地震影响范围分析。如果您对WebGIS的开发有兴趣的读者有一定的参考价值。
由于是WebGIS项目,因此需要叠加影像底图、地震基础信息、全国行政村点位信息。其中影像底图采用xyz瓦片的形式组织,已经在本地离线化。而地震基础信息、全国行政点位信息采用PostGIS数据库进行存储,其数据已经由后台程序进行存储至空间数据库中。下面对这两张表和具体数据进行简要介绍。
地震基础信息的表逻辑结构如下:
表的物理sql语句如下:
-- ---------------------------- -- Table structure for biz_earthquake_info -- ---------------------------- DROP TABLE IF EXISTS "public"."biz_earthquake_info"; CREATE TABLE "public"."biz_earthquake_info" ( "id" int8 NOT NULL, "eq_time" timestamp(6) NOT NULL, "eq_lng" varchar(32) COLLATE "pg_catalog"."default" NOT NULL, "eq_lat" varchar(32) COLLATE "pg_catalog"."default" NOT NULL, "eq_depth" varchar(16) COLLATE "pg_catalog"."default" NOT NULL, "eq_level" varchar(8) COLLATE "pg_catalog"."default", "eq_location" varchar(255) COLLATE "pg_catalog"."default", "create_by" varchar(64) COLLATE "pg_catalog"."default", "create_time" timestamp(6), "update_by" varchar(64) COLLATE "pg_catalog"."default", "update_time" timestamp(6) ) ; COMMENT ON COLUMN "public"."biz_earthquake_info"."id" IS '主键'; COMMENT ON COLUMN "public"."biz_earthquake_info"."eq_time" IS '发震时间'; COMMENT ON COLUMN "public"."biz_earthquake_info"."eq_lng" IS '发震经度'; COMMENT ON COLUMN "public"."biz_earthquake_info"."eq_lat" IS '发震纬度'; COMMENT ON COLUMN "public"."biz_earthquake_info"."eq_depth" IS '震源深度,单位千米'; COMMENT ON COLUMN "public"."biz_earthquake_info"."eq_level" IS '震级'; COMMENT ON COLUMN "public"."biz_earthquake_info"."eq_location" IS '震中位置'; COMMENT ON COLUMN "public"."biz_earthquake_info"."create_by" IS '创建人'; COMMENT ON COLUMN "public"."biz_earthquake_info"."create_time" IS '创建时间'; COMMENT ON COLUMN "public"."biz_earthquake_info"."update_by" IS '修改人'; COMMENT ON COLUMN "public"."biz_earthquake_info"."update_time" IS '修改时间'; -- ---------------------------- -- Indexes structure for table biz_earthquake_info -- ---------------------------- CREATE INDEX "idx_biz_earthquake_info_depth" ON "public"."biz_earthquake_info" USING btree ( "eq_depth" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST ); CREATE INDEX "idx_biz_earthquake_info_etime" ON "public"."biz_earthquake_info" USING btree ( "eq_time" "pg_catalog"."timestamp_ops" ASC NULLS LAST ); CREATE INDEX "idx_biz_earthquake_info_qlevel" ON "public"."biz_earthquake_info" USING btree ( "eq_level" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST ); -- ---------------------------- -- Primary Key structure for table biz_earthquake_info -- ---------------------------- ALTER TABLE "public"."biz_earthquake_info" ADD CONSTRAINT "pk_biz_earthquake_info" PRIMARY KEY ("id");
全国行政村点位表逻辑结构如下所示:
行政村点位的物理sql语句如下:
-- ---------------------------- -- Table structure for biz_village -- ---------------------------- DROP TABLE IF EXISTS "public"."biz_village"; CREATE TABLE "public"."biz_village" ( "id" int8 NOT NULL, "province_name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, "city_code" varchar(16) COLLATE "pg_catalog"."default" NOT NULL, "city_name" varchar(512) COLLATE "pg_catalog"."default", "area_code" varchar(64) COLLATE "pg_catalog"."default", "area_name" varchar(512) COLLATE "pg_catalog"."default", "township_code" varchar(64) COLLATE "pg_catalog"."default", "township_name" varchar(512) COLLATE "pg_catalog"."default", "village_code" varchar(64) COLLATE "pg_catalog"."default", "village_name" varchar(512) COLLATE "pg_catalog"."default", "address" varchar(512) COLLATE "pg_catalog"."default", "type" varchar(32) COLLATE "pg_catalog"."default", "lng" varchar(24) COLLATE "pg_catalog"."default", "lat" varchar(24) COLLATE "pg_catalog"."default", "geom" "public"."geometry" ) ; COMMENT ON COLUMN "public"."biz_village"."id" IS '主键'; COMMENT ON COLUMN "public"."biz_village"."province_name" IS '省份名称'; COMMENT ON COLUMN "public"."biz_village"."city_code" IS '市级编码'; COMMENT ON COLUMN "public"."biz_village"."city_name" IS '市级名称'; COMMENT ON COLUMN "public"."biz_village"."area_code" IS '区县编码'; COMMENT ON COLUMN "public"."biz_village"."area_name" IS '区县名称'; COMMENT ON COLUMN "public"."biz_village"."township_code" IS '乡镇编码'; COMMENT ON COLUMN "public"."biz_village"."township_name" IS '乡镇名称'; COMMENT ON COLUMN "public"."biz_village"."village_code" IS '乡村编码'; COMMENT ON COLUMN "public"."biz_village"."village_name" IS '乡村名称'; COMMENT ON COLUMN "public"."biz_village"."address" IS '地址'; COMMENT ON COLUMN "public"."biz_village"."type" IS '类型'; COMMENT ON COLUMN "public"."biz_village"."lng" IS '经度'; COMMENT ON COLUMN "public"."biz_village"."lat" IS '纬度'; COMMENT ON COLUMN "public"."biz_village"."geom" IS 'geom'; -- ---------------------------- -- Indexes structure for table biz_village -- ---------------------------- CREATE INDEX "idx_biz_village_areacode" ON "public"."biz_village" USING btree ( "area_code" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST ); CREATE INDEX "idx_biz_village_city_code" ON "public"."biz_village" USING btree ( "city_code" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST ); CREATE INDEX "idx_biz_village_geom" ON "public"."biz_village" USING gist ( "geom" "public"."gist_geometry_ops_2d" ); -- ---------------------------- -- Primary Key structure for table biz_village -- ---------------------------- ALTER TABLE "public"."biz_village" ADD CONSTRAINT "pk_biz_village" PRIMARY KEY ("id");
这里的应用程序后台采用Java语言开发,开发框架使用SpringBoot,数据库访问采用Mybatis-Plus。系统整体采用MVC三层设计架构,当前展示的系统访问压力不大,采用单体架构模式。
这里仅提供地震覆盖范围查询,因此仅需定义VO视图对象即可,关键代码如下:
package com.yelang.project.extend.earthquake.domain; import java.io.Serializable; import java.math.BigDecimal; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; @NoArgsConstructor @AllArgsConstructor @Setter @Getter @ToString public class EarthquakeVillageVo implements Serializable{ private static final long serialVersionUID = -4857307169183564693L; private BigDecimal dist;//距离 private String address;//位置 private String villageName;//村庄名称 private String lng;//经度 private String lat; }
package com.yelang.project.extend.earthquake.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.yelang.project.extend.earthquake.domain.EarthquakeVillageVo; import com.yelang.project.extend.earthquake.domain.Village; /** * 乡村行政区划接口 * @author yelangking * */ public interface VillageMapper extends BaseMapper{ static final String FIND_LIST_BY_LNG_LAT = ""; @Select(FIND_LIST_BY_LNG_LAT) List findListByLngLat(@Param("pointinfo")String pointinfo); }
这里定义了数据查询的逻辑,需要注意的是,我们的数据表在设计的时候用的是geometry的字段,而且用的是4326的坐标系,4326默认的单位是度。而日常生活中使用的米作为长度单位。为了解决这个问题,我们可以将数据类型转换成geography,就可以实现按米来搜索,以上的sql就是一个实例,其中5000米表示5公里,实际项目中可以实现动态传入,这里仅演示功能。
service业务逻辑层比较简单,仅实现将控制器的参数传给mapper进行方法调用,因此忽略不写。这里将控制器的代码贴出,供参考:
/** * 震中位置5公里分析 * @param lng 经度 * @param lat 纬度 * @return */ @PostMapping("/villageinfo") @ResponseBody public AjaxResult earthinfo(String lng,String lat){ Listlist = earthquakeInfoService.findListByLngLat(lng, lat); AjaxResult ar = AjaxResult.success(); ar.put("data", list); return ar; }
前端采用我们熟悉的Leafletjs,而前端开发框架采用bootstrap和Jquery,想改成vue或者React的朋友可以自己进行相应的改造,这里暂不提供改造代码。
前端展示页面主要实现地震信息的查询,地图浏览,缩放、漫游,地震信息分析,地震信息top提示,三级范围展示、图例展示等等。这些功能的具体实例,在之前的博客中有相关的涉及,在此不再进行赘述,仅提供关键代码供参考。
图例主要用于理解地图上的标记,这里我们根据距离震中的不同距离来标识不同的行政点位。关键代码如下:
function initLegend(){ const legend = L.control.Legend({ position: "bottomleft", collapsed: false, symbolWidth: 24, opacity: 1, title:"图例", column: 2, legends: [ { label: ">3.5公里", type: "circle", radius: 6, color: "green", fillColor: "green", fillOpacity: 0.6, weight: 2 }, { label: "1-3.5公里", type: "circle", radius: 6, color: "yellow", fillColor: "yellow", fillOpacity: 0.6, weight: 2 }, { label: "小于1公里", type: "circle", radius: 6, color: "red", fillColor: "red", fillOpacity: 0.6, weight: 2 }] }).addTo(mymap); }
震中位置采用marker的方式进行标记,而影响范围则使用园来标识。
这里使用ajax的方式,由前端将地震发生的经纬度作为接口参数传递到后台,后台经过计算,将不同范围的数据返回到前端,包括经纬度位置,还有距离震中的距离、行政区名称等等。再由前端动态绘制相应的界面。关键代码如下:
$.ajax({ type: "post", url: prefix + "/villageinfo", data: {"lng":lng,"lat":lat}, success: function(rsData) { var villageData = rsData.data; for (var i = 0; i < villageData.length; i++) { var info = villageData[i]; var dist = info.dist; var strokeStyleSet = "green"; if(parseFloat(dist) > 1000 && parseFloat(dist) <= 3500){ strokeStyleSet = "yellow"; } if(parseFloat(dist) <= 1000){ strokeStyleSet = "red"; } var marker = L.circleMarker(new L.LatLng(info.lat, info.lng), {radius: 8, labelStyle: { text: info.villageName, rotation: 0, zIndex: i, strokeStyle :strokeStyleSet }}); var content = "地址:"+info.address + "
震中位置:"+name; content += "
距离震中(千米):"+info.dist; marker.bindPopup(content); marker.addTo(showLayerGroup); } mymap.fitBounds(showLayerGroup.getBounds()); }
最终实际效果如下:
以上就是本文的主要内容,本文将结合地震信息数据,基于SpringBoot框架开发,PostGis数据库作为空间数据库,Leaflet作为WebGIS可视化组件,重点讲解如何进行地震影响范围分析。行文仓促,不当之处,还请各位朋友在评论区批评指正。