Mittwoch, 1. Dezember 2010

Locator ich noch oder Spatial ich schon?

Diese Frage stellen sich unsere Kunden immer mal wieder. Und sie zu beantworten, ist zugegebenermassen nicht so ganz einfach.
Deshalb wollen wir hier ein paar Hilfestellungen geben.

Da wäre zunächst einmal die grobe Einteilung in 2D-Vektordaten (Locator) und alles andere (Spatial), wie 3D-Vektordaten, Rasterdaten, Netzwerkdatenmodell, Topologien, Geokodierung, Lineare Bezugssysteme, Routing, Geodienste (ausser WMS), etc.
Was die 2D-Vektordaten betrifft, muss man dann noch mal genauer auf die von Locator unterstützten Features schauen. Diese sind im Detail in Tabelle B-1 im Oracle Spatial Developer’s Guide beschrieben. Was dort nicht aufgeführt ist, statt dessen aber in Tabelle B-2, ist Spatial.

Darüberhinaus kann man auch noch die sogenannte Feature Usage Statistics zu Rate ziehen. Nutzer/-innen mit DBA-Rechten können sich diese wie folgt anzeigen lassen:
select * 
from   dba_feature_usage_statistics 
where  lower(name) like '%locator%' or 
       lower(name) like '%spatial%';
Seit 11gR2 werden Locator und Spatial darin gesondert ausgewiesen.

Dienstag, 30. November 2010

Lauter kleine Helferlein

Heute soll es darum gehen, Geometrien, die nicht Simple Feature-konform sind, soweit möglich zu korrigieren.
Für eine solche Korrektur steht seit 11gR1 die Funktion RECTIFY_GEOMETRY im Package SDO_UTIL bereit, welche die korrigierte (rektifizierte) Geometrie zurückliefert.
Ein Blick in die Oracle Spatial Online-Dokumentation verrät dabei, welche Fehler korrigierbar sind:
  • doppelte Stützpunkte (bezogen auf die Toleranz)
  • sich selbst schneidende Polygone
  • falsche Orientierung von innerem oder/und äusseren Ring(en) eines Polygons
Dort findet sich ebenso das Format beschrieben.
SDO_UTIL.RECTIFY_GEOMETRY(
  geom      IN SDO_GEOMETRY,
  tolerance IN NUMBER
) RETURN SDO_GEOMETRY;

Wie kann man nun diese Funktion in Anwendung bringen? Schauen wir uns das einfach mal genauer an.
Zunächst wird eine Tabelle angelegt, in welcher alle fehlerhaften Geometrien registriert werden sollen.
drop table geometry_errors purge;

-- Fehlertabelle anlegen
create table geometry_errors (
  table_name      varchar2(30),
  column_name     varchar2(30),
  obj_rowid       rowid,
  geometry        sdo_geometry,
  tolerance       number,
  error_code      char(5),
  error_message   varchar2(256),
  error_context   varchar2(256),
  is_fixed        number(1) default 0
);
Die eigentliche Prozedur zum Überprüfen der Geometrien, kann dann wie nachfolgend aussehen. Die problematischen Geometrien darunter werden in die Fehlertabelle übernommen.
-- Prozedur zum Prüfen auf invalide Geometrien im gesamten Schema
-- Achtung: Kann einige Zeit in Anspruch nehmen!
declare
  DEFAULT_TOLERANCE   number := 0.0000005;
  COMMIT_FREQUENCY    number := 100;
  geom_cursor         sys_refcursor;
  v_diminfo           sdo_dim_array;
  v_srid              number;
  v_tolerance         number;
  v_rowid             rowid;
  v_geometry          sdo_geometry;
  v_num_rows          number;
  v_num_errors        number;
  v_error_code        char(5);
  v_error_message     varchar2(256);
  v_error_context     varchar2(256);
  v_status            varchar2(256);
begin

  -- Alle Tabellen mit SDO_GEOMETRY Spalten prozessieren
  for t in (
    select table_name, column_name
    from   user_tab_columns
    where  data_type = 'SDO_GEOMETRY'
    order by table_name, column_name )
  loop
  
    -- Lies Toleranz aus den Metadaten
    begin
      select diminfo, srid into v_diminfo, v_srid
      from user_sdo_geom_metadata
      where table_name = t.table_name
        and column_name = t.column_name;
    exception
      when no_data_found then
        v_diminfo := null;
        v_srid := null;
    end;
 
    -- Bei fehlenden Metadaten, Default-Toleranz annehmen
    if v_diminfo is null then
      v_tolerance := DEFAULT_TOLERANCE;
    else
      v_tolerance := v_diminfo(1).sdo_tolerance;
    end if;
 
    -- Geometrien prozessieren
    v_num_rows := 0;
    v_num_errors := 0;

    open geom_cursor for
      'select rowid,' || t.column_name || ' from ' || t.table_name;
    loop
      v_status := NULL;
   
      -- Hole Geometrie
      fetch geom_cursor into v_rowid, v_geometry;
        exit when geom_cursor%notfound;
      v_num_rows := v_num_rows + 1;
   
      -- Validiere Geometry
      v_status := sdo_geom.validate_geometry_with_context (v_geometry, v_tolerance);
   
      -- Wenn Fehler, dann protokollieren
      if v_status <> 'TRUE' then
   
        -- Fehler hochzählen
        v_num_errors := v_num_errors + 1;
  
        -- Format the error message
        if length(v_status) >= 5 then
          v_error_code := substr(v_status, 1, 5);
          v_error_message := sqlerrm(-v_error_code);
          v_error_context := substr(v_status,7);
        else
          v_error_code := v_status;
          v_error_message := null;
          v_error_context := null;
        end if;
  
        -- Fehler wegschreiben
        insert into geometry_errors (
          table_name,
          column_name,
          obj_rowid,
          geometry,
          tolerance,
          error_code,
          error_message,
          error_context
        )
        values (
          t.table_name,
          t.column_name,
          v_rowid,
          v_geometry,
          v_tolerance,
          v_error_code,
          v_error_message,
          v_error_context
        );
      end if;
   
      -- Commit entsprechend COMMIT_FREQUENCY
      if mod(v_num_rows,COMMIT_FREQUENCY) = 0 then
        commit;
      end if;
    end loop;
  end loop;
  
  -- Finales Commit
  commit;
end;
/
Zu beachten ist dabei, dass das Ausführen der Prozedur eine Weile in Anspruch nehmen kann, je nach Anzahl der zu überprüfenden Geometrien.
Bevor es an die eigentliche Korrektur geht, schauen wir uns zunächst die Fehlertabelle genauer an.
-- Fehler pro Tabelle, Error Code
select table_name, error_code, error_message, count(*)
from geometry_errors
group by table_name, error_code, error_message 
order by table_name, error_code;

-- Fehler pro Error Code, Tabelle
select error_code, error_message, table_name, count(*)
from geometry_errors
group by error_code, error_message, table_name
order by error_code, table_name;

-- Fehlerdetails
select table_name, obj_rowid, is_fixed, error_message, error_context
from geometry_errors
where is_fixed = 0
order by table_name, obj_rowid;
Für die Korrektur wird nun die Funktion SDO_UTIL.RECTIFY_GEOMETRY eingesetzt.
-- Prozedur zum Korrigieren der Geometrien
declare
  -- Fehlerbehandlung für nicht korrigierbare Geometrien
  -- "ORA-13199: the given geometry cannot be rectified"
  cannot_rectify exception;
  pragma exception_init(cannot_rectify, -13199);
  v_geometry_fixed sdo_geometry;

begin
  -- Invalide Geometrien prozessieren
  for e in (
    select rowid, table_name, column_name, obj_rowid, tolerance, geometry
    from geometry_errors
    where is_fixed = 0
    order by table_name, column_name
  )
  loop
    -- Wenn möglich, Geometrie korrigieren mit SDO_UTIL.RECTIFY_GEOMETRY. 
    -- Andernfalls:
    --   In 11.1.0.6: Funktion gibt NULL zurück
    --   In 11.1.0.7 und 11.2: Funktion wirft ORA-13199 Fehler
    begin
      v_geometry_fixed := sdo_util.rectify_geometry (e.geometry, e.tolerance);
    exception
      when cannot_rectify then
        v_geometry_fixed := null;
    end;

    if v_geometry_fixed is not null then
      -- Korrigiere Geometrie
      execute immediate 'update ' || e.table_name || ' set '|| e.column_name || ' = :g where rowid = :r'
        using v_geometry_fixed, e.obj_rowid;

      -- Kennzeichne korrigierte Geometrien in Fehlertabelle mit is_fixed = 1
      update geometry_errors set is_fixed = 1 where rowid = e.rowid;
      -- Alternativ ist auch DELETE möglich
      -- delete from geometry_error where rowid = e.rowid;
    end if;

  end loop;
end;
/
Was wurde korrgiert? Was nicht? Das Ergebnis kann am Ende in der Fehlertabelle überprüft werden.
-- Fehler nach Tabelle, Korrekturstatus und Error Code
select table_name, is_fixed, error_code, error_message, count(*)
from geometry_errors
group by table_name, is_fixed, error_code, error_message 
order by table_name, is_fixed, error_code;

-- Fehler nach Korrekturstatus und Error Code
select is_fixed, error_code, error_message, count(*)
from geometry_errors
group by is_fixed, error_code, error_message
order by is_fixed, error_code;

-- Details
select table_name, obj_rowid, is_fixed, error_message, error_context
from geometry_errors
order by is_fixed, table_name, obj_rowid;
Möglicherweise konnten nicht alle fehlerhaften Geometrien auf diese Weise korrigiert werden, aber ein erster Schritt in Richtung Qualitätsverbesserung ist getan.
Wer die Fehlertabelle nach erfolgter Korrektur nicht mehr benötigt, sollte übrigens nicht vergessen, diese wieder zu entfernen.
drop table geometry_errors purge;

Montag, 22. November 2010

GPX-Dateien nach SDO_GEOMETRY umwandeln

Jüngst habe ich für einen Kollegen einen GPS-Track in die Datenbank geladen. Ich hatte eine .gpx-Datei, die in etwa so aussieht ...
<gpx xmlns="http://www.topografix.com/GPX/1/1" tc2=" ...
   <trk>
       <name>2010-11-16T03:46:55Z</name>
       <trkseg>
           <trkpt lat="51.4799802" lon="7.9678522">
               <ele>270.7484131</ele>
               <time>2010-11-16T03:46:55Z</time>
           </trkpt>
           <trkpt lat="51.4799436" lon="7.9678679">
               <ele>264.0192871</ele>
               <time>2010-11-16T03:47:06Z</time>
           </trkpt>
           <trkpt lat="51.4797696" lon="7.9681059">
               <ele>264.4998779</ele>
               <time>2010-11-16T03:47:12Z</time>
           </trkpt>
           <trkpt lat="51.4797497" lon="7.9681919">
               <ele>264.9805908</ele>
               <time>2010-11-16T03:47:14Z</time>
           </trkpt>
Zunächst hatte ich ein wenig nach Converter-Software gegoogelt, wurde jedoch nicht so recht fündig (komische Lizenzbedingungen, keine Konvertierung nach GML oder KML, sondern nur in andere Formate). Da es aber um eine einfach zu verstehende XML-Datei geht, beschloß ich, mir einfach selbst eine Funktion zu schreiben, welche die Arbeit erledigt. Und hier ist sie ...
create or replace function convert_gpx_to_sdo(
 p_gpxfile in xmltype,
 p_lrs     in number default 0
) return sdo_geometry is
 v_ordinates sdo_ordinate_array := sdo_ordinate_array();
 v_gtype     number;

 v_cnt       pls_integer := 1;

 v_startts   timestamp;
 v_interval  interval day(9) to second;

 c_gpxns     varchar2(200) := 'xmlns="http://www.topografix.com/GPX/1/1"';
begin
 if p_lrs = 1 then
   v_gtype := 3302;
 else
   v_gtype := 2002;
 end if;

 for tp in (
   select
     extractvalue(value(tp), '/trkpt/@lon', c_gpxns) x,
     extractvalue(value(tp), '/trkpt/@lat', c_gpxns) y,
     extractvalue(value(tp), '/trkpt/time', c_gpxns) m
   from table(xmlsequence(extract(p_gpxfile, '//trkpt', c_gpxns))) tp
 ) loop
   if v_cnt = 1 then
     v_startts := to_timestamp(tp.m, 'YYYY-MM-DD"T"HH24:MI:SS"Z"');
   end if;
   if p_lrs = 1 then
     v_ordinates.extend(3);
   else
     v_ordinates.extend(2);
   end if;
   v_ordinates(v_cnt) := tp.x;
   v_cnt := v_cnt + 1;
   v_ordinates(v_cnt) := tp.y;
   v_cnt := v_cnt + 1;
   if p_lrs = 1 then
     v_interval := to_timestamp(tp.m,  'YYYY-MM-DD"T"HH24:MI:SS"Z"') - v_startts;
     v_ordinates(v_cnt) :=
      extract(MINUTE from v_interval) +
      extract(HOUR from v_interval) * 60 +
      extract(SECOND from v_interval) / 60;
     v_cnt := v_cnt + 1;
    end if;
 end loop;

 return sdo_geometry(v_gtype, 8307, null, sdo_elem_info_array(1,2,1), v_ordinates);
end convert_gpx_to_sdo;
/
sho err
Die Funktion nimmt das GPX-File (XMLTYPE) als ersten Parameter entgegen. Der zweite Parameter gibt an, ob eine Linear Referencing-Geometrie zurückgegeben werden soll. Wenn ja, werden die Measures in Minuten gespeichert. Gebt hier entweder "1" oder "0" an ... Man könnte hier sicherlich noch mehr machen: die GPX-Dateien enthalten eine Höhenangabe - man könnte also auch 3D-Geometrien bauen ...
Vielleicht jemand diese erste Version brauchen - viel Spaß damit!

Freitag, 12. November 2010

Views mit SDO_GEOMETRY

Auch für Geodaten-Tabellen werden recht häufig Views generiert. Daten aus verschiedenen Tabellen stehen damit quasi als "eine Tabelle" bereit. Und man kann mit den Views auch sehr gut arbeiten. Nur lassen sich die Views von vielen GIS-Werkzeugen und auch vom Oracle MapBuilder (das Werkzeug zum Einrichten der Kartendefinitionen für Oracle MAPS) nicht verwenden - die Auswahldialoge zeigen sie einfach nicht an.
Nun befindet sich auf der View zwar kein Spatial-Index, aber das ist ja auch richtig so; auf eine View kann kein Index gelegt werden. Der Grund ist die Spatial-Metadaten-View USER_SDO_GEOM_METADATA, die von all diesen Werkzeugen ausgelesen wird und meist Grundlage der Auswahllisten ist.
Die Lösung ist also einfach: Die View wird, wie die zugrundeliegende Spatial-Tabelle in USER_SDO_GEOM_METADATA eingetragen. Nehmt einfach dieses SQL hier als Vorlage.
insert into user_sdo_geom_metadata values (
  '{TABLE/VIEW NAME}',
  '{GEOM_COL_NAME}',
  sdo_dim_array(
   sdo_dim_element('X', {xmin}, {xmax}, {tolerance}),
   sdo_dim_element('Y', {ymin}, {ymax}, {tolerance})
  ),
  {SRID}
)
/
Einen Index könnt Ihr danach immer noch nicht anlegen - aber das braucht Ihr auch nicht - der View sollte nun in eurem GIS-Werkzeug oder im Oracle MapBuilder sicht- und auswählbar sein.

Samstag, 16. Oktober 2010

INSIDE, TOUCH ... oder etwa doch anders

Wie kann ich eigentlich herausfinden, in welcher topologischen Beziehung sich 2 Objekte zueinander definden?

Die Funktion RELATE im Package SDO_GEOM liefert im Ergebnis die Lagebeziehung zwischen 2 Objekten.
select
  c2.feature_name,
  sdo_geom.relate(
    c2.geometry,
    'determine',    -- Maskierungsparameter
    c1.geometry, 
    0.05 ) topo_rel
from 
  m_admin_area1 c1, 
  m_admin_area1 c2
where 
  c1.feature_name = 'GERMANY';
Der Wert DETERMINE für den Maskierungsparameter ermittelt dabei diejenige Lagebeziehung zwischen 2 Objekten, welche der Realität am meisten entspricht.
Im Falle der obigen Abfrage wird anhand des kostenfrei bereitgestellten NAVTEQ Beispieldatensets für Oracle die Lagebeziehung zwischen Deutschland und allen anderen Ländern ermittelt.

Wird übrigens als Wert für den Maskierungsparameter ANYINTERACT angegeben, gibt die Funktion TRUE zurück für alle Lagebeziehungen, die ungleich DISJOINT sind.

Donnerstag, 14. Oktober 2010

SQL Developer 3.0 ist draußen: Mit Spatial-Unterstützung!

Seit dem 13. Oktober ist das Early Adopter-Release des SQL Developer 3.0 draußen. Das besondere daran ist, dass nun eine Unterstützung für Spatial drin ist: out-of-the-box und ohne GeoRaptor. Hier ein Screenshot. Ihr sehr, dass es nun eine Map-Ansicht von Geodaten gibt und dass zu einer Tabelle (über den Eintrag Räumlich im Kontextmenü) Spatial-Bezogene Operationen angeboten werden.
Der SQL Developer wird mit Sicherheit nicht mit einem Spatial Commander oder einem ähnlichen GIS-Werkzeug konkurrieren können, aber die Basisoperationen (sprich: was ein SQL bzw. PLSQL-Entwickler braucht) sind nun out-of-the-box drin. Und das ist gut!

Donnerstag, 30. September 2010

APEX und die Frage: Wo sind meine Metadaten geblieben?

Wer schon mal eine kleine oder auch größere APEX-Geo-Anwendung erstellt hat, wird die nachfolgend beschriebene Situation vielleicht schon mal erlebt haben.

Jede Tabelle mit einer SDO_GEOMETRY-Spalte benötigt eine Registrierung in den SDO-Metadaten der Oracle Datenbank. Das ist ein INSERT in die Nutzer-bezogene View USER_SDO_GEOM_METADATA und kann z.B. so aussehen:
SQL> insert into user_sdo_geom_metadata (
  table_name,
  column_name,
  diminfo,
  srid)
values (
  'GEOTAB',
  'geometry',
  sdo_dim_array(sdo_dim_element('X',-180,180,0.005),
  sdo_dim_element('Y',-90,90,0.005)),
  8307);
Entwickelt man eine Anwendung in APEX und benutzt für das Registrieren der SDO_GEOMETRY Spalte in den Metadaten den SQL Workshop, dann läuft das soweit auch ohne Probleme durch.

Dann wird ordentlicherweise auch gleich noch der Spatial Index angelegt und schon erscheint die Fehlermeldung ORA-00942: table or view does not exist.

Ein kurzes
SQL> select * from user_sdo_geom_metadata where table_name = 'GEOTAB';
bringt kein Ergebnis zurück.

Was ist passiert? Wo ist der Eintrag in die Metadaten geblieben?
Mit DBA-Rechten ist es recht einfach, in der entsprechenden Tabelle des Nutzers MDSYS nachzuschauen.
SQL> select * from mdsys.sdo_geom_metadata_table;
Dort ist in der Spalte SDO_OWNER dann anstatt des erwarteten Nutzers (hier im Beispiel SPATIAL) je nach dem von APEX verwendeten Web Listener entweder ANONYMOUS, APEX_PUBLIC_USER oder HTMLDB_PUBLIC_USER zu finden. Das ist der Nutzername der APEX-Session, in dessen Schema dann auch die SDO_GEOMETRY Metadaten registriert werden.

Wie kann das jetzt bereinigt werden?
Bitten Sie Ihren DBA, Ihrem Nutzer UPDATE-Rechte für die MDSYS-Tabelle SDO_GEOM_METADATA_TABLE zuzuweisen.

SQL> grant update on mdsys.sdo_geom_metadata_table;
Dann ändern Sie den SDO_OWNER-Eintrag wie folgt ab:
SQL> update MDSYS.SDO_GEOM_METADATA_TABLE
  set sdo_owner='SPATIAL'
  where sdo_table_name = 'GEOTAB' and sdo_owner = 'ANONYMOUS';
Wenn Sie jetzt die Metadaten überprüfen, sollte nunmehr alles im grünen Bereich sein.

Dienstag, 21. September 2010

Gauss-Krüger: EPSG oder nicht EPSG: Das ist hier die Frage!

Seit Oracle10g Release 2 unterstützt die Oracle-Datenbank die EPSG-Systematik für Koordinatensysteme. Die Projektion Gauss-Krüger Zone 3 steht damit gleich zweimal bereit:
  • als "klassische" Oracle-SRID 82027
  • im EPSG-Standard als Code 31467
SQL> select srid,cs_name from cs_srs where srid in (31467, 82027)

      SRID CS_NAME
---------- ----------------------------------------
     31467 DHDN / Gauss-Kruger zone 3
     82027 GK Zone 3 (DHDN)
Man könnte auf den Gedanken kommen, dass es nun egal ist, welchen Code man verwendet. Aber das ist es leider nicht. Zwischen dem nach EPSG standardisierten System 31467 und der "Oracle-Version" gibt es Unterschiede ... und die möchte ich in diesem Blog Posting herausarbeiten.
Zunächst nehme ich die Koordinate von Oracle in München (mit dem Oracle-Geocoder, versteht sich) und rechne die nach EPSG:31467 um.
select sdo_cs.transform(
  sdo_geometry(2001, 8307, sdo_point_type(11.536734, 48.1800773, null), null, null), 
  31467
) transformed from dual;

TRANSFORMED
------------------------------------------------------------------------------------
SDO_GEOMETRY(2001, 31467, SDO_POINT_TYPE(3688714,69, 5341125,2, NULL), NULL, NULL)
Dies ist die absolut korrekte Koordinate im Koordinatensystem EPSG:31467. Man könnte aber auf den Gedanken kommen, diese mit der ID 82027 in die Datenbank zu speichern ... wenn's das gleiche Koordinatensystem ist, wäre das ja egal ...
Also rechnen wir die Koordinate wieder in WGS84 zurück und zwar einmal mit der SRID 31467 und einmal mit 82027.
select sdo_cs.transform(
  SDO_GEOMETRY(2001, 31467, SDO_POINT_TYPE(3688714.69, 5341125.2, NULL), NULL, NULL ),
  8307
) transformed from dual;

TRANSFORMED
------------------------------------------------------------------------------------
SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(11,5367341, 48,1800773, NULL), NULL, NULL)

select sdo_cs.transform(
  SDO_GEOMETRY(2001, 82027, SDO_POINT_TYPE(3688714.69, 5341125.2, NULL), NULL, NULL ),
  8307
) from dual;

TRANSFORMED
------------------------------------------------------------------------------------
SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(11,5391267, 48,180154, NULL), NULL, NULL)
Und man sieht, dass es nicht das gleiche ist. Wenn man die Well Known Texts vergleicht, lässt sich auch feststellen, dass es in den Parametern ein paar Unterschiede gibt. Die Abweichung liegt meist im Bereich von ca. 100 bis 200 Metern.
select sdo_geom.sdo_distance(
 sdo_cs.transform(
  SDO_GEOMETRY(2001, 31467, SDO_POINT_TYPE(3688714.69, 5341125.2, NULL), NULL, NULL ),
  8307
 ),
 sdo_cs.transform(
  SDO_GEOMETRY(2001, 82027, SDO_POINT_TYPE(3688714.69, 5341125.2, NULL), NULL, NULL ),
  8307
 ),
 1
) distanz from dual;

DISTANZ
-------------
   178,128988
Und was bedeutet das? Zuerstmal alles kein Problem! Man muss es, wenn man GK3-Koordinaten (bspw. aus Shapefiles) in die Datenbank lädt, nur beachten. Stellt man beim Betrachten der Daten Abweichungen im Bereich von 100 bis 200 Metern fest, sollte man die andere GK3-SRID versuchen. Meistens liegt man mit der neueren EPSG-Nummer 31467 richtig. Aber ich habe auch schon Fälle erlebt, in denen die 82027 genommen werden musste.
Rechnet man eine Geometrie von 82027 nach 31467 um, kommen (folgerichtig) auch nicht die gleichen Koordinaten heraus.
SQL> select sdo_cs.transform(
  2    SDO_GEOMETRY(2001, 82027, SDO_POINT_TYPE(3688714.69, 5341125.2, NULL), NULL, NULL ),
  3    31467
  4  ) TRANSFORMED from dual;

TRANSFORMED
-----------------------------------------------------------------------------------
SDO_GEOMETRY(2001, 31467, SDO_POINT_TYPE(3688892,31, 5341139,61, NULL), NULL, NULL)
Für die anderen in Deutschland gebräuchlichen Gauss-Krüger Projektionen gilt das analog.
SQL> select srid,cs_name from cs_srs where srid in (31466, 82015);

      SRID CS_NAME
---------- ----------------------------------------
     31466 DHDN / Gauss-Kruger zone 2
     82015 GK Zone 2 (DHDN)

SQL> select srid,cs_name from cs_srs where srid in (31468, 82032);

      SRID CS_NAME
---------- ----------------------------------------
     31468 DHDN / Gauss-Kruger zone 4
     82032 GK Zone 4 (DHDN)

Montag, 20. September 2010

Oracle Partner CISS TDI erweitert seine CITRA-Schnittstellenpalette

Der Oracle Partner CISS TDI GmbH hat seine CITRA-Schnittstellenpalette um einen Reader für das OpenStreetMap-Daten im XML-Format erweitert.
Die Schnittstelle beinhaltet
  • eine Konfiguration für das Oracle Network Datenmodell sowie
  • eine sehr gut ausgestalteten Übersichtskarte in Oracle Spatial zur Verwendung im Oracle Fusion Middleware MapViewer
Mit dieser Schnittstelle schafft CISS TDI die Möglichkeit, OpenStreetMap-Daten nativ mit Oracle Spatial zu verwenden.
Weitere Informationen sind hier zu finden.

SDO_GEOMETRY Viewer für Oracle SQL Developer

Für das kostenfreie DB-Entwicklungs- und Administrationswerkzeug SQL Developer gibt es eine Erweiterung, welche mit als SDO_GEOMETRY gespeicherten 2-dimensionalen Geometriedaten umgehen kann.
Der sogenannte GeoRaptor ist ein Open-Source-Projekt auf sourceforge.net.
Neben den eigentlichen "Features", wie z.B.
  • Kontextmenü für die Tabellen mit SDO_GEOMETRY-Spalte
  • Viewer mit den typischen Funktionen, wie Zoom, Rectangle Zoom, Pan, Copy sowie der Möglichkeit, die Signaturen der ausgewählten Geometrien festzulegen
  • SQL Code-Snippets
können auf den Projektseiten auch gleich neue Features angefragt bzw. Probleme mit vorhandenen berichtet werden.

Hinweise zur Installation gibt es hier.
Und wie sieht der Viewer in Aktion aus?

Bemerkung: Für die Darstellung wurden Daten aus dem frei für Oracle verfügbaren Datenset von NAVTEQ verwendet. Das ist zu finden unter Oracle Spatial Partners′ Data.

Montag, 13. September 2010

Oracle OpenWorld 2010 demnächst

Vom 19.-23. September findet in San Francisco die Oracle OpenWorld 2010 statt.
Unter den vielen verschiedenen Themenbereichen wird auch ein Fokus auf "Oracle Spatial & Oracle MapViewer" gesetzt. Alle Veranstaltungen dazu sind hier zu finden.

Mittwoch, 8. September 2010

De-aggregieren zusammengesetzter Geometrien

Aus einer zusammengesetzten Geometrie (Multipolygon, welches mehrere Elemente, optional auch Subelemente/Ringe enthält) können mit Hilfe der Funktion EXTRACT einzelne Elemente herausgezogen werden.

Diese Funktion für 2D-Vektordaten, sowie analog EXTRACT3D für 3D-Vektordaten, steht im PL/SQL Package SDO_UTIL zur Verfügung. Letztere Funktion gibt es allerdings erst seit der DB Version 11.1 im Package.

Das Format ist wie folgt kurz beschrieben:
sdo_util.extract (
  geometry IN SDO_GEOMETRY,
  element IN NUMBER,
  ring IN NUMBER default 0
) return sdo_geometry; -- 2D

Und wie geht´s konkret?

Gegeben sei das Multipolgyon "Brandenburg" (SDO_GTYPE = 2007) aus dem World Sample NAVTEQ Data Bundle.

-- Extraction von Element 1, Ring 1
SQL> select sdo_util.extract(geometry, 1, 1) from m_admin_area2 where feature_name = 'Brandenburg';
-- Ergebnis ist der äußere Ring von Brandenburg

-- Extraction von Element 1, Ring 2
SQL> select sdo_util.extract(geometry, 1, 2) from m_admin_area2 where feature_name = 'Brandenburg';
-- Ergebnis ist der innere Ring von Brandenburg, gleichzeitig die administrative Grenze des Bundeslandes Berlin

-- Extraction von Element 2, Ring 2
SQL> select sdo_util.extract(geometry, 2, 1) from m_admin_area2 where feature_name = 'Brandenburg';
-- Ergebnis hier ist eine kleine Brandenburgische Exklave in Sachsen-Anhalt

Weitere Infos finden sich natürlich in der Online-Doku auf OTN (http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14255/sdo_util.htm#sthref1955).

Donnerstag, 2. September 2010

Es geht los!

Auf diesem Blog werden wir künftig Informationen, Tipps und Tricks zu Oracle Locator und Oracle Spatial veröffentlichen. Wir, das sind Karin Patenge, Bernhard Fischer-Wasels, Haitham Zyadeh und Carsten Czarski. Das Blog richtet sich an Entwickler und technisch Interessierte.