1. 程式人生 > >mysql對GIS的支援 & oracle 空間資料庫說明

mysql對GIS的支援 & oracle 空間資料庫說明

今天下午閒來無事,無意中翻看了一下mysql的手冊,以前總是很有針對性的查閱手冊的內容,重點都是放在了sql語句的一些基本細節、mysql的效能引數、儲存控制的管理等方面,但是今天無意中發現了一個mysql的重要特點,那就是mysql對gis相關的空間資料也有儲存功能,這一點突然激起了我的興趣,所以也著重的研究了一下手冊的相關內容。從手冊上來看 其實mysql很早就提供了對gis物件的支援,只是我沒有發現而已。

PostgreSQL由於具備PostGIS擴充套件而在開源GIS中有廣泛地應用,而作為開源資料庫中的另一個巨頭,mysql也不曾放棄gis這一重要的資料庫應用領域。從MySQL4.1開始,mysql就引入了一系列空間擴充套件,使其具備了一定的空間處理能力。
mysql遵守OGC的OpenGIS Geometry Model,支援以下空間資料物件
Geometry (non-instantiable)

Point (instantiable)
Curve (non-instantiable)
LineString (instantiable)
Line
LinearRing
Surface (non-instantiable)
Polygon (instantiable)
GeometryCollection (instantiable)

MultiPoint (instantiable)
MultiCurve (non-instantiable)
MultiLineString (instantiable)
MultiSurface (non-instantiable)
MultiPolygon (instantiable)

WTK是將空間資料匯入mysql空間資料表的主要途徑。WTB是WTK的二進位制形式,也可以為mysql辨識。

建立mysql空間資料表
當前只有MyISAM引擎的資料表支援地理空間資料的儲存,所以在建立資料表的時候必須進行宣告。

CREATE DATABASE geodatabase;
USE geodatabase;
CREATE TABLE test(
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(128) NOT NULL,
  pnt POINT,
  line LINESTRING,
  pgn POLYGON
)ENGINE=MyISAM;


用以下SQL插入一條空間資料

INSERT INTO `test` VALUES(
null,
'a test string',
POINTFROMTEXT('POINT(15 20)'),
LINESTRINGFROMTEXT('LINESTRING(0 0, 10 10, 20 25, 50 60)'),
POLYGONFROMTEXT('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))')
);

這裡也可以用通行的GEOMFROMTEXT函式實現WKT到資料庫內部幾何格式的轉換。而GEOMFROMWKB函式用於轉換WKB。

用以下SQL從資料表中獲得空間資料

SELECT id,name,ASTEXT(pnt),ASTEXT(line),ASTEXT(pgn) from `test`;

ASTEXT函式的功能與GEOMFROMTEXT的功能恰好相反,就是將資料從內部格式轉換為WKT;相應的ASBINARY可以轉換為WKB。

mysql內建的gis函式,這些函式是mysql資料庫本身就具備了比較強大的空間分析能力。mysql作為“最快”的開源資料庫,在gis領域中完全可以有更廣泛的應用。

     我個人認為充分的發掘mysql在gis空間資料儲存上的特點,通過php指令碼或者c#程式開發有特色的儲存方式一定是一件非常有意義的事情,有時間的話我回做一些嘗試,有什麼進展也會及時的寫在部落格上。

由於最近弄一些空間資料,所以找了些oracle空間資料庫的一些知識.下面是彙總:

Oracle Spatial由一坨的物件資料型別,型別方法,操作子,函式與過程組合而成。一個地理物件作為一個SDO_GEOMETRY物件儲存在表的一個欄位裡。空間索引則由普通的DDL和DML語句來建立與維護。
建立表:
CREATE TABLE cola_markets (
mkt_id NUMBER PRIMARY KEY,
name VARCHAR2(32),
shape SDO_GEOMETRY);

插入資料:
INSERT INTO cola_markets VALUES(
1,
'cola_a',
SDO_GEOMETRY(
2003, -- two-dimensional polygon
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,3), -- one rectangle (1003 = exterior)
SDO_ORDINATE_ARRAY(1,1, 5,7) -- only 2 points needed to
-- define rectangle (lower left and upper right) with
-- Cartesian-coordinate data
)
);
INSERT INTO cola_markets VALUES(
2,
'cola_b',
SDO_GEOMETRY(
2003, -- two-dimensional polygon
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,1), -- one polygon (exterior polygon ring)
SDO_ORDINATE_ARRAY(5,1, 8,1, 8,6, 5,7, 5,1)
)
);

INSERT INTO cola_markets VALUES(
3,
'cola_c',
SDO_GEOMETRY(
2003, -- two-dimensional polygon
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,1), -- one polygon (exterior polygon ring)
SDO_ORDINATE_ARRAY(3,3, 6,3, 6,5, 4,5, 3,3)
)
);

INSERT INTO cola_markets VALUES(
4,
'cola_d',
SDO_GEOMETRY(
2003, -- two-dimensional polygon
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,4), -- one circle
SDO_ORDINATE_ARRAY(8,7, 10,9, 8,11)
)
);

更新檢視:USER_SDO_GEOM_METADATA
INSERT INTO user_sdo_geom_metadata
(TABLE_NAME,
COLUMN_NAME,
DIMINFO,
SRID)
VALUES (
'cola_markets',
'shape',
SDO_DIM_ARRAY( -- 20X20 grid
SDO_DIM_ELEMENT('X', 0, 20, 0.005),
SDO_DIM_ELEMENT('Y', 0, 20, 0.005)
),
NULL -- SRID
);

建立空間索引:
CREATE INDEX cola_spatial_idx
ON cola_markets(shape)
INDEXTYPE IS MDSYS.SPATIAL_INDEX;
-- Preceding statement created an R-tree index.

這樣在mapguide下就可以preview空間資料資訊.

下面來說一下其中最關鍵的一些object:

( SDO_GEOMETRY物件型別
在Spatial中,地理物件的描述是放在一個單獨的型別為SDO_GEOMETRY的欄位中的。任何有這個欄位的表,都至少要定義一個其它主鍵欄位。

Oracle Spatial定義的SDO_GEOMETRY型別為:
CREATE TYPE sdo_geometry AS OBJECT (
 SDO_GTYPE NUMBER,
 SDO_SRID NUMBER,
 SDO_POINT SDO_POINT_TYPE,
 SDO_ELEM_INFO SDO_ELEM_INFO_ARRAY,
 SDO_ORDINATES SDO_ORDINATE_ARRAY);

當然Spatial也定義了SDO_POINT_TYPE, SDO_ELEM_INFO_ARRAY, 和
SDO_ORDINATE_ARRAY型別:
CREATE TYPE sdo_point_type AS OBJECT (
   X NUMBER,
   Y NUMBER,
   Z NUMBER);
CREATE TYPE sdo_elem_info_array AS VARRAY (1048576) of NUMBER;
CREATE TYPE sdo_ordinate_array AS VARRAY (1048576) of NUMBER;

因為SDO_ORDINATE_ARRAY最大為1048576,所以SDO_GEOMETRY物件的頂點數量就依賴於它的維度,二維為524288,三維為349525,四維只有262144個頂點了。

注意:

對於一個給定的層(同一欄位),所有的地理物件必須都是相同的維度,不能將二維與三維的資料放在一個層裡。

如果你使用四位的SDO_ETYPE那麼,你也要使用四位的SDO_GTYPE。

)

SDO_GEOMETRY Object Type
2.1 SDO_GTYPE  dltt
    d:維數
    l:linear referencing system (LRS)
    tt:Geometry type
    00 UNKNOWN_GEOMETRY
    01 POINT
    02 LINE or CURVE
    03 POLYGON
    04 COLLECTION
    05 MULTIPOINT
    06 MULTILINE or MULTICURVE
    07 MULTIPOLYGON
2.2 SDO_SRID
    確認coordinate system,此值為SDO_COORD_REF_SYS表中的SRID值。此值也被插入到USER_SDO_GEOM_METADATA檢視中。
2.3 SDO_POINT
    (1)SDO_ELEM_INFO and SDO_ORDINATES are both null
    (2)SDO_POINT attribute is non-null
    結論:儲存座標
2.4 SDO_ELEM_INFO
    用來解釋儲存在SDO_ORDINATES屬性中的座標資訊。
    SDO_STARTING_OFFSET:SDO_ORDINATES中的offset min為1
    SDO_ETYPE: 1, 2, 1003, and 2003 simple elements; 3 polygon ring; 4, 1005, and 2005 compound elements
    SDO_INTERPRETATION
2.5 SDO_ORDINATES
    長陣列,存放空間物件的座標
2.6 Usage Considerations
    SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT 用來檢查幾何物件的一致性。

1.1 SDO_GEOMETRY欄位詳解
Oracle Spatial的空間資料都儲存在空間欄位sdo_Geometry中,理解sdo_Geometry是編寫Oracle Spatial程式的關鍵。sdo_Geometry是按照Open GIS規範定義的一個物件,其原始的建立方式如下所示:

CREATE TYPE sdo_geometry AS OBJECT (
SDO_GTYPE NUMBER,
SDO_SRID NUMBER,
SDO_POINT SDO_POINT_TYPE,
SDO_ELEM_INFO SDO_ELEM_INFO_ARRAY,
SDO_ORDINATES SDO_ORDINATE_ARRAY);
該物件由五個部分組成,各部分的意義如下表所示:
欄位名
 型別
 描述
 
SDO_GTYPE
 NUMBER
 幾何物件的型別
 
SDO_SRID
 NUMBER
 幾何物件的座標系
 
SDO_POINT
 SDO_POINT_TYPE
 表示幾何型別為點的幾何物件
 
 

SDO_ELEM_INFO
 

SDO_ELEM_INFO_ARRAY
 是一個可變長度的陣列,每3個數作為一個元素單位,用於解釋座標是如何儲存在SDO_ORDINATES中的
 
 

SDO_ORDINATES
 

SDO_ORDINATE_ARRAY
 是一個可變長度的陣列,用於儲存幾何物件的真實座標,該陣列的型別為NUMBER型
 


表1.1.1  sdo_geometry 各組成部分的意義
① SDO_GTYPE
是一個NUMBER型的數值,用來定義儲存幾何物件的型別。SDO_GTYPE是一個4個數字的整數,其格式為dltt,其中d表示幾何物件的維數;l表示三維線性參考系統中的線性參考值,當d為3維或者4維時需要設定該值,一般情況下為空;tt為幾何物件的型別,Oracle Spatial定義了7種類型的幾何型別,目前,tt使用了00到07,其中08到99是Oracle Spatial保留的數字,以備將來幾何物件擴充套件所用。下表描述了Oracle Spatia1支援的幾何物件型別。
數值    幾何型別        描述
DL00                    用於存放自定義型別的幾何物件
DL01    點              幾何物件包含一個點
DL02    直線或曲線      幾何物件由直線或曲線段組成
DL03    多邊形          幾何物件包含一個多邊形,該多邊形可以含有洞
DL04    複合形狀集      點、線、多邊形超集,可包含所有型別
DL05    複合點          幾何物件由一個點或多個點組成
DL06    複合線或曲線    幾何物件由一條線或多條線組成
DL07    複合多邊形      幾何物件可以包含多個外環、多個不相交的多邊形
DL08 - 99               Oracle Spatial 暫且保留
表1.1.2  Oracle Spatia1支援的幾何物件型別

② SDO_SRID
SDO_SRID也是一個NUMBER型的數值,它用於標識與幾何物件相關的空間座標系。如果SDO_SRID為空(null),則表示沒有座標系與該幾何物件相關;如果該值不為空,則該值必須為MDSYS.CS_SRS表中SRID欄位的一個值,在建立含有幾何物件的表時,這個值必須加入到描述空間資料表元資料的USER_SDO_GEOM_METADATA檢視的SRID欄位中。對於我們通常使用國際標準的Longitude/Latitude(8307),Oracle Spatial規定,一個幾何欄位中的所有幾何物件都必須為相同的SDO_SRID值。

③ SDO_POINT
SDO_POINT是一個包含三維座標X,Y,Z數值資訊的物件,用於表示幾何型別為點的幾何物件。如果SDO_ELEM_INFO和SDO_ORDINATES陣列都為空,則SDO_POINT中的X,Y,Z為點物件的座標值,否則,sdo_Point的值將被忽略(用NULL表示)。Oracle Spatial強烈要求用SDO_POINT儲存空間實體為點型別空間資料,這樣可以極大的優化Oracle Spatial的儲存效能和查詢效率。

④ SDO_ELEM_INFO
SDO_ELEM_INFO是一個可變長度的陣列,每3個數作為一個元素單位,用於表示座標是如何儲存在SDO_ORDINATES陣列中的。本文把組成一個元素的3個數稱為3元組。一個3元組包含以下3部分的內容:
◇ SDO_STARTING_OFFSET
SDO_STARTING_OFFSET 表明每個幾何元素的第一個座標在SDO_ORDINATES陣列中的儲存位置。它的值從1開始,逐漸增加。
◇ SDO_ETYPE
SDO_ETYPE 用於表示幾何物件中每個組成元素的幾何型別。當它的值為1, 2, 1003和2003時,表明這個幾何元素為簡單元素。如果SDO_ETYPE為1003,表明該多邊形為外環(第一個數為1表示外環),座標值以逆時針儲存;如果SDO_ETYPE為2003,表明該多邊形為內環(第一個數為2表示內環),座標值以順時針儲存。當SDO_ETYPE為4, 1005和2005時,表明這個幾何元素為複雜元素。它至少包含一個3元組用以說明該複雜元素具有多少個幾何簡單元素。同樣,1005表示多邊形為外環,座標值以逆時針儲存;2005表示多邊形為內環,座標值以順時針儲存。
◇ SDO_INTERPRETATION
SDO_INTERPRETATION具有兩層含義,具體的作用由SDO_ETYPE是否為複雜元素決定。如果SDO_ETYPE是複雜元素(4, 1005和2005),則SDO_INTERPRETATION表示它後面有幾個子3元組屬於這個複雜元素。如果SDO_ETYPE是簡單元素(1, 2, 1003和2003),則SDO_INTERPRETATION表示該元素的座標值在SDO_ORDINATES中是如何排列的。
需要注意的是,對於複雜元素來說,組成它的子元素是連續的,一個子元素的最後一個點是下一個子元素的起點。最後一個子元素的最後一個座標要麼與下一個元素的SDO_STARTING_OFFSET值減1所對應的座標相同,要麼是整個SDO_ORDINATES陣列的最後一個座標。SDO_ETYPE和SDO_INTERPRETATION之間的關係如下表:

SDO_ETYPE        SDO_INTERPRETATION           描述說明
0                任意值                       用於自定義型別,Oracle Spatial不支援

1                1                            點型別

1                n > 1                        具有n個點的點集合

2                1                            由直線段組成的線串

2                2                            由弧線段組成的線串,一個弧線段由起點、弧線上任意一點和終點組成,相鄰兩個弧線段的接點只需要儲存一次

1003
2003             1                            由直線段組成的多邊形,起點和終點必須相同

1003
2003             2                            由弧線段組成的多邊形,起點和終點必須相同。一個弧線段由起點、弧線上任意一點和終點組成,相鄰兩個弧線段的接點只需要儲存一次

1003
2003             3                            矩形:由左下角和右上角兩點確定

1003
2003             4                            圓:由圓周上的三個點組成

4                n >1                         由直線段和弧線段組成的複合線,n表示複合線的相鄰子元素的個數,子元素的SDO_ETYPE必須為2,一個子元素的最後一點是下一子元素的第一個點,並且該點不能重複

1005
2005             n >1                         由直線段和弧線段組成的複合多邊形,n表示複合線的相鄰子元素的個數,子元素的SDO_ETYPE必須為2,一個子元素的最後一點是下一子元素的第一個點,並且該點不能重複。多邊形的起點和終點必須相同

表1.1.3  SDO_ETYPE和SDO_INTERPRETATION 的組合關係

⑤ SDO_ORDINATES
SDO_ORDINATES是一個可變長度的陣列,用於儲存幾何物件的實際座標,是一個最大長度為1048576,型別為Number的陣列。
SDO_ORDINATES必須與sdo_Elem_Info陣列配合使用,才具有實際意義。SDO_ORDINATES的座標儲存方式由幾何物件的維數決定,如果幾何物件為二維,則SDO_ORDINATES的座標以{ x1, y1, x2, y2, …}順序排列,如果幾何物件為三維,則SDO_ORDINATES的座標以{x1, y1, z1, x2, y2, z2, …}的順序排列。
例項說明
下面用例項來進一步說明SDO_GEOMETRY物件的使用方法。

① 一個帶洞的多邊形

• SDO_GTYPE = 2003,表示幾何物件是一個二維的多邊形。
• SDO_SRID = NULL,在二維情況下不需設定線性參考值。
• SDO_POINT = NULL,表示幾何物件不是點型別。
• SDO_ELEM_INFO = (1,1003,1, 19,2003,1),有兩個三元組元素(1,1003,1) 和(19,2003,1),按照先後順序,在(1,1003,1)中,“1”表示該子元素的起點為SDO_ORDINATES陣列中的第1個值,“1003”表示該元素為多邊形外環,“1”表示該多邊形由直線組成;在(19,2003,1)中,“19”表示該子元素的起點為SDO_ORDINATES陣列中的第15個值,“2003”表示該元素為多邊形內環,“1”表示該多邊形由直線組成。
• SDO_ORDINATES = (2,4, 4,3, 10,3, 13,5, 13,9, 11,13, 5,13, 2,11, 2,4,
7,5, 7,10, 10,10, 10,5, 7,5)。外環座標以逆時針排列,內環座標以順時針排列。

② 一個直線段與弧線段組成的複合線串

• SDO_GTYPE = 2002,表示幾何物件是一個二維的線串。
• SDO_SRID = NULL,在二維情況下不需設定線性參考值。
• SDO_POINT = NULL,表示幾何物件不是點型別。
• SDO_ELEM_INFO = (1,4,2, 1,2,1, 3,2,2),有三個三元組元素(1,4,2)(1,2,1) 和(3,2,2),按照先後順序,(1,4,2)表示該線串為複合線串,它由下面兩個三元組描述的子元素組成;在(1,2,1)中,“1”表示該子元素的起點為SDO_ORDINATES陣列中的第1個值,“2”表示該元素為線,“1”表示這段線由直線組成;在(3,2,2)中,“3”表示該子元素的起點為SDO_ORDINATES陣列中的第3個值,“2”表示該元素為線,“2”表示這段線由弧線段組成。
• SDO_ORDINATES = (10,10, 10,14, 6,10, 14,10),座標(10,14)是直線段和弧線段的連線點,沒有重複儲存。

③ 一個直線段與弧線段組成的複合多邊形
• SDO_GTYPE = 2003,表示幾何物件是一個二維的多邊形。
• SDO_SRID = NULL,在二維情況下不需設定線性參考值。
• SDO_POINT = NULL,表示幾何物件不是點型別。
• SDO_ELEM_INFO = (1,1005,2, 1,2,1, 5,2,2),有三個三元組元素(1,2005,2)(1,2,1) 和(5,2,2),按照先後順序,(1,2005,2)表示該多邊形為複合多邊形,它由下面兩個三元組描述的子元素組成;在(1,2,1)中,“1”表示該子元素的起點為SDO_ORDINATES陣列中的第1個值,“2”表示該元素為線,“1”表示這段線由直線組成;在(5,2,2)中,“5”表示該子元素的起點為SDO_ORDINATES陣列中的第5個值,“2”表示該元素為線,“2”表示這段線由弧線段組成。
• SDO_ORDINATES = (6,10, 10,1, 14,10, 10,14, 6,10),座標(14,10)是直線段和弧線段的連線點,沒有重複儲存。
    在Oracle Spatial中,可以運用SQL語句進行幾何資料的各種操作,例如:
建立一個oralce資料庫名為Data1:
Create Table Data1( mktID integer,//第幾號目標
Name char(20),                        //目標名稱
Shape SDO_GEOMETRY                     //目標的空間資料
);
把上例中的複合多邊形插入資料庫Data1:
Insert into Datal values( 1,                      //編號
‘複合多邊形’,                                   //名稱
MDSYS.SDO_GEOME1RY(2003,NULL,NULL,              //空間資料
MDSYS.SDO_ELEM _INFO_ARRAY( 1, 1005, 2, 1, 2, 1, 5, 2, 2 ),
MDSYS.SDO_ORDINATES_ARRAY(6,10, 10,1, 14,10, 10,14, 6,10)
);