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 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_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 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_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_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_terrain_elev_in_box_approx(latlon, nautmiles): #nautmiles/=2 zoomlevel = 8 merc_ = mapper.latlon2merc(latlon, zoomlevel) merc = (int(merc_[0]), int(merc_[1])) pixels = mapper.approx_scale(merc, zoomlevel, nautmiles) #print "Num pixels on zoomlevel 8",pixels," naut",nautmiles del merc del merc_ while pixels > 4 and zoomlevel > 0: zoomlevel -= 1 pixels /= 2 #print "Pixels on zoom",zoomlevel,": ",pixels pixels = int(pixels + 0.5) if pixels <= 1: pixels = 1 if zoomlevel >= 8: zoomlevel = 8 merc_ = mapper.latlon2merc(latlon, zoomlevel) merc = (int(merc_[0]), int(merc_[1])) #print "Getting terrain zoomlevel ",zoomlevel return get_terrain_elev_merc(merc, zoomlevel, (pixels, pixels))
def get_terrain_elev_in_box_approx(latlon,nautmiles): #nautmiles/=2 zoomlevel=8 merc_=mapper.latlon2merc(latlon,zoomlevel) merc=(int(merc_[0]),int(merc_[1])) pixels=mapper.approx_scale(merc, zoomlevel, nautmiles) #print "Num pixels on zoomlevel 8",pixels," naut",nautmiles del merc del merc_ while pixels>4 and zoomlevel>0: zoomlevel-=1 pixels/=2 #print "Pixels on zoom",zoomlevel,": ",pixels pixels=int(pixels+0.5) if pixels<=1: pixels=1 if zoomlevel>=8: zoomlevel=8 merc_=mapper.latlon2merc(latlon,zoomlevel) merc=(int(merc_[0]),int(merc_[1])) #print "Getting terrain zoomlevel ",zoomlevel return get_terrain_elev_merc(merc,zoomlevel,(pixels,pixels))
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 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 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 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 get_obstacle_free_height_on_line(pos1,pos2): minimum_distance=2.0 merc1=mapper.latlon2merc(pos1,13) merc2=mapper.latlon2merc(pos2,13) onenm=mapper.approx_scale(merc1,13,1.0) av=Vertex(int(merc1[0]),int(merc1[1])) bv=Vertex(int(merc2[0]),int(merc2[1])) linelen=(av-bv).approxlength() l=Line(av,bv) bb=BoundingBox(min(merc1[0],merc2[0]), min(merc1[1],merc2[1]), max(merc1[0],merc2[0]), max(merc1[1],merc2[1])).expanded(onenm*minimum_distance*1.5) obstacles=[0] for item in chain(notam_geo_search.get_notam_objs_cached()['obstacles'], extracted_cache.get_obstacles_in_bb(bb)): if not 'pos' in item: continue if not 'elev' in item: continue 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) actualclosest=l.approx_closest(itemv) actualdist=(actualclosest-itemv).approxlength()/onenm if actualdist<minimum_distance: itemalt=mapper.parse_elev(item['elev']) obstacles.append(itemalt) minstep=2*onenm stepcount=linelen/float(minstep) if stepcount>100: newstep=linelen/100.0 if newstep>minstep: minstep=newstep if linelen<1e-3: linelen=1e-3 along=0.0 #isfirstorlast=(idx==0 or idx==l-1) while True: alongf=float(along)/float(linelen) end=False if alongf>1.0: alongf=1.0 end=True merc=((1.0-alongf)*merc1[0]+(alongf)*merc2[0], (1.0-alongf)*merc1[1]+(alongf)*merc2[1]) latlon=mapper.merc2latlon(merc,13) elev=get_terrain_elev_in_box_approx(latlon,2.0*minstep/onenm) obstacles.append(elev) along+=minstep if end: break return max(obstacles)
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)
def getmap(self): #print "DAta:",request.params data = json.loads(request.params['data']) ad = data['ad'] perf = data['perf'] what = data['what'] #print "Perf:",perf imgsize = 300 im = cairo.ImageSurface(cairo.FORMAT_RGB24, imgsize, imgsize) ctx = cairo.Context(im) def getpos(xd): return xd.get('usable_pos', xd['pos']) if not 'physical' in ad: rwy = ad['runways'][0] hdg = float(rwy["rwyhdg"]) hdgrad = (hdg / (180.0 / math.pi)) runway_length = float(rwy["runway_length"]) threshold = float(rwy["threshold"]) posA = mapper.latlon2merc((59, 18), 20) meter = mapper.approx_scale(posA, 20, 1 / 1852.0) rwylen = meter * runway_length delta = (math.sin(hdgrad) * rwylen, -math.cos(hdgrad) * rwylen) print "Delta:", delta posB = (posA[0] + delta[0], posA[1] + delta[1]) latlonA = mapper.to_str(mapper.merc2latlon(posA, 20)) latlonB = mapper.to_str(mapper.merc2latlon(posB, 20)) ad['physical'] = [[ dict(name=rwy['name'], usable_pos=latlonA, pos=latlonA, threshold=threshold), dict(name="^" + rwy['name'], usable_pos=latlonB, pos=latlonB, threshold=0) ]] if 'physical' in ad: def getdist_meter(p1, p2): brg, dist = mapper.bearing_and_distance( mapper.merc2latlon(p1, 20), mapper.merc2latlon(p2, 20)) return dist * 1852.0 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 justmercs(): for p1, p2, n1, n2, t1, t2 in draw_cmds(): yield p1 yield p2 bb = bsptree.bb_from_mercs(justmercs()) center = (0.5 * (bb.x1 + bb.x2), 0.5 * (bb.y1 + bb.y2)) #print "Center:",center mercradius = max(bb.x2 - bb.x1, bb.y2 - bb.y1) scaling = (imgsize / 1.3) / mercradius def topixel(merc): off = (merc[0] - center[0], merc[1] - center[1]) return (off[0] * scaling + imgsize / 2, off[1] * scaling + imgsize / 2) def draw_marker(ctx, p1, p2, thresholdratio, msg, col=(1, 0, 0)): ninety = [p2[1] - p1[1], p2[0] - p1[0]] ninety = [ninety[0], -ninety[1]] #if ninety[0]<0: # ninety[0],ninety[1]=-ninety[0],-ninety[1] #print "ninety:",ninety p1 = topixel(p1) p2 = topixel(p2) d = [ p1[0] + thresholdratio * (p2[0] - p1[0]), p1[1] + thresholdratio * (p2[1] - p1[1]) ] """ dB=[d[0]+ninety[0],d[1]+ninety[1]] if dB[0]>0.75*imgsize: ninety[0],ninety[1]=-ninety[0],-ninety[1] elif dB[0]<0.25*imgsize: ninety[0],ninety[1]=-ninety[0],-ninety[1] elif dB[1]<0.25*imgsize: ninety[0],ninety[1]=-ninety[0],-ninety[1] elif dB[1]>0.75*imgsize: ninety[0],ninety[1]=-ninety[0],-ninety[1] dB=[d[0]+ninety[0],d[1]+ninety[1]] """ ctx.new_path() ctx.set_source(cairo.SolidPattern(*(col + (1, )))) ctx.arc(d[0], d[1], 6, 0, 2 * math.pi) ctx.fill() ctx.new_path() ctx.move_to(*d) ctx.save() ang = math.atan2(ninety[1], ninety[0]) * 180.0 / 3.1415 if ang > 90 or ang < -90: ang = (ang + 180) % 360 angrad = ang * (math.pi / 180) ctx.translate(*d) ctx.rotate(angrad) ctx.set_font_size(17) ext = ctx.text_extents(msg)[:4] w = ext[2] cand1 = ctx.user_to_device(10 + w / 2, 0) cand2 = ctx.user_to_device(-10 - w / 2, 0) def edgedist(x): return min(x[0], x[0] - imgsize, x[1], x[1] - imgsize) if edgedist(cand1) > edgedist(cand2): dC = [10, -ext[1] / 2] else: dC = [-10 - w, -ext[1] / 2] #dC=[dB[0],dB[1]] ctx.move_to(*dC) ctx.show_text(msg) ctx.restore() for p1, p2, n1, n2, t1, t2 in draw_cmds(): print "n1:", n1, "n2:", n2 print "p1:", mapper.merc2latlon(p1, 20) print "p2:", mapper.merc2latlon(p2, 20) pix1 = topixel(p1) pix2 = topixel(p2) ctx.set_source(cairo.SolidPattern(0.5, 0.5, 0.5, 1)) ctx.new_path() ctx.set_line_width(10) ctx.move_to(*pix1) ctx.line_to(*pix2) ctx.stroke() for p1, p2, n1, n2, t1, t2 in draw_cmds(): print "Matching", n1, n2, "to", perf['name'] if n2 == perf['name']: p1, n1, t1, p2, n2, t2 = p2, n2, t2, p1, n1, t1 if n1 == perf['name']: runwaylen = getdist_meter(p1, p2) startratio = perf["start"] / runwaylen start300ratio = perf["start300"] / runwaylen startrollratio = perf["start_roll"] / runwaylen safe_factor = 1.43 if 'safe_factor' in perf: safe_factor = float(perf['safe_factor']) thresholdratio = t1 / runwaylen landingratio = perf["land"] / runwaylen landingrollratio = landingratio - perf[ "landing_roll"] / runwaylen landingratio *= safe_factor landingrollratio *= safe_factor landingratio += thresholdratio landingrollratio += thresholdratio if what == 'start': draw_marker(ctx, p1, p2, 0, "Start", col=(1, 0, 0)) draw_marker(ctx, p1, p2, startrollratio, "Lättning", col=(1, 0.5, 0)) draw_marker(ctx, p1, p2, startratio, "tröskelhöjd", col=(1, 1, 0)) draw_marker(ctx, p1, p2, start300ratio, "300 fot höjd", col=(0, 1, 0)) if what == 'landing': draw_marker(ctx, p1, p2, thresholdratio, "tröskelhöjd ", col=(1, 0, 0)) draw_marker(ctx, p1, p2, landingrollratio, "Senaste sättning", col=(1, 0.5, 0)) draw_marker(ctx, p1, p2, landingratio, "Senaste stopp", (0, 1, 0)) buf = StringIO.StringIO() im.write_to_png(buf) png = buf.getvalue() response.headers['Content-Type'] = 'image/png' return png
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)
def get_obstacle_free_height_on_line(pos1, pos2): minimum_distance = 2.0 merc1 = mapper.latlon2merc(pos1, 13) merc2 = mapper.latlon2merc(pos2, 13) onenm = mapper.approx_scale(merc1, 13, 1.0) av = Vertex(int(merc1[0]), int(merc1[1])) bv = Vertex(int(merc2[0]), int(merc2[1])) linelen = (av - bv).approxlength() l = Line(av, bv) bb = BoundingBox(min(merc1[0], merc2[0]), min(merc1[1], merc2[1]), max(merc1[0], merc2[0]), max(merc1[1], merc2[1])).expanded(onenm * minimum_distance * 1.5) obstacles = [0] for item in chain(notam_geo_search.get_notam_objs_cached()['obstacles'], extracted_cache.get_obstacles_in_bb(bb)): if not 'pos' in item: continue if not 'elev' in item: continue 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) actualclosest = l.approx_closest(itemv) actualdist = (actualclosest - itemv).approxlength() / onenm if actualdist < minimum_distance: itemalt = mapper.parse_elev(item['elev']) obstacles.append(itemalt) minstep = 2 * onenm stepcount = linelen / float(minstep) if stepcount > 100: newstep = linelen / 100.0 if newstep > minstep: minstep = newstep if linelen < 1e-3: linelen = 1e-3 along = 0.0 #isfirstorlast=(idx==0 or idx==l-1) while True: alongf = float(along) / float(linelen) end = False if alongf > 1.0: alongf = 1.0 end = True merc = ((1.0 - alongf) * merc1[0] + (alongf) * merc2[0], (1.0 - alongf) * merc1[1] + (alongf) * merc2[1]) latlon = mapper.merc2latlon(merc, 13) elev = get_terrain_elev_in_box_approx(latlon, 2.0 * minstep / onenm) obstacles.append(elev) along += minstep if end: break return max(obstacles)
def getmap(self): #print "DAta:",request.params data=json.loads(request.params['data']) ad=data['ad'] perf=data['perf'] what=data['what'] #print "Perf:",perf imgsize=300 im=cairo.ImageSurface(cairo.FORMAT_RGB24,imgsize,imgsize) ctx=cairo.Context(im) def getpos(xd): return xd.get('usable_pos',xd['pos']) if not 'physical' in ad: rwy=ad['runways'][0] hdg=float(rwy["rwyhdg"]) hdgrad=(hdg/(180.0/math.pi)) runway_length=float(rwy["runway_length"]) threshold=float(rwy["threshold"]) posA=mapper.latlon2merc((59,18),20) meter=mapper.approx_scale(posA, 20, 1/1852.0) rwylen=meter*runway_length delta=(math.sin(hdgrad)*rwylen,-math.cos(hdgrad)*rwylen) print "Delta:",delta posB=(posA[0]+delta[0],posA[1]+delta[1]) latlonA=mapper.to_str(mapper.merc2latlon(posA,20)) latlonB=mapper.to_str(mapper.merc2latlon(posB,20)) ad['physical']=[ [dict(name=rwy['name'], usable_pos=latlonA, pos=latlonA, threshold=threshold), dict(name="^"+rwy['name'], usable_pos=latlonB, pos=latlonB, threshold=0)]] if 'physical' in ad: def getdist_meter(p1,p2): brg,dist=mapper.bearing_and_distance(mapper.merc2latlon(p1,20),mapper.merc2latlon(p2,20)) return dist*1852.0 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 justmercs(): for p1,p2,n1,n2,t1,t2 in draw_cmds(): yield p1 yield p2 bb=bsptree.bb_from_mercs(justmercs()) center=(0.5*(bb.x1+bb.x2),0.5*(bb.y1+bb.y2)) #print "Center:",center mercradius=max(bb.x2-bb.x1,bb.y2-bb.y1) scaling=(imgsize/1.3)/mercradius def topixel(merc): off=(merc[0]-center[0],merc[1]-center[1]) return (off[0]*scaling+imgsize/2,off[1]*scaling+imgsize/2) def draw_marker(ctx,p1,p2,thresholdratio,msg,col=(1,0,0)): ninety=[p2[1]-p1[1],p2[0]-p1[0]] ninety=[ninety[0],-ninety[1]] #if ninety[0]<0: # ninety[0],ninety[1]=-ninety[0],-ninety[1] #print "ninety:",ninety p1=topixel(p1) p2=topixel(p2) d=[p1[0]+thresholdratio*(p2[0]-p1[0]), p1[1]+thresholdratio*(p2[1]-p1[1])] """ dB=[d[0]+ninety[0],d[1]+ninety[1]] if dB[0]>0.75*imgsize: ninety[0],ninety[1]=-ninety[0],-ninety[1] elif dB[0]<0.25*imgsize: ninety[0],ninety[1]=-ninety[0],-ninety[1] elif dB[1]<0.25*imgsize: ninety[0],ninety[1]=-ninety[0],-ninety[1] elif dB[1]>0.75*imgsize: ninety[0],ninety[1]=-ninety[0],-ninety[1] dB=[d[0]+ninety[0],d[1]+ninety[1]] """ ctx.new_path() ctx.set_source(cairo.SolidPattern(*(col+(1,)))) ctx.arc(d[0],d[1],6,0,2*math.pi) ctx.fill() ctx.new_path() ctx.move_to(*d) ctx.save() ang=math.atan2(ninety[1],ninety[0])*180.0/3.1415 if ang>90 or ang <-90: ang=(ang+180)%360 angrad=ang*(math.pi/180) ctx.translate(*d) ctx.rotate(angrad) ctx.set_font_size(17); ext=ctx.text_extents(msg)[:4] w=ext[2] cand1=ctx.user_to_device(10+w/2,0) cand2=ctx.user_to_device(-10-w/2,0) def edgedist(x): return min(x[0],x[0]-imgsize,x[1],x[1]-imgsize) if edgedist(cand1)>edgedist(cand2): dC=[10,-ext[1]/2] else: dC=[-10-w,-ext[1]/2] #dC=[dB[0],dB[1]] ctx.move_to(*dC) ctx.show_text(msg) ctx.restore() for p1,p2,n1,n2,t1,t2 in draw_cmds(): print "n1:",n1,"n2:",n2 print "p1:",mapper.merc2latlon(p1,20) print "p2:",mapper.merc2latlon(p2,20) pix1=topixel(p1) pix2=topixel(p2) ctx.set_source(cairo.SolidPattern(0.5,0.5,0.5,1)) ctx.new_path() ctx.set_line_width(10) ctx.move_to(*pix1) ctx.line_to(*pix2) ctx.stroke() for p1,p2,n1,n2,t1,t2 in draw_cmds(): print "Matching",n1,n2,"to",perf['name'] if n2==perf['name']: p1,n1,t1,p2,n2,t2=p2,n2,t2,p1,n1,t1 if n1==perf['name']: runwaylen=getdist_meter(p1,p2) startratio=perf["start"]/runwaylen start300ratio=perf["start300"]/runwaylen startrollratio=perf["start_roll"]/runwaylen safe_factor=1.43 if 'safe_factor' in perf: safe_factor=float(perf['safe_factor']) thresholdratio=t1/runwaylen landingratio=perf["land"]/runwaylen landingrollratio=landingratio-perf["landing_roll"]/runwaylen landingratio*=safe_factor landingrollratio*=safe_factor landingratio+=thresholdratio landingrollratio+=thresholdratio if what=='start': draw_marker(ctx,p1,p2,0,"Start",col=(1,0,0)) draw_marker(ctx,p1,p2,startrollratio,"Lättning",col=(1,0.5,0)) draw_marker(ctx,p1,p2,startratio,"tröskelhöjd",col=(1,1,0)) draw_marker(ctx,p1,p2,start300ratio,"300 fot höjd",col=(0,1,0)) if what=='landing': draw_marker(ctx,p1,p2,thresholdratio,"tröskelhöjd ",col=(1,0,0)) draw_marker(ctx,p1,p2,landingrollratio,"Senaste sättning",col=(1,0.5,0)) draw_marker(ctx,p1,p2,landingratio,"Senaste stopp",(0,1,0)) buf=StringIO.StringIO() im.write_to_png(buf) png=buf.getvalue() response.headers['Content-Type'] = 'image/png' return png
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