GeoCacheData.java 11.3 KB
package com.bsth.data.gpsdata.arrival;

import com.bsth.data.gpsdata.GpsEntity;
import com.bsth.data.gpsdata.arrival.entity.StationRoute;
import com.bsth.data.gpsdata.arrival.utils.CircleQueue;
import com.bsth.data.gpsdata.arrival.utils.StationRouteComp;
import com.google.common.collect.ArrayListMultimap;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Polygon;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * Created by panzhao on 2016/12/23.
 */
@Component
public class GeoCacheData {

    static Logger logger = LoggerFactory.getLogger(GeoCacheData.class);

    //每辆车缓存最后1000条gps
    private static final int CACHE_SIZE = 1000;
    private static Map<String, CircleQueue<GpsEntity>> gpsCacheMap = new HashMap<>();

    //线路路段走向
    private static ArrayListMultimap<String, LineString> sectionCacheMap;

    //线路站点路由
    private static ArrayListMultimap<String, StationRoute> stationCacheMap;

    //线路_上下行_站点编码 ——> 站点
    private static Map<String, StationRoute> routeCodeMap;

    //停车场
    public static Map<String, Polygon> tccMap;

    //线路限速信息
    private static Map<String, Double> speedLimitMap;

    @Autowired
    JdbcTemplate jdbcTemplate;

    public static CircleQueue<GpsEntity> getGps(String nbbm) {
        return gpsCacheMap.get(nbbm);
    }

    public static void putGps(GpsEntity gps) {
        CircleQueue<GpsEntity> queue = gpsCacheMap.get(gps.getNbbm());
        if (queue == null) {
            /*//第一个点从站内开始
            if (gps.getInstation() == 0)
                return;*/

            queue = new CircleQueue<>(CACHE_SIZE);
            gpsCacheMap.put(gps.getNbbm(), queue);
        }
        queue.add(gps);
    }

    public static void clear(String nbbm) {
        try {
            CircleQueue<GpsEntity> queue = gpsCacheMap.get(nbbm);
            if (queue != null)
                queue.clear();
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    public static StationRoute getRouteCode(GpsEntity gps) {
        return routeCodeMap.get(gps.getLineId() + "_" + gps.getUpDown() + "_" + gps.getStopNo());
    }

    public static List<StationRoute> getStationRoute(String lineCode, int directions) {
        return stationCacheMap.get(lineCode + "_" + directions);
    }

    public static StationRoute getStation(String lineCode, int directions, String code) {
        List<StationRoute> list = getStationRoute(lineCode, directions);

        for (StationRoute sr : list) {
            if (sr.getCode().equals(code)) {
                return sr;
            }
        }
        return null;
    }

    public static Double speedLimit(String lineCode){
        return speedLimitMap.get(lineCode);
    }

    public static List<LineString> getLineStringList(GpsEntity gps){
        return sectionCacheMap.get(gps.getLineId() + "_" + gps.getUpDown());
    }

    public static List<StationRoute> midwayStation(String lineCode, int directions, String sCode, String eCode) {
        List<StationRoute> list = getStationRoute(lineCode, directions), rs = new ArrayList<>();

        boolean flag = false;
        for (StationRoute sr : list) {
            if (flag)
                rs.add(sr);
            if (sr.getCode().equals(sCode))
                flag = true;
            else if (sr.getCode().equals(eCode))
                break;
        }
        return rs;
    }

    public static Polygon getTccPolygon(String code) {
        return tccMap.get(code);
    }

    GeometryFactory geometryFactory = new GeometryFactory();
    public void loadData() {
        loadStationRoutesData();
        loadTccMapData();
        loadSpeedLimit();

        //加载路段信息
        loadRoadsData();
    }

    private void loadRoadsData() {
        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";
        List<Map<String, Object>> secList = jdbcTemplate.queryForList(sql);

        String polygonStr, key;
        String[] coords;
        int i, len;

        ArrayListMultimap<String, LineString> sectionCacheTempMap = ArrayListMultimap.create();
        Coordinate[] cds;
        String[] temps1, temps2;
        for (Map<String, Object> tMap : secList) {
            polygonStr = tMap.get("GSECTION_VECTOR").toString();
            key = tMap.get("LINE_CODE") + "_" + tMap.get("DIRECTIONS");

            coords = polygonStr.substring(11, polygonStr.length() - 1).split(",");
            len = coords.length - 1;
            //每2个点连一条线
            for(i = 0; i < len; i ++){
                temps1 = coords[i].split(" ");
                temps2 = coords[i + 1].split(" ");

                cds = new Coordinate[2];
                cds[0] = new Coordinate(Float.parseFloat(temps1[1]), Float.parseFloat(temps1[0]));
                cds[1] = new Coordinate(Float.parseFloat(temps2[1]), Float.parseFloat(temps2[0]));

                sectionCacheTempMap.put(key, geometryFactory.createLineString(cds));
            }
        }

        if(sectionCacheTempMap.size() > 0)
            sectionCacheMap = sectionCacheTempMap;
    }

    private void loadTccMapData(){
        //加载停车场数据
        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";
        List<Map<String, Object>> tccList = jdbcTemplate.queryForList(sql);
        Map<String, Polygon> tccTempMap = new HashMap<>();

        Polygon polygon;
        for (Map<String, Object> tMap : tccList) {

            try {
                polygon = geometryFactory.createPolygon(parsePolygon(tMap.get("G_PARK_POINT").toString()));
                tccTempMap.put(tMap.get("PARK_CODE").toString()
                        , polygon);
            } catch (Exception e) {
                logger.error("停车场:" + tMap.get("PARK_CODE"), e);
            }
        }
        if (tccTempMap.size() > 0)
            tccMap = tccTempMap;
    }

    private void loadStationRoutesData(){
        //加载站点路由
        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";
        List<StationRoute> routeList = jdbcTemplate.query(sql, new RowMapper<StationRoute>() {
            @Override
            public StationRoute mapRow(ResultSet rs, int rowNum) throws SQLException {
                StationRoute sRoute = new StationRoute();
                sRoute.setCode(rs.getString("STATION_CODE"));
                sRoute.setLineCode(rs.getString("LINE_CODE"));
                sRoute.setDirections(rs.getInt("DIRECTIONS"));
                sRoute.setPoint(geometryFactory.createPoint(new Coordinate(rs.getFloat("G_LATY"), rs.getFloat("G_LONX"))));
                sRoute.setRadius(rs.getFloat("RADIUS"));
                sRoute.setRouteSort(rs.getInt("STATION_ROUTE_CODE"));
                sRoute.setMark(rs.getString("STATION_MARK"));
                sRoute.setName(rs.getString("STATION_NAME"));

                String shapesType = rs.getString("SHAPES_TYPE");
                //多边形电子围栏
                if (StringUtils.isNotEmpty(shapesType) && shapesType.equals("d")) {
                    sRoute.setPolygon(geometryFactory.createPolygon(parsePolygon(rs.getString("G_POLYGON_GRID"))));
                }
                return sRoute;
            }
        });
        //按线路和走向分组
        if (routeList.size() > 0) {
            ArrayListMultimap<String, StationRoute> tempMap = ArrayListMultimap.create();
            Map<String, StationRoute> codeMap = new HashMap<>(routeList.size());
            for (StationRoute sr : routeList) {
                tempMap.put(sr.getLineCode() + "_" + sr.getDirections(), sr);
                //站点编码 ——> 和路由顺序对照
                codeMap.put(sr.getLineCode() + "_" + sr.getDirections() + "_" + sr.getCode(), sr);
            }

            StationRouteComp srCom = new StationRouteComp();
            //连接路由
            Set<String> set = tempMap.keySet();
            for (String key : set) {
                Collections.sort(tempMap.get(key), srCom);
                connectStationRoute(tempMap.get(key));
            }

            stationCacheMap = tempMap;
            routeCodeMap = codeMap;
        }
    }

    private void loadSpeedLimit(){
        //加载线路限速信息
        String sql = "select l.LINE_CODE,i.SPEEDING from bsth_c_line_information i left join bsth_c_line l on i.line=l.id where i.speed_limit is not null";
        List<Map<String, Object>> speedMap = jdbcTemplate.queryForList(sql);
        Map<String, Double> speedTempMap = new HashMap<>();
        for (Map<String, Object> tMap : speedMap) {
            try {
                speedTempMap.put(tMap.get("LINE_CODE").toString(), Double.parseDouble(tMap.get("SPEEDING").toString()));
            } catch (NumberFormatException e) {
                logger.error("speeding is null...");
            }
        }
        speedLimitMap = speedTempMap;
    }

    private void connectStationRoute(List<StationRoute> list) {
        int size = list.size();
        StationRoute sr = null;
        for (int i = 0; i < size; i++) {
            sr = list.get(i);
            //上一个
            if (i > 0)
                sr.setPrve(list.get(i - 1));
            //下一个
            if (i < size - 1)
                sr.setNext(list.get(i + 1));
        }
    }

    public Coordinate[] parsePolygon(String polygonStr) {
        String[] coords = polygonStr.substring(9, polygonStr.length() - 2).split(","), temps;

        Coordinate[] cds = new Coordinate[coords.length];
        int len = coords.length;
        for (int i = 0; i < len; i++) {
            temps = coords[i].split(" ");
            cds[i] = new Coordinate(Float.parseFloat(temps[1]), Float.parseFloat(temps[0]));
        }
        return cds;
    }

    /**
     * 是不是终点站
     *
     * @param lineId
     * @param upDown
     * @param stationCode
     * @return
     */
    public static boolean isEndStation(String lineId, Integer upDown, String stationCode) {
        StationRoute station = routeCodeMap.get(lineId + "_" + upDown + "_" + stationCode);
        return station != null && station.getMark().equals("E");
    }
}