Oracle Spatial在MDSYS模式下定义了一系列几何类型、函数来支持空间数据的存储和使用,最为人耳熟能详的就是SDO_GEOMETRY这种类型——当然,ArcSDE也可以使用这种类型进行存储。让我们首先来看一下SDO_GEOMETRY的定义:
CREATE OR REPLACE
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,
MEMBER FUNCTION GET_GTYPE
RETURN NUMBER DETERMINISTIC,
MEMBER FUNCTION GET_DIMS
RETURN NUMBER DETERMINISTIC,
MEMBER FUNCTION GET_LRS_DIM
RETURN NUMBER DETERMINISTIC)
ALTER TYPE SDO_GEOMETRY
ADD MEMBER FUNCTION GET_WKB RETURN BLOB DETERMINISTIC,
ADD MEMBER FUNCTION GET_WKT RETURN CLOB DETERMINISTIC,
ADD MEMBER FUNCTION ST_CoordDim RETURN SMALLINT DETERMINISTIC,
ADD MEMBER FUNCTION ST_IsValid RETURN INTEGER DETERMINISTIC,
ADD CONSTRUCTOR FUNCTION SDO_GEOMETRY(wkt IN CLOB,
srid IN INTEGER DEFAULT NULL) RETURN SELF AS RESULT,
ADD CONSTRUCTOR FUNCTION SDO_GEOMETRY(wkt IN VARCHAR2,
srid IN INTEGER DEFAULT NULL) RETURN SELF AS RESULT,
ADD CONSTRUCTOR FUNCTION SDO_GEOMETRY(wkb IN BLOB,
srid IN INTEGER DEFAULT NULL) RETURN SELF AS RESULT
CASCADE
其中的SDO_GTYPE属性是一个4位的NUMBER类型对象,这个4位的数字表示了这个几何对象的类型,让我们来看看这4个数字如何来约定几何类型。
这4个数字的形式为“DLTT”,其中D代表维数,可以取值为2、3、4;L代表线性参考,如果没有取值为0;TT代表几何类型,取值为00到09,这00到09的取值也是有讲究的,下表就是不同值对应的几何类型:
DL00 |
UNKNOWN_GEOMETRY |
未知类型 |
DL01 |
POINT |
点 |
DL02 |
LINE or CURVE |
线/曲线 |
DL03 |
POLYGON or SURFACE |
面/曲面 |
DL04 |
COLLECTION |
其它任何几何类型的集合 |
DL05 |
MULTIPOINT |
POINT的集合 |
DL06 |
MULTILINE or MULTICURVE |
LINE or CURVE的集合 |
DL07 |
MULTIPOLYGON or MULTISURFACE |
POLYGON or SURFACE的集合 |
DL08 |
SOLID |
实体,由若干个三维闭合的表面组成 |
DL09 |
MULTISOLID |
SOLID的集合 |
表 1 SDO_GTYPE的约定
SDO_GEOMETRY中的SDO_SRID属性代表了几何对象的坐标系统,它要么是空,要么是一个在SDO_COORD_REF_SYS中定义的SRID值,比如我们最熟悉的4326等等。
SDO_GEOMETRY中的SDO_POINT属性是一个SDO_POINT_TYPE类型的对象,这个类型很简单:
CREATE OR REPLACE
TYPE SDO_POINT_TYPE AS OBJECT (
X NUMBER,
Y NUMBER,
Z NUMBER)
其实,SDO_POINT_TYPE类型对象就代表了一个点,而在SDO_GEOMETRY中,只有当SDO_ELEM_INFO和SDO_ORDINATES属性都为空的时候,这个SDO_POINT属性才会被解析。事实上,从下面我们可以看到,SDO_ELEM_INFO和SDO_ORDINATES属性才是一般存放几何对象的地方。但是,Oracle建议如果是一个空间表中只有点数据,那么使用SDO_POINT进行存储会提高性能。不得不说,Oracle在这个地方的定义实在是有点不太优雅。
SDO_GEOMETRY的SDO_ELEM_INFO和SDO_ORDINATES属性分别是SDO_ELEM_INFO_ARRAY和SDO_ORDINATE_ARRAY类型,这两个类型都是存放NUMBER的数组。SDO_ELEM_INFO和SDO_ORDINATES属性是要配合起来解析的:
SDO_ELEM_INFO指定了在SDO_ORDINATES属性中存储的坐标形式应当如何解释,依次每3个值一组,每个组代表一个“Element”,每组中的3个值分别是: SDO_STARTING_OFFSET、SDO_ETYPE、SDO_INTERPRETATION,SDO_STARTING_OFFSET代表了从SDO_ORDINATES中开始解析的坐标序号;SDO_ETYPE和SDO_INTERPRETATION则配合起来解析(又一对需要配合起来解析属性!):
SDO_ETYPE |
SDO_INTERPRETATION |
含义 |
0 |
任意值 |
不支持的类型,比如曲线和样条曲线 |
1 |
1 |
点 |
1 |
0 |
有向点,除了实际点的坐标,还包含虚拟的指向方向 |
1 |
N>1 |
有n个点的点集 |
2 |
1 |
直线 |
2 |
2 |
圆弧构成的多段线,1、2、3点构成第一个圆弧,3、4、5点构成第二个圆弧… |
1003或2003 |
1 |
多边形,最后一个点必须和第一个点相同以闭合 |
1003或2003 |
2 |
圆弧构成的多边形,1、2、3点构成第一个圆弧,3、4、5点构成第二个圆弧… |
1003或2003 |
3 |
矩形,包含两个点:左下角和右上角 |
1003或2003 |
4 |
圆形,包含3个在圆上的点 |
4 |
N>1 |
复合线,有些线段是直线,有些线段是圆弧 |
1005或2005 |
N>1 |
复合多边形,有些线段是直线,有些线段是圆弧 |
表 2 SDO_ELEM_INFO的含义
SDO_ORDINATES属性相对就简单一点了,它就是记录所有点坐标的数组,具体如何解析和SDO_ETYPE有关,注意,对于多边形来说,外环坐标点应按逆时针排列,内环坐标点应按顺时针排列,且都需要闭合。Btw:SDO_ORDINATE的最大大小为1,048,576,因此,一个SDO_GEOMETRY对象最大的顶点数: 二维点524,288个,三维点349,525个,四维点262,144个。
OK,到此为止,Oracle Spatial对于SDO_GEOMETRY类型的描述算是基本结束了,是不是有点让你感到混沌、还带上一点战战兢兢的感觉?希望下面的这个图可以让你稍微减轻一点这种感觉:
图 1 SDO_GEOMETRY的描述