MySQL 空間距離

當SNS產品加入LBS的技術將會讓移動互聯網領域更加豐富多彩,例如:大衆點評,街旁,盛大切客 這些運行在智能手機端的應用,當用戶拿出手機就能夠根據你當前的所在地向你推薦一些有用的信息,例如:附近的美食,商鋪,周邊生活信息,等。html

攻城師們,你有沒有想過這些應用背後的技術實現呢?手機端得到當前的座標後是怎麼進行計算和查詢返回附件的結果呢?mysql

用Java程序能夠實現Dijkstra算法得到點與多點之間最短路徑的計算結果,可是我我的認爲是一種暴力的方法,開發的簡化程度和計算的執行效率不會很是高。
參考資料:http://baike.baidu.com/view/7839.htmandroid

接着再往下想,用到數據庫技術是必然,但不會把節點的座標信息存儲到數據庫普通的字段中進行查詢,若是和Dijkstra算法相比不會簡化工做量也不會提升性能,但使用到MySQL中空間數據庫的概念就會簡化不少也會獲得性能的提高,開源的MySQL Spatial空間索引機制就能夠對點到多點之間的距離計算,相似的Spatial Database還有,PostGIS,SpatiaLite。算法

個人廢話:
在android手機上得到當前座標後,將數據整好錄入android中的SQLite數據庫也能夠得到當前點對多點的最短路徑,也就是說在地理數據不會更新的場景下徹底能夠採用android手機上的數據庫完成這項工做,沒有必要非要利用服務器端的Spatial Database完成最短路徑的計算。sql

MySQL空間數據幾種主要類型:
     – GEOMETRY  Geometry是層次結構的根類。它是一種非實例化類,但具備不少屬性,這些屬性對由任何Geometry子類建立的全部幾何值來講是共同的。
     – POINT   表明座標空間中單個位置的幾何類,他的屬性包含 X-座標值,Y-座標值。
     – LINESTRING  具備線段的座標,由每一個連續的點對(兩點)定義。若是僅包含兩點,LineString爲Line。 若是它既是簡單的也是封閉的,LineString爲LinearRing。
     – POLYGON  它由單個外部邊界以及0或多個內部邊界定義,其中,每一個內部邊界定義爲Polygon中的1個孔。例如:在地區地圖上,Polygon對象可表示森林。
     – MULTIPOINT  MultiPoint是一種由Point元素構成的幾何對象集合。這些點未以任何方式鏈接或排序。
     – MULTILINESTRING  MultiLineString是一種由 LineString元素構成的MultiCurve幾何對象集合,例如:河流體系或高速路系統。
     – MULTIPOLYGON  MultiPolygon是一種由Polygon元素構成的幾何對象集合。在地區地圖上,MultiPolygon可表示湖泊系統。
     – GEOMETRYCOLLECTION   他是由1個或多個任意類幾何對象構成的幾何對象。GeometryCollection中的全部元素必須具備相同的空間參考系(即相同的座標系).
以上幾種的類型依賴關係,如圖所示:
數據庫

瞭解過上述一些基本知識,下面來建立一張商戶表,而且包含定義的空間數據庫的POINT字段:
  Create table shop (
     shop_id int(3) primary key,
     Location POINT,
     Shop_na vachar(100),
     Shop_info vachar(300)
     );服務器

插入幾條商家的門店信息,其中採用GeomFromText方法將座標的數據庫插入POINT字段中,例如:
insert into shop values (‘XXX’,’,GeomFromText(‘POINT(1 1)’),’XX店’,’ '其餘信息');
下面將根據客戶當前所在位置在MySQL中查詢,搜索出在當前位置附近的必定範圍內的門店,而且能夠作到按距離由近到遠排列顯示出來,從讓用戶而找到離他最近的門店。
把客戶當前所在位置可設成變量 ,例如:set @center=GeomFromText(‘POINT(10 10)’);函數

再把要找到最近門店能夠縮小搜索範圍 設半徑,添加搜索條件
例:set @radius=30;
WHERE SQRT(POW( ABS( X(location) – X(@center)), 2) + POW( ABS(Y(location) – Y(@center)), 2 )) < @radius 性能

最近門店搜索,完整的SQL示例:
SELECT shop_id,shop_na, SQRT(POW( ABS( X(Location) – X(@center)), 2) + POW(ABS(Y(Location) – Y(@center)), 2 )) AS distance
FROM shop WHERE SQRT(POW( ABS( X(location) – X(@center)), 2) + POW( ABS(Y(location) – Y(@center)), 2 )) < @radius
order by distance;spa

其中涉及的數學函數SQRT(x):表示求一個數x的平方根。POW(x,y):包含兩個參數表示求x的y次冪。ABS(x):表示求數X的絕對值。整個SQRT(POW( ABS( X(Location) – X(@center)), 2) + POW(ABS(Y(Location) – Y(@center)), 2 ))這個SQL語句實現的是一個算術表達式

即兩點間的直線距離。
好比說如今有兩個點座標A(x1,y1),B(x2,y2) 要求線段AB長度 就是用這個公式去計算。把A當作當前位置B當作一個門店,不就是至關於計算當前位置到門店這兩個點的距離嗎。座標點有了帶進去就行,等於如今只要能用函數把這個公式表示出來就能夠了。
因此用到這三個函數:
SQRT(x):表示求一個數x的平方根。就至關於那個根號。√x
POW(x,y):包含兩個參數表示求x的y次冪
例如pow(2,3)就表示23,那麼POW((X1-X2),2)就至關於〖(x1-x2)〗^2
ABS(x):表示求數X的絕對值。|x|  ABS(x1-x2)就等於|x1-x2|.

根據那個公式組合起來就好了
整個SQRT(POW( ABS( X(Location) – X(@center)), 2) + POW(ABS(Y(Location) – Y(@center)), 2))這句話就是用來表示這個公式的
,
這個公式計算得出來的值就是兩點間的直線距離。

參考資料:
http://dev.mysql.com/doc/refman/5.1/zh/spatial-extensions-in-mysql.html
http://en.wikipedia.org/wiki/Spatial_database

口水:
 以上部份內容來自 NJ-AMT 實習生餘珊的分析報告。

–end–

相關文章
相關標籤/搜索