Arbeitsverzeichnis für Pendel-Redaktion. Beinhaltet Skripte sowie alle Pendel-Inhalte.
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

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()