|
|
@@ -0,0 +1,232 @@
|
|
|
+package com.shkpr.service.customgateway.core.utils;
|
|
|
+
|
|
|
+import com.global.base.log.LogLevelFlag;
|
|
|
+import com.global.base.log.LogPrintMgr;
|
|
|
+import com.shkpr.service.customgateway.core.constants.LogFlagBusiType;
|
|
|
+import org.geotools.referencing.CRS;
|
|
|
+import org.geotools.referencing.GeodeticCalculator;
|
|
|
+import org.locationtech.jts.geom.*;
|
|
|
+import org.locationtech.jts.util.GeometricShapeFactory;
|
|
|
+import org.opengis.referencing.FactoryException;
|
|
|
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
|
|
+import org.opengis.referencing.operation.TransformException;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 地理工具类
|
|
|
+ *
|
|
|
+ * @author 欧阳劲驰
|
|
|
+ * @since 1.0.0
|
|
|
+ */
|
|
|
+public class GeomUtil {
|
|
|
+ /**
|
|
|
+ * log
|
|
|
+ */
|
|
|
+ private final static String mStrClassName = "GeomUtil";
|
|
|
+ private final static String mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
|
|
|
+ /**
|
|
|
+ * geom工厂
|
|
|
+ */
|
|
|
+ private static final GeometryFactory geometryFactory = new GeometryFactory();
|
|
|
+ /**
|
|
|
+ * 形状工厂
|
|
|
+ */
|
|
|
+ private final static GeometricShapeFactory shapeFactory = new GeometricShapeFactory(geometryFactory);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算长度
|
|
|
+ *
|
|
|
+ * @param coordinate1 坐标1
|
|
|
+ * @param coordinate2 坐标2
|
|
|
+ * @return 长度
|
|
|
+ */
|
|
|
+ public static double calcLength(Coordinate coordinate1, Coordinate coordinate2) {
|
|
|
+ double x1 = coordinate1.getX();
|
|
|
+ double y1 = coordinate1.getY();
|
|
|
+ double x2 = coordinate2.getX();
|
|
|
+ double y2 = coordinate2.getY();
|
|
|
+ //计算差
|
|
|
+ double dx = Math.abs(x1 - x2);
|
|
|
+ double dy = Math.abs(y1 - y2);
|
|
|
+ //计算长
|
|
|
+ return Math.sqrt(dx * dx + dy * dy);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转数组
|
|
|
+ *
|
|
|
+ * @param coordinate 坐标
|
|
|
+ * @return 坐标数组
|
|
|
+ */
|
|
|
+ public static double[] toArray(Coordinate coordinate) {
|
|
|
+ return new double[]{coordinate.getX(), coordinate.getY()};
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转数组
|
|
|
+ *
|
|
|
+ * @param lineString 线
|
|
|
+ * @return 坐标数组
|
|
|
+ */
|
|
|
+ public static double[][] toArray(LineString lineString) {
|
|
|
+ //获取geom的坐标
|
|
|
+ Coordinate[] coords = lineString.getCoordinates();
|
|
|
+ if (coords == null || coords.length == 0) return new double[0][2];
|
|
|
+ //构建坐标数组
|
|
|
+ double[][] result = new double[coords.length][2];
|
|
|
+ //存入坐标
|
|
|
+ for (int j = 0; j < coords.length; j++) {
|
|
|
+ result[j][0] = coords[j].getX();
|
|
|
+ result[j][1] = coords[j].getY();
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转数组
|
|
|
+ *
|
|
|
+ * @param multiLineString 线集合
|
|
|
+ * @return 坐标数组
|
|
|
+ */
|
|
|
+ public static double[][][] toArray(MultiLineString multiLineString) {
|
|
|
+ //geom长度
|
|
|
+ int geomLength = multiLineString.getNumGeometries();
|
|
|
+ //结果
|
|
|
+ double[][][] result = new double[geomLength][][];
|
|
|
+ //遍历geom
|
|
|
+ for (int i = 0; i < geomLength; i++) {
|
|
|
+ //获取geom
|
|
|
+ Geometry geom = multiLineString.getGeometryN(i);
|
|
|
+ if (geom instanceof LineString) result[i] = toArray((LineString) geom);
|
|
|
+ else result[i] = new double[0][];
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从数组转换
|
|
|
+ *
|
|
|
+ * @param array 数组
|
|
|
+ * @return 坐标
|
|
|
+ */
|
|
|
+ public static Coordinate ofArray(double[] array) {
|
|
|
+ if (array == null || array.length < 2) return null;
|
|
|
+ return new Coordinate(array[0], array[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从数组转换
|
|
|
+ *
|
|
|
+ * @param array 数组
|
|
|
+ * @return 线
|
|
|
+ */
|
|
|
+ public static LineString ofArray(double[][] array) {
|
|
|
+ if (array == null || array.length == 0) return geometryFactory.createLineString();
|
|
|
+ //遍历数组并构建坐标集合
|
|
|
+ Coordinate[] coordinates = new Coordinate[array.length];
|
|
|
+ for (int j = 0; j < array.length; j++) {
|
|
|
+ //坐标判断
|
|
|
+ if (array[j].length < 2) throw new IllegalArgumentException("坐标点必须包含 [x, y]");
|
|
|
+ //转坐标
|
|
|
+ coordinates[j] = ofArray(array[j]);
|
|
|
+ }
|
|
|
+ return geometryFactory.createLineString(coordinates);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从数组转换
|
|
|
+ *
|
|
|
+ * @param array 数组
|
|
|
+ * @return 多线
|
|
|
+ */
|
|
|
+ public static MultiLineString ofArray(double[][][] array) {
|
|
|
+ if (array == null || array.length == 0) return geometryFactory.createMultiLineString();
|
|
|
+ //遍历数组并构建线集合
|
|
|
+ LineString[] lineStrings = new LineString[array.length];
|
|
|
+ for (int i = 0; i < array.length; i++) {
|
|
|
+ //转线
|
|
|
+ lineStrings[i] = ofArray(array[i]);
|
|
|
+ }
|
|
|
+ return geometryFactory.createMultiLineString(lineStrings);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建圆
|
|
|
+ *
|
|
|
+ * @param centre 圆心
|
|
|
+ * @param radius 半径
|
|
|
+ * @param crsCode 坐标系
|
|
|
+ * @return 圆
|
|
|
+ */
|
|
|
+ public static Polygon createCircle(Coordinate centre, double radius, String crsCode) {
|
|
|
+ try {
|
|
|
+ //端点数量
|
|
|
+ int extremePointsTotal = 32;
|
|
|
+ //经度
|
|
|
+ double lng = centre.getX();
|
|
|
+ //纬度
|
|
|
+ double lat = centre.getY();
|
|
|
+ //坐标系
|
|
|
+ CoordinateReferenceSystem crs = CRS.decode("EPSG:" + crsCode);
|
|
|
+ if (crs == null) return null;
|
|
|
+
|
|
|
+ //创建大地计算器,并设置坐标系
|
|
|
+ GeodeticCalculator gc = new GeodeticCalculator(crs);
|
|
|
+
|
|
|
+ //计算东点(90度),正东移动
|
|
|
+ gc.setStartingGeographicPoint(lng, lat);
|
|
|
+ gc.setDirection(90, radius);
|
|
|
+ //获取结果
|
|
|
+ double[] eastCoords = gc.getDestinationPosition().getCoordinate();
|
|
|
+ Coordinate eastPoint = new Coordinate(eastCoords[1], eastCoords[0]); // 创建 Coordinate 对象
|
|
|
+
|
|
|
+ //计算西点(270度),正西移动
|
|
|
+ gc.setStartingGeographicPoint(lng, lat);
|
|
|
+ gc.setDirection(270, radius);
|
|
|
+ //获取结果
|
|
|
+ double[] westCoords = gc.getDestinationPosition().getCoordinate();
|
|
|
+ Coordinate westPoint = new Coordinate(westCoords[1], westCoords[0]);
|
|
|
+
|
|
|
+ //计算北点(0度),正北移动
|
|
|
+ gc.setStartingGeographicPoint(lng, lat);
|
|
|
+ gc.setDirection(0, radius);
|
|
|
+ //获取结果
|
|
|
+ double[] northCoords = gc.getDestinationPosition().getCoordinate();
|
|
|
+ Coordinate northPoint = new Coordinate(northCoords[1], northCoords[0]);
|
|
|
+
|
|
|
+ //计算南点(180度)
|
|
|
+ gc.setStartingGeographicPoint(lng, lat);
|
|
|
+ gc.setDirection(180, radius);
|
|
|
+ //获取结果
|
|
|
+ double[] southCoords = gc.getDestinationPosition().getCoordinate();
|
|
|
+ Coordinate southPoint = new Coordinate(southCoords[1], southCoords[0]);
|
|
|
+
|
|
|
+ //创建边界框
|
|
|
+ double x1 = westPoint.x;
|
|
|
+ double x2 = eastPoint.x;
|
|
|
+ double y1 = southPoint.y;
|
|
|
+ double y2 = northPoint.y;
|
|
|
+ Envelope envelope = new Envelope(x1, x2, y1, y2);
|
|
|
+
|
|
|
+ //设置圆心
|
|
|
+ Coordinate coordinate = new Coordinate(lng, lat);
|
|
|
+ shapeFactory.setCentre(coordinate);
|
|
|
+ //设置边界
|
|
|
+ shapeFactory.setEnvelope(envelope);
|
|
|
+ //设置边界点数量
|
|
|
+ shapeFactory.setNumPoints(extremePointsTotal);
|
|
|
+
|
|
|
+ //创建圆
|
|
|
+ Polygon circle = shapeFactory.createCircle();
|
|
|
+ //设置坐标系
|
|
|
+ circle.setSRID(Integer.parseInt(crsCode));
|
|
|
+
|
|
|
+ return circle;
|
|
|
+ } catch (TransformException | FactoryException e) {
|
|
|
+ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
|
|
|
+ , String.format("geom创建失败: error:%s", e));
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|