package com.stylefeng.guns.modular.crossCity.server.impl;
|
|
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
|
import com.stylefeng.guns.modular.crossCity.dao.LocationMapper;
|
import com.stylefeng.guns.modular.crossCity.dao.SiteMapper;
|
import com.stylefeng.guns.modular.crossCity.model.Site;
|
import com.stylefeng.guns.modular.crossCity.server.ISiteService;
|
import com.stylefeng.guns.modular.crossCity.warpper.SiteWarpper;
|
import org.springframework.stereotype.Service;
|
|
import javax.annotation.Resource;
|
import java.util.*;
|
|
|
@Service
|
public class SiteServiceImpl extends ServiceImpl<SiteMapper, Site> implements ISiteService {
|
|
@Resource
|
private SiteMapper siteMapper;
|
|
@Resource
|
private LocationMapper locationMapper;
|
|
private static final double COORDINATE_EPSILON = 1E-10;
|
|
|
/**
|
* 获取站点
|
* @return
|
* @throws Exception
|
*/
|
@Override
|
public List<SiteWarpper> querySite(Integer startSiteId) throws Exception {
|
List<Map<String, Object>> sites = null;
|
if(null == startSiteId){
|
sites = siteMapper.querySite(null);
|
}else{
|
sites = siteMapper.querySite(startSiteId);
|
}
|
Set<String> set = new HashSet<>();
|
for(Map<String, Object> site : sites) {
|
set.add(site.get("cityCode").toString());
|
}
|
|
List<SiteWarpper> list = new ArrayList<>();
|
for(String c : set){
|
SiteWarpper siteWarpper = new SiteWarpper();
|
List<Object> data = new ArrayList<>();
|
String name = "";
|
String code = "";
|
for(Map<String, Object> s : sites){
|
if(c.equals(s.get("cityCode").toString())){
|
Map<String, Object> map = new HashMap<>();
|
map.put("id", s.get("id"));
|
map.put("name", s.get("name").toString());
|
name = s.get("cityName").toString();
|
code = s.get("cityCode").toString();
|
data.add(map);
|
}
|
}
|
siteWarpper.setName(name);
|
siteWarpper.setCode(code);
|
siteWarpper.setSites(data);
|
list.add(siteWarpper);
|
}
|
return list;
|
}
|
|
|
/**
|
* 判断点是都在区域范围内
|
* @param siteId
|
* @param code
|
* @param lonLat
|
* @return
|
* @throws Exception
|
*/
|
@Override
|
public boolean areaMonitoring(Integer siteId, String code, String lonLat) throws Exception {
|
List<Map<String, Object>> list = this.queryLocation(siteId);
|
for(Map<String, Object> map : list){
|
if(Integer.valueOf(map.get("type").toString()) == 1){//行政区域
|
if(null != map.get("districtCode")){
|
if(code.equals(map.get("districtCode").toString())){
|
return true;
|
}
|
continue;
|
}
|
if(null != map.get("cityCode")){
|
if(code.equals(map.get("cityCode").toString())){
|
return true;
|
}
|
code = code.substring(0, 4) + "00";
|
if(code.equals(map.get("cityCode").toString())){
|
return true;
|
}
|
continue;
|
}
|
if(null != map.get("provinceCode")){
|
code = code.substring(0, 2) + "0000";
|
if(code.equals(map.get("provinceCode").toString())){
|
return true;
|
}
|
continue;
|
}
|
}
|
if(Integer.valueOf(map.get("type").toString()) == 2){//电子围栏
|
Object coordinate = map.get("coordinate");
|
if(coordinate != null && isPointInElectronicFence(lonLat, coordinate.toString())){
|
return true;
|
}
|
continue;
|
}
|
}
|
return false;
|
}
|
|
static boolean isPointInElectronicFence(String lonLat, String coordinate) {
|
double[] point = parseCoordinate(lonLat);
|
if (point == null || coordinate == null || coordinate.trim().isEmpty()) {
|
return false;
|
}
|
String[] fences = coordinate.split("_");
|
for (String fence : fences) {
|
String[] coordinatePoints = fence.split(";");
|
if (coordinatePoints.length < 3) {
|
continue;
|
}
|
List<double[]> polygon = new ArrayList<>();
|
boolean validPolygon = true;
|
for (String coordinatePoint : coordinatePoints) {
|
double[] vertex = parseCoordinate(coordinatePoint);
|
if (vertex == null) {
|
validPolygon = false;
|
break;
|
}
|
polygon.add(vertex);
|
}
|
if (validPolygon && isPointInPolygon(point, polygon)) {
|
return true;
|
}
|
}
|
return false;
|
}
|
|
private static double[] parseCoordinate(String coordinate) {
|
if (coordinate == null || coordinate.trim().isEmpty()) {
|
return null;
|
}
|
String[] values = coordinate.trim().split(",");
|
if (values.length != 2) {
|
return null;
|
}
|
try {
|
double longitude = Double.parseDouble(values[0].trim());
|
double latitude = Double.parseDouble(values[1].trim());
|
if (Double.isNaN(longitude) || Double.isInfinite(longitude)
|
|| Double.isNaN(latitude) || Double.isInfinite(latitude)) {
|
return null;
|
}
|
return new double[]{longitude, latitude};
|
} catch (NumberFormatException e) {
|
return null;
|
}
|
}
|
|
private static boolean isPointInPolygon(double[] point, List<double[]> polygon) {
|
boolean inside = false;
|
for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) {
|
double[] start = polygon.get(j);
|
double[] end = polygon.get(i);
|
if (isPointOnSegment(point, start, end)) {
|
return true;
|
}
|
boolean intersects = (start[1] > point[1]) != (end[1] > point[1])
|
&& point[0] < (end[0] - start[0]) * (point[1] - start[1])
|
/ (end[1] - start[1]) + start[0];
|
if (intersects) {
|
inside = !inside;
|
}
|
}
|
return inside;
|
}
|
|
private static boolean isPointOnSegment(double[] point, double[] start, double[] end) {
|
double crossProduct = (point[0] - start[0]) * (end[1] - start[1])
|
- (point[1] - start[1]) * (end[0] - start[0]);
|
if (Math.abs(crossProduct) > COORDINATE_EPSILON) {
|
return false;
|
}
|
return point[0] >= Math.min(start[0], end[0]) - COORDINATE_EPSILON
|
&& point[0] <= Math.max(start[0], end[0]) + COORDINATE_EPSILON
|
&& point[1] >= Math.min(start[1], end[1]) - COORDINATE_EPSILON
|
&& point[1] <= Math.max(start[1], end[1]) + COORDINATE_EPSILON;
|
}
|
|
/**
|
* 根据站点id获取地点区域
|
* @param siteId
|
* @return
|
* @throws Exception
|
*/
|
@Override
|
public List<Map<String, Object>> queryLocation(Integer siteId) throws Exception {
|
return locationMapper.queryLocation(siteId);
|
}
|
}
|