基于LBS的兴趣点查询

来源:互联网 发布:淘宝刷单违规处罚 编辑:程序博客网 时间:2024/05/28 15:28
  • 问题:

在服务端保存有海量的兴趣点(POI,Point of Interest),根据用户的位置,如何判断用户当前出在哪个POI呢?

  • 分析:

兴趣点是海量的,用户也是电信级的。如果每次查询用户所处的兴趣点,都要将全部兴趣点取出来计算一遍距离,从中选取最小的,这样会给服务端带来极大的压力(计算量级别约为:兴趣点数*用户数)。

我们知道赤道约为4万公里,1度大约为111公里,1分大约为2公里,1秒大约为33米(经纬度的单位分别为度、分、秒,1度=60分=60*60秒)。

我们可以根据用户所在位置的经纬度,先从海量数据中选取用户周围一定范围内的兴趣点,然后计算用户与兴趣点之间的距离,从而选出用户所处的兴趣点。

但是,位置信息都是有一定的精度范围的,一般GPS定位精度在10米左右,基站定位精度在1000M左右,另外有的POI本来就是在一起的,比如一个是在一楼,另一个是在两楼。因此如果单单通过计算距离的最小值来选出用户所处的兴趣点也不可能完全正确。我们可以将一定范围以内的兴趣点提供给用户,让用户自己来确定在所处的兴趣点。

  • 详细方案:

假设用户所在的位置信息为(px,py,pm),px表示经度,py表示纬度,pm表示范围。

如果我们要搜索的范围是12公里(即pm=12公里)以内的,我们应该从海量兴趣点数据库中,选取经纬度变化满足以下条件的兴趣点:  

1.经度范围在[px-0.1, px+0.1](单位度)

2.纬度范围在[py-0.1,py+0.1](单位度)

备注: 0.1度=6分 约等于12公里,其中基于经纬度的相关距离信息如下:

关于用经纬度计算距离: 

地球赤道上环绕地球一周走一圈共40075.04公里,而@一圈分成360°,而每1°(度)有60,每一度一秒在赤道上的长度计算如下:
40075.04km/360°=111.31955km
111.31955km/60=1.8553258km=1855.3m
而每一分又有60秒,每一秒就代表1855.3m/60=30.92m
任意两点距离计算公式为
d=111.12cos{1/[sinΦAsinΦB十cosΦAcosΦBcos(λB—λA)]}
其中A点经度,纬度分别为λA和ΦA,B点的经度、纬度分别为λB和ΦB,d为距离。


这样就可以选出用户周围24公里*24公里这样一个范围的兴趣点。

针对以上兴趣点,我们逐个计算用户与兴趣点之间的距离,选取距离在 1000+pm (单位米)范围内的兴趣点,提供给用户进行选择确认。

计算模型中的参数可根据实际数据进行微调

  • 服务端压力:

以上方案,通过第一次筛选,极大减少了第二次筛选的计算量。主要压力为从海量数据库中查询出满足条件的兴趣点记录。不过这问题不大,完全可以通过优化数据库进行解决,如根据经纬度对表进行分区,或者基于经纬度进行函数索引等等。

  • 获取用户准确位置信息为什么那么难

首先,是因为用户的位置信息有不同的来源:GPS/WIFI/基站;其次,用户是在移动的;最后,每次获得的位置信息的准确度是在变化的。所以这些原因造成想要获得用户的准确位置信息是一件很复杂的事情。

  • 如何获取用户的位置信息

获取用户的位置信息是异步的,android通过调用一个listener回调函数,告诉应用用户的具体位置。但是,这种方式需要用户等一段时间才行,如果希望短时间内获取用户的位置信息,可以采用locationManager.getLastKnownLocation获取用户最近一次的位置信息,然后等待listener来更新更加准确的用户位置信息。

  • 如何获取准确的用户位置信息

前面已经知道,多种原因造成我们获得的用户位置信息不是那么准确,如果我们希望能够得到较为精确的位置信息怎么办?
如果用户是在不断移动的:那么不断通过listener获取用户位置信息,并从中找到最准确的位置信息;
如果用户是相对静止的:那么通过listener获取用户位置信息,并从中找到最准确的位置信息,如果连续n次,都没有找到比之前的位置信息更加准确,那么认为已经找到最准确信息,删除listener;
如果只需要获取用户粗略位置信息:那么通过listerer获取用户位置信息,从前面n个位置信息中,找到最准确的,删除listener;

原创粉丝点击