3

元の問題は、セット内のポイントの1つが特定のポリゴン内にあるかどうかを調べようとしていたことでした。結果が得られなかったので、最も単純なケースに減らしましたが、それでも結果は得られませんでした。

ポリゴン ジオメトリは次のようになります (座標の中心にある小さな四角形)。

geom1 := SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1),     
SDO_ORDINATE_ARRAY(10,10, 10,-10, -10,-10, -10,10))

ポイント[0,0]がSDO_RELATEを使用してそのポリゴン内にあるかどうかを調べようとしていました。

sdo_relate(geom1, 
        SDO_GEOMETRY('MULTIPOINT((0 0))',8307),
       'mask=anyinteract')

Oracleのドキュメントanyinteractによると:

ANYINTERACT: オブジェクトはばらばらではありません。

多角形の内側の点は、明らかにそれと切り離されていません。CONTAINSそのため、別の方法でポイントを初期化し、座標とすべてをチェックしてから、代わりにそこに配置しようとしてANYINTERACT最終的に目的の出力を取得するのに約1時間費やしました。

だから私の質問は:

  • これはバグですか?containsパラメータは明らかにより厳密です。anyinteract
  • セット内のポイントのいずれかがポリゴン内にあるかどうかを確認する最良の方法は何ですか? ここでは、Contains は役に立ちません。ポイントのいずれかが外側にある場合、SDO_RELATE の結果が false になるためです。機能しないよりも適切な交差タイプanyinteractはありません。
4

1 に答える 1

2

まず、ポリゴンの形式が正しくありません: 閉じません。多角形の場合、最後の点は最初の点と一致する必要があります。次のようにしてエラーを検出できます。

SQL> select sdo_geom.validate_geometry_with_context (SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(10,10, 10,-10, -10,-10, -10,10)), 0.05) from dual;

13348 [Element <1>] [Ring <1>]    
1 row selected.

ORA-13348: polygon boundary is not closed

それを修正すると、別のエラーが発生します。

SQL> select sdo_geom.validate_geometry_with_context (SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(10,10, 10,-10, -10,-10, -10,10, 10,10)), 0.05) from dual;

13367 [Element <1>] [Ring <1>]
1 row selected.

ORA-13367: wrong orientation for interior/exterior rings

ポリゴンの場合、ポイントは反時計回りである必要があります。それを修正すると、ポリゴンは正しくなります。

SQL> select sdo_geom.validate_geometry_with_context (SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(10,10, -10,10, -10,-10, 10,-10, 10,10)), 0.05) from dual;

TRUE
1 row selected.

また、クエリは適切に機能します。次に例を示します。

create table t1 (id number, note varchar2(20), geom sdo_geometry);

insert into t1 (id, note, geom) 
values (
 1,
 'Not closed',
 SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1), SDO_ORDINATE_ARRAY(10,10, 10,-10, -10,-10, -10,10))
);

insert into t1 (id, note, geom) 
values (
 2,
 'Wrong orientation',
 SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1), SDO_ORDINATE_ARRAY(10,10, 10,-10, -10,-10, -10,10, 10,10))
);

insert into t1 (id, note, geom) 
values (
 3,
 'Valid',
 SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1), SDO_ORDINATE_ARRAY(10,10, -10,10, -10,-10, 10,-10, 10,10))
);

commit;

insert into user_sdo_geom_metadata (table_name, column_name, diminfo, srid)
values (
  'T1',
  'GEOM', 
  sdo_dim_array (
    sdo_dim_element ('Long',-180,180,0.5),
    sdo_dim_element ('Lat',-90,90,0.5)
  ),
  8307
);
commit;

create index t1_sx on t1 (geom) indextype is mdsys.spatial_index;

テスト テーブルには、ポリゴンの 3 つのバリアントが含まれています。クエリを試してみましょう:

select *
from t1
where sdo_relate(
  geom, 
  SDO_GEOMETRY('MULTIPOINT((0 0))',8307),
  'mask=anyinteract'
) = 'TRUE';

これは正しい結果を返します:有効なポリゴンのみがポイントを含むものとして正しく識別されます:

        ID NOTE                 GEOM(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
---------- -------------------- -------------------------------------------------------------------------------
         3 Valid                SDO_GEOMETRY(2003, 8307, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARRAY(10, 10, -10, 10, -10, -10, 10, -10, 10, 10))

1 row selected.

point-in-polygon の ANYINTERACT と CONTAINS の違いについては、ポリゴンの境界上(より正確には境界の許容範囲内) にあるポイントに影響を与える可能性があります。ANYINTERACT 検索はそれらを返します。CONTAINS/INSIDE 検索はそうではありません。

これは、たとえばポイントをポリゴンに分散させたい場合 (販売地域の顧客ポイントの場所など) に重要であり、一部の顧客の場所のポイントが隣接する地域間の境界にある場合があります。ANYINTERACT 検索では、それらの場所が両方の地域にあることが報告されます。 . INSIDE 検索では、どちらにも含まれていないと報告されます。

最後に、クエリに簡単な構文を使用します。

select *
from t1
where sdo_anyinteract(
  geom, 
  SDO_GEOMETRY('MULTIPOINT((0 0))',8307)
) = 'TRUE';

エラー コード (13348 など) に対応するメッセージを取得する方法に関する情報。私は通常、この手法を使用します。

set serveroutput on
exec dbms_output.put_line(sqlerrm(-13348))

これにより、完全なエラー メッセージが出力されます。マイナス記号を付けてエラーを渡す必要があることに注意してください。

于 2015-05-22T09:07:41.333 に答える