def get_obstacles(self,routes,vertdist=1000.0,interval=10): byid=dict() items=chain(notam_geo_search.get_notam_objs_cached()['obstacles'], get_obstacles()) print "Get terrain" for closeitem in chain(geo.get_stuff_near_route(routes,items,3.0,vertdist), geo.get_terrain_near_route(routes,vertdist,interval=interval), geo.get_low_sun_near_route(routes) ): byid.setdefault(closeitem['id'],[]).append(closeitem) for v in byid.values(): v.sort(key=lambda x:x['dist_from_a']) #print byid return byid
def get_obstacles(self, routes, vertdist=1000.0, interval=10): byid = dict() items = chain(notam_geo_search.get_notam_objs_cached()['obstacles'], get_obstacles()) print "Get terrain" for closeitem in chain( geo.get_stuff_near_route(routes, items, 3.0, vertdist), geo.get_terrain_near_route(routes, vertdist, interval=interval), geo.get_low_sun_near_route(routes)): byid.setdefault(closeitem['id'], []).append(closeitem) for v in byid.values(): v.sort(key=lambda x: x['dist_from_a']) #print byid return byid
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_airspaces(self): print "Get airspaces called" getsectors = int(request.params.get("sectors", "0")) out = [] if 1: for space in extracted_cache.get_airspaces( ) + get_notam_objs_cached( )['areas'] + extracted_cache.get_aip_sup_areas(): lat, lon = mapper.from_str(space['points'][0]) #if lat<57 or lat>62: # continue if getsectors == 0 and space.get('type', None) == 'sector': continue name = space['name'] if space['type'] == "notamarea": name = "NOTAM:" + name clnd = cleanup_poly( [mapper.from_str(x) for x in space['points']], name) if not clnd: print "Skipped area", name, space continue out.append( dict( name=name, freqs=space['freqs'] if space.get('freqs', "") else [], floor=space.get('floor', ""), type=space['type'], ceiling=space.get('ceiling', ""), points=[dict(lat=p[0], lon=p[1]) for p in clnd])) aiptexts = [] points = [] version = request.params.get("version", None) getaiptext = int(request.params.get("aip", "0")) print "version", version if version and int(version.strip()) >= 5: user_aipgen = request.params.get("aipgen", "") else: user_aipgen = "" for airp in extracted_cache.get_airfields(): lat, lon = mapper.from_str(airp['pos']) if lat < 54 or lon < 4 or lon >= 30.5: try: if not version or int(version.strip()) <= 7: continue except: continue #if lat<58.5 or lat>60.5: # continue aname = airp['name'] notams = [] icao = None taf = None metar = None kind = 'field' if airp.get('icao', 'zzzz').lower() != 'zzzz': icao = airp['icao'] notams = notam_geo_search.get_notam_for_airport(icao) metar = metartaf.get_metar(icao) taf = metartaf.get_taf(icao) kind = 'port' ap = dict(name=aname, lat=lat, lon=lon, kind=kind, notams=notams, remark=airp.get('remark', ''), alt=float(airp.get('elev', 0))) if 'runways' in airp: ap['runways'] = airp['runways'] if icao: ap['icao'] = icao if taf.text: ap['taf'] = taf.text if metar.text: ap['metar'] = metar.text if getaiptext and 'aiptext' in airp: for aiptext in airp['aiptext']: if aip_text_documents.check_doc( aiptext['icao'], aiptext['category'], aiptext['checksum']): #^^^Okay, this really needs an explanation^^^ #Nominally, each aiptext item in aipdata.cache (from which the get_airfields() function #ultimately gets all its data, should always have its corresponding aiptext in html format #available on disk. Now, if the on-disk file is deleted (should never happen), we will #get an exception later down where we try to send this data (with the checksum we have here) #over http to the client. Unfortunately, the routine that sends the data is not at liberty #to modify "what was sent", so the entire sync operation fails. This hack here makes the #failure happen earlier, and in that case the given aiptext-document is suppressed #completely, meaning that the sync operation succeeds, albeit without one specific document #(hey, better than nothing!). # #Of course, the real question is why a document may be missing. A bug of some sort right now, #2012-08-28, makes this bug occur every now and then. Investigation is ongoing. aiptexts.append( dict(name=icao + "_" + aiptext['category'], icao=icao, data=aiptext)) if 'adcharts' in airp and '' in airp['adcharts'] and airp[ 'adcharts'][""]['blobname']: ret = airp['adcharts'][""] try: cksum = ret['checksum'] try: aprojmatrix = get_proj(cksum).matrix except Exception: #print traceback.format_exc() #print "Using 0-proj for ",aname aprojmatrix = [0 for x in xrange(6)] ap['adchart_matrix'] = list(aprojmatrix) ap['adchart_width'] = ret['render_width'] ap['adchart_height'] = ret['render_height'] ap['adchart_name'] = ret['blobname'] ap['adchart_checksum'] = cksum ap['adchart_url'] = ret['url'] except Exception, cause: print "Couldn't get projection for airport %s (%s)" % ( aname, cause) points.append(ap)
class ApiController(BaseController): no_login_required = True #But we don't show personal data without user/pass def get_airspaces(self): print "Get airspaces called" getsectors = int(request.params.get("sectors", "0")) out = [] if 1: for space in extracted_cache.get_airspaces( ) + get_notam_objs_cached( )['areas'] + extracted_cache.get_aip_sup_areas(): lat, lon = mapper.from_str(space['points'][0]) #if lat<57 or lat>62: # continue if getsectors == 0 and space.get('type', None) == 'sector': continue name = space['name'] if space['type'] == "notamarea": name = "NOTAM:" + name clnd = cleanup_poly( [mapper.from_str(x) for x in space['points']], name) if not clnd: print "Skipped area", name, space continue out.append( dict( name=name, freqs=space['freqs'] if space.get('freqs', "") else [], floor=space.get('floor', ""), type=space['type'], ceiling=space.get('ceiling', ""), points=[dict(lat=p[0], lon=p[1]) for p in clnd])) aiptexts = [] points = [] version = request.params.get("version", None) getaiptext = int(request.params.get("aip", "0")) print "version", version if version and int(version.strip()) >= 5: user_aipgen = request.params.get("aipgen", "") else: user_aipgen = "" for airp in extracted_cache.get_airfields(): lat, lon = mapper.from_str(airp['pos']) if lat < 54 or lon < 4 or lon >= 30.5: try: if not version or int(version.strip()) <= 7: continue except: continue #if lat<58.5 or lat>60.5: # continue aname = airp['name'] notams = [] icao = None taf = None metar = None kind = 'field' if airp.get('icao', 'zzzz').lower() != 'zzzz': icao = airp['icao'] notams = notam_geo_search.get_notam_for_airport(icao) metar = metartaf.get_metar(icao) taf = metartaf.get_taf(icao) kind = 'port' ap = dict(name=aname, lat=lat, lon=lon, kind=kind, notams=notams, remark=airp.get('remark', ''), alt=float(airp.get('elev', 0))) if 'runways' in airp: ap['runways'] = airp['runways'] if icao: ap['icao'] = icao if taf.text: ap['taf'] = taf.text if metar.text: ap['metar'] = metar.text if getaiptext and 'aiptext' in airp: for aiptext in airp['aiptext']: if aip_text_documents.check_doc( aiptext['icao'], aiptext['category'], aiptext['checksum']): #^^^Okay, this really needs an explanation^^^ #Nominally, each aiptext item in aipdata.cache (from which the get_airfields() function #ultimately gets all its data, should always have its corresponding aiptext in html format #available on disk. Now, if the on-disk file is deleted (should never happen), we will #get an exception later down where we try to send this data (with the checksum we have here) #over http to the client. Unfortunately, the routine that sends the data is not at liberty #to modify "what was sent", so the entire sync operation fails. This hack here makes the #failure happen earlier, and in that case the given aiptext-document is suppressed #completely, meaning that the sync operation succeeds, albeit without one specific document #(hey, better than nothing!). # #Of course, the real question is why a document may be missing. A bug of some sort right now, #2012-08-28, makes this bug occur every now and then. Investigation is ongoing. aiptexts.append( dict(name=icao + "_" + aiptext['category'], icao=icao, data=aiptext)) if 'adcharts' in airp and '' in airp['adcharts'] and airp[ 'adcharts'][""]['blobname']: ret = airp['adcharts'][""] try: cksum = ret['checksum'] try: aprojmatrix = get_proj(cksum).matrix except Exception: #print traceback.format_exc() #print "Using 0-proj for ",aname aprojmatrix = [0 for x in xrange(6)] ap['adchart_matrix'] = list(aprojmatrix) ap['adchart_width'] = ret['render_width'] ap['adchart_height'] = ret['render_height'] ap['adchart_name'] = ret['blobname'] ap['adchart_checksum'] = cksum ap['adchart_url'] = ret['url'] except Exception, cause: print "Couldn't get projection for airport %s (%s)" % ( aname, cause) points.append(ap) for sigp in extracted_cache.get_sig_points(): lat, lon = mapper.from_str(sigp['pos']) kind = sigp.get('kind', 'sigpoint') if kind == 'sig. point': kind = 'sigpoint' if not kind in ['sigpoint', 'city', 'town']: kind = 'sigpoint' points.append( dict(name=sigp['name'], lat=lat, lon=lon, kind=kind, alt=-9999.0)) user = request.params.get('user', None) correct_pass = False if user: try: print "Received password", request.params[ 'password'], "user:"******"Bad password") correct_pass = True trips = get_user_trips(user) except Exception: print traceback.format_exc() trips = [] else: trips = [] #print "Just added:",points[-1] #add sig. points! if 1: for obst in chain( notam_geo_search.get_notam_objs_cached()['obstacles'], extracted_cache.get_obstacles()): lat, lon = mapper.from_str(obst['pos']) #if lat<58.5 or lat>59.5: # continue tname = obst.get('name', 'Unknown') if obst.get('kind', '').startswith("notam"): tname = "Notam Obst." points.append( dict(name=tname, lat=lat, lon=lon, kind="obstacle", alt=float(obst['elev']))) if request.params.get('csv', '').strip() != "": #use CSV format meta.Session.flush() meta.Session.commit() buf = StringIO.StringIO() w = csv.writer(buf) for space in out: freq = '' if len(space['freqs']) > 0: freq = " ".join(u"%s" % (x[1], ) for x in space['freqs']) freq = freq line = [ space['name'], '*', freq, '*', space['floor'], space['ceiling'] ] for point in space['points']: lat, lon = point['lat'], point['lon'] line.append(lat) line.append(lon) for i in xrange(len(line)): if type(line[i]) == unicode: line[i] = line[i].encode('utf8') w.writerow(line) response.headers['Content-Type'] = 'text/plain' return buf.getvalue() elif request.params.get('binary', '').strip() != '': response.headers['Content-Type'] = 'application/binary' ret = android_fplan_map_format(airspaces=out, points=points, aiptexts=aiptexts, trips=trips, version=version, user_aipgen=user_aipgen, correct_pass=correct_pass) print "meta.Session.flush/commit" meta.Session.flush() meta.Session.commit() if 'zip' in request.params: zobj = zlib.compressobj(9) #,zlib.DEFLATED,14) ret = zobj.compress(ret) ret += zobj.flush() print "Android map download from:", request.environ.get( "REMOTE_ADDR", 'unknown'), " size: ", len(ret), "bytes" return ret else: meta.Session.flush() meta.Session.commit() rawtext = json.dumps(dict(airspaces=out, points=points), indent=1) if 'zip' in request.params: response.headers[ 'Content-Type'] = 'application/x-gzip-compressed' return zlib.compress(rawtext) else: response.headers['Content-Type'] = 'text/plain' return rawtext
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 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_airspaces(self): print "Get airspaces called" getsectors=int(request.params.get("sectors","0")) out=[] if 1: for space in extracted_cache.get_airspaces()+get_notam_objs_cached()['areas']+extracted_cache.get_aip_sup_areas(): lat,lon=mapper.from_str(space['points'][0]) #if lat<57 or lat>62: # continue if getsectors==0 and space.get('type',None)=='sector': continue name=space['name'] if space['type']=="notamarea": name="NOTAM:"+name clnd=cleanup_poly([mapper.from_str(x) for x in space['points']],name) if not clnd: print "Skipped area",name,space continue out.append(dict( name=name, freqs=space['freqs'] if space.get('freqs',"") else [], floor=space.get('floor',""), type=space['type'], ceiling=space.get('ceiling',""), points=[dict(lat=p[0],lon=p[1]) for p in clnd])) aiptexts=[] points=[] version=request.params.get("version",None) getaiptext=int(request.params.get("aip","0")) print "version",version if version and int(version.strip())>=5: user_aipgen=request.params.get("aipgen","") else: user_aipgen="" for airp in extracted_cache.get_airfields(): lat,lon=mapper.from_str(airp['pos']) if lat<54 or lon<4 or lon>=30.5: try: if not version or int(version.strip())<=7: continue except: continue #if lat<58.5 or lat>60.5: # continue aname=airp['name'] notams=[] icao=None taf=None metar=None kind='field' if airp.get('icao','zzzz').lower()!='zzzz': icao=airp['icao'] notams=notam_geo_search.get_notam_for_airport(icao) metar=metartaf.get_metar(icao) taf=metartaf.get_taf(icao) kind='port' ap=dict( name=aname, lat=lat, lon=lon, kind=kind, notams=notams, remark=airp.get('remark',''), alt=float(airp.get('elev',0))) if 'runways' in airp: ap['runways']=airp['runways'] if icao: ap['icao']=icao if taf.text: ap['taf']=taf.text if metar.text: ap['metar']=metar.text if getaiptext and 'aiptext' in airp: for aiptext in airp['aiptext']: if aip_text_documents.check_doc(aiptext['icao'],aiptext['category'],aiptext['checksum']): #^^^Okay, this really needs an explanation^^^ #Nominally, each aiptext item in aipdata.cache (from which the get_airfields() function #ultimately gets all its data, should always have its corresponding aiptext in html format #available on disk. Now, if the on-disk file is deleted (should never happen), we will #get an exception later down where we try to send this data (with the checksum we have here) #over http to the client. Unfortunately, the routine that sends the data is not at liberty #to modify "what was sent", so the entire sync operation fails. This hack here makes the #failure happen earlier, and in that case the given aiptext-document is suppressed #completely, meaning that the sync operation succeeds, albeit without one specific document #(hey, better than nothing!). # #Of course, the real question is why a document may be missing. A bug of some sort right now, #2012-08-28, makes this bug occur every now and then. Investigation is ongoing. aiptexts.append( dict(name=icao+"_"+aiptext['category'], icao=icao, data=aiptext)) if 'adcharts' in airp and '' in airp['adcharts'] and airp['adcharts'][""]['blobname']: ret=airp['adcharts'][""] try: cksum=ret['checksum'] try: aprojmatrix=get_proj(cksum).matrix except Exception: #print traceback.format_exc() #print "Using 0-proj for ",aname aprojmatrix=[0 for x in xrange(6)] ap['adchart_matrix']=list(aprojmatrix) ap['adchart_width']=ret['render_width'] ap['adchart_height']=ret['render_height'] ap['adchart_name']=ret['blobname'] ap['adchart_checksum']=cksum ap['adchart_url']=ret['url'] except Exception,cause: print "Couldn't get projection for airport %s (%s)"%(aname,cause) points.append(ap)
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)