日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

lbs(查看附近的人),看看社交软件如何实现查看附近的人

發布時間:2023/12/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lbs(查看附近的人),看看社交软件如何实现查看附近的人 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文?https://www.cnblogs.com/iforever/p/4061095.html?utm_source=tuicool&utm_medium=referral

? ? 最近在做一款移動端棋牌游戲,為了進一步提高用戶體驗、拉近玩家的距離,我們決定在游戲中加入好友功能,而對于體驗好友功能的玩家來說,要是玩牌的時候可以看看附近都有誰在玩牌,跟他們交流交流玩牌心得什么的無疑是個不錯的想法。而要實現查看附近的人就需要提提LBS(Location Based Service),他的意思就是基于位置的服務,就是通過移動終端獲取到許多用戶或者物體的經緯度坐標,通過這些位置信息所提供的服務。

?????? 好了,扯了這么多,我們來看看如何實現查看附近人的功能的:

?????? 首先要具備下面這些環境:

  • php+MySQL(MySQL不是必須,本文中用的是redis來存儲用戶的信息)
  • redis(本文用的是redis,當然你也可以用MySQL)
  • geohash.class.php類(這個類是用來處理經緯度坐標的一些基本函數,當然這些東西完全可以自己去寫,如果時間充裕的話)
  • ?????? 好了,等這些環境都具備了之后,我來講講這個實現過程:

    • 首先介紹下GeoHash思想

    ?? ?? 第一步.? 編碼

    ????? 這個功能應用到了一個很好的算法GeoHash,也許有同學聽過這個功能,沒錯GeoHash就是通過一個巧妙的算法(不由得驚嘆前輩們真牛!)把經緯度轉化為字符串,這樣有什么好處呢,顯而易見,將二維的數據轉化為了一維,這樣一來存儲就方便了,搜索效率也會高很多,那么現在問題來了,GeoHash算法是如何把經緯度坐標轉化為字符串的?

    ????? 將經緯度編碼為字符串的過程可以分為以下3個步驟:

    ????? 首先就是編碼,對于經緯度的編碼通過折半比較法,當大于中值時該位編碼為1(小于時編碼為0),下次新的區間為中值到最大值(或者最小值到中值),這樣一直比較下去,直到到達要求的精度,精度和緯度的方法是一樣的,只不過一個原始區間是(-90,90),一個是(-180,180),光說不好理解,下面我們看看一個簡單的例子:

    對經度32.165進行編碼:???????????????????????????????????????????????????????????????????????????????????????????????? 對緯度89.156進行編碼:

    編碼

    min

    mid

    max

    1

    -90

    0

    90

    0

    0

    45

    90

    1

    0

    22.5

    45

    0

    22.5

    033.75

    45

    1

    22.5

    28.125

    33.75

    1

    28.125

    30.9375

    33.75

    0

    30.9375

    32.34375

    33.75

    1

    30.9375

    31.640625

    32.34375

    1

    31.640625

    31.9921875

    32.34375

    0

    31.9921875

    32.16796875

    32.34375

    編碼

    min

    mid

    max

    1

    -180

    0

    180

    0

    0

    90

    180

    1

    0

    45

    90

    1

    45

    67.5

    90

    1

    67.5

    78.75

    90

    1

    78.75

    84.375

    90

    1

    84.375

    87.1875

    90

    1

    87.1875

    88.59375

    90

    0

    88.59375

    89.296875

    90

    1

    88.59375

    88.9453125

    89.296875

    ??????? 這樣便可將(89.156,32.165) =>? (10101 10110,10111 11101)

    ??????? 這個時候就到了第二步驟——組碼了,顧名思義,將第一步產生的編碼組合起來為下一步產生字符串做準備,組碼的方式是偶數位放置經度,奇數位放緯度(為什么要這么做呢,我猜可能是谷歌為了大家統一規范,僅此而已,其實奇偶數位互換也可以的),對于上面的經緯度編碼后再組碼如下:

    經度:10101 11101

    緯度:10111 11101

    位置編碼:11001 11011 11111 10011

    圖 3

    ?????? 對于上面的位置編碼,為什么要這么編碼呢,為什么要奇數位放緯度,偶數為方經度呢,我們看看下面這張圖,用這張圖模擬地圖的經緯度,A點(-180,90),B點(180,90),C點(-180,-90),D點(180,-90);

    A

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    B

    ?

    010101

    010111

    011101

    011111

    110101

    110111

    111101

    111111

    ?

    ?

    010100

    010110

    011100

    011110

    110100

    110110

    111100

    111110

    ?

    ?

    010001

    010011

    011001

    011011

    110001

    110011

    111001

    111011

    ?

    ?

    010000

    010010

    011000

    011010

    110000

    110010

    111000

    111010

    ?

    ?

    000101

    000111

    001101

    001111

    100101

    100111

    101101

    101111

    ?

    ?

    000100

    000110

    001100

    001110

    100100

    100110

    101100

    101110

    ?

    ?

    000001

    000011

    001001

    001011

    100001

    100011

    101001

    101011

    ?

    ?

    000000

    000010

    001000

    001010

    100000

    100010

    101000

    101010

    ?

    C

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    D

    圖 4

    ??????? 如圖4所示,這樣就可以將地圖(經度-180~180,緯度-90~90)分為很多很多多的小塊,每一個小塊都有唯一的二進制編碼,當位數達到一定的長度時就可以表示很小的一塊區域,這不就可以根據二進制編碼定位一個唯一的位置了嗎,對于劃分的進一步理解可看下面的圖。

    圖 5

    ????? 如圖5所示,左邊是是對緯度(-180,180)的劃分,可以看出通過劃分可以確定(22.4,45)這一緯度區間的編碼為1001,當然了位數越多精度越高,同理對經度進行劃分,可以確定(-78.75,-67.5)這一經度范圍的編碼為0001,可以想象,當左右兩張圖合在一起時就可以確定一個唯一的矩形區域,當該區域足夠小的時候就可一看做一個點。

    ?

    ??? ? 第二步.? 組碼

    ????? 從圖3可以看出我們對經緯度編碼后可得二進制字符串11001 11011 11111 10011

    ????? 最后使用用0-9、b-z(去掉a, i, l, o)這32個字母進行base32編碼,首先將11001 11011 11111 10011轉成十進制,對應著25、27、32、19,十進制對應的編碼就是tvzm。同理,將編碼轉換成經緯度的解碼算法與之相反,具體不再贅述。至此,我們的對geohash有了個大致的了解。

    ??????? 圖 6

    • 如何具體的應用到程序中

    ?????? 首先思考一下查看附近的人的流程:

  • 用戶點擊查看附近的人按鈕,首先獲取到該用戶的選位置信息(經緯度),傳給服務器。

  • 服務器收到數據之后對該用戶的位置信息進行geohash計算,獲得該用戶的位置hash字符串。

  • 對該用戶的位置信息hash串進行緩存(緩存時間長短根據具體情況而定)。

  • 根據該hash串選出附近的人。

  • 對hash進行解碼,計算出附近用戶的位置,返回給用戶。

  • ?????? 首先看看geohash.class.php這個公共類庫里面的基本方法:

    ?

    [public]Geohash()?????? 初始化hash映射表

    Geohash

    [public]encode(lat,lat, long)?????? 對經緯度進行編碼

    ?

    [public]decode()?????? 對hash進行解碼

    圖 7

    ????? 如圖7所示,顯而易見這個類庫里面有3個函數,第一個用來初始化hash映射表,其實就是把0123456789bcdefghjkmnpqrstuvwxyz字符串中的每個字符和它對應的二進制編碼對應起來(左邊補零至5位)。encode()是用來生成hash的,decode是用來解碼hash得到hash對應的經緯度的。

    ??????? 下面我們看個例子,現在假設有圖8中的幾個用戶查看附近的人:

    mid

    坐標

    100

    (42.61233,-5.61234)

    101

    (-20.25689, 50.56897)

    102

    (10.11233, 57.21234)

    103

    (49.26343, -123.26895)

    104

    (0.00534, -179.56732)

    105

    (-30.55555, 0.28958)

    106

    (5.00001, -140.63422)

    107

    (42.61234, -5.61234)

    108

    (5.00001, -140.63422)

    圖 8

    ?????? 圖8的數據發送到服務器經過geohash計算得出下面的hash表:

    ?

    mid

    坐標

    100

    ezs42m34yfp_100

    101

    mh7uy8r5n6j_101

    102

    t3b9tbuu84u_102

    103

    c2b26bnk32b_103

    104

    80021bgp45m_104

    105

    k484ntdc58w_105

    106

    8bgury1r1jm_106

    107

    ezs42m34ygz_107

    108

    8bgury1r1jm_108

    圖 9

    ??????? 計算出這些hash值,將hash值存入redis中,存入redis中之后,那么問題來了,如何去獲取一個用戶附近的用戶呢?當redis數據庫中有了一些用戶的記錄之后,來一個用戶,我們先對其進行編碼,然后根據該用戶的位置hash從redis中選出該用戶附近的hash,選取附近的hash這一步很簡單,對于redis只需這么做:

    <?php$mid = 2014;$level = 7; //獲取的精度等級,數字越大,附近這個范圍越小$redis = Redis::init(); //假設這樣獲取到redis實例$mykey = '8gur95yjmz'; //假設我的hash為這個$redis->setex($mykey.'_'.$mid,$_SERVER['REQUEST_TIME'],86400); //這里設置緩存1天,具體情況具體對待 $search = substr($makey,0,$level);$nearbys = $redis->keys("{$search}*"); ?>

    ????? 程序 1

    ?????? 上面的幾句代碼就可以選出我附近的人的hash,當然,其中的level來設置精度的,這個數字越大,附近的人范圍越小,具體參考圖10中的值,這個表中的值是從我的導師李偉(weickly)那里獲取到的。要注意,這個地方搜索完之后要排除自己。還有一點要注意,就是在緩存時鍵名的最后一定要加上_{$mid},這樣做可以避免多個用戶在同一位置是互相覆蓋的情況(就像圖9中mid為106和108的用戶),放在最后是為了不影響搜索。

    1

    2500000m

    2

    630000m

    3

    78000m

    4

    20000m

    5

    2400m

    6

    610m

    7

    76m

    8

    19m

    9

    2m

    圖 10

    ??????? 例如mid為109,經緯度為(42.61236, -5.61234)的用戶,當他點擊獲取附近的人按鈕式,我獲取到他的經緯度并計算出他的hash,$mykey='ezs42m34yzx',然后通過程序段1可以獲取到他附近的hash:

    100

    ezs42m34yfp_100

    (42.61233,-5.61234)

    3.3m

    107

    ezs42m34ygz_107

    (42.61234, -5.61234)

    2.2m

    109

    ezs42m34yzx_109

    (42.61236, -5.61234)

    0m

    圖 11

    ??????? 圖11中獲取到了用戶109附近的用戶hashs,獲取到hash值還并沒有完成,首先排除掉自己109那條記錄,然后通過Geohash類中的decode將hash解碼為經緯度,通過每個用戶的經緯度計算出和109用戶的距離,然后按距離等級返回,比如說小于100,小于200……

    ??????? 至此,獲取附近的人就完成了,當然了具體實踐的時候還要隨機應變具體情況具體對待,我寫這篇文章只是想起到拋磚引玉的效果,本文中可能會存在很多不足,還望斧正。

    ?

      本文版權歸作者(luluyrt@163.com)和博客園共有,未經作者本人同意禁止任何形式的轉載,轉載文章之后必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責任的權利。?

    總結

    以上是生活随笔為你收集整理的lbs(查看附近的人),看看社交软件如何实现查看附近的人的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。