SpatialOperate.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. package com.onemap.sanya.utils;
  2. import com.fasterxml.jackson.databind.ObjectMapper;
  3. import com.onemap.common.core.annotation.Excel;
  4. import com.onemap.sanya.domain.spatial.CustomXY;
  5. import java.io.IOException;
  6. import java.lang.reflect.Field;
  7. import java.text.ParseException;
  8. import java.util.ArrayList;
  9. import java.util.Arrays;
  10. import java.util.List;
  11. import java.util.stream.Collectors;
  12. import com.onemap.sanya.domain.spatial.FldInfo;
  13. import com.onemap.sanya.domain.spatial.SuperMapFreature;
  14. import com.onemap.sanya.domain.spatial.SuperMapGeo;
  15. import org.geotools.geojson.GeoJSON;
  16. import org.geotools.geometry.jts.JTS;
  17. import org.geotools.util.factory.Hints;
  18. import org.locationtech.jts.geom.*;
  19. import org.locationtech.jts.geom.Polygon;
  20. import org.locationtech.jts.geom.GeometryFactory;
  21. import org.locationtech.jts.io.WKTReader;
  22. import org.locationtech.jts.io.WKTWriter;
  23. import org.geotools.referencing.CRS;
  24. import org.opengis.referencing.crs.CRSAuthorityFactory;
  25. import org.opengis.referencing.crs.CoordinateReferenceSystem;
  26. import org.opengis.referencing.operation.MathTransform;
  27. public class SpatialOperate {
  28. static Hints hints = new Hints();
  29. // static GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(hints);
  30. static PrecisionModel precisionModel = new PrecisionModel(PrecisionModel.FLOATING);
  31. // 定义一个坐标参考系统,这里使用EPSG:4326,即WGS84
  32. static final int srid = 4490;
  33. static String srid4326 = "GEOGCS[\"WGS 84\",\n" +
  34. " DATUM[\"WGS_1984\",\n" +
  35. " SPHEROID[\"WGS 84\",6378137,298.257223563,\n" +
  36. " AUTHORITY[\"EPSG\",\"7030\"]],\n" +
  37. " AUTHORITY[\"EPSG\",\"6326\"]],\n" +
  38. " PRIMEM[\"Greenwich\",0,\n" +
  39. " AUTHORITY[\"EPSG\",\"8901\"]],\n" +
  40. " UNIT[\"degree\",0.0174532925199433,\n" +
  41. " AUTHORITY[\"EPSG\",\"9122\"]],\n" +
  42. " AUTHORITY[\"EPSG\",\"4326\"]]";
  43. static String srid3857 = "PROJCS[\"WGS 84 / Pseudo-Mercator\",\n" +
  44. " GEOGCS[\"WGS 84\",\n" +
  45. " DATUM[\"WGS_1984\",\n" +
  46. " SPHEROID[\"WGS 84\",6378137,298.257223563,\n" +
  47. " AUTHORITY[\"EPSG\",\"7030\"]],\n" +
  48. " AUTHORITY[\"EPSG\",\"6326\"]],\n" +
  49. " PRIMEM[\"Greenwich\",0,\n" +
  50. " AUTHORITY[\"EPSG\",\"8901\"]],\n" +
  51. " UNIT[\"degree\",0.0174532925199433,\n" +
  52. " AUTHORITY[\"EPSG\",\"9122\"]],\n" +
  53. " AUTHORITY[\"EPSG\",\"4326\"]],\n" +
  54. " PROJECTION[\"Mercator_1SP\"],\n" +
  55. " PARAMETER[\"central_meridian\",0],\n" +
  56. " PARAMETER[\"scale_factor\",1],\n" +
  57. " PARAMETER[\"false_easting\",0],\n" +
  58. " PARAMETER[\"false_northing\",0],\n" +
  59. " UNIT[\"metre\",1,\n" +
  60. " AUTHORITY[\"EPSG\",\"9001\"]],\n" +
  61. " AXIS[\"Easting\",EAST],\n" +
  62. " AXIS[\"Northing\",NORTH],\n" +
  63. " 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" +
  64. " AUTHORITY[\"EPSG\",\"3857\"]]";
  65. static String srid4490 = "GEOGCS[\"China Geodetic Coordinate System 2000\",\n" +
  66. " DATUM[\"China_2000\",\n" +
  67. " SPHEROID[\"CGCS2000\",6378137,298.257222101,\n" +
  68. " AUTHORITY[\"EPSG\",\"1024\"]],\n" +
  69. " AUTHORITY[\"EPSG\",\"1043\"]],\n" +
  70. " PRIMEM[\"Greenwich\",0,\n" +
  71. " AUTHORITY[\"EPSG\",\"8901\"]],\n" +
  72. " UNIT[\"degree\",0.0174532925199433,\n" +
  73. " AUTHORITY[\"EPSG\",\"9122\"]],\n" +
  74. " AUTHORITY[\"EPSG\",\"4490\"]]";
  75. static String srid4546 = "PROJCS[\"CGCS2000 / 3-degree Gauss-Kruger CM 111E\",\n" +
  76. " GEOGCS[\"China Geodetic Coordinate System 2000\",\n" +
  77. " DATUM[\"China_2000\",\n" +
  78. " SPHEROID[\"CGCS2000\",6378137,298.257222101,\n" +
  79. " AUTHORITY[\"EPSG\",\"1024\"]],\n" +
  80. " AUTHORITY[\"EPSG\",\"1043\"]],\n" +
  81. " PRIMEM[\"Greenwich\",0,\n" +
  82. " AUTHORITY[\"EPSG\",\"8901\"]],\n" +
  83. " UNIT[\"degree\",0.0174532925199433,\n" +
  84. " AUTHORITY[\"EPSG\",\"9122\"]],\n" +
  85. " AUTHORITY[\"EPSG\",\"4490\"]],\n" +
  86. " PROJECTION[\"Transverse_Mercator\"],\n" +
  87. " PARAMETER[\"latitude_of_origin\",0],\n" +
  88. " PARAMETER[\"central_meridian\",111],\n" +
  89. " PARAMETER[\"scale_factor\",1],\n" +
  90. " PARAMETER[\"false_easting\",500000],\n" +
  91. " PARAMETER[\"false_northing\",0],\n" +
  92. " UNIT[\"metre\",1,\n" +
  93. " AUTHORITY[\"EPSG\",\"9001\"]],\n" +
  94. " AUTHORITY[\"EPSG\",\"4546\"]]";
  95. // 创建GeometryFactory
  96. static GeometryFactory geometryFactory = new GeometryFactory(precisionModel, srid);
  97. public static Polygon createPolygonByXYArray(List<CustomXY> coors) {
  98. Polygon pPolygon = null;
  99. if (coors == null || coors.size() == 0)
  100. return pPolygon;
  101. Coordinate[] coordinates = new Coordinate[]{new Coordinate(1, 2), new Coordinate(1, 2), new Coordinate(1, 2)};
  102. pPolygon = geometryFactory.createPolygon();
  103. return pPolygon;
  104. }
  105. public static String geometry2Wkt(Geometry geometry) {
  106. String wkt = "SRID=" + srid + ";";
  107. WKTWriter wktWriter = new WKTWriter();
  108. wkt += wktWriter.write(geometry);
  109. return wkt;
  110. }
  111. public static String geometry2GeoJson(Geometry geometry) throws IOException {
  112. String wkt = "";
  113. GeoJSON.write(geometry, wkt);
  114. return wkt;
  115. }
  116. public static Point createPoint(Double x, Double y) {
  117. return geometryFactory.createPoint(new Coordinate(x, y));
  118. }
  119. /**
  120. * 根据坐标点创建
  121. *
  122. * @param points
  123. * @return
  124. */
  125. public static Polygon createPolygon(List<Coordinate> points) {
  126. Polygon polygon = null;
  127. if (points == null)
  128. return polygon;
  129. Coordinate[] coordinates = points.toArray(new Coordinate[points.size()]);
  130. LinearRing ring = geometryFactory.createLinearRing(coordinates);
  131. polygon = geometryFactory.createPolygon(ring);
  132. polygon.setSRID(srid);
  133. return polygon;
  134. }
  135. /**
  136. * 经纬度转墨卡托 便于面积转换
  137. *
  138. * @param geom
  139. * @return
  140. */
  141. public static Geometry lonlat2WebMactor(Geometry geom) {
  142. try {
  143. //这里是以OGC WKT形式定义的是World Mercator投影,网页地图一般使用该投影
  144. CRSAuthorityFactory factory=CRS.getAuthorityFactory(true);
  145. Integer wkid=geom.getSRID();
  146. CoordinateReferenceSystem sourceTarget = factory.createCoordinateReferenceSystem("EPSG:"+4490);
  147. // MathTransform transform1 = CRS.findMathTransform(DefaultGeographicCRS.WGS84, sourceTarget);
  148. // Geometry geometry1= JTS.transform(geom, transform1);
  149. // 投影转换
  150. CoordinateReferenceSystem crsTarget=factory.createCoordinateReferenceSystem("EPSG:"+4546);
  151. // CoordinateReferenceSystem crsTarget = CRS.parseWKT(srid4546);
  152. MathTransform transform2 = CRS.findMathTransform(sourceTarget, crsTarget, false);
  153. return JTS.transform(geom, transform2);
  154. } catch (Exception e) {
  155. // TODO Auto-generated catch block
  156. e.printStackTrace();
  157. return null;
  158. }
  159. }
  160. /**
  161. * 获取面积(平方米)
  162. *
  163. * @param geometry
  164. * @return
  165. */
  166. public static Double getGeometryArea(Geometry geometry) {
  167. if (geometry == null)
  168. return 0.00;
  169. Geometry geometry1 = lonlat2WebMactor(geometry);
  170. if (geometry1 == null)
  171. return 0.00;
  172. return geometry1.getArea();
  173. }
  174. /**
  175. * 根据wkt 生成多边形
  176. *
  177. * @param wkt
  178. * @return
  179. * @throws ParseException
  180. */
  181. public static Geometry createPolygonByWkt(String wkt) throws ParseException, org.locationtech.jts.io.ParseException {
  182. Geometry geometry=null;
  183. WKTReader reader = new WKTReader();
  184. Integer index = wkt.indexOf(";");
  185. if (index > -1)
  186. wkt = wkt.substring(index + 1);
  187. geometry=reader.read(wkt);
  188. return geometry;
  189. }
  190. /**
  191. * 根据wkt 生成多边形
  192. *
  193. * @param wkt
  194. * @return
  195. * @throws ParseException
  196. */
  197. public static Geometry createGeometryByWkt(String wkt) throws ParseException, org.locationtech.jts.io.ParseException {
  198. WKTReader reader = new WKTReader();
  199. Integer index = wkt.indexOf(";");
  200. if (index > -1)
  201. wkt = wkt.substring(index + 1);
  202. Geometry geometry = reader.read(wkt);
  203. geometry.setSRID(srid);
  204. return geometry;
  205. }
  206. public static Double getIntersectsArea(Geometry polygon1, Geometry other) {
  207. Double result=0.0;
  208. Geometry intersetGeom =null;
  209. Boolean isInster= polygon1.intersects(other);
  210. if(isInster)
  211. {
  212. try {
  213. intersetGeom = polygon1.intersection(other);
  214. }
  215. catch (Exception er){
  216. result=0.0;
  217. }
  218. }
  219. if (intersetGeom == null) {
  220. result=0.0;
  221. }
  222. else {
  223. Geometry pPolgon = lonlat2WebMactor(intersetGeom);
  224. if (pPolgon != null)
  225. result = pPolgon.getArea() / 666.66;
  226. }
  227. return result;
  228. }
  229. /**
  230. * 计算多个面交集
  231. *
  232. * @param polygons
  233. * @return
  234. */
  235. public static Double getIntersectByGeometrys(List<Geometry> polygons) {
  236. Geometry intersetGeom = null;
  237. if (polygons.size() >= 2) {
  238. for (int i = 1; i < polygons.size(); i++) {
  239. // 第一次用前两个比较
  240. if (i == 1) {
  241. intersetGeom = polygons.get(0).intersection(polygons.get(i));
  242. }
  243. // 后续用上次的结果比较
  244. else if (i == polygons.size() - 1) {
  245. intersetGeom = intersetGeom.intersection(polygons.get(i));
  246. }
  247. // 检查交集是否为空,如果为空则提前结束循环
  248. if (intersetGeom.isEmpty()) {
  249. return 0.00;
  250. }
  251. }
  252. }
  253. if (!intersetGeom.isEmpty()) {
  254. return lonlat2WebMactor(intersetGeom).getArea()/666.66;
  255. } else {
  256. return 0.00;
  257. }
  258. }
  259. public static SuperMapFreature Feature2Supermap(Object obj, Geometry geom ) throws org.locationtech.jts.io.ParseException, IllegalAccessException {
  260. SuperMapFreature res = new SuperMapFreature();
  261. Geometry geometry = geom;
  262. WKTReader reader = new WKTReader();
  263. Field[] fields = obj.getClass().getDeclaredFields();
  264. String[] fieldNames = new String[fields.length];
  265. String[] fieldValues = new String[fields.length];
  266. Integer smId = 0;
  267. for (int i = 0; i < fields.length; i++) {
  268. String fldName = fields[i].getName().toUpperCase();
  269. // if(fldName.equals("SMGEOMETRY"))
  270. // continue;
  271. fields[i].setAccessible(true);
  272. fieldNames[i] = fldName;
  273. String s = "null";
  274. if(fldName=="SMGEOMETRY")
  275. fieldValues[i]="";
  276. fieldValues[i] = fields[i].get(obj) == null ? s : fields[i].get(obj).toString();
  277. if (fields[i].getName().toUpperCase().equals("SMID"))
  278. smId = Integer.parseInt(fields[i].get(obj).toString());
  279. }
  280. int innerCout = 0;
  281. LinearRing outRing = null;
  282. Integer[] parts = new Integer[1];
  283. Integer[] partTop = new Integer[1];
  284. Integer partIndex = 0;
  285. List<Coordinate> allPoints = new ArrayList<>();
  286. int outPointCount = 0;
  287. LinearRing curInnerRing = null;
  288. Polygon polygon = null;
  289. if (geom.getGeometryType() == Geometry.TYPENAME_MULTIPOLYGON)
  290. polygon = (Polygon) geom.getGeometryN(0);
  291. else if (geom.getGeometryType() == Geometry.TYPENAME_POLYGON) {
  292. polygon = (Polygon) geom;
  293. }
  294. innerCout = polygon.getNumInteriorRing();
  295. outRing = polygon.getExteriorRing();
  296. parts = new Integer[innerCout + 1];
  297. partTop = new Integer[innerCout+1];
  298. outPointCount = outRing.getNumPoints();
  299. parts[0] = outPointCount - 1;
  300. partTop[0] = 1;
  301. partIndex = outPointCount - 1;
  302. for (Integer i = 1; i < innerCout; i++) {
  303. curInnerRing = polygon.getInteriorRingN(i - 1);
  304. partIndex += curInnerRing.getNumPoints();
  305. parts[i] = partIndex;
  306. partTop[i] = -1;
  307. Coordinate[] ddd= curInnerRing.getCoordinates();
  308. List<Coordinate> dddfs= Arrays.stream(ddd).collect(Collectors.toList());
  309. allPoints.addAll(dddfs);
  310. }
  311. allPoints.addAll(Arrays.stream(outRing.getCoordinates()).collect(Collectors.toList()));
  312. SuperMapGeo superMapGeo = new SuperMapGeo();
  313. superMapGeo.setCenter(new Coordinate(geom.getCentroid().getX(), geom.getCentroid().getY()));
  314. superMapGeo.setId(smId);
  315. superMapGeo.setParts(parts);
  316. superMapGeo.setPoints(allPoints);
  317. superMapGeo.setType("REGION");
  318. superMapGeo.setPartTopo(partTop);
  319. res.setFieldNames(fieldNames);
  320. res.setFieldValues(fieldValues);
  321. res.setGeometry(superMapGeo);
  322. res.setID(smId);
  323. return res;
  324. }
  325. /**
  326. * 根据类生成字段列表
  327. *
  328. * @param object
  329. * @return
  330. */
  331. public static List<FldInfo> getFieldAnnotation(Object object) {
  332. Field[] fields = object.getClass().getDeclaredFields();
  333. List<FldInfo> fldInfos = new ArrayList<>();
  334. for (Field field : fields) {
  335. // 是否引用ApiModelProperty注解
  336. String name = field.getName();
  337. String typeName = field.getType().getName();
  338. boolean bool = field.isAnnotationPresent(Excel.class);
  339. String cnName = "";
  340. if (bool) {
  341. cnName = field.getAnnotation(Excel.class).name();
  342. // fldInfos.add(new FldInfo(value);
  343. System.out.print(cnName);
  344. }
  345. if (cnName == "" || cnName == null)
  346. cnName = name;
  347. fldInfos.add(new FldInfo(name.toUpperCase(), cnName.toUpperCase(), typeName.toUpperCase()));
  348. }
  349. return fldInfos;
  350. }
  351. //
  352. // private GeometryFactory geometryFactory = new GeometryFactory();
  353. // /**
  354. // * 根据wkt生成点
  355. // *
  356. // * @param wkt
  357. // * @return
  358. // * @throws ParseException
  359. // */
  360. // public Point creatPoint(String wkt) throws ParseException {
  361. // WKTReader wktReader = new WKTReader();
  362. // Point point = null;
  363. // if (wkt != null)
  364. // point = (Point) wktReader.read(wkt);
  365. // return point;
  366. // }
  367. //
  368. // /**
  369. // * 根据wkt生成线
  370. // *
  371. // * @param wkt
  372. // * @return
  373. // * @throws ParseException
  374. // */
  375. // public LineString creatPolyline(String wkt) throws ParseException {
  376. // WKTReader wktReader = new WKTReader();
  377. // LineString polyline = null;
  378. // if (wkt != null)
  379. // polyline = (LineString) wktReader.read(wkt);
  380. // return polyline;
  381. // }
  382. //
  383. // /**
  384. // * wkt生产面
  385. // *
  386. // * @param wkt
  387. // * @return
  388. // * @throws ParseException
  389. // */
  390. // public Polygon creatPolygon(String wkt) throws ParseException {
  391. // WKTReader wktReader = new WKTReader();
  392. // Polygon polygon = null;
  393. // if (wkt != null)
  394. // polygon = (Polygon) wktReader.read(wkt);
  395. // return polygon;
  396. // }
  397. //
  398. // /**
  399. // * 获取面积
  400. // * @param wkt
  401. // * @return
  402. // * @throws ParseException
  403. // */
  404. // public Double getArea(String wkt) throws ParseException {
  405. // WKTReader wktReader = new WKTReader();
  406. // Polygon polygon = null;
  407. // if (wkt != null)
  408. // polygon = (Polygon) wktReader.read(wkt);
  409. // return polygon.getArea();
  410. // }
  411. //
  412. //
  413. // /**
  414. // * 根据坐标创建点
  415. // * @param x
  416. // * @param y
  417. // * @return
  418. // */
  419. // public Geometry createPointXY(Double x,Double y)
  420. // {
  421. // Geometry geometry=null;
  422. // Coordinate coord = new Coordinate(x,y);
  423. // Point point = geometryFactory.createPoint( coord );
  424. // return point;
  425. // }
  426. //
  427. // /**
  428. // * 获取2个实体的的相交面积
  429. // * @param one
  430. // * @param other
  431. // * @return
  432. // */
  433. // public Double getInsertion(Geometry one,Geometry other)
  434. // {
  435. // if(one==null||other==null)
  436. // return 0.00;
  437. // Geometry geometry= one.intersection(other);
  438. // if(geometry==null)
  439. // return 0.00;
  440. // return geometry.getArea();
  441. // }
  442. }