diff --git a/osm_fieldwork/basemapper.py b/osm_fieldwork/basemapper.py index ebc55d9a..e6c90758 100755 --- a/osm_fieldwork/basemapper.py +++ b/osm_fieldwork/basemapper.py @@ -22,8 +22,10 @@ import argparse import concurrent.futures import logging +import os import queue import re +import shutil import sys import threading from io import BytesIO @@ -340,7 +342,7 @@ def getTiles( log.info("%d threads, %d tiles" % (cores, total)) mirrors = [self.sources[self.source]] - # epdb.st() + if len(self.tiles) < chunk or chunk == 0: dlthread(self.base, mirrors, self.tiles, self.xy) else: @@ -596,6 +598,51 @@ def create_basemap_file( log.info(f"Wrote {outfile}") +def move_tiles( + boundary=None, + indir=None, + outdir=None, +) -> None: + """Move tiles within a boundary to another directory. Used for managing the + map tile cache. + + Args: + boundary (str | BytesIO, optional): The boundary for the area you want. + indir (str, optional): Top level directory for existing tile cache. + outdir (str, optional): Output directory name for the new tile cache. + + Returns: + None + """ + bbox_factory = BoundaryHandlerFactory(boundary) + bbox = bbox_factory.get_bounding_box() + zooms = os.listdir(indir) + + if not Path(outdir).exists(): + log.info(f"Making {outdir}...") + + for level in zooms: + tiles = list(mercantile.tiles(bbox[0], bbox[1], bbox[2], bbox[3], int(level))) + total = len(tiles) + log.info("%d tiles for zoom level %r" % (total, level)) + + for tile in tiles: + base = f"{tile.z}/{tile.y}/{tile.x}.jpg" + inspec = f"{indir}/{base}" + if Path(inspec).exists(): + # log.debug("Input tile %s exists" % inspec) + root = os.path.basename(indir) + outspec = f"{outdir}/{root}/{tile.z}/{tile.y}" + if not Path(outspec).exists(): + os.makedirs(outspec) + outspec += f"/{tile.x}.jpg" + # print(f"Move {inspec} to {outspec}") + shutil.move(inspec, outspec) + else: + # log.debug("Input tile %s doesn't exist" % inspec) + continue + + def main(): """This main function lets this class be run standalone by a bash script.""" parser = argparse.ArgumentParser(description="Create an tile basemap for ODK Collect") @@ -615,7 +662,8 @@ def main(): "-o", "--outfile", required=False, help="Output file name, allowed extensions [.mbtiles/.sqlitedb/.pmtiles]" ) parser.add_argument("-z", "--zooms", default="12-17", help="The Zoom levels") - parser.add_argument("-d", "--outdir", help="Output directory name for tile cache") + parser.add_argument("-d", "--outdir", help="Output directory name for new tile cache") + parser.add_argument("-m", "--move", help="Move tiles to different directory") parser.add_argument("-a", "--append", action="store_true", default=False, help="Append to an existing database file") parser.add_argument( "-s", @@ -631,6 +679,11 @@ def main(): parser.print_help() quit() + if args.move and args.outfile is not None: + log.error("You can't move files to the same directory!") + parser.print_help() + # quit() + if not args.source: log.error("You need to specify a source!") parser.print_help() @@ -664,6 +717,14 @@ def main(): stream=sys.stdout, ) + if args.move is not None and args.outdir is None: + log.error("You need to specify the new tile cache directory!") + parser.print_help() + quit() + elif args.move is not None and args.outdir is not None: + move_tiles(boundary_parsed, args.move, args.outdir) + return + create_basemap_file( boundary=boundary_parsed, tms=args.tms,