package com.stylefeng.guns.modular.crossCity.server.impl;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import com.baomidou.mybatisplus.mapper.EntityWrapper;
|
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
|
import com.stylefeng.guns.core.util.ToolUtil;
|
import com.stylefeng.guns.modular.crossCity.dao.DriverSelfTripMapper;
|
import com.stylefeng.guns.modular.crossCity.dao.LocationMapper;
|
import com.stylefeng.guns.modular.crossCity.dao.SiteMapper;
|
import com.stylefeng.guns.modular.crossCity.model.DriverSelfTrip;
|
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 com.stylefeng.guns.modular.system.util.model.GeoFencingPolygon;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
|
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.stereotype.Service;
|
import org.springframework.web.client.RestTemplate;
|
|
import javax.annotation.Resource;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
|
@Service
|
public class SiteServiceImpl extends ServiceImpl<SiteMapper, Site> implements ISiteService {
|
|
@Resource
|
private SiteMapper siteMapper;
|
|
@Resource
|
private LocationMapper locationMapper;
|
|
@Resource
|
private DriverSelfTripMapper driverSelfTripMapper;
|
|
@Autowired
|
private ObjectProvider<MongoTemplate> mongoTemplateProvider;
|
|
@Autowired
|
private RestTemplate restTemplate;
|
|
private static final String AMAP_KEY = "6dd64582ed31b84134ac38b2355eb82b";
|
|
|
/**
|
* 获取站点
|
* @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, Integer code, String lonLat) throws Exception {
|
List<Map<String, Object>> list = this.queryLocation(siteId);
|
String province = code.toString().substring(0, 2) + "0000";
|
String city = code.toString().substring(0, 4) + "00";
|
for(Map<String, Object> map : list){
|
if(Integer.valueOf(map.get("type").toString()) == 1){//行政区域
|
if(null != map.get("districtCode")){
|
if(code.toString().equals(map.get("districtCode").toString())){
|
return true;
|
}
|
continue;
|
}
|
if(null != map.get("cityCode")){
|
if(city.equals(map.get("cityCode").toString())){
|
return true;
|
}
|
continue;
|
}
|
if(null != map.get("provinceCode")){
|
if(province.equals(map.get("provinceCode").toString())){
|
return true;
|
}
|
continue;
|
}
|
}
|
if(Integer.valueOf(map.get("type").toString()) == 2){//电子围栏
|
if(matchAreaType2(siteId, lonLat)){
|
return true;
|
}
|
}
|
}
|
return true;
|
}
|
|
/**
|
* 根据站点id获取地点区域
|
* @param siteId
|
* @return
|
* @throws Exception
|
*/
|
@Override
|
public List<Map<String, Object>> queryLocation(Integer siteId) throws Exception {
|
if (siteId == null || siteId >= 0) {
|
return locationMapper.queryLocation(siteId);
|
}
|
int absSiteId = Math.abs(siteId);
|
int selfTripId = absSiteId / 10;
|
int typeFlag = absSiteId % 10;
|
if (selfTripId <= 0 || (typeFlag != 1 && typeFlag != 2)) {
|
return new ArrayList<>();
|
}
|
DriverSelfTrip selfTrip = driverSelfTripMapper.selectById(selfTripId);
|
if (selfTrip == null || selfTrip.getState() == null || selfTrip.getState() != 1) {
|
return new ArrayList<>();
|
}
|
|
Map<String, Object> location = new HashMap<>();
|
location.put("type", 2);
|
if (typeFlag == 1) {
|
if (selfTrip.getStartLon() == null || selfTrip.getStartLat() == null) {
|
return new ArrayList<>();
|
}
|
location.put("coordinate", selfTrip.getStartLon() + "," + selfTrip.getStartLat() + ";3000");
|
return Collections.singletonList(location);
|
}
|
|
if (ToolUtil.isEmpty(selfTrip.getDestJson())) {
|
return new ArrayList<>();
|
}
|
JSONArray destArray = JSON.parseArray(selfTrip.getDestJson());
|
if (destArray == null || destArray.size() == 0) {
|
return new ArrayList<>();
|
}
|
StringBuilder sb = new StringBuilder();
|
for (int i = 0; i < destArray.size(); i++) {
|
JSONObject dest = destArray.getJSONObject(i);
|
if (dest == null || dest.getDouble("endLon") == null || dest.getDouble("endLat") == null) {
|
continue;
|
}
|
if (sb.length() > 0) {
|
sb.append("_");
|
}
|
sb.append(dest.getDouble("endLon")).append(",").append(dest.getDouble("endLat")).append(";3000");
|
}
|
if (sb.length() == 0) {
|
return new ArrayList<>();
|
}
|
location.put("coordinate", sb.toString());
|
return Collections.singletonList(location);
|
}
|
|
/**
|
* 根据经纬度查询所在站点(命中多个时返回第一个)
|
*/
|
@Override
|
public Site querySiteByLonLat(Double lon, Double lat) throws Exception {
|
if (lon == null || lat == null) {
|
return null;
|
}
|
List<Site> siteList = this.selectList(new EntityWrapper<Site>().eq("state", 1).orderBy("id", true));
|
if (siteList == null || siteList.size() <= 0) {
|
return null;
|
}
|
Site nearest = null;
|
Double minDistance = null;
|
for (Site site : siteList) {
|
if (site == null || site.getId() == null) {
|
continue;
|
}
|
if (site.getDefaultPointLon() == null || site.getDefaultPointLat() == null) {
|
continue;
|
}
|
double distance = calcDistanceMeters(lat, lon, site.getDefaultPointLat(), site.getDefaultPointLon());
|
if (minDistance == null || distance < minDistance) {
|
minDistance = distance;
|
nearest = site;
|
}
|
}
|
return nearest;
|
}
|
|
private double calcDistanceMeters(double lat1, double lon1, double lat2, double lon2) {
|
double earthRadius = 6371000D;
|
double dLat = Math.toRadians(lat2 - lat1);
|
double dLon = Math.toRadians(lon2 - lon1);
|
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
|
+ Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
|
* Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
return earthRadius * c;
|
}
|
|
private boolean matchAreaType1(List<Map<String, Object>> locations, String adCode) {
|
if (ToolUtil.isEmpty(adCode)) {
|
return false;
|
}
|
if (adCode.length() < 4) {
|
return false;
|
}
|
String province = adCode.substring(0, 2) + "0000";
|
String city = adCode.substring(0, 4) + "00";
|
for (Map<String, Object> map : locations) {
|
if (map == null || map.get("type") == null) {
|
continue;
|
}
|
if (Integer.valueOf(map.get("type").toString()) != 1) {
|
continue;
|
}
|
if (map.get("districtCode") != null && adCode.equals(map.get("districtCode").toString())) {
|
return true;
|
}
|
if (map.get("cityCode") != null && city.equals(map.get("cityCode").toString())) {
|
return true;
|
}
|
if (map.get("provinceCode") != null && province.equals(map.get("provinceCode").toString())) {
|
return true;
|
}
|
}
|
return false;
|
}
|
|
private boolean matchAreaType2(Integer siteId, String lonLat) {
|
MongoTemplate mongoTemplate;
|
try {
|
mongoTemplate = mongoTemplateProvider.getIfAvailable();
|
} catch (Exception ex) {
|
return false;
|
}
|
if (mongoTemplate == null || ToolUtil.isEmpty(lonLat)) {
|
return false;
|
}
|
String[] split = lonLat.split(",");
|
if (split.length != 2) {
|
return false;
|
}
|
GeoJsonPoint point = new GeoJsonPoint(Double.valueOf(split[0]), Double.valueOf(split[1]));
|
Query query = Query.query(Criteria.where("geoJsonPolygon").intersects(point));
|
List<GeoFencingPolygon> geoFencingPolygons = mongoTemplate.find(query, GeoFencingPolygon.class);
|
if (geoFencingPolygons == null || geoFencingPolygons.size() <= 0) {
|
return false;
|
}
|
List<Integer> siteIds = geoFencingPolygons.stream().map(GeoFencingPolygon::getSiteId).collect(Collectors.toList());
|
return siteIds.contains(siteId);
|
}
|
|
private String getAdCodeByLonLat(Double lon, Double lat) {
|
try {
|
String location = lon + "," + lat;
|
String url = "https://restapi.amap.com/v3/geocode/regeo?key=" + AMAP_KEY + "&location=" + location;
|
String body = restTemplate.getForObject(url, String.class);
|
if (ToolUtil.isEmpty(body)) {
|
return null;
|
}
|
com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSON.parseObject(body);
|
if (!"1".equals(jsonObject.getString("status"))) {
|
return null;
|
}
|
com.alibaba.fastjson.JSONObject regeocode = jsonObject.getJSONObject("regeocode");
|
if (regeocode == null) {
|
return null;
|
}
|
com.alibaba.fastjson.JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
|
if (addressComponent == null) {
|
return null;
|
}
|
return addressComponent.getString("adcode");
|
} catch (Exception ex) {
|
return null;
|
}
|
}
|
}
|