Montag, 8. September 2014

Hoch- und Rechtswert von Geometrien verschieben

Heute erhielt ich die Frage, wie man mittels SQL die Hochwerte von Geometrien z.B. um 100 Meter erhöhen kann.
Die Antwort darauf ist relativ einfach: z.B. mit einer Funktion.
Für die Funktion habe ich mit folgenden Prämissen gearbeitet:
  • Bei den Geometrietypen handelt sich um Linien oder Polygone.
  • Die Geometrien sind zweidimensional.
  • Die Masseinheit für die Verschiebung ist "m".
Der Funktion gebe ich 3 Parameter mit:
  1. Ausgangsgeometrie
  2. Offset für den Rechtswert
  3. Offset für den Hochwert
Der Default für die beiden Offset-Werte ist jeweils 0.
Damit sieht die Funktion dann wie folgt aus:
create or replace function geom_add_offset(
  p_geom sdo_geometry,
  p_offset_east number default 0,               -- Offset für den Rechtswert in Metern
  p_offset_north number default 0               -- Offset für den Hochwert in Metern
) return sdo_geometry deterministic is
  l_geom sdo_geometry := p_geom ;
begin
  for i in 1..p_geom.sdo_ordinates.count loop
    if mod(i,2) = 0 then
    -- Hochwert: 2. Wert in einem Koordinatenpaar
      l_geom.sdo_ordinates(i) := l_geom.sdo_ordinates(i) + p_offset_north;
   else
    -- Hochwert: 1. Wert in einem Koordinatenpaar
      l_geom.sdo_ordinates(i) := l_geom.sdo_ordinates(i) + p_offset_east;
    end if; 
  end loop;
  return l_geom;
end geom_add_offset;
/
Diese Funktion kann ich jetzt in jedes beliebige SQL-Statement einbauen.
Beispielhaft lege ich eine neue Tabelle, welche den Hochwert aller Geometrien um 100 erhöht.
create table geom_tab_with_offset as
select
  id,
  name,
  geom_add_offset(geometry, 0, 100) as geometry
from geom_tab;
Visuell dargestellt sieht das für ein Beispiel-Polygon dann ausschnittsweise so aus:
Mit recht wenig Aufwand lässt sich also die gewünschte Verschiebung direkt mittels SQL in der Datenbank vornehmen.

1 Kommentar:

  1. Eine kleine Erweiterung erlaubt es variabel Punkte, Linien oder Polygone an die Funktion zu übergeben, die dann um den Verschiebevektor verändert zurückgegeben werden.

    create or replace function geom_add_offset(
    p_geom sdo_geometry,
    p_offset_east number default 0, -- Offset für den Rechtswert in Metern
    p_offset_north number default 0 -- Offset für den Hochwert in Metern
    ) return sdo_geometry deterministic is
    l_geom sdo_geometry := p_geom ;
    begin
    --select p_geom.get_GType() into p_gtyp from dual;
    if p_geom.get_GType() in (2,3) then
    BEGIN
    for i in 1..p_geom.sdo_ordinates.count loop
    if mod(i,2) = 0 then
    -- Hochwert: 2. Wert in einem Koordinatenpaar
    l_geom.sdo_ordinates(i) := l_geom.sdo_ordinates(i) + p_offset_north;
    else
    -- Rechtswert: 1. Wert in einem Koordinatenpaar
    l_geom.sdo_ordinates(i) := l_geom.sdo_ordinates(i) + p_offset_east;
    end if;
    end loop;
    END;
    elsif p_geom.get_GType() in (1) then
    BEGIN
    -- Hochwert:
    l_geom.sdo_point.Y := l_geom.sdo_point.Y + p_offset_north;
    -- Rechtswert:
    l_geom.sdo_point.X := l_geom.sdo_point.X + p_offset_east;
    END;
    else
    l_geom := NULL;
    end if;
    return l_geom;
    end geom_add_offset;
    /

    AntwortenLöschen