/usr/lib/python3/dist-packages/rasterio/rio/bounds.py is in python3-rasterio 0.36.0-2build5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | import logging
import os
import click
from cligj import (
precision_opt, indent_opt, compact_opt, projection_geographic_opt,
projection_mercator_opt, projection_projected_opt, sequence_opt,
use_rs_opt, geojson_type_feature_opt, geojson_type_bbox_opt,
geojson_type_collection_opt)
from .helpers import write_features, to_lower
import rasterio
from rasterio.warp import transform_bounds
logger = logging.getLogger('rio')
# Bounds command.
@click.command(short_help="Write bounding boxes to stdout as GeoJSON.")
# One or more files, the bounds of each are a feature in the collection
# object or feature sequence.
@click.argument('INPUT', nargs=-1, type=click.Path(), required=True)
@precision_opt
@indent_opt
@compact_opt
@projection_geographic_opt
@projection_projected_opt
@projection_mercator_opt
@click.option(
'--dst-crs', default='', metavar="EPSG:NNNN", callback=to_lower,
help="Output in specified coordinates.")
@sequence_opt
@use_rs_opt
@geojson_type_collection_opt(True)
@geojson_type_feature_opt(False)
@geojson_type_bbox_opt(False)
@click.pass_context
def bounds(ctx, input, precision, indent, compact, projection, dst_crs,
sequence, use_rs, geojson_type):
"""Write bounding boxes to stdout as GeoJSON for use with, e.g.,
geojsonio
$ rio bounds *.tif | geojsonio
If a destination crs is passed via dst_crs, it takes precedence over
the projection parameter.
"""
import rasterio.warp
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
logger = logging.getLogger('rio')
dump_kwds = {'sort_keys': True}
if indent:
dump_kwds['indent'] = indent
if compact:
dump_kwds['separators'] = (',', ':')
stdout = click.get_text_stream('stdout')
# This is the generator for (feature, bbox) pairs.
class Collection(object):
def __init__(self, env):
self._xs = []
self._ys = []
self.env = env
@property
def bbox(self):
return min(self._xs), min(self._ys), max(self._xs), max(self._ys)
def __call__(self):
for i, path in enumerate(input):
with rasterio.open(path) as src:
bounds = src.bounds
if dst_crs:
bbox = transform_bounds(src.crs,
dst_crs, *bounds)
elif projection == 'mercator':
bbox = transform_bounds(src.crs,
{'init': 'epsg:3857'}, *bounds)
elif projection == 'geographic':
bbox = transform_bounds(src.crs,
{'init': 'epsg:4326'}, *bounds)
else:
bbox = bounds
if precision >= 0:
bbox = [round(b, precision) for b in bbox]
yield {
'type': 'Feature',
'bbox': bbox,
'geometry': {
'type': 'Polygon',
'coordinates': [[
[bbox[0], bbox[1]],
[bbox[2], bbox[1]],
[bbox[2], bbox[3]],
[bbox[0], bbox[3]],
[bbox[0], bbox[1]]]]},
'properties': {
'id': str(i),
'title': path,
'filename': os.path.basename(path)}}
self._xs.extend(bbox[::2])
self._ys.extend(bbox[1::2])
try:
with rasterio.Env(CPL_DEBUG=verbosity > 2) as env:
write_features(
stdout, Collection(env), sequence=sequence,
geojson_type=geojson_type, use_rs=use_rs,
**dump_kwds)
except Exception:
logger.exception("Exception caught during processing")
raise click.Abort()
|