1、人员定位大屏区域匹配

master
shenzhidan 2026-08-12 15:15:21 +08:00
parent 44fb60dd2c
commit ddf94df855
2 changed files with 137 additions and 0 deletions

View File

@ -0,0 +1,122 @@
package com.zcloud.personnel.positioning.command.query;
import com.alibaba.cola.exception.BizException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zcloud.personnel.positioning.persistence.dataobject.AreaDO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 使
*/
@Component
@RequiredArgsConstructor
class PositionAreaMatcher {
private final ObjectMapper objectMapper;
/**
* JSON
*/
List<AreaPolygon> prepare(List<AreaDO> areas) {
if (areas == null || areas.isEmpty()) {
return Collections.emptyList();
}
List<AreaPolygon> result = new ArrayList<>(areas.size());
for (AreaDO area : areas) {
result.add(new AreaPolygon(area, parsePolygon(area.getPolygonJson())));
}
return result;
}
/**
* 使
*/
AreaDO match(BigDecimal lon, BigDecimal lat, List<AreaPolygon> areas) {
if (lon == null || lat == null || areas == null) {
return null;
}
for (AreaPolygon area : areas) {
if (isPointInPolygon(lon, lat, area.points)) {
return area.area;
}
}
return null;
}
/**
* JSON FindS
*/
private List<BigDecimal[]> parsePolygon(String polygonJson) {
List<BigDecimal[]> points = new ArrayList<>();
if (!StringUtils.hasText(polygonJson)) {
return points;
}
try {
collectPoints(objectMapper.readTree(polygonJson), points);
} catch (IOException e) {
throw new BizException("区域边界坐标JSON格式错误");
}
return points;
}
private void collectPoints(JsonNode node, List<BigDecimal[]> points) {
if (node == null || node.isNull() || node.isMissingNode()) {
return;
}
if (node.isObject()) {
node.elements().forEachRemaining(child -> collectPoints(child, points));
return;
}
if (!node.isArray()) {
return;
}
if (node.size() >= 2 && node.get(0).isNumber() && node.get(1).isNumber()) {
points.add(new BigDecimal[]{node.get(0).decimalValue(), node.get(1).decimalValue()});
return;
}
for (JsonNode child : node) {
collectPoints(child, points);
}
}
/**
* 使线
*/
private boolean isPointInPolygon(BigDecimal lon, BigDecimal lat, List<BigDecimal[]> points) {
if (points == null || points.size() < 3) {
return false;
}
boolean inside = false;
double x = lon.doubleValue();
double y = lat.doubleValue();
for (int i = 0, j = points.size() - 1; i < points.size(); j = i++) {
double xi = points.get(i)[0].doubleValue();
double yi = points.get(i)[1].doubleValue();
double xj = points.get(j)[0].doubleValue();
double yj = points.get(j)[1].doubleValue();
if ((yi > y) != (yj > y)
&& x < (xj - xi) * (y - yi) / (yj - yi) + xi) {
inside = !inside;
}
}
return inside;
}
static class AreaPolygon {
private final AreaDO area;
private final List<BigDecimal[]> points;
private AreaPolygon(AreaDO area, List<BigDecimal[]> points) {
this.area = area;
this.points = points;
}
}
}

View File

@ -0,0 +1,15 @@
package com.zcloud.personnel.positioning.persistence.dataobject;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
*
*/
@Data
@AllArgsConstructor
public class PersonnelLocationAreaUpdateDO {
private String findsStaffNo;
private Long locationAreaId;
private String locationAreaName;
}