蛮力解决方案的第一次尝试可能如下所示:
CREATE OR REPLACE FUNCTION FILTER_MULTI_POLYGONS
(
udtGeometry IN SDO_GEOMETRY,
udtMask IN SDO_GEOMETRY,
dTolerance IN NUMBER
)
RETURN SDO_GEOMETRY
AS
iElements INTEGER;
udtElement SDO_GEOMETRY;
udtResult SDO_GEOMETRY := NULL;
iCount INTEGER;
BEGIN
IF udtGeometry IS NOT NULL THEN
iElements := SDO_UTIL.GETNUMELEM(udtGeometry);
FOR iElement IN 1..iElements
LOOP
udtElement := SDO_UTIL.EXTRACT(udtGeometry, iElement);
IF SDO_GEOM.SDO_DISTANCE(udtElement, udtMask, dTolerance) <= dTolerance THEN
IF udtResult IS NULL THEN
udtResult := udtElement;
ELSE
udtResult := SDO_UTIL.APPEND(udtResult, udtElement);
END IF;
END IF;
END LOOP;
END IF;
RETURN udtResult;
END;
我说蛮力是因为:
各个子多边形未编入索引,因此此解决方案不利用空间索引。如果性能足够重要,则可能值得将您的多多边形分解为其构成的子多边形(每个子多边形在源表中有一行),以便您可以使用利用空间索引的不同解决方案。您可以在前面(通过更改源表的设计)或在幕后(可能使用基于原始表的物化视图)执行此操作。
看起来您使用的是 Oracle XE,因此仅限于 Oracle Spatial 功能的定位器子集。
第 1 项和第 2 项意味着确定哪些子多边形与蒙版交互的唯一内置选择似乎是通过 SDO_GEOM.SDO_DISTANCE。这将是资源密集型的(因为它将为每个子多边形调用),并且只为您提供一种类型的交互,而不是使用内置空间运算符(依赖于空间索引)可能实现的许多交互。
SDO_UTIL.APPEND 可能不是构建“过滤”多面体结果的最高效(或正确,特别是如果您的多面体不是不相交的)方式,但它说明了这个概念。
无论如何,这就是我对一些示例蒙版运行您的示例几何图形的结果。您应该确保该函数针对您的真实几何图形返回预期结果。
SQL> REM Example mask that overlaps first polygon only
SQL> SELECT
2 FILTER_MULTI_POLYGONS
3 (
4 T1.G,
5 SDO_GEOMETRY
6 (
7 2003,
8 NULL,
9 NULL,
10 SDO_ELEM_INFO_ARRAY(1, 1003, 3),
11 SDO_ORDINATE_ARRAY(0, 0, 53, 96)
12 ),
13 0.1
14 ) AS RESULT
15 FROM T1;
RESULT(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
--------------------------------------------------------------------------------
SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARR
AY(50, 95, 55, 95, 53, 96, 55, 97, 53, 98, 55, 99, 50, 99, 50, 95))
SQL> REM Example mask that overlaps second polygon only
SQL> SELECT
2 FILTER_MULTI_POLYGONS
3 (
4 T1.G,
5 SDO_GEOMETRY
6 (
7 2003,
8 NULL,
9 NULL,
10 SDO_ELEM_INFO_ARRAY(1, 1003, 3),
11 SDO_ORDINATE_ARRAY(56, 0, 60, 96)
12 ),
13 0.1
14 ) AS RESULT
15 FROM T1;
RESULT(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
--------------------------------------------------------------------------------
SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARR
AY(55, 100, 55, 95, 60, 95, 60, 100, 55, 100))
SQL> REM Example mask that overlaps both polygons
SQL> SELECT
2 FILTER_MULTI_POLYGONS
3 (
4 T1.G,
5 SDO_GEOMETRY
6 (
7 2003,
8 NULL,
9 NULL,
10 SDO_ELEM_INFO_ARRAY(1, 1003, 3),
11 SDO_ORDINATE_ARRAY(0, 0, 100, 100)
12 ),
13 0.1
14 ) AS RESULT
15 FROM T1;
RESULT(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
--------------------------------------------------------------------------------
SDO_GEOMETRY(2007, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1, 17, 1003, 1), SDO
_ORDINATE_ARRAY(50, 95, 55, 95, 53, 96, 55, 97, 53, 98, 55, 99, 50, 99, 50, 95,
55, 100, 55, 95, 60, 95, 60, 100, 55, 100))
SQL> REM Example mask that overlaps neither polygon
SQL> SELECT
2 FILTER_MULTI_POLYGONS
3 (
4 T1.G,
5 SDO_GEOMETRY
6 (
7 2003,
8 NULL,
9 NULL,
10 SDO_ELEM_INFO_ARRAY(1, 1003, 3),
11 SDO_ORDINATE_ARRAY(0, 0, 10, 10)
12 ),
13 0.1
14 ) AS RESULT
15 FROM T1;
RESULT(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
--------------------------------------------------------------------------------
希望这可以帮助。