吉安感知网项目-后端
linwei
2026-06-05 f3104f14213028277c883e19301b820ae724bd70
feat(utils): 添加几何数据处理和区域编码转换功能

- 在GeomUtils中新增extractCenterPoint方法用于从几何数据中提取中心点坐标
- 在GdPatrolTaskServiceImpl中新增convertAreaCodeToRegionCode方法将区域编码转换为多级行政区划编码格式
- 在GdWorkOrderServiceImpl中集成高德地图API根据经纬度获取行政区划信息
- 实现通过几何数据自动提取中心点并设置对应区域编码的功能
- 添加相关依赖注入和日志记录支持
3 files modified
137 ■■■■■ changed files
drone-common/src/main/java/org/sxkj/common/utils/GeomUtils.java 35 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java 40 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdWorkOrderServiceImpl.java 62 ●●●●● patch | view | raw | blame | history
drone-common/src/main/java/org/sxkj/common/utils/GeomUtils.java
@@ -2,8 +2,10 @@
import org.apache.commons.lang3.StringUtils;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
@@ -50,4 +52,37 @@
            return null;
        }
    }
    /**
     * 从几何数据中提取中心点坐标
     *
     * @param geom WKT格式的几何数据
     * @return 中心点坐标数组,格式为 [经度, 纬度],如果提取失败返回null
     */
    public static double[] extractCenterPoint(String geom) {
        if (StringUtils.isBlank(geom)) {
            return null;
        }
        try {
            // 解析WKT字符串
            Geometry geometry = wktReader.read(geom);
            // 获取几何对象的中心点
            Point centroid = geometry.getCentroid();
            if (centroid == null) {
                return null;
            }
            Coordinate coordinate = centroid.getCoordinate();
            if (coordinate == null) {
                return null;
            }
            // 返回 [经度, 纬度]
            return new double[]{coordinate.x, coordinate.y};
        } catch (ParseException e) {
            return null;
        }
    }
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java
@@ -674,7 +674,9 @@
            param.setSingleTime(DateUtil.format(gdPatrolTaskVO.getExecuteTime(), "yyyy-MM-dd HH:mm:ss"));
         }
        if (StringUtil.isNotBlank(gdPatrolTaskVO.getAreaCode())) {
            param.setRegionCode(gdPatrolTaskVO.getAreaCode());
            // regionCode : "3600,3608,360802"
            String regionCode = convertAreaCodeToRegionCode(gdPatrolTaskVO.getAreaCode());
            param.setRegionCode(regionCode);
        }
        if (StringUtil.isNotBlank(gdPatrolTaskVO.getAirportId())) {
            param.setAirportId(gdPatrolTaskVO.getAirportId());
@@ -753,4 +755,40 @@
        return baseMapper.selectListByWorkOrderId(workOrderId);
    }
    /**
     * 将区域编码转换为多级行政区划编码格式
     *
     * @param areaCode 区域编码(如:360802)
     * @return 多级行政区划编码,格式为 "省编码,市编码,区编码"(如:"3600,3608,360802")
     */
    private String convertAreaCodeToRegionCode(String areaCode) {
        if (StringUtil.isBlank(areaCode)) {
            return null;
        }
        // 如果已经是逗号分隔的格式,直接返回
        if (areaCode.contains(",")) {
            return areaCode;
        }
        // 去除空格并确保长度为6位
        String cleanCode = areaCode.trim();
        if (cleanCode.length() != 6) {
            log.warn("区域编码格式不正确,期望6位数字,实际为: {}", cleanCode);
            return cleanCode;
        }
        try {
            // 提取省、市、区三级编码
            String provinceCode = cleanCode.substring(0, 2) + "00";      // 省级编码(如:3600)
            String cityCode = cleanCode.substring(0, 4) + "0";           // 市级编码(如:3608)
            String districtCode = cleanCode;                             // 区级编码(如:360802)
            return provinceCode + "," + cityCode + "," + districtCode;
        } catch (Exception e) {
            log.error("区域编码转换失败: {}", e.getMessage());
            return areaCode;
        }
    }
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdWorkOrderServiceImpl.java
@@ -1,9 +1,11 @@
package org.sxkj.gd.workorder.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
@@ -13,6 +15,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.sxkj.common.constant.CommonConstant;
import org.sxkj.common.constant.WordOrderConstant;
import org.sxkj.common.utils.AmapUtils;
import org.sxkj.common.utils.GeomUtils;
import org.sxkj.common.utils.OrderNumUtils;
import org.sxkj.gd.workorder.entity.GdPatrolTaskEntity;
@@ -32,9 +35,7 @@
import org.sxkj.gd.workorder.vo.GdWorkOrderVO;
import org.sxkj.system.cache.SysCache;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.*;
/**
 * 工单任务表 服务实现类
@@ -42,6 +43,7 @@
 * @author lw
 * @since 2026-01-14
 */
@Slf4j
@Service
public class GdWorkOrderServiceImpl extends BaseServiceImpl<GdWorkOrderMapper, GdWorkOrderEntity> implements IGdWorkOrderService {
@@ -90,6 +92,13 @@
        }
        entity.setGeom(validatedGeom);
        // 从几何数据中提取中心点坐标,用于获取行政区划编码
        double[] centerCoords = GeomUtils.extractCenterPoint(validatedGeom);
        if (centerCoords == null || centerCoords.length < 2) {
            return false;
        }
        String areaCodePrefix = getDistrictCodeByLocation(centerCoords[0], centerCoords[1]);
        entity.setAreaCode(areaCodePrefix);
        // 生成工单编号
        if (StringUtils.isBlank(entity.getWorkOrderCode())) {
            String timestamp = OrderNumUtils.initOrderNum(WordOrderConstant.ORDER_REDIS_KEY);
@@ -261,4 +270,51 @@
        return false;
    }
    /**
     * 根据经纬度获取行政区划编码
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @return 行政区划编码
     */
    public String getDistrictCodeByLocation(double longitude, double latitude) {
        Map<String, String> districtInfo = getDistrictInfoByLocation(longitude, latitude);
        String adcode = districtInfo.get("adcode");
        log.info("行政区划信息:{}", adcode);
        // if (adcode != null && adcode.length() >= 3) {
        //     return adcode.substring(0, 2);
        // }
        return adcode;
    }
    /**
     * 根据经纬度获取行政区划信息
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @return 行政区划信息
     */
    public Map<String, String> getDistrictInfoByLocation(double longitude, double latitude) {
        // 使用高德地图工具类获取行政区划信息
        String location = longitude + "," + latitude;
        JSONObject result = AmapUtils.searchByLatLng(location);
        Map<String, String> districtInfo = new HashMap<>();
        if (result != null && "1".equals(result.getString("status"))) {
            JSONObject regeocode = result.getJSONObject("regeocode");
            if (regeocode != null) {
                JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
                if (addressComponent != null) {
                    districtInfo.put("province", addressComponent.getString("province"));
                    districtInfo.put("city", addressComponent.getString("city"));
                    districtInfo.put("district", addressComponent.getString("district"));
                    districtInfo.put("adcode", addressComponent.getString("adcode"));
                    districtInfo.put("township", addressComponent.getString("township"));
                    districtInfo.put("formatted_address", regeocode.getString("formatted_address"));
                }
            }
        }
        return districtInfo;
    }
}