欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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