공부한거 잊었을 때 보려고 만든 블로그

자바 스프링 기상청 단기예보 (동네날씨) API (2) 위도경도 격자 변환 본문

자유 주제

자바 스프링 기상청 단기예보 (동네날씨) API (2) 위도경도 격자 변환

Parcon 2023. 5. 2. 20:44

 

public static int TO_GRID = 0;
public static int TO_GPS = 1;

private LatXLngY convertGRID_GPS(int mode, double lat_X, double lng_Y) {
    double RE = 6371.00877; // 지구 반경(km)
    double GRID = 5.0; // 격자 간격(km)
    double SLAT1 = 30.0; // 투영 위도1(degree)
    double SLAT2 = 60.0; // 투영 위도2(degree)
    double OLON = 126.0; // 기준점 경도(degree)
    double OLAT = 38.0; // 기준점 위도(degree)
    double XO = 43; // 기준점 X좌표(GRID)
    double YO = 136; // 기준점 Y좌표(GRID)

    // LCC DFS 좌표변환 ( code : "TO_GRID"(위경도->좌표, lat_X:위도,  lng_Y:경도), "TO_GPS"(좌표->위경도,  lat_X:x, lng_Y:y) ) 

    double DEGRAD = Math.PI / 180.0;
    double RADDEG = 180.0 / Math.PI;

    double re = RE / GRID;
    double slat1 = SLAT1 * DEGRAD;
    double slat2 = SLAT2 * DEGRAD;
    double olon = OLON * DEGRAD;
    double olat = OLAT * DEGRAD;

    double sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5);
    sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn);
    double sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);
    sf = Math.pow(sf, sn) * Math.cos(slat1) / sn;
    double ro = Math.tan(Math.PI * 0.25 + olat * 0.5);
    ro = re * sf / Math.pow(ro, sn);
    LatXLngY rs = new LatXLngY();

    if (mode == TO_GRID) {
        rs.lat = lat_X;
        rs.lng = lng_Y;
        double ra = Math.tan(Math.PI * 0.25 + (lat_X) * DEGRAD * 0.5);
        ra = re * sf / Math.pow(ra, sn);
        double theta = lng_Y * DEGRAD - olon;
        if (theta > Math.PI) theta -= 2.0 * Math.PI;
        if (theta < -Math.PI) theta += 2.0 * Math.PI;
        theta *= sn;
        rs.x = Math.floor(ra * Math.sin(theta) + XO + 0.5);
        rs.y = Math.floor(ro - ra * Math.cos(theta) + YO + 0.5);
	}
    
    else {
        rs.x = lat_X;
        rs.y = lng_Y;
        double xn = lat_X - XO;
        double yn = ro - lng_Y + YO;
        double ra = Math.sqrt(xn * xn + yn * yn);
        if (sn < 0.0) {
       		ra = -ra;
        }
        double alat = Math.pow((re * sf / ra), (1.0 / sn));
        alat = 2.0 * Math.atan(alat) - Math.PI * 0.5;
        double theta = 0.0;
        if (Math.abs(xn) <= 0.0) {
            theta = 0.0;
        }
        else {
            if (Math.abs(yn) <= 0.0) {
                theta = Math.PI * 0.5;
                if (xn < 0.0) {
                    theta = -theta;
                }
            }
            else theta = Math.atan2(xn, yn);
        }
        double alon = theta / sn + olon;
        rs.lat = alat * RADDEG;
        rs.lng = alon * RADDEG;
	}
    
    return rs;
}
LatXLngY tmp = convertGRID_GPS(TO_GRID, Latitude, Longitude);

class LatXLngY {
    public double lat;
    public double lng;

    public double x;
    public double y;
}

 

출처 : https://gist.github.com/fronteer-kr/14d7f779d52a21ac2f16

 

기상청 격자 <-> 위경도 변환

GitHub Gist: instantly share code, notes, and snippets.

gist.github.com

 

getDate와 getTime 함수로 base_date, base_time에 넣을 현재 시간에 가장 가까운 예보를 가져오고

convertGRID_GPS함수로 위도경도를 격자로 변환하여 nx, ny에 넣을 좌표 값을 가져온다.