Найдите точки, используя пространственный Oracle, непосредственно перед полигоном.

У меня много многоугольников и много точек, и я хочу найти такую ​​точку, чтобы при проведении линии между этой точкой и многоугольником она не пересекалась ни с каким другим многоугольником. Поэтому в основном мне нужна точка, которая находится очень близко к многоугольнику, и между ними нет другого многоугольника.

Я попробовал следующий запрос, и он дает мне все точки, пересекаются ли они многоугольником или нет.

SELECT P.POINTLOC from pointTable P WHERE NOT MDSYS.SDO_OVERLAPBDYINTERSECT(P.POINTLOC," +
            "MDSYS.SDO_GEOMETRY(2003,null,null,MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1)," +
"MDSYS.SDO_ORDINATE_ARRAY(4, 226, 150, 254, 164, 240, 191, 212, 176,4,226)))    = 'TRUE'";

Then I tried this query and it gives some correct points but miss a few correct points:

SELECT P.POINTLOC from pointTable P WHERE MDSYS.SDO_WITHIN_DISTANCE(P.POINTLOC," +
            "MDSYS.SDO_GEOMETRY(2003,null,null,MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1)," +
"MDSYS.SDO_ORDINATE_ARRAY(4, 226, 150, 254, 164, 240, 191, 212, 176,4,226)),'distance = 40')    = 'TRUE'";

Может ли кто-нибудь указать, какой пространственный оператор Oracle лучше всего подходит для этой ситуации?


person user16666    schedule 19.11.2014    source источник


Ответы (1)


Похоже, вы ищете реализацию ближайшего соседа — Oracle предоставляет пространственный оператор SDO_NN.

Более подробную информацию можно найти здесь: http://docs.oracle.com/database/121/SPATL/sdo_operat.htm#SPATL1032

Это только продвинет вас вперед, так как найдет ближайшую точку к многоугольнику, но не гарантирует, что между вашей точкой и вашим целевым многоугольником нет многоугольников. Я подозреваю, что если вы хотите убедиться в этом, вам придется проявить творческий подход.

Мой подход был бы таким:

  1. используйте SDO_NN, чтобы получить ближайшую точку или точки
  2. используйте SDO_GEOM.SDO_CENTROID, чтобы найти центр тяжести многоугольника
  3. создать строку SDO_GEOMETRY в запросе/памяти, которая соединяет две точки
  4. используйте это как основу предложения NOT EXISTS, чтобы исключить точки, где многоугольник пересекает эту линию

Что-то вроде следующего непроверенного/не совсем законченного примера, возможно:

SELECT *
FROM points pnt
WHERE sdo_nn(pnt.point, sdo_geometry(your polygon here)) = 'TRUE' -- fill this with your polygon
AND NOT EXISTS (
  SELECT 1
  FROM polygons plg
  WHERE sdo_geom.sdo_intersection(
    plg.polygon
  , sdo_geometry(
      2002
    , NULL -- oracle srid
    , NULL -- point
    , sdo_elem_info_array(1, 2, 1) -- line
    , sdo_ordinate_array(
      , sdo_geom.sdo_centroid(
          sdo_geometry(your polygon here) -- fill this with your polygon
        , 0.05
        ).x
      , sdo_geom.sdo_centroid(
          sdo_geometry(your polygon here) -- fill this with your polygon
        , 0.05 -- tolerance
        ).t
      , pnt.point.sdo_point.x
      , pnt.point.sdo_point.y
      ) -- line between point and polygon centroid
    )
  , 0.05 -- tolerance
  ) = 'TRUE'
) 

В зависимости от вашего набора данных/производительности вы можете сделать это в PL/SQL, используя коллекции или циклы.

Приведенный выше пример немного грубый и готовый, но я надеюсь, что вы уловили суть.

person Ben    schedule 24.11.2014
comment
Одно небольшое замечание: pnt.point.x не будет извлекать X точки. Вам нужно использовать pt.point.sdo_point.x. То же самое для центроида: должно быть ...).sdo_point.x. - person Albert Godfrind; 27.11.2014
comment
Другая проблема, которая у меня есть, связана с использованием центроидов. Линия от точки до центроида многоугольника не совпадает с линией до границы многоугольника (вы можете получить ее, используя SDO_GEOM.SDO_CLOSEST_POINTS). Определенно возможно, что центроид многоугольника виден из точки, но не из многоугольника (определяется кратчайшей линией от точки до многоугольника). В ОП говорится ... между этой точкой и многоугольником рисуется линия, но не указывается, что это за линия: любая линия? Или кратчайшая линия до границы полигона? - person Albert Godfrind; 27.11.2014
comment
Еще одно соображение заключается в том, что OP не указывает, что ему нужна только самая близкая видимая точка к многоугольнику. Если он это сделает, то ваше решение в порядке. Если нет (т. е. ему нужны все точки, видимые из многоугольника), то проблема становится несколько более интенсивной с точки зрения вычислений, поскольку вы больше не можете использовать SDO_NN для минимизации набора результатов. По сути, вы получаете декартово произведение всех точек и всех полигонов, строите линию между каждой парой и используете каждую линию для поиска любых других зданий. ОП говорит о многих, но сколько? 10000 каждого из них означает 100 миллионов случаев! - person Albert Godfrind; 27.11.2014
comment
Все это немного двусмысленно, поэтому я не даю окончательного (или синтаксически правильного) ответа. - person Ben; 29.11.2014
comment
Я согласен с тем, что ОП должен уточнить его / ее потребность. Если задачу можно ограничить поиском только точек на некотором расстоянии от базового многоугольника или только N ближайших точек (как предложил Бен), то ее можно решить с разумной эффективностью. Если такого предела не существует, то эффективное решение становится затруднительным. - person Albert Godfrind; 07.12.2014