zoukankan      html  css  js  c++  java
  • 空间数据类型与元数据

    空间数据类型与元数据

     Oracle Spatial由一坨的对象数据类型,类型方法,操作子,函数与过程组合而成。一个地理对象作为一个SDO_GEOMETRY对象保存在表的一个字段里。空间索引则由普通的DDL和DML语句来建立与维护。
     本章主要说了一些例子演示如何建立,查询,索引空间数据。
    2.1 简单的插入,索引与查询空间数据例子
     本节演示一个很简单建立空间表,插入,建立索引,查询数据的过程。
     场景是一个软饮料公司,用地理信息来表示他们的产品(可乐)在各个地区的情况。这些情况可以是:市场份额,竞争压力,增长潜力等等。而地区可以是邻近的市,州,省或国家。
     我们要作的是:
     1.建立一个表(COLA_MARKETS)来保存空间数据
     2.插入四个(cola_a, cola_b, cola_c, cola_d)地区的数据
     3.升级USER_SDO_GEOM_METADATA视图来反正这些地区的维度信息
     4.建立空间索引(COLA_SPATIAL_IDX)
     5.进行一些空间查询

    Example 2¨C1Simple Example: Inserting,Indexing, and Querying Spatial Data
    -- Create a table for cola (soft drink) markets in a
    --
     given geography (such as city or state).
    --
     Each row will be an area of interest for a specific
    --
     cola (for example, where the cola is most preferred
    --
     by residents, where the manufacturer believes the
    --
     cola has growth potential, and so on).
    --
     (For restrictions on spatial table and column names, see 
    --
     Section2.6.1 and Section2.6.2.)
    CREATE TABLE cola_markets (
      mkt_id 
    NUMBER PRIMARY KEY,
      name 
    VARCHAR2(32),
      shape SDO_GEOMETRY);
    -- The next INSERT statement creates an area of interest for 
    --
     Cola A. This area happens to be a rectangle.
    --
     The area could represent any user-defined criterion: for
    --
     example, where Cola A is the preferred drink, where
    --
     Cola A is under competitive pressure, where Cola A
    --
     has strong growth potential, and so on.
     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,15,7-- only 2 points needed to
              -- define rectangle (lower left and upper right) with
              -- Cartesian-coordinate data
      )
    );
    -- The next two INSERT statements create areas of interest for 
    --
     Cola B and Cola C. These areas are simple polygons (but not
    --
     rectangles).
    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,18,18,65,75,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,36,36,54,53,3)
      )
    );
    -- Now insert an area of interest for Cola D. This is a
    --
     circle with a radius of 2. It is completely outside the
    --
     first three areas of interest.
    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,710,98,11)
      )
    );
    ---------------------------------------------------------------------------
    --
     UPDATE METADATA VIEW --
    --
    -------------------------------------------------------------------------
    --
     Update the USER_SDO_GEOM_METADATA view. This is required
    --
     before the Spatial index can be created. Do this only once for each
    --
     layer (that is, table-column combination; here: COLA_MARKETS and SHAPE).
    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'0200.005),
        SDO_DIM_ELEMENT(
    'Y'0200.005)
         ),
      
    NULL   -- SRID
    );
    -------------------------------------------------------------------
    --
     CREATE THE SPATIAL INDEX --
    --
    -----------------------------------------------------------------
    CREATE INDEX cola_spatial_idx
       
    ON cola_markets(shape)
       INDEXTYPE 
    IS MDSYS.SPATIAL_INDEX;
    -- Preceding statement created an R-tree index.
    --
    -----------------------------------------------------------------
    --
     PERFORM SOME SPATIAL QUERIES --
    --
    -----------------------------------------------------------------
    --
     Return the topological intersection of two geometries.
    SELECT SDO_GEOM.SDO_INTERSECTION(c_a.shape, c_c.shape, 0.005)
       
    FROM cola_markets c_a, cola_markets c_c 
       
    WHERE c_a.name = 'cola_a' AND c_c.name = 'cola_c';
    -- Do two geometries have any spatial relationship?
    SELECT SDO_GEOM.RELATE(c_b.shape, 'anyinteract', c_d.shape, 0.005)
      
    FROM cola_markets c_b, cola_markets c_d
      
    WHERE c_b.name = 'cola_b' AND c_d.name = 'cola_d';
    -- Return the areas of all cola markets.
    SELECT name, SDO_GEOM.SDO_AREA(shape, 0.005FROM cola_markets;
    -- Return the area of just cola_a.
    SELECT c.name, SDO_GEOM.SDO_AREA(c.shape, 0.005FROM cola_markets c 
       
    WHERE c.name = 'cola_a';
    -- Return the distance between two geometries.
    SELECT SDO_GEOM.SDO_DISTANCE(c_b.shape, c_d.shape, 0.005)
       
    FROM cola_markets c_b, cola_markets c_d
       
    WHERE c_b.name = 'cola_b' AND c_d.name = 'cola_d';
    -- Is a geometry valid?
    SELECT c.name, SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(c.shape, 0.005)
       
    FROM cola_markets c WHERE c.name = 'cola_c';
    -- Is a layer valid? (First, create the results table.)
    CREATE TABLE val_results (sdo_rowid ROWID, result VARCHAR2(2000));
    CALL SDO_GEOM.VALIDATE_LAYER_WITH_CONTEXT(
    'COLA_MARKETS''SHAPE'
    'VAL_RESULTS'2);
    SELECT * from val_results;

     2.2 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个顶点了。

    2.2.1 SDO_GTYPE
    SDO_GTYPE属性声明了地理对象的类型。它由四位数据组成dltt:
    1.d表明了维度
    2.l定义了LRS(这个没看懂,在第七章会说,到时候再说)
    3.tt定义了地理对象的类型00至07,08和99保留
    dl00:未知的地理类型,Spatial会无视这个类型的地理对象
    dl01:点对象,地理对象包含一个点
    dl02:线或曲线,地理对象可以包含直线与曲线
    dl03:多边形, 地理对象可以包含有洞或无洞的多边形,对于有洞的多边形,先是描述外边,然后再描述内边
    dl04:集合,地理对象为不同类型的集合
    dl05:多点,地理对象是多个点的集合
    dl06:多线或多曲线,地理对象有一或更多的线或曲线集合
    dl07:多多边形,地理对象有多个不相交的多边形组成

    对于一个给定的层(同一字段),所有的地理对象必须都是相同的维度,不能将二维与三维的数据放在一个层里。

    2.2.2 SDO_SRID
    SDO_SRID属性定义了空间坐标参考系统。如果SDO_SRID为null,则没有指定坐标系统,如果SDO_SRID不为null,那么它的值必须在SDO_COORD_REF_SYS表中,而且它的值必须插入USER_SDO_GEOM_METADATA视图中。

    2.2.3 SDO_POINT
    SDO_POINT属性定义为SDO_POINT_TYPE类型,它是X,Y,Z之类的数字组成。如果SDO_ELEM_INFO与SDO_ORDINATES数组都为NULL,并且SDO_POINT属性不为null,那么会被缺省认为是点对象。其它情况下,SDO_POINT会被Spatial所忽略。如果这个层只有点对象,那么推荐你将其保存在SDO_POINT属性中。

    2.2.4 SDO_ELEM_INFO
    SDO_ELEM_INFO属性定义要如何理解SDO_ORDINATES属性。
    每三个数字为一组
    1.SDO_STARTING_OFFSET:声明了第一个坐标在SDO_ORDINATES数组中的位置。位置开始于1而不是0。因此,第一个元素的第一个坐标是SDO_GEOMETRY.SDO_ORDINATES(1).
    2.SDO_ETYPE:声明元素的类型:
     1,2,1003,2003:被认为是简单元素,它们由SDO_ELEM_INFO数组的单个三值对定义。对于1003与2003来说:1003为外多边形环(以逆时针顺序),2003为内多边形环(以顺时针顺序),如果你使用四位的SDO_ETYPE那么,你也要使用四位的SDO_GTYPE。
     4,1005,2005:被认为是组合元素。这些组合元素是连续,上一个的结尾点是下一个元素的开始点。而且点不重复
    2.SDO_INTERPRETATION:表示的意思依赖地SDO_ETYPE是否是组合元素。如果SDO_ETYPE不是组合元素(1,2,1003,2003),那么这个属性决定了元素坐标队列的翻译顺序。如下:
    SDO_TYPE SDO_INTERPRETATION MEANING
    0  any number   不支持
    1  1    点类型
    1  9    有方法的点
    1  n > 1    N个点的集合
    2  1    由直线段组成的线段
    2  2    由曲线组成的线段
          每一曲线段由三个点来描述:起点,任意在曲线段上的一点,终点,前一个终点是下一个的起点。
    1003or2003 1    由直线段组合的多边形,最后一点要与第一个点相同
    1003or2003 2    由曲线组合的多边形,最后一点要与第一个点相同
    1003or2003 3    矩形,由左下至右上的两个点描述的矩形。
    1003or2003 4    圆,由三个非共线的点进行描述
    4  n > 1    由直线与曲线组合的线段,N描述了多少个点组成一个线段
    1005or2005 n > 1    由直线与曲线组合的多边形

    2.2.5 SDO_ORDINATES
    这个属性就是一个1048576长的数组,保存了地理对象的坐标。对于三维数据,空间索引将对Z轴无视。这个数组中的数据必须都有效。

    2.2.6 使用条件:
    Spatial并不去检查地理对象数据的完整性,对于不合规则的数据,它只是将期忽略。当然,可以使用SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT函数来进行检查。

    2.3 SDO_GEOMETRY中的方法
    SDO_GEOMETRY类型有自己的方法,可以使用它们来得到SDO_GEOMOTRY中的一些信息:
    Get_Dims Number  返回对象的维度与ST_CoordDim返回相同的结果
    Get_GType Number  返回对象的类型
    Get_LRS_Dim Number  返回对象使用LRS地理坐标系统
    Get_WKB BLOB  返回众所周知的二进制(WKB)的地理对象
    Get_WKT CLOB  返回众所周知的文本(WKT)格式的地理对象
    ST_CoordDim Number  返回坐标维度
    ST_IsValid Number  如果地理对象有效返回0,否则返回1,这个方法使用0.001作为公差,使用SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT函数来指定其它的公差值。

    ELECT c.shape.Get_Dims()
      
    FROM cola_markets c WHERE c.name = 'cola_b';
     
    C.SHAPE.GET_DIMS()                                                              
    ------------------                                                              
                     2                                                              
     
    SELECT c.shape.Get_GType()
      
    FROM cola_markets c WHERE c.name = 'cola_b';
     
    C.SHAPE.GET_GTYPE()                                                             
    -------------------                                                             
                      3                                                             
     
    SELECT a.route_geometry.Get_LRS_Dim()
      
    FROM lrs_routes a WHERE  a.route_id = 1;
     
    A.ROUTE_GEOMETRY.GET_LRS_DIM()                                                  
    ------------------------------                                                  
                                 3 
    SELECT c.shape.Get_WKT()
      
    FROM cola_markets c WHERE c.name = 'cola_b';
     
    C.SHAPE.GET_WKT()                                                               
    --------------------------------------------------------------------------------
    POLYGON ((5.0 1.08.0 1.08.0 6.05.0 7.05.0 1.0))                         

    SELECT c.shape.ST_CoordDim()
      
    FROM cola_markets c WHERE c.name = 'cola_b';
     
    C.SHAPE.ST_COORDDIM()                                                           
    ---------------------   

    SELECT c.shape.ST_IsValid()
      
    FROM cola_markets c WHERE c.name = 'cola_b';
     
    C.SHAPE.ST_ISVALID()                                                            
    --------------------                                                            
                       1 

     2.4 SDO_GEOMETRY的构造函数
    SDO_GEOMETRY对象的构造函数可以使用WKT与WKB来建立。
    SDO_GEOMETRY(wkt CLOB, srid NUMBER DEFAULT NULL);
    SDO_GEOMETRY(wkt VARCHAR2, srid NUMBER DEFAULT NULL);
    SDO_GEOMETRY(wkb BLOB, srid NUMBER DEFAULT NULL);
    SRID值必须与表中同字段的其它的SRID相同
    SELECT SDO_GEOMETRY('POINT(-79 37)') FROM DUAL;
     
    SDO_GEOMETRY('POINT(-7937)')(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_I
    --------------------------------------------------------------------------------
    SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(-79, 37, NULL), NULL, NULL)
    例子:
    DECLARE
      cola_b_wkb  BLOB;
      cola_b_wkt_clob  CLOB;
      cola_b_wkt_varchar  VARCHAR2(255);
      cola_b_geom  SDO_GEOMETRY;
    BEGIN
    -- Get cola_b geometry into CLOB, VARCHAR2, and BLOB objects,
    -- for use by the constructor.
    SELECT c.shape.Get_WKT() INTO cola_b_wkt_clob
      FROM cola_markets c WHERE c.name = 'cola_b';
    cola_b_wkt_varchar := cola_b_wkt_clob;
    SELECT c.shape.Get_WKB() INTO cola_b_wkb
      FROM cola_markets c WHERE c.name = 'cola_b';
    -- Use some SDO_GEOMETRY constructors;
    -- insert 3 geometries into the table; display the geometries later.
    cola_b_geom := SDO_GEOMETRY(cola_b_wkt_clob);
    INSERT INTO cola_markets VALUES (101, 'cola_b_from_clob', cola_b_geom);
    cola_b_geom := SDO_GEOMETRY(cola_b_wkt_varchar);
    INSERT INTO cola_markets VALUES (102, 'cola_b_from_varchar', cola_b_geom);
    cola_b_geom := SDO_GEOMETRY(cola_b_wkb);
    INSERT INTO cola_markets VALUES (103, 'cola_b_from_wkb', cola_b_geom);
    END;
    /
     
    PL/SQL procedure successfully completed.
     
    -- Display the geometries created using SDO_GEOMETRY constructors.
    -- All three geometries are identical.
    SELECT name, shape FROM cola_markets WHERE mkt_id > 100;
     
    NAME                                                                           
    --------------------------------                                               
    SHAPE(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)   
    --------------------------------------------------------------------------------
    cola_b_from_clob                                                               
    SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARR
    AY(5, 1, 8, 1, 8, 6, 5, 7, 5, 1))                                              
                                                                                   
    cola_b_from_varchar                                                            
    SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARR
    AY(5, 1, 8, 1, 8, 6, 5, 7, 5, 1))                                              
                                                                                   
    cola_b_from_wkb                                                                
    SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARR
    AY(5, 1, 8, 1, 8, 6, 5, 7, 5, 1))

    2.5 例子大集合
    2.5.1 矩形:SDO_GTYPE = 2003, SDO_SRID = NULL, SDO_POINT = NULL, SDO_ELEM_INFO = (1, 1003, 3), SDO_ORDINATES = (1, 1, 5, 7)
    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
      )
    );
    2.5.2 有洞的多边形:SDO_GTYPE = 2003, SDO_SRID = NULL, SDO_PONT = NULL, SDO_ELEM_INFO = (1,1003,1,19,2003,1)这个声明了两个元素,1,1003,1与19,2003,1,1003表明这是一个外多边形,2003表明这是一个内多边形,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_GEOM.SDO_AREA函数来说,这个面积等于外多边形减内多边形的面积。对于SDO_GEOM.SDO_LENGTH函数来说,边长等于外多边形与内多边形的总和。
    INSERT INTO cola_markets VALUES(
      10,
      'polygon_with_hole',
      SDO_GEOMETRY(2003,  -- two-dimensional polygon
        NULL,
        NULL,
        SDO_ELEM_INFO_ARRAY(1,1003,1, 19,2003,1), -- polygon with hole
        SDO_ORDINATE_ARRAY(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)
      )
    );多边形不能多层嵌套,就是说A中有B,但B中不能再有C了。
    2.5.3 组合线段: SDO_GTYPE = 2002, SDO_SRID = NULL, SDO_POINT = NULL, SDO_ELEM_INFO = (1, 4, 2, 1, 2, 1, 3, 2, 2)这个表明 4,2是说明这个元素是一个组合线段,由两个子元素组成。1,2,1说明这个元素是个直线段,坐标从第一个开始,3,2,2说明第二个元素为曲线,坐标从第三个开始,是个曲线,SDO_ORDINATES=(10,10,10,14,6,10,14,10)

    INSERT INTO cola_markets VALUES(
      11,
      'compound_line_string',
      SDO_GEOMETRY(
        2002,
        NULL,
        NULL,
        SDO_ELEM_INFO_ARRAY(1,4,2, 1,2,1, 3,2,2), -- compound line string
        SDO_ORDINATE_ARRAY(10,10, 10,14, 6,10, 14,10)
      )
    );
    2.5.4 组合多边形:SDO_GTYPE=2003, SDO_SRID=NULL,SDO_POINT=NULL,SDO_ELEM_INFO=(1,1005,2,1,2,1,5,2,2),SDO_ORDINATES=(6,10,10,1,14,10,10,14,6,10)
    INSERT INTO cola_markets VALUES(
      12,
      'compound_polygon',
      SDO_GEOMETRY(
        2003,  -- two-dimensional polygon
        NULL,
        NULL,
        SDO_ELEM_INFO_ARRAY(1,1005,2, 1,2,1, 5,2,2), -- compound polygon
        SDO_ORDINATE_ARRAY(6,10, 10,1, 14,10, 10,14, 6,10)
      )
    );
    2.5.5 点:SDO_GTYPE=2001,SDO_SRID=NULL,SDO_POINT=SDO_POINT_TYPE(12, 14, NULL),SDO_ELEM_INFO=NULL,SDO_ORDINATES=NULL

    INSERT INTO cola_markets VALUES(
       90,
       'point_only',
       SDO_GEOMETRY(
          2001,
          NULL,
          SDO_POINT_TYPE(12, 14, NULL),
          NULL,
          NULL));

    2.5.6 有向点:这是一个特殊的地理对象,它由一个点与一个虚拟的终点组成,它可以表示一个有方向的图标之类的东东。SDO_GTYPE=2001,SDO_SRID=NULL, SDO_POINT = NULL, SDO_ELEM_INFO=(1,1,1,3,1,0),SDO_ORDINATES=(12,14,0.3,0.2), 12,14为点的坐标,0.3,0.2表示相对与起点的角度。
    INSERT INTO cola_markets VALUES(
      91,
    'oriented_point',
      SDO_GEOMETRY(
        2001,
        NULL,
        NULL,
        SDO_ELEM_INFO_ARRAY(1,1,1, 3,1,0),
        SDO_ORDINATE_ARRAY(12,14, 0.3,0.2)));

  • 相关阅读:
    vue 相对其他热门 框架 优点 --- 待续
    vue router 只需要这么几步
    正则表达式
    MySQL数据库优化的八种方式
    Django REST Framework 最佳实践
    Node.js ZLIB
    Node.js 虚拟机
    Node.js 实用工具
    Node.js URL
    Node.js UDP/Datagram
  • 原文地址:https://www.cnblogs.com/frogbag/p/927275.html
Copyright © 2011-2022 走看看