您好,欢迎访问一九零五行业门户网

mysql对GIS的支持 & oracle 空间数据库说明

今天下午闲来无事,无意中翻看了一下mysql的手册,以前总是很有针对性的查阅手册的内容,重点都是放在了sql语句的一些基本细节、mysql的性能参数、存储控制的管理等方面,但是今天无意中发现了一个mysql的重要特点,那就是mysql对gis相关的空间数据也有存储
今天下午闲来无事,无意中翻看了一下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)
);
其它类似信息

推荐信息