[Talk-de] ESRI Shapefiles

Hermann Schwärzler hermann.schwaerzler at chello.at
Do Jul 26 12:27:08 UTC 2007


hallo thomas

Thomas Krüger wrote:
[...]
> Jetzt habe ich ein wenig rumgesucht, bin aber zu keiner
> vernüftigen Lösung gekommen, diese in JOSM reinzubekommen.
> Ich fand Tool namen shp2osm, in dem ich erst mal ein paar Bug beheben
> musste und dann beim Testen (mit den QGIS Demofiles und der freien
> Osnabrücker Karte) eine .osm-Datei mit Koordinaten in einem anderen
> Format als Länge/Breite in Grad bekam.
> Damit kam JOSM nicht klar und ich als Projektions- und
> Koordinaten-Analphabet erst recht nicht.
> Ein Beispiel:
> <node lat='5799654.02' lon='3429429.46' id='1' ></node>
> Kennt jemand eine Lösung?

ich habe das perl-skript "shp2osm.pl" von gabriel ebner etwas angepasst
und es kann jetzt koordinaten umrechnen, indem es Geo::Proj4 verwendet.
du musst nur "our $from" anpassen (ich habe daten aus dem
österreichischen GK M28) und es geht schon.
wenn deine quellprojektion - wie im mail von Frank Jäger steht - EPSG
31467 ist, musst du
   our $from = "+proj=tmerc +lat_0=0 +lon_0=9 +k=1.000000 +x_0=3500000" .
               "+y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs";
schreiben.

falls du beim installieren von "Geo::ShapeFile" von CPAN einen fehler
bei den tests bekommst, kannst du ruhig mit "force" installieren, weil
das problem ein fehlender überladener operator ist, der in unserem fall
nicht verwendet wird.

ach ja, und falls das validator-plugin von JOSM (berechtigerweise)
viele "duplicate nodes" anzeigt (bei mir waren die nodes bei
strassenabzweigungen immer doppelt), habe ich noch ein sehr rustikales
shell-skript das diese entfernt/ersetzt. bitte melde dich, wenn du es
brauchst. vorwarnung: funktioniert momentan nur mit unix/linux (es
verwendet "ed" um die datei zu editieren). :-)

grüße
hermann

---8<----- falten und vorsichtig abscheiden ------------->8---
#!/usr/bin/perl
# Copyright (C) 2006  Gabriel Ebner <ge at gabrielebner.at>
use Geo::ShapeFile;
use HTML::Entities qw(encode_entities_numeric);
use Geo::Proj4;

print <<'END';
<?xml version="1.0"?>
<osm version="0.3" generator="shp2osm.pl">
END

BEGIN {
    our %default_tags = ( source     => 'shapefiles' );
    # GK M28 -> wgs84
    our $from = Geo::Proj4->new(
          "+proj=tmerc +lon_0=10d20 +x_0=0 +y_0=-5000000 +ellps=bessel
".
          "+towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232");
    our $to   = Geo::Proj4->new("+proj=latlong +datum=WGS84");
}


for my $file (@ARGV) {
     $file =~ s/\.shp$//;
     my $shpf = Geo::ShapeFile->new($file);
     proc_shpf($shpf);
}

{
     BEGIN { our $i = -1; }

     sub tags_out {
         my ($tags) = @_;
         my %tags = $tags ? %$tags : ();
         $tags{'created_by'} ||= 'shp2osm.pl';
         delete $tags{'_deleted'} unless $tags{'_deleted'};
         while ( my ( $k, $v ) = each %tags ) {
             my $key = encode_entities_numeric($k);
             my $val = encode_entities_numeric($v);
             print '    <tag k="'. $key .'" v="'. $val ."\"/>\n" if $val;
         }
     }

     sub node_out {
         my ( $lon, $lat, $tags ) = @_;
         my $id = $i--;
         print "  <node id=\"$id\" lat=\"$lat\" lon=\"$lon\">\n";
         tags_out $tags;
         print "  </node>\n";
         $id;
     }

     sub seg_out {
         my ( $from, $to, $tags ) = @_;
         my $id = $i--;
         print "  <segment id=\"$id\" from=\"$from\" to=\"$to\">\n";
         tags_out $tags;
         print "  </segment>\n";
         $id;
     }

     sub way_out {
         my ( $segs, $tags ) = @_;
         my $id = $i--;
         print "  <way id=\"$id\">\n";
         print "    <seg id=\"$_\"/>\n" for @$segs;
         tags_out $tags;
         print "  </way>\n";
         $id;
     }
}

print <<'END';
</osm>
END

sub project_coordinates {
     my ( $from, $to, $lon, $lat, $tags ) = @_;

     my $pr_point = $from->transform($to, [ $lon, $lat ]);

     my $lon_proj = $pr_point->[0];
     my $lat_proj = $pr_point->[1];

     return [ $lon_proj, $lat_proj, $tags ];
}


sub polyline_out {
     my ( $pts, $tags, $connect_last_seg ) = @_;

     my ( $first_node, $last_node, @segs );
     for my $pt (@$pts) {
         $pt_proj = project_coordinates($from, $to, @$pt);
         my $node = node_out @$pt_proj;
         push @segs, seg_out $last_node, $node if $last_node;
         $last_node = $node;
         $first_node ||= $last_node;
     }
     push @segs, seg_out $last_node, $first_node
       if $first_node
       && $connect_last_seg;
     way_out \@segs, $tags;
}

sub proc_obj {
     my ( $shp, $dbf, $type ) = @_;
     my $tags = { %default_tags, %$dbf };
     my $is_polygon = $type % 10 == 5;
     for ( 1 .. $shp->num_parts ) {
         polyline_out [ map( [ $_->X(), $_->Y() ], $shp->get_part($_) )
], $tags,
           $is_polygon;
     }
}

sub proc_shpf {
     my ($shpf) = @_;
     my $type = $shpf->shape_type;
     for ( 1 .. $shpf->shapes() ) {
         my $shp = $shpf->get_shp_record($_);
         my %dbf = $shpf->get_dbf_record($_);
         proc_obj $shp, \%dbf, $type;
     }
}





Mehr Informationen über die Mailingliste Talk-de