Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
// 소스출처 : http://www.kma.go.kr/weather/forecast/digital_forecast.jsp 내부에 있음
// 기상청에서 이걸 왜 공식적으로 공개하지 않을까?
//
// (사용 예)
// var rs = dfs_xy_conv("toLL","60","127");
// console.log(rs.lat, rs.lng);
//
<script language="javascript">
//<!--
//
// LCC DFS 좌표변환을 위한 기초 자료
//
var RE = 6371.00877; // 지구 반경(km)
var GRID = 5.0; // 격자 간격(km)
var SLAT1 = 30.0; // 투영 위도1(degree)
var SLAT2 = 60.0; // 투영 위도2(degree)
var OLON = 126.0; // 기준점 경도(degree)
var OLAT = 38.0; // 기준점 위도(degree)
var XO = 43; // 기준점 X좌표(GRID)
var YO = 136; // 기1준점 Y좌표(GRID)
//
// LCC DFS 좌표변환 ( code : "toXY"(위경도->좌표, v1:위도, v2:경도), "toLL"(좌표->위경도,v1:x, v2:y) )
//
function dfs_xy_conv(code, v1, v2) {
var DEGRAD = Math.PI / 180.0;
var RADDEG = 180.0 / Math.PI;
var re = RE / GRID;
var slat1 = SLAT1 * DEGRAD;
var slat2 = SLAT2 * DEGRAD;
var olon = OLON * DEGRAD;
var olat = OLAT * DEGRAD;
var 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);
var sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);
sf = Math.pow(sf, sn) * Math.cos(slat1) / sn;
var ro = Math.tan(Math.PI * 0.25 + olat * 0.5);
ro = re * sf / Math.pow(ro, sn);
var rs = {};
if (code == "toXY") {
rs['lat'] = v1;
rs['lng'] = v2;
var ra = Math.tan(Math.PI * 0.25 + (v1) * DEGRAD * 0.5);
ra = re * sf / Math.pow(ra, sn);
var theta = v2 * 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'] = v1;
rs['y'] = v2;
var xn = v1 - XO;
var yn = ro - v2 + YO;
ra = Math.sqrt(xn * xn + yn * yn);
if (sn < 0.0) - ra;
var alat = Math.pow((re * sf / ra), (1.0 / sn));
alat = 2.0 * Math.atan(alat) - Math.PI * 0.5;
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;
}
else theta = Math.atan2(xn, yn);
}
var alon = theta / sn + olon;
rs['lat'] = alat * RADDEG;
rs['lng'] = alon * RADDEG;
}
return rs;
}
//-->
</script>

dalku commented Jun 15, 2017

// 안드로이드 하시는분들 시간절약하세요~

public class MainActivity extends AppCompatActivity {

public static int TO_GRID = 0;
public static int TO_GPS = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    LatXLngY tmp = convertGRID_GPS(TO_GRID, 37.579871128849334, 126.98935225645432);
    LatXLngY tmp2 = convertGRID_GPS(TO_GRID, 35.101148844565955, 129.02478725562108);
    LatXLngY tmp3 = convertGRID_GPS(TO_GRID, 33.500946412305076, 126.54663058817043);

    Log.e(">>", "x = " + tmp.x + ", y = " + tmp.y);
    Log.e(">>", "x = " + tmp2.x + ", y = " + tmp2.y);
    Log.e(">>", "x = " + tmp3.x + ", y = " + tmp3.y);
}


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; // 기1준점 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;
}



class LatXLngY
{
    public double lat;
    public double lng;

    public double x;
    public double y;

}

}

dalku commented Feb 5, 2018

스위프트 4 용.
//////////////// GPS -> GRID ///////////////
func convertGRID_GPS(mode: Int, lat_X: Double, lng_Y: Double) -> LatXLngY {
let RE = 6371.00877 // 지구 반경(km)
let GRID = 5.0 // 격자 간격(km)
let SLAT1 = 30.0 // 투영 위도1(degree)
let SLAT2 = 60.0 // 투영 위도2(degree)
let OLON = 126.0 // 기준점 경도(degree)
let OLAT = 38.0 // 기준점 위도(degree)
let XO:Double = 43 // 기준점 X좌표(GRID)
let YO:Double = 136 // 기1준점 Y좌표(GRID)

    //
    // LCC DFS 좌표변환 ( code : "TO_GRID"(위경도->좌표, lat_X:위도,  lng_Y:경도), "TO_GPS"(좌표->위경도,  lat_X:x, lng_Y:y) )
    //
    
    let DEGRAD = Double.pi / 180.0
    let RADDEG = 180.0 / Double.pi
    
    let re = RE / GRID
    let slat1 = SLAT1 * DEGRAD
    let slat2 = SLAT2 * DEGRAD
    let olon = OLON * DEGRAD
    let olat = OLAT * DEGRAD
    
    var sn = tan(Double.pi * 0.25 + slat2 * 0.5) / tan(Double.pi * 0.25 + slat1 * 0.5)
    sn = log(cos(slat1) / cos(slat2)) / log(sn)
    var sf = tan(Double.pi * 0.25 + slat1 * 0.5)
    sf = pow(sf, sn) * cos(slat1) / sn
    var ro = tan(Double.pi * 0.25 + olat * 0.5)
    ro = re * sf / pow(ro, sn)
    var rs = LatXLngY(lat: 0, lng: 0, x: 0, y: 0)

    if mode == TO_GRID {
        rs.lat = lat_X
        rs.lng = lng_Y
        var ra = tan(Double.pi * 0.25 + (lat_X) * DEGRAD * 0.5)
        ra = re * sf / pow(ra, sn)
        var theta = lng_Y * DEGRAD - olon
        if theta > Double.pi {
            theta -= 2.0 * Double.pi
        }
        if theta < -Double.pi {
            theta += 2.0 * Double.pi
        }
        
        theta *= sn
        rs.x = Int(floor(ra * sin(theta) + XO + 0.5))
        rs.y = Int(floor(ro - ra * cos(theta) + YO + 0.5))
    }
    else {
        rs.x = Int(lat_X)
        rs.y = Int(lng_Y)
        let xn = lat_X - XO
        let yn = ro - lng_Y + YO
        var ra = sqrt(xn * xn + yn * yn)
        if (sn < 0.0) {
            ra = -ra
        }
        var alat = pow((re * sf / ra), (1.0 / sn))
        alat = 2.0 * atan(alat) - Double.pi * 0.5
        
        var theta = 0.0
        if (abs(xn) <= 0.0) {
            theta = 0.0
        }
        else {
            if (abs(yn) <= 0.0) {
                theta = Double.pi * 0.5
                if (xn < 0.0) {
                    theta = -theta
                }
            }
            else {
                theta = atan2(xn, yn)
            }
        }
        let alon = theta / sn + olon
        rs.lat = alat * RADDEG
        rs.lng = alon * RADDEG
    }
    return rs
    
    
}

struct LatXLngY {
    public var lat: Double
    public var lng: Double
    
    public var x: Int
    public var y: Int
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment