Commit ea43080336788d609cbf12c16abbcec39b4a0da5
1 parent
0cf6e342
update
Showing
14 changed files
with
333 additions
and
77 deletions
src/main/java/com/bsth/data/gpsdata/GpsEntity.java
| @@ -67,16 +67,10 @@ public class GpsEntity { | @@ -67,16 +67,10 @@ public class GpsEntity { | ||
| 67 | /** 当前执行班次ID */ | 67 | /** 当前执行班次ID */ |
| 68 | private Long schId; | 68 | private Long schId; |
| 69 | 69 | ||
| 70 | - /** 是否异常数据 */ | ||
| 71 | - private boolean abnormal; | ||
| 72 | -/* | ||
| 73 | - private int valid;*/ | ||
| 74 | - | ||
| 75 | - private int version; | 70 | + /** 是否是不完整的数据 */ |
| 71 | + private boolean incomplete; | ||
| 76 | 72 | ||
| 77 | - /** 是否起终点站 | ||
| 78 | - private boolean sEPoint; | ||
| 79 | - */ | 73 | + private int version; |
| 80 | 74 | ||
| 81 | /** 0: 站外 1:站内 2:场内 */ | 75 | /** 0: 站外 1:站内 2:场内 */ |
| 82 | private int instation; | 76 | private int instation; |
| @@ -88,6 +82,12 @@ public class GpsEntity { | @@ -88,6 +82,12 @@ public class GpsEntity { | ||
| 88 | /** 状态 */ | 82 | /** 状态 */ |
| 89 | private String signalState = "normal"; | 83 | private String signalState = "normal"; |
| 90 | 84 | ||
| 85 | + /** 异常状态 */ | ||
| 86 | + private String abnormalStatus; | ||
| 87 | + | ||
| 88 | + /** 越界距离 */ | ||
| 89 | + private double outOfBoundDistance; | ||
| 90 | + | ||
| 91 | public Integer getCompanyCode() { | 91 | public Integer getCompanyCode() { |
| 92 | return companyCode; | 92 | return companyCode; |
| 93 | } | 93 | } |
| @@ -241,14 +241,6 @@ public class GpsEntity { | @@ -241,14 +241,6 @@ public class GpsEntity { | ||
| 241 | this.station = station; | 241 | this.station = station; |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | - public boolean isAbnormal() { | ||
| 245 | - return abnormal; | ||
| 246 | - } | ||
| 247 | - | ||
| 248 | - public void setAbnormal(boolean abnormal) { | ||
| 249 | - this.abnormal = abnormal; | ||
| 250 | - } | ||
| 251 | - | ||
| 252 | public String getSignalState() { | 244 | public String getSignalState() { |
| 253 | return signalState; | 245 | return signalState; |
| 254 | } | 246 | } |
| @@ -264,4 +256,28 @@ public class GpsEntity { | @@ -264,4 +256,28 @@ public class GpsEntity { | ||
| 264 | public void setInstation(int instation) { | 256 | public void setInstation(int instation) { |
| 265 | this.instation = instation; | 257 | this.instation = instation; |
| 266 | } | 258 | } |
| 259 | + | ||
| 260 | + public String getAbnormalStatus() { | ||
| 261 | + return abnormalStatus; | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + public void setAbnormalStatus(String abnormalStatus) { | ||
| 265 | + this.abnormalStatus = abnormalStatus; | ||
| 266 | + } | ||
| 267 | + | ||
| 268 | + public boolean isIncomplete() { | ||
| 269 | + return incomplete; | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + public void setIncomplete(boolean incomplete) { | ||
| 273 | + this.incomplete = incomplete; | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + public double getOutOfBoundDistance() { | ||
| 277 | + return outOfBoundDistance; | ||
| 278 | + } | ||
| 279 | + | ||
| 280 | + public void setOutOfBoundDistance(double outOfBoundDistance) { | ||
| 281 | + this.outOfBoundDistance = outOfBoundDistance; | ||
| 282 | + } | ||
| 267 | } | 283 | } |
src/main/java/com/bsth/data/gpsdata/GpsRealData.java
| @@ -122,7 +122,7 @@ public class GpsRealData implements CommandLineRunner { | @@ -122,7 +122,7 @@ public class GpsRealData implements CommandLineRunner { | ||
| 122 | for (String device : set) { | 122 | for (String device : set) { |
| 123 | gps = gpsMap.get(device); | 123 | gps = gpsMap.get(device); |
| 124 | //过滤异常GPS数据 | 124 | //过滤异常GPS数据 |
| 125 | - if (gps == null || gps.isAbnormal()) | 125 | + if (gps == null || gps.isIncomplete()) |
| 126 | continue; | 126 | continue; |
| 127 | 127 | ||
| 128 | sch = dayOfSchedule.execPlanMap().get(gps.getNbbm()); | 128 | sch = dayOfSchedule.execPlanMap().get(gps.getNbbm()); |
| @@ -220,7 +220,7 @@ public class GpsRealData implements CommandLineRunner { | @@ -220,7 +220,7 @@ public class GpsRealData implements CommandLineRunner { | ||
| 220 | 220 | ||
| 221 | nbbm = BasicData.deviceId2NbbmMap.get(gps.getDeviceId()); | 221 | nbbm = BasicData.deviceId2NbbmMap.get(gps.getDeviceId()); |
| 222 | if (StringUtils.isBlank(nbbm)) | 222 | if (StringUtils.isBlank(nbbm)) |
| 223 | - gps.setAbnormal(true);//标记为异常数据 | 223 | + gps.setIncomplete(true);//标记为异常数据 |
| 224 | else | 224 | else |
| 225 | gps.setNbbm(nbbm); | 225 | gps.setNbbm(nbbm); |
| 226 | //有更新的点位 | 226 | //有更新的点位 |
src/main/java/com/bsth/data/gpsdata/arrival/GeoCacheData.java
| @@ -45,6 +45,9 @@ public class GeoCacheData { | @@ -45,6 +45,9 @@ public class GeoCacheData { | ||
| 45 | //停车场 | 45 | //停车场 |
| 46 | public static Map<String, Polygon> tccMap; | 46 | public static Map<String, Polygon> tccMap; |
| 47 | 47 | ||
| 48 | + //线路限速信息 | ||
| 49 | + private static Map<String, Double> speedLimitMap; | ||
| 50 | + | ||
| 48 | @Autowired | 51 | @Autowired |
| 49 | JdbcTemplate jdbcTemplate; | 52 | JdbcTemplate jdbcTemplate; |
| 50 | 53 | ||
| @@ -94,6 +97,14 @@ public class GeoCacheData { | @@ -94,6 +97,14 @@ public class GeoCacheData { | ||
| 94 | return null; | 97 | return null; |
| 95 | } | 98 | } |
| 96 | 99 | ||
| 100 | + public static Double speedLimit(String lineCode){ | ||
| 101 | + return speedLimitMap.get(lineCode); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + public static List<LineString> getLineStringList(GpsEntity gps){ | ||
| 105 | + return sectionCacheMap.get(gps.getLineId() + "_" + gps.getUpDown()); | ||
| 106 | + } | ||
| 107 | + | ||
| 97 | public static List<StationRoute> midwayStation(String lineCode, int directions, String sCode, String eCode) { | 108 | public static List<StationRoute> midwayStation(String lineCode, int directions, String sCode, String eCode) { |
| 98 | List<StationRoute> list = getStationRoute(lineCode, directions), rs = new ArrayList<>(); | 109 | List<StationRoute> list = getStationRoute(lineCode, directions), rs = new ArrayList<>(); |
| 99 | 110 | ||
| @@ -113,8 +124,72 @@ public class GeoCacheData { | @@ -113,8 +124,72 @@ public class GeoCacheData { | ||
| 113 | return tccMap.get(code); | 124 | return tccMap.get(code); |
| 114 | } | 125 | } |
| 115 | 126 | ||
| 127 | + GeometryFactory geometryFactory = new GeometryFactory(); | ||
| 116 | public void loadData() { | 128 | public void loadData() { |
| 117 | - final GeometryFactory geometryFactory = new GeometryFactory(); | 129 | + loadStationRoutesData(); |
| 130 | + loadTccMapData(); | ||
| 131 | + loadSpeedLimit(); | ||
| 132 | + | ||
| 133 | + //加载路段信息 | ||
| 134 | + loadRoadsData(); | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + private void loadRoadsData() { | ||
| 138 | + String sql = "select r.LINE_CODE,r.SECTION_CODE,r.SECTIONROUTE_CODE,s.SECTION_NAME,ST_AsText(s.GSECTION_VECTOR) as GSECTION_VECTOR, r.DIRECTIONS from bsth_c_sectionroute r INNER JOIN bsth_c_section s on r.section=s.id where r.destroy=0 and GSECTION_VECTOR is not null order by line_code,directions,sectionroute_code"; | ||
| 139 | + List<Map<String, Object>> secList = jdbcTemplate.queryForList(sql); | ||
| 140 | + | ||
| 141 | + String polygonStr, key; | ||
| 142 | + String[] coords; | ||
| 143 | + int i, len; | ||
| 144 | + | ||
| 145 | + ArrayListMultimap<String, LineString> sectionCacheTempMap = ArrayListMultimap.create(); | ||
| 146 | + Coordinate[] cds; | ||
| 147 | + String[] temps1, temps2; | ||
| 148 | + for (Map<String, Object> tMap : secList) { | ||
| 149 | + polygonStr = tMap.get("GSECTION_VECTOR").toString(); | ||
| 150 | + key = tMap.get("LINE_CODE") + "_" + tMap.get("DIRECTIONS"); | ||
| 151 | + | ||
| 152 | + coords = polygonStr.substring(11, polygonStr.length() - 1).split(","); | ||
| 153 | + len = coords.length - 1; | ||
| 154 | + //每2个点连一条线 | ||
| 155 | + for(i = 0; i < len; i ++){ | ||
| 156 | + temps1 = coords[i].split(" "); | ||
| 157 | + temps2 = coords[i + 1].split(" "); | ||
| 158 | + | ||
| 159 | + cds = new Coordinate[2]; | ||
| 160 | + cds[0] = new Coordinate(Float.parseFloat(temps1[1]), Float.parseFloat(temps1[0])); | ||
| 161 | + cds[1] = new Coordinate(Float.parseFloat(temps2[1]), Float.parseFloat(temps2[0])); | ||
| 162 | + | ||
| 163 | + sectionCacheTempMap.put(key, geometryFactory.createLineString(cds)); | ||
| 164 | + } | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + if(sectionCacheTempMap.size() > 0) | ||
| 168 | + sectionCacheMap = sectionCacheTempMap; | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + private void loadTccMapData(){ | ||
| 172 | + //加载停车场数据 | ||
| 173 | + String sql = "select PARK_CODE, ST_AsText(G_PARK_POINT) as G_PARK_POINT from bsth_c_car_park where park_code is not null and b_park_point is not null"; | ||
| 174 | + List<Map<String, Object>> tccList = jdbcTemplate.queryForList(sql); | ||
| 175 | + Map<String, Polygon> tccTempMap = new HashMap<>(); | ||
| 176 | + | ||
| 177 | + Polygon polygon; | ||
| 178 | + for (Map<String, Object> tMap : tccList) { | ||
| 179 | + | ||
| 180 | + try { | ||
| 181 | + polygon = geometryFactory.createPolygon(parsePolygon(tMap.get("G_PARK_POINT").toString())); | ||
| 182 | + tccTempMap.put(tMap.get("PARK_CODE").toString() | ||
| 183 | + , polygon); | ||
| 184 | + } catch (Exception e) { | ||
| 185 | + logger.error("停车场:" + tMap.get("PARK_CODE"), e); | ||
| 186 | + } | ||
| 187 | + } | ||
| 188 | + if (tccTempMap.size() > 0) | ||
| 189 | + tccMap = tccTempMap; | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + private void loadStationRoutesData(){ | ||
| 118 | //加载站点路由 | 193 | //加载站点路由 |
| 119 | String sql = "select r.LINE_CODE,r.DIRECTIONS,r.STATION_CODE,r.STATION_MARK,s.SHAPES_TYPE,s.G_LONX,s.G_LATY,ST_AsText(s.G_POLYGON_GRID) as G_POLYGON_GRID,s.RADIUS, r.STATION_ROUTE_CODE,s.STATION_NAME from bsth_c_stationroute r left join bsth_c_station s on r.station=s.id where r.destroy=0 order by r.station_route_code"; | 194 | String sql = "select r.LINE_CODE,r.DIRECTIONS,r.STATION_CODE,r.STATION_MARK,s.SHAPES_TYPE,s.G_LONX,s.G_LATY,ST_AsText(s.G_POLYGON_GRID) as G_POLYGON_GRID,s.RADIUS, r.STATION_ROUTE_CODE,s.STATION_NAME from bsth_c_stationroute r left join bsth_c_station s on r.station=s.id where r.destroy=0 order by r.station_route_code"; |
| 120 | List<StationRoute> routeList = jdbcTemplate.query(sql, new RowMapper<StationRoute>() { | 195 | List<StationRoute> routeList = jdbcTemplate.query(sql, new RowMapper<StationRoute>() { |
| @@ -159,26 +234,17 @@ public class GeoCacheData { | @@ -159,26 +234,17 @@ public class GeoCacheData { | ||
| 159 | stationCacheMap = tempMap; | 234 | stationCacheMap = tempMap; |
| 160 | routeCodeMap = codeMap; | 235 | routeCodeMap = codeMap; |
| 161 | } | 236 | } |
| 237 | + } | ||
| 162 | 238 | ||
| 163 | - //加载停车场数据 | ||
| 164 | - sql = "select PARK_CODE, ST_AsText(G_PARK_POINT) as G_PARK_POINT from bsth_c_car_park where park_code is not null and b_park_point is not null"; | ||
| 165 | - List<Map<String, Object>> tccList = jdbcTemplate.queryForList(sql); | ||
| 166 | - Map<String, Polygon> tccTempMap = new HashMap<>(); | ||
| 167 | - | ||
| 168 | - Polygon polygon; | ||
| 169 | - for (Map<String, Object> tMap : tccList) { | ||
| 170 | - | ||
| 171 | - try { | ||
| 172 | - polygon = geometryFactory.createPolygon(parsePolygon(tMap.get("G_PARK_POINT").toString())); | ||
| 173 | - tccTempMap.put(tMap.get("PARK_CODE").toString() | ||
| 174 | - , polygon); | ||
| 175 | - } catch (Exception e) { | ||
| 176 | - logger.error("停车场:" + tMap.get("PARK_CODE"), e); | ||
| 177 | - } | 239 | + private void loadSpeedLimit(){ |
| 240 | + //加载线路限速信息 | ||
| 241 | + String sql = "select l.LINE_CODE,i.SPEED_LIMIT from bsth_c_line_information i left join bsth_c_line l on i.line=l.id where i.speed_limit is not null"; | ||
| 242 | + List<Map<String, Object>> speedMap = jdbcTemplate.queryForList(sql); | ||
| 243 | + Map<String, Double> speedTempMap = new HashMap<>(); | ||
| 244 | + for (Map<String, Object> tMap : speedMap) { | ||
| 245 | + speedTempMap.put(tMap.get("LINE_CODE").toString(), Double.parseDouble(tMap.get("SPEED_LIMIT").toString())); | ||
| 178 | } | 246 | } |
| 179 | - | ||
| 180 | - if (tccTempMap.size() > 0) | ||
| 181 | - tccMap = tccTempMap; | 247 | + speedLimitMap = speedTempMap; |
| 182 | } | 248 | } |
| 183 | 249 | ||
| 184 | private void connectStationRoute(List<StationRoute> list) { | 250 | private void connectStationRoute(List<StationRoute> list) { |
| @@ -209,6 +275,7 @@ public class GeoCacheData { | @@ -209,6 +275,7 @@ public class GeoCacheData { | ||
| 209 | 275 | ||
| 210 | /** | 276 | /** |
| 211 | * 是不是终点站 | 277 | * 是不是终点站 |
| 278 | + * | ||
| 212 | * @param lineId | 279 | * @param lineId |
| 213 | * @param upDown | 280 | * @param upDown |
| 214 | * @param stationCode | 281 | * @param stationCode |
src/main/java/com/bsth/data/gpsdata/arrival/GpsRealAnalyse.java
| @@ -33,6 +33,8 @@ public class GpsRealAnalyse { | @@ -33,6 +33,8 @@ public class GpsRealAnalyse { | ||
| 33 | InOutStationSignalHandle inOutStationSignalHandle; | 33 | InOutStationSignalHandle inOutStationSignalHandle; |
| 34 | @Autowired | 34 | @Autowired |
| 35 | ReverseSignalHandle reverseSignalHandle; | 35 | ReverseSignalHandle reverseSignalHandle; |
| 36 | + @Autowired | ||
| 37 | + AbnormalStateHandle abnormalStateHandle; | ||
| 36 | 38 | ||
| 37 | @Autowired | 39 | @Autowired |
| 38 | GpsRealData gpsRealData; | 40 | GpsRealData gpsRealData; |
| @@ -72,14 +74,21 @@ public class GpsRealAnalyse { | @@ -72,14 +74,21 @@ public class GpsRealAnalyse { | ||
| 72 | public void run() { | 74 | public void run() { |
| 73 | 75 | ||
| 74 | try { | 76 | try { |
| 77 | + //是否有任务 | ||
| 78 | + boolean task; | ||
| 75 | CircleQueue<GpsEntity> prevs = GeoCacheData.getGps(gps.getNbbm()); | 79 | CircleQueue<GpsEntity> prevs = GeoCacheData.getGps(gps.getNbbm()); |
| 76 | //掉线处理 | 80 | //掉线处理 |
| 77 | offlineSignalHandle.handle(gps, prevs); | 81 | offlineSignalHandle.handle(gps, prevs); |
| 78 | //状态处理 | 82 | //状态处理 |
| 79 | - if(!correctSignalHandle.handle(gps, prevs)) | ||
| 80 | - return; | 83 | + task = correctSignalHandle.handle(gps, prevs); |
| 81 | //场,站内外判断 | 84 | //场,站内外判断 |
| 82 | stationInsideHandle.handle(gps, prevs); | 85 | stationInsideHandle.handle(gps, prevs); |
| 86 | + //异常判定(越界/超速) | ||
| 87 | + abnormalStateHandle.handle(gps, prevs); | ||
| 88 | + | ||
| 89 | + if(!task) | ||
| 90 | + return; //无任务的,到这里就结束 | ||
| 91 | + | ||
| 83 | //反向处理 | 92 | //反向处理 |
| 84 | reverseSignalHandle.handle(gps, prevs); | 93 | reverseSignalHandle.handle(gps, prevs); |
| 85 | //进出站动作处理 | 94 | //进出站动作处理 |
src/main/java/com/bsth/data/gpsdata/arrival/handlers/AbnormalStateHandle.java
0 → 100644
| 1 | +package com.bsth.data.gpsdata.arrival.handlers; | ||
| 2 | + | ||
| 3 | +import com.bsth.data.gpsdata.GpsEntity; | ||
| 4 | +import com.bsth.data.gpsdata.arrival.GeoCacheData; | ||
| 5 | +import com.bsth.data.gpsdata.arrival.SignalHandle; | ||
| 6 | +import com.bsth.data.gpsdata.arrival.utils.CircleQueue; | ||
| 7 | +import com.bsth.data.gpsdata.arrival.utils.GeoUtils; | ||
| 8 | +import com.vividsolutions.jts.geom.Coordinate; | ||
| 9 | +import com.vividsolutions.jts.geom.GeometryFactory; | ||
| 10 | +import com.vividsolutions.jts.geom.LineString; | ||
| 11 | +import com.vividsolutions.jts.geom.Point; | ||
| 12 | +import org.springframework.stereotype.Component; | ||
| 13 | + | ||
| 14 | +import java.util.List; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * GPS异常状态判定 (越界/超速) | ||
| 18 | + * Created by panzhao on 2017/1/10. | ||
| 19 | + */ | ||
| 20 | +@Component | ||
| 21 | +public class AbnormalStateHandle extends SignalHandle{ | ||
| 22 | + | ||
| 23 | + //默认限速 | ||
| 24 | + private static final double DEFAULT_SPEED_LIMIT = 60; | ||
| 25 | + //越界阈值 | ||
| 26 | + private static final double OUT_BOUNDS_THRESHOLD = 100; | ||
| 27 | + | ||
| 28 | + GeometryFactory geometryFactory = new GeometryFactory(); | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public boolean handle(GpsEntity gps, CircleQueue<GpsEntity> prevs) { | ||
| 32 | + | ||
| 33 | + if(overspeed(gps)) | ||
| 34 | + return true; | ||
| 35 | + | ||
| 36 | + if(outOfBounds((gps))) | ||
| 37 | + return true; | ||
| 38 | + | ||
| 39 | + return false; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * 是否超速 | ||
| 44 | + * @param gps | ||
| 45 | + * @return | ||
| 46 | + */ | ||
| 47 | + public boolean overspeed(GpsEntity gps){ | ||
| 48 | + double maxSpeed = DEFAULT_SPEED_LIMIT; | ||
| 49 | + if(GeoCacheData.speedLimit(gps.getLineId()) != null) | ||
| 50 | + maxSpeed = GeoCacheData.speedLimit(gps.getLineId()); | ||
| 51 | + | ||
| 52 | + if(gps.getSpeed() > maxSpeed){ | ||
| 53 | + gps.setAbnormalStatus("overspeed"); | ||
| 54 | + return true; | ||
| 55 | + } | ||
| 56 | + return false; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + /** | ||
| 60 | + * 是否越界 | ||
| 61 | + * @param gps | ||
| 62 | + * @return | ||
| 63 | + */ | ||
| 64 | + public boolean outOfBounds(GpsEntity gps){ | ||
| 65 | + //场内的车不处理 | ||
| 66 | + if(gps.getInstation() == 2){ | ||
| 67 | + return false; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + List<LineString> list = GeoCacheData.getLineStringList(gps); | ||
| 71 | + Point point = geometryFactory.createPoint(new Coordinate(gps.getLat(), gps.getLon())); | ||
| 72 | + | ||
| 73 | + double min = -1, distance; | ||
| 74 | + | ||
| 75 | + for(LineString lineString : list){ | ||
| 76 | + distance = GeoUtils.getDistanceFromLine(lineString, point); | ||
| 77 | + | ||
| 78 | + if(min == -1 || min > distance) | ||
| 79 | + min = distance; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + gps.setOutOfBoundDistance(min); | ||
| 83 | + if(min > OUT_BOUNDS_THRESHOLD){ | ||
| 84 | + gps.setAbnormalStatus("outBounds"); | ||
| 85 | + return true; | ||
| 86 | + } | ||
| 87 | + return false; | ||
| 88 | + } | ||
| 89 | +} |
src/main/java/com/bsth/data/gpsdata/arrival/utils/GeoUtils.java
| @@ -3,10 +3,7 @@ package com.bsth.data.gpsdata.arrival.utils; | @@ -3,10 +3,7 @@ package com.bsth.data.gpsdata.arrival.utils; | ||
| 3 | import com.bsth.data.gpsdata.GpsEntity; | 3 | import com.bsth.data.gpsdata.GpsEntity; |
| 4 | import com.bsth.data.gpsdata.arrival.GeoCacheData; | 4 | import com.bsth.data.gpsdata.arrival.GeoCacheData; |
| 5 | import com.bsth.data.gpsdata.arrival.entity.StationRoute; | 5 | import com.bsth.data.gpsdata.arrival.entity.StationRoute; |
| 6 | -import com.vividsolutions.jts.geom.Coordinate; | ||
| 7 | -import com.vividsolutions.jts.geom.GeometryFactory; | ||
| 8 | -import com.vividsolutions.jts.geom.Point; | ||
| 9 | -import com.vividsolutions.jts.geom.Polygon; | 6 | +import com.vividsolutions.jts.geom.*; |
| 10 | 7 | ||
| 11 | import java.util.List; | 8 | import java.util.List; |
| 12 | import java.util.Map; | 9 | import java.util.Map; |
| @@ -90,6 +87,36 @@ public class GeoUtils { | @@ -90,6 +87,36 @@ public class GeoUtils { | ||
| 90 | return Math.PI * degree / 180; | 87 | return Math.PI * degree / 180; |
| 91 | } | 88 | } |
| 92 | 89 | ||
| 90 | + /** | ||
| 91 | + * 计算点 到 线的距离 | ||
| 92 | + * @param line | ||
| 93 | + * @param p | ||
| 94 | + * @return | ||
| 95 | + */ | ||
| 96 | + public static double getDistanceFromLine(LineString line, Point p){ | ||
| 97 | + Point s = line.getStartPoint(); | ||
| 98 | + Point e = line.getEndPoint(); | ||
| 99 | + | ||
| 100 | + double d1 = getDistance(s, p); | ||
| 101 | + double d2 = getDistance(p, e); | ||
| 102 | + double d3 = getDistance(s, e); | ||
| 103 | + double distance = 0; | ||
| 104 | + | ||
| 105 | + double alpha = Math.acos((d1*d1 + d3*d3 - d2*d2)/(2*d1*d3)); | ||
| 106 | + double beta = Math.acos((d2*d2 + d3*d3 - d1*d1)/(2*d2*d3)); | ||
| 107 | + | ||
| 108 | + if(alpha>Math.PI/2) { | ||
| 109 | + distance = d1; | ||
| 110 | + } | ||
| 111 | + else if(beta > Math.PI/2) { | ||
| 112 | + distance = d2; | ||
| 113 | + } | ||
| 114 | + else { | ||
| 115 | + distance = Math.sin(alpha) * d1; | ||
| 116 | + } | ||
| 117 | + return distance; | ||
| 118 | + } | ||
| 119 | + | ||
| 93 | 120 | ||
| 94 | /** | 121 | /** |
| 95 | * gps 是否在某个停车场内 | 122 | * gps 是否在某个停车场内 |
src/main/resources/static/real_control_v2/css/home.css
| @@ -79,7 +79,7 @@ | @@ -79,7 +79,7 @@ | ||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | .home-gps-table dl dt:nth-of-type(4), .home-gps-table dl dd:nth-of-type(4) { | 81 | .home-gps-table dl dt:nth-of-type(4), .home-gps-table dl dd:nth-of-type(4) { |
| 82 | - width: 9% | 82 | + width: 8%; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | .home-gps-table dl dt:nth-of-type(5), .home-gps-table dl dd:nth-of-type(5) { | 85 | .home-gps-table dl dt:nth-of-type(5), .home-gps-table dl dd:nth-of-type(5) { |
| @@ -248,6 +248,13 @@ span.signal-state-outbounds{ | @@ -248,6 +248,13 @@ span.signal-state-outbounds{ | ||
| 248 | font-size: 11px; | 248 | font-size: 11px; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | +span.signal-state-speed-limit{ | ||
| 252 | + color: red; | ||
| 253 | + padding: 2px 3px; | ||
| 254 | + border-radius: 3px; | ||
| 255 | + font-size: 11px; | ||
| 256 | +} | ||
| 257 | + | ||
| 251 | .home-svg-edit-icon{ | 258 | .home-svg-edit-icon{ |
| 252 | position: absolute; | 259 | position: absolute; |
| 253 | right: 10px; | 260 | right: 10px; |
| @@ -265,4 +272,10 @@ span.signal-state-outbounds{ | @@ -265,4 +272,10 @@ span.signal-state-outbounds{ | ||
| 265 | .home-svg-edit-icon:before{ | 272 | .home-svg-edit-icon:before{ |
| 266 | font-family: FontAwesome; | 273 | font-family: FontAwesome; |
| 267 | content: "\f040"; | 274 | content: "\f040"; |
| 275 | +} | ||
| 276 | + | ||
| 277 | +.carpark-icon{ | ||
| 278 | + color: #4dc24d; | ||
| 279 | + font-size: 14px; | ||
| 280 | + margin-left: 5px; | ||
| 268 | } | 281 | } |
| 269 | \ No newline at end of file | 282 | \ No newline at end of file |
src/main/resources/static/real_control_v2/css/main.css
| @@ -180,10 +180,10 @@ svg.line-chart g.item:nth-last-child(3)>text.down { | @@ -180,10 +180,10 @@ svg.line-chart g.item:nth-last-child(3)>text.down { | ||
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | svg.line-chart g.gps-wrap>rect { | 182 | svg.line-chart g.gps-wrap>rect { |
| 183 | - width: 34px; | 183 | + width: 30px; |
| 184 | height: 15px; | 184 | height: 15px; |
| 185 | - /*fill: #fff;*/ | ||
| 186 | - rx: 4px; | 185 | + /* fill: #fff; */ |
| 186 | + rx: 2px; | ||
| 187 | cursor: pointer; | 187 | cursor: pointer; |
| 188 | } | 188 | } |
| 189 | 189 | ||
| @@ -202,8 +202,8 @@ svg.line-chart g.gps-wrap>rect.hover { | @@ -202,8 +202,8 @@ svg.line-chart g.gps-wrap>rect.hover { | ||
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | svg.line-chart g.gps-wrap>text { | 204 | svg.line-chart g.gps-wrap>text { |
| 205 | - font-size: 13px; | ||
| 206 | - transform: translate(2px, 12px); | 205 | + font-size: 12px; |
| 206 | + transform: translate(0, 12px); | ||
| 207 | pointer-events: none; | 207 | pointer-events: none; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| @@ -220,8 +220,8 @@ svg.line-chart .merge_hide { | @@ -220,8 +220,8 @@ svg.line-chart .merge_hide { | ||
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | svg.line-chart g.merge-item rect { | 222 | svg.line-chart g.merge-item rect { |
| 223 | - width: 24px; | ||
| 224 | - height: 24px; | 223 | + width: 22px; |
| 224 | + height: 22px; | ||
| 225 | rx: 15px; | 225 | rx: 15px; |
| 226 | fill: #19a53a; | 226 | fill: #19a53a; |
| 227 | cursor: pointer; | 227 | cursor: pointer; |
src/main/resources/static/real_control_v2/fragments/home/line_panel.html
| @@ -30,12 +30,16 @@ | @@ -30,12 +30,16 @@ | ||
| 30 | <dd>{{speed}}</dd> | 30 | <dd>{{speed}}</dd> |
| 31 | <dd>{{expectStopTime}}</dd> | 31 | <dd>{{expectStopTime}}</dd> |
| 32 | <dd> | 32 | <dd> |
| 33 | - {{if abnormal != null}} | ||
| 34 | - {{if abnormal == 'outBounds'}} | ||
| 35 | - 越界 | 33 | + {{if abnormalStatus != null}} |
| 34 | + {{if abnormalStatus == 'outBounds'}} | ||
| 35 | + <span class="signal-state-outbounds">越界</span> | ||
| 36 | + {{else if abnormalStatus == 'overspeed'}} | ||
| 37 | + <span class="signal-state-speed-limit">超速</span> | ||
| 36 | {{/if}} | 38 | {{/if}} |
| 37 | - {{else}} | ||
| 38 | - 正常 | 39 | + {{/if}} |
| 40 | + | ||
| 41 | + {{if instation == 2}} | ||
| 42 | + <i class="uk-icon-product-hunt carpark-icon"></i> | ||
| 39 | {{/if}} | 43 | {{/if}} |
| 40 | </dd> | 44 | </dd> |
| 41 | <dd title="{{stationName}}">{{stationName}}</dd> | 45 | <dd title="{{stationName}}">{{stationName}}</dd> |
| @@ -46,12 +50,16 @@ | @@ -46,12 +50,16 @@ | ||
| 46 | </script> | 50 | </script> |
| 47 | 51 | ||
| 48 | <script id="home-gps-abnormal-temp" type="text/html"> | 52 | <script id="home-gps-abnormal-temp" type="text/html"> |
| 49 | - {{if abnormal != null}} | ||
| 50 | - {{if abnormal == 'outBounds'}} | 53 | + {{if abnormalStatus != null}} |
| 54 | + {{if abnormalStatus == 'outBounds'}} | ||
| 51 | <span class="signal-state-outbounds">越界</span> | 55 | <span class="signal-state-outbounds">越界</span> |
| 56 | + {{else if abnormalStatus == 'overspeed'}} | ||
| 57 | + <span class="signal-state-speed-limit">超速</span> | ||
| 52 | {{/if}} | 58 | {{/if}} |
| 53 | - {{else}} | ||
| 54 | - 正常 | 59 | + {{/if}} |
| 60 | + | ||
| 61 | + {{if instation == 2}} | ||
| 62 | + <i class="uk-icon-product-hunt carpark-icon"></i> | ||
| 55 | {{/if}} | 63 | {{/if}} |
| 56 | </script> | 64 | </script> |
| 57 | </div> | 65 | </div> |
src/main/resources/static/real_control_v2/js/data/data_basic.js
| @@ -135,6 +135,9 @@ var gb_data_basic = (function () { | @@ -135,6 +135,9 @@ var gb_data_basic = (function () { | ||
| 135 | return nbbm2deviceMap; | 135 | return nbbm2deviceMap; |
| 136 | }, | 136 | }, |
| 137 | getLineInformation: getLineInformation, | 137 | getLineInformation: getLineInformation, |
| 138 | + allInformations: function () { | ||
| 139 | + return lineInformations; | ||
| 140 | + }, | ||
| 138 | stationRoutes: function (lineCode) { | 141 | stationRoutes: function (lineCode) { |
| 139 | return stationRoutes[lineCode] | 142 | return stationRoutes[lineCode] |
| 140 | }, | 143 | }, |
src/main/resources/static/real_control_v2/js/data/data_gps.js
| @@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
| 3 | var gb_data_gps = (function() { | 3 | var gb_data_gps = (function() { |
| 4 | 4 | ||
| 5 | //fixed time refresh delay | 5 | //fixed time refresh delay |
| 6 | - var delay = 1000 * 5; | 6 | + var delay = 1000 * 7; |
| 7 | //deviceId ——> gps | 7 | //deviceId ——> gps |
| 8 | var realData = {}; | 8 | var realData = {}; |
| 9 | //refresh after callback | 9 | //refresh after callback |
| @@ -38,11 +38,13 @@ var gb_data_gps = (function() { | @@ -38,11 +38,13 @@ var gb_data_gps = (function() { | ||
| 38 | $.each(rs, function() { | 38 | $.each(rs, function() { |
| 39 | old = realData[this.deviceId]; | 39 | old = realData[this.deviceId]; |
| 40 | if (old) { | 40 | if (old) { |
| 41 | - if (old.timestamp < this.timestamp) | 41 | + if (this.timestamp > old.timestamp){ |
| 42 | if (old.upDown != this.upDown) | 42 | if (old.upDown != this.upDown) |
| 43 | upDownChange.push(this); | 43 | upDownChange.push(this); |
| 44 | else | 44 | else |
| 45 | upArr.push(this); | 45 | upArr.push(this); |
| 46 | + } | ||
| 47 | + | ||
| 46 | } else | 48 | } else |
| 47 | addArr.push(this); | 49 | addArr.push(this); |
| 48 | 50 | ||
| @@ -55,8 +57,6 @@ var gb_data_gps = (function() { | @@ -55,8 +57,6 @@ var gb_data_gps = (function() { | ||
| 55 | 57 | ||
| 56 | //时间格式化 | 58 | //时间格式化 |
| 57 | this.dateStr = moment(this.timestamp).format('YYYY-MM-DD HH:mm:ss'); | 59 | this.dateStr = moment(this.timestamp).format('YYYY-MM-DD HH:mm:ss'); |
| 58 | - //异常检测 | ||
| 59 | - gb_gps_abnormal.check(this); | ||
| 60 | realData[this.deviceId] = this; | 60 | realData[this.deviceId] = this; |
| 61 | }); | 61 | }); |
| 62 | 62 |
src/main/resources/static/real_control_v2/js/data/gps_abnormal.js
| 1 | -/** gps 信号异常状态,无效 | 越界 | 超速 */ | 1 | +/** gps 信号异常状态,无效 | 越界 | 超速 |
| 2 | + * | ||
| 3 | + * | ||
| 4 | + * 前端计算略微有点卡顿, 交由后端计算 | ||
| 5 | + * */ | ||
| 2 | 6 | ||
| 3 | var gb_gps_abnormal = (function () { | 7 | var gb_gps_abnormal = (function () { |
| 4 | 8 | ||
| @@ -11,7 +15,12 @@ var gb_gps_abnormal = (function () { | @@ -11,7 +15,12 @@ var gb_gps_abnormal = (function () { | ||
| 11 | }; | 15 | }; |
| 12 | 16 | ||
| 13 | //越界 | 17 | //越界 |
| 18 | + var threshold = 120; | ||
| 14 | var gpsOutOfBounds = function (gps) { | 19 | var gpsOutOfBounds = function (gps) { |
| 20 | + //进场班次不管 | ||
| 21 | + if (gps.sch && gps.sch.bcType == 'in') | ||
| 22 | + return; | ||
| 23 | + | ||
| 15 | var roads = allRoads[gps.lineId + '_' + gps.upDown]; | 24 | var roads = allRoads[gps.lineId + '_' + gps.upDown]; |
| 16 | if (!roads) | 25 | if (!roads) |
| 17 | return; | 26 | return; |
| @@ -25,15 +34,19 @@ var gb_gps_abnormal = (function () { | @@ -25,15 +34,19 @@ var gb_gps_abnormal = (function () { | ||
| 25 | }); | 34 | }); |
| 26 | 35 | ||
| 27 | //越界阈值 120米 | 36 | //越界阈值 120米 |
| 28 | - var threshold = 120; | ||
| 29 | - if (gps.sch && gps.sch.bcType == 'in') | ||
| 30 | - return; | ||
| 31 | - | ||
| 32 | if (min > threshold) { | 37 | if (min > threshold) { |
| 33 | gps.abnormal = 'outBounds'; | 38 | gps.abnormal = 'outBounds'; |
| 34 | gps.outBoundsDistance = min; | 39 | gps.outBoundsDistance = min; |
| 40 | + return true; | ||
| 35 | } | 41 | } |
| 36 | - //console.log('最短距离', min, gps.nbbm); | 42 | + }; |
| 43 | + | ||
| 44 | + | ||
| 45 | + //线路限速数据 | ||
| 46 | + var lineSpeedLimit = {}; | ||
| 47 | + //超速 | ||
| 48 | + var overspeed = function (gps) { | ||
| 49 | + | ||
| 37 | }; | 50 | }; |
| 38 | 51 | ||
| 39 | /** | 52 | /** |
| @@ -56,6 +69,14 @@ var gb_gps_abnormal = (function () { | @@ -56,6 +69,14 @@ var gb_gps_abnormal = (function () { | ||
| 56 | //按线路_走向 分组数据 | 69 | //按线路_走向 分组数据 |
| 57 | allRoads = groupByLineAndUpdown(list); | 70 | allRoads = groupByLineAndUpdown(list); |
| 58 | }); | 71 | }); |
| 72 | + | ||
| 73 | + //线路限速数据 | ||
| 74 | + var infos = gb_data_basic.allInformations(); | ||
| 75 | + for (var lineCode in infos) { | ||
| 76 | + lineSpeedLimit[lineCode] = infos[lineCode].speedLimit == null ? 70 : infos[lineCode].speedLimit; | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + console.log('lineSpeedLimit', lineSpeedLimit); | ||
| 59 | }; | 80 | }; |
| 60 | 81 | ||
| 61 | function minDistanceFromRoad(pos, gps) { | 82 | function minDistanceFromRoad(pos, gps) { |
| @@ -69,6 +90,9 @@ var gb_gps_abnormal = (function () { | @@ -69,6 +90,9 @@ var gb_gps_abnormal = (function () { | ||
| 69 | 90 | ||
| 70 | if (!min || min > distance) | 91 | if (!min || min > distance) |
| 71 | min = distance; | 92 | min = distance; |
| 93 | + | ||
| 94 | + if (distance <= threshold) | ||
| 95 | + return threshold; | ||
| 72 | } | 96 | } |
| 73 | 97 | ||
| 74 | return min; | 98 | return min; |
| @@ -104,10 +128,11 @@ var gb_gps_abnormal = (function () { | @@ -104,10 +128,11 @@ var gb_gps_abnormal = (function () { | ||
| 104 | return { | 128 | return { |
| 105 | initData: initData, | 129 | initData: initData, |
| 106 | check: function (gps) { | 130 | check: function (gps) { |
| 107 | - if (!allRoads) { | 131 | + if (!allRoads || gps.instation == 2) { |
| 108 | return; | 132 | return; |
| 109 | } | 133 | } |
| 110 | 134 | ||
| 135 | + //越界判定 | ||
| 111 | gpsOutOfBounds(gps); | 136 | gpsOutOfBounds(gps); |
| 112 | } | 137 | } |
| 113 | } | 138 | } |
src/main/resources/static/real_control_v2/js/utils/svg_chart.js
| @@ -183,7 +183,7 @@ var gb_svg_chart = (function () { | @@ -183,7 +183,7 @@ var gb_svg_chart = (function () { | ||
| 183 | var circle = get_circle(gps.stopNo + '_' + gps.upDown, svg); | 183 | var circle = get_circle(gps.stopNo + '_' + gps.upDown, svg); |
| 184 | if (!circle) return -100; | 184 | if (!circle) return -100; |
| 185 | 185 | ||
| 186 | - return circle.attr('cx') - 17.5; | 186 | + return circle.attr('cx') - 16.5; |
| 187 | }, | 187 | }, |
| 188 | gy = function (gps, svg) { | 188 | gy = function (gps, svg) { |
| 189 | var circle = get_circle(gps.stopNo + '_' + gps.upDown, svg); | 189 | var circle = get_circle(gps.stopNo + '_' + gps.upDown, svg); |
| @@ -322,14 +322,14 @@ var gb_svg_chart = (function () { | @@ -322,14 +322,14 @@ var gb_svg_chart = (function () { | ||
| 322 | 'merge-item': true | 322 | 'merge-item': true |
| 323 | }); | 323 | }); |
| 324 | //merge rect | 324 | //merge rect |
| 325 | - mergerG.append('rect').attr('x', x - 12) | 325 | + mergerG.append('rect').attr('x', x - 11) |
| 326 | .attr('y', function () { | 326 | .attr('y', function () { |
| 327 | - return isDown ? y + 7 : y - 32; | 327 | + return isDown ? y + 8 : y - 31; |
| 328 | }); | 328 | }); |
| 329 | //merge text | 329 | //merge text |
| 330 | var len = gpsArr.length; | 330 | var len = gpsArr.length; |
| 331 | mergerG.append('text').text(len) | 331 | mergerG.append('text').text(len) |
| 332 | - .attr('x', x - ((len + '').length * 4)) | 332 | + .attr('x', x - ((len + '').length * 4.5)) |
| 333 | .attr('y', isDown ? y + 24 : y - 14); | 333 | .attr('y', isDown ? y + 24 : y - 14); |
| 334 | }; | 334 | }; |
| 335 | 335 |
src/main/resources/static/real_control_v2/js/utils/svg_chart_tooltip.js
| @@ -13,7 +13,6 @@ var gb_svg_tooltip = (function () { | @@ -13,7 +13,6 @@ var gb_svg_tooltip = (function () { | ||
| 13 | if (rect.attr('aria-describedby')) | 13 | if (rect.attr('aria-describedby')) |
| 14 | return; | 14 | return; |
| 15 | var gps = gb_data_gps.findOne($(this).attr('_id').split('_')[1]); | 15 | var gps = gb_data_gps.findOne($(this).attr('_id').split('_')[1]); |
| 16 | - console.log('gps', gps); | ||
| 17 | $(this).qtip({ | 16 | $(this).qtip({ |
| 18 | show: { | 17 | show: { |
| 19 | ready: true, | 18 | ready: true, |