import os imgbase = u"E:\\Images" def old_to_new(val): if str(val)[-1] not in "NSEW": return float(val) newval = float(val[:-1])/100.0 if val[-1] in "SW": newval = -newval return newval def mark_bad(when): open(os.path.join(imgbase, "%s.bad" % when),"w").close() def scan_where(): fields = {} for f in os.listdir(imgbase): if not f.endswith(".where"): continue imgpath = os.path.join(imgbase, f) if os.path.exists(imgpath.replace(".where",".bad")): continue bits = open(imgpath,"r").read() if bits.startswith("("): words=eval(bits) else: words=bits.split(" ") lat, lon = map(old_to_new,words[:2]) when, discard = os.path.splitext(f) fields[when] = (lat, lon) return fields import key_codes import e32 lock=e32.Ao_lock() running=1 def quit(): global running,lock running=0 lock.signal() def refresh(): # just wakes up, doesn't do anything directly global lock lock.signal() import appuifw appuifw.app.screen='full' appuifw.app.exit_key_handler=quit import graphics c=appuifw.Canvas() appuifw.app.body=c c.bind(key_codes.EKey9,refresh) def nextday(): global dayno, pointno dayno += 1 if dayno >= len(days): dayno = 0 pointno = 0 render() def prevday(): global dayno, pointno dayno -= 1 if dayno < 0: dayno = len(days)-1 pointno = 0 render() def nextpoint(): global pointno pointno += 1 render() def prevpoint(): global pointno pointno -= 1 render() # really need a "point" data type... def pointstep(pt1, pt2, nsteps): pt1_x, pt1_y = pt1 pt2_x, pt2_y = pt2 return ((pt2_x - pt1_x)/nsteps, (pt2_y - pt1_y)/nsteps) def addpoints(pt, dpt): pt_x, pt_y = pt dpt_x, dpt_y = dpt return (pt_x + dpt_x, pt_y + dpt_y) def animate_boxes(start_point, latscale, lonscale, steps): # ds.rectangle ( (pt1, pt2), color) # assume corners, so we just have to do 2 of them end_1 = (latscale.inmax, lonscale.inmin) # upper left end_2 = (latscale.inmin, lonscale.inmax) # lower right step_1 = pointstep(start_point, end_1, steps) step_2 = pointstep(start_point, end_2, steps) run_1 = start_point run_2 = start_point for _ in range(steps): run_1 = addpoints(run_1, step_1) run_2 = addpoints(run_2, step_2) # print (latlon_to_xy(run_1, latscale, lonscale), latlon_to_xy(run_2, latscale, lonscale)) # print yellow #rectx1, recty1 = latlon_to_xy(run_1, latscale, lonscale) #rectx2, recty2 = latlon_to_xy(run_2, latscale, lonscale) #ds.rectangle( ((rect, ), yellow, width=3) ds.rectangle( (latlon_to_xy(run_1, latscale, lonscale), latlon_to_xy(run_2, latscale, lonscale)), yellow, width=3) e32.ao_sleep(0.1) ds.rectangle( (latlon_to_xy(run_1, latscale, lonscale), latlon_to_xy(run_2, latscale, lonscale)), 0, width=3) # ds.line( (latlon_to_xy(run_1, latscale, lonscale), latlon_to_xy(run_2, latscale, lonscale)), green, width=3) def viewpicture(): # dayno + pointno... print dayno, pointno # lifted from render(): points = points_of_day(allpoints, days[dayno]) latscale, lonscale, order = make_scalers(points) dkey = order[pointno] imgpath = os.path.join(imgbase, dkey + ".jpg") lat, lon = points[dkey] # animation! print lat, lon animate_boxes((lat, lon), latscale, lonscale, 5) # steps # now open the picture appuifw.Content_handler(refresh).open(imgpath) def badpicture(): # dayno + pointno... print dayno, pointno # lifted from render(): points = points_of_day(allpoints, days[dayno]) latscale, lonscale, order = make_scalers(points) dkey = order[pointno] del allpoints[dkey] mark_bad(dkey) render() c.bind(key_codes.EKeyLeftArrow, prevday) c.bind(key_codes.EKeyRightArrow, nextday) c.bind(key_codes.EKeyDownArrow, nextpoint) c.bind(key_codes.EKeyUpArrow, prevpoint) c.bind(key_codes.EKeyDevice3, viewpicture) c.bind(key_codes.EKeyStar, badpicture) ds=graphics.Draw(c) class scaler: def __init__(self, insamp): self.inmin = insamp self.inmax = insamp self.outmin = None self.outmax = None def addval(self, v): self.inmin = min(self.inmin, v) self.inmax = max(self.inmax, v) def scale(self, v): inrange = self.inmax - self.inmin outrange = self.outmax - self.outmin return self.outmin + outrange *(v - self.inmin)/inrange def center(self): inrange = self.inmax - self.inmin return self.inmin + inrange/2 def make_scalers(points): order = points.keys() order.sort() samplat, samplon = points[order[0]] latscale = scaler(samplat) lonscale = scaler(samplon) for lat, lon in points.values(): latscale.addval(lat) lonscale.addval(lon) max_x,max_y = c.size latscale.outmin = 0 latscale.outmax = max_y lonscale.outmin = 0 lonscale.outmax = max_x return latscale, lonscale, order def find_days(points): days = {} for k in points.keys(): d,t = k.split("t") days[d] = days.get(d,0) + 1 daylist = days.keys() daylist.sort() # require 2 points for a day to count return [day for day in daylist if days[day] > 2] #def find_hours(points): # days = {} # for k in points.keys(): # d,t = k.split("t") # dd = d + "t" + t[:2] # days[dd] = days.get(dd,0) + 1 # daylist = days.keys() # daylist.sort() # # require 2 points for a day to count # return [day for day in daylist if days[day] > 2] def points_of_day(points, day): subpoints = {} for k,v in points.items(): d,t = k.split("t") if d == day: # or say d.startswith(day) to handle prefix hours? subpoints[k] = v return subpoints allpoints = scan_where() days = find_days(allpoints) #hours = find_hours(allpoints) dayno = 0 pointno = 0 # point within day def bothscale(point, latscale, lonscale): lat, lon = point return (latscale.scale(lat), lonscale.scale(lon)) def latlon_to_xy(point, latscale, lonscale): neglat, lon = bothscale(point, latscale, lonscale) return lon, latscale.outmax - neglat blue = (0,0,255) green = (0,255,0) red = (255,0,0) yellow = (255,255,0) def render(): ds.clear(0) max_x,max_y = c.size points = points_of_day(allpoints, days[dayno]) latscale, lonscale, order = make_scalers(points) # note that %.3g doesn't truncate at all, though that may be documented label = u"Day %s/%s: c %.4s,%.4s" % (dayno+1, len(days), latscale.center(),lonscale.center()) ds.text( (0,max_y), label, yellow) # do this here instead of in prevpoint/nextpoint because they don't know our bounds global pointno if pointno >= len(order): pointno = len(order) - 1 if pointno < 0: pointno = 0 pointkey = order[pointno] lastpoint = points[order.pop(0)] if pointno == 0: ds.point(latlon_to_xy(lastpoint, latscale, lonscale), yellow, width=4) else: ds.point(latlon_to_xy(lastpoint, latscale, lonscale), blue, width=4) # lastd, lastt = order[0].split("t") for k in order: # sleep makes the rendering order visible, but we don't need that with a cursor # e32.ao_sleep(0.1) thispoint = points[k] # plot from lastpoint to thispoint, scaled by size ds.line((latlon_to_xy(lastpoint, latscale, lonscale), latlon_to_xy(thispoint, latscale, lonscale)), green) lastpoint = thispoint if k == pointkey: # cursor ds.point(latlon_to_xy(thispoint, latscale, lonscale), yellow, width=4) # d,t = k.split("t") # if d != lastd: # ds.point(latlon_to_xy(lastpoint, latscale, lonscale), yellow, width=2) # lastd = d # what about pictures? # keep an "nth" point, use up-down to select # click to show, just "open" it? or imgviewer render it? # add "delete this point" too, make a .bad file? while running: e32.ao_sleep(0.5) render() lock.wait()