2008-10-06 5 views
18

Java에서 지구 표면 위치를 lat, lon에서 UTM으로 변환하는 방법을 아는 사람이 있습니까 (예 : WGS84)? 저는 현재 Geotools를보고 있지만 불행히도 해결책은 분명하지 않습니다.Java, lat/lon을 UTM으로 변환

+1

예 GeoTools 설명서는 최종 사용자가 이미 API 및 일반적으로 GIS에 대해 매우 잘 알고 있다고 가정합니다. 이해하기가 매우 어렵습니다. 나는 현재지도를 사용하여지도에 점을 표시하는 데 어려움을 겪고 있습니다. http://stackoverflow.com/questions/29567231/why-cant-this-code-producea-a-points-layer-in-geotools – cj5

답변

19

Geotools 2.4를 사용하여 일부는 example code을 기반으로 작동하는 것을 얻을 수있었습니다.

double utmZoneCenterLongitude = ... // Center lon of zone, example: zone 10 = -123 
int zoneNumber = ...     // zone number, example: 10 
double latitude, longitude = ...  // lat, lon in degrees 

MathTransformFactory mtFactory = ReferencingFactoryFinder.getMathTransformFactory(null); 
ReferencingFactoryContainer factories = new ReferencingFactoryContainer(null); 

GeographicCRS geoCRS = org.geotools.referencing.crs.DefaultGeographicCRS.WGS84; 
CartesianCS cartCS = org.geotools.referencing.cs.DefaultCartesianCS.GENERIC_2D; 

ParameterValueGroup parameters = mtFactory.getDefaultParameters("Transverse_Mercator"); 
parameters.parameter("central_meridian").setValue(utmZoneCenterLongitude); 
parameters.parameter("latitude_of_origin").setValue(0.0); 
parameters.parameter("scale_factor").setValue(0.9996); 
parameters.parameter("false_easting").setValue(500000.0); 
parameters.parameter("false_northing").setValue(0.0); 

Map properties = Collections.singletonMap("name", "WGS 84/UTM Zone " + zoneNumber); 
ProjectedCRS projCRS = factories.createProjectedCRS(properties, geoCRS, null, parameters, cartCS); 

MathTransform transform = CRS.findMathTransform(geoCRS, projCRS); 

double[] dest = new double[2]; 
transform.transform(new double[] {longitude, latitude}, 0, dest, 0, 1); 

int easting = (int)Math.round(dest[0]); 
int northing = (int)Math.round(dest[1]); 
5

알버타 10 TM 대답은 아마도 당신이 필요로하는 것에 대한 과잉 공격 일 것입니다 - 개발자의 작품에서 나온 this link에 아마도 필요한 모든 정보가있을 것입니다.

+1

이 링크는 질문에 대한 답변 일지 모르지만 본질적인 부분을 포함하는 것이 좋습니다. 여기에 답변하고 참조 용 링크를 제공하십시오. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않게 될 수 있습니다. - [검토 중] (리뷰/저품각 게시물/17991146) –

1

Steve Dutch at University of Wisconson에는 알고리즘에 대한 훌륭한 글이 있습니다. 또한 귀하의 번호를 확인하는 데 도움이되는 Excel 문서가 포함되어 있습니다.

+1

이 링크는 질문에 대한 답변 일지 모르지만 여기에 답변의 핵심 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않게 될 수 있습니다. - [리뷰에서] (리뷰/저품절 포스트/17991149) –

9

나는 JCoord을 제안합니다. 아주 간단한 API를 사용하여 다양한지도 제작 좌표 체계간에 변환 할 수 있습니다.

당신은 소스 코드를 살펴볼 때 짜증이납니다. 그것은 조밀 한 삼각법의 페이지와 페이지입니다. 훌륭한 재료.

또한 JSCoord라는 자바 스크립트 버전이 있습니다.

0

아마도 여기 공간 데이터를 많이 조작하고 있습니다. Postgres 확장과 함께 공간적으로 사용 가능한 관계형 dbms를 사용하고 있다고 가정합니다. PostGIS에서 이러한 종류의 변환을 쉽게 수행 할 수 있으며, OGC 표준에 정의 된대로 기하학적 연산과 관계를 광범위하게 지원합니다.

그냥 생각해보십시오!

19

라이브러리 없음, 아니요. 이것을 복사하십시오!

위의 두 클래스를 사용하면 학위 (위도/경도)를 UTM 및 그 반대로 변환 할 수 있습니다.

private class Deg2UTM 
{ 
    double Easting; 
    double Northing; 
    int Zone; 
    char Letter; 
    private Deg2UTM(double Lat,double Lon) 
    { 
     Zone= (int) Math.floor(Lon/6+31); 
     if (Lat<-72) 
      Letter='C'; 
     else if (Lat<-64) 
      Letter='D'; 
     else if (Lat<-56) 
      Letter='E'; 
     else if (Lat<-48) 
      Letter='F'; 
     else if (Lat<-40) 
      Letter='G'; 
     else if (Lat<-32) 
      Letter='H'; 
     else if (Lat<-24) 
      Letter='J'; 
     else if (Lat<-16) 
      Letter='K'; 
     else if (Lat<-8) 
      Letter='L'; 
     else if (Lat<0) 
      Letter='M'; 
     else if (Lat<8) 
      Letter='N'; 
     else if (Lat<16) 
      Letter='P'; 
     else if (Lat<24) 
      Letter='Q'; 
     else if (Lat<32) 
      Letter='R'; 
     else if (Lat<40) 
      Letter='S'; 
     else if (Lat<48) 
      Letter='T'; 
     else if (Lat<56) 
      Letter='U'; 
     else if (Lat<64) 
      Letter='V'; 
     else if (Lat<72) 
      Letter='W'; 
     else 
      Letter='X'; 
     Easting=0.5*Math.log((1+Math.cos(Lat*Math.PI/180)*Math.sin(Lon*Math.PI/180-(6*Zone-183)*Math.PI/180))/(1-Math.cos(Lat*Math.PI/180)*Math.sin(Lon*Math.PI/180-(6*Zone-183)*Math.PI/180)))*0.9996*6399593.62/Math.pow((1+Math.pow(0.0820944379, 2)*Math.pow(Math.cos(Lat*Math.PI/180), 2)), 0.5)*(1+ Math.pow(0.0820944379,2)/2*Math.pow((0.5*Math.log((1+Math.cos(Lat*Math.PI/180)*Math.sin(Lon*Math.PI/180-(6*Zone-183)*Math.PI/180))/(1-Math.cos(Lat*Math.PI/180)*Math.sin(Lon*Math.PI/180-(6*Zone-183)*Math.PI/180)))),2)*Math.pow(Math.cos(Lat*Math.PI/180),2)/3)+500000; 
     Easting=Math.round(Easting*100)*0.01; 
     Northing = (Math.atan(Math.tan(Lat*Math.PI/180)/Math.cos((Lon*Math.PI/180-(6*Zone -183)*Math.PI/180)))-Lat*Math.PI/180)*0.9996*6399593.625/Math.sqrt(1+0.006739496742*Math.pow(Math.cos(Lat*Math.PI/180),2))*(1+0.006739496742/2*Math.pow(0.5*Math.log((1+Math.cos(Lat*Math.PI/180)*Math.sin((Lon*Math.PI/180-(6*Zone -183)*Math.PI/180)))/(1-Math.cos(Lat*Math.PI/180)*Math.sin((Lon*Math.PI/180-(6*Zone -183)*Math.PI/180)))),2)*Math.pow(Math.cos(Lat*Math.PI/180),2))+0.9996*6399593.625*(Lat*Math.PI/180-0.005054622556*(Lat*Math.PI/180+Math.sin(2*Lat*Math.PI/180)/2)+4.258201531e-05*(3*(Lat*Math.PI/180+Math.sin(2*Lat*Math.PI/180)/2)+Math.sin(2*Lat*Math.PI/180)*Math.pow(Math.cos(Lat*Math.PI/180),2))/4-1.674057895e-07*(5*(3*(Lat*Math.PI/180+Math.sin(2*Lat*Math.PI/180)/2)+Math.sin(2*Lat*Math.PI/180)*Math.pow(Math.cos(Lat*Math.PI/180),2))/4+Math.sin(2*Lat*Math.PI/180)*Math.pow(Math.cos(Lat*Math.PI/180),2)*Math.pow(Math.cos(Lat*Math.PI/180),2))/3); 
     if (Letter<'M') 
      Northing = Northing + 10000000; 
     Northing=Math.round(Northing*100)*0.01; 
    } 
} 

private class UTM2Deg 
{ 
    double latitude; 
    double longitude; 
    private UTM2Deg(String UTM) 
    { 
     String[] parts=UTM.split(" "); 
     int Zone=Integer.parseInt(parts[0]); 
     char Letter=parts[1].toUpperCase(Locale.ENGLISH).charAt(0); 
     double Easting=Double.parseDouble(parts[2]); 
     double Northing=Double.parseDouble(parts[3]);   
     double Hem; 
     if (Letter>'M') 
      Hem='N'; 
     else 
      Hem='S';    
     double north; 
     if (Hem == 'S') 
      north = Northing - 10000000; 
     else 
      north = Northing; 
     latitude = (north/6366197.724/0.9996+(1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)-0.006739496742*Math.sin(north/6366197.724/0.9996)*Math.cos(north/6366197.724/0.9996)*(Math.atan(Math.cos(Math.atan((Math.exp((Easting - 500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting - 500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2)/3))-Math.exp(-(Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1 - 0.006739496742*Math.pow((Easting - 500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2)/3)))/2/Math.cos((north-0.9996*6399593.625*(north/6366197.724/0.9996-0.006739496742*3/4*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.pow(0.006739496742*3/4,2)*5/3*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4-Math.pow(0.006739496742*3/4,3)*35/27*(5*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/3))/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2))+north/6366197.724/0.9996)))*Math.tan((north-0.9996*6399593.625*(north/6366197.724/0.9996 - 0.006739496742*3/4*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.pow(0.006739496742*3/4,2)*5/3*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4-Math.pow(0.006739496742*3/4,3)*35/27*(5*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/3))/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2))+north/6366197.724/0.9996))-north/6366197.724/0.9996)*3/2)*(Math.atan(Math.cos(Math.atan((Math.exp((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2)/3))-Math.exp(-(Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2)/3)))/2/Math.cos((north-0.9996*6399593.625*(north/6366197.724/0.9996-0.006739496742*3/4*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.pow(0.006739496742*3/4,2)*5/3*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4-Math.pow(0.006739496742*3/4,3)*35/27*(5*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/3))/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2))+north/6366197.724/0.9996)))*Math.tan((north-0.9996*6399593.625*(north/6366197.724/0.9996-0.006739496742*3/4*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.pow(0.006739496742*3/4,2)*5/3*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4-Math.pow(0.006739496742*3/4,3)*35/27*(5*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/3))/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2))+north/6366197.724/0.9996))-north/6366197.724/0.9996))*180/Math.PI; 
     latitude=Math.round(latitude*10000000); 
     latitude=latitude/10000000; 
     longitude =Math.atan((Math.exp((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2)/3))-Math.exp(-(Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2)/3)))/2/Math.cos((north-0.9996*6399593.625*(north/6366197.724/0.9996-0.006739496742*3/4*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.pow(0.006739496742*3/4,2)*5/3*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2* north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4-Math.pow(0.006739496742*3/4,3)*35/27*(5*(3*(north/6366197.724/0.9996+Math.sin(2*north/6366197.724/0.9996)/2)+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/4+Math.sin(2*north/6366197.724/0.9996)*Math.pow(Math.cos(north/6366197.724/0.9996),2)*Math.pow(Math.cos(north/6366197.724/0.9996),2))/3))/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2))))*(1-0.006739496742*Math.pow((Easting-500000)/(0.9996*6399593.625/Math.sqrt((1+0.006739496742*Math.pow(Math.cos(north/6366197.724/0.9996),2)))),2)/2*Math.pow(Math.cos(north/6366197.724/0.9996),2))+north/6366197.724/0.9996))*180/Math.PI+Zone*6-183; 
     longitude=Math.round(longitude*10000000); 
     longitude=longitude/10000000;  
    } 
} 
+0

더 나은 이해를위한 짧은 코멘트가 좋을 수도 있습니다. –

+0

다음과 같은 클래스 사용 : UTM2Deg pos = new UTM2Deg ("35 R 312915.84 4451481.33") lat = pos.latitude. – user2548538

+1

지구가 회전 타원체이고 구형이 아니라는 점에서이 요소가 작용합니까? –

0

내 프로젝트의 경우 Ahmed Taha의 LatLongLib 라이브러리를 사용했습니다. 저는 UTM 시스템에서 Latitude-Longitude 시스템으로 좌표를 변환하는 것이 매우 쉽고 그 반대도 마찬가지라고 생각합니다. UTMUtils, UTMPoint 및 LatLonPoint 클래스로 게임하면됩니다.

시간 전 나는 또한 Jcoord을 선택하는 것으로 생각했습니다. 요점까지 쉽고 직선적이었습니다. 그러나 WGS84 타원체를 사용해야하고 LatLongLib 만 그 기능을 가진 것처럼 보였습니다.

1

이 프로젝트 https://github.com/Berico-Technologies/Geo-Coordinate-Conversion-Java/을 사용하여 jitpack을 사용하여 기존 pom.xml에 추가 할 수 있습니다.

위도와 경도로 UTM 좌표 (30N, 30 구역 및 북반구)를 성공적으로 변환 할 수있었습니다. Point 클래스는 com.vividsolutions.jts.geom.Point 클래스 타입이다

public void setPunto(Point punto) { 
    this.punto = punto; 
    LatLon latlon = UTMCoord.locationFromUTMCoord(30, AVKey.NORTH, punto.getX(), punto.getY()); 
    this.latitud = latlon.getLatitude().degrees; 
    this.longitud = latlon.getLongitude().degrees; 
} 

참고 : 아래에있는 내 예를 참조하십시오.

2

실제로 코드의 몇 줄에서 수행 할 수 있습니다 좌표 변환 :

Coordinate coordinate = new Coordinate(x, y); 
MathTransform transform = CRS.findMathTransform(CRS.decode("EPSG:4326"), CRS.decode("EPSG:3857"), false); 
JTS.transform(coordinate, coordinate, transform); 

이것은 위도/경도가 (EPSG : 4326) 좌표 변환됩니다 웹 메르카토르 투영에 (EPSG : 3857) 동등 어구.

당신은 당신의 빌드 도구에서 다음과 같은 두 가지 GeoTools 라이브러리에 (예를 들어 받는다는) 의존해야

<repositories> 
    <repository> 
     <id>osgeo</id> 
     <name>Open Source Geospatial Foundation Repository</name> 
     <url>http://download.osgeo.org/webdav/geotools/</url> 
    </repository> 
</repositories> 

<dependencies> 
    <dependency> 
     <groupId>org.geotools</groupId> 
     <artifactId>gt-api</artifactId> 
     <version>${geotools.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.geotools</groupId> 
     <artifactId>gt-epsg-hsql</artifactId> 
     <version>${geotools.version}</version> 
    </dependency> 
</dependencies> 

이 답변 gis.stackexchange.com에 question/reply에 구축합니다. 현재 답변은 매우 장황하기 때문에 내 답글을 올리십시오.

+0

JTS를 사용하여 UTM에서 위도/경도로 어때요? –