菜鸟AI - 让提示词生成更简单! 全站导航 全站导航
AI工具安装 新手教程 进阶教程 辅助资源 AI提示词 热点资讯 技术资讯 产业资讯 内容生成 模型技术 AI信息库

已有账号?

首页 > AI教程 > SpringBoot+PostGIS震中影响范围可视化实战评测
进阶教程

SpringBoot+PostGIS震中影响范围可视化实战评测

2026-05-30
阅读 0
热度 0
作者 菜鸟AI编辑部
摘要

摘要

基于SpringBoot与PostGIS,利用全国行政村点位数据,按震中距离划分同心圆影响圈,实现震中

地震这种自然灾害,说实话,到现在还是没法准确预测。一旦强震真来了,破坏力摆在那里,损失往往非常惨重。通常,震后救援部门会迅速响应,但具体怎么救,很大程度上取决于震中在哪儿、震级有多大——这些都是救援方案的核心变量。关于具体如何实施救援,这里就不展开了。今天我们聊点更实际的:作为GIS开发人员,能不能利用我们的技术,给相关部门提供一些信息基础,帮他们做决策? 思路是这样的:我们有全国行政村级点位数据,然后根据地震的震中位置,按距离划几个圈——比如1公里以内、1到3.5公里、3.5到5公里(这几个区间只是参考,实际用的时候肯定要结合更多因素)。本文就沿着这个思路,结合地震信息,基于SpringBoot + PostGIS + Leaflet这套技术栈,重点演示如何做地震影响范围分析。如果你对WebGIS开发感兴趣,这应该有点参考价值。 ## 一、基础数据 既然是WebGIS项目,影像底图得先安排上。我们用的是本地离线化的XYZ瓦片。地震基础信息和全国行政村点位数据则存在PostGIS里,程序后台已经提前灌进去了。下面简单看看这两张表的逻辑。 ### 1、地震基础信息 地震信息表的逻辑结构: 对应的建表SQL: ```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 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 ALTER TABLE "public"."biz_earthquake_info" ADD CONSTRAINT "pk_biz_earthquake_info" PRIMARY KEY ("id"); ``` ### 2、全国行政村 行政村点位表的逻辑结构: 建表SQL: ```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 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 ALTER TABLE "public"."biz_village" ADD CONSTRAINT "pk_biz_village" PRIMARY KEY ("id"); ``` ## 二、Ja va后台服务设计 后台用Ja va开发,框架选了SpringBoot,ORM用的MyBatis-Plus。整体是标准的MVC三层架构。这套系统访问压力不大,所以直接上单体架构,够用。 ### 1、实体类设计 这次只需要做地震覆盖范围查询,因此定义个VO视图对象就够了。关键代码: ```ja va package com.yelang.project.extend.earthquake.domain; import ja va.io.Serializable; import ja va.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; //纬度 } ``` ### 2、Mapper类设计 ```ja va package com.yelang.project.extend.earthquake.mapper; import ja va.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; public interface VillageMapper extends BaseMapper { static final String FIND_LIST_BY_LNG_LAT = "<script>" + "with bp as ( select st_geomfromtext(${pointinfo},4326) :: geography tp ) " + "select st_distance(t.geom :: geography, bp.tp) dist, t.address, t.village_name, t.lng, t.lat " + "from biz_village t, bp where st_dwithin(t.geom :: geography, bp.tp, 5000 ) order by dist " + "</script>"; @Select(FIND_LIST_BY_LNG_LAT) List findListByLngLat(@Param("pointinfo") String pointinfo); } ``` 这里有个关键点需要说明:我们的表中`geom`字段用的是`geometry`类型,坐标系是4326,但4326坐标系默认的单位是度。而在实际业务中,距离当然是用“米”更直观。解决方法是把数据类型转成`geography`,这样计算出来的距离单位就是米了。上面SQL里的5000表示5000米(也就是5公里),实际项目里可以做成动态参数,这里先硬编码演示功能。 ### 3、控制器设计 Service层比较简单,就是把控制器的参数传给Mapper调用,代码就不贴了。直接看控制器: ```ja va /** * 震中位置5公里分析 * @param lng 经度 * @param lat 纬度 * @return */ @PostMapping("/villageinfo") @ResponseBody public AjaxResult earthinfo(String lng, String lat) { List list = earthquakeInfoService.findListByLngLat(lng, lat); AjaxResult ar = AjaxResult.success(); ar.put("data", list); return ar; } ``` ## 三、前端展示 前端选的是Leaflet,配合Bootstrap和jQuery。想用Vue或React的朋友可以自己改造,这里就不提供对应代码了。 页面主要功能包括:地震信息查询、地图浏览(缩放、漫游)、影响范围分析、地震信息弹窗提示、三级范围展示、图例展示等。这些具体实现在之前的文章里有过介绍,不重复了,直接上关键代码。 ### 1、初始化图例 图例帮助理解地图标记的含义。这里根据距离震中的远近,用不同颜色标记行政村点位: ```ja vascript 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); } ``` ### 2、震中位置及影响范围标记 震中用Marker标记,影响范围用圆形表示。 ### 3、行政村点查询及标记 前端用Ajax把地震经纬度传给后台,后台算出结果后返回每个点的经纬度、距离和行政区名称。前端再把这些点动态绘到地图上: ```ja vascript $.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()); } }); ``` 最终效果是这样的: ## 总结 整个思路其实不复杂:地震数据有了,行政村点位数据也有了,关键是利用PostGIS的空间查询能力,把“距离震中多远”这个问题跑通。前后端打通之后,地图上就能直观看到哪些村庄在哪个影响范围里。对于救援部门来说,这个信息能帮他们更快地判断重点区域在哪,往哪个方向调派资源。当然,这里只是一个技术验证,真正投入实战需要考虑的因素还有很多,但至少,这个路子是走得通的。

来源:互联网

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

同类文章推荐

相关文章推荐

更多