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 implements ISiteService { @Resource private SiteMapper siteMapper; @Resource private LocationMapper locationMapper; @Resource private DriverSelfTripMapper driverSelfTripMapper; @Autowired private ObjectProvider mongoTemplateProvider; @Autowired private RestTemplate restTemplate; private static final String AMAP_KEY = "6dd64582ed31b84134ac38b2355eb82b"; /** * 获取站点 * @return * @throws Exception */ @Override public List querySite(Integer startSiteId) throws Exception { List> sites = null; if(null == startSiteId){ sites = siteMapper.querySite(null); }else{ sites = siteMapper.querySite(startSiteId); } Set set = new HashSet<>(); for(Map site : sites) { set.add(site.get("cityCode").toString()); } List list = new ArrayList<>(); for(String c : set){ SiteWarpper siteWarpper = new SiteWarpper(); List data = new ArrayList<>(); String name = ""; String code = ""; for(Map s : sites){ if(c.equals(s.get("cityCode").toString())){ Map 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> list = this.queryLocation(siteId); String province = code.toString().substring(0, 2) + "0000"; String city = code.toString().substring(0, 4) + "00"; for(Map 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> 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 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 siteList = this.selectList(new EntityWrapper().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> 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 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 geoFencingPolygons = mongoTemplate.find(query, GeoFencingPolygon.class); if (geoFencingPolygons == null || geoFencingPolygons.size() <= 0) { return false; } List 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; } } }