You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
4.3 KiB
175 lines
4.3 KiB
import argparse |
|
import csv |
|
import os.path as path |
|
import re |
|
|
|
importdir = 'images' |
|
datafile = path.join(importdir, 'gps.csv') |
|
args = None |
|
|
|
# Imported data with appended attributes as list of lists |
|
# Items: |
|
# - Image file name |
|
# - lon, lat |
|
# - title, description |
|
# - x, y: Default tile position |
|
data = None |
|
|
|
# Has message in error case |
|
error = None |
|
|
|
# How many tiles on the canvas in (x, y) |
|
matrixdims = (6, 3) |
|
|
|
|
|
def parse_args(): |
|
parser = argparse.ArgumentParser(description="Site Builder Main Program") |
|
parser.add_argument('-i', '--importdir', type=str, help=f'Path to images directory, default={importdir}', default=importdir) |
|
parser.add_argument('-d', '--datafile', type=str, help=f'Filename of CSV data file, default={datafile}', default=datafile) |
|
parser.add_argument('-v', '--verbose', action='store_true', help='Enable verbose output') |
|
parser.add_argument('-vv', '--veryverbose', action='store_true', help='Enable very verbose output') |
|
return parser.parse_args() |
|
|
|
|
|
def log(message): |
|
if args.verbose or args.veryverbose: |
|
print(message) |
|
|
|
def logvv(message): |
|
if args.veryverbose: |
|
print(message) |
|
|
|
|
|
def exit_with_error(message): |
|
print(message) |
|
exit(1) |
|
|
|
|
|
def read_csv_to_dict(csv_file): |
|
""" |
|
Reads a CSV file and returns a list of dictionaries, one per row. |
|
Assumes the first row contains headers. |
|
In error case, returns None |
|
""" |
|
global message |
|
data = [] |
|
with open(csv_file, newline='', encoding='utf-8') as f: |
|
reader = csv.reader(f, skipinitialspace=False, delimiter='\t') |
|
log(f"Read lines from {csv_file}") |
|
|
|
for row in reader: |
|
|
|
logvv(f"Processing row: {row}") |
|
|
|
if not row or len(row) < 4: |
|
message = f"Invalid row: {row}" |
|
return None |
|
|
|
if not ' ' in row[1].strip(): |
|
message = f'Invalid location: {row[1]}' |
|
return None |
|
|
|
geo = re.findall(r'[\d]*[.][\d]+', row[1]) |
|
|
|
if len(geo) != 2: |
|
message = f'Invalid loc/lon: {row[1]}' |
|
|
|
values = [ row[0], float(geo[0]), float(geo[1]), row[2], row[3] ] |
|
data.append(values) |
|
logvv(f"Read row : {values}") |
|
|
|
if len(data) == 0: |
|
message = f'Empty file: {csv_file}' |
|
return None |
|
else: |
|
log(f'Imported {len(data)} records.') |
|
|
|
return data |
|
|
|
|
|
def read_importdata(): |
|
|
|
global data |
|
|
|
if not path.exists(args.importdir): |
|
exit_with_error(f"Error: Import directory '{args.importdir}' does not exist.") |
|
|
|
if not path.exists(args.datafile): |
|
exit_with_error(f"Error: Data file '{args.datafile}' does not exist.") |
|
|
|
log(f"Import directory: {args.importdir}") |
|
log(f"Data file: {args.datafile}") |
|
|
|
data = read_csv_to_dict(args.datafile) |
|
|
|
if data is None: |
|
exit_with_error(message) |
|
|
|
log("Read successful") |
|
|
|
|
|
def find_geo_extrema(data): |
|
""" |
|
Find min and max location values for lon and lat. |
|
Returns (lonmin, lonmax, latmin, latmax) or None in error case. |
|
""" |
|
|
|
if len(data) == 0: |
|
return None |
|
|
|
lonmin = lonmax = data[0][1] |
|
latmin = latmax = data[0][2] |
|
|
|
for entry in data[1:]: |
|
if entry[1] < lonmin: |
|
lonmin = entry[1] |
|
if entry[1] > lonmax: |
|
lonmax = entry[1] |
|
if entry[2] < latmin: |
|
latmin = entry[2] |
|
if entry[2] > latmax: |
|
latmax = entry[2] |
|
|
|
return (lonmin, lonmax, latmin, latmax) |
|
|
|
|
|
def translate_pos(min, max, pos, size): |
|
"""Values must be numbers.""" |
|
|
|
return round((pos - min) / (max - min) * size) |
|
|
|
def append_tile_pos(data, geo_extrema, matrixdims): |
|
""" |
|
Adds two columns with x and y position (integer) of the tile in the canvas |
|
""" |
|
|
|
ret = [] |
|
|
|
for e in data: |
|
x = translate_pos(geo_extrema[2], geo_extrema[3], e[2], matrixdims[0]) |
|
y = translate_pos(geo_extrema[0], geo_extrema[1], e[1], matrixdims[1]) |
|
|
|
e.append(x) |
|
e.append(y) |
|
|
|
ret.append(e) |
|
logvv(f'Data updated: {e}') |
|
|
|
return ret |
|
|
|
def calculate_orig_pos(): |
|
global data |
|
geo_extrema = find_geo_extrema(data) |
|
data = append_tile_pos(data, geo_extrema, matrixdims) |
|
|
|
|
|
def main(): |
|
global args |
|
args=parse_args() |
|
read_importdata() |
|
calculate_orig_pos() |
|
log("Finished.") |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |