Posts mit dem Label gpx convert sdo_geometry werden angezeigt. Alle Posts anzeigen
Posts mit dem Label gpx convert sdo_geometry werden angezeigt. Alle Posts anzeigen

Donnerstag, 10. März 2011

SDO nach GPX konvertieren - ein Beispiel

Für das Treffen der DOAG SIG Spatial nächste Woche in Potsdam bereite ich gerade meinen Vortrag zum Thema "Geodaten und XML in der Oracle-Datenbank" vor. Dabei werde ich (unter anderem) darauf eingehen, wie man mit den Mitteln der Datenbank aus einem SDO_GEOMETRY ein GPX-File erzeugen kann. Das kann interessant sein, wenn eine Geometrie eine Route repräsentiert und man diese auf ein Navigationsgerät laden möchte ...
Das Generieren der GPX-Datei ist (verwendet man die SQL/XML-Funktionen) sehr einfach. Hier ist eine PL/SQL-Funktion, die ein SDO_GEOMETRY entgegennimmt und ein GPX-File zurückgibt.
create or replace function make_gpx(
  p_name in varchar2,
  p_geom in sdo_geometry
) return xmltype is 
  v_gpx  xmltype;
  v_geom sdo_geometry;
begin
  -- CHECK FOR LINESTRING GEOMETRY
  if not p_geom.get_gtype() = 2 then   
   raise_application_error(-20000, 'CAN BUILD GPX TRACK ONLY FOR LINESTRING GEOMETRIES');
  end if;
  -- CHECK FOR LATLON GEOMETRY - TRANSFORM IF NOT 
  if p_geom.sdo_srid not in (4326, 8307) then
   v_geom := sdo_cs.transform(p_geom, 4326);
  else 
   v_geom := p_geom;
  end if;
  -- CONSTRUCT GPX XML 
  select
   xmlelement("gpx", 
    xmlattributes('http://www.topografix.com/GPX/1/1' as "xmlns"),
    xmlelement("trk",
     xmlelement("name", p_name),
     xmlelement("trkseg", 
     (
      select 
       xmlagg(
        xmlelement("trkpt",
         xmlattributes(v.y as "lat", v.x as "lon")
        )
       )
       from table(sdo_util.getvertices(v_geom)) v
      )
     )
    )
   ) into v_gpx 
  from dual;
  return v_gpx;
end;
/
sho err
Viel Spaß beim Ausprobieren ... und wer noch mehr zum Thema "Geodaten und XML" wissen möchte (und spontan ist), der kommt nächste Woche nach Potsdam zur DOAG SIG Spatial.

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!