报告模块重构
This commit is contained in:
parent
c0b9515088
commit
2d072b01ff
@ -1,15 +1,9 @@
|
||||
package com.cdzy.operations.utils;
|
||||
|
||||
import org.locationtech.jts.geom.Coordinate;
|
||||
import org.locationtech.jts.geom.GeometryFactory;
|
||||
import org.locationtech.jts.geom.Polygon;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.geo.*;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -24,131 +18,12 @@ public class RedisUtil {
|
||||
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
private final String geoKey="ebike_geo";
|
||||
|
||||
@Autowired
|
||||
public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/* ------------------- key 相关操作 ------------------ */
|
||||
|
||||
/**
|
||||
* 添加地理位置
|
||||
*
|
||||
* @param point 经纬度
|
||||
* @param member 成员名称
|
||||
*/
|
||||
public void addLocation(Point point, String member) {
|
||||
redisTemplate.opsForGeo().add(geoKey, point, member);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定范围内的成员
|
||||
*
|
||||
* @param center 中心点
|
||||
* @param radius 半径(单位:公里)
|
||||
* @return 范围内的成员列表
|
||||
*/
|
||||
public List<String> findNearbyMembers(Point center, double radius) {
|
||||
Distance distance = new Distance(radius, RedisGeoCommands.DistanceUnit.KILOMETERS);
|
||||
Circle circle = new Circle(center, distance);
|
||||
GeoResults<RedisGeoCommands.GeoLocation<Object>> results = redisTemplate.opsForGeo()
|
||||
.radius(geoKey, circle);
|
||||
return results.getContent().stream()
|
||||
.map(geoLocation -> geoLocation.getContent().getName().toString())
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 多边形查询
|
||||
* @param polygonPoints 边界点
|
||||
* @return 成员列表
|
||||
*/
|
||||
public List<String> searchByPolygon( List<Point> polygonPoints ) {
|
||||
|
||||
// 1. 构造多边形
|
||||
GeometryFactory factory = new GeometryFactory();
|
||||
Coordinate[] coordinates = polygonPoints.stream()
|
||||
.map(p -> new Coordinate(p.getX(), p.getY()))
|
||||
.toArray(Coordinate[]::new);
|
||||
Polygon polygon = factory.createPolygon(coordinates);
|
||||
|
||||
// 2. 计算最小外接圆
|
||||
Point center = calculateBoundingCircleCenter(polygonPoints);
|
||||
double radius = calculateMaxRadius(polygonPoints, center);
|
||||
|
||||
// 3. 查询圆内所有点
|
||||
GeoResults<RedisGeoCommands.GeoLocation<Object>> results =
|
||||
redisTemplate.opsForGeo()
|
||||
.radius(geoKey,
|
||||
new Circle(center, new Distance(radius, Metrics.KILOMETERS)),
|
||||
RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
|
||||
.includeCoordinates());
|
||||
|
||||
// 4. 过滤多边形内的点
|
||||
List<String> matches = new ArrayList<>();
|
||||
for (GeoResult<RedisGeoCommands.GeoLocation<Object>> result : results) {
|
||||
Point point = result.getContent().getPoint();
|
||||
if (polygon.contains(factory.createPoint(
|
||||
new Coordinate(point.getX(), point.getY())))) {
|
||||
matches.add(result.getContent().getName().toString());
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
// 计算外接圆中心(多边形顶点平均值)
|
||||
private Point calculateBoundingCircleCenter(List<Point> points) {
|
||||
double sumX = 0, sumY = 0;
|
||||
for (Point p : points) {
|
||||
sumX += p.getX();
|
||||
sumY += p.getY();
|
||||
}
|
||||
return new Point(sumX / points.size(), sumY / points.size());
|
||||
}
|
||||
|
||||
// 计算最大半径
|
||||
private double calculateMaxRadius(List<Point> points, Point center) {
|
||||
return points.stream()
|
||||
.mapToDouble(p -> Math.sqrt(
|
||||
Math.pow(p.getX() - center.getX(), 2) +
|
||||
Math.pow(p.getY() - center.getY(), 2)))
|
||||
.max().orElse(0)*100;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断点是否在多边形内
|
||||
* @param point 待判断点
|
||||
* @param polygon 多边形顶点
|
||||
* @return 是否在多边形内
|
||||
*/
|
||||
public static boolean isPointInPolygon(Point point, List<Point> polygon) {
|
||||
double x = point.getX();
|
||||
double y = point.getY();
|
||||
|
||||
boolean inside = false;
|
||||
for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) {
|
||||
double xi = polygon.get(i).getX();
|
||||
double yi = polygon.get(i).getY();
|
||||
double xj = polygon.get(j).getX();
|
||||
double yj = polygon.get(j).getY();
|
||||
|
||||
boolean intersect = ((yi > y) != (yj > y))
|
||||
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 Redis 键
|
||||
*
|
||||
*/
|
||||
public void deleteGeoKey() {
|
||||
redisTemplate.delete(geoKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置过期时间
|
||||
* @param key 键
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.cdzy.ebikereport;
|
||||
package com.cdzy.report;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.cdzy.ebikereport.component;
|
||||
package com.cdzy.report.component;
|
||||
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.cdzy.ebikereport.component;
|
||||
package com.cdzy.report.component;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@ -1,12 +1,12 @@
|
||||
package com.cdzy.ebikereport.component;
|
||||
package com.cdzy.report.component;
|
||||
|
||||
|
||||
import com.cdzy.common.model.dto.EbikeTracking;
|
||||
import com.cdzy.common.model.dto.ResGPSDto;
|
||||
import com.cdzy.common.utils.CoordinateUtil;
|
||||
import com.cdzy.ebikereport.enums.BitSwitch;
|
||||
import com.cdzy.ebikereport.utils.BinaryUtil;
|
||||
import com.cdzy.ebikereport.utils.RedisUtil;
|
||||
import com.cdzy.report.enums.BitSwitch;
|
||||
import com.cdzy.report.utils.BinaryUtil;
|
||||
import com.cdzy.report.utils.RedisUtil;
|
||||
import com.ebike.feign.clients.OperationsFeignClient;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.cdzy.ebikereport.config;
|
||||
package com.cdzy.report.config;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.cdzy.ebikereport.config;
|
||||
package com.cdzy.report.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.cdzy.ebikereport.enums;
|
||||
package com.cdzy.report.enums;
|
||||
|
||||
/**
|
||||
* @author attiya
|
||||
@ -1,4 +1,4 @@
|
||||
package com.cdzy.ebikereport.utils;
|
||||
package com.cdzy.report.utils;
|
||||
|
||||
/**
|
||||
* @author attiya
|
||||
@ -1,15 +1,9 @@
|
||||
package com.cdzy.ebikereport.utils;
|
||||
package com.cdzy.report.utils;
|
||||
|
||||
import org.locationtech.jts.geom.Coordinate;
|
||||
import org.locationtech.jts.geom.GeometryFactory;
|
||||
import org.locationtech.jts.geom.Polygon;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.geo.*;
|
||||
import org.springframework.data.redis.connection.RedisGeoCommands;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -24,131 +18,12 @@ public class RedisUtil {
|
||||
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
private final String geoKey="ebike_geo";
|
||||
|
||||
@Autowired
|
||||
public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/* ------------------- key 相关操作 ------------------ */
|
||||
|
||||
/**
|
||||
* 添加地理位置
|
||||
*
|
||||
* @param point 经纬度
|
||||
* @param member 成员名称
|
||||
*/
|
||||
public void addLocation(Point point, String member) {
|
||||
redisTemplate.opsForGeo().add(geoKey, point, member);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定范围内的成员
|
||||
*
|
||||
* @param center 中心点
|
||||
* @param radius 半径(单位:公里)
|
||||
* @return 范围内的成员列表
|
||||
*/
|
||||
public List<String> findNearbyMembers(Point center, double radius) {
|
||||
Distance distance = new Distance(radius, RedisGeoCommands.DistanceUnit.KILOMETERS);
|
||||
Circle circle = new Circle(center, distance);
|
||||
GeoResults<RedisGeoCommands.GeoLocation<Object>> results = redisTemplate.opsForGeo()
|
||||
.radius(geoKey, circle);
|
||||
return results.getContent().stream()
|
||||
.map(geoLocation -> geoLocation.getContent().getName().toString())
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 多边形查询
|
||||
* @param polygonPoints 边界点
|
||||
* @return 成员列表
|
||||
*/
|
||||
public List<String> searchByPolygon( List<Point> polygonPoints ) {
|
||||
|
||||
// 1. 构造多边形
|
||||
GeometryFactory factory = new GeometryFactory();
|
||||
Coordinate[] coordinates = polygonPoints.stream()
|
||||
.map(p -> new Coordinate(p.getX(), p.getY()))
|
||||
.toArray(Coordinate[]::new);
|
||||
Polygon polygon = factory.createPolygon(coordinates);
|
||||
|
||||
// 2. 计算最小外接圆
|
||||
Point center = calculateBoundingCircleCenter(polygonPoints);
|
||||
double radius = calculateMaxRadius(polygonPoints, center);
|
||||
|
||||
// 3. 查询圆内所有点
|
||||
GeoResults<RedisGeoCommands.GeoLocation<Object>> results =
|
||||
redisTemplate.opsForGeo()
|
||||
.radius(geoKey,
|
||||
new Circle(center, new Distance(radius, Metrics.KILOMETERS)),
|
||||
RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
|
||||
.includeCoordinates());
|
||||
|
||||
// 4. 过滤多边形内的点
|
||||
List<String> matches = new ArrayList<>();
|
||||
for (GeoResult<RedisGeoCommands.GeoLocation<Object>> result : results) {
|
||||
Point point = result.getContent().getPoint();
|
||||
if (polygon.contains(factory.createPoint(
|
||||
new Coordinate(point.getX(), point.getY())))) {
|
||||
matches.add(result.getContent().getName().toString());
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
// 计算外接圆中心(多边形顶点平均值)
|
||||
private Point calculateBoundingCircleCenter(List<Point> points) {
|
||||
double sumX = 0, sumY = 0;
|
||||
for (Point p : points) {
|
||||
sumX += p.getX();
|
||||
sumY += p.getY();
|
||||
}
|
||||
return new Point(sumX / points.size(), sumY / points.size());
|
||||
}
|
||||
|
||||
// 计算最大半径
|
||||
private double calculateMaxRadius(List<Point> points, Point center) {
|
||||
return points.stream()
|
||||
.mapToDouble(p -> Math.sqrt(
|
||||
Math.pow(p.getX() - center.getX(), 2) +
|
||||
Math.pow(p.getY() - center.getY(), 2)))
|
||||
.max().orElse(0)*100;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断点是否在多边形内
|
||||
* @param point 待判断点
|
||||
* @param polygon 多边形顶点
|
||||
* @return 是否在多边形内
|
||||
*/
|
||||
public static boolean isPointInPolygon(Point point, List<Point> polygon) {
|
||||
double x = point.getX();
|
||||
double y = point.getY();
|
||||
|
||||
boolean inside = false;
|
||||
for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) {
|
||||
double xi = polygon.get(i).getX();
|
||||
double yi = polygon.get(i).getY();
|
||||
double xj = polygon.get(j).getX();
|
||||
double yj = polygon.get(j).getY();
|
||||
|
||||
boolean intersect = ((yi > y) != (yj > y))
|
||||
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 Redis 键
|
||||
*
|
||||
*/
|
||||
public void deleteGeoKey() {
|
||||
redisTemplate.delete(geoKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置过期时间
|
||||
* @param key 键
|
||||
@ -1,41 +0,0 @@
|
||||
package com.cdzy.ebikereport;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.cdzy.common.model.EbikeTracking;
|
||||
import com.cdzy.common.model.ResGPSDto;
|
||||
import com.cdzy.common.utils.CoordinateUtil;
|
||||
import com.cdzy.ebikereport.enums.BitSwitch;
|
||||
import com.cdzy.ebikereport.utils.BinaryUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.geo.Point;
|
||||
|
||||
@SpringBootTest
|
||||
class EbikeReportApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
|
||||
Integer number = 131082;
|
||||
String binary = BinaryUtil.to32BitBinary(number);
|
||||
binary = new StringBuilder(binary).reverse().toString();
|
||||
System.out.println(binary);
|
||||
char helmet = binary.charAt(BitSwitch.IS_HELMET_EXIT);
|
||||
char acc = binary.charAt(BitSwitch.ACC_ON);
|
||||
System.out.println(acc);
|
||||
char wheelLocked = binary.charAt(BitSwitch.IS_WHEEL_LOCKED);
|
||||
char setLocked = binary.charAt(BitSwitch.IS_SEAT_LOCKED);
|
||||
char isHelmetLocked = binary.charAt(BitSwitch.IS_HELMET_LOCKED);
|
||||
char isWheelSpin = binary.charAt(BitSwitch.IS_WHEEL_SPIN);
|
||||
char isMoving = binary.charAt(BitSwitch.IS_MOVING);
|
||||
ResGPSDto resGpsDto = new ResGPSDto();
|
||||
resGpsDto.setHelmetExit(helmet);
|
||||
resGpsDto.setAccOn(acc);
|
||||
resGpsDto.setWheelLocked(wheelLocked);
|
||||
resGpsDto.setSeatLocked(setLocked);
|
||||
resGpsDto.setIsHelmetLocked(isHelmetLocked);
|
||||
resGpsDto.setIsWheelSpin(isWheelSpin);
|
||||
resGpsDto.setIsMoving(isMoving);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.cdzy.report;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class EbikeReportApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user