У меня есть границы города от переписи, загруженной в базу данных оракула. Я пытаюсь использовать данные для разрешения города и штата на любую широту или долготу. У меня есть заявление sql, чтобы уменьшить города, которые мне нужны для проверки области, однако мне пришлось написать свою собственную функцию pl/SQL, чтобы проверить, существует ли точка в городских пределах. Его алгоритм литья лучей, который я получил от версии ADA, приведенной здесь http://rosettacode.org/wiki/Ray-casting_algorithm. Проблема в том, что полойгон сложный (т. Е. Он имеет формы в форме), алгоритм возвращает неверные результаты. Может ли кто-нибудь предложить способ обойти эту проблему?Рэй-литье с функцией Pl/SQL
Вот Pl/SQL Polygon Функция:
CREATE OR REPLACE PACKAGE Polygons as
type Point is record
(
X number,
Y number
);
type Point_List is table of Point;
type poly_Segment is VARRAY(2) of Point;
type Polygon is TABLE of poly_Segment;
function Get_Point(x number,y number) return Point;
function Create_Polygon (listOfPoints Point_List) return Polygon;
function Is_Inside (pt2Check Point, shape2Check Polygon) return varchar2;
end Polygon;
/
CREATE OR REPLACE package body Polygons as
EPSILON CONSTANT number := 0.00001;
function Get_Point(x number,y number) return Point is
pnt2Rtn Point;
BEGIN
pnt2Rtn.x := x;
pnt2Rtn.y := y;
return pnt2Rtn;
END Get_Point;
function Ray_Intersects_Segment(Who Point, locSec poly_Segment) return Boolean
is
The_Point Point := Who;
Above Point;
Below Point;
M_Red number;
Red_Is_Infinity Boolean := False;
M_Blue number;
Blue_Is_Infinity Boolean := False;
begin
if locSec (1).Y < locSec (2).Y then
Above := locSec (2);
Below := locSec (1);
else
Above := locSec (1);
Below := locSec (2);
end if;
if The_Point.Y = Above.Y or The_Point.Y = Below.Y then
The_Point.Y := The_Point.Y + EPSILON;
end if;
if The_Point.Y < Below.Y or The_Point.Y > Above.Y then
return False;
elsif The_Point.X > Above.X and The_Point.X > Below.X then
return False;
elsif The_Point.X < Above.X and The_Point.X < Below.X then
return True;
else
if Above.X <> Below.X then
M_Red := (Above.Y - Below.Y)/(Above.X - Below.X);
else
Red_Is_Infinity := True;
end if;
if Below.X <> The_Point.X then
M_Blue := (The_Point.Y - Below.Y)/(The_Point.X - Below.X);
else
Blue_Is_Infinity := True;
end if;
if Blue_Is_Infinity then
return True;
elsif Red_Is_Infinity then
return False;
elsif M_Blue >= M_Red then
return True;
else
return False;
end if;
end if;
end Ray_Intersects_Segment;
function Create_Polygon (listOfPoints Point_List) return Polygon is
polyRes Polygon := new Polygon();
Side poly_Segment;
begin
polyRes.extend(listOfPoints.Count);
for I in 1..listOfPoints.Count loop
Side := new poly_Segment();
Side.extend(2);
Side (1) := listOfPoints (I);
--connect connect the lines if its the last item connect back to the first
if I = listOfPoints.COUNT then
Side (2) := listOfPoints (listOfPoints.FIRST);
else
Side (2) := listOfPoints (I + 1);
end if;
polyRes(I) := Side;
end loop;
return polyRes;
end Create_Polygon;
function Is_Inside (pt2Check Point, shape2Check Polygon) return varchar2 is
cnt4Intersect number := 0;
begin
for Side in 1..shape2Check.count loop
if Ray_Intersects_Segment (pt2Check, shape2Check (Side)) then
cnt4Intersect := cnt4Intersect + 1;
end if;
end loop;
if cnt4Intersect mod 2 = 0 then
return 'N';
else
return 'Y';
end if;
end Is_Inside;
end Polygons;
/
Вот ссылка на данные формы http://pastebin.com/yxrftXQn
Я тестирование, чтобы увидеть, если 33.66840, - 87.59806 был в городе (это, но по моей функции его нет)
EDIT Итак, после некоторых исследований я обнаружил, что проблема заключается в том, как я определяю формы многоугольников. Мне нужно было настроить фид данных.
EDIT Возможно ли сохранить пакет Polygon и использовать его SDO_RELATE и по-прежнему повысить эффективность (может ли кто-нибудь предоставить пример кода)?
Вы уверены, что вам нужно заново изобрести это конкретное колесо, а не используя функциональность Oracle Spatial, встроенную в базу данных? –
Для одной своей базы данных оракула 9 для двух пространственных пространств оракула есть собственный продукт и имеет свои собственные ограничения. Посмотрите руководство по покупке https://shop.oracle.com/pls/ostore/product?p1=OracleSpatialandGraph&p2. = & p3 = & p4 = & intcmp = ocom_Oracle_Spatial_and_Graph – Bostwick
Даже Oracle 9i существует подмножество Spatial (называемое Locator), доступное в стандартной версии (см. http://docs.oracle.com/cd/B10501_01/appdev.920/a96630/sdo_locator .htm # i632018). Локатор включает в себя [SDO_RELATE] (http://docs.oracle.com/cd/B10501_01/appdev.920/a96630/sdo_operat.htm#i78531) оператор, который можно использовать для определения того, находится ли точка в многоугольнике. –