背景
今天对一些经纬做坐标数据进行投影,然后计算长度等。发现了geotools神奇的内容。发现使用EPSG的编码建立的坐标在读取数据的时候报错。分别出现了以下报错,揪头发好久后发现问题。
问题描述
源码
import org.geotools.geometry.jts.JTS;
import org.locationtech.jts.geom.Point;
import org.geotools.referencing.CRS;
import org.locationtech.jts.io.WKTReader;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
public static void LayoutSetting(String wkt) {
WKTReader reader = new WKTReader();
try {
Point geometry = (Point) reader.read(wkt);
CoordinateReferenceSystem crsresource = CRS.decode("EPSG:4326");
CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");
// 投影转换
MathTransform transform = CRS.findMathTransform(crsresource, crsTarget);
Point Point = (Point) JTS.transform(geometry, transform);
System.out.println(Point.toString());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
LayoutSetting("POINT(108.919395773839 34.2610691575462)");
}
报错
1 因为库不存在引起的报错
Exception in thread "main" org.opengis.referencing.NoSuchAuthorityCodeException: No code "EPSG:4326" from authority "EPSG" found for object of type "EngineeringCRS".
at org.geotools.referencing.factory.epsg.CartesianAuthorityFactory.noSuchAuthorityException(CartesianAuthorityFactory.java:136)
at org.geotools.referencing.factory.epsg.CartesianAuthorityFactory.createEngineeringCRS(CartesianAuthorityFactory.java:128)
at org.geotools.referencing.factory.epsg.CartesianAuthorityFactory.createCoordinateReferenceSystem(CartesianAuthorityFactory.java:119)
at org.geotools.referencing.factory.AuthorityFactoryAdapter.createCoordinateReferenceSystem(AuthorityFactoryAdapter.java:779)
at org.geotools.referencing.factory.ThreadedAuthorityFactory.createCoordinateReferenceSystem(ThreadedAuthorityFactory.java:635)
at org.geotools.referencing.DefaultAuthorityFactory.createCoordinateReferenceSystem(DefaultAuthorityFactory.java:176)
at org.geotools.referencing.CRS.decode(CRS.java:517)
at org.geotools.referencing.CRS.decode(CRS.java:433)
at com.ytkj.aos.core.util.ProjectGeometry.Project4326To3857(ProjectGeometry.java:70)
at com.ytkj.aos.core.util.ProjectGeometry.main(ProjectGeometry.java:178)
2 使用EPSG坐标报错引起的错误
2024-06-25T16:14:44.582+0800 WARNING Possible use of "Popular Visualisation Pseudo Mercator" projection outside its valid area.
Latitude 108°55.2'N is out of range (±90°).
原因分析
先报错1 是因为没有找到CRS引擎,也就是没有找到CRS库 gt-epsg-hsql
解决办法,引入库
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-epsg-hsql</artifactId>
<version>${geotools.version}</version>
</dependency>
<!-- <geotools.version>24-RC</geotools.version>-->
后报错 2, 经过尝试,调换XY坐标即可解出
public static void main(String[] args) {
LayoutSetting("POINT(108.919395773839 34.2610691575462)");
}
//输出 POINT (12124851.67505479 4063911.3374026217) 结果居然是对的
虽然能解决我坐标转换问题,但是,但是我的数据是从pg来的,我pg出的坐标全是POINT(经度 纬度)
我用这样的解决办法肯定不行的,肯定是我那个地方除了问题,与我就找啊找,找啊找,然后下班时间到了,我就熬夜加班了…
最后的最后,无奈我换了解决办法…(此处无奈记下,此生抽空复盘改掉)
解决方案
最终解决办法是,换初始化坐标思路。
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.io.ParseException;
import org.geotools.referencing.CRS;
import org.locationtech.jts.io.WKTReader;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
public class LayoutSetting {
private double limitMaxY;
private double limitMaxX;
public static Geometry getGeometry(String wkt) throws ParseException {
Geometry geometry;
WKTReader reader = new WKTReader();
geometry = (Point) reader.read(wkt);
return geometry;
}
private static CoordinateReferenceSystem getWgs84() throws FactoryException {
String wgs84 = "GEOGCS[\"WGS 84\", \n" +
" DATUM[\"World Geodetic System 1984\", \n" +
" SPHEROID[\"WGS 84\", 6378137.0, 298.257223563, AUTHORITY[\"EPSG\",\"7030\"]], \n" +
" AUTHORITY[\"EPSG\",\"6326\"]], \n" +
" PRIMEM[\"Greenwich\", 0.0, AUTHORITY[\"EPSG\",\"8901\"]], \n" +
" UNIT[\"degree\", 0.017453292519943295],\n" +
" AXIS[\"Geodetic longitude\", EAST], \n" +
" AXIS[\"Geodetic latitude\", NORTH], \n" +
" \n" +
" AUTHORITY[\"EPSG\",\"4326\"]]";
return CRS.parseWKT(wgs84);
}
private static CoordinateReferenceSystem getWebMercator() throws FactoryException {
String webMercator = "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\",GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Mercator_Auxiliary_Sphere\"],PARAMETER[\"False_Easting\",0.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0],PARAMETER[\"Standard_Parallel_1\",0.0],PARAMETER[\"Auxiliary_Sphere_Type\",0.0],UNIT[\"Meter\",1.0],AUTHORITY[\"EPSG\",3857]]";
return CRS.parseWKT(webMercator);
}
public static Geometry ProjectWgs84toWebMercator(Geometry source) {
Geometry pointTarget = null;
try {
CoordinateReferenceSystem crsSource = getWgs84();
CoordinateReferenceSystem crsTarget = getWebMercator();
// 投影转换
MathTransform transform = CRS.findMathTransform(crsSource, crsTarget, true);
pointTarget = JTS.transform(source, transform);
} catch (FactoryException | TransformException e) {
e.printStackTrace();
}
return pointTarget;
}
public static void main(String[] args) throws ParseException {
Geometry point= getGeometry( "POINT(108.919395773839 34.2610691575462)");
Geometry XY=ProjectWgs84toWebMercator(point);
System.out.println(XY.toString());
}
}
详情请关注“学GIS的小宝同学”微信公众号