首页 > 解决方案 > 用圆角坐标在 Python 中序列化 GeoJSON

问题描述

我想在 Python 中以有限的坐标精度序列化 GeoJSON FeatureCollections。

例如,这是一个 FeatureCollection(在 Python 中表示为dicts 和s):list

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "Liberty Island",
        "area_sqm": 24950.40123456,
        "established": 1875,
        "height_ft": 305
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [ -74.04715418815613, 40.690994683044906 ],
            [ -74.04499769210815, 40.68873311507798 ],
            [ -74.04354929924011, 40.689676800252016 ],
            [ -74.04715418815613, 40.690994683044906 ]
          ]
        ]
      }
    }
  ]
}

我可以使用以下方法对其进行序列化json.dumps

print(json.dumps(fc))

这将打印出 JSON:

{"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {"name": "Liberty Island", "area_sqm": 24950.40123456, "established": 1875, "height_ft": 305}, "geometry": {"type": "Polygon", "coordinates": [[[-74.04715418815613, 40.690994683044906], [-74.04499769210815, 40.68873311507798], [-74.04354929924011, 40.689676800252016], [-74.04715418815613, 40.690994683044906]]]}}]}

那些坐标太精确了。根据维基百科,7 位是 ~cm 精度,这应该足够好。我得到的是〜纳米精度。

我想用坐标的七位精度序列化 GeoJSON FeatureCollection。请注意,我想对 中的所有内容使用 Python 的默认序列化properties:因为其中的值可能是任何内容,所以我无法就多少精度就足够了做出任何普遍的声明。

我想要的输出是这样的:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "Liberty Island",
        "area_sqm": 24950.40123456,
        "established": 1875,
        "height_ft": 305
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [ -74.0471541, 40.6909946 ],
            [ -74.0449976, 40.6887331 ],
            [ -74.0435492, 40.6896768 ],
            [ -74.0471541, 40.6909946 ]
          ]
        ]
      }
    }
  ]
}

标签: pythonjsonpython-3.xgeojson

解决方案


我不确定您要进行什么确切的序列化,但是在FeatureCollection简化方面,这应该可以帮助您入门:

import json
from copy import copy


def simplify_geometries(feat_collection):
    new_coll = copy(feat_collection)
    old_features = new_coll['features']
    new_features = []

    for feature in old_features:
        geometry = feature['geometry']
        coords = shorten_arr(geometry['coordinates'])
        geometry['coordinates'] = coords

        new_features.append(feature)

    new_coll['features'] = new_features
    return json.dumps(new_coll)


print(simplify_geometries(
    json.loads('{"type": "FeatureCollection",...')
))

哪里shorten_arr是一个简单的递归:

def shorten_arr(arr, dec_places=7):
    if not isinstance(arr, list):
        return round(arr, dec_places)

    to_ret = []
    for n in arr:
        if isinstance(n, list):
            n = shorten_arr(n, dec_places)
        to_ret.append(shorten_arr(n, dec_places))
    return to_ret

推荐阅读