1. 程式人生 > >Geohash求當前區域周圍8個區域編碼的一種思路

Geohash求當前區域周圍8個區域編碼的一種思路

首先感謝GeoHash核心原理解析這篇文章讓我明白了什麼叫geohash

在這篇文章裡,作者提出了幾個使用geohash的注意點:

由於GeoHash是將區域劃分為一個個規則矩形,並對每個矩形進行編碼,這樣在查詢附近POI資訊時會導致以下問題,比如紅色的點是我們的位 置,綠色的兩個點分別是附近的兩個餐館,但是在查詢的時候會發現距離較遠餐館的GeoHash編碼與我們一樣(因為在同一個GeoHash區域塊上),而 較近餐館的GeoHash編碼與我們不一致。這個問題往往產生在邊界處。

解決的思路很簡單,我們查詢時,除了使用定位點的GeoHash編碼進行匹配外,還使用周圍8個區域的GeoHash編碼,這樣可以避免這個問題。

那麼如何得到周圍8個區域的geohash編碼呢,作者沒有提供更明確的思路,在網上也搜尋不到相關的解決辦法,所以在這裡提大家提供我的思路。

看到這裡,我假設各位已經清楚如何對經緯度進行geohash編碼。
在對經度進行二分逼近時,落在左邊區間為0,右邊為1:
第一次劃分:這裡寫圖片描述
第二次劃分:這裡寫圖片描述
第三次劃分:這裡寫圖片描述

可以看出每一塊區域的編碼,從左往右依次對應了十進位制的0~(2^n)-1,同樣的,對緯度逼近的過程中,每一塊區域從下往上同樣依次對應0~(2^n)-1。
因此,很容易的就能求出周圍區域的geohash值:
1. 將當前區域的geohash編碼解碼成經緯度對應的二進位制串
2. 將二進位制串+1或者-1就能得到左右經度(或上下緯度)區域對應的二進位制串(注意邊界)
3. 得到的經緯度二進位制串兩兩組合再進行geohash的編碼,得到的就是周圍區域的編碼了。
程式碼如下:

/**
     * 求與當前geohash相鄰的8個格子的geohash值。
     * @param geohash
     * @return string陣列,周圍格子的geohash值
     * @throws LengthOutOfRangException
     *             geohash長度超出範圍(<=12)
     */
    public String[] expand(String geohash) throws LengthOutOfRangException {
        if (geohash.length() > 12
) throw new LengthOutOfRangException("The length of geohash is out of range"); String bCoordinate = decodeToBinary(geohash);//當前geohash值對應的二進位制串 StringBuilder bLat = new StringBuilder(); StringBuilder bLon = new StringBuilder(); for (int i = 0; i < bCoordinate.length(); i++) { if ((i % 2) == 0) { bLon.append(bCoordinate.charAt(i)); } else { bLat.append(bCoordinate.charAt(i)); } } String lat = bLat.toString(); String lon = bLon.toString(); String downLat = calculate(lat, -1); String upLat = calculate(lat, 1); String leftLon = calculate(lon, -1); String rightLon = calculate(lon, 1); return new String[] { encode(upLat,leftLon), encode(upLat,lon), encode(upLat,rightLon), encode(lat,leftLon), geohash, encode(lat,rightLon), encode(downLat,leftLon), encode(downLat,lon), encode(downLat,rightLon) }; } /** * 計算當前格子左右(上下)格子的經(緯)度值二進位制串 * * @param coordinate * 當前格子的經/緯度值 * @param i * 偏移量 * @return */ private String calculate(String coordinate, int i) { int length = coordinate.length(); String result = Integer.toBinaryString((Integer.valueOf(coordinate, 2) + i) + (1 << length)).substring(1); if (result.length() != length) { return null; } else { return result; } }

相關推薦

Geohash當前區域周圍8區域編碼思路

首先感謝GeoHash核心原理解析這篇文章讓我明白了什麼叫geohash 在這篇文章裡,作者提出了幾個使用geohash的注意點: 由於GeoHash是將區域劃分為一個個規則矩形,並對每個矩形進行編碼,這樣在查詢附近POI資訊時會導致以下問題,比如紅色

用打表的方式解決Geohash當前區域周圍8區域編碼

兩個多月前寫了上一篇計算周圍8個格子編碼的文章,實際用時發現效率不高,因為每次計算都需要先解碼成二進位制串算完再進行編碼。後來在github上發現一個js專案,用打表的方法來求周圍8個格子,效率提高了不少。這裡寫一點自己的理解。 拿”wx4g”這個geohas

Geohash 基本知識及 .NET 下計算相鄰8區域編碼

fine 一個 detail bits 獲取 geohash 技術 esp stat 目錄 一、簡介 二、計算方法 三、GeoHash的精度 四、查找相鄰8個區域的Geohash編碼(.NET) 最近項目中需要搜索周邊的 POI 信息,查找的過程中了解到了 Geohas

PHP的date()獲得當前時間 少8小時的解決方法

摘要:PHP的date()獲得的當前時間和實際的本地時間不一致的,和北京時間正好差8個小時的解決方法。 難度:20 初學PHP想獲得當前時間,翻翻PHP手冊或書就知道用時間函式date() 格式化一個本地時間/日期,寫個測試程式碼: 〈?php          echo date(’Y-m-d H:i:s

滲透測試的8步驟 展現次完整的滲透測試過程及思路

         滲透測試這個事情不是隨便拿個工具就可以做了, 要了解業務還需要給出解決方案 。之前安全加介紹了金融行業 實戰微信銀行滲透測試, 運營商 滲透測試實戰 ,今天讓我們來說說 滲透測試&n

一個整數型數組裡除了倆數字之外,其他的數字都出現倆次,找出這倆只出現次的數字

思路: 1 倆個相同的數字異或等於0。假設陣列中只有一個只出現一次的數字,因此從頭到尾依次異或陣列中的每個數字,那麼最終的結果就是那個只出現一次的數字。 2 想辦法把陣列分成倆個子陣列,使2個只出現一次的數字分別在兩個子陣列中。 3 分陣列,用依次異或陣列中的每個數,最後的

思路比較2日期是否相等的方式

字符 進行 != 思路 ati 轉換 格式轉換 new imp 我們在應用中經常會遇到2個日期比較是否同一年,或者同一個月或者同一日,等。 常規方式,我們通過逐個年,月,日的比較,才能確定是否是同一年,或同一個月或同一日。 我們換一種思路,把2個日期按同一個日期格式轉換成字

K8S從懵圈到熟練 – 叢集服務的三要點和實現

以我的經驗來講,理解K8S叢集服務的概念,是比較不容易的一件事情。尤其是當我們基於似是而非的理解,去排查服務相關問題的時候,會非常

Kubernetes 從懵圈到熟練:叢集服務的三要點和實現

作者 | 聲東 阿里雲售後技術專家<br /> 文章來源:Docker,點選檢視原文。 <br />以

OSPF多區域連通

ping span term spf 技術 family margin peer 路由 1.OSPF屬於鏈路狀態路由選擇協議,並且是共有標準。理論上是沒有網絡規模限制的。支持網絡的層次化設計。2.OSPF可以將網絡分為2層骨幹區域:0區域為骨幹區域非骨幹區域:.除了骨幹區域

MySQL操作的時候,發現輸入當前資料,資料庫中儲存的資料總比輸入的要小8小時

在使用mybatis進行MySQL操作的時候,發現輸入當前資料,資料庫中儲存的資料總比輸入的要小8個小時,幾經搜尋找到了原因,原來是因為mybatis配置檔案中 <property name="url" value="jdbc:mysql://localhost:3306/mybatisD

n三角形最多可以構成多少區域

題目: Problem Description 用N個三角形最多可以把平面分成幾個區域? Input 輸入資料的第一行是一個正整數T(1<=T<=10000),表示測試資料的數量.然後是T組測試資料,每組測試資料只包含一個正整數N(1<=N<=1

Android同一個TextView裡響應多區域點選事件

    專案中遇到這樣的一個需求:物流資訊中會返回一個配送人員的手機號碼,一個投訴電話,根據快遞公司不同,有時候還會返回一個快遞單號,這三個標籤的字型顯示為藍色並且可點選。第一反應是放不同的TextView或者Button分別處理他們的點選事件,當然是不可取的,因為這些物流資訊不止一條,我們看那些電商的物流

hdu 1249 N三角形把平面分成幾區域

查詢的內容:/*每條邊最多與前面已畫的(n—1)個三角形的各兩條邊相交,第n個三角形每條邊最多與2*(n-1)條邊相交。對於每條邊,它所截出的區域(不算第n個三角形的角)有2*(n-1)-1個,於是3條邊可截出6*(n-1)-3個區域,再加上3個角即可多出6*(n-1)個區

N點可以將圓劃分成幾區域

尤拉示性數公式: V:頂點數; E:邊數; F:被劃分區域數; #include<bits/stdc++.h> using namespace std; long long C(int n, int m) { long long s=1

Android 仿PC端QQ自由截圖,可支援次截多區域

仿PC端QQ截圖,可任意截圖,這裡只做了矩形這一種形狀,可同時支援擷取多個區域,支援撤銷上次截圖,重新擷取。 實現原理: 自定義SurfaceView,在SurfaceView上繪製具有一個可拉伸,移動的矩形框,當點選截圖按鈕後,計算矩形

用N三角形最多可以把平面分成幾區域

遞推公式:a[i]=a[i-1]+6*(i-1); 10000以內的 #include<iostream> using namespace std; long long a[10001]; int main() { a[1]=2; for(int i=2;

CSS-蜂窩狀展示區域(多六邊形)的實現方式

lis child form 兩個 說明 多個 組合 hid clas 網上已經有很多關於正六邊形的CSS畫法,主要是利用一個矩形和前後的兩個三角形組合而成。 之前在看四維圖新的官網的時候,發現了一種六邊形的畫法,比較適合多排六邊形組合成蜂窩狀的展示區域(註:四維圖新現在改

1到1000的所有的素數的java程式碼(每行顯示8素數)

public class SuShu {public static void main(String[] args) {int s = 0;for (int i = 2; i <= 1000; i++) {int g = 1;//控制除數範圍  因為素數的定義是不能整除1到它自己本身之間的整數for (

MVC 在Action中,過濾器中,或檢視中,獲取當前請求的 控制器/檢視/區域的名字及跳轉

MVC 在Action中或過濾器中或檢視中獲取當前請求的控制器/檢視/區域的名字 1)過濾器中: public class CMSAttribute : FilterAttribute, IAuthorizationFilter {  public void OnAu