Skip to content

Instantly share code, notes, and snippets.

@seraekim
Last active June 2, 2019 14:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seraekim/8bbbac819f304cc4dde5db909f89d7af to your computer and use it in GitHub Desktop.
Save seraekim/8bbbac819f304cc4dde5db909f89d7af to your computer and use it in GitHub Desktop.
convert among LambertConformalConic XY Grid, Longitude/Latitude and Address
package org.srkim.test;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* can convert among LambertConformalConic XY Grid, Longitude/Latitude and
* Address. need to import apache commons io and org.json provided examples via
* class main method.
*
* @author srkim
*
*/
public class LambertConformalConicProj {
final static double PI = Math.PI;
final static double DEG_TO_RAD = PI / 180.0;
final static double RAD_TO_DEG = 180.0 / PI;
/**
* GRID SPACING [km]
*/
final static double SPACING = 5;
/**
* RADIUS OF EARTH [km]
*/
final static double RADIUS = 6371 / SPACING;
/**
* STANDARD LATITUDE 1
*/
final static double STAND_LAT1 = 30.0 * DEG_TO_RAD;
/**
* STANDARD LATITUDE 2
*/
final static double STAND_LAT2 = 60.0 * DEG_TO_RAD;
/**
* LONGITUDE OF REFERENCE POINT
*/
final static double REF_LON = 126.0 * DEG_TO_RAD;
/**
* LATITUDE OF REFERENCE POINT
*/
final static double REF_LAT = 38.0 * DEG_TO_RAD;
/**
* X COORDINATE OF REFERENCE POINT
*/
final static double REF_X = 43;
/**
* Y COORDINATE OF REFERENCE POINT
*/
final static double REF_Y = 136;
static double sn = Math.tan(PI * 0.25 + STAND_LAT2 * 0.5) / Math.tan(PI * 0.25 + STAND_LAT1 * 0.5);
static double sf = Math.tan(PI * 0.25 + STAND_LAT1 * 0.5);
static double ro = Math.tan(PI * 0.25 + REF_LAT * 0.5);
static {
sn = Math.log(Math.cos(STAND_LAT1) / Math.cos(STAND_LAT2)) / Math.log(sn);
sf = Math.pow(sf, sn) * Math.cos(STAND_LAT1) / sn;
ro = RADIUS * sf / Math.pow(ro, sn);
}
/*
* from user's data.
*/
double x, y, lon, lat;
List<Object> address;
public void setXy(double x, double y) {
this.x = x;
this.y = y;
}
public void setLonlat(double lon, double lat) {
this.lon = lon;
this.lat = lat;
}
public void setAddress(String address) {
List<Object> list = new ArrayList<>();
list.add(address);
this.address = list;
}
public void setAddress(List<Object> address) {
this.address = address;
}
public List<Object> getAddress() {
return address;
}
public void lonlat2Xy() {
double ra = Math.tan(PI * 0.25 + lat * DEG_TO_RAD * 0.5);
ra = RADIUS * sf / Math.pow(ra, sn);
double theta = lon * DEG_TO_RAD - REF_LON;
if (theta > PI)
theta = theta - (2.0 * PI);
if (theta < -PI)
theta = theta + (2.0 * PI);
theta = theta * sn;
x = (ra * Math.sin(theta)) + REF_X;
x = Math.round(x);
y = (ro - ra * Math.cos(theta)) + REF_Y;
y = Math.round(y);
log(x + " : " + y);
}
public void lonlat2Address() {
JSONObject jObj = requestApi("latlng=" + lat + "," + lon);
JSONArray results = jObj.getJSONArray("results");
List<Object> addressArray = new ArrayList<>();
for (int i = 0; i < results.length(); i++) {
List<Object> types = results.getJSONObject(i).getJSONArray("address_components").getJSONObject(0)
.getJSONArray("types").toList();
for (Object o : types) {
if ("sublocality_level_2".equals(o)) {
addressArray.add(results.getJSONObject(i).getString("formatted_address"));
}
}
}
address = addressArray;
log(addressArray);
}
public void xy2Lonlat() {
double xn = x - REF_X;
double yn = ro - y + REF_Y;
double ra = Math.sqrt(xn * xn + yn * yn);
if (sn < 0.0)
ra = -ra;
double alat = Math.pow((RADIUS * sf / ra), (1.0 / sn));
double theta = 0;
alat = 2.0 * Math.atan(alat) - PI * 0.5;
if (Math.abs(xn) <= 0.0) {
theta = 0.0;
} else {
if (Math.abs(yn) <= 0.0) {
theta = PI * 0.5;
if (xn < 0.0)
theta = -theta;
} else {
theta = Math.atan2(xn, yn);
}
}
double alon = theta / sn + REF_LON;
lon = alon * RAD_TO_DEG;
lat = alat * RAD_TO_DEG;
log(lon + " : " + lat);
}
public void xy2Address() {
xy2Lonlat();
lonlat2Address();
}
public void address2Lonlat() {
JSONObject jObj = requestApi("address=" + urlEncode(address.get(0)));
JSONArray results = jObj.getJSONArray("results");
JSONObject loc = results.getJSONObject(results.length() - 1).getJSONObject("geometry")
.getJSONObject("location");
lon = loc.getDouble("lng");
lat = loc.getDouble("lat");
log(lon + " : " + lat);
}
public void address2Xy() {
address2Lonlat();
lonlat2Xy();
}
public static void main(String[] args) {
LambertConformalConicProj s = new LambertConformalConicProj();
// can set initially lng/lat, xy, address(String or List)
s.setLonlat(126.9156168, 37.476128);
// 1. CONVERT LONLAT TO XY
s.lonlat2Xy();
// 2. INPUT LONGITUDE AND LATITUDE, OUTPUT address
s.lonlat2Address();
// 3. INPUT XY, OUTPUT LONGITUDE AND LATITUDE
s.xy2Lonlat();
// 4. INPUT XY, OUTPUT ADDRESS
s.xy2Address();
// 5. INPUT ADDRESS, OUTPUT LONGITUDE AND LATITUDE
s.address2Lonlat();
// 6. INPUT ADDRESS, OUTPUT XY
s.address2Xy();
}
/*
* commons,,,,
*/
private JSONObject requestApi(String params) {
String apiUrl = "https://maps.googleapis.com/maps/api/geocode/json?language=ko&";
JSONObject jObj = null;
try {
jObj = new JSONObject(IOUtils.toString(new URL(apiUrl + params), Charset.forName("UTF-8")));
log(apiUrl + params);
} catch (JSONException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jObj;
}
private String urlEncode(Object obj) {
String result = null;
try {
result = URLEncoder.encode((String) obj, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
private void log(Object msg) {
System.out.println(Thread.currentThread().getStackTrace()[2] + " " + msg);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment