geodata 0.8.0-a.8 copy "geodata: ^0.8.0-a.8" to clipboard
geodata: ^0.8.0-a.8 copied to clipboard

outdated

A geospatial client to read GeoJSON and OGC API Features data sources.

example/geodata_example.dart

// Copyright (c) 2020-2022 Navibyte (https://navibyte.com). All rights reserved.
// Use of this source code is governed by a “BSD-3-Clause”-style license that is
// specified in the LICENSE file.
//
// Docs: https://github.com/navibyte/geospatial

// ignore_for_file: avoid_print

import 'package:equatable/equatable.dart';
import 'package:geocore/data.dart';

import 'package:geodata/geojson_client.dart';
import 'package:geodata/ogcapi_features_client.dart';

/*
To test run this from command line: 

GeoJSON (web / http) resource as a data source:
dart example/geodata_example.dart geojson https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/ 2.5_day.geojson,significant_week.geojson 3 items
dart example/geodata_example.dart geojson https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/ significant_week.geojson 3 items id us7000g9zq

OGC API Features data sources:
dart example/geodata_example.dart ogcfeat https://demo.pygeoapi.io/master/ lakes 2 items
dart example/geodata_example.dart ogcfeat https://demo.pygeoapi.io/master/ lakes 2 items id 3
dart example/geodata_example.dart ogcfeat https://www.ldproxy.nrw.de/kataster/ verwaltungseinheit 2 items bbox 7,50.6,7.2,50.8
dart example/geodata_example.dart ogcfeat https://weather.obs.fmibeta.com/ fmi_aws_observations 2 items bbox 23,62,24,63

OGC API Features meta queries:
dart example/geodata_example.dart ogcfeat https://demo.pygeoapi.io/master/ - 1 meta
dart example/geodata_example.dart ogcfeat https://www.ldproxy.nrw.de/kataster/ - 1 meta
dart example/geodata_example.dart ogcfeat https://weather.obs.fmibeta.com/ - 1 meta

More demo APIs (however this page seems to be somewhat outdated, be careful!):
https://github.com/opengeospatial/ogcapi-features/tree/master/implementations
*/

const _defaultOperation = 'items';
const _defaultLimit = 2;
const _defaultMaxPagedResults = 2;

/// A simple example to read features from standard OGC API Features services.
Future<void> main(List<String> args) async {
  // configure Equatable to apply toString() default impls
  EquatableConfig.stringify = true;

  // check enough args
  if (args.length < 3) {
    print(
      'Args: {service} {baseUrl} {collectionIds} '
      '[limit] [operation] [param] [value]',
    );
    print('Allowed sources: oapif, geojson');
    return;
  }

  // parse args
  final serviceType = args[0];
  final baseURL = args[1];
  final collectionIds = args[2].split(',');
  final limit = args.length >= 4 ? int.tryParse(args[3]) : _defaultLimit;
  final operation = args.length >= 5 ? args[4] : _defaultOperation;
  var maxPagedResults = _defaultMaxPagedResults;

  // parse query
  GeodataQuery query = FeatureItemsQuery(
    limit: limit,
  );
  if (args.length >= 7) {
    switch (args[5]) {
      case 'id':
        query = FeatureItemQuery(
          id: args[6],
        );
        maxPagedResults = 1;
        break;
      case 'bbox':
        final bbox = args[6].split(',');
        if (bbox.length == 4 || bbox.length == 6) {
          query = FeatureItemsQuery(
            limit: limit,
            bounds: GeoBounds.from(bbox.map<num>(double.parse)),
          );
        }
        break;
    }
  }

  try {
    // Create a feature service and apply an operation on it.
    switch (serviceType) {
      case 'geojson':
        // Loop over all collections (here sub resources like "2.5_day.geojson")
        for (final collectionId in collectionIds) {
          // A location to read GeoJSON data from.
          final location = Uri.parse(baseURL).resolve(collectionId);

          print('');
          print('Reading web resource at: $location');

          // GeoJSON client for a data source
          final source = geoJsonHttpClient(location: location);
          switch (operation) {
            case 'items':
              // get actual data, a single feature or features
              if (query is FeatureItemsQuery) {
                await _callItemsPaged(source, query, maxPagedResults);
              } else if (query is FeatureItemQuery) {
                await _callItemById(source, query);
              }
              break;
            default:
              throw ArgumentError('Unknow operation $operation');
          }
        }
        break;
      case 'ogcfeat':
        // An enpoint to read data from.
        final endpoint = Uri.parse(baseURL);

        // OGC API Features client (the service provides both meta and items)
        final service = ogcApiFeaturesHttpClient(endpoint: endpoint);

        switch (operation) {
          case 'meta':
            // read landing page
            final meta = await service.meta();
            print('OGC API Features service:');
            _printMeta(meta);

            // read conformance classes
            final conformance = await service.conformance();
            _printConformance(conformance);

            // read meta about collections
            print('Collections:');
            final collections = await service.collections();
            for (final coll in collections) {
              _printCollection(coll);
            }
            break;
          case 'items':
            // Loop over all collections
            for (final collectionId in collectionIds) {
              // get feature source for a collection
              final source = await service.collection(collectionId);

              // read meta for this collection
              final meta = await source.meta();
              print('Collection meta:');
              _printCollection(meta);

              // get actual data, a single feature or features
              if (query is FeatureItemsQuery) {
                await _callItemsPaged(source, query, maxPagedResults);
              } else if (query is FeatureItemQuery) {
                await _callItemById(source, query);
              }
            }
            break;
          default:
            throw ArgumentError('Unknow operation $operation');
        }
        break;
      default:
        throw ArgumentError('Unknow source type $serviceType');
    }
  } on FeatureException catch (e) {
    print('Calling $baseURL failed: ${e.failure.name}');
    if (e.cause != null) {
      print('Cause: ${e.cause}');
    }
    if (e.trace != null) {
      print(e.trace);
    }
  } catch (e, st) {
    print('Calling $baseURL failed: $e');
    print(st);
  }
}

Future<bool> _callItemById(
  FeatureSource source,
  FeatureItemQuery query,
) async {
  // fetch feature item
  final item = await source.item(query);
  _printFeature(item.feature);
  return true;
}

Future<bool> _callItemsPaged(
  FeatureSource source,
  FeatureItemsQuery query,
  int maxPagedResults,
) async {
  // fetch feature items as paged results, max rounds by maxPagedResults
  var round = 0;
  Paged<FeatureItems>? page = await source.itemsPaged(query);
  while (page != null && round++ < maxPagedResults) {
    _printFeatures(page.current);
    page = await page.next();
  }
  return true;
}

void _printFeatures(FeatureItems items) {
  print('Features:');
  if (items is OGCFeatureItems) {
    if (items.timeStamp != null) {
      print('  timestamp: ${items.timeStamp}');
    }
    if (items.numberMatched != null) {
      print('  number matched: ${items.numberMatched}');
    }
    if (items.numberReturned != null) {
      print('  number returned: ${items.numberReturned}');
    }
    _printLinks(items.links);
  }
  items.collection.features.forEach(_printFeature);
}

void _printFeature(Feature f) {
  print('Feature with id: ${f.id}');
  print('  geometry: ${f.geometry}');
  print('  properties:');
  for (final key in f.properties.keys) {
    print('    $key: ${f.properties[key]}');
  }
}

void _printMeta(ResourceMeta meta) {
  print('  title: ${meta.title}');
  if (meta.description != null) {
    print('  description: ${meta.description}');
  }
}

void _printConformance(Iterable<String> conformance) {
  print('Conformance classes:');
  for (final e in conformance) {
    print('  $e');
  }
}

void _printLinks(Links links) {
  if (links.all.isNotEmpty) {
    print('  Links:');
    for (final link in links.all) {
      print('    ${link.rel} : ${link.href}');
    }
  }
}

void _printCollection(CollectionMeta meta) {
  _printResource(meta);
  final extent = meta.extent;
  if (extent != null) {
    print('    extent crs: ${extent.crs}');
    for (final bounds in extent.allBounds) {
      print('    spatial bbox min: ${bounds.min.values}');
      print('    spatial bbox max: ${bounds.max.values}');
    }
    for (final interval in extent.allIntervals) {
      if (!interval.isOpen) {
        print('    temporal interval: $interval');
      }
    }
  }
}

void _printResource(ResourceMeta meta) {
  if (meta is CollectionMeta) {
    print('  ${meta.id} (${meta.title})');
  } else {
    print('  ${meta.title}');
  }
  if (meta.description != null) {
    print('    ${meta.description}');
  }
}
3
likes
0
pub points
52%
popularity

Publisher

verified publishernavibyte.com

A geospatial client to read GeoJSON and OGC API Features data sources.

Homepage
Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

equatable, geocore, http, meta

More

Packages that depend on geodata