Commit ef4be998 authored by hanbing's avatar hanbing

[add] 拆解wkt,判断点是否在多边形范围内

parent 4924ed56
package net.wanji.web.bo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author Kent HAN
* @date 2023/5/16 10:37
*/
@Data
public class SpecialServiceRouteBO {
@ApiModelProperty(value = "起点坐标")
private double[] startLonLat;
@ApiModelProperty(value = "终点坐标")
private double[] endLonLat;
}
......@@ -7,8 +7,10 @@ import io.swagger.annotations.ApiResponses;
import net.wanji.common.annotation.aspect.AspectLog;
import net.wanji.common.enums.BaseEnum;
import net.wanji.common.framework.rest.JsonViewObject;
import net.wanji.web.bo.SpecialServiceRouteBO;
import net.wanji.web.common.exception.CrossRelationException;
import net.wanji.web.service.SpecialServiceService;
import net.wanji.web.vo.SpecialServiceRouteVO;
import net.wanji.web.vo.specialService.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
......@@ -26,13 +28,23 @@ import java.util.Set;
* @author Kent HAN
* @date 2022/11/8 10:57
*/
@Api(value = "SpecialServiceController", description = "快速特勤")
@Api(value = "SpecialServiceController", description = "特勤管理")
@RequestMapping("/specialService")
@RestController
public class SpecialServiceController {
@Autowired
SpecialServiceService specialServiceService;
@AspectLog(description = "备选路线推送", operationType = BaseEnum.OperationTypeEnum.QUERY)
@ApiOperation(value = "备选路线推送", notes = "备选路线推送", response = SpecialServiceRouteVO.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@PostMapping(value = "/specialServiceRoute",
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
public JsonViewObject specialServiceRoute(@RequestBody SpecialServiceRouteBO specialServiceRouteBO) {
specialServiceService.specialServiceRoute(specialServiceRouteBO);
return JsonViewObject.newInstance().success();
}
@AspectLog(description = "添加特勤", operationType = BaseEnum.OperationTypeEnum.QUERY)
@ApiOperation(value = "添加特勤", notes = "添加特勤", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
......
package net.wanji.web.service;
import net.wanji.web.bo.SpecialServiceRouteBO;
import net.wanji.web.vo.specialService.*;
import java.util.List;
......@@ -31,4 +32,6 @@ public interface SpecialServiceService {
void disableSpecialService(EnableDisableSpecialServiceInVO enableDisableSpecialServiceInVO);
Set<String> crossInList(String crossId);
void specialServiceRoute(SpecialServiceRouteBO specialServiceRouteBO);
}
......@@ -3,15 +3,23 @@ package net.wanji.web.service.impl;
import cn.hutool.http.HttpUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.wanji.common.utils.geo.CalUtils;
import net.wanji.common.utils.tool.CrossUtil;
import net.wanji.databus.dao.entity.RidInfoEntity;
import net.wanji.databus.dao.mapper.BaseCrossInfoMapper;
import net.wanji.web.common.enums.CrossPhasePlanTurnTypeEnum;
import net.wanji.databus.dao.mapper.RidInfoMapper;
import net.wanji.databus.po.BaseCrossInfoPO;
import net.wanji.databus.po.TBaseCrossInfo;
import net.wanji.web.bo.SpecialServiceRouteBO;
import net.wanji.web.common.enums.CrossDirEnum;
import net.wanji.web.common.enums.CrossPhasePlanTurnTypeEnum;
import net.wanji.web.common.enums.SpecialServiceCrossTurnEnum;
import net.wanji.web.common.exception.CrossRelationException;
import net.wanji.common.utils.tool.CrossUtil;
import net.wanji.databus.po.TBaseCrossInfo;
import net.wanji.web.mapper.*;
import net.wanji.web.po.*;
import net.wanji.web.po.CrossDirTurnPO;
import net.wanji.web.po.RidInfoPO;
import net.wanji.web.po.SpecialServiceCrossPO;
import net.wanji.web.po.SpecialServicePO;
import net.wanji.web.service.SpecialServiceService;
import net.wanji.web.vo.specialService.*;
import org.springframework.beans.BeanUtils;
......@@ -27,23 +35,31 @@ import java.util.*;
*/
@Service
public class SpecialServiceServiceImpl implements SpecialServiceService {
// key所有路段的多边形
Map<double[][], RidInfoEntity> allRidPolygons = new HashMap<>();
// 所有路段,key起始点,value路段实体类
Map<double[][], RidInfoEntity> allStartEnds = new HashMap<>();
// 相交路段
List<RidInfoEntity> straddleRids = new ArrayList<>();
@Autowired
SpecialServiceMapper specialServiceMapper;
@Autowired
SpecialServiceCrossMapper specialServiceCrossMapper;
@Autowired
CustomRidInfoMapper customRidInfoMapper;
@Autowired
BaseCrossInfoMapper tBaseBaseCrossInfoMapper;
@Autowired
CrossDirTurnMapper crossDirTurnMapper;
@Autowired
CrossPhasePlanMapper crossPhasePlanMapper;
@Autowired
private BaseCrossInfoMapper baseCrossInfoMapper;
@Autowired
private RidInfoMapper ridInfoMapper;
private Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
......@@ -323,4 +339,118 @@ public class SpecialServiceServiceImpl implements SpecialServiceService {
String s = dirStr + "进口";
return s;
}
@Override
public void specialServiceRoute(SpecialServiceRouteBO specialServiceRouteBO) {
// 初始化所有路段多边形
initAllPolygons();
// 获取起点路口和终点路口
double[] startLonLat = specialServiceRouteBO.getStartLonLat();
double[] endLonLat = specialServiceRouteBO.getEndLonLat();
double startMinDistance = Double.MAX_VALUE;
double endMinDistance = Double.MAX_VALUE;
BaseCrossInfoPO startCross = null;
BaseCrossInfoPO endCross = null;
for (double[][] ridPolygon : allRidPolygons.keySet()) {
boolean isStartInPolygon = CalUtils.isPointinPolygon(startLonLat, ridPolygon);
boolean isEndInPolygon = CalUtils.isPointinPolygon(endLonLat, ridPolygon);
if (isStartInPolygon) {
RidInfoEntity ridInfoEntity = allRidPolygons.get(ridPolygon);
String ridStartCrossId = ridInfoEntity.getStartCrossId();
BaseCrossInfoPO ridStartCrossPO = baseCrossInfoMapper.selectById(ridStartCrossId);
String ridStartLocation = ridStartCrossPO.getLocation();
double[] ridStartLonLat = CrossUtil.getLonLat(ridStartLocation);
double distanceToRidStart = CalUtils.calculate_distance(
ridStartLonLat[0], ridStartLonLat[1], startLonLat[0], startLonLat[1]);
startMinDistance = Math.min(startMinDistance, distanceToRidStart);
if (distanceToRidStart == startMinDistance) {
startCross = ridStartCrossPO;
}
String ridEndCrossId = ridInfoEntity.getEndCrossId();
BaseCrossInfoPO ridEndCrossPO = baseCrossInfoMapper.selectById(ridEndCrossId);
String ridEndLocation = ridEndCrossPO.getLocation();
double[] ridEndLonLat = CrossUtil.getLonLat(ridEndLocation);
double distanceToRidEnd = CalUtils.calculate_distance(
ridEndLonLat[0], ridEndLonLat[1], startLonLat[0], startLonLat[1]);
startMinDistance = Math.min(startMinDistance, distanceToRidEnd);
if (distanceToRidEnd == startMinDistance) {
startCross = ridEndCrossPO;
}
}
if (isEndInPolygon) {
RidInfoEntity ridInfoEntity = allRidPolygons.get(ridPolygon);
String ridStartCrossId = ridInfoEntity.getStartCrossId();
BaseCrossInfoPO ridStartCrossPO = baseCrossInfoMapper.selectById(ridStartCrossId);
String ridStartLocation = ridStartCrossPO.getLocation();
double[] ridStartLonLat = CrossUtil.getLonLat(ridStartLocation);
double distanceToRidStart = CalUtils.calculate_distance(
ridStartLonLat[0], ridStartLonLat[1], startLonLat[0], startLonLat[1]);
endMinDistance = Math.min(endMinDistance, distanceToRidStart);
if (distanceToRidStart == endMinDistance) {
endCross = ridStartCrossPO;
}
String ridEndCrossId = ridInfoEntity.getEndCrossId();
BaseCrossInfoPO ridEndCrossPO = baseCrossInfoMapper.selectById(ridEndCrossId);
String ridEndLocation = ridEndCrossPO.getLocation();
double[] ridEndLonLat = CrossUtil.getLonLat(ridEndLocation);
double distanceToRidEnd = CalUtils.calculate_distance(
ridEndLonLat[0], ridEndLonLat[1], endLonLat[0], endLonLat[1]);
endMinDistance = Math.min(endMinDistance, distanceToRidEnd);
if (distanceToRidEnd == endMinDistance) {
endCross = ridEndCrossPO;
}
}
}
// 返回两条备选线路
System.out.println("todo");
}
private void initAllPolygons() {
allRidPolygons.clear();
List<RidInfoEntity> ridInfoEntities = ridInfoMapper.selectAll();
for (RidInfoEntity ridInfoEntity : ridInfoEntities) {
String wkt = ridInfoEntity.getWkt();
String[] lonLats = wkt.split(";");
int length = lonLats.length;
double[][] doubles = new double[length + 1][2]; // +1是为了首尾相接,算法工具类需要
for (int i = 0; i < length; i++) {
String lonLat = lonLats[i];
String[] pointLonLat = lonLat.split(",");
double pointLon = Double.parseDouble(pointLonLat[0]);
double pointLat = Double.parseDouble(pointLonLat[1]);
double[] pointLonLatDouble = {pointLon, pointLat};
doubles[i] = pointLonLatDouble;
if (i == length - 1) { // 最后一个点位
doubles[i + 1] = doubles[0]; // 首尾相接,算法工具类需要
}
}
allRidPolygons.put(doubles, ridInfoEntity);
}
}
private void fillAllStartEnds() {
allStartEnds.clear();
List<RidInfoEntity> ridInfoEntities = ridInfoMapper.selectAll();
for (RidInfoEntity ridInfoEntity : ridInfoEntities) {
String startCrossId = ridInfoEntity.getStartCrossId();
String endCrossId = ridInfoEntity.getEndCrossId();
BaseCrossInfoPO startCrossPO = baseCrossInfoMapper.selectById(startCrossId);
String startLocation = startCrossPO.getLocation();
double[] startLonLat = CrossUtil.getLonLat(startLocation);
BaseCrossInfoPO endCrossPO = baseCrossInfoMapper.selectById(endCrossId);
String endLocation = endCrossPO.getLocation();
double[] endLonLat = CrossUtil.getLonLat(endLocation);
double[][] doubles = new double[][]{startLonLat, endLonLat};
allStartEnds.put(doubles, ridInfoEntity);
}
}
}
\ No newline at end of file
package net.wanji.web.vo;
/**
* @author Kent HAN
* @date 2023/5/16 14:27
*/
public class SpecialServiceRouteVO {
}
package net.wanji.common.utils.geo;
import java.math.BigDecimal;
import java.text.NumberFormat;
public class CalculateUtils {
/**
* 加法
*
* @param var1
* @param var2
* @return
*/
public static double add(double var1, double var2) {
BigDecimal b1 = new BigDecimal(Double.toString(var1));
BigDecimal b2 = new BigDecimal(Double.toString(var2));
return b1.add(b2).doubleValue();
}
/**
* 减法
*
* @param var1
* @param var2
* @return
*/
public static double sub(double var1, double var2) {
BigDecimal b1 = new BigDecimal(Double.toString(var1));
BigDecimal b2 = new BigDecimal(Double.toString(var2));
return b1.subtract(b2).doubleValue();
}
/**
* 乘法
*
* @param var1
* @param var2
* @return
*/
public static double mul(double var1, double var2) {
BigDecimal b1 = new BigDecimal(Double.toString(var1));
BigDecimal b2 = new BigDecimal(Double.toString(var2));
return b1.multiply(b2).doubleValue();
}
/**
* 除法
*
* @param v1 被除数
* @param v2 除数
* @param scale 精度,到小数点后几位
* @return
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("精确度不能小于0");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 四舍五入
*
* @param v
* @param scale 精确位数
* @return
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("精确度不能小于0");
}
BigDecimal b = new BigDecimal(Double.toString(v));
return b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
// return b.divide(b, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/*
* 加法计算并保留小数点
* */
public static double addRound(double var1, double var2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("精确度不能小于0");
}
return round(add(var1, var2), scale);
// BigDecimal b = new BigDecimal(Double.toString(add(var1,var2)));
// return b.divide(b, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/*
* 减法计算并保留小数点
* */
public static double subRound(double var1, double var2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("精确度不能小于0");
}
return round(sub(var1, var2), scale);
}
/*
* 乘法计算并保留小数点
* */
public static double mulRound(double var1, double var2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("精确度不能小于0");
}
return round(mul(var1, var2), scale);
}
//把数字转为指定格式的百分数
public static String getPercentFormat(int maxFract, int minFract, int maxInt, int minInt, Double d) {
NumberFormat percentFormat = NumberFormat.getPercentInstance();
percentFormat.setMaximumFractionDigits(maxFract); //最大小数位数
percentFormat.setMaximumIntegerDigits(maxInt);//最大整数位数
percentFormat.setMinimumFractionDigits(minFract); //最小小数位数
percentFormat.setMinimumIntegerDigits(minInt);//最小整数位数
return percentFormat.format(d);//自动转换成百分比显示
}
}
......@@ -25,4 +25,6 @@ public interface RidInfoMapper {
@Param("endCrossId") String endCrossId);
RidInfoEntity selectByEndInDir(String endCrossId, int spilloverDirInt);
List<RidInfoEntity> selectAll();
}
......@@ -76,4 +76,9 @@
FROM t_base_rid_info t1 JOIN t_base_cross_info t2 ON t1.start_cross_id = t2.id
WHERE t1.end_cross_id = #{endCrossId} and t1.in_dir = #{spilloverDirInt} and t2.is_signal = 1
</select>
<select id="selectAll" resultType="net.wanji.databus.dao.entity.RidInfoEntity">
select <include refid="Base_Column_List"/>
from t_base_rid_info
</select>
</mapper>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment