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.