def weather(self): dummy,routes=get_route(tripuser(),request.params['tripname']) ret=[] alts=request.params.get('alts','') if alts==None: altvec=[] else: altvec=alts.split(",") for route,altitude in zip(routes,altvec): #print("Looking for waypoint: %s"%(way.pos,)) try: mapper.parse_elev(altitude) except mapper.NotAnAltitude,cause: ret.append(['','']) continue #skip this alt #N+1 selects.... merc1=mapper.latlon2merc(mapper.from_str(route.a.pos),14) merc2=mapper.latlon2merc(mapper.from_str(route.a.pos),14) center=(0.5*(merc1[0]+merc2[0]),0.5*(merc1[1]+merc2[1])) lat,lon=mapper.merc2latlon(center,14) #print "Fetching weather for %s,%s, %s"%(lat,lon,route.altitude) when=route.depart_dt+(route.arrive_dt-route.depart_dt)/2 dummy1,dummy2,we=gfs_weather.get_prognosis(when) if we==None: return ""; #Fail completely we don't have the weather here. We only succeed if we have weather for all parts of the journey. else: try: wi=we.get_wind(lat,lon,mapper.parse_elev(altitude)) except: print traceback.format_exc() return "" #print "Got winds:",wi ret.append([wi['direction'],wi['knots']])
def load_ad_json(self,ac): out=[] physical=[] for rwy in ac['runways']: curphys=[] for i,end in enumerate(rwy['ends']): endb=rwy['ends'][(i+1)%2] usable_pos=end.get("usable_pos",end['pos']) usable_posb=endb.get("usable_pos",endb['pos']) brg1,runway_dist=mapper.bearing_and_distance(mapper.from_str(usable_pos),mapper.from_str(usable_posb)) #brg2,landing_dist=mapper.bearing_afnd_distance(mapper.from_str(end['pos']),mapper.from_str(usable_posb)) brgdummy,threshold_dist=mapper.bearing_and_distance(mapper.from_str(usable_pos),mapper.from_str(end['pos'])) out.append(dict( name=end['thr'], rwyhdg=brg1, runway_length=runway_dist*1852.0, threshold=threshold_dist*1852.0 )) curphys.append(dict( name=end['thr'], pos=end['pos'], usable_pos=end.get("usable_pos",end['pos']), threshold=threshold_dist*1852.0)) physical.append(curphys) jsonstr=json.dumps(dict(runways=out,physical=physical)) print "JSON:",jsonstr return jsonstr
def enroutenotams(self): c.techroute, c.route = get_route(tripuser(), session['current_trip']) c.tripobj = meta.Session.query(Trip).filter( sa.and_(Trip.user == tripuser(), Trip.trip == session['current_trip'])).one() if len(c.route) == 0 or len(c.techroute) == 0: redirect( h.url_for(controller='flightplan', action="index", flash=u"Must have at least two waypoints in trip!")) return c.trip = c.tripobj.trip for rt in c.route: rt.notampoints = dict() rt.notampoints.update( dict([(info['item']['notam'], info['item']) for info in get_notampoints_on_line(mapper.from_str(rt.a.pos), mapper.from_str(rt.b.pos), 5)])) for rt in c.route: for space in get_notam_areas_on_line(mapper.from_str(rt.a.pos), mapper.from_str(rt.b.pos)): rt.notampoints[space['name']] = space c.thislink = h.url_for(controller='flightplan', action="enroutenotams") return render('/enroutenotams.mako')
def draw_cmds(): for d in ad['physical']: yield (mapper.latlon2merc(mapper.from_str(getpos(d[0])), 20), mapper.latlon2merc(mapper.from_str(getpos(d[1])), 20), d[0]['name'], d[1]['name'], d[0]['threshold'], d[1]['threshold'])
def weather(self): dummy, routes = get_route(tripuser(), request.params['tripname']) ret = [] alts = request.params.get('alts', '') if alts == None: altvec = [] else: altvec = alts.split(",") for route, altitude in zip(routes, altvec): #print("Looking for waypoint: %s"%(way.pos,)) try: mapper.parse_elev(altitude) except mapper.NotAnAltitude, cause: ret.append(['', '']) continue #skip this alt #N+1 selects.... merc1 = mapper.latlon2merc(mapper.from_str(route.a.pos), 14) merc2 = mapper.latlon2merc(mapper.from_str(route.a.pos), 14) center = (0.5 * (merc1[0] + merc2[0]), 0.5 * (merc1[1] + merc2[1])) lat, lon = mapper.merc2latlon(center, 14) #print "Fetching weather for %s,%s, %s"%(lat,lon,route.altitude) when = route.depart_dt + (route.arrive_dt - route.depart_dt) / 2 dummy1, dummy2, we = gfs_weather.get_prognosis(when) if we == None: return "" #Fail completely we don't have the weather here. We only succeed if we have weather for all parts of the journey. else: try: wi = we.get_wind(lat, lon, mapper.parse_elev(altitude)) except: print traceback.format_exc() return "" #print "Got winds:",wi ret.append([wi['direction'], wi['knots']])
def load_ad_json(self, ac): out = [] physical = [] for rwy in ac['runways']: curphys = [] for i, end in enumerate(rwy['ends']): endb = rwy['ends'][(i + 1) % 2] usable_pos = end.get("usable_pos", end['pos']) usable_posb = endb.get("usable_pos", endb['pos']) brg1, runway_dist = mapper.bearing_and_distance( mapper.from_str(usable_pos), mapper.from_str(usable_posb)) #brg2,landing_dist=mapper.bearing_afnd_distance(mapper.from_str(end['pos']),mapper.from_str(usable_posb)) brgdummy, threshold_dist = mapper.bearing_and_distance( mapper.from_str(usable_pos), mapper.from_str(end['pos'])) out.append( dict(name=end['thr'], rwyhdg=brg1, runway_length=runway_dist * 1852.0, threshold=threshold_dist * 1852.0)) curphys.append( dict(name=end['thr'], pos=end['pos'], usable_pos=end.get("usable_pos", end['pos']), threshold=threshold_dist * 1852.0)) physical.append(curphys) jsonstr = json.dumps(dict(runways=out, physical=physical)) print "JSON:", jsonstr return jsonstr
def querywpname(self): pos=mapper.from_str(request.params['pos']) lat,lon=pos print "Getwpname:",pos zoomlevel=int(request.params['zoomlevel']) sigps=get_sigpoints(lat,lon,zoomlevel) print "Getwpname sigps:",sigps if len(sigps): return json.dumps([sigps[0]['name'],mapper.from_str(sigps[0]['pos'])]) return "notok"
def querywpname(self): pos = mapper.from_str(request.params['pos']) lat, lon = pos print "Getwpname:", pos zoomlevel = int(request.params['zoomlevel']) sigps = get_sigpoints(lat, lon, zoomlevel) print "Getwpname sigps:", sigps if len(sigps): return json.dumps( [sigps[0]['name'], mapper.from_str(sigps[0]['pos'])]) return "notok"
def get_freqs(self,route): for rt in route: rt.freqset=dict() for air in airspace.get_airspaces_on_line(mapper.from_str(rt.a.pos),mapper.from_str(rt.b.pos)): for freq in air['freqs']: try: currs=rt.freqset.setdefault(freq[0],[]) new=fmt_freq(freq[1]) if not new in currs: currs.append(new) except Exception,cause: pass #print "Couldn't add freq %s: %s"%(freq,cause)
def get_freqs(self, route): for rt in route: rt.freqset = dict() for air in airspace.get_airspaces_on_line( mapper.from_str(rt.a.pos), mapper.from_str(rt.b.pos)): for freq in air['freqs']: try: currs = rt.freqset.setdefault(freq[0], []) new = fmt_freq(freq[1]) if not new in currs: currs.append(new) except Exception, cause: pass #print "Couldn't add freq %s: %s"%(freq,cause)
def get_all_tiles_near(routes,zoomlevel,dist_nm,tilesize): resultset=set() for rt in routes: m1=mapper.latlon2merc(mapper.from_str(rt.a.pos),zoomlevel) m2=mapper.latlon2merc(mapper.from_str(rt.b.pos),zoomlevel) av=Vertex(int(m1[0]),int(m1[1])) bv=Vertex(int(m2[0]),int(m2[1])) l=Line(av,bv) startmerc=clampmerc(m1,tilesize) maxdist=mapper.approx_scale(startmerc,zoomlevel,dist_nm) maxdist+=3*tilesize/2 fill(l,startmerc,zoomlevel=zoomlevel,maxdist=maxdist,tilesize=tilesize,result=resultset) return resultset
def get_low_sun_near_route(rts): l=len(rts) out=[] dt=None for idx,rt in enumerate(rts): if rt.dt==None: continue #print "ord:",rt.a.ordering tottime=rt.dt-rt.startdt merca=rt.subposa mercb=rt.subposb curtime=timedelta(0) real_heading=rt.tt+rt.wca while True: if curtime>=tottime: break f=divide(curtime,tottime) fi=1.0-f merc=(fi*merca[0]+f*mercb[0],fi*merca[1]+f*mercb[1]) latlon=mapper.merc2latlon(merc,13) when=rt.startdt+curtime ele,azi=sun_position_in_sky(when,latlon[0],latlon[1]) #print "Sun position: ele=%s, azi=%s, heading=%s"%(ele,azi,real_heading) if (ele>-0.5 and ele<25): off=(azi-real_heading) if abs(off)<25: dirclock=int(round(off/15.0)) if dirclock<=0: dirclock+=12 out.append(dict( name="Low Sun Warning (Direction: %d o'clock, %.0f deg above horizon. Blinding?)"%( dirclock,max(0,ele)), pos=mapper.to_str(latlon), elev="", elevf=0, dist=0, bearing=azi, closestalt=None, kind='lowsun', dist_from_a=mapper.bearing_and_distance(mapper.from_str(rt.a.pos),latlon)[1], dist_from_b=mapper.bearing_and_distance(mapper.from_str(rt.b.pos),latlon)[1], dir_from_a=describe_dir(rt.tt), dir_from_b=describe_dir((rt.tt+180.0)%360.0), a=rt.a, b=rt.b, id=rt.a.id)) print "Generated sun warning:",out[-1] break curtime+=timedelta(minutes=2) return out
def get_notampoints_on_line(latlon1,latlon2,dist_nm): zoomlevel=13 distmax=mapper.approx_scale(mapper.latlon2merc(latlon1,zoomlevel),zoomlevel,dist_nm) px1,py1=mapper.latlon2merc(latlon1,zoomlevel) px2,py2=mapper.latlon2merc(latlon2,zoomlevel) a=Vertex(int(px1),int(py1)) b=Vertex(int(px2),int(py2)) line=Line(a,b) crosses=[] for kind,items in get_notam_objs_cached().items(): if kind!="areas": for item in items: x,y=mapper.latlon2merc(mapper.from_str(item['pos']),zoomlevel) d=line.approx_dist(Vertex(int(x),int(y))) clo=line.approx_closest(Vertex(int(x),int(y))) alongd=(clo-a).approxlength() totd=(a-b).approxlength() #print "AlongD: %s, totd: %s"%(alongd,totd) #print "Line: %s, notam coord: %s, closest: %s"%((a,b),(x,y),clo) #print "Item %s, d: %s, distmax: %s"%(item,d,distmax) if totd<1e-6: perc=0 else: perc=alongd/totd if d<distmax: #print "Yielding item." yield dict(item=item,alongperc=perc)
def clean_up_polygon(poss): print "Clean poly:",poss def tov(merc): return Vertex(int(merc[0]),int(merc[1])) def fromv(v): return (v.get_x(),v.get_y()) vertices=[] last=None for pos in poss: #print pos if pos==last: continue last=pos vertices.append(tov(mapper.latlon2merc(mapper.from_str(pos),13))) poly=Polygon(vvector(vertices)) #print "calling tidy-up" shape=tidy_up_polygon(poly) ret=[] for poly in shape.get_polys(): #print "Got poly" vs=poly.get_vertices() out=[] for v in vs: out.append(mapper.to_str(mapper.merc2latlon(fromv(v),13))) ret.append(out) return ret
def get_stuff_near_route(rts,items,dist,vertdist): for item in items: try: itemmerc=mapper.latlon2merc(mapper.from_str(item['pos']),13) except Exception: print "Bad coord:",item['pos'] continue itemv=Vertex(int(itemmerc[0]),int(itemmerc[1])) onenm=mapper.approx_scale(itemmerc,13,1.0) for rt in rts: if rt.dt==None: continue #print "=========================================" av=Vertex(int(rt.subposa[0]),int(rt.subposa[1])) bv=Vertex(int(rt.subposb[0]),int(rt.subposb[1])) l=Line(av,bv) linelen=(bv-av).approxlength() actualclosest=l.approx_closest(itemv) #print item['name'],"A: ",av,"B: ",bv,"clo:",actualclosest actualdist=(actualclosest-itemv).approxlength()/onenm #print "Actualdist: ",actualdist ls=(actualclosest-av).approxlength() #print "Length from start:",ls #print "Linelen:",linelen if linelen>1e-3: along=ls/linelen else: along=0 #print "Along:",along #print "Startalt:",rt.startalt," endalt: ",rt.endalt alongnm=rt.d*along alongnm_a=rt.relstartd+alongnm #print "NM from ",rt.a.waypoint," is ",alongnm_a closealt=rt.startalt+(rt.endalt-rt.startalt)*along #print "Altitude at point: ",closealt, " before: ",rt.a.waypoint,rt.b.waypoint altmargin=0 if 'elev' in item: itemalt=mapper.parse_elev(item['elev']) altmargin=closealt-itemalt else: itemalt=None altmargin=0 if actualdist<dist and altmargin<vertdist: bear=mapper.approx_bearing_vec(actualclosest,itemv) d=dict(item) #print "Yielding." d['name']=d['kind']+': ' +d['name'] d['dist_from_a']=alongnm_a d['dist_from_b']=rt.outer_d-alongnm_a d['dir_from_a']=describe_dir(rt.tt) d['dir_from_b']=describe_dir((rt.tt+180.0)%360.0) d['dist']=actualdist d['bearing']=bear d['elevf']=itemalt if itemalt!=None: d['vertmargin']=altmargin d['closestalt']=closealt d['a']=rt.a d['b']=rt.b d['id']=rt.a.id yield d
def gpx(self): # Return a rendered template #return render('/flightplan.mako') # or, return a response if not self.validate(tripname=request.params.get('tripname', None), exception=False): return "Internal error. Missing trip-name or user-session." waypoints = list( meta.Session.query(Waypoint).filter( sa.and_(Waypoint.user == tripuser(), Waypoint.trip == c.trip.trip)).order_by( Waypoint.ordering).all()) if len(waypoints) == 0: return redirect( h.url_for(controller='flightplan', action="index", flash=u"Must have at least two waypoints in trip!")) c.waypoints = [] for wp in waypoints: lat, lon = mapper.from_str(wp.pos) c.waypoints.append(dict(lat=lat, lon=lon, name=wp.waypoint)) #response.headers['Content-Type'] = 'application/xml' response.content_type = 'application/octet-stream' response.charset = "utf8" return render('/gpx.mako')
def get_airspaces(routes): for routename,coords,altspec in routes: sig=getsig(coords,altspec) if (routename,sig) in predef: #pobj=None #for sroutename,ssig in predef: # if routename==sroutename: pobj=(routename,sig) width_nm,floor,ceiling,coordstr=predef[pobj] rawcoords=re.findall(ur"(\d{6}N)\s*(\d{7}E)",coordstr) coords=[mapper.latlon2merc(mapper.from_str(mapper.parse_coords(lats,lons)),13) for lats,lons in rawcoords] width=float(mapper.approx_scale(coords[0],13,1.25*width_nm)) try: outline=get_outline(coords,width) except Exception: uprint(u"Trouble parsing %s"%(routename,)) raise yield dict(name=routename, floor=floor, ceiling=ceiling, freqs=[], type="RNAV", points=[mapper.to_str(mapper.merc2latlon(x,13)) for x in outline]) else: uprint("Need to have predefine for route %s, with md5: %s"%(routename,sig)) uprint("Altitude, and points") raise Exception('Missing predef for route. Use: ("%s","%s") : ( 10,"FL 65","FL 95","""\n\n """),'%(routename,sig))
def follow_along13(context,start,end,longwayround=False): if type(context)==list: borders=[[mapper.latlon2merc(mapper.from_str(x),13) for x in points] for points in context] else: borders=get_borders(context) print "start,end",start,end part1,idx1,pos1=find_closest(borders,start) part2,idx2,pos2=find_closest(borders,end) print "Found",pos1,pos2 if part1!=part2: raise Exception("Start and endpoint are not on same island!") part=part1 print "from,to",idx1,idx2 if idx1==idx2: return [start,end] res1,dist1=circle(borders[part],pos1,idx1,idx2,pos2,-1) res2,dist2=circle(borders[part],pos1,idx1,idx2,pos2,1) if dist1<dist2: if longwayround: ret=res2 else: ret=res1 else: if longwayround: ret=res1 else: ret=res2 return [start]+ret+[end]
def follow_along13(context, start, end, longwayround=False): if type(context) == list: borders = [[ mapper.latlon2merc(mapper.from_str(x), 13) for x in points ] for points in context] else: borders = get_borders(context) print "start,end", start, end part1, idx1, pos1 = find_closest(borders, start) part2, idx2, pos2 = find_closest(borders, end) print "Found", pos1, pos2 if part1 != part2: raise Exception("Start and endpoint are not on same island!") part = part1 print "from,to", idx1, idx2 if idx1 == idx2: return [start, end] res1, dist1 = circle(borders[part], pos1, idx1, idx2, pos2, -1) res2, dist2 = circle(borders[part], pos1, idx1, idx2, pos2, 1) if dist1 < dist2: if longwayround: ret = res2 else: ret = res1 else: if longwayround: ret = res1 else: ret = res2 return [start] + ret + [end]
def clean_up_polygon(poss): print "Clean poly:", poss def tov(merc): return Vertex(int(merc[0]), int(merc[1])) def fromv(v): return (v.get_x(), v.get_y()) vertices = [] last = None for pos in poss: #print pos if pos == last: continue last = pos vertices.append(tov(mapper.latlon2merc(mapper.from_str(pos), 13))) poly = Polygon(vvector(vertices)) #print "calling tidy-up" shape = tidy_up_polygon(poly) ret = [] for poly in shape.get_polys(): #print "Got poly" vs = poly.get_vertices() out = [] for v in vs: out.append(mapper.to_str(mapper.merc2latlon(fromv(v), 13))) ret.append(out) return ret
def save(self): #print "Saving tripname:",request.params if not self.validate(exception=False, tripname=request.params.get('tripname', False)): return "" try: waypoints = meta.Session.query(Waypoint).filter( sa.and_(Waypoint.user == tripuser(), Waypoint.trip == c.trip.trip)).order_by( Waypoint.ordering).all() #print "REquest:",request.params c.userobj.realname = request.params.get('realname', c.userobj.realname) for idx, way in enumerate(waypoints): dof_s = "date_of_flight_%d" % (way.id, ) dep_s = "departure_time_%d" % (way.id, ) fuel_s = "fuel_%d" % (way.id, ) persons_s = "persons_%d" % (way.id, ) name_s = "name%d" % (way.id, ) way.waypoint = request.params.get(name_s, way.waypoint) if dof_s in request.params: #possibly add new stay if not way.stay: #print "Adding stay: ord/id",way.ordering,way.id way.stay = Stay(tripuser(), c.trip.trip, way.id) if re.match(ur"\d{4}-?\d{2}\-?\d{2}", request.params.get(dof_s, '')): way.stay.date_of_flight = request.params.get(dof_s, '') else: way.stay.date_of_flight = '' if re.match(ur"\d{2}:?\d{2}", request.params.get(dep_s, '')): way.stay.departure_time = request.params.get(dep_s, '') else: way.stay.departure_time = '' try: way.stay.nr_persons = int(request.params[persons_s]) except Exception: way.stay.nr_persons = None way.stay.fuel = None way.stay.fueladjust = None try: fuelstr = request.params.get(fuel_s, '').strip() if fuelstr.startswith("+") or fuelstr.startswith("-"): way.stay.fueladjust = float(fuelstr) else: way.stay.fuel = float(fuelstr) except Exception: pass way.altitude = unicode( int( get_terrain_elev.get_terrain_elev( mapper.from_str(way.pos)))) else:
def get_pixel_radius(o,zoomlevel): merc=mapper.latlon2merc(mapper.from_str(o['pos']),zoomlevel) draw_radius_nm=(int(o['height'])*2.0*0.16e-3) draw_radius_pixels=mapper.approx_scale(merc,zoomlevel,draw_radius_nm) radius=draw_radius_pixels if radius<4: radius=4 return radius
def get_pos_elev(latlon): for airf in cache.get_airfields(): #print "Considering:",airf apos=mapper.from_str(airf['pos']) dx=apos[0]-latlon[0] dy=apos[1]-latlon[1] if abs(dx)+abs(dy)<0.25*1.0/60.0 and 'elev' in airf: return airf['elev'] return get_terrain_elev(latlon)
def enroutenotams(self): c.techroute,c.route=get_route(tripuser(),session['current_trip']) c.tripobj=meta.Session.query(Trip).filter(sa.and_( Trip.user==tripuser(),Trip.trip==session['current_trip'])).one() if len(c.route)==0 or len(c.techroute)==0: redirect(h.url_for(controller='flightplan',action="index",flash=u"Must have at least two waypoints in trip!")) return c.trip=c.tripobj.trip for rt in c.route: rt.notampoints=dict() rt.notampoints.update(dict([(info['item']['notam'],info['item']) for info in get_notampoints_on_line(mapper.from_str(rt.a.pos),mapper.from_str(rt.b.pos),5)])) for rt in c.route: for space in get_notam_areas_on_line(mapper.from_str(rt.a.pos),mapper.from_str(rt.b.pos)): rt.notampoints[space['name']]=space c.thislink=h.url_for(controller='flightplan',action="enroutenotams") return render('/enroutenotams.mako')
def get_latlon_outline(latlonseq,width_nm): print "Width nm:",width_nm mercseq=[mapper.latlon2merc(mapper.from_str(ll),13) for ll in latlonseq] width=float(mapper.approx_scale(mercseq[0],13,width_nm)) mercout=get_merc_outline(mercseq,width) points=[mapper.to_str(mapper.merc2latlon(x,13)) for x in mercout] return points
def get_notampoints(lat,lon,zoomlevel): clickx,clicky=mapper.latlon2merc((lat,lon),zoomlevel) for kind,items in get_notam_objs_cached().items(): if kind!="areas": for item in items: x,y=mapper.latlon2merc(mapper.from_str(item['pos']),zoomlevel) radius=10 d=(clickx-x)**2+(clicky-y)**2 if d<=(radius)**2: yield item
def get_sigpoints(lat,lon,zoomlevel): clickx,clicky=mapper.latlon2merc((lat,lon),13) rad=8<<(13-zoomlevel) bb=BoundingBox(clickx-rad,clicky-rad,clickx+rad,clicky+rad) out=[] for sigp in cache.get_sig_points_in_bb(bb): x,y=mapper.latlon2merc(mapper.from_str(sigp['pos']),zoomlevel) d=(clickx-x)**2+(clicky-y)**2 out.append((d,sigp)) return [sigp for d,sigp in sorted(out)]
def coordparse(self): val=request.params['val'] try: s=mapper.anyparse(val) c.pos=s c.deg,c.degmin,c.degminsec=mapper.to_all_formats(mapper.from_str(s)) print "Rendering mako coordpres" return render("/coordpres.mako") except Exception: print "returning empty string , coordpres" return ""
def coordparse(self): val = request.params['val'] try: s = mapper.anyparse(val) c.pos = s c.deg, c.degmin, c.degminsec = mapper.to_all_formats( mapper.from_str(s)) print "Rendering mako coordpres" return render("/coordpres.mako") except Exception: print "returning empty string , coordpres" return ""
def search(self): searchstr=request.params.get('search','') ordi=int(request.params.get('ordinal',0)) #print "searching:",searchstr,ordi #time.sleep(1.5*f.random()) latlon_match=re.match(r"(\d+)\.(\d+)([NS])(\d+)\.(\d+)([EW])",searchstr) if latlon_match: latdeg,latdec,ns,londeg,londec,ew=latlon_match.groups() lat=float(latdeg)+float("0."+latdec) lon=float(londeg)+float("0."+londec) if ns in ['S','s']: lat=-lat if ew in ['W','w']: lon=-lon return json.dumps(dict(ordinal=ordi,hits=[['Unknown Waypoint',[lat,lon],'Unknown Waypoint']])) dec_match=re.match(r"\s*(\d+\.\d+)\s*,\s*(\d+\.\d+)\s*",searchstr) if dec_match: latdec,londec=dec_match.groups() lat=float(latdec) lon=float(londec) return json.dumps(dict(ordinal=ordi,hits=[['Unknown Waypoint',[lat,lon],'Unknown Waypoint']])) #print "Searching for ",searchstr searchstr=strip_accents(searchstr).lower() apoints=[] for airp in get_airfields(): if strip_accents(airp['name']).lower().count(searchstr) or \ airp['icao'].lower().count(searchstr): d=dict(airp) d['kind']='airport' apoints.append(d) spoints=[] for sigpoint in get_sig_points(): if strip_accents(sigpoint['name']).lower().count(searchstr): spoints.append(sigpoint) def namekey(x): return x['name'] points=list(sorted(apoints,key=namekey)) points.extend(sorted(spoints,key=namekey)) if len(points)==0: return "" #points.sort(key=lambda x:x['name']) def extract_name(x): if 'kind' in x: return "%s (%s)"%(x['name'],x['kind']) return x.get('name','unknown item') hits=[[extract_name(x),mapper.from_str(x['pos']),x.get('name','unknown item')] for x in points[:15]] ret=json.dumps(dict(ordinal=ordi,hits=hits)) #print "returning json:",ret return ret
def get_airfields(lat,lon,zoomlevel): clickx,clicky=mapper.latlon2merc((lat,lon),13) rad=10 if zoomlevel>=10: rad<<=(zoomlevel-10) rad<<=(13-zoomlevel) bb=BoundingBox(clickx-rad,clicky-rad,clickx+rad,clicky+rad) out=[] for airp in cache.get_airfields_in_bb(bb): x,y=mapper.latlon2merc(mapper.from_str(airp['pos']),zoomlevel) d=(clickx-x)**2+(clicky-y)**2 out.append((d,airp)) return [airp for d,airp in sorted(out)]
def filter_bad_airfields(bad,good): toadd=[] try: bspitems=[] for item in good: bspitems.append(BspTree.Item( mapper.latlon2merc(mapper.from_str(item['pos']),13),item) ) bsp=BspTree(bspitems) for abad in bad: m=mapper.latlon2merc(mapper.from_str(abad['pos']),13) twonm=mapper.approx_scale(m,13,2) bb=BoundingBox(m[0],m[1],m[0],m[1]).expanded(twonm) for ap in bsp.findall_in_bb(bb): print "Not adding bad airfield:",ap.val['name'] break else: toadd.append(abad) except: print "Failed to add bad airfields" raise return toadd
def save(self): #print "Saving tripname:",request.params if not self.validate(exception=False,tripname=request.params.get('tripname',False)): return "" try: waypoints=meta.Session.query(Waypoint).filter(sa.and_( Waypoint.user==tripuser(), Waypoint.trip==c.trip.trip)).order_by(Waypoint.ordering).all() #print "REquest:",request.params c.userobj.realname=request.params.get('realname',c.userobj.realname) for idx,way in enumerate(waypoints): dof_s="date_of_flight_%d"%(way.id,) dep_s="departure_time_%d"%(way.id,) fuel_s="fuel_%d"%(way.id,) persons_s="persons_%d"%(way.id,) name_s="name%d"%(way.id,) way.waypoint=request.params.get(name_s,way.waypoint) if dof_s in request.params: #possibly add new stay if not way.stay: #print "Adding stay: ord/id",way.ordering,way.id way.stay=Stay(tripuser(),c.trip.trip,way.id) if re.match(ur"\d{4}-?\d{2}\-?\d{2}",request.params.get(dof_s,'')): way.stay.date_of_flight=request.params.get(dof_s,'') else: way.stay.date_of_flight='' if re.match(ur"\d{2}:?\d{2}",request.params.get(dep_s,'')): way.stay.departure_time=request.params.get(dep_s,'') else: way.stay.departure_time='' try: way.stay.nr_persons=int(request.params[persons_s]) except Exception: way.stay.nr_persons=None way.stay.fuel=None way.stay.fueladjust=None try: fuelstr=request.params.get(fuel_s,'').strip() if fuelstr.startswith("+") or fuelstr.startswith("-"): way.stay.fueladjust=float(fuelstr) else: way.stay.fuel=float(fuelstr) except Exception: pass way.altitude=unicode(int(get_terrain_elev.get_terrain_elev(mapper.from_str(way.pos)))) else:
def filter_bad_airfields(bad, good): toadd = [] try: bspitems = [] for item in good: bspitems.append( BspTree.Item( mapper.latlon2merc(mapper.from_str(item['pos']), 13), item)) bsp = BspTree(bspitems) for abad in bad: m = mapper.latlon2merc(mapper.from_str(abad['pos']), 13) twonm = mapper.approx_scale(m, 13, 2) bb = BoundingBox(m[0], m[1], m[0], m[1]).expanded(twonm) for ap in bsp.findall_in_bb(bb): print "Not adding bad airfield:", ap.val['name'] break else: toadd.append(abad) except: print "Failed to add bad airfields" raise return toadd
def invent_matrix(self,cksum,variant): print "Variant:",variant for ad in ec.get_airfields(): if not 'adcharts' in ad: continue dbb=False for adchart in ad['adcharts'].values(): if adchart['checksum']==cksum: lat,lon=mapper.from_str(ad['pos']) w,h=adchart['render_width'],adchart['render_height'] print "adpos:",ad['pos'],lat,lon dbb=True break if dbb:break else: raise Exception("Can't find this chart in aipdata") if variant.lower().count('vac'): mercsizex=w mercsizey=h scale=7 else: mercsizex=w mercsizey=h scale=1 print "lat,lon",lat,lon m1=mapper.latlon2merc((lat,lon),13) print "corner merc",m1 ns=[] for offx,offy in [(0,0), (mercsizex,0), (0,mercsizey), (mercsizex,mercsizey)]: merc2=(m1[0]+(offx-mercsizex/2)*scale,m1[1]+(offy-mercsizey/2)*scale) n=AirportMarker() n.latitude,n.longitude=mapper.merc2latlon(merc2,13) n.x,n.y=(offx,offy) ns.append(n) error,A,T=customproj.solve(ns) matrix=list(A)+list(T) print "Fake projection:",matrix return matrix
def get_polygons_around(lat,lon,polys): zoomlevel=13 px,py=mapper.latlon2merc((lat,lon),zoomlevel) insides=[] for space in polys: poly_coords=[] for coord in space['points']: x,y=mapper.latlon2merc(mapper.from_str(coord),zoomlevel) poly_coords.append(Vertex(int(x),int(y))) if len(poly_coords)<3: #print "Space %s has few points: %s "%(space['name'],space['points']) continue poly=Polygon(vvector(poly_coords)) #print "Checking if inside poly:",space if poly.is_inside(Vertex(int(px),int(py))): insides.append(space) #print "Is inside" else: pass#print "Is NOT inside" return insides
def invent_matrix(self, cksum, variant): print "Variant:", variant for ad in ec.get_airfields(): if not 'adcharts' in ad: continue dbb = False for adchart in ad['adcharts'].values(): if adchart['checksum'] == cksum: lat, lon = mapper.from_str(ad['pos']) w, h = adchart['render_width'], adchart['render_height'] print "adpos:", ad['pos'], lat, lon dbb = True break if dbb: break else: raise Exception("Can't find this chart in aipdata") if variant.lower().count('vac'): mercsizex = w mercsizey = h scale = 7 else: mercsizex = w mercsizey = h scale = 1 print "lat,lon", lat, lon m1 = mapper.latlon2merc((lat, lon), 13) print "corner merc", m1 ns = [] for offx, offy in [(0, 0), (mercsizex, 0), (0, mercsizey), (mercsizex, mercsizey)]: merc2 = (m1[0] + (offx - mercsizex / 2) * scale, m1[1] + (offy - mercsizey / 2) * scale) n = AirportMarker() n.latitude, n.longitude = mapper.merc2latlon(merc2, 13) n.x, n.y = (offx, offy) ns.append(n) error, A, T = customproj.solve(ns) matrix = list(A) + list(T) print "Fake projection:", matrix return matrix
def get_airspaces(routes): for routename, coords, altspec in routes: sig = getsig(coords, altspec) if (routename, sig) in predef: #pobj=None #for sroutename,ssig in predef: # if routename==sroutename: pobj = (routename, sig) width_nm, floor, ceiling, coordstr = predef[pobj] rawcoords = re.findall(ur"(\d{6}N)\s*(\d{7}E)", coordstr) coords = [ mapper.latlon2merc( mapper.from_str(mapper.parse_coords(lats, lons)), 13) for lats, lons in rawcoords ] width = float( mapper.approx_scale(coords[0], 13, 1.25 * width_nm)) try: outline = get_outline(coords, width) except Exception: uprint(u"Trouble parsing %s" % (routename, )) raise yield dict(name=routename, floor=floor, ceiling=ceiling, freqs=[], type="RNAV", points=[ mapper.to_str(mapper.merc2latlon(x, 13)) for x in outline ]) else: uprint( "Need to have predefine for route %s, with md5: %s" % (routename, sig)) uprint("Altitude, and points") raise Exception( 'Missing predef for route. Use: ("%s","%s") : ( 10,"FL 65","FL 95","""\n\n """),' % (routename, sig))
def get_polygons_on_line(latlon1,latlon2,polys): zoomlevel=13 px1,py1=mapper.latlon2merc(latlon1,zoomlevel) px2,py2=mapper.latlon2merc(latlon2,zoomlevel) line=Line(Vertex(int(px1),int(py1)),Vertex(int(px2),int(py2))) crosses=[] for space in polys: poly_coords=[] for coord in space['points']: x,y=mapper.latlon2merc(mapper.from_str(coord),zoomlevel) poly_coords.append(Vertex(int(x),int(y))) if len(poly_coords)<3: #print "Space %s has few points: %s "%(space['name'],space['points']) continue poly=Polygon(vvector(poly_coords)) #print "Checking if intersect poly:",space if len(poly.intersect_line(line))>0: crosses.append(space) #print "Is crossing" else: pass#print "Is NOT crossing" return crosses
def get_borders(pcountry): #print "Getting for",pcountry global borders if not borders: if not os.path.exists("fplan/extract/lands.bin"): if os.system("bunzip2 fplan/extract/lands.bin.bz2") != 0: raise Exception("Couldn't unbzip2 lands.bin.bz2") f = open("fplan/extract/lands.bin") tborders = pickle.load(f) f.close() out = dict() for country, parts in tborders.items(): outparts = [] tot = 0 for part in parts: outpart = [] poly_coords = [] last = None for coord in part: merc = mapper.latlon2merc(mapper.from_str(coord), 13) if merc == last: continue last = merc outpart.append(merc) tot += 1 poly_coords.append(Vertex(int(merc[0]), int(merc[1]))) assert len(outpart) >= 3 if outpart[0] == outpart[-1]: outpart = outpart[:-1] poly_coords = poly_coords[:-1] poly = Polygon(vvector(poly_coords)) assert poly.is_ccw() outparts.append(outpart) #print "Parts in ",country,len(outparts),tot out[country] = outparts borders = out #if pcountry!="sweden": # raise Exception("Debug, just allow sweden for now. just remove this after.") return borders[pcountry]
def get_borders(pcountry): #print "Getting for",pcountry global borders if not borders: if not os.path.exists("fplan/extract/lands.bin"): if os.system("bunzip2 fplan/extract/lands.bin.bz2")!=0: raise Exception("Couldn't unbzip2 lands.bin.bz2") f=open("fplan/extract/lands.bin") tborders=pickle.load(f) f.close() out=dict() for country,parts in tborders.items(): outparts=[] tot=0 for part in parts: outpart=[] poly_coords=[] last=None for coord in part: merc=mapper.latlon2merc(mapper.from_str(coord),13) if merc==last: continue last=merc outpart.append(merc) tot+=1 poly_coords.append(Vertex(int(merc[0]),int(merc[1]))) assert len(outpart)>=3 if outpart[0]==outpart[-1]: outpart=outpart[:-1] poly_coords=poly_coords[:-1] poly=Polygon(vvector(poly_coords)) assert poly.is_ccw() outparts.append(outpart) #print "Parts in ",country,len(outparts),tot out[country]=outparts borders=out #if pcountry!="sweden": # raise Exception("Debug, just allow sweden for now. just remove this after.") return borders[pcountry]
def gpx(self): # Return a rendered template #return render('/flightplan.mako') # or, return a response if not self.validate(tripname=request.params.get('tripname',None),exception=False): return "Internal error. Missing trip-name or user-session." waypoints=list(meta.Session.query(Waypoint).filter(sa.and_( Waypoint.user==tripuser(),Waypoint.trip==c.trip.trip)).order_by(Waypoint.ordering).all()) if len(waypoints)==0: return redirect(h.url_for(controller='flightplan',action="index",flash=u"Must have at least two waypoints in trip!")) c.waypoints=[] for wp in waypoints: lat,lon=mapper.from_str(wp.pos) c.waypoints.append(dict( lat=lat, lon=lon, name=wp.waypoint )) #response.headers['Content-Type'] = 'application/xml' response.content_type = 'application/octet-stream' response.charset="utf8" return render('/gpx.mako')
def parse_airfields(): out = [] for item in csv.reader(open("fplan/extract/denmark.airfields.csv")): print item icao, empty, ICAO, name, d1, d2, pos, elev, owner, phone, d4, d5, webside = item if not pos[-1] in ['E', 'W']: pos = pos + "E" print "ICAO:", icao assert icao.upper() == ICAO name = coding(name) lat, lon = mapper.from_str(mapper.parsecoord(pos)) nasaelev = get_terrain_elev((lat, lon)) if elev == '': elev = nasaelev if nasaelev != 9999: assert abs(float(elev) - nasaelev) < 100 ad = dict(icao=ICAO, name=name, pos=mapper.to_str((lat, lon)), date="2010-01-01T00:00:00Z", elev=int(elev)) out.append(ad) return out
def parse_airfields(): out=[] for item in csv.reader(open("fplan/extract/denmark.airfields.csv")): print item icao,empty,ICAO,name,d1,d2,pos,elev,owner,phone,d4,d5,webside=item if not pos[-1] in ['E','W']: pos=pos+"E" print "ICAO:",icao assert icao.upper()==ICAO name=coding(name) lat,lon=mapper.from_str(mapper.parsecoord(pos)) nasaelev=get_terrain_elev((lat,lon)) if elev=='': elev=nasaelev if nasaelev!=9999: assert abs(float(elev)-nasaelev)<100 ad=dict( icao=ICAO, name=name, pos=mapper.to_str((lat,lon)), date="2010-01-01T00:00:00Z", elev=int(elev)) out.append(ad) return out
def cm(latlonstr, zoomlevel): return clampmerc( mapper.latlon2merc(mapper.from_str(latlonstr), zoomlevel))
def cm(latlonstr,zoomlevel): return clampmerc(mapper.latlon2merc(mapper.from_str(latlonstr),zoomlevel))
def generate_big_tile(pixelsize,x1,y1,zoomlevel,osmdraw,tma=False,return_format="PIL",user=None,only_user=False): """ set osmdraw==True and make sure a full working openstreetmap mapnik environment is available, in order to draw using mapnik. If false, a basemap must already have been drawn, and all that can be done is that new airspaces etc an be filled in. """ def only(x): if only_user: #print "Ignoring ",len(x) return [] return x print "TMA:",tma imgx,imgy=pixelsize assert osmdraw in [True,False] if not osmdraw: #osmdraw should probably be renamed use 'use_existing_basemap' print "Making %dx%d tile at %s/%s, zoomlevel: %d"%(pixelsize[0],pixelsize[1],x1,y1,zoomlevel) print "Generating tile" print "mapnikstyle file:",os.getenv("SWFP_MAPNIK_STYLE") mapfile = os.path.join(os.getenv("SWFP_MAPNIK_STYLE"),"osm.xml") #--------------------------------------------------- # Change this to the bounding box you want # # lon lat lon lat #ll = (center[1], hilat, center[1], lolat) #--------------------------------------------------- lat1,lon1=mapper.merc2latlon((x1,y1),zoomlevel) lat2,lon2=mapper.merc2latlon((x1+imgx,y1+imgy),zoomlevel) m = mapnik.Map(imgx,imgy) mapnik.load_map(m,mapfile) c0 = prj.forward(mapnik.Coord(lon1,lat1)) c1 = prj.forward(mapnik.Coord(lon2,lat2)) if hasattr(mapnik,'mapnik_version') and mapnik.mapnik_version() >= 800: #bbox = mapnik.Box2d(0,0,256<<zoomlevel,256<<zoomlevel) bbox = mapnik.Box2d(c0.x,c0.y,c1.x,c1.y) else: bbox = mapnik.Envelope(c0.x,c0.y,c1.x,c1.y) #bbox = mapnik.Envelope(0,0,256<<zoomlevel,256<<zoomlevel) m.zoom_to_box(bbox) im = mapnik.Image(imgx,imgy) mapnik.render(m, im) buf=im.tostring() #print "len im tostring:" ,len(buf) assert len(buf)%4==0 num_pixels=len(buf)/4 as_array=numpy.fromstring(buf,numpy.dtype("u1")) assert len(as_array)==len(buf) r,g,b,a=numpy.hsplit(as_array.reshape(num_pixels,4),(1,2,3)) assert len(r)==num_pixels print "Num pixels: ",num_pixels swapped=numpy.column_stack((b,g,r,a)).reshape(4*num_pixels) assert len(swapped)==num_pixels*4 assert num_pixels==imgx*imgy im=cairo.ImageSurface.create_for_data(swapped,cairo.FORMAT_RGB24,imgx,imgy) #as_array=numpy.fromstring(buf,numpy.dtype("u4")) #as_array.byteswap(True) else: #print "Reading existing map instead" im=Image.new("RGBA",(imgx,imgy)) for i in xrange(0,pixelsize[0],256): for j in xrange(0,pixelsize[1],256): rawtile,tilemeta=maptilereader.gettile("plain",zoomlevel,x1+i,y1+j) io=StringIO.StringIO(rawtile) io.seek(0) sub=Image.open(io) im.paste(sub,(i,j,i+256,j+256)) buf=im.tostring() #print "len im tostring:" ,len(buf) assert len(buf)%4==0 num_pixels=len(buf)/4 assert num_pixels==imgx*imgy as_array=numpy.fromstring(buf,numpy.dtype("u1")) assert len(as_array)==len(buf) r,g,b,a=numpy.hsplit(as_array.reshape(num_pixels,4),(1,2,3)) assert len(r)==num_pixels #print "Num pixels: ",num_pixels swapped=numpy.column_stack((b,g,r,a)).reshape(4*num_pixels) im=cairo.ImageSurface.create_for_data(swapped,cairo.FORMAT_RGB24,imgx,imgy) ctx=cairo.Context(im) if tma: def tolocal(merc): return (merc[0]-x1,merc[1]-y1) merc13=mapper.merc2merc((x1-50,y1-50),zoomlevel,13) merc13b=mapper.merc2merc((x1+imgx+50,y1+imgy+50),zoomlevel,13) bb13=BoundingBox(merc13[0],merc13[1],merc13b[0],merc13b[1]) bycolor=dict() for space in chain( only(get_airspaces_in_bb2(bb13)),get_notam_objs_cached()['areas'], only(get_aip_sup_areas()),get_firs(),userdata.get_all_airspaces(user)): if space['type']=='sector': continue #Don't draw "sectors" vertices=[] for coord in space['points']: merc=mapper.latlon2merc(mapper.from_str(coord),zoomlevel) vertices.append(tolocal(merc))#merc[0]-x1,merc[1]-y1) try: areacol,solidcol=get_airspace_color(space['type']) except Exception: print space raise bycolor.setdefault((areacol,solidcol),[]).append(vertices) def colorsorter(col): if col[0]>0.5: return (110,0,0,0) return col for (areacol,solidcol),polygons in sorted(bycolor.items(),key=lambda x:colorsorter(x[0])): if areacol[3]<=0.05: continue surface2 = cairo.ImageSurface(cairo.FORMAT_ARGB32, imgx, imgy) ctx2=cairo.Context(surface2) ctx2.set_operator(cairo.OPERATOR_DEST_OUT) ctx2.rectangle(0,0,imgx,imgy) ctx2.set_source(cairo.SolidPattern(0,0,0,1.0)) ctx2.paint() ctx2.set_operator(cairo.OPERATOR_OVER) for poly in polygons: ctx2.new_path() for vert in poly: ctx2.line_to(*vert) ctx2.close_path() ctx2.set_source(cairo.SolidPattern(areacol[0],areacol[1],areacol[2],1.0)) ctx2.fill_preserve() ctx2.set_operator(cairo.OPERATOR_DEST_OUT) ctx2.rectangle(0,0,imgx,imgy) ctx2.set_source(cairo.SolidPattern(0,0,0,1.0-areacol[3])) ctx2.paint() #ctx2.set_operator(cairo.OPERATOR_OVER) ctx.set_source_surface(surface2) ctx.rectangle(0,0,imgx,imgy) ctx.paint() for (areacol,solidcol),polygons in sorted(bycolor.items(),key=lambda x:colorsorter(x[1])): for poly in polygons: ctx.new_path() for vert in poly: ctx.line_to(*vert) ctx.close_path() ctx.set_source(cairo.SolidPattern(*solidcol)) ctx.stroke() for obst in chain(only(get_obstacles_in_bb(bb13)),userdata.get_all_obstacles(user)): if zoomlevel>=9: ctx.set_source(cairo.SolidPattern(1.0,0.0,1.0,0.25)) merc=mapper.latlon2merc(mapper.from_str(obst['pos']),zoomlevel) pos=tolocal(merc)#(merc[0]-x1,merc[1]-y1) radius=parse_obstacles.get_pixel_radius(obst,zoomlevel) ctx.new_path() ctx.arc(pos[0],pos[1],radius,0,2*math.pi) ctx.fill_preserve() ctx.set_source(cairo.SolidPattern(1.0,0.0,1.0,0.75)) ctx.new_path() ctx.arc(pos[0],pos[1],radius,0,2*math.pi) ctx.stroke() for sigp in chain(only(get_sig_points_in_bb(bb13)),userdata.get_all_sigpoints(user)): if zoomlevel>=9: #print sigp if zoomlevel==9 and sigp.get('kind','') in ['entry/exit point','holding point']: continue if sigp.get('kind','') in ['town','city']:continue merc=mapper.latlon2merc(mapper.from_str(sigp['pos']),zoomlevel) pos=tolocal(merc)#(merc[0]-x1,merc[1]-y1) ctx.set_source(cairo.SolidPattern(0.0,0.0,1.0,0.65)) ctx.new_path() ctx.line_to(pos[0],pos[1]-3) ctx.line_to(pos[0]+3,pos[1]) ctx.line_to(pos[0],pos[1]+3) ctx.line_to(pos[0]-3,pos[1]) ctx.close_path() ctx.stroke() for notamtype,items in get_notam_objs_cached().items(): if notamtype=="areas": continue for item in items: if zoomlevel>=8: ctx.set_source(cairo.SolidPattern(0.25,1,0.25,0.25)) merc=mapper.latlon2merc(mapper.from_str(item['pos']),zoomlevel) pos=tolocal(merc)#(merc[0]-x1,merc[1]-y1) radius=5 ctx.new_path() ctx.arc(pos[0],pos[1],radius,0,2*math.pi) ctx.fill_preserve() ctx.set_source(cairo.SolidPattern(0,1.0,0,0.75)) ctx.new_path() ctx.arc(pos[0],pos[1],radius,0,2*math.pi) ctx.stroke() for airfield in chain(only(get_airfields_in_bb(bb13)),userdata.get_all_airfields(user)): if zoomlevel<6: continue ctx.set_source(cairo.SolidPattern(0.8,0.5,1.0,0.25)) merc=mapper.latlon2merc(mapper.from_str(airfield['pos']),zoomlevel) pos=(merc[0]-x1,merc[1]-y1) if zoomlevel<=11: radius=5 else: radius=5<<(zoomlevel-11) ctx.new_path() ctx.arc(pos[0],pos[1],radius,0,2*math.pi) ctx.fill_preserve() ctx.set_source(cairo.SolidPattern(0.8,0.5,1.0,0.75)) ctx.new_path() ctx.arc(pos[0],pos[1],radius,0,2*math.pi) ctx.stroke() for rwy in airfield.get('runways',[]): ends=rwy['ends'] mercs=[] #print "Ends:",ends surface=rwy.get('surface','hard').lower() for end in ends: #print "pos:",end['pos'] latlon=mapper.from_str(end['pos']) #print "latlon:",latlon merc=mapper.latlon2merc(latlon,zoomlevel) #print "Merc:",merc mercs.append(merc) if len(mercs)==2: a,b=mercs #print "Drawing:",airfield['icao'],a,b if surface=='gravel': ctx.set_source(cairo.SolidPattern(0.5,0.3,0.0,1)) elif surface=='grass': ctx.set_source(cairo.SolidPattern(0.0,0.65,0.0,1)) else: ctx.set_source(cairo.SolidPattern(0.0,0.0,0.0,1)) lwidth=mapper.approx_scale(a,zoomlevel,40.0/1852.0) if lwidth<=2: lwidth=2.0 ctx.set_line_width(lwidth) ctx.new_path() ctx.move_to(*tolocal(a)) ctx.line_to(*tolocal(b)) ctx.stroke() if return_format=="PIL": b,g,r,a=numpy.hsplit(swapped.reshape(num_pixels,4),(1,2,3)) back=numpy.column_stack((r,g,b)).reshape(3*num_pixels) im=Image.frombuffer("RGB",(imgx,imgy),back,'raw','RGB',0,1) else: assert return_format=="cairo" pass #print "Returning rendered image and map" return im
def save(self): print request.params ad = request.params['ad'] chartobj = None mapchecksum = request.params['mapchecksum'] for adobj in ec.get_airfields(): if adobj['name'] == ad: bb = False for adchart in adobj['adcharts'].values(): if adchart['checksum'] == mapchecksum: chartobj = adchart bb = True break if bb: break else: self.error("No such airport" + ad) marks = dict() for param, val in request.params.items(): if param in [ "save", "ad", 'mapchecksum', 'scroll_x', 'scroll_y', 'maptype', 'scale', 'north' ]: continue if param.startswith("del"): continue if param.startswith("set_"): x, y = [int(v) for v in param.split("_")[1:]] session['curadmarker'] = (x, y) session.save() continue if param == "add": xs = meta.Session.query(AirportMarker.x).filter( sa.and_(AirportMarker.user == session['user'], AirportMarker.airport == ad)).all() if xs: maxx = max(xs)[0] + 1 else: maxx = 0 marks[(maxx, 0)] = dict(latitude=None, longitude=None, x=maxx, y=0) session['curadmarker'] = (maxx, 0) session.save() continue sx, sy, attrib = re.match(ur"mark_(\d+)_(\d+)_(\w*)", param).groups() x = int(sx) y = int(sy) marks.setdefault((x, y), dict())[attrib] = val thresholds = dict() for rwy in adobj.get('runways', []): ends = rwy['ends'] for end in ends: thresholds[end['thr']] = mapper.from_str(end['pos']) for param, val in request.params.items(): if param.startswith("del_"): x, y = [int(v) for v in param.split("_")[1:]] marks.pop((x, y)) continue meta.Session.query(AirportMarker).filter( sa.and_(AirportMarker.user == session['user'], AirportMarker.airport == ad)).delete() ms = [] arppos = mapper.from_str(adobj['pos']) for (x, y), val in marks.items(): m = AirportMarker() m.user = session['user'] m.airport = ad m.mapchecksum = str(mapchecksum) m.x = int(val['x']) m.y = int(val['y']) m.latitude, w1 = parselatlon(val['latitude'], arppos, thresholds, 0) m.longitude, w2 = parselatlon(val['longitude'], arppos, thresholds, 1) if w1 or w2: m.weight = w1 + w2 else: m.weigth = 1 meta.Session.add(m) ms.append(m) proj = meta.Session.query(AirportProjection).filter( sa.and_(AirportProjection.user == session['user'], AirportProjection.airport == ad, AirportProjection.mapchecksum == str(mapchecksum))).one() try: proj.scale = float(request.params['scale'].strip()) except: proj.scale = None try: proj.north = float(request.params['north'].strip()) except: proj.north = None def both_lat_lon(x): return x.latitude and x.longitude def neither_lat_lon(x): return not x.latitude and not x.longitude def just_lat(x): return x.latitude and not x.longitude def just_lon(x): return not x.latitude and x.longitude ms = [m for m in ms if not neither_lat_lon(m)] """ if (len(ms)==4 and len([m for m in ms if just_lat(m)])==2 and len([m for m in ms if just_lon(m)])==2): extra=[] for m in ms: n=AirportMarker() n.x=m.x n.y=m.y if just_lat(m): n.latitude=m.latitude n.x+=1000 extra.append(n) if just_lon(m): n.y+=1000 n.longitude=m.longitude extra.append(n) ms.extend(extra) """ if len(ms) == 1 and both_lat_lon( ms[0]) and proj.scale and proj.north != None: print "Scale/north triggered" print "Adchart:", chartobj if chartobj != None: render_height = chartobj['render_height'] mark, = ms pixelpos = (mark.x, mark.y) mapsize = adchart.get('mapsize', (210, 297)) mapheight_meter = mapsize[1] / 1000.0 * proj.scale mapheight_km = mapheight_meter / 1000.0 merc = mapper.latlon2merc((mark.latitude, mark.longitude), 17) pixels = mapper.approx_scale(merc, 17, mapheight_km / 1.852) newmerc = (merc[0], merc[1] - pixels) northrad = proj.north / (180.0 / math.pi) newpixelpos = (pixelpos[0] + render_height * math.sin(northrad), pixelpos[1] - render_height * math.cos(northrad)) m = AirportMarker() m.x = newpixelpos[0] m.y = newpixelpos[1] latlon = mapper.merc2latlon(newmerc, 17) m.latitude = latlon[0] m.longitude = latlon[1] m.weight = 1 ms.append(m) if len(ms) == 2 and all(both_lat_lon(x) for x in ms): print "Have exactly two marks now" mark1, mark2 = ms lm1, lm2 = [ mapper.latlon2merc((mark.latitude, mark.longitude), 17) for mark in [mark1, mark2] ] ld = (lm2[0] - lm1[0], lm2[1] - lm1[1]) pd = (mark2.x - mark1.x, mark2.y - mark1.y) lm3 = (lm1[0] - ld[1], lm1[1] + ld[0]) pm3 = (mark1.x - pd[1], mark1.y + pd[0]) llm3 = mapper.merc2latlon(lm3, 17) m = AirportMarker() m.x = pm3[0] m.y = pm3[1] m.latitude, w1 = llm3[0], 1 m.longitude, w2 = llm3[1], 1 ms.append(m) print "delta pixels", pd print "delta latlon", ld print "extra end pixels", m.x, m.y print "extra end latlon", m.latitude, m.longitude eqns = 0 for m in ms: if both_lat_lon(m): eqns += 2 elif just_lat(m): eqns += 1 elif just_lon(m): eqns += 1 try: if eqns < 4: raise Exception("Unsolvable") error, A, T = customproj.solve(ms) matrix = list(A) + list(T) if proj.matrix: oldmatrix = list(proj.matrix) newmatrix = list(A) + list(T) diff = sum(abs(a - b) for a, b in zip(oldmatrix, newmatrix)) else: diff = 1e30 #enough to trigger update if diff > 1e-12: proj.matrix = tuple(newmatrix) proj.updated = datetime.utcnow().replace(microsecond=0) except Exception, cause: print "Couldn't solve projection equation %s" % (cause, ) proj.matrix = [1, 0, 0, 1, 0, 0] proj.updated = datetime.utcnow().replace(microsecond=0) meta.Session.add(proj)