package com.onemap.sanya.utils; import com.fasterxml.jackson.databind.ObjectMapper; import com.onemap.common.core.annotation.Excel; import com.onemap.sanya.domain.spatial.CustomXY; import java.io.IOException; import java.lang.reflect.Field; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import com.onemap.sanya.domain.spatial.FldInfo; import com.onemap.sanya.domain.spatial.SuperMapFreature; import com.onemap.sanya.domain.spatial.SuperMapGeo; import org.geotools.geojson.GeoJSON; import org.geotools.geometry.jts.JTS; import org.geotools.util.factory.Hints; import org.locationtech.jts.geom.*; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.io.WKTReader; import org.locationtech.jts.io.WKTWriter; import org.geotools.referencing.CRS; import org.opengis.referencing.crs.CRSAuthorityFactory; import org.opengis.referencing.crs.CRSFactory; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; public class SpatialOperate { static Hints hints = new Hints(); // static GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(hints); static PrecisionModel precisionModel = new PrecisionModel(PrecisionModel.FLOATING); // 定义一个坐标参考系统,这里使用EPSG:4326,即WGS84 static final int srid = 4490; // WGS84 坐标系(EPSG:4326) private static final String WGS84 = "EPSG:4490"; // 根据你的地理位置选择合适的 UTM Zone private static final String UTM_ZONE = "EPSG:32650"; // static String srid4326 = "GEOGCS[\"WGS 84\",\n" + " DATUM[\"WGS_1984\",\n" + " SPHEROID[\"WGS 84\",6378137,298.257223563,\n" + " AUTHORITY[\"EPSG\",\"7030\"]],\n" + " AUTHORITY[\"EPSG\",\"6326\"]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " AUTHORITY[\"EPSG\",\"8901\"]],\n" + " UNIT[\"degree\",0.0174532925199433,\n" + " AUTHORITY[\"EPSG\",\"9122\"]],\n" + " AUTHORITY[\"EPSG\",\"4326\"]]"; static String srid3857 = "PROJCS[\"WGS 84 / Pseudo-Mercator\",\n" + " GEOGCS[\"WGS 84\",\n" + " DATUM[\"WGS_1984\",\n" + " SPHEROID[\"WGS 84\",6378137,298.257223563,\n" + " AUTHORITY[\"EPSG\",\"7030\"]],\n" + " AUTHORITY[\"EPSG\",\"6326\"]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " AUTHORITY[\"EPSG\",\"8901\"]],\n" + " UNIT[\"degree\",0.0174532925199433,\n" + " AUTHORITY[\"EPSG\",\"9122\"]],\n" + " AUTHORITY[\"EPSG\",\"4326\"]],\n" + " PROJECTION[\"Mercator_1SP\"],\n" + " PARAMETER[\"central_meridian\",0],\n" + " PARAMETER[\"scale_factor\",1],\n" + " PARAMETER[\"false_easting\",0],\n" + " PARAMETER[\"false_northing\",0],\n" + " UNIT[\"metre\",1,\n" + " AUTHORITY[\"EPSG\",\"9001\"]],\n" + " AXIS[\"Easting\",EAST],\n" + " AXIS[\"Northing\",NORTH],\n" + " EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs\"],\n" + " AUTHORITY[\"EPSG\",\"3857\"]]"; static String srid4490 = "GEOGCS[\"China Geodetic Coordinate System 2000\",\n" + " DATUM[\"China_2000\",\n" + " SPHEROID[\"CGCS2000\",6378137,298.257222101,\n" + " AUTHORITY[\"EPSG\",\"1024\"]],\n" + " AUTHORITY[\"EPSG\",\"1043\"]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " AUTHORITY[\"EPSG\",\"8901\"]],\n" + " UNIT[\"degree\",0.0174532925199433,\n" + " AUTHORITY[\"EPSG\",\"9122\"]],\n" + " AUTHORITY[\"EPSG\",\"4490\"]]"; static String srid4546 = "PROJCS[\"CGCS2000 / 3-degree Gauss-Kruger CM 111E\",\n" + " GEOGCS[\"China Geodetic Coordinate System 2000\",\n" + " DATUM[\"China_2000\",\n" + " SPHEROID[\"CGCS2000\",6378137,298.257222101,\n" + " AUTHORITY[\"EPSG\",\"1024\"]],\n" + " AUTHORITY[\"EPSG\",\"1043\"]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " AUTHORITY[\"EPSG\",\"8901\"]],\n" + " UNIT[\"degree\",0.0174532925199433,\n" + " AUTHORITY[\"EPSG\",\"9122\"]],\n" + " AUTHORITY[\"EPSG\",\"4490\"]],\n" + " PROJECTION[\"Transverse_Mercator\"],\n" + " PARAMETER[\"latitude_of_origin\",0],\n" + " PARAMETER[\"central_meridian\",111],\n" + " PARAMETER[\"scale_factor\",1],\n" + " PARAMETER[\"false_easting\",500000],\n" + " PARAMETER[\"false_northing\",0],\n" + " UNIT[\"metre\",1,\n" + " AUTHORITY[\"EPSG\",\"9001\"]],\n" + " AUTHORITY[\"EPSG\",\"4546\"]]"; // 创建GeometryFactory static GeometryFactory geometryFactory = new GeometryFactory(precisionModel, srid); public static Polygon createPolygonByXYArray(List coors) { Polygon pPolygon = null; if (coors == null || coors.size() == 0) return pPolygon; Coordinate[] coordinates = new Coordinate[]{new Coordinate(1, 2), new Coordinate(1, 2), new Coordinate(1, 2)}; pPolygon = geometryFactory.createPolygon(); return pPolygon; } public static String geometry2Wkt(Geometry geometry) { String wkt = "SRID=" + srid + ";"; WKTWriter wktWriter = new WKTWriter(); wkt += wktWriter.write(geometry); return wkt; } public static String geometry2GeoJson(Geometry geometry) throws IOException { String wkt = ""; GeoJSON.write(geometry, wkt); return wkt; } public static Point createPoint(Double x, Double y) { Point point = null; if(x == null && y == null) { return point; } point=geometryFactory.createPoint(new Coordinate(x, y)); point.setSRID(srid); return point; } /** * 根据坐标点创建 * * @param points * @return */ public static Polygon createPolygon(List points) { Polygon polygon = null; if (points == null) return polygon; Coordinate[] coordinates = points.toArray(new Coordinate[points.size()]); LinearRing ring = geometryFactory.createLinearRing(coordinates); polygon = geometryFactory.createPolygon(ring); polygon.setSRID(srid); return polygon; } /** * 为输入的 Geometry 计算 24 米缓冲区,并保持原始坐标系 * @param inputGeometry 输入的几何图形(支持点、线、面等) * @param bufferMeters 缓冲(米) * @return * @throws Exception */ public static Geometry bufferByMeters(Geometry inputGeometry,Double bufferMeters) throws Exception { CoordinateReferenceSystem sourceCRS = CRS.parseWKT(srid4490); // 投影转换 CoordinateReferenceSystem utmCRS = CRS.parseWKT(srid4546); // 转换到 UTM 坐标系进行缓冲区计算 MathTransform toUTM = CRS.findMathTransform(sourceCRS, utmCRS, true); Geometry geometryInUTM = JTS.transform(inputGeometry, toUTM); // 计算 缓冲区 Geometry bufferedGeometryUTM = geometryInUTM.buffer(bufferMeters); // 转回原始坐标系 MathTransform toSource = CRS.findMathTransform(utmCRS, sourceCRS, true); return JTS.transform(bufferedGeometryUTM, toSource); } /** * 经纬度转墨卡托 便于面积转换 * * @param geom * @return */ // public static Geometry lonlat2WebMactor(Geometry geom) { // try { // //这里是以OGC WKT形式定义的是World Mercator投影,网页地图一般使用该投影 // CRSAuthorityFactory factory=CRS.getAuthorityFactory(true); // Integer wkid=geom.getSRID(); // CoordinateReferenceSystem sourceTarget = factory.createCoordinateReferenceSystem("EPSG:"+4490); // //// MathTransform transform1 = CRS.findMathTransform(DefaultGeographicCRS.WGS84, sourceTarget); //// Geometry geometry1= JTS.transform(geom, transform1); // // 投影转换 // CoordinateReferenceSystem crsTarget=factory.createCoordinateReferenceSystem("EPSG:"+4546); //// CoordinateReferenceSystem crsTarget = CRS.parseWKT(srid4546); // // MathTransform transform2 = CRS.findMathTransform(sourceTarget, crsTarget, false); // return JTS.transform(geom, transform2); // } catch (Exception e) { // e.printStackTrace(); // return null; // } // } /** * 经纬度转墨卡托 便于面积转换 * * @param geom * @return */ public static Geometry lonlat2WebMactor(Geometry geom) { try { //这里是以OGC WKT形式定义的是World Mercator投影,网页地图一般使用该投影 CoordinateReferenceSystem sourceTarget = CRS.parseWKT(srid4490); // MathTransform transform1 = CRS.findMathTransform(DefaultGeographicCRS.WGS84, sourceTarget); // Geometry geometry1= JTS.transform(geom, transform1); // 投影转换 CoordinateReferenceSystem crsTarget = CRS.parseWKT(srid4546); MathTransform transform2 = CRS.findMathTransform(sourceTarget, crsTarget, false); return JTS.transform(geom, transform2); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取面积(平方米) * * @param geometry * @return */ public static Double getGeometryArea(Geometry geometry) { if (geometry == null) return 0.00; Geometry geometry1 = lonlat2WebMactor(geometry); if (geometry1 == null) return 0.00; return geometry1.getArea(); } /** * 根据wkt 生成多边形 * * @param wkt * @return * @throws ParseException */ public static Geometry createPolygonByWkt(String wkt) throws ParseException, org.locationtech.jts.io.ParseException { Geometry geometry=null; WKTReader reader = new WKTReader(); Integer index = wkt.indexOf(";"); if (index > -1) wkt = wkt.substring(index + 1); geometry=reader.read(wkt); return geometry; } /** * 根据wkt 生成多边形 * * @param wkt * @return * @throws ParseException */ public static Geometry createGeometryByWkt(String wkt) throws ParseException, org.locationtech.jts.io.ParseException { WKTReader reader = new WKTReader(); Integer index = wkt.indexOf(";"); if (index > -1) wkt = wkt.substring(index + 1); Geometry geometry = reader.read(wkt); geometry.setSRID(srid); return geometry; } public static Double getIntersectsArea(Geometry polygon1, Geometry other) { Double result=0.0; Geometry intersetGeom =null; Boolean isInster= polygon1.intersects(other); if(isInster) { try { intersetGeom = polygon1.intersection(other); } catch (Exception er){ result=0.0; } } if (intersetGeom == null) { result=0.0; } else { Geometry pPolgon = lonlat2WebMactor(intersetGeom); if (pPolgon != null) result = pPolgon.getArea() / 666.66; } return result; } /** * 计算多个面交集 * * @param polygons * @return */ public static Double getIntersectByGeometrys(List polygons) { Geometry intersetGeom = null; if (polygons.size() >= 2) { for (int i = 1; i < polygons.size(); i++) { // 第一次用前两个比较 if (i == 1) { intersetGeom = polygons.get(0).intersection(polygons.get(i)); } // 后续用上次的结果比较 else if (i == polygons.size() - 1) { intersetGeom = intersetGeom.intersection(polygons.get(i)); } // 检查交集是否为空,如果为空则提前结束循环 if (intersetGeom.isEmpty()) { return 0.00; } } } if (!intersetGeom.isEmpty()) { return lonlat2WebMactor(intersetGeom).getArea()/666.66; } else { return 0.00; } } public static SuperMapFreature Feature2Supermap(Object obj, Geometry geom ) throws org.locationtech.jts.io.ParseException, IllegalAccessException { SuperMapFreature res = new SuperMapFreature(); Geometry geometry = geom; WKTReader reader = new WKTReader(); Field[] fields = obj.getClass().getDeclaredFields(); String[] fieldNames = new String[fields.length]; String[] fieldValues = new String[fields.length]; Integer smId = 0; for (int i = 0; i < fields.length; i++) { String fldName = fields[i].getName().toUpperCase(); // if(fldName.equals("SMGEOMETRY")) // continue; fields[i].setAccessible(true); fieldNames[i] = fldName; String s = "null"; if ("SMGEOMETRY".equals(fldName)) { fieldValues[i] = ""; } else { fieldValues[i] = fields[i].get(obj) == null ? s : fields[i].get(obj).toString(); } if (fields[i].getName().toUpperCase().equals("SMID")) smId = Integer.parseInt(fields[i].get(obj).toString()); } int innerCout = 0; LinearRing outRing = null; Integer[] parts = new Integer[1]; Integer[] partTop = new Integer[1]; Integer partIndex = 0; List allPoints = new ArrayList<>(); int outPointCount = 0; LinearRing curInnerRing = null; Polygon polygon = null; if (geom.getGeometryType() == Geometry.TYPENAME_MULTIPOLYGON) polygon = (Polygon) geom.getGeometryN(0); else if (geom.getGeometryType() == Geometry.TYPENAME_POLYGON) { polygon = (Polygon) geom; } innerCout = polygon.getNumInteriorRing(); outRing = polygon.getExteriorRing(); parts = new Integer[innerCout + 1]; partTop = new Integer[innerCout+1]; outPointCount = outRing.getNumPoints(); parts[0] = outPointCount - 1; partTop[0] = 1; partIndex = outPointCount - 1; for (Integer i = 1; i < innerCout; i++) { curInnerRing = polygon.getInteriorRingN(i - 1); partIndex += curInnerRing.getNumPoints(); parts[i] = partIndex; partTop[i] = -1; Coordinate[] ddd= curInnerRing.getCoordinates(); List dddfs= Arrays.stream(ddd).collect(Collectors.toList()); allPoints.addAll(dddfs); } allPoints.addAll(Arrays.stream(outRing.getCoordinates()).collect(Collectors.toList())); SuperMapGeo superMapGeo = new SuperMapGeo(); superMapGeo.setCenter(new Coordinate(geom.getCentroid().getX(), geom.getCentroid().getY())); superMapGeo.setId(smId); superMapGeo.setParts(parts); superMapGeo.setPoints(allPoints); superMapGeo.setType("REGION"); superMapGeo.setPartTopo(partTop); res.setFieldNames(fieldNames); res.setFieldValues(fieldValues); res.setGeometry(superMapGeo); res.setID(smId); return res; } /** * 根据类生成字段列表 * * @param object * @return */ public static List getFieldAnnotation(Object object) { Field[] fields = object.getClass().getDeclaredFields(); List fldInfos = new ArrayList<>(); for (Field field : fields) { // 是否引用ApiModelProperty注解 String name = field.getName(); String typeName = field.getType().getName(); boolean bool = field.isAnnotationPresent(Excel.class); String cnName = ""; if (bool) { cnName = field.getAnnotation(Excel.class).name(); // fldInfos.add(new FldInfo(value); System.out.print(cnName); } if (cnName == null || cnName.isEmpty()) cnName = name; fldInfos.add(new FldInfo(name.toUpperCase(), cnName.toUpperCase(), typeName.toUpperCase())); } return fldInfos; } /** * 根据类生成字段列表 * * @param object * @return */ public static List getFieldAnnotationJZDJ(Object object) { Field[] fields = object.getClass().getDeclaredFields(); List fldInfos = new ArrayList<>(); for (Field field : fields) { // 是否引用ApiModelProperty注解 String name = field.getName(); String typeName = field.getType().getName(); boolean bool = field.isAnnotationPresent(Excel.class); String cnName = ""; if (bool) { cnName = field.getAnnotation(Excel.class).name(); // fldInfos.add(new FldInfo(value); System.out.print(cnName); } if (cnName == null || cnName.isEmpty()) cnName = name; fldInfos.add(new FldInfo(name, cnName, typeName)); } return fldInfos; } // // private GeometryFactory geometryFactory = new GeometryFactory(); // /** // * 根据wkt生成点 // * // * @param wkt // * @return // * @throws ParseException // */ // public Point creatPoint(String wkt) throws ParseException { // WKTReader wktReader = new WKTReader(); // Point point = null; // if (wkt != null) // point = (Point) wktReader.read(wkt); // return point; // } // // /** // * 根据wkt生成线 // * // * @param wkt // * @return // * @throws ParseException // */ // public LineString creatPolyline(String wkt) throws ParseException { // WKTReader wktReader = new WKTReader(); // LineString polyline = null; // if (wkt != null) // polyline = (LineString) wktReader.read(wkt); // return polyline; // } // // /** // * wkt生产面 // * // * @param wkt // * @return // * @throws ParseException // */ // public Polygon creatPolygon(String wkt) throws ParseException { // WKTReader wktReader = new WKTReader(); // Polygon polygon = null; // if (wkt != null) // polygon = (Polygon) wktReader.read(wkt); // return polygon; // } // // /** // * 获取面积 // * @param wkt // * @return // * @throws ParseException // */ // public Double getArea(String wkt) throws ParseException { // WKTReader wktReader = new WKTReader(); // Polygon polygon = null; // if (wkt != null) // polygon = (Polygon) wktReader.read(wkt); // return polygon.getArea(); // } // // // /** // * 根据坐标创建点 // * @param x // * @param y // * @return // */ // public Geometry createPointXY(Double x,Double y) // { // Geometry geometry=null; // Coordinate coord = new Coordinate(x,y); // Point point = geometryFactory.createPoint( coord ); // return point; // } // // /** // * 获取2个实体的的相交面积 // * @param one // * @param other // * @return // */ // public Double getInsertion(Geometry one,Geometry other) // { // if(one==null||other==null) // return 0.00; // Geometry geometry= one.intersection(other); // if(geometry==null) // return 0.00; // return geometry.getArea(); // } }