[points] Fixes to point index

This commit is contained in:
Al
2016-08-06 18:23:30 -04:00
parent 964728a02d
commit 954bb08a8d

View File

@@ -1,3 +1,4 @@
import array
import geohash import geohash
import os import os
import math import math
@@ -43,6 +44,8 @@ class PointIndex(object):
if not index_path: if not index_path:
index_path = os.path.join(save_dir or '.', self.INDEX_FILENAME) index_path = os.path.join(save_dir or '.', self.INDEX_FILENAME)
self.index_path = index_path
if not index: if not index:
self.index = defaultdict(list) self.index = defaultdict(list)
else: else:
@@ -50,9 +53,10 @@ class PointIndex(object):
if not points_path: if not points_path:
points_path = os.path.join(save_dir or '.', self.POINTS_FILENAME) points_path = os.path.join(save_dir or '.', self.POINTS_FILENAME)
self.points_path = points_path
if not points: if not points:
self.points = [] self.points = array.array('d')
else: else:
self.points = points self.points = points
@@ -73,9 +77,11 @@ class PointIndex(object):
for key in [code] + geohash.neighbors(code): for key in [code] + geohash.neighbors(code):
self.index[key].append(self.i) self.index[key].append(self.i)
self.points.extend([lat, lon]) self.points.extend([lat, lon])
def add_point(self, lat, lon, properties, cache=False, include_only_properties=None): def add_point(self, lat, lon, properties, cache=False, include_only_properties=None):
if include_only_properties is None and self.include_only_properties:
include_only_properties = self.include_only_properties
if include_only_properties is not None: if include_only_properties is not None:
properties = {k: v for k, v in properties.iteritems() if k in include_only_properties} properties = {k: v for k, v in properties.iteritems() if k in include_only_properties}
@@ -85,12 +91,12 @@ class PointIndex(object):
def load_properties(self, filename): def load_properties(self, filename):
properties = json.load(open(filename)) properties = json.load(open(filename))
self.i = int(properties.get('num_polygons', self.i)) self.i = int(properties.get('num_points', self.i))
self.precision = int(properties.get('precision', self.precision)) self.precision = int(properties.get('precision', self.precision))
def save_properties(self, out_filename): def save_properties(self, out_filename):
out = open(out_filename, 'w') out = open(out_filename, 'w')
json.dump({'num_polygons': str(self.i), json.dump({'num_points': str(self.i),
'precision': self.precision}, out) 'precision': self.precision}, out)
def save_index(self): def save_index(self):
@@ -113,10 +119,15 @@ class PointIndex(object):
return 'props:{}'.format(i) return 'props:{}'.format(i)
def get_properties(self, i): def get_properties(self, i):
return self.points_db.Get(self.properties_key(i)) return json.loads(self.points_db.Get(self.properties_key(i)))
def compact_points_db(self):
self.points_db.CompactRange('\x00', '\xff')
def save(self): def save(self):
self.save_index() self.save_index()
self.save_points()
self.compact_points_db()
self.save_properties(os.path.join(self.save_dir, self.PROPS_FILENAME)) self.save_properties(os.path.join(self.save_dir, self.PROPS_FILENAME))
@classmethod @classmethod
@@ -154,11 +165,18 @@ class PointIndex(object):
return [] return []
return sorted(distances, key=operator.itemgetter(-1)) return sorted(distances, key=operator.itemgetter(-1))
def points_with_properties(self, results):
return [(self.get_properties(i), lat, lon, distance)
for i, lat, lon, distance in results]
def nearest_points(self, latitude, longitude):
return self.points_with_properties(self.all_nearby_points(latitude, longitude))
def nearest_n_points(self, latitude, longitude, n=2): def nearest_n_points(self, latitude, longitude, n=2):
return self.all_nearby_points(latitude, longitude)[:n] return self.points_with_properties(self.all_nearby_points(latitude, longitude)[:n])
def nearest_point(self, latitude, longitude): def nearest_point(self, latitude, longitude):
distances = self.all_nearby_points(latitude, longitude) distances = self.all_nearby_points(latitude, longitude)
if not distances: if not distances:
return None return None
return distances[0] return self.points_with_properties(distances[:1])[0]