def main(argv): try: import psyco psyco.full() except ImportError: pass try: CONF_FILE = str(argv[4]) except (IndexError, ValueError): debug("no config file given, using the default 'scanaerial.cfg'") CONF_FILE = "scanaerial.cfg" try: config = ConfigParser.ConfigParser() config.readfp(open(sys.path[0] + '/' + CONF_FILE)) except: debug('could not read config file %s' % CONF_FILE) exit(1) try: INPUT_LAT = float(argv[1]) INPUT_LON = float(argv[2]) except (IndexError, ValueError): debug("this program expects latitude longitude, now running debug mode") INPUT_LAT = 51.0720147 INPUT_LON = 7.2181707 try: ZOOM = int(float(argv[3])) except (IndexError, ValueError): ZOOM = config.getint('WMS', 'fixedzoomlevel') debug("could not read TZoom from commandline, fixed zoom level %d is used" % ZOOM) # Coordinates from command string. # (format is decimal, for SAS-planet go to Settings and set'em there as --d. # You can use SAS-Planet: click right mouse button on center of forest. # SET SOME CONSTANTS BLACK = 0 WHITE = 1 PROGRAM_START_TIMESTAMP = clock() WMS_SERVER_URL = config.get('WMS', 'wms_server_url') PROJECTION = config.get('WMS', 'projection') TILE_SIZE = (config.getint('WMS', 'tile_sizex'), config.getint('WMS', 'tile_sizey')) #FIXME natural:water should go to .cfg NODES but how? It would be nice if the user could expand it for more keys. WAY_TAGS = {"source:tracer":"scanaerial", \ "source:zoomlevel": ZOOM , \ "source:position": config.get('WMS', 'wmsname'), \ "natural":"water"} POLYGON_TAGS = WAY_TAGS.copy() POLYGON_TAGS["type"] = "multipolygon" #smoothness of way, bigger = less dots and turns = 0.6-1.3 is ok DOUGLAS_PEUCKER_EPSILON = config.getfloat('SCAN', 'douglas_peucker_epsilon') #sensivity for colour change, bigger = larger area covered = 20-23-25 is ok colour_str = config.getfloat('SCAN', 'colour_str') web = WmsCanvas(WMS_SERVER_URL, PROJECTION, ZOOM, TILE_SIZE, mode = "RGB") was_expanded = True normales_list = [] mask = WmsCanvas(None, PROJECTION, ZOOM, TILE_SIZE, mode = "1") debug("proj=%s, z=%s" % (PROJECTION, ZOOM)) ## Getting start pixel ## x, y = web.PixelFrom4326(INPUT_LON, INPUT_LAT) x, y = int(x), int(y) INITCOLOUR = web[x, y] debug("INITCOLOUR = %s" % str(INITCOLOUR)) colour_table = {} DIRECTIONS = [(1, 0), (-1, 0), (0, 1), (0, -1)] queue = set([(x, y), ]) mask[x, y] = WHITE ttz = clock() normales_list = set([]) norm_dir = {(0, -1):0, (1, 0):1, (0, 1):2, (-1, 0):3} while queue: px = queue.pop() for d in DIRECTIONS: x1, y1 = px[0] + d[0], px[1] + d[1] if mask[x1, y1] is not WHITE: col = web[x1, y1] if col not in colour_table: try: colour_table[col] = (distance(INITCOLOUR, col) <= colour_str) except: debug(web.tiles) debug(mask.tiles) if colour_table[col]: mask[x1, y1] = WHITE queue.add((x1, y1)) debug("First walk (masking): %s" % str(clock() - ttz)) debug("Colour table has %s entries" % len(colour_table)) queue = [(x, y), ] ttz = clock() mask.MaxFilter(config.getint('SCAN', 'maxfilter_setting')) debug("B/W MaxFilter: %s" % str(clock() - ttz)) del web oldmask = mask mask = WmsCanvas(None, PROJECTION, ZOOM, TILE_SIZE, mode = "1") bc = 1 ttz = clock() while queue: px = queue.pop() for d in DIRECTIONS: x1, y1 = px[0] + d[0], px[1] + d[1] if mask[x1, y1] is not WHITE and oldmask[x1, y1] is WHITE: mask[x1, y1] = WHITE bc += 1 queue.append((x1, y1)) if oldmask[x1, y1] is not WHITE: normales_list.add(((x1 + px[0]) / 2., \ (y1 + px[1]) / 2., \ norm_dir[px[0] - x1, px[1] - y1])) debug("Found %s normales here." % len(normales_list)) debug("Second walk (leaving only poly): %s" % str(clock() - ttz)) stdout.write('<osm version="0.6">') node_num = 0 way_num = 0 outline = [] popped = False lin = [] tz = clock() while normales_list: if not popped: x, y, d = normales_list.pop() lin = [(x, y), ] popped = True found = False if d is 0: #up-pointing vector search = [(x + 0.5, y - 0.5, 3), (x + 1, y, 0), (x + 0.5, y + 0.5, 1)] if d is 1: search = [(x + 0.5, y + 0.5, 0), (x, y + 1, 1), (x - 0.5, y + 0.5, 2)] if d is 2: search = [(x - 0.5, y + 0.5, 1), (x - 1, y, 2), (x - 0.5, y - 0.5, 3)] if d is 3: search = [(x - 0.5, y - 0.5, 2), (x, y - 1, 3), (x + 0.5, y - 0.5, 0)] for kp in search: if kp in normales_list: normales_list.remove(kp) x, y, d = kp lin.append((x, y)) found = True break if not found: popped = False if not config.getint('SCAN', 'deactivate_simplifying'): lin = douglas_peucker(lin, DOUGLAS_PEUCKER_EPSILON) debug("line found; simplified to %s" % len(lin)) else: debug("skipped simplifing") if len(lin) >= 6: outline.append(lin) lin = [] if lin: lin = douglas_peucker(lin, DOUGLAS_PEUCKER_EPSILON) debug("line post-found; simplified to %s" % len(lin)) if len(lin) >= 4: outline.append(lin) debug("Normales walk: %s, " % (str(clock() - ttz),)) roles = {} for lin in outline: area = 0 prx, pry = lin[-1] for x, y in lin: area += (x * pry - y * prx) / 2 prx = x pry = y node_num -= 1 lon, lat = oldmask.PixelAs4326(x, y) stdout.write('<node id="%s" lon="%s" lat="%s" version="1" />' % (node_num, lon, lat)) way_num -= 1 roles[way_num] = (area > 0) stdout.write('<way id="%s" version="1">' % (way_num)) for y in range(node_num, node_num + len(lin)): stdout.write('<nd ref="%s" />' % (y)) stdout.write('<nd ref="%s" />' % (node_num)) if len(outline) == 1: for z in WAY_TAGS.iteritems(): stdout.write(' <tag k="%s" v="%s" />"' % z) stdout.write("</way>") if way_num < -1: stdout.write('<relation id="-1" version="1">') for y in range(way_num, 0): role = ("inner", "outer")[int(roles[y])] stdout.write('<member type="way" ref="%s" role="%s" />' % (y, role)) for z in POLYGON_TAGS.iteritems(): stdout.write(' <tag k="%s" v="%s" />"' % z) stdout.write('</relation>') stdout.write("</osm>") stdout.flush() debug("All done in: %s" % str(clock() - PROGRAM_START_TIMESTAMP))
px = queue.pop() for d in DIRECTIONS: x1, y1 = px[0] + d[0], px[1] + d[1] if (x - SIZE_LIMIT) > x1: continue if (x + SIZE_LIMIT) < x1: continue if (y - SIZE_LIMIT) > y1: continue if (y + SIZE_LIMIT) < y1: continue if mask[x1, y1] is not WHITE: col = web[x1, y1] if col not in colour_table: try: colour_table[col] = (distance(INITCOLOUR, col) <= colour_str) except: debug(web.tiles) debug(mask.tiles) if colour_table[col]: mask[x1, y1] = WHITE queue.add((x1, y1)) debug("First walk (masking): %s" % str(process_time() - ttz)) debug("Colour table has %s entries" % len(colour_table)) queue = [ (x, y), ] ttz = process_time()
DIRECTIONS = [(1, 0), (-1, 0), (0, 1), (0, -1)] queue = set([(x, y), ]) mask[x, y] = WHITE ttz = clock() normales_list = set([]) norm_dir = {(0, -1):0, (1, 0):1, (0, 1):2, (-1, 0):3} while queue: px = queue.pop() for d in DIRECTIONS: x1, y1 = px[0] + d[0], px[1] + d[1] if mask[x1, y1] is not WHITE: col = web[x1, y1] if col not in colour_table: try: colour_table[col] = (distance(INITCOLOUR, col) <= colour_str) except: debug(web.tiles) debug(mask.tiles) if colour_table[col]: mask[x1, y1] = WHITE queue.add((x1, y1)) debug("First walk (masking): %s" % str(clock() - ttz)) debug("Colour table has %s entries" % len(colour_table)) queue = [(x, y), ] ttz = clock() mask.MaxFilter(config.getint('SCAN', 'maxfilter_setting')) debug("B/W MaxFilter: %s" % str(clock() - ttz)) del web