GeoJson转ArcGIS的EsriJson
程序员文章站
2022-07-02 11:18:48
这次遇到了一个小问题,postgresql只能到处geojson(毕竟是一个标准格式),而客户需求的是ArcGIS支持的EsriJson格式。需要在数据之间进行一个转换。再网上查阅了一定资料,最后发现下面的代码比较可行。这里分享一下:主要代码package com.cic.analysis.business.utils;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.cic...
这次遇到了一个小问题,postgresql只能到处geojson(毕竟是一个标准格式),而客户需求的是ArcGIS支持的EsriJson格式。需要在数据之间进行一个转换。再网上查阅了一定资料,最后发现下面的代码比较可行。这里分享一下:
主要代码
package com.cic.analysis.business.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cic.common.utils.StringUtils;
import java.math.BigDecimal;
import java.util.*;
public class EsriGeoJsonUtil {
//EsriJson转geoJson
public static String esri2geo(String ersiJson){
Map geoMap = new HashMap();
try {
List geoFs = new ArrayList();
geoMap.put("type", "FeatureCollection");
Map esriMap = (Map) JSON.parse(ersiJson);
Object esriFs = esriMap.get("features");
if(esriFs instanceof List){
esriFs = (List<Map<String, Object>>) esriFs;
for(int i=0; i< ((List) esriFs).size(); i++){
Map esriF = (Map) ((List) esriFs).get(i);
Map geoF = new HashMap();
geoF.put("type", "Feature");
geoF.put("properties", esriF.get("attributes"));
Map<String, Object> geometry = (Map<String, Object>) esriF.get("geometry");
if(null != geometry.get("x")){
geoF.put("geometry", geoPoint(geometry));
}else if(null != geometry.get("points")){
geoF.put("geometry", geoPoints(geometry));
}else if(null != geometry.get("paths")){
geoF.put("geometry", geoLine(geometry));
}else if(null != geometry.get("rings")){
geoF.put("geometry", geoPoly(geometry));
}
geoFs.add(geoF);
}
geoMap.put("features", geoFs);
}
}catch (Exception e){
e.printStackTrace();
}
return new JSONObject(geoMap).toString();
}
//geoJosn转EsriJson
public static String geo2ersi(String geoJson, String idAttribute){
Map esriMap = new HashMap();
try {
Map geoMap = (Map) JSON.parse(geoJson);
esriMap = getEsriGeo(geoMap, idAttribute);
Map spatialReference = new HashMap();
spatialReference.put("wkid", 4326);
esriMap.put("spatialReference",spatialReference);
}catch (Exception e){
e.printStackTrace();
}
return new JSONObject(esriMap).toString();
}
public static Map getEsriGeo(Map geoMap, String idAttribute){
Map esriMap = new HashMap();
idAttribute = StringUtils.isNotEmpty(idAttribute)? idAttribute:"OBJECTID";
String type = geoMap.get("type").toString();
switch (type){
case "Point":
List<BigDecimal> coords = (List<BigDecimal>) geoMap.get("coordinates");
esriMap.put("x", coords.get(0));
esriMap.put("y", coords.get(1));
break;
case "MultiPoint":
esriMap.put("points",geoMap.get("coordinates"));
break;
case "LineString":
List<Object> coordsList = new ArrayList<>();
coordsList.add(geoMap.get("coordinates"));
esriMap.put("paths",coordsList);
break;
case "MultiLineString":
esriMap.put("paths",geoMap.get("coordinates"));
break;
case "Polygon":
List<List<List<BigDecimal>>> coordinates = (List<List<List<BigDecimal>>>) geoMap.get("coordinates");
List<List<List<BigDecimal>>> rings = orientRings(coordinates);
esriMap.put("rings", rings);
break;
case "MultiPolygon":
List<List<List<List<BigDecimal>>>> mcoordinates = (List<List<List<List<BigDecimal>>>>) geoMap.get("coordinates");
List<List<List<BigDecimal>>> mrings = flattenMultiPolygonRings(mcoordinates);
esriMap.put("rings", mrings);
break;
case "Feature":
if (null != geoMap.get("geometry")) {
Map geometry = getEsriGeo((Map) geoMap.get("geometry"), idAttribute);
esriMap.put("geometry", geometry);
}
if(null != geoMap.get("properties")){
Map properties = (Map) geoMap.get("properties");
if (null != geoMap.get("id")) {
properties.put(idAttribute, geoMap.get("id"));
}
esriMap.put("attributes", properties);
}
break;
case "FeatureCollection":
List<Object> esriFs = new ArrayList<>();
List<Map> features = (List<Map>) geoMap.get("features");
for (int i = 0; i < features.size(); i++) {
esriFs.add(getEsriGeo(features.get(i), idAttribute));
}
esriMap.put("features", esriFs);
esriMap.put("geometryType","esriGeometryPolygon");
break;
case "GeometryCollection":
List<Object> esriFsc = new ArrayList<>();
List<Map> geometries = (List<Map>) geoMap.get("geometries");
for (int i = 0; i < geometries.size(); i++) {
esriFsc.add(getEsriGeo(geometries.get(i), idAttribute));
}
esriMap.put("geometries", esriFsc);
esriMap.put("geometryType","esriGeometryPolygon");
break;
}
return esriMap;
}
public static Map geoPoint(Map<String, Object> geometry){
Map geo = new HashMap();
geo.put("type", "point");
BigDecimal x = (BigDecimal) geometry.get("x");
BigDecimal y = (BigDecimal) geometry.get("y");
List<BigDecimal> coords = new ArrayList<>();
coords.add(x);
coords.add(y);
geo.put("coordinates", coords);
return geo;
}
public static Map geoPoints(Map<String, Object> geometry){
Map geo = new HashMap();
List<Object> points = (List<Object>) geometry.get("points");
if(points.size()==1){
geo.put("type", "Point");
geo.put("coordinates", points.get(0));
}else{
geo.put("type", "MultiPoint");
geo.put("coordinates", points);
}
return geo;
}
public static Map geoLine(Map<String, Object> geometry){
Map geo = new HashMap();
List<Object> paths = (List<Object>) geometry.get("paths");
if(paths.size()==1){
geo.put("type", "LineString");
geo.put("coordinates", paths.get(0));
}else{
geo.put("type", "MultiLineString");
geo.put("coordinates", paths);
}
return geo;
}
public static Map geoPoly(Map<String, Object> geometry){
Map geo = new HashMap();
List<List<List<BigDecimal>>> rings = (List<List<List<BigDecimal>>>) geometry.get("rings");
if(rings.size()==1){
geo.put("type", "Polygon");
geo.put("coordinates", rings);
}else{
List<List<List<List<BigDecimal>>>> coords = new ArrayList();
String type = "";
int len = coords.size() - 1;
for(int i=0; i< rings.size(); i++){
if(ringIsClockwise( rings.get(i))){
List<List<List<BigDecimal>>> item = new ArrayList<>();
item.add(rings.get(i));
coords.add(item);
len++;
}else{
coords.get(len).add(rings.get(i));
}
}
if(coords.size() == 1){
type="Polygon";
}else{
type="MultiPolygon";
}
geo.put("type", type);
geo.put("coordinates",coords.size()==1?coords.get(0): coords);
}
return geo;
}
public static boolean ringIsClockwise(List<List<BigDecimal>> rings){
int total = 0;
List<BigDecimal> pt1 = null;
List<BigDecimal> pt2 = null;
for(int i=0; i< rings.size()-1; i++){
pt1 = rings.get(i);
pt2 = rings.get(i+1);
total += (pt2.get(0).doubleValue() - pt1.get(0).doubleValue())* (pt2.get(1).doubleValue() + pt1.get(1).doubleValue());
}
return total>=0;
}
public static List<List<List<BigDecimal>>> orientRings ( List<List<List<BigDecimal>>> polygon) {
List<List<List<BigDecimal>>> ringsList = new ArrayList<>();
List<List<BigDecimal>> outerRing = closeRing(polygon.get(0));
if (outerRing.size() >= 4) {
if (!ringIsClockwise(outerRing)) {
Collections.reverse(outerRing);
}
ringsList.add(outerRing);
polygon.remove(0);
for (int i = 0; i < polygon.size(); i++) {
List<List<BigDecimal>> hole = closeRing(polygon.get(i));
if (hole.size() >= 4) {
if (ringIsClockwise(hole)) {
Collections.reverse(hole);
}
ringsList.add(hole);
}
}
}
return ringsList;
}
public static List<List<BigDecimal>> closeRing (List<List<BigDecimal>> coords) {
if (!pointsEqual(coords.get(0), coords.get(coords.size()-1))) {
coords.add(coords.get(0));
}
return coords;
}
public static boolean pointsEqual (List<BigDecimal> a, List<BigDecimal> b) {
for (int i = 0; i < a.size(); i++) {
if (a.get(i).compareTo(b.get(i)) != 0) {
return false;
}
}
return true;
}
public static List<List<List<BigDecimal>>> flattenMultiPolygonRings (List<List<List<List<BigDecimal>>>> rings) {
List<List<List<BigDecimal>>> polygonList = new ArrayList<>();
for (int i = 0; i < rings.size(); i++) {
List<List<List<BigDecimal>>> polygons = orientRings(rings.get(i));
for (int x = polygons.size() - 1; x >= 0; x--) {
List<List<BigDecimal>> polygon = polygons.get(x);
polygonList.add(polygon);
}
}
return polygonList;
}
}
测试代码
package com.cic.analysis.business.utils;
import org.junit.Test;
import static org.junit.Assert.*;
public class EsriGeoJsonUtilTest {
@Test
public void esri2geo() {
String geoJson="{\n" +
" \"type\": \"FeatureCollection\",\n" +
" \"features\": [\n" +
" {\n" +
" \"type\": \"Feature\",\n" +
" \"properties\": {\n" +
" \"color\":\"#dddddd\",\n" +
" \"id\":\"2222\"\n" +
" },\n" +
" \"geometry\": {\n" +
" \"type\": \"Polygon\",\n" +
" \"coordinates\": [\n" +
" [\n" +
" [\n" +
" -9.84375,\n" +
" 55.57834467218206\n" +
" ],\n" +
" [\n" +
" -48.515625,\n" +
" 7.013667927566642\n" +
" ],\n" +
" [\n" +
" 67.1484375,\n" +
" -8.754794702435618\n" +
" ],\n" +
" [\n" +
" 31.9921875,\n" +
" 48.69096039092549\n" +
" ],\n" +
" [\n" +
" -9.84375,\n" +
" 55.57834467218206\n" +
" ]\n" +
" ]\n" +
" ]\n" +
" }\n" +
" }\n" +
" ]\n" +
"}";
System.out.println(EsriGeoJsonUtil.geo2ersi(geoJson,""));
}
}
输出结果
{"features":[{"geometry":{"rings":[[[-9.84375,55.57834467218206],[31.9921875,48.69096039092549],[67.1484375,-8.754794702435618],[-48.515625,7.013667927566642],[-9.84375,55.57834467218206]]]},"attributes":{"color":"#dddddd","id":"2222"}}],"spatialReference":{"wkid":4326},"geometryType":"esriGeometryPolygon"}
本文地址:https://blog.csdn.net/GISuuser/article/details/109266545
上一篇: 用一个栈对另一个栈排序Java实现