QGIS暴雨专题图产出功能

This commit is contained in:
zzw
2026-06-09 08:56:18 +08:00
parent 60443470b1
commit 9d3e51be31
14 changed files with 426 additions and 11 deletions
@@ -10,13 +10,8 @@ import java.util.Map;
*/
public class BaseConstants {
// url
public static final String RAIN_MAPS_TEMPLATE_PATH = "F:/files/xian/dzxx/maps/rain/"; // 暴雨专题图模板路径
// 暴雨专题图模板路径
public static final String RAIN_MAPS_OUTPUT_PATH = "F:/files/xian/dzxx/output/rain/map/"; // 暴雨专题图文件输出路径
public static final String RAIN_DOCUMENT_OUTPUT_PATH = "F:/files/xian/dzxx/output/rain/暴雨应急预评估报告.docx"; // 暴雨评估报告文件输出路径
// 提示语
public static final String PARAMS_ERROR = "参数有误,请重新传入!";
@@ -0,0 +1,36 @@
package com.gis.xian.controller;
import com.gis.xian.domain.ApiResponse;
import com.gis.xian.dto.pub.RTriggerDTO;
import com.gis.xian.query.RQuery;
import com.gis.xian.service.pub.IREventService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* @author zzw
* @description: 暴雨事件控制类
* @date 2026/6/8 下午4:36
*/
@Slf4j
@RestController
@RequestMapping("/open")
public class REventController {
@Resource
private IREventService irEventService;
@PostMapping("/rs/trigger")
public ApiResponse<RQuery> trigger(@RequestBody @Validated RTriggerDTO trigger) {
RQuery query = irEventService.trigger(trigger);
return ApiResponse.ok(query);
}
@PostMapping("/rs/delete/{Id}")
public ApiResponse<Boolean> delete(@PathVariable Long Id) {
Boolean deleted = irEventService.deletedById(Id);
return ApiResponse.ok(deleted);
}
}
@@ -0,0 +1,27 @@
package com.gis.xian.dto.pub;
import lombok.Data;
import org.locationtech.jts.geom.Geometry;
import java.time.LocalDateTime;
/**
* @author zzw
* @description: 暴雨信息
* @date 2026/6/8 下午4:49
*/
@Data
public class REventDTO {
private String rainId;
private String rainQueueId;
private String disasterName;
private String position;
private LocalDateTime occurrenceTime;
private String rainfall;
private String duration;
private Geometry geom; //经纬度
private Double longitude;
private Double latitude;
private String rainType;
}
@@ -0,0 +1,22 @@
package com.gis.xian.dto.pub;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author zzw
* @description: RTriggerDTO
* @date 2026/6/8 下午4:44
*/
@Data
public class RTriggerDTO {
private String position; // 区县
private double longitude; // 经度
private double latitude; // 纬度
private String rainfall; // 降雨量
private String duration; // 已持续时间
private String rainType; // 暴雨类型
private LocalDateTime occurrenceTime; // 发生时间
}
@@ -0,0 +1,54 @@
package com.gis.xian.entity.pub;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.gis.xian.handler.GeometryTypeHandler;
import lombok.Data;
import org.locationtech.jts.geom.Geometry;
import java.time.LocalDateTime;
/**
* @author zzw
* @description: 暴雨事件表
* @date 2026/6/8 下午4:38
*/
@Data
@TableName("public.r_event")
public class REvent {
@TableId
@TableField("id")
private Long Id;
@TableField("rain_id")
private String rainId;
@TableField("rain_queue_id")
private String rainQueueId;
@TableField("disaster_name")
private String disasterName;
@TableField("position")
private String position;
@TableField("occurrence_time")
private LocalDateTime occurrenceTime;
@TableField("rainfall")
private String rainfall;
@TableField("duration")
private String duration;
@TableField(value = "geom", typeHandler = GeometryTypeHandler.class)
private Geometry geom; //经纬度
@TableField("longitude")
private Double longitude;
@TableField("latitude")
private Double latitude;
@TableField("rain_type")
private String rainType;
@TableField(value = "create_time",fill = FieldFill.INSERT_UPDATE)
private LocalDateTime createTime;
@TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField("is_deleted")
private Integer delFlag = 0;
}
@@ -101,7 +101,7 @@ public class EarthquakeHandler {
// 地震事件 + 批次
String batch = queueId.substring(rainId.length());
String path = rainId + "/" + batch + "/" + size + "/" + map.getName();
return String.format("%s", BaseConstants.RAIN_MAPS_OUTPUT_PATH + path + ".jpg");
return String.format("%s", qgisProperties.getBasePath() + qgisProperties.getRainMapsOutputPath() + path + ".jpg");
}
public String format(LocalDateTime time) {
@@ -0,0 +1,14 @@
package com.gis.xian.mapper.pub;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gis.xian.entity.pub.REvent;
import org.apache.ibatis.annotations.Mapper;
/**
* @author zzw
* @description: REventMapper
* @date 2026/6/8 下午6:01
*/
@Mapper
public interface REventMapper extends BaseMapper<REvent> {
}
@@ -0,0 +1,20 @@
package com.gis.xian.query;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author zzw
* @description: 暴雨参数
* @date 2026/6/8 下午4:43
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RQuery {
private String rainId;
private String rainQueueId;
}
@@ -3,6 +3,7 @@ package com.gis.xian.service.pub;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gis.xian.config.DataSource;
import com.gis.xian.dto.pub.EqAssessmentDTO;
import com.gis.xian.dto.pub.RAssessmentDTO;
import com.gis.xian.entity.pub.DZEqQueue;
/**
@@ -16,6 +17,9 @@ public interface IDZEqQueueService extends IService<DZEqQueue> {
// 地震评估
public void assess(EqAssessmentDTO assess);
// 暴雨评估
public void assess(RAssessmentDTO assess);
// 更新评估进度、状态
public void updated(String event, String queueId, double progress, int state);
}
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.gis.xian.config.DataSource;
import com.gis.xian.dto.pub.DZProductDTO;
import com.gis.xian.dto.pub.EqAssessmentDTO;
import com.gis.xian.dto.pub.RAssessmentDTO;
import com.gis.xian.entity.pub.DZProduct;
import com.gis.xian.query.ProductQuery;
@@ -20,6 +21,9 @@ public interface IDZProductService extends IService<DZProduct> {
// qgis 地震制图服务
public void makeEarthquakeMaps(EqAssessmentDTO assess);
// qgis 暴雨制图服务
public void makeRainstormMaps(RAssessmentDTO assess);
// 获取产品
public List<DZProductDTO> getProducts(ProductQuery query);
}
@@ -0,0 +1,21 @@
package com.gis.xian.service.pub;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gis.xian.config.DataSource;
import com.gis.xian.dto.pub.RTriggerDTO;
import com.gis.xian.entity.pub.REvent;
import com.gis.xian.query.RQuery;
/**
* @author zzw
* @description: IREventService
* @date 2026/6/8 下午6:01
*/
@DataSource("slave1")
public interface IREventService extends IService<REvent> {
// 暴雨触发
public RQuery trigger(RTriggerDTO trigger);
// 删除暴雨事件
public Boolean deletedById(Long Id);
}
@@ -69,6 +69,26 @@ public class DZEqQueueServiceImpl extends ServiceImpl<DZEqQueueMapper, DZEqQueue
}
}
@Transactional
@Override
public void assess(RAssessmentDTO assess) {
log.info("开始评估,评估参数:{}", assess);
// 异常值
if (assess == null) {
throw new ParmaException(BaseConstants.PARAMS_ERROR);
}
// 评估业务
try {
// 初始化评估
initial(assess, BaseConstants.MANUAL);
// 专题图产出
idzProductService.makeRainstormMaps(assess);
} catch (Exception ex) {
log.error(ex.getMessage());
throw new ServeException(BaseConstants.ASSESS_SERVER_ERROR);
}
}
// 地震初始化评估进度和评估状态
private void initial(EqAssessmentDTO assess, int type) {
@@ -8,9 +8,11 @@ import com.gis.xian.config.QgisProperties;
import com.gis.xian.constant.BaseConstants;
import com.gis.xian.dto.pub.DZProductDTO;
import com.gis.xian.dto.pub.EqAssessmentDTO;
import com.gis.xian.dto.pub.RAssessmentDTO;
import com.gis.xian.entity.pub.DZProduct;
import com.gis.xian.enums.BaseEnums;
import com.gis.xian.enums.EqMapsEnums;
import com.gis.xian.enums.RainMapsEnums;
import com.gis.xian.handler.EarthquakeHandler;
import com.gis.xian.mapper.pub.DZProductMapper;
import com.gis.xian.query.ProductQuery;
@@ -50,10 +52,6 @@ public class DZProductServiceImpl extends ServiceImpl<DZProductMapper, DZProduct
@Resource
private IFeignService iFeignService;
@Resource
private IActiveFaultService iActiveFaultService;
@Resource
private IDZXXInfluenceService idzxxInfluenceService;
@Resource
private QgisProperties qgisProperties;
@Resource
private EarthquakeHandler earthquakeHandler;
@@ -70,6 +68,17 @@ public class DZProductServiceImpl extends ServiceImpl<DZProductMapper, DZProduct
iFeignService.invoke(args);
}
@Override
@Async("xianPool")
public void makeRainstormMaps(RAssessmentDTO assess) {
// 待产专题图集
List<RainMapsEnums> maps = Arrays.asList(RainMapsEnums.values());
// 设置制图参数
List<QgisArgs> args = setMakeRainstormMapsArgs(assess, maps);
// 调用出图服务
iFeignService.invoke(args);
}
// 获取产品
@Override
public List<DZProductDTO> getProducts(ProductQuery query) {
@@ -170,6 +179,67 @@ public class DZProductServiceImpl extends ServiceImpl<DZProductMapper, DZProduct
return args;
}
// 暴雨 制图参数
private List<QgisArgs> setMakeRainstormMapsArgs(RAssessmentDTO assess, List<RainMapsEnums> maps) {
// 专题图集参数
List<QgisArgs> args = new ArrayList<>();
// A4 画幅
for (RainMapsEnums map : maps) {
// qgis参数
QgisArgs arg = new QgisArgs();
arg.setId(map.getNum());
arg.setEvent(assess.getRainId());
arg.setQueueId(assess.getRainQueueId());
arg.setCenterX(assess.getLongitude());
arg.setCenterY(assess.getLatitude());
arg.setInfo(earthquakeHandler.parseRInfo(assess.getOccurrenceTime(), assess.getRainfall(), assess.getDuration()));
arg.setMapTitle(earthquakeHandler.combineR(assess.getPosition(), assess.getRainType(), map));
arg.setMapTime(BaseUtils.formatTime(LocalDateTime.now(), false));
arg.setMapLayout(BaseConstants.MAP_LAYOUT_A3); // A4
arg.setMapUint(BaseConstants.MAP_UNIT); // 单位
// 死信队列中获取单张图片
arg.setName(map.getName());
arg.setOutFile(earthquakeHandler.getRPath(assess.getRainId(), assess.getRainQueueId(), BaseConstants.MAP_LAYOUT_A4, map));
arg.setPath(qgisProperties.getRainMapsTemplatePath() + map.getName() + ".qgz");
arg.setDisaster(BaseConstants.RAIN_DISASTER_MAP); // 暴雨灾害
// 按规则缩放
arg.setZoomRule(BaseEnums.NO.getCode().toString()); // 默认不缩放
arg.setZoomValue(""); // 默认缩放值
args.add(arg);
}
// 增加 A3 画幅
for (RainMapsEnums map : maps) {
// qgis参数
QgisArgs arg = new QgisArgs();
arg.setId(map.getNum());
arg.setEvent(assess.getRainId());
arg.setQueueId(assess.getRainQueueId());
arg.setCenterX(assess.getLongitude());
arg.setCenterY(assess.getLatitude());
arg.setInfo(earthquakeHandler.parseRInfo(assess.getOccurrenceTime(), assess.getRainfall(), assess.getDuration()));
arg.setMapTitle(earthquakeHandler.combineR(assess.getPosition(), assess.getRainType(), map));
arg.setMapTime(BaseUtils.formatTime(LocalDateTime.now(), false));
arg.setMapLayout(BaseConstants.MAP_LAYOUT_A4); // A4
arg.setMapUint(BaseConstants.MAP_UNIT); // 单位
// 死信队列中获取单张图片
arg.setName(map.getName());
arg.setOutFile(earthquakeHandler.getRPath(assess.getRainId(), assess.getRainQueueId(), BaseConstants.MAP_LAYOUT_A3, map));
arg.setPath(qgisProperties.getRainMapsTemplatePath() + map.getName() + ".qgz");
arg.setDisaster(BaseConstants.RAIN_DISASTER_MAP); // 暴雨灾害
arg.setZoomRule(BaseEnums.NO.getCode().toString()); // 默认不缩放
arg.setZoomValue(""); // 默认缩放值
args.add(arg);
}
log.info("制图参数设置完成!");
return args;
}
/**
* 专题图缩放变化:
@@ -0,0 +1,128 @@
package com.gis.xian.service.pub.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gis.xian.config.DataSource;
import com.gis.xian.constant.BaseConstants;
import com.gis.xian.dto.pub.RAssessmentDTO;
import com.gis.xian.dto.pub.REventDTO;
import com.gis.xian.dto.pub.RTriggerDTO;
import com.gis.xian.entity.pub.REvent;
import com.gis.xian.mapper.pub.REventMapper;
import com.gis.xian.query.RQuery;
import com.gis.xian.service.ex.ParmaException;
import com.gis.xian.service.ex.ServeException;
import com.gis.xian.service.ex.ServiceException;
import com.gis.xian.service.pub.IDZEqQueueService;
import com.gis.xian.service.pub.IREventService;
import com.gis.xian.utils.BaseUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author zzw
* @description: REventServiceImpl
* @date 2026/6/8 下午4:45
*/
@Slf4j
@Service
@DataSource("slave1")
public class REventServiceImpl extends ServiceImpl<REventMapper, REvent> implements IREventService {
@Resource
private IDZEqQueueService idzEqQueueService;
// 暴雨触发
@Transactional
@Override
public RQuery trigger(RTriggerDTO trigger) {
log.info("暴雨参数:{}", trigger);
// 异常值
if (trigger == null) {
throw new ParmaException(BaseConstants.PARAMS_ERROR);
}
// 专题图命名代码
String code = BaseUtils.generationRainCode(trigger.getOccurrenceTime());
// 暴雨业务
try {
// 暴雨信息存储
REventDTO eventdto = new REventDTO();
BeanUtils.copyProperties(trigger, eventdto);
eventdto.setRainId(code);
log.info("暴雨专题图编码:{}", code);
handle(eventdto);
} catch (Exception ex) {
log.error(ex.getMessage());
ex.printStackTrace();
throw new ServeException(BaseConstants.RAIN_SERVER_ERROR);
}
String batch = BaseUtils.generationBatchCode(code);
// 评估业务
try {
RAssessmentDTO assess = new RAssessmentDTO();
BeanUtils.copyProperties(trigger, assess);
assess.setRainId(code);
assess.setRainQueueId(batch);
// 开始评估
idzEqQueueService.assess(assess);
} catch (Exception ex) {
log.error(ex.getMessage());
ex.printStackTrace();
throw new ServeException(BaseConstants.ASSESS_SERVER_ERROR);
}
// 地震编码
return new RQuery(code, batch);
}
// 删除暴雨
@Override
public Boolean deletedById(Long Id) {
// 空值
if (Id == null) {
throw new ParmaException(BaseConstants.PARAMS_ERROR);
}
// 条件构造
LambdaQueryWrapper<REvent> lambdaQuery = Wrappers.lambdaQuery(REvent.class);
lambdaQuery.eq(REvent::getId, Id);
int flag = this.baseMapper.delete(lambdaQuery);
return flag > 0 ? true : false;
}
// 处理暴雨数据
private void handle(REventDTO eventdto) {
// 抛出异常
if (eventdto == null) {
throw new ParmaException(BaseConstants.PARAMS_ERROR);
}
try {
REvent revent = new REvent();
BeanUtils.copyProperties(eventdto, revent);
// 处理空间数据
GeometryFactory geometryFactory = new GeometryFactory();
Point point = geometryFactory.createPoint(new Coordinate(
eventdto.getLongitude(), eventdto.getLatitude()
));
revent.setGeom(point);
revent.getGeom().setSRID(4490);
// 存库
save(revent);
log.info("暴雨位基本信息已存库...");
} catch (Exception ex) {
log.error("暴雨触发:暴雨基本信息保存失败!", ex.getMessage());
ex.printStackTrace();
throw new ServiceException(BaseConstants.RAIN_SERVER_ERROR);
}
}
}