import math acceptableLocationDiff = 30; acceptableTimeDiff = 30; def distanceBetween(location1, location2): # Pythagoras for the purpose of this example. # Real code uses real coordinates, so great circle distance is calculated. a = abs(location1.latitude - location2.latitude); b = abs(location1.longitude - location2.longitude); return math.sqrt(pow(a,2)+pow(b,2)); # This function removes all entries within acceptableTimeDiff if person hasn't moved more than acceptableDis. # Why? Because if I'm at the same bar for 4 hours, and my location is logged every 2 minutes... that's a lot of points. I'd like some of them removed. def filterNearDuplicates(locations): """Remove any locations that are very close in time and distance (isolates small movements)""" # always add the first item in the locations list filteredList = [locations[0]]; for i in range(1, len(locations)): locationDistance = distanceBetween(locations[i],locations[i-1]); timeDistance = abs(locations[i].timestamp - locations[i-1].timestamp); # Only keep records that have changed enough to be significant if locationDistance > acceptableLocationDiff or timeDistance > acceptableTimeDiff: filteredList.append(locations[i]); return filteredList; def findIntersections(locations): """Returns an array of Intersection objects, each representing an intersection of two or more people.""" if len(locations) == 0: print("No locations to compare"); return []; # First, sort the list by timestamp and X,Y location sortedLocations = sorted(locations, key=lambda k: (k.timestamp, k.latitude, k.longitude)); # intersections will be an array of Intersection objects intersections = [] # personList is a unique list of people found at a location. personList = set(); # prime the pump lastLocation = sortedLocations[0]; personList.add(lastLocation.owner); for i, location in enumerate(sortedLocations): if ( abs(location.timestamp - lastLocation.timestamp) <= acceptableTimeDiff and distanceBetween(lastLocation, location) <= acceptableLocationDiff): if lastLocation.owner is not location.owner: # We have two different owners, within the acceptable range, add them personList.add(location.owner); else: # We moved either in time or location # But first, we need to save the last Intersection, if any if len(personList) > 1: intersections.append(Intersection(lastLocation.timestamp, lastLocation.latitude, lastLocation.longitude, personList)); lastLocation = location; personList = set(); # start over personList.add(lastLocation.owner); return intersections; class Location(object): """A location (lat,long) along with when the location was recorded and the person who owns the location.""" def __init__(self, timestamp, latitude, longitude): self.timestamp = timestamp; self.latitude = latitude; self.longitude = longitude; # The owners are added after the object is created self.owner = None; def __repr__(self): return '{}: {}, {} - {} owned by: {}'.format(self.__class__.__name__, self.latitude, self.longitude, self.timestamp, (self.owner.name if self.owner is None else "none")); class Person(object): """A person with a name and a list of locations. The constructor automatically takes ownership of all Locations.""" def __init__(self, name, locations): self.name = name; sortedLocations = sorted(locations, key=lambda k: (k.timestamp, k.latitude, k.longitude)); self.locations = filterNearDuplicates(sortedLocations); for location in self.locations: location.owner = self; def __repr__(self): return '{}: {} {}'.format(self.__class__.__name__, self.name, len(self.locations)); class Intersection(object): """An intersection of one or more people at a specific timestamp and location (within the specified range for each).""" def __init__(self, latitude, longitude, timestamp, people): self.latitude = latitude; self.longitude = longitude; self.timestamp = timestamp; self.people = people; def __repr__(self): output = '{}: Latitude: {}, Longitude: {}, TimeStamp: {}\n'.format(self.__class__.__name__, self.latitude, self.longitude, self.timestamp); for i, person in enumerate(self.people): output += (person.name if i == 0 else ', ' + person.name); return output; # Some data to test with. person1 = Person("Joe", [ Location(99998, 885, 9970), Location(99999, 888, 9999), # This point is too close to person1[0] and will be removed ny filterNearDuplicates() Location(99987, 999, 1234), # This is the point where all persons meet on the same time. Location(12345, 950, 1238)]); person2 = Person("Sam", [ Location(99999, 888, 6666), Location(66666, 555, 1234), # This one is good considering timestamp, but is very far away considering distance. Location(99979, 998, 1236)]); # This point is ok :) person3 = Person("Art", [ Location(99999, 888, 7777), Location(99980, 995, 1234), Location(12345, 950, 1238)]); people = [person1,person2,person3] # First put all of the locations into one list to compare them allLocations = []; for person in people: allLocations.extend(person.locations); # Now let's walk through and create a list of intersections between groups of people intersections = findIntersections(allLocations); # Now format it in a way that is readable for humans. print('-----------------'); print('These people are close both in time and place:'); print('--'); for intersection in intersections: print(repr(intersection)); print('--');
Run
Reset
Share
Import
Link
Embed
Language▼
English
中文
Python Fiddle
Python Cloud IDE
Follow @python_fiddle
Browser Version Not Supported
Due to Python Fiddle's reliance on advanced JavaScript techniques, older browsers might have problems running it correctly. Please download the latest version of your favourite browser.
Chrome 10+
Firefox 4+
Safari 5+
IE 10+
Let me try anyway!
url:
Go
Python Snippet
Stackoverflow Question