Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
计算JSON多段线的中点(Python 2.7.0,无库)_Python_Json_Python 2.7_Jython_Polyline - Fatal编程技术网

计算JSON多段线的中点(Python 2.7.0,无库)

计算JSON多段线的中点(Python 2.7.0,无库),python,json,python-2.7,jython,polyline,Python,Json,Python 2.7,Jython,Polyline,情景: 我有一个向web服务发出请求的服务器 web服务返回一个JSON对象 JSON对象包含数组中的多段线顶点 JSON对象的一个小片段是: { "objectIdFieldName": "OBJECTID", "globalIdFieldName": "", "geometryType": "esriGeometryPolyline", "spatialReference": { "wkid": 476, "latestWkid": 476 },

情景:

我有一个向web服务发出请求的服务器

  • web服务返回一个JSON对象
  • JSON对象包含数组中的多段线顶点

JSON对象的一个小片段是:

{
  "objectIdFieldName": "OBJECTID",
  "globalIdFieldName": "",
  "geometryType": "esriGeometryPolyline",
  "spatialReference": {
    "wkid": 476,
    "latestWkid": 476
  },
  "fields": [
    {
      "name": "OBJECTID",
      "alias": "OBJECTID",
      "type": "esriFieldTypeOID"
    }
  ],
  "features": [
    {
      "attributes": {
        "OBJECTID": 3311
      },
      "geometry": {
        "paths": [
          [
            [
              675844.1562959617,
              4861766.9811610579
            ],
            [
              675878.30397594348,
              4861792.5977392439
            ],
            [
              675891.38832408097,
              4861800.4024024364
            ],
            [
              675902.17710777745,
              4861804.9933949765
            ],
            [
              675912.27726199664,
              4861808.2070551421
            ],
            [
              675923.52513550781,
              4861810.2730065044
            ],
            [
              675934.77300901897,
              4861811.1911861338
            ],
            [
              675943.03676202707,
              4861811.1911861338
            ],
            [
              675951.07095439639,
              4861810.502546167
            ],
            [
              675961.17111910321,
              4861808.6661449578
            ],
            [
              675970.35304125212,
              4861806.1411667075
            ],
            [
              675981.51595173683,
              4861800.7007851209
            ],
            [
              675998.03647276573,
              4861792.2469376959
            ]
          ]
        ]
      }
    },

**The JSON object has been cut off.**
可以在此处找到完整的JSON对象:


问题:

使用JSON顶点,我想计算多段线的中点(见下面的绿点):

  • 一些行(ObjectID 3716和3385)是多部分的。在这种情况下,只能为直线的最长部分(而不是其他部分)生成中点
  • 为了解决这个问题,JSON文本可以保存为文本文件,并加载到python脚本中。在本例中,可以使用Python的JSON库——尽管下面提到了catch


输出如下所示(格式可能不同):


捕获物:

这需要在Python2.7.0中完成——因为我的系统使用2.7.0

  • 需要注意的是,我无法将任何Python库导入到我正在使用的系统中的Jython实现中。因此,不幸的是,脚本不应该导入任何python库(用于测试的JSON库除外)


是否可以使用Python 2.7.0计算JSON多段线的中点(无需导入库)?

是的,您可以仅使用内置Python函数/无需导入外部库轻松计算多段线的中点

让我们打破你的要求:

  • 在对象的
    features
    字段中迭代该特征
  • 能够计算多段线的长度
  • 如果有多条要素,请为每个要素拾取最长的多段线
  • 找到此多段线的中点(如注释中所建议的,可以通过求和多段线线段的长度沿多段线前进,直到确定位于中点之间的两个点,并使用
因此,我们需要一些辅助函数来计算两点之间的距离,然后是多段线的距离,依此类推:

# Euclidean distance between two points
def get_distance(p1, p2):
    return sum([(x-y)**2 for (x,y) in zip(p1, p2)]) ** (0.5)

# Length of a polyline by summing the length of its segments
def get_distance_line(line):
    total = 0
    for start_index in range(len(line) - 1):
        stop_index = start_index + 1
        total += get_distance(line[start_index], line[stop_index])
    return total

# Get the polyline with the longest distance
# within a list of polyline
def get_longest(li):
    return max(li, key=get_distance_line)

# Compute the target point at `_target_dist`
# of `p1` along the p1-p2 segment
def _get_pt_at_dist(p1, p2, _target_dist):
    # Define the vector from p1 to p2
    vx = p2[0] - p1[0]
    vy = p2[1] - p1[1]
    # Compute the length of the vector
    lv = (vx ** 2 + vy ** 2) ** 0.5
    # Compute the unit vector (the vector with length 1)
    nv = [vx / lv, vy / lv]
    # Compute the target point
    return [
        p1[0] + nv[0] * _target_dist,
        p1[1] + nv[1] * _target_dist,
    ]

# Get a point at a specific distance on a Polyline
# - 1st step to find the two points enclosing the `target_dist
# - 2nd step to calculate the midpoint along the 2 previously selected points
def get_point_at_distance(line, target_dist):
    sum_dist = 0
    for start_index in range(len(line) - 1):
        stop_index = start_index + 1
        n_dist = get_distance(line[start_index], line[stop_index])
        if sum_dist + n_dist > target_dist:
            # We have found the two enclosing points
            p1, p2 = line[start_index], line[stop_index]
            _target_dist = target_dist - sum_dist
            return _get_pt_at_dist(p1, p2, _target_dist)
        else:
            sum_dist += n_dist

    raise ValueError("target distance is greater than the length of the line")
让我们迭代您的数据(我将您的对象命名为
dataset
),并使用这些函数计算中点:

result = {}

for ft in dataset['features']:
    paths = ft['geometry']['paths']

    # Pick the longest path of default to
    # the only existing one:
    if len(paths) == 1:
        p = paths[0]
    else:
        p = get_longest(paths)

    # Compute the distance
    # and the half of the distance
    # for this polyline
    distance_line = get_distance_line(p)
    middle_dist = distance_line / 2

    # Compute the midpoint and save it
    # into a `dict` using the `OBJECTID`
    # attribute as a key
    midpoint = get_point_at_distance(p, middle_dist)
    result[ft['attributes']['OBJECTID']] = midpoint
结果对象:

{3311: [675916.9814634613, 4861809.071098591],
 3385: [676208.6690235228, 4861536.554984818],
 2165: [676163.9343346333, 4861476.37263185],
 2682: [676060.391694662, 4861904.761846619],
 2683: [675743.1665799635, 4861724.081134027],
 2691: [676137.4796253176, 4861557.709372229],
 2375: [676118.1225925689, 4861730.258496471],
 2320: [676142.0016617056, 4861959.660392438],
 3716: [675979.6112380569, 4861724.356721315],
 3546: [676262.2623328466, 4861665.145686949],
 3547: [676167.5737531717, 4861612.6987658115],
 3548: [676021.3677275265, 4861573.140917723],
 3549: [675914.4334252588, 4861669.870444033],
 3550: [675866.6003329497, 4861735.571798388],
 3551: [675800.1231731868, 4861827.48182595],
 3552: [675681.9432478376, 4861918.988687315]}

请注意:首先,我选择了节点数最多的路径(而不是距离最长的路径-使用类似
def get_longest(li):return max(li,key=len)
),我得到的(视觉)结果与提供的结果非常接近,所以,也许这就是为什么你想说
行中最长的部分
,但我不确定

是的,您可以仅使用内置Python函数/轻松计算多段线的中点,而无需导入外部库

让我们打破你的要求:

  • 在对象的
    features
    字段中迭代该特征
  • 能够计算多段线的长度
  • 如果有多条要素,请为每个要素拾取最长的多段线
  • 找到此多段线的中点(如注释中所建议的,可以通过求和多段线线段的长度沿多段线前进,直到确定位于中点之间的两个点,并使用
因此,我们需要一些辅助函数来计算两点之间的距离,然后是多段线的距离,依此类推:

# Euclidean distance between two points
def get_distance(p1, p2):
    return sum([(x-y)**2 for (x,y) in zip(p1, p2)]) ** (0.5)

# Length of a polyline by summing the length of its segments
def get_distance_line(line):
    total = 0
    for start_index in range(len(line) - 1):
        stop_index = start_index + 1
        total += get_distance(line[start_index], line[stop_index])
    return total

# Get the polyline with the longest distance
# within a list of polyline
def get_longest(li):
    return max(li, key=get_distance_line)

# Compute the target point at `_target_dist`
# of `p1` along the p1-p2 segment
def _get_pt_at_dist(p1, p2, _target_dist):
    # Define the vector from p1 to p2
    vx = p2[0] - p1[0]
    vy = p2[1] - p1[1]
    # Compute the length of the vector
    lv = (vx ** 2 + vy ** 2) ** 0.5
    # Compute the unit vector (the vector with length 1)
    nv = [vx / lv, vy / lv]
    # Compute the target point
    return [
        p1[0] + nv[0] * _target_dist,
        p1[1] + nv[1] * _target_dist,
    ]

# Get a point at a specific distance on a Polyline
# - 1st step to find the two points enclosing the `target_dist
# - 2nd step to calculate the midpoint along the 2 previously selected points
def get_point_at_distance(line, target_dist):
    sum_dist = 0
    for start_index in range(len(line) - 1):
        stop_index = start_index + 1
        n_dist = get_distance(line[start_index], line[stop_index])
        if sum_dist + n_dist > target_dist:
            # We have found the two enclosing points
            p1, p2 = line[start_index], line[stop_index]
            _target_dist = target_dist - sum_dist
            return _get_pt_at_dist(p1, p2, _target_dist)
        else:
            sum_dist += n_dist

    raise ValueError("target distance is greater than the length of the line")
让我们迭代您的数据(我将您的对象命名为
dataset
),并使用这些函数计算中点:

result = {}

for ft in dataset['features']:
    paths = ft['geometry']['paths']

    # Pick the longest path of default to
    # the only existing one:
    if len(paths) == 1:
        p = paths[0]
    else:
        p = get_longest(paths)

    # Compute the distance
    # and the half of the distance
    # for this polyline
    distance_line = get_distance_line(p)
    middle_dist = distance_line / 2

    # Compute the midpoint and save it
    # into a `dict` using the `OBJECTID`
    # attribute as a key
    midpoint = get_point_at_distance(p, middle_dist)
    result[ft['attributes']['OBJECTID']] = midpoint
结果对象:

{3311: [675916.9814634613, 4861809.071098591],
 3385: [676208.6690235228, 4861536.554984818],
 2165: [676163.9343346333, 4861476.37263185],
 2682: [676060.391694662, 4861904.761846619],
 2683: [675743.1665799635, 4861724.081134027],
 2691: [676137.4796253176, 4861557.709372229],
 2375: [676118.1225925689, 4861730.258496471],
 2320: [676142.0016617056, 4861959.660392438],
 3716: [675979.6112380569, 4861724.356721315],
 3546: [676262.2623328466, 4861665.145686949],
 3547: [676167.5737531717, 4861612.6987658115],
 3548: [676021.3677275265, 4861573.140917723],
 3549: [675914.4334252588, 4861669.870444033],
 3550: [675866.6003329497, 4861735.571798388],
 3551: [675800.1231731868, 4861827.48182595],
 3552: [675681.9432478376, 4861918.988687315]}

请注意:首先,我选择了节点数最多的路径(而不是距离最长的路径-使用类似
def get_longest(li):return max(li,key=len)
),我得到的(视觉)结果与提供的结果非常接近,所以,也许这就是为什么你想说
行中最长的部分
,但我不确定

总长度是每段(或弧,如果可以得到其半径)长度的总和。中点可以通过增加长度来计算,直到达到总长度的一半。你能给我上面的输入多段线的输出样本吗?@Bluespider我提供了一个输出样本(并对问题进行了总体更新)。谢谢。总长度是每段(或弧,如果你能得到它的半径)长度的总和。中点可以通过增加长度来计算,直到达到总长度的一半。你能给我上面的输入多段线的输出样本吗?@Bluespider我提供了一个输出样本(并对问题进行了总体更新)。谢谢,谢谢!关于你在答案末尾的注释:是的,我在寻找长度最长的部分,而不是顶点最多的部分。我最初在问题的建议结果集中包含了错误的部分(最短的部分,但更多的顶点)。对不起;我已经改正了,没问题!希望有帮助!非常感谢。关于你在答案末尾的注释:是的,我在寻找长度最长的部分,而不是顶点最多的部分。我最初在问题的建议结果集中包含了错误的部分(最短的部分,但更多的顶点)。对不起;我已经改正了,没问题!希望有帮助!