def get_worklist(self): worklist=[] for ad in sorted(ec.get_airfields(),key=lambda x:x['name']): print "Airfield:",ad if not 'adcharts' in ad: continue for adchart in ad['adcharts'].values(): projurl=h.url_for(controller='airportproj',action="show",ad=ad['name'],checksum=adchart['checksum']) found=False for proj in meta.Session.query(AirportProjection).filter(sa.and_( AirportProjection.user==session['user'], AirportProjection.airport==ad['name'])).order_by(AirportProjection.updated).all(): current=(proj.mapchecksum==str(adchart['checksum'])) date=proj.updated airport=proj.airport marks=meta.Session.query(AirportMarker).filter(sa.and_( AirportMarker.user==session['user'], AirportMarker.airport==ad['name'])).all() if current: if len(proj.matrix)==0 or all([x==0 for x in proj.matrix]): needwork=True else: needwork=False worklist.append(dict(current=current,updated=date,airport=airport,url=projurl,marks=marks,needwork=needwork,variant=adchart['variant'],cksum=str(adchart['checksum']))) found=True if not found: worklist.append(dict(current=False,updated=None,airport=ad['name'],url=projurl,marks=[],needwork=True,variant=adchart['variant'],cksum=str(adchart['checksum']))) return worklist
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 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 load(self): name = request.params['name'] #print "Loading",repr(name) ret = json.dumps(dict(runways=[])) for ac in ec.get_airfields(): if not filter(ac): continue if ac['name'] == name: physical = [] if 'runways' in ac: ret = self.load_ad_json(ac) break response.headers['Content-Type'] = 'application/json' return ret
def load(self): name=request.params['name'] #print "Loading",repr(name) ret=json.dumps(dict(runways=[])) for ac in ec.get_airfields(): if not filter(ac): continue if ac['name']==name: physical=[] if 'runways' in ac: ret=self.load_ad_json(ac) break response.headers['Content-Type'] = 'application/json' return ret
def get_worklist(self): worklist = [] for ad in sorted(ec.get_airfields(), key=lambda x: x['name']): print "Airfield:", ad if not 'adcharts' in ad: continue for adchart in ad['adcharts'].values(): projurl = h.url_for(controller='airportproj', action="show", ad=ad['name'], checksum=adchart['checksum']) found = False for proj in meta.Session.query(AirportProjection).filter( sa.and_( AirportProjection.user == session['user'], AirportProjection.airport == ad['name'])).order_by( AirportProjection.updated).all(): current = (proj.mapchecksum == str(adchart['checksum'])) date = proj.updated airport = proj.airport marks = meta.Session.query(AirportMarker).filter( sa.and_(AirportMarker.user == session['user'], AirportMarker.airport == ad['name'])).all() if current: if len(proj.matrix) == 0 or all( [x == 0 for x in proj.matrix]): needwork = True else: needwork = False worklist.append( dict(current=current, updated=date, airport=airport, url=projurl, marks=marks, needwork=needwork, variant=adchart['variant'], cksum=str(adchart['checksum']))) found = True if not found: worklist.append( dict(current=False, updated=None, airport=ad['name'], url=projurl, marks=[], needwork=True, variant=adchart['variant'], cksum=str(adchart['checksum']))) return worklist
def search(self): print "Search called:", request.params term = strip_accents(request.params['term']).lower() if len(term) < 3: return json.dumps([]) response.headers['Content-Type'] = 'application/json' hits = [] for ac in ec.get_airfields(): if not filter(ac): continue if (strip_accents(ac['name']).lower().count(term)): hits.append(ac['name']) hits.sort() return json.dumps(hits[:10])
def search(self): print "Search called:",request.params term=strip_accents(request.params['term']).lower() if len(term)<3: return json.dumps([]) response.headers['Content-Type'] = 'application/json' hits=[] for ac in ec.get_airfields(): if not filter(ac): continue if (strip_accents(ac['name']).lower().count(term)): hits.append(ac['name']) hits.sort() return json.dumps(hits[:10])
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 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 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 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 show(self): ad = request.params['ad'] cksum = request.params['checksum'] chartobj = None for adobj in ec.get_airfields(): bb = False if adobj['name'] == ad and 'adcharts' in adobj: for adchart in adobj['adcharts'].values(): if adchart['checksum'] == cksum: chartobj = adchart bb = True break if bb: break else: self.error("No such airport/picture " + ad + "/" + cksum) projs = meta.Session.query(AirportProjection).filter( sa.and_( AirportProjection.user == session['user'], AirportProjection.airport == ad, AirportProjection.mapchecksum == adchart['checksum'])).all() c.markers = meta.Session.query(AirportMarker).filter( sa.and_( AirportMarker.user == session['user'], AirportMarker.airport == ad, AirportMarker.mapchecksum == adchart['checksum'])).order_by( AirportMarker.latitude, AirportMarker.longitude, AirportMarker.x, AirportMarker.y).all() if not projs: proj = AirportProjection() proj.user = session['user'] proj.airport = ad proj.mapchecksum = str(adchart['checksum']) proj.updated = datetime.utcnow() proj.matrix = (1, 0, 0, 1, 0, 0) proj.scale = None proj.north = None meta.Session.add(proj) meta.Session.flush() meta.Session.commit() else: proj, = projs proj.mapchecksum = str(proj.mapchecksum) if all([x == 0 for x in proj.matrix[4:6]]): projmatrix = self.invent_matrix(proj.mapchecksum, adchart['variant']) else: projmatrix = proj.matrix A = projmatrix[0:4] T = projmatrix[4:6] transform = customproj.Transform(A, T) c.matrix = projmatrix c.initial_scroll_x = request.params.get("scroll_x", 0) c.initial_scroll_y = request.params.get("scroll_y", 0) c.maptype = request.params.get("maptype", "chart") c.variant = adchart['variant'] c.curadmarker = session.get('curadmarker', (0, 0)) c.img = adchart['blobname'] + "," + adchart['checksum'] c.flash = None c.ad = ad c.mapchecksum = adchart['checksum'] c.mapsize = adchart.get('mapsize', (210, 297)) c.scale = proj.scale if proj.scale != None else "" c.north = proj.north if proj.north != None else "" c.runways = [] c.arp = transform.to_pixels(mapper.from_str(adobj['pos'])) arp1m = mapper.latlon2merc(mapper.from_str(adobj['pos']), 17) arp2m = mapper.latlon2merc(mapper.from_str(adobj['pos']), 17) arp1m = (arp1m[0], arp1m[1] - 250) arp2m = (arp2m[0] + 250, arp2m[1]) c.arp1 = transform.to_pixels(mapper.merc2latlon(arp1m, 17)) c.arp2 = transform.to_pixels(mapper.merc2latlon(arp2m, 17)) def dist(x, y): return math.sqrt((x[0] - y[0])**2 + (x[1] - y[1])**2) c.ratio = abs(dist(c.arp, c.arp1) - dist(c.arp, c.arp2)) / max( dist(c.arp, c.arp1), dist(c.arp, c.arp2)) c.transform_reasonable = True x, y = c.arp if x < -200 or y < -200 or x >= 4000 or y >= 4000: c.transform_reasonable = False c.revmarkers = [] c.width, c.height = chartobj['render_width'], chartobj['render_height'] try: c.base_coords=\ [mapper.latlon2merc(transform.to_latlon((0,0)),13), mapper.latlon2merc(transform.to_latlon((c.width,0)),13), mapper.latlon2merc(transform.to_latlon((0,c.height)),13), mapper.latlon2merc(transform.to_latlon((c.width,c.height)),13)] except Exception: print "problem with basecoords:", traceback.format_exc() c.base_coords = [(0, 0) for x in xrange(4)] for mark in c.markers: lat, lon = transform.to_latlon((mark.x, mark.y)) if mark.latitude: lat = mark.latitude if mark.longitude: lon = mark.longitude pos = transform.to_pixels((lat, lon)) c.revmarkers.append(pos) for rwy in adobj.get('runways', []): ends = rwy['ends'] latlon1 = mapper.from_str(ends[0]['pos']) latlon2 = mapper.from_str(ends[1]['pos']) print rwy, "Runway pos", latlon1, " to ", latlon2 p1 = transform.to_pixels(latlon1) p2 = transform.to_pixels(latlon2) for p in [p1, p2]: x, y = p if x < -200 or y < -200 or x >= 4000 or y >= 4000: c.transform_reasonable = False c.runways.append( ((int(p1[0]), int(p1[1])), (int(p2[0]), int(p2[1])))) c.random = md5.md5(pickle.dumps(projmatrix)).hexdigest() return render('/airportproj.mako')
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)
charts = [] print "Client request params", request.params if version <= 3: prevstamp = int(request.params["stamp"]) print "getnewadchart, prevstamp:", prevstamp #Make any sort of race impossible by substracting 5 minutes from now. #A race will now only happen if a file is modified on disk, after this #routine started, but ends up with a timestamp 5 minutes earlier in #time, but that can't happen. nowstamp = utcdatetime2stamp_inexact(datetime.utcnow()) - 60 * 5 assert version in [1, 2, 3] print "Old stamp", prevstamp for ad in extracted_cache.get_airfields(): if ad.get('icao', 'ZZZZ').upper() == 'ZZZZ': continue #Ignore non-icao airports if 'adcharts' in ad: for adc in ad['adcharts'].values(): newer = False try: cksum, proj = self.get_sel_cksum(adc['blobname']) if proj and proj.updated > datetime.utcfromtimestamp( prevstamp): newer = True #print "selected",cksum,"for",adc if version <= 2 and adc['variant'] != '': continue #Don't send all kinds of charts to old clients if cksum == None: continue for level in xrange(5):
def index(self): ack_cnt = meta.Session.query(NotamAck.appearnotam,NotamAck.appearline,sa.func.count('*').label('acks')).filter(NotamAck.user==session.get('user',None)).group_by(NotamAck.appearnotam,NotamAck.appearline).subquery() c.items=meta.Session.query(NotamUpdate,ack_cnt.c.acks,Notam.downloaded).outerjoin( (ack_cnt,sa.and_( NotamUpdate.appearnotam==ack_cnt.c.appearnotam, NotamUpdate.appearline==ack_cnt.c.appearline))).outerjoin( (Notam,Notam.ordinal==NotamUpdate.appearnotam) ).order_by(sa.desc(Notam.downloaded)).filter( NotamUpdate.disappearnotam==sa.null()).all() c.categories=set([notamupdate.category for notamupdate,acks,downloaded in c.items]) user=meta.Session.query(User).filter(User.user==session['user']).one() c.showobst=user.showobst def vandalize(x): x=x.replace(u"Å",u"A") x=x.replace(u"Ä",u"A") x=x.replace(u"Ö",u"O") return x for air in get_airfields(): c.categories.add(vandalize(u"%s/%s"%(air['icao'].upper(),air['name'].upper()))) c.sel_cat=set(x.category for x in meta.Session.query(NotamCategoryFilter).filter(NotamCategoryFilter.user==session['user'])) c.shown=[] c.show_cnt=0 c.hide_cnt=0 c.countries=[ dict(name="Sweden",sel=False,short="ES"), dict(name="Finland",sel=False,short="EF"), dict(name="Estonia",sel=False,short="EE"), dict(name="Latvia",sel=False,short="EV"), dict(name="Denmark",sel=False,short="EK"), ] if 1: for ct in meta.Session.query(NotamCountryFilter).filter( NotamCountryFilter.user==session['user']).all(): for countrydict in c.countries: if countrydict['name']==ct.country: countrydict['sel']=True selcountries=set() for ct in c.countries: if ct['sel']: selcountries.add(ct['short']) if len(selcountries)==0: selcountries=None ms=[] ms.append(re.compile(r".*\bOBST\s+ERECTED\b.*")) ms.append(re.compile(r".*TURBINE?S?\s+ERECTED\b.*")) ms.append(re.compile(r".*\bMASTS?\s+ERECTED\b.*")) ms.append(re.compile(r".*\bCRANES?\s+ERECTED\b.*")) ms.append(re.compile(r".*LIGHTS?.*OUT\s+OF\s+SERVICE.*",re.DOTALL)) for notamupdate,acks,downloaded in c.items: if not c.showobst: match=False for m in ms: if m.match(notamupdate.text): match=True break if match: c.hide_cnt+=1 continue if (len(c.sel_cat)==0 or notamupdate.category in c.sel_cat) and \ (selcountries==None or notamupdate.category==None or notamupdate.category[:2] in selcountries): c.shown.append((notamupdate,acks,downloaded)) c.show_cnt+=1 else: c.hide_cnt+=1 print "Start rendering mako" return render('/notam.mako')
charts=[] print "Client request params",request.params if version<=3: prevstamp=int(request.params["stamp"]) print "getnewadchart, prevstamp:",prevstamp #Make any sort of race impossible by substracting 5 minutes from now. #A race will now only happen if a file is modified on disk, after this #routine started, but ends up with a timestamp 5 minutes earlier in #time, but that can't happen. nowstamp=utcdatetime2stamp_inexact(datetime.utcnow())-60*5 assert version in [1,2,3] print "Old stamp",prevstamp for ad in extracted_cache.get_airfields(): if ad.get('icao','ZZZZ').upper()=='ZZZZ':continue #Ignore non-icao airports if 'adcharts' in ad: for adc in ad['adcharts'].values(): newer=False try: cksum,proj=self.get_sel_cksum(adc['blobname']) if proj and proj.updated>datetime.utcfromtimestamp(prevstamp): newer=True #print "selected",cksum,"for",adc if version<=2 and adc['variant']!='': continue #Don't send all kinds of charts to old clients if cksum==None: continue for level in xrange(5): cstamp=parse_landing_chart.get_timestamp(adc['blobname'],cksum,level) #print "Read file stamp:",cstamp,"prevstamp:",prevstamp
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 show(self): ad=request.params['ad'] cksum=request.params['checksum'] chartobj=None for adobj in ec.get_airfields(): bb=False if adobj['name']==ad and 'adcharts' in adobj: for adchart in adobj['adcharts'].values(): if adchart['checksum']==cksum: chartobj=adchart bb=True break if bb: break else: self.error("No such airport/picture "+ad+"/"+cksum) projs=meta.Session.query(AirportProjection).filter(sa.and_( AirportProjection.user==session['user'], AirportProjection.airport==ad, AirportProjection.mapchecksum==adchart['checksum'])).all() c.markers=meta.Session.query(AirportMarker).filter(sa.and_( AirportMarker.user==session['user'], AirportMarker.airport==ad, AirportMarker.mapchecksum==adchart['checksum'])).order_by(AirportMarker.latitude,AirportMarker.longitude,AirportMarker.x,AirportMarker.y).all() if not projs: proj=AirportProjection() proj.user=session['user'] proj.airport=ad proj.mapchecksum=str(adchart['checksum']) proj.updated=datetime.utcnow() proj.matrix=(1,0,0,1,0,0) proj.scale=None proj.north=None meta.Session.add(proj) meta.Session.flush() meta.Session.commit() else: proj,=projs proj.mapchecksum=str(proj.mapchecksum) if all([x==0 for x in proj.matrix[4:6]]): projmatrix=self.invent_matrix(proj.mapchecksum,adchart['variant']) else: projmatrix=proj.matrix A=projmatrix[0:4] T=projmatrix[4:6] transform=customproj.Transform(A,T) c.matrix=projmatrix c.initial_scroll_x=request.params.get("scroll_x",0) c.initial_scroll_y=request.params.get("scroll_y",0) c.maptype=request.params.get("maptype","chart") c.variant=adchart['variant'] c.curadmarker=session.get('curadmarker',(0,0)) c.img=adchart['blobname']+","+adchart['checksum'] c.flash=None c.ad=ad c.mapchecksum=adchart['checksum'] c.mapsize=adchart.get('mapsize',(210,297)) c.scale=proj.scale if proj.scale!=None else "" c.north=proj.north if proj.north!=None else "" c.runways=[] c.arp=transform.to_pixels(mapper.from_str(adobj['pos'])) arp1m=mapper.latlon2merc(mapper.from_str(adobj['pos']),17) arp2m=mapper.latlon2merc(mapper.from_str(adobj['pos']),17) arp1m=(arp1m[0],arp1m[1]-250) arp2m=(arp2m[0]+250,arp2m[1]) c.arp1=transform.to_pixels(mapper.merc2latlon(arp1m,17)) c.arp2=transform.to_pixels(mapper.merc2latlon(arp2m,17)) def dist(x,y): return math.sqrt((x[0]-y[0])**2+(x[1]-y[1])**2) c.ratio=abs(dist(c.arp,c.arp1)-dist(c.arp,c.arp2))/max(dist(c.arp,c.arp1),dist(c.arp,c.arp2)); c.transform_reasonable=True x,y=c.arp if x<-200 or y<-200 or x>=4000 or y>=4000: c.transform_reasonable=False c.revmarkers=[] c.width,c.height=chartobj['render_width'],chartobj['render_height'] try: c.base_coords=\ [mapper.latlon2merc(transform.to_latlon((0,0)),13), mapper.latlon2merc(transform.to_latlon((c.width,0)),13), mapper.latlon2merc(transform.to_latlon((0,c.height)),13), mapper.latlon2merc(transform.to_latlon((c.width,c.height)),13)] except Exception: print "problem with basecoords:",traceback.format_exc() c.base_coords=[(0,0) for x in xrange(4)] for mark in c.markers: lat,lon=transform.to_latlon((mark.x,mark.y)) if mark.latitude: lat=mark.latitude if mark.longitude: lon=mark.longitude pos=transform.to_pixels((lat,lon)) c.revmarkers.append(pos) for rwy in adobj.get('runways',[]): ends=rwy['ends'] latlon1=mapper.from_str(ends[0]['pos']) latlon2=mapper.from_str(ends[1]['pos']) print rwy,"Runway pos",latlon1," to ",latlon2 p1=transform.to_pixels(latlon1) p2=transform.to_pixels(latlon2) for p in [p1,p2]: x,y=p if x<-200 or y<-200 or x>=4000 or y>=4000: c.transform_reasonable=False c.runways.append(( (int(p1[0]),int(p1[1])), (int(p2[0]),int(p2[1])) )) c.random=md5.md5(pickle.dumps(projmatrix)).hexdigest() return render('/airportproj.mako')
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)