GeoHash索引
GeoHash簡介
GeoHash索引是一種基于B樹索引,又結合了格網索引的思想的使用廣泛的空間索引算法。GeoHash將空間位置編碼為一串字符,通過字符串的比較可以得到空間的大致范圍。這種編碼方法起初被用于以唯一的URL標識地圖上的點實體,而點實體一般是以經緯度標識的,所以問題就轉變為如何使用URL標識經緯度坐標。下面舉例說明GeoHash編碼的具體實現步驟。設定武漢大學的經緯度坐標是(114.360734E, 30.541093N),首先,可以通過如下算法對緯度30.54進行逼近編碼:
(1)對維度區間[-90,90]進行二分為[-90,0)和[0,90],稱為左右區間,可以確定30.541093屬于右區間[0,90],給標記為1;
(2)接著將區間[0,90]進行二分為 [0,45)和[45,90],可以確定30.541093屬于左區間 [0,45),給標記為0;
(3)遞歸上述過程30.541093,如果給定的緯度屬于左區間,則記錄0,如果屬于右區間則記錄1,這樣隨著算法的進行會產生一個序列101010110110111,序列的長度跟給定的區間劃分次數有關。
(4)同樣的方法,對經度區間[-180, 180]進行編碼,可以得到一個二進制序列110100010101001。
(5)合并經緯度編碼,偶數位放經度編碼(第一位從0開始),奇數位放緯度編碼,把兩串編碼組合生成新串11100 11001 00011 10011 01100 10111。
(6)對合成的新的二進制串,每五位轉成十進制數得到28,25,3,19,12,23,然后再進行Base32編碼得到該經緯度的GeoHash編碼為wt3mdr。
對于GeoHash索引,需要明確的是:(1)GeoHash編碼值表示的并不是一個點,而是一個矩形區域。落在該矩形區域的所有點都可以用該編碼表示。(2)字符串越長,表示的范圍越精確。編碼的前綴可以表示更大的區域。例如wt3mdrff,它的前綴wt3mdr表示包含編碼wt3mdrff在內的更大范圍。 利用該特性可以進行臨近點的搜索。首先根據用戶當前坐標計算GeoHash值,然后取其前綴進行查詢。(3)GeoHash將區域劃分為一個個規則矩形,位于矩形邊界兩側的兩點,雖然十分接近,但編碼會完全不同,因為它的編碼方式從左上到右下突變時存在不連續的“跳躍”。
一個例子
下面的例子用到了一個第三方GeoHash庫,我使用maven構建項目,pom文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.tzy</groupId><artifactId>geohash</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>geohash</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><repositories><repository><id>repo1.maven.org</id><name>Maven Official Repository</name><url>http://repo1.maven.org/maven2/</url></repository></repositories><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>ch.hsr</groupId><artifactId>geohash</artifactId><version>1.3.0</version></dependency></dependencies> </project>Java代碼入下:
package cn.tzy.geohash;import java.util.ArrayList; import java.util.List;import ch.hsr.geohash.GeoHash;public class GeoHashEx {public static void main(String[] args) {double lat = 30.541093;double lon = 114.360734;int precision = 6;GeoHash geoHash = GeoHash.withCharacterPrecision(lat, lon, precision);String hashCode = geoHash.toBase32();System.out.print("GeoHash編碼為:");System.out.println(hashCode);String binaryCode = geoHash.toBinaryString();System.out.print("對應的二進制編碼為:");System.out.println(binaryCode);int length = binaryCode.length();System.out.print("對應的十進制編碼為:");for(int i = 0; i < length; i+=5) {String code = binaryCode.substring(i, i + 5);int num = Integer.valueOf(code, 2);System.out.print(num);System.out.print(" ");}System.out.println();char[] binaryCodes = binaryCode.toCharArray();List<Character> latCodes = new ArrayList<Character>();List<Character> lonCodes = new ArrayList<Character>();for (int i = 0; i < binaryCodes.length; i++) {if (i % 2 == 0) {lonCodes.add(binaryCodes[i]);} else {latCodes.add(binaryCodes[i]);}}StringBuilder latCode = new StringBuilder();StringBuilder lonCode = new StringBuilder();for (Character ch : latCodes) {latCode.append(ch);}for (Character ch : lonCodes) {lonCode.append(ch);}System.out.print("維度編碼為:");System.out.println(latCode.toString());System.out.print("經度編碼為:");System.out.println(lonCode.toString());} }運行結果如下:
GeoHash編碼為:wt3mdr 對應的二進制編碼為:111001100100011100110110010111 對應的十進制編碼為:28 25 3 19 12 23 維度編碼為:101010110110111 經度編碼為:110100010101001總結
- 上一篇: FL Studio中Plucked!合成
- 下一篇: 使用UE4画刷BSP创建房子