Go to content Go to navigation and search

Home

Current Oracle Spatial Blog Articles


Search

Browse

RSS / Atom

Email me

textpattern

Creative Commons License
All Blog Articles, Data Models and Free Source Code by Simon Greener, The SpatialDB Advisor is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Gridding a sdo_geometry line/polygon object (Oracle)

Tuesday December 20 2011 at 23:06

Keywordsgrid gridding raster vector chopping intersection boundary clip polygon line
Summary

A vector-to-raster algorithm generating tiles covering (multi-)line/polygon geometries. Boundary tiles are clipped forming non-square tiles.

A common question that comes up in the various database forums (PostGIS, SQL Server, Oracle) is how to “grid” a linear or polygonal object.

By “grid” one means work out the square pixels (rectangular polygons) that cover or define a vector geometry.

Here is some SQL for doing this for Oracle Locator.

Single Geometry

Here is a method applied to a single geometry. The function Morton and REGULARGRIDXY are provided in other blog articles or at the end of this article. Note that REGULARGRIDXY is used in order to ensure that the gridding takes place according to a commonly defined MBR.

  1. WITH geomQuery AS (
  2. SELECT sdo_geom.sdo_min_mbr_ordinate(g.geom,1) AS minx,
  3.        round(sdo_geom.sdo_max_mbr_ordinate(g.geom,1),2) AS maxx,
  4.        sdo_geom.sdo_min_mbr_ordinate(g.geom,2) AS miny,
  5.        round(sdo_geom.sdo_max_mbr_ordinate(g.geom,2),2) AS maxy,
  6.        g.geom, 0.050 AS gridX, 0.050 AS gridY, 0 AS loCol, 0 AS loRow
  7.   FROM (SELECT sdo_geom.sdo_xor(sdo_geom.sdo_buffer(a.geom,1.000,0.0005),
  8.                                 sdo_geom.sdo_buffer(a.geom,0.500,0.0005),0.0005) AS geom
  9.           FROM (SELECT sdo_geometry('MULTIPOINT((09.25 10.00),(10.75 10.00),(10.00 10.75),(10.00 9.25))',
  10.                                     NULL) AS geom
  11.                   FROM DUAL) a
  12.        ) g
  13. )
  14. SELECT f.mkey,f.gcol,f.grow,f.geom
  15.   FROM (SELECT TESSELATE.Morton(b.gcol - a.loCol, b.grow - a.loRow) AS mKey,
  16.                b.gcol,b.grow,
  17.                CASE WHEN a.geom.get_gtype() IN (3,7)
  18.                     THEN sdo_geom.sdo_Intersection(a.geom,b.geometry,0.005)
  19.                     ELSE a.geom
  20.                 END AS geom
  21.           FROM geomQuery a,
  22.                TABLE(TESSELATE.RegularGridXY(a.minx,a.miny,a.maxx,a.maxy,a.gridX,a.gridY,a.geom.sdo_srid)) b
  23.          WHERE sdo_geom.relate(a.geom,'ANYINTERACT',b.geom,0.0005) = 'TRUE'
  24.        ) f
  25.  WHERE f.geom.get_gtype() IN (3,7) /* Don't want point or line tiles */
  26.  ORDER BY f.mKey;

The result of this looks like.

Multiple Geometries

The following grids multiple geometries into a single logical grid.

  1. -- Multiple features
  2. --
  3. WITH geomQuery AS (
  4. SELECT g.rid,
  5.        MIN(sdo_geom.sdo_min_mbr_ordinate(g.geom,1))          OVER (partition BY g.pid) AS minx,
  6.        MAX(round(sdo_geom.sdo_max_mbr_ordinate(g.geom,1),2)) OVER (partition BY g.pid) AS maxx,
  7.        MIN(sdo_geom.sdo_min_mbr_ordinate(g.geom,2))          OVER (partition BY g.pid) AS miny,
  8.        MAX(round(sdo_geom.sdo_max_mbr_ordinate(g.geom,2),2)) OVER (partition BY g.pid) AS maxy,
  9.        CODESYS.GEOM.ROUNDORDINATES(g.geom,3) AS geom,
  10.        0.050 AS gridX, 0.050 AS gridY, 0 AS loCol, 0 AS loRow, g.tol
  11.   FROM (SELECT 1 AS pid, a.rid, t.tol,
  12.                sdo_geom.sdo_xor(sdo_geom.sdo_buffer(a.geom,1.000,t.tol),
  13.                                 sdo_geom.sdo_buffer(a.geom,0.750,t.tol),t.tol) AS geom
  14.           FROM (SELECT 0.00005 AS tol FROM DUAL) t,
  15.                (SELECT 1 AS rid, sdo_geometry('POINT(09.50 10.00)',NULL) AS geom FROM DUAL
  16.       UNION ALL SELECT 2 AS rid, sdo_geometry('POINT(10.50 10.00)',NULL) AS geom FROM DUAL
  17.       UNION ALL SELECT 3 AS rid, sdo_geometry('POINT(10.00 10.50)',NULL) AS geom FROM DUAL
  18.       UNION ALL SELECT 4 AS rid, sdo_geometry('POINT(10.00 09.50)',NULL) AS geom FROM DUAL) a ) g
  19. )
  20. SELECT ROW_NUMBER() OVER (ORDER BY f.gcol,f.grow) AS tid,
  21.        TESSELATE.Morton(f.gcol - f.loCol, f.grow - f.loRow) AS mKey,
  22.        f.gcol, f.grow,
  23.        COUNT(*) AS UnionedTileCount,
  24.        sdo_aggr_union(sdoaggrtype(f.geom,f.tol)) AS geom
  25.   FROM (SELECT b.gcol, b.grow, a.loCol, a.loRow, a.tol,
  26.                CASE WHEN a.geom.get_gtype() IN (3,7)
  27.                     THEN sdo_geom.sdo_Intersection(a.geom,b.geometry,0.005)
  28.                     ELSE a.geom
  29.                 END AS geom
  30.           FROM geomQuery a,
  31.                TABLE(TESSELATE.RegularGridXY(a.minx,a.miny,a.maxx,a.maxy,a.gridX,a.gridY,a.geom.sdo_srid)) b
  32.          WHERE sdo_geom.relate(a.geom,'ANYINTERACT',b.geom,a.tol) = 'TRUE' ) f
  33.  WHERE f.geom IS NOT NULL
  34.    AND f.geom.get_gtype() IN (3,7) /* Don't want point or line tiles */
  35.  GROUP BY f.gcol,f.grow,f.loCol,f.loRow,f.tol
  36.  ORDER BY 2;

That looks like this.

I hope this is of use to Oracle users.

Creative Commons License

post this at del.icio.uspost this at Diggpost this at Technoratipost this at Redditpost this at Farkpost this at Yahoo! my webpost this at Windows Livepost this at Google Bookmarkspost this to Twitter

Comment