如何在大量经纬度数据中搜索附近的点
2017-12-05 14:19
204 查看
空间数据库
例如在postgresql中新建一个可以保存空间数据的表:CREATE TABLE "public"."roadpoint" (
"lat" float8 DEFAULT 0,
"lng" float8 DEFAULT 0,
"gisp" point,
"id" int4 DEFAULT nextval('roadpoint_id_seq'::regclass) NOT NULL,
"geohashcode" varchar(20) DEFAULT NULL::character varying,
CONSTRAINT "roadpoint_idpkey" PRIMARY KEY ("id")
)
WITH (OIDS=FALSE)
;
ALTER TABLE "public"."roadpoint" OWNER TO "bmkpdev";
COMMENT ON COLUMN "public"."roadpoint"."lat" IS '纬度';
COMMENT ON COLUMN "public"."roadpoint"."lng" IS '经度';
CREATE INDEX "geohash_index" ON "public"."roadpoint" USING hash ("geohashcode");
CREATE INDEX "georoadpointgis_idx" ON "public"."roadpoint" USING gist ("gisp") WITH (fillfactor = 85);
CREATE INDEX "lat_index" ON "public"."roadpoint" USING btree ("lat");
CREATE INDEX "lng_index" ON "public"."roadpoint" USING btree ("lng");
建立之后打开表如下:
![](http://i2.51cto.com/images/blog/201712/05/41db486d0bca5958f2f44dbbc39deb5e.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
其中 lng 和 lat为经纬度数据:
gisp为空间数据列:
生成gisp数据列的sql语句如下:
update roadpoint set gisp = point(lng,lat) where gisp is null
生成geohashcode
python代码如下:from math import log10
base32 = '0123456789bcdefghjkmnpqrstuvwxyz'
decodemap = { }
for i in range(len(base32)):
decodemap[__base32[i]] = i
del i
def decode_exactly(geohash):
lat_interval, lon_interval = (-90.0, 90.0), (-180.0, 180.0)
lat_err, lon_err = 90.0, 180.0
is_even = True
for c in geohash:
cd = __decodemap[c]
for mask in [16, 8, 4, 2, 1]:
if is_even: # adds longitude info
lon_err /= 2
if cd & mask:
lon_interval = ((lon_interval[0]+lon_interval[1])/2, lon_interval[1])
else:
lon_interval = (lon_interval[0], (lon_interval[0]+lon_interval[1])/2)
else: # adds latitude info
lat_err /= 2
if cd & mask:
lat_interval = ((lat_interval[0]+lat_interval[1])/2, lat_interval[1])
else:
lat_interval = (lat_interval[0], (lat_interval[0]+lat_interval[1])/2)
is_even = not is_even
lat = (lat_interval[0] + lat_interval[1]) / 2
lon = (lon_interval[0] + lon_interval[1]) / 2
return lat, lon, lat_err, lon_err
def decode(geohash):
"""
Decode geohash, returning two strings with latitude and longitude
containing only relevant digits and with trailing zeroes removed.
"""
lat, lon, lat_err, lon_err = decode_exactly(geohash)
Format to the number of decimals that are known
lats = "%.*f" % (max(1, int(round(-log10(lat_err)))) - 1, lat) lons = "%.*f" % (max(1, int(round(-log10(lon_err)))) - 1, lon) if '.' in lats: lats = lats.rstrip('0') if '.' in lons: lons = lons.rstrip('0') return lats, lons
def encode(latitude, longitude, precision=12):
"""
Encode a position given in float arguments latitude, longitude to
a geohash which will have the character count precision.
"""
lat_interval, lon_interval = (-90.0, 90.0), (-180.0, 180.0)
geohash = []
bits = [ 16, 8, 4, 2, 1 ]
bit = 0
ch = 0
even = True
while len(geohash) < precision:
if even:
mid = (lon_interval[0] + lon_interval[1]) / 2
if longitude > mid:
ch |= bits[bit]
lon_interval = (mid, lon_interval[1])
else:
lon_interval = (lon_interval[0], mid)
else:
mid = (lat_interval[0] + lat_interval[1]) / 2
if latitude > mid:
ch |= bits[bit]
lat_interval = (mid, lat_interval[1])
else:
lat_interval = (lat_interval[0], mid)
even = not even
if bit < 4:
bit += 1
else:
geohash += __base32[ch]
bit = 0
ch = 0
return ''.join(geohash)
调用示例
geohashtext = geohash.encode(float(lat),float(lng),7)其中lat为纬度 lng为经度 7为定位精度
再 将数据导入到上面的postgresql 表中
在geohashcode列添加上索引,执行如下语句:
select lng,lat from roadpoint where geohashcode = '' and geo_distance(gisp,point(114.404498,30.511795)) = (select MIN(geo_distance(gisp,point(114.404498,30.511795))) from roadpoint)
就可以很快的找到最近的定位数据。
相关文章推荐
- 3分钟让你学会如何用超级表格发布搜索,查询数据
- BULK INSERT如何将大量数据高效地导入SQL Server
- 如何解决PHP里大量数据循环时内存耗尽的问题
- Oracle中如何用一条SQL快速生成1大量测试数据
- 如何向mysql中插入大量数据
- 如何自己动手获取大量知乎网民数据?
- 如何在JavaScript中处理大量数据
- UITableView,UICollectionView和CoreData完美结合进行增删改操作,如何导入大量数据,如何利用NSEntityMigrationPol
- 如何处理大量数据并发操作
- solr 学习之路 如何将数据库中大量的数据导入solr <三>
- Android之如何实现通讯录的搜索并且让匹配到的数据变颜色
- access 如何解决组合框无法满足大量数据的选择问题?
- 能源物联网中如何处理上报的大量数据问题的思路分析(题目有点长,但是我不介意它更长)--后续会继续补充
- 如何快速插入大量的数据(Sqlserver)
- 跟据经纬度实现附近搜索Java实现
- qt 中如何向QTableWidget里大量添加数据?
- Q:一个数据表中有大量数据,如何提高查询速度?
- 美国国家安全局解密特工培训手册:如何利用谷歌等大众搜索工具搜集保密数据
- ElasticSearch48:初识搜索引擎_上机动手实战基于scroll技术滚动搜索大量数据
- 如何处理大量数据并发操作