Länge von Ways in einer OSM-Datei ermitteln?

Hallo,

gibt es ein Tool, das anhand der Daten in einer .osm-Datei die Länge (in km, Meilen, oder was auch immer) aller darin enthaltenen Ways berechnet und ausgibt?

Optimal wäre ein CSV-Output mit allen tags und einer weiteren Spalte für die Länge. Also bspw:

Name highway length
Schlossallee primary 3.141
Parkstraße secondary 2.718

Gibt es hierfür ein handliches Tool, ohne ganze Datenbanken- oder GIS-Systeme installieren zu müssen?

TIA

Jepp, gibt es: https://github.com/osmcode/libosmium welches auch direkt mit PBF arbeiten kann.
Und in den Examples findest du dann auch ein Skript für die Länge(nermittlung)

Danke, werde ich mir anschauen.

Hallo,

ich bin nun endlich mal dazu gekommen, mich näher damit zu beschäftigen. Wenn ich das recht verstehe, ist das eine Library für die Verwendung in C(++). Richtig?
Das übersteigt allerdings meine Programmierfähigkeiten. Gibt es eine Möglichkeit, diese Library aus anderen Sprachen anzusteuern? Perl? Ruby?
Das verwandte osmium-Kommandozeilentool kann die Längen nicht ermitteln, oder?
Gibt es noch andere Lösungsmöglichkeiten für mein Problem (s.o.)?

TIA und Gruß

Quick&Dirty mit libosmium würde das so aussehen: https://gist.github.com/mmd-osm/d069197aca039e789a75855bdc76ea56

Dazu müsstest du zunächst libosmium herunterladen, kompilieren wie in https://github.com/osmcode/libosmium#building beschrieben und dann im cmake Verzeichnis ein

examples/osmium_road_length meine_osm_datei.osm

aufrufen.

Achja, ebenfalls müsstest du noch den Code in libosmium/examples/osmium_road_length.cpp durch die Version oben ersetzen.

Wenn du dein File irgendwo hochladen kannst, kann ich das auch gerne hier laufen lassen.

BTW: Es gibt auch ein Issue für die Overpass API dazu: https://github.com/drolbr/Overpass-API/issues/237

Ich hätte auf den ersten Blick auch Osmium empfohlen. Die Sache ist aber nicht ganz so einfach.

Zum einen bestehen Straßen oft aus mehreren Ways, das heißt, man muss die Längen dieser Ways addieren. Hierbei reicht es aber nicht aus, einfach nach Ways mit gleichem Namen zu suchen, denn in manchen Städten gibt es gleichnamige Straßen, die in unterschiedlichen Ortsteilen liegen. Man muss wirklich schauen, die betreffenden Ways aneinanderhängen.

Zusätzlich muss man prüfen, ob gleichnamige Ways nahe beieinander liegen, denn es ist nicht zwingen, dass eine direkte Verbindung besteht.

Und als weitere Schwierigkeit müssen auch die Fälle berücksichtigt werden, bei denen der Straßenname gar nicht am Way-Objekt hängt, sondern an einer Relation die mehrere dieser Ways zusammenfasst.

Eine entsprechende Auswertung könnte man natürlich mit der Osmium-Bibliothek bauen, aber vielleicht wär dann doch der Weg über eine Datenbank einfacher…

Hallo,

Nein, das brauche ich alles gar nicht. Mir reicht wirklich ein Datensatz je OSM-Objekt. Die Längen aller Einträge mit Namen “Schlossallee” zu addieren, kriege ich dann schon selbst in der CSV-Datei hin. Im Gegenteil darf das Tool gar nichts zusammenfassen, da ja sonst Unterschiede bei anderen Tags (primary/secondary oder surface) verloren gehen könnten. Ich will ja die Längen nach allen verfügbaren Tags gruppieren können. Also bspw. auch ermitteln, welcher Anteil der Straßen asphaltiert ist (über die Einträge im Surface-Tag)
Auf die Tags, die “indirekt” über Relationen an einem Objekt hängen, kann ich ebenfalls gerne verzichten. Mir reichen alle “direkten”.

Gibt es da kein anderes fertiges Tool, wo man nicht erst rumkompilieren muss?

Ich hatte ansonsten noch irgendwo einen Perl-Code rumfliegen, mit dem man die Entfernung zwischen zwei Koordinaten ermitteln kann. Damit müsste man sich ja den Way nur entlanghangeln. Das erscheint mir momentan fast einfacher… :expressionless:

Gruß

Achso, wenn du eine Lösung in Perl suchst, frag doch am besten mal bei Netzwolf nach. Der kann dir bestimmt weiterhelfen.

Hallo,

ich habe die verregneten Feiertage genutzt, was in Perl zusammenzustümpern. Das folgende Skript erwartet auf der Kommandozeile eine *.osm-Datei (bspw. aus JOSM abgespeichert) und gibt alle darin enthaltenen Ways in eine gleichnamige *.csv-Datei aus inkl. aller Tags und der berechneten Länge in Kilometern. Letztere landet in der Spalte ‘calculated_length’ um Konflikte mit dem gelegentlich verwendeten Tag ‘length’ zu vermeiden. Einzelne Nodes sowie Relationen werden (derzeit noch) ignoriert.

use strict;
use XML::Simple qw(:strict);
use Math::Trig;

my $wayid;
my $key;
my $lastpoint;
my $outfile;
my $point;
my $subpoint;
my $lastpont;
my $length;

my %keys;	

my $xml = new XML::Simple;
my $infile = $ARGV[0];
my $osm = $xml->XMLin($infile, KeyAttr => { node => 'id', way => 'id', tag => 'k'}, ForceArray => [ 'node', 'way', 'tag' ]) or die "Fehler beim Öffnen der Datei $infile : $!\n";

$keys{'id'}=1;

#Alle Daten einsammeln und die Längen berechnen
foreach $wayid (keys(%{ $osm->{'way'} } )){

	#Längenfeld vorbereiten
	$osm->{'way'}->{$wayid}->{'tag'}->{'calculated_length'}->{'v'}=0;

	#Merken aller vorkommenden Keys
	foreach $key (keys(%{$osm->{'way'}->{$wayid}->{'tag'}})) {
		$keys{$key}=1;
	}

	#Laengenberechnung
	$lastpoint=undef;
	$length=0;

	foreach $point ($osm->{'way'}->{$wayid}->{'nd'}) {
		foreach $subpoint (@$point){
			if ($lastpoint){
				$length+=&calcDist($osm->{'node'}->{$lastpoint->{'ref'}}->{'lat'}, $osm->{'node'}->{$lastpoint->{'ref'}}->{'lon'}, $osm->{'node'}->{$subpoint->{'ref'}}->{'lat'}, $osm->{'node'}->{$subpoint->{'ref'}}->{'lon'});
			}
			$lastpoint=$subpoint;
		}
	}
	#Länge in der Datenstruktur ablegen
	$osm->{'way'}->{$wayid}->{'tag'}->{'calculated_length'}->{'v'}=$length;

}

#Daten ausgeben
$outfile=$infile;
$outfile=~s/\.osm$/.csv/;

open OUTFILE, ">$outfile" or die "Fehler beim Öffnen der Outputdatei $outfile : $!\n";

#Header schreiben
foreach $key (sort(keys(%keys))){
	$_.="$key;";
}
print OUTFILE "$_\n";

#Daten schreiben
foreach $wayid (keys(%{$osm->{'way'}})){
	$_=undef;
	foreach $key (sort(keys(%keys))) {
		if ($key ne 1 and $key ne 'nd'){
			if ($key eq 'id') {
				$_.=$wayid.';';
			}else{
				$_.="'".$osm->{'way'}->{$wayid}->{'tag'}->{$key}->{'v'}."';";
			}
		}
	}
	print OUTFILE "$_\n";
}

close OUTFILE;

#-----------------------------------------------------------------------------------------------
sub calcDist{
	my $lat1=shift;
	my $lon1=shift;

	my $lat2=shift;
	my $lon2=shift;

	my $R = 6371; #km

	my $dLat = &deg2rad($lat2-$lat1);
	my $dLon = &deg2rad($lon2-$lon1);
	my $lat1 = &deg2rad($lat1);
	my $lat2 = &deg2rad($lat2);

	my $a = sin($dLat/2) * sin($dLat/2) + sin($dLon/2) * sin($dLon/2) * cos($lat1) * cos($lat2); 
	my $c = 2 * atan2( $a**(0.5), (1-$a)**(0.5) );
	my $d = $R * $c;
	return $d;
}

Kommentare sind immer willkommen! :smiley:

Gruß

Hallo an alle,

ich hätte eine Frage zu Libosmium, da es hier im Thread erwähnt wurde. Habt ihr Erfahrung mit der Einrichtung der Libosmium-Lib auf Windows? Ich versuche schon seit längerer Zeit es einzurichten, aber es gelingt mir einfach nicht. Ich bekomme beim bauen mit git cmd die Meldung, dass der angegebene Pfad zu vcvarsall.bat nicht gefunden werden kann. Vielen Dank im Voraus.