geo_osm_pbf 1.0.0 copy "geo_osm_pbf: ^1.0.0" to clipboard
geo_osm_pbf: ^1.0.0 copied to clipboard

Streaming OpenStreetMap `.osm.pbf` reader and extract downloader in pure Dart. Hand-rolled protobuf decoding with no dependencies, delivering nodes, tagged nodes, ways and relations with their full tags.

example/geo_osm_pbf_example.dart

import 'dart:io';

import 'package:geo_osm_pbf/geo_osm_pbf.dart';

/// Summarises what an `.osm.pbf` extract contains.
///
/// With no arguments it downloads a small region and reads that. With a path
/// it reads the file you already have, which is the usual way to try this
/// against a real extract without waiting for a download.
///
/// ```sh
/// dart run example/geo_osm_pbf_example.dart
/// dart run example/geo_osm_pbf_example.dart ./maps/santa-catarina.osm.pbf
/// dart run example/geo_osm_pbf_example.dart --region europe/monaco
/// ```
Future<void> main(List<String> args) async {
  final path = await _resolveInput(args);
  if (path == null) return;

  const parser = OsmPbfParser();

  // Reading the header costs one blob, not a scan of the file.
  final header = await parser.readHeader(path);
  stdout.writeln('File: $path');
  if (header != null) {
    stdout
      ..writeln('  written by      ${header.writingProgram ?? 'unknown'}')
      ..writeln('  required        ${header.requiredFeatures.join(', ')}')
      ..writeln('  bounding box    ${header.bbox ?? 'not declared'}');
    if (header.unsupportedFeatures.isNotEmpty) {
      stdout.writeln(
        '  WARNING: unsupported features ${header.unsupportedFeatures}',
      );
    }
  }

  var nodes = 0;
  var taggedNodes = 0;
  var ways = 0;
  var relations = 0;
  var multipolygons = 0;
  final highways = <String, int>{};
  final places = <String, int>{};

  final watch = Stopwatch()..start();

  await parser.parse(
    path,
    onNode: (_) => nodes++,
    onTaggedNode: (node) {
      taggedNodes++;
      final place = node.tags['place'];
      if (place != null) places[place] = (places[place] ?? 0) + 1;
    },
    onWay: (way) {
      ways++;
      final highway = way.tags['highway'];
      if (highway != null) highways[highway] = (highways[highway] ?? 0) + 1;
    },
    onRelation: (relation) {
      relations++;
      if (relation.isMultipolygon) multipolygons++;
    },
  );

  watch.stop();

  stdout
    ..writeln('')
    ..writeln('  nodes           $nodes')
    ..writeln('  tagged nodes    $taggedNodes')
    ..writeln('  ways            $ways')
    ..writeln('  relations       $relations ($multipolygons multipolygon)')
    ..writeln('  parsed in       ${watch.elapsedMilliseconds} ms')
    ..writeln('')
    ..writeln('  top highway classes:');
  _printTop(highways, 8);

  if (places.isNotEmpty) {
    stdout.writeln('  place types:');
    _printTop(places, 5);
  }
}

/// Returns the `.osm.pbf` to read, downloading one when none was given.
Future<String?> _resolveInput(List<String> args) async {
  final positional = args.where((a) => !a.startsWith('--')).toList();
  if (positional.isNotEmpty && args.first != '--region') {
    final path = positional.first;
    if (!File(path).existsSync()) {
      stderr.writeln('No such file: $path');
      exitCode = 1;
      return null;
    }
    return path;
  }

  final regionIndex = args.indexOf('--region');
  final region = regionIndex >= 0 && regionIndex + 1 < args.length
      ? args[regionIndex + 1]
      : 'europe/monaco';

  stdout.writeln('Downloading $region ...');
  final downloader = OsmDownloader(outputDirectory: Directory('./osm-cache'));
  try {
    return await downloader.downloadRegion(
      region: region,
      onProgress: (received, total, url) {
        final mb = (received / 1e6).toStringAsFixed(1);
        stdout.write('\r  $mb MB');
      },
    );
  } finally {
    downloader.close();
    stdout.writeln('');
  }
}

void _printTop(Map<String, int> counts, int limit) {
  final sorted = counts.entries.toList()
    ..sort((a, b) => b.value.compareTo(a.value));
  for (final e in sorted.take(limit)) {
    stdout.writeln('    ${e.key.padRight(18)} ${e.value}');
  }
}
1
likes
150
points
413
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Streaming OpenStreetMap `.osm.pbf` reader and extract downloader in pure Dart. Hand-rolled protobuf decoding with no dependencies, delivering nodes, tagged nodes, ways and relations with their full tags.

Repository (GitHub)
View/report issues

License

Apache-2.0 (license)

Dependencies

path

More

Packages that depend on geo_osm_pbf