如何表示地理位置
我在用户界面上添加了与Facebook的集成,并且可以将搜索与类别和位置结合起来:
这给我带来了一些问题,不仅是Facebook的集成,还有位置方面的问题。我并没有从数据存储中获取位置,而是直接在HTML中写死了这些位置:
<select name="w" id="searcharea">
<option value="1" >Entire India</option>
<option value="2" > Andaman & Nicobar Islands</option>
<option value="3" > Andhra Pradesh</option>
等等。我们可以看到选项的值没有意义:1、2、3这些数字没有任何实际含义,我只是随便放了些数字。数据存储中的记录可以根据经度、纬度和半径来匹配,比如像?lat=-22.45&lon=-43.12&r=294200
这样的URL就是一个参数化的例子,它可以匹配里约热内卢及其周边地区,这里的半径是随便选的,目的是为了匹配里约而不是圣保罗。经度和纬度四舍五入到小数点后两位也被认为是“足够好”。但是,我该如何将HTML和数据存储之间进行映射呢?一个HTML选项值只有一个值,而经度、纬度和半径却是三个值。我希望找到一个解决方案,能够涵盖所有内容,而不需要我自己添加地理编码。经度、纬度和半径都是国际标准,所以我自然希望避免为位置创建自己的ID。我可能可以设计一个算法,让选项值是一个数字,这个数字可以解码成三个值,比如选项值123456789876可以解码为经度1234、纬度5678和半径9876。你能推荐一些解决方案吗?或者告诉我这些可能的解决方案有哪些优缺点?如果你想查看我提到的网站,可以通过这个链接访问koolbusiness.com
我希望与其他解决方案保持“兼容”,比如geomodel和谷歌地图,因此也希望用户能够选择“行政区域”、“城市”、“国家”,这种方式要与谷歌地图兼容,因为他们已经创建并更新了这个结构及其内容,而我使用了Python库geomodel来为我的实体启用地理功能:
class A(GeoModel,search.SearchableModel):
primary_image=blobstore.BlobReferenceProperty()
postaladress=db.PostalAddressProperty(indexed=False,verbose_name="postaladdress")
...
使用geomodel实现基本搜索是可行的:
m=int(self.request.get('r')) if self.request.get('r') else 804670#radius
lat = self.request.get('lat')
lon = self.request.get('lon')
articles = A.proximity_fetch(A.all(),db.GeoPt(lat, lon),max_results=PAGESIZE+1, max_distance=m)
articles = sorted(articles, key=lambda x: x.modified, reverse=True)
但是,如何将视图与后端集成,因为选项值只能接受一个值呢?我应该将三个值(经度、纬度、半径)编码为一个值吗?还是有其他解决方案?谢谢你。
3 个回答
你可能在找一种叫做“四叉键”的东西。四叉键是一种空间索引,或者说是一种填充空间的曲线。它看起来像四叉树或者分形,可以把二维的复杂性简化成一维的复杂性。谷歌地图和必应地图使用的是Z曲线,因为它比较容易处理。而希尔伯特曲线在填充空间方面表现更好,但处理起来更复杂。四叉键的主要思想是从左到右查找一个瓦片及其位置。举个例子,如果你的四叉键是12333222244,你可以搜索1233*,这样就能找到那个瓦片及其之后或者下面的所有位置,因为它是一种树形数据结构。
为什么不直接这样做:
<option value="{lat:-22.45,long:-43.12,r:294200}">Rio De Janeiro</option>
这样你就可以用 jsondecode 函数把这个值解码,获取里面的各个部分。
最简单的方法就是在你的代码里定义一个查找表,放在配置文件中。例如:
location_map = {
1: {'name': Rio De Janeiro', 'lat': -22.45, 'long': -43.12, 'radius': 294200},
# ...
}
然后,你可以直接用选项的值作为关键字,从这个数组中查找对应的值。你还可以通过遍历这个数组来生成表单字段,输出名称和值的配对。