目录
前言
随着全球气候变化和地壳活动的不断演变,地震作为一种自然灾害,其发生的频率和影响力日益受到人们的关注。当一个城市或地区遭受地震的威胁时,对其进行详尽的分析显得尤为必要。地震附近城市分析的必要性主要包含以下几个方面:
一、了解地震风险,保障居民安全
地震附近城市的分析,首要目的是了解该城市的地震风险。通过对城市地质结构、地震历史数据、地震活动频率和强度等方面的深入研究,可以准确评估城市面临的地震风险等级。这种评估对于城市规划和防灾减灾措施的制定至关重要,能够确保城市居民的生命财产安全。
二、指导城市规划和建设
地震附近城市的分析还能够为城市规划和建设提供重要指导。在了解城市地震风险的基础上,可以合理规划城市布局,避免在地震活动频繁或地质条件脆弱的区域进行重要建筑和基础设施的建设。此外,分析结果还可以为建筑物的抗震设计提供科学依据,确保建筑物在地震发生时能够保持相对稳定,减少倒塌和破坏的风险。
三、提高城市应急管理能力
地震灾害的突发性和不可预测性要求城市必须具备高效的应急管理能力。地震附近城市的分析可以为城市的应急管理工作提供重要支持。通过对城市地震风险的评估,可以制定相应的应急预案和救援计划,确保在地震发生后能够迅速、有效地进行救援和恢复工作。同时,分析结果还可以帮助城市完善应急设施,提高应对地震灾害的能力。
四、促进城市可持续发展
地震附近城市的分析不仅关注当前的地震风险,还着眼于城市的未来发展。通过深入分析城市的地质条件和地震活动规律,可以为城市的可持续发展提供重要支持。在规划城市未来发展时,可以充分考虑地震风险因素,采取科学合理的措施来降低地震对城市的影响。这有助于实现城市的可持续发展,确保居民在享受城市带来的便利和舒适的同时,也能够享受到安全和稳定的生活环境。
本文基于中国地震台网的数据,以及全国城市点位数据,通过分析地震震中位置100公里范围内的城市列表,以及震中位置与城市的直线距离,为后面做空间分析打下坚实的基础,通过本文,您可以了解到如何在PostGIS数据库中进行空间范围查询,同时可以了解如何将查询结果进行Web空间可视化的具体方法。
博文首先介绍空间数据的基本情况,即如何在空间数据中如何进行空间分析,然后讲解如何使用Java进行后台空间分析的应用,其次介绍如何在Leaflet对分析的结果进行Web可视化,最后给出实际的运行例子,让大家知道程序最终的成果。
一、空间数据说明
本节将对空间数据结构和数据,100公里范围的空间分析查询进行简单介绍。让大家了解如何进行地震位置指定范围城市查询。
1、空间查询
在空间数据库中,要想实现100公里范围内的指定目标查询。采用的是我们熟悉的范围查询函数。st_dwithin () ,为了方便将两个空间对象进行以米为单位的距离换算, 我们将geometry对象转换为geography类型。具体使用的查询语句如下所示:
SELECT T.pk_id, T.NAME, T.pinyin, T.classz, T.bz, T.slx, st_x ( T.geom ) lon, st_y ( T.geom ) lat, st_distance ( T.geom :: geography, t1.geom :: geography ) dist FROM biz_geographic_name T, biz_ceic_earthquake t1 WHERE t1.pk_id = 1792871415574196226 AND st_dwithin ( T.geom :: geography, t1.geom :: geography, 100000 ) ORDER BY dist
将上述的sql语句在PostGIS数据库中执行以后,可以看到以下的查询结果:
通过这条sql语句就可以实现对空间数据的分析。大家请注意,在数据库中我们将地震点存储为Geometry数据,而在界面上我们需要进行经纬度的还原,因此我们采用直接获取经纬度的方法,即:st_x ( T.geom ) lon,st_y ( T.geom ) lat
下面的章节将实现把上面的查询结果进行Web应用开发,完全实现通过一个地震点来实时查询地震点附件的城市列表分析。
二、Java后台开发
在了解了空间数据查询的SQL具体的写法之后,我们来开发针对性的后台。开发语言采用我们熟悉的Java开发语言。Java在GIS开发当中其实也是能实现很多需求的。当学会这门语言之后,用起来就会比较爽,这里不多说,无意与其它语言进行对比,不喜勿喷。
1、模型层设计与实现
在模型层,我们主要介绍实体类的代码实现和Mapper即数据库访问层的设计与实现。实体类主要用来将数据库查询的结果集绑定到对象中。而Mapper则实现对PostGIS空间数据库的绑定和设置。下面我们将分别对这两个主要的类进行编码,在进行OOP设计时,我们发现可以直接利用原始的实体类,只需要扩展出经纬度两个属性即可,因此我们采用视图对象(VO)的方式来实现。
package com.yelang.project.extend.earthquake.domain; import java.io.Serializable; import java.math.BigDecimal; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.yelang.framework.aspectj.lang.annotation.Excel; import com.yelang.framework.handler.PgGeometryTypeHandler; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @Data @ToString @AllArgsConstructor @NoArgsConstructor @TableName(value ="biz_geographic_name",autoResultMap = true) public class GeographicName implements Serializable{ private static final long serialVersionUID = -3694849578429480952L; @TableId(value = "pk_id") @Excel(name = "序号") private Long pkId; @Excel(name = "城市名称") private String name; @Excel(name = "城市汉语拼音") private String pinyin; @Excel(name = "类别") private String classz; @Excel(name = "备注") private String bz; private String slx; public GeographicName(String name, String pinyin, String classz, String bz, String slx, String geom) { super(); this.name = name; this.pinyin = pinyin; this.classz = classz; this.bz = bz; this.slx = slx; this.geom = geom; } @TableField(typeHandler = PgGeometryTypeHandler.class) private String geom; @TableField(exist=false) private String geomJson; @TableField(exist=false) @Excel(name = "城市距离(单位:米)") private BigDecimal dist;//距离 }
package com.yelang.project.extend.earthquake.domain; import java.io.Serializable; import lombok.Data; import lombok.EqualsAndHashCode; /** * 城市地名视图对象 * @author yelangking */ @Data @EqualsAndHashCode(callSuper=false) public class GeographicNameVo extends GeographicName implements Serializable{ private static final long serialVersionUID = -7161733218138543509L; private String lon;//经度 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.GeographicNameVo; public interface GeographicNameMapper extends BaseMapper<GeographicName>{ static final String FIND_LIST_BY_EARTHID = "<script>" +"select t.pk_id,t.name,t.pinyin,t.classz,t.bz,t.slx,st_x(t.geom) lon,st_y(t.geom) lat, " +" st_distance(t.geom :: geography, t1.geom :: geography) dist from biz_geographic_name t,biz_ceic_earthquake t1 " + " where t1.pk_id= #{eqId} and st_dwithin(t.geom :: geography,t1.geom :: geography,100000 ) order by dist " + "</script>"; @Select(FIND_LIST_BY_EARTHID) List<GeographicNameVo> findListByEarthId(@Param("eqId") Long eqId); }
2、控制层设计与实现
业务层比较简单,不进行详细说明。在这个实例当中,业务层的实现比较简单。这里将控制层的代码实现进行说明。这里仅实现页面的跳转和一个ajax接口,关键代码如下:
package com.yelang.project.extend.earthquake.controller; import java.util.List; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.yelang.framework.aspectj.lang.annotation.Log; import com.yelang.framework.aspectj.lang.enums.BusinessType; import com.yelang.framework.web.controller.BaseController; import com.yelang.framework.web.domain.AjaxResult; import com.yelang.framework.web.page.TableDataInfo; import com.yelang.project.extend.earthquake.domain.EarthquakeInfo; import com.yelang.project.extend.earthquake.domain.GeographicNameVo; import com.yelang.project.extend.earthquake.domain.crawler.CeicEarthquake; import com.yelang.project.extend.earthquake.service.ICeicEarthquakeService; import com.yelang.project.extend.earthquake.service.IGeographicNameService; import com.yelang.project.extend.scenicspot.domain.ScenicSpotDistVo; import com.yelang.project.extend.scenicspot.service.IScenicSpotService; @Controller @RequestMapping("/ceiceq/info") public class CeicEarthquakeInfoController extends BaseController{ private String prefix = "ceicearthquake/info"; @Autowired private IGeographicNameService geoNameService; //跳转附近城市页面,用get请求 @RequiresPermissions("ceiceq:info:nearbycities") @GetMapping("/nearbycities/{pkId}") public String nearbyCities(@PathVariable("pkId")Long pkId,ModelMap mmap){ mmap.put("pkId", pkId); CeicEarthquake earthQuake = ceicEarthQuakeService.getById(pkId); mmap.put("earthQuake", earthQuake); List<GeographicNameVo> dataList = geoNameService.findListByEarthId(pkId); mmap.put("dataList", dataList); return prefix + "/nearbycities"; } /** * 获取附近城市列表数据,用post * @param pkId * @return */ @PostMapping("/nearbycities/{pkId}") @ResponseBody public AjaxResult nearbycities(@PathVariable("pkId")Long pkId){ AjaxResult ar = AjaxResult.success(); List<GeographicNameVo> dataList = geoNameService.findListByEarthId(pkId); ar.put("data", dataList); return ar; } }
以上代码即给出了后台Java实现的关键代码。通过以上代码即完成了空间数据分析查询接口开发。下面通过Leaflet组件来进行地图可视化开发。
三、Leaflet地图开发
作为WebGIS的典型组件之一,Leaflet以其良好的生态和丰富的插件和示例应用开发。这里我们同样采取熟悉的Leaflet作为web开发组件。本小节主要讲解如何使用Leaflet进行空间可视化展示开发。
1、地震震中位置展示
在进行地震及附件城市列表可视化展示时,首先需要对震中位置进行展示。关键的代码如下所示。
var lon = [[${earthQuake.epiLon}]]; var lat = [[${earthQuake.epiLat}]]; var cityInfo = [[${earthQuake.locationC}]];
$(function() { var marker = L.circleMarker(new L.LatLng(lat, lon), {radius: 8, labelStyle: { text: cityInfo, rotation: 0, zIndex: 2, strokeStyle :"red" }, color : "red" }).addTo(mymap); });
这时我们来看一下实际的效果:
2、附近城市展示
把震中位置展示出来之后,还要把地震100公里附近的城市也展示出来。关键代码如下:
function showDistance(){ $.ajax({ type:"post", url:prefix + "/nearbycities/" + [[${pkId + ''}]], dataType:"json", cache:false, processData:false, success:function(result){ if(result.code == web_status.SUCCESS){ var strokeStyleSet = "green"; for(var i=0;i<result.data.length;i++){ var dataInfo = result.data[i]; var dist = dataInfo.dist; if(parseFloat(dist) <= 30000){ strokeStyleSet = "red"; } if(parseFloat(dist) > 30000 && parseFloat(dist) <= 60000 ){ strokeStyleSet = "orange"; } if(parseFloat(dist) >= 60000){ strokeStyleSet = "green"; } var _dist = parseFloat(dataInfo.dist / 1000).toFixed(2); var content = "<strong>城市名称:</strong>"+dataInfo.name + "<br/><strong>震中位置:</strong>"+ cityInfo; content += "<br/><strong>距离(千米):</strong>"+_dist; var marker = L.circleMarker(new L.LatLng(dataInfo.lat, dataInfo.lon), {radius: 8, labelStyle: { text: dataInfo.name, rotation: 0, zIndex: i, strokeStyle :strokeStyleSet }, color : strokeStyleSet }).addTo(mymap); marker.bindPopup(content); L.polyline( [ [ [lat, lon],[dataInfo.lat, dataInfo.lon]]], { labelStyle: { text:dataInfo.name + ":" + _dist + "千米", zIndex: 0, collisionFlg: false, textAlign:'center', strokeStyle :strokeStyleSet }, color : strokeStyleSet }).addTo(mymap); } } }, error:function(){ $.modal.alertWarning("获取信息失败"); } }); }
右边的附近城市列表展示代码如下:
<table class="table table-bordered white-bg" > <thead> <tr> <th width="50%">城市名称</th> <th>城市级别</th> <th>距离(公里)</th> </tr> </thead> <tbody> <tr th:each="data,itemStat:${dataList}"> <td >[[${itemStat.count}]]、[[${data.name}]]</td> <td>[[${data.bz}]]</td> <td th:text="${#numbers.formatDecimal((data.dist / 1000 ), 1, 2)}"></td> </tr> </tbody> </table>
3、成果展示
下面展示几个具体的地震点的附近城市信息:
2024-05-19 03:35:44 山西大同市阳高县 3.9级地震 震源深度13米 附近城市示意图
2024-05-10 09:37:24 台湾花莲县 4.6级 震源深度10米 附近城市分布示意图
2024-04-30 07:52:46 陕西汉中市洋县 2.8级 震源深度10米 附近城市分布示意图
2018-10-01 13:09:07 湖南常德市鼎城区 3.1级 震源深度 7米 附近城市分布示意图
总结
以上就是本文的主要内容,本文基于中国地震台网的数据,以及全国城市点位数据,通过分析地震震中位置100公里范围内的城市列表,以及震中位置与城市的直线距离,为后面做空间分析打下坚实的基础,通过本文,您可以了解到如何在PostGIS数据库中进行空间范围查询,同时可以了解如何将查询结果进行Web空间可视化的具体方法。行文仓促,难免有不足之处,如果您发现有问题,欢迎各路朋友在评论区留下宝贵意见,万分感谢。