Java,将经纬度转换为UTM

有没有人知道一种方式,在Java中,将地球表面的位置从lat,lon转换为UTM(比如在WGS84中)? 我目前正在看Geotools,但不幸的是解决scheme并不明显。

基于一些示例代码 ,我能够使用Geotools 2.4来获得有效的东西。

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]); 

没有图书馆,没有什么。 复制这个!

使用这两个类,您可以转换度(纬度/经度)UTM和副Versa!

 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; } } 

我build议JCoord 。 它允许您使用一个非常简单的API在各种制图坐标系之间进行转换。

嘿,你感觉很好玩,看看源代码。 它是密集的三angular形的页面和页面。 辉煌的东西。

还有一个名为JSCoord的JavaScript版本。

艾伯塔省10 TM答案可能是为你所需要的矫枉过正 – 从开发者工作的这个链接可能有你需要的所有信息。

看看OpenMap,特别是API中的com.bbn.openmap.proj.coords包。

Wisconson大学的Steve Dutch在algorithm上有很好的写法。 还包括一个Excel文件来帮助validation你的号码。

坐标转换实际上只需要几行代码即可完成:

 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)转换为Web墨卡托投影(EPSG:3857)坐标。

您只需要在构build工具(如maven)中依赖以下两个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> 

这个答案build立在gis.stackexchange.com的问题/回复上。 张贴我的答复,因为这里的答案似乎是相当冗长。

我在这里find了这个 您也可以从这里下载一个完整的实现文件作为* .java文件,并将其复制粘贴到您的项目中。

你可以使用这个项目https://github.com/Berico-Technologies/Geo-Coordinate-Conversion-Java/ ,使用jitpack将它添加到你现有的pom.xml中。

我已经成功地将UTM坐标(30N,这是30个区域和北半球)转换为经度和纬度。 看到我的例子如下:

 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; } 

请注意,Point类是com.vividsolutions.jts.geom.Point类的types。

这个问题类似于这篇文章中的问题 。 如果你看看它的解决scheme,你可以很容易地适应UTM。

也许你在这里操作了很多空间数据,我假设你正在使用一种PostGIS和PostGIS扩展等空间启用的关系数据库。 您可以轻松地在PostGIS中进行这种转换,它提供了OGC标准中定义的几何操作和关系的广泛支持。

只是一个想法!

对于我的项目,我使用了Ahmed Taha的图书馆LatLongLib 。 我认为将坐标从UTM系统转换为纬度经度系统非常容易,反之亦然。 你只需要玩类UTMUtils,UTMPoint和LatLonPoint。

之前我也考虑过selectJcoord 。 这一点也很简单直接。 但是,我需要使用WGS84椭圆体,并且当时只有LatLongLib才具有这个特性。