制作计算距离的功能

时间:2017-10-20 10:13:27

标签: python

您好我使用Python来计算用户走路的距离。我决定他们是否以速度行走。如果速度低于5米/秒,他们会考虑走路。但是我在制作这个功能时遇到了麻烦。你能帮我解决一下这个功能吗?到目前为止,我的输入是手动放入另一个名为“make_timestamped_loc”的函数,并通过名为“total_dist”的函数计算距离。这是我的代码......

import ctp17hw1
dic_loc = []
def make_timestamped_loc(La, Lng, TS):
    new_loc = {}
    new_loc['latitude'] = La
    new_loc['longitude'] = Lng
    new_loc['timestamp'] = int(TS)
    dic_loc.append(new_loc)

make_timestamped_loc(37.481236, 126.952733, 1483196400)
make_timestamped_loc(37.310045, 127.101255, 1408323255)
make_timestamped_loc(37.383065, 126.672596, 1508322531)
make_timestamped_loc(37.383065, 116.672596, 1444999230)

# make_timestamped_loc(37.383065, 112.672596, 1444999230) #error sample
print(dic_loc)
def sort_locs(sortingDict):
    newlist = sorted(sortingDict, key=lambda k: k['timestamp'])
    for i in range(len(dic_loc) - 1, -1, -1):
       dic_loc.remove(dic_loc[i])
    for i in range(len(newlist)):
        for j in range(len(newlist)):
            if (newlist[i]['timestamp'] == newlist[j]['timestamp']
                and (newlist[i]['latitude'] != newlist[j]['latitude'] or newlist[i]['longitude'] != newlist[j]['longitude'])
                and i != j):
                raise ValueError('There is duplicated location on same time!')
        sortingDict.append(newlist[i])
sort_locs(dic_loc)


def total_dist(sortedDict):
        totalDist = 0;
        for i in range(len(sortedDict) - 1):
            sm = ctp17hw1.dist(sortedDict[i]["latitude"], sortedDict[i]["longitude"], sortedDict[i+1]["latitude"], sortedDict[i+1]["longitude"])
            totalDist = totalDist + sm
        return totalDist
total_dist(dic_loc)
print(total_dist(dic_loc))

ctp17hw1是另一个用于计算距离的文件。 因为Unix的时间,我很困惑。 非常感谢你

1 个答案:

答案 0 :(得分:0)

使用Getting distance between two points based on latitude/longitudeIterate a list as pair (current, next) in Python中提供的解决方案,我能够构建这个问题的Pythonic方法:

import itertools

from collections import namedtuple
from math import sin, cos, sqrt, atan2, radians

Location = namedtuple('Location', ['long', 'lat', 'time'])
all_locations = [
    Location(lat=37.481236, long=126.952733, time=1488323400),
    Location(lat=37.310045, long=127.101255, time=1488323255),
    Location(lat=37.383065, long=126.672596, time=1488323531),
    Location(lat=37.383065, long=116.672596, time=1488323230),
]


def distance(loc_a, loc_b):
    """Extracted from: https://stackoverflow.com/questions/19412462"""
    R = 6373.0

    lat_a, lat_b = radians(loc_a.lat), radians(loc_b.lat)
    long_a, long_b = radians(loc_a.long), radians(loc_b.long)
    dlat = lat_b - lat_a
    dlong = long_b - long_a

    a = sin(dlat / 2)**2 + cos(lat_a) * cos(lat_b) * sin(dlong / 2) ** 2
    c = 2 * atan2(sqrt(a), sqrt(1 - a))

    return R * c


def pairwise(iterable):
    """Extracted from: https://stackoverflow.com/questions/5434891"""
    a, b = itertools.tee(iterable)
    next(b, None)
    return zip(a, b)


sorted_locations = sorted(all_locations, key=lambda l: l.time)
total_distance = sum(distance(a, b) for a, b in pairwise(sorted_locations))
delta_time = sorted_locations[-1].time - sorted_locations[0].time
print(total_distance, delta_time, total_distance / delta_time)

使用namedtuple不是强制性的,但我觉得它会简化代码。名为tuple的FTR是仅包含声明字段的简单结构(此处为long,lat和time)。

pairwise函数允许迭代2对列表(即当前和下一个元素)。通过按时间在排序的位置列表上使用它,我可以轻松地评估距离。基本上是:

sorted_locations = [l1, l2, l3]
distances = [distance(a, b) for a, b in pairwise(sorted_locations)]
# equivalent to [distance(l1, l2), distance(l2, l3)]
total_distance = sum(distances)

不使用中间列表将减少内存消耗(在示例中与大型列表相关)无关紧要。我还可以声明一个距离生成器(使用列表推导的(distance(a, b) for ...) insteand)。

注意我没有预先计算long / lat的radians,并且对于列表的非extrem元素计算它们2次。这可能会有一点性能提升,但我主要想在这里保持算法简单。