Frage

I've a table with points. I would like to create polygon based on this points and then return only these points which are on perimeter(exclude points which are inside a polygon) . Is there any easy way to do that on database level using SDO GEOMETRY? I find sth like a GrahamScan, but I can't find anything like that for Spatial

War es hilfreich?

Lösung

I can't think of any easy answer with the built-in packages that Oracle supplies. You might have to consider writing some fairly horrible code to do this if you want to solve the problem in Oracle.

A cheesy solution might be to break this into a few steps:

  1. Brute force all possible lines between every set of two points (select the cartesian product of the points, construct these into lines):
  2. Find all lines where there is no intersection with any other line (the outer-most perimeter) and get the point values.
  3. Join the point values back to your original table to retrieve any data (if necessary).

This will likely not perform or scale well, but it should work if your dataset isn't very big.

Here's a quick illustration (untested SQL)...

Inputs:

SELECT sdo_geometry(2001, NULL, sdo_point_type(tbl.x, tbl.y,  NULL), NULL, NULL)
FROM my_table tbl

Inputs to algorithm

Cartesian product of coordinates converted to lines:

WITH point_cartesian AS (
  SELECT 
    tbl.x x1
  , tbl.y y1
  , tbl2.x x2
  , tbl2.y y2
  FROM my_table tbl
  CROSS JOIN my_table tbl2
  WHERE tbl.x != tbl2.x 
  OR tbl.y != tbl2.y
)
SELECT sdo_geometry(
  2002
, NULL
, NULL
, sdo_elem_info_array(1, 2, 1)
, sdo_ordinate_array(x1, y1, x2, y2)
)
FROM point_cartesian

Cartesian product of coordinates converted to lines

Identify desired lines:

WITH point_cartesian AS (
  SELECT 
    tbl.x x1
  , tbl.y y1
  , tbl2.x x2
  , tbl2.y y2
  FROM my_table tbl
  CROSS JOIN my_table tbl2
  WHERE tbl.x != tbl2.x 
  OR tbl.y != tbl2.y
)
, lines AS (
  SELECT sdo_geometry(
    2002
  , NULL
  , NULL
  , sdo_elem_info_array(1, 2, 1)
  , sdo_ordinate_array(x1, y1, x2, y2)
  ) geom
  , ROWNUM line_id
  FROM point_cartesian
)
SELECT *
FROM lines l1
WHERE NOT EXISTS (
  SELECT 1
  FROM lines l2
  WHERE l2.line_id != l1.line_id
  AND sdo_geom.sdo_intersect (l1.geom, l2.geom, 0.05) IS NOT NULL
)

Identify lines

Please note: the SQL is untested, but hopefully you get the idea.

Andere Tipps

If the data is indeed like described in the first answer, then the simplest and fastest method is just to get the convex hull around your set of points. Assuming that your input is table MY_TABLE that contains two columns, X and Y that represent longitude and latitude (hence the SRID of 4326):

select sdo_aggr_convexhull (
         sdoaggrtype (
           sdo_geometry(2001, 4326, sdo_point_type(x, y,  NULL), NULL, NULL),
           0.5
         )
       )
from my_table;

The result is a a polygon constructed using the perimeter points.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top