Exemplo n.º 1
0
 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))
Exemplo n.º 2
0
def clean_up_polygon(poss):
    print "Clean poly:",poss
    def tov(merc):
        return Vertex(int(merc[0]),int(merc[1]))
    def fromv(v):
        return (v.get_x(),v.get_y())
    vertices=[]
    last=None
    for pos in poss:
        #print pos
        if pos==last: continue
        last=pos
        vertices.append(tov(mapper.latlon2merc(mapper.from_str(pos),13)))
    poly=Polygon(vvector(vertices))
    #print "calling tidy-up"
    shape=tidy_up_polygon(poly)
    ret=[]
    for poly in shape.get_polys():
        #print "Got poly"
        vs=poly.get_vertices()
        out=[]
        for v in vs:
            out.append(mapper.to_str(mapper.merc2latlon(fromv(v),13)))
        ret.append(out)
    return ret
Exemplo n.º 3
0
def clean_up_polygon(poss):
    print "Clean poly:", poss

    def tov(merc):
        return Vertex(int(merc[0]), int(merc[1]))

    def fromv(v):
        return (v.get_x(), v.get_y())

    vertices = []
    last = None
    for pos in poss:
        #print pos
        if pos == last: continue
        last = pos
        vertices.append(tov(mapper.latlon2merc(mapper.from_str(pos), 13)))
    poly = Polygon(vvector(vertices))
    #print "calling tidy-up"
    shape = tidy_up_polygon(poly)
    ret = []
    for poly in shape.get_polys():
        #print "Got poly"
        vs = poly.get_vertices()
        out = []
        for v in vs:
            out.append(mapper.to_str(mapper.merc2latlon(fromv(v), 13)))
        ret.append(out)
    return ret
Exemplo n.º 4
0
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    
Exemplo n.º 5
0
def get_low_sun_near_route(rts):
    l=len(rts)
    out=[]
    dt=None
    for idx,rt in enumerate(rts):
        if rt.dt==None: continue
        #print "ord:",rt.a.ordering
        tottime=rt.dt-rt.startdt
        merca=rt.subposa
        mercb=rt.subposb
        curtime=timedelta(0)
        real_heading=rt.tt+rt.wca
        while True:
            if curtime>=tottime:
                break
            f=divide(curtime,tottime)
            fi=1.0-f
            merc=(fi*merca[0]+f*mercb[0],fi*merca[1]+f*mercb[1])
            latlon=mapper.merc2latlon(merc,13)        
            when=rt.startdt+curtime
            ele,azi=sun_position_in_sky(when,latlon[0],latlon[1])
            #print "Sun position: ele=%s, azi=%s, heading=%s"%(ele,azi,real_heading)
            if (ele>-0.5 and ele<25):
                off=(azi-real_heading)
                if abs(off)<25:
                    dirclock=int(round(off/15.0))
                    if dirclock<=0:
                        dirclock+=12
                    out.append(dict(
                        name="Low Sun Warning (Direction: %d o'clock, %.0f deg above horizon. Blinding?)"%(
                                dirclock,max(0,ele)),
                        pos=mapper.to_str(latlon),
                        elev="",
                        elevf=0,
                        dist=0,
                        bearing=azi,
                        closestalt=None,
                        kind='lowsun',
                        dist_from_a=mapper.bearing_and_distance(mapper.from_str(rt.a.pos),latlon)[1],
                        dist_from_b=mapper.bearing_and_distance(mapper.from_str(rt.b.pos),latlon)[1],
                        dir_from_a=describe_dir(rt.tt),
                        dir_from_b=describe_dir((rt.tt+180.0)%360.0),
                        a=rt.a,
                        b=rt.b,
                        id=rt.a.id))
                    print "Generated sun warning:",out[-1]
                    break
            curtime+=timedelta(minutes=2)
    return out
Exemplo n.º 6
0
 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))
Exemplo n.º 7
0
def parse_airfields():
    out = []
    for item in csv.reader(open("fplan/extract/denmark.airfields.csv")):
        print item
        icao, empty, ICAO, name, d1, d2, pos, elev, owner, phone, d4, d5, webside = item
        if not pos[-1] in ['E', 'W']:
            pos = pos + "E"
        print "ICAO:", icao
        assert icao.upper() == ICAO
        name = coding(name)
        lat, lon = mapper.from_str(mapper.parsecoord(pos))
        nasaelev = get_terrain_elev((lat, lon))
        if elev == '':
            elev = nasaelev
        if nasaelev != 9999:
            assert abs(float(elev) - nasaelev) < 100
        ad = dict(icao=ICAO,
                  name=name,
                  pos=mapper.to_str((lat, lon)),
                  date="2010-01-01T00:00:00Z",
                  elev=int(elev))
        out.append(ad)
    return out
Exemplo n.º 8
0
def parse_airfields():
    out=[]
    for item in csv.reader(open("fplan/extract/denmark.airfields.csv")):
        print item
        icao,empty,ICAO,name,d1,d2,pos,elev,owner,phone,d4,d5,webside=item
        if not pos[-1] in ['E','W']:
            pos=pos+"E"
        print "ICAO:",icao
        assert icao.upper()==ICAO
        name=coding(name)
        lat,lon=mapper.from_str(mapper.parsecoord(pos))
        nasaelev=get_terrain_elev((lat,lon))
        if elev=='':
            elev=nasaelev        
        if nasaelev!=9999:
            assert abs(float(elev)-nasaelev)<100
        ad=dict(
            icao=ICAO,
            name=name,
            pos=mapper.to_str((lat,lon)),
            date="2010-01-01T00:00:00Z",
            elev=int(elev))
        out.append(ad)
    return out
Exemplo n.º 9
0
 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
Exemplo n.º 10
0
def osm_airfields_parse():
    nameicao = parse_info()
    f = open("adnames.txt", "w")
    for name, icao in sorted(nameicao, key=lambda x: x[0]):
        f.write("%s: %s\n" % (icao.encode('utf8'), name.encode('utf8')))
    f.close()
    ads = []
    hits = 0
    misses = []

    name2icao = []
    for name, icao in nameicao:
        name2icao.append((normalize(name), name, icao))

    dupecheck = set()

    for lon, lat, name in csv.reader(open("fplan/extract/aerodromes.txt")):
        name = unicode(name, "utf8")
        if not name.strip(): continue

        icao = None
        n1 = normalize(name)
        if frozenset(n1) in dupecheck:
            continue
        dupecheck.add(frozenset(n1))
        lastquality = 0
        lastname = None
        for n2, iname, iicao in name2icao:
            #print repr(n1),"==",repr(n2)
            minlen = min(len(n1), len(n2))
            if minlen > 2:
                minlen = minlen - 1
            quality = len(n1.intersection(n2))
            if quality >= minlen and quality > lastquality:
                if icao != None and icao != iicao:
                    print "For name:", name, "Previous match:,", icao, "New match:", iicao, "Name:", iname, "last name:", lastname, "quality:", quality, "last:", lastquality, "minlen:", minlen
                    #assert icao==None
                icao = iicao
                lastquality = quality
                lastname = iname
        #print "Ap with name:",name
        if icao:
            hits += 1
            icao = icao
        else:
            icao = 'ZZZZ'
            misses.append(name)
            #print "Missed:",name
        d = dict(icao=icao,
                 name=name,
                 pos=mapper.to_str((float(lat), float(lon))),
                 elev=int(gte.get_terrain_elev((float(lat), float(lon)))))

        if hits % 10 == 0:
            print "Hits: %d, Misses: %d, Perc: %.1f" % (
                hits, len(misses), 100.0 * (float(hits) /
                                            (float(hits) + len(misses))))
        ads.append(d)
    print "Misses:"
    f = open("missedads.txt", "w")
    for miss in sorted(misses):
        f.write((miss + " - " + repr(normalize(miss)) + u"\n").encode('utf8'))
    f.close()
    f = open("foundads.txt", "w")
    for norm, name, icao in name2icao:
        f.write((name + " - " + repr(norm) + u"\n").encode('utf8'))
    f.close()
    print "Hits: ", hits
    print "Misses: ", len(misses)

    return ads
Exemplo n.º 11
0
def get_terrain_near_route(rts,vertdist,interval=10):
    l=len(rts)
    out=[]
    for idx,rt in enumerate(rts):
        #print "ord:",rt.a.ordering
        if rt.dt==None:
            continue
        merca=rt.subposa
        mercb=rt.subposb
        
        minstep=2
                
        stepcount=rt.d/float(minstep)
        if stepcount>100:
            newstep=rt.d/100.0
            if newstep>minstep:
                minstep=newstep
        if interval<minstep:
            interval=minstep        
        df=rt.d
        
        
        if df<1e-3:
            df=1e-3
        along_nm=0.0
        #isfirstorlast=(idx==0 or idx==l-1)        
        while True:
            alongf=float(along_nm)/float(df)
            end=False
            if alongf>1.0:
                alongf=1.0
                end=True
            merc=((1.0-alongf)*merca[0]+(alongf)*mercb[0],
                  (1.0-alongf)*merca[1]+(alongf)*mercb[1])
            alt=(1.0-alongf)*rt.startalt+(alongf)*rt.endalt
            latlon=mapper.merc2latlon(merc,13)
            elev=get_terrain_elev_in_box_approx(latlon,2*minstep)
            
            
            dist_from_a=mapper.bearing_and_distance(mapper.from_str(rt.a.pos),latlon)[1]
            dist_from_b=rt.d-dist_from_a
            if dist_from_b<0: dist_from_b=0
            
                
                
            
            
            #if isfirstorlast and (along_nm<2.5 or along_nm>d-2.5):
            #    along_nm+=minstep
            #    continue
               
            if (alt-elev<vertdist and
                not (rt.a.stay and dist_from_a<5) and
                not ((rt.b.stay or idx==l-1) and dist_from_b<5) ):

                #print "idx",idx,"ord:",rt.a.ordering
                #print "Terrain warning: ",dict(a=rt.a.waypoint,b=rt.b.waypoint,kind=rt.legpart,startalt=rt.startalt,endalt=rt.endalt,along=alongf,end=end)
                out.append(dict(
                    name="Terrain warning",
                    pos=mapper.to_str(latlon),
                    elev="%.0f"%(elev,),
                    elevf=elev,
                    dist=0,
                    bearing=0,
                    closestalt=alt,
                    kind='terrain',
                    dist_from_a=dist_from_a,
                    dir_from_a=describe_dir(rt.tt),
                    dist_from_b=dist_from_b,
                    dir_from_b=describe_dir((rt.tt+180.0)%360.0),
                    a=rt.a,
                    b=rt.b,
                    id=rt.a.id))
                along_nm+=interval
            else:
                along_nm+=minstep
            if end: 
                break
    return out
Exemplo n.º 12
0
        if type(name) == str:
            name = unicode(name, "utf8")
        mercf = mapper.latlon2merc((lat, lon), 13)
        for a in origads:
            merca = mapper.latlon2merc(mapper.from_str(a["pos"]), 13)
            dist = math.sqrt((merca[0] - mercf[0]) ** 2 + (merca[1] - mercf[1]) ** 2)
            if dist < 120:
                found = a
                break
        if found:
            found["flygkartan_id"] = flygkartan_id
        else:
            d = dict(
                icao="ZZZZ",
                name=name,
                pos=mapper.to_str((lat, lon)),
                elev=int(get_terrain_elev((lat, lon))),
                flygkartan_id=flygkartan_id,
            )
            if filtericao(d):
                ads.append(d)

    minor_ad_charts = extra_airfields.minor_ad_charts

    for ad in ads:
        if ad["name"].count(u"Långtora"):
            ad["pos"] = mapper.to_str(mapper.from_aviation_format("5944.83N01708.20E"))

        if ad["name"] in minor_ad_charts:
            charturl = minor_ad_charts[ad["name"]]
            arp = ad["pos"]
Exemplo n.º 13
0
        borders=[[mapper.latlon2merc(mapper.from_str(x),13) for x in points] for points in context]
    else:
        borders=get_borders(context)
    print "start,end",start,end
    part1,idx1,pos1=find_closest(borders,start)
    part2,idx2,pos2=find_closest(borders,end)
    print "Found",pos1,pos2
    if part1!=part2: raise Exception("Start and endpoint are not on same island!")
    part=part1
    print "from,to",idx1,idx2
    if idx1==idx2:
        return [start,end]
    res1,dist1=circle(borders[part],pos1,idx1,idx2,pos2,-1)
    res2,dist2=circle(borders[part],pos1,idx1,idx2,pos2,1)
    if dist1<dist2:
        if longwayround:
            ret=res2
        else:
            ret=res1
    else:
        if longwayround:
            ret=res1
        else:
            ret=res2        
    return [start]+ret+[end]

if __name__=='__main__':
    fa=follow_along("sweden",(59.0,11.4),(61.0,12.5))
    print " - ".join(mapper.to_str(pos) for pos in fa)
        
    
Exemplo n.º 14
0
    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
Exemplo n.º 15
0
def fi_parse_tma():
    p=parse.Parser(r"/ais/eaip/pdf/enr/EF_ENR_2_1_EN.pdf",fixuphref,country='fi')
	
    res=[]    
    atsres=[]
    for pagenr in xrange(4,p.get_num_pages()): 
        parsed,atsparsed=parse_page(p,pagenr)#pagenr)
        res.extend(parsed)
        atsres.extend(atsparsed)        
        #break
        
    
    print "Len ouf out ",len(res)
    atsout=[]    
    for space in atsres:
        #print "bef cut:",space['points']
        mypolys=[makepoly.poly(space['points'])]    
        for tmaitem in res:
            if tmaitem['type']!='TMA': continue
            outmypolys=[]
            assert len(mypolys)>=1
            for mypoly in list(mypolys):
                tmapoly=makepoly.poly(tmaitem['points'])
                #print mypoly
                #print tmapoly
                shape=mypoly.subtract(tmapoly)
                newpolys=shape.get_polys()
                if len(newpolys)>1:
                    print "Length is:", len(newpolys)
                #print "Cutting"
                outmypolys.extend([shapemerge2d.Polygon(x) for x in list(newpolys)])
                #assert len(newpolys)==1
            if len(outmypolys)>1:
                print "outmypolys:",outmypolys
                #print "Cut to:",mypoly
            mypolys=outmypolys
            
        for mypoly in mypolys:
            t=[]
            for mx,my in [(v.get_x(),v.get_y()) for v in  mypoly.get_vertices()]:
                t.append(mapper.to_str(mapper.merc2latlon((mx,my),13)))
            #print "Aft cut:",t
            newspace=dict(space)
            newspace['points']=t            
            atsout.append(newspace)
        if len(mypolys)>1:    
            print "Space was split into ",len(mypolys),"parts"
    res.extend(atsout)
        
    res.append(dict(
        name="FINLAND FIR",
        icao="EFIN",
        floor='GND',
        ceiling='-',
        freqs=[],
        type='FIR',
        date=datetime(2011,4,9),
        points=mapper.parse_coord_str("""                                   
    601130N 0190512E - 601803N 0190756E -
610000N 0191905E - 614000N 0193000E -
631000N 0201000E - 632830N 0204000E -
633700N 0213000E - 644100N 0225500E -
653148N 0240824E -
Along the common X/Y state boundary to 690336N 0203255E -
Along the common X/Y state boundary to 690307N 0285545E -
Along the common X/Y state boundary to 601201N 0271735E - 
600800N 0263300E -
595830N 0260642E - 595300N 0255200E -
595430N 0252000E - 595300N 0245100E -
590000N 0210000E - 591524N 0203239E -
593346N 0195859E - 601130N 0190512E
""",context="finland")))
        
        
        
    #for pa in res:
    #    pretty(pa)
        
        
    return res
Exemplo n.º 16
0
    else:
        borders = get_borders(context)
    print "start,end", start, end
    part1, idx1, pos1 = find_closest(borders, start)
    part2, idx2, pos2 = find_closest(borders, end)
    print "Found", pos1, pos2
    if part1 != part2:
        raise Exception("Start and endpoint are not on same island!")
    part = part1
    print "from,to", idx1, idx2
    if idx1 == idx2:
        return [start, end]
    res1, dist1 = circle(borders[part], pos1, idx1, idx2, pos2, -1)
    res2, dist2 = circle(borders[part], pos1, idx1, idx2, pos2, 1)
    if dist1 < dist2:
        if longwayround:
            ret = res2
        else:
            ret = res1
    else:
        if longwayround:
            ret = res1
        else:
            ret = res2
    return [start] + ret + [end]


if __name__ == '__main__':
    fa = follow_along("sweden", (59.0, 11.4), (61.0, 12.5))
    print " - ".join(mapper.to_str(pos) for pos in fa)
Exemplo n.º 17
0
def fi_parse_tma():
    p = parse.Parser(r"/ais/eaip/pdf/enr/EF_ENR_2_1_EN.pdf",
                     fixuphref,
                     country='fi')

    res = []
    atsres = []
    for pagenr in xrange(4, p.get_num_pages()):
        parsed, atsparsed = parse_page(p, pagenr)  #pagenr)
        res.extend(parsed)
        atsres.extend(atsparsed)
        #break

    print "Len ouf out ", len(res)
    atsout = []
    for space in atsres:
        #print "bef cut:",space['points']
        mypolys = [makepoly.poly(space['points'])]
        for tmaitem in res:
            if tmaitem['type'] != 'TMA': continue
            outmypolys = []
            assert len(mypolys) >= 1
            for mypoly in list(mypolys):
                tmapoly = makepoly.poly(tmaitem['points'])
                #print mypoly
                #print tmapoly
                shape = mypoly.subtract(tmapoly)
                newpolys = shape.get_polys()
                if len(newpolys) > 1:
                    print "Length is:", len(newpolys)
                #print "Cutting"
                outmypolys.extend(
                    [shapemerge2d.Polygon(x) for x in list(newpolys)])
                #assert len(newpolys)==1
            if len(outmypolys) > 1:
                print "outmypolys:", outmypolys
                #print "Cut to:",mypoly
            mypolys = outmypolys

        for mypoly in mypolys:
            t = []
            for mx, my in [(v.get_x(), v.get_y())
                           for v in mypoly.get_vertices()]:
                t.append(mapper.to_str(mapper.merc2latlon((mx, my), 13)))
            #print "Aft cut:",t
            newspace = dict(space)
            newspace['points'] = t
            atsout.append(newspace)
        if len(mypolys) > 1:
            print "Space was split into ", len(mypolys), "parts"
    res.extend(atsout)

    res.append(
        dict(name="FINLAND FIR",
             icao="EFIN",
             floor='GND',
             ceiling='-',
             freqs=[],
             type='FIR',
             date=datetime(2011, 4, 9),
             points=mapper.parse_coord_str(
                 """                                   
    601130N 0190512E - 601803N 0190756E -
610000N 0191905E - 614000N 0193000E -
631000N 0201000E - 632830N 0204000E -
633700N 0213000E - 644100N 0225500E -
653148N 0240824E -
Along the common X/Y state boundary to 690336N 0203255E -
Along the common X/Y state boundary to 690307N 0285545E -
Along the common X/Y state boundary to 601201N 0271735E - 
600800N 0263300E -
595830N 0260642E - 595300N 0255200E -
595430N 0252000E - 595300N 0245100E -
590000N 0210000E - 591524N 0203239E -
593346N 0195859E - 601130N 0190512E
""",
                 context="finland")))

    #for pa in res:
    #    pretty(pa)

    return res
Exemplo n.º 18
0
def no_obstacles():
    out = []
    fnames = [
        "/home/anders/saker/avl_fplan_world/norway_obst/20120903pkt.shp",
        "/home/anders/saker/avl_fplan_world/norway_obst/20120903linpkt.shp",
        "/home/anders/saker/avl_fplan_world/norway_obst/20120903lin.shp"
    ]

    for fname in fnames:
        r = shapefile.Reader(fname)
        utm = Proj(proj='utm', zone=33, ellps='WGS84')
        wgs84 = Proj(init='epsg:4326')

        untrans = set()
        osts = {
            unicode('Vindm\xef\xbf\xbdlle', 'utf8'): 'Wind turbine',
            u'T\ufffdrn': 'Tower',
            u'Mast TELE': 'Mast',
            u'Annet': 'Antenna',
            u'Heisekran': 'Crane',
            u'Tank': 'Tank',
            u'Fyr': 'Lighthouse',
            u'Bru': 'Bridge',
            u'Mast EL': 'Mast',
            u'Pipe': 'Chimney',
            u'Oljeinstallasjon': 'Oil Platform',
            u'Mast/stolpe veilys': 'Mast',
            u'Bygning': 'Building',
            u'Hoppbakke': 'Ski-jump',
            u'Silo': 'Silo',
            u'Skiheis': 'Ski lift',
            u'Kraftlinespenn': 'Power lines',
            u'LuftledningLH': 'Power lines',
            u'Gondolheis': 'Ski lift',
            u'Taubane': 'Aerial tramway',
            u'L\ufffdypestreng': 'Power lines'
        }
        """
    "Wind turbine",
    "Mast",
    "Cathedral",
    "Pylon",
    "Building",
    "Platform",
    "Chimney",
    "Mine hoist",
    "Bridge pylon",
    "Crane",
    "W Tower",
    "Church",
    "Silo",
    "City Hall",
    "Gasometer",
    "Tower",
    "Bridge pylon, 60 per minute"]
    """
        columns = [x[0] for x in r.fields]

        for rec in r.shapeRecords():
            #print "col:",columns
            #print "rec:",rec.record
            d = dict(zip(columns[1:], rec.record))

            def fixname(n):
                n = n.strip()
                if n == "":
                    n = "Unknown"
                return n

            nortype = unicode(d['hindertype'], 'utf8')
            engtype = osts.get(nortype, nortype)
            if not nortype in osts:
                untrans.add(nortype)
            base = dict(name=fixname(unicode(d['lfh_navn'], 'utf8')),
                        height=int(d['hoeydeover'] / 0.3048),
                        elev=int(d['totalhoeyd'] / 0.3048),
                        lighting=unicode(d['lyssetting'], 'utf8'),
                        kind=engtype,
                        date=datetime(2012, 9, 1))
            if base['height'] < 300:
                continue
            for point in rec.shape.points:
                x, y = point
                lon, lat = transform(utm, wgs84, x, y)
                #print "Input: ",d,x,y,"output:",lat,lon
                cur = copy(base)
                cur['pos'] = mapper.to_str((lat, lon))
                out.append(cur)
            #break
        print "missing translations", untrans
    return out
Exemplo n.º 19
0
#encoding=utf8
import fplan.lib.mapper as mapper
import rwy_constructor

minor_ad_charts={
        u"Frölunda":"http://www.swflightplanner.se:8080/frolunda.jpg"
}
frolunda=dict(icao="ESVF",
         name=u"Frölunda",
         pos=mapper.to_str(mapper.from_aviation_format("5927.5N01742.4E")),
         runways=rwy_constructor.get_rwys(
                    [
                     dict(pos="59.458468, 17.70691",thr="16",usable_pos="59.459198, 17.70644"),
                     dict(pos="59.45414, 17.71009",thr="34"),
                     #dict(pos="59.458716, 17.707166",thr="07",usable_pos="59.458505, 17.705782"),
                     #dict(pos="59.459343, 17.712018",thr="25",usable_pos="59.459343, 17.712018"),
                     ]
                    ),
         elev=30)
                 
extra_airfields=[
    frolunda,
         
    dict(icao="ZZZZ",
         name=u"Finspång",
         pos=mapper.to_str(mapper.from_aviation_format("5843.990N01536.171E")),
         elev=164),#TODO: Add real elev
    dict(icao="ZZZZ",
         name=u"Motala/Skärstad",
         pos=mapper.to_str(mapper.from_aviation_format("5829.5N01506.2E")),
         elev=338),#TODO: Add real elev
Exemplo n.º 20
0
def osm_airfields_parse():
    nameicao=parse_info()
    f=open("adnames.txt","w")
    for name,icao in sorted(nameicao,key=lambda x:x[0]):        
        f.write("%s: %s\n"%(icao.encode('utf8'),name.encode('utf8')))
    f.close()
    ads=[]
    hits=0
    misses=[]
    
    name2icao=[]
    for name,icao in nameicao:
        name2icao.append((normalize(name),name,icao))
    
    dupecheck=set()    
    
    for lon,lat,name in csv.reader(open("fplan/extract/aerodromes.txt")):
        name=unicode(name,"utf8")
        if not name.strip(): continue
        
        icao=None
        n1=normalize(name)
        if frozenset(n1) in dupecheck:
            continue
        dupecheck.add(frozenset(n1))
        lastquality=0
        lastname=None
        for n2,iname,iicao in name2icao:
            #print repr(n1),"==",repr(n2)
            minlen=min(len(n1),len(n2))
            if minlen>2:
                minlen=minlen-1
            quality=len(n1.intersection(n2))
            if quality>=minlen and quality>lastquality:
                if icao!=None and icao!=iicao:
                    print "For name:",name,"Previous match:,",icao,"New match:",iicao,"Name:",iname,"last name:",lastname,"quality:",quality,"last:",lastquality,"minlen:",minlen
                    #assert icao==None
                icao=iicao
                lastquality=quality
                lastname=iname
        #print "Ap with name:",name
        if icao:
            hits+=1
            icao=icao
        else:
            icao='ZZZZ'
            misses.append(name)
            #print "Missed:",name
        d=dict(
                icao=icao,
                name=name,
                pos=mapper.to_str((float(lat),float(lon))),
                elev=int(gte.get_terrain_elev((float(lat),float(lon))))
                )
            
        if hits%10==0:
            print "Hits: %d, Misses: %d, Perc: %.1f"%(hits,len(misses),100.0*(float(hits)/(float(hits)+len(misses))))
        ads.append(d)
    print "Misses:"
    f=open("missedads.txt","w")        
    for miss in sorted(misses):
        f.write((miss+" - "+repr(normalize(miss))+u"\n").encode('utf8'))
    f.close()    
    f=open("foundads.txt","w")        
    for norm,name,icao in name2icao:
        f.write((name+" - "+repr(norm)+u"\n").encode('utf8'))
    f.close()    
    print "Hits: ",hits
    print "Misses: ",len(misses)
    
    return ads
Exemplo n.º 21
0
def extract_airfields(filtericao=lambda x:True,purge=True):
    #print getxml("/AIP/AD/AD 1/ES_AD_1_1_en.pdf")
    ads=[]
    p=Parser("/AIP/AD/AD 1/ES_AD_1_1_en.pdf")
    points=dict()
    startpage=None
    for pagenr in xrange(p.get_num_pages()):
        page=p.parse_page_to_items(pagenr)
        if page.count("Aerodrome directory"):
            startpage=pagenr
            break
    if startpage==None:
        raise Exception("Couldn't find aerodrome directory in file")
    #print "Startpage: %d"%(startpage,)
    #nochartf=open("nochart.txt","w")
    for pagenr in xrange(startpage,p.get_num_pages()):
        row_y=[]
        page=p.parse_page_to_items(pagenr)
        allines=[x for x in (page.get_lines(page.get_partially_in_rect(0,0,15,100))) if x.strip()]
        for item,next in zip(allines,allines[1:]+[""]):
            #print "item:",item
            
            m=re.match(ur"^\s*[A-ZÅÄÖ]{3,}(?:/.*)?\b.*",item)
            if m:
                #print "Candidate, next is:",next
                if re.match(r"^\s*[A-Z]{4}\b.*",next):
                    #print "Matched:",item
                    #print "y1:",item.y1                    
                    row_y.append(item.y1)
        for y1,y2 in zip(row_y,row_y[1:]+[100.0]):
            #print "Extacting from y-range: %f-%f"%(y1,y2)
            items=list(page.get_partially_in_rect(0,y1-0.25,5.0,y2+0.25,ysort=True))
            if len(items)>=2:
                #print "Extract items",items
                ad=dict(name=unicode(items[0].text).strip(),
                        icao=unicode(items[1].text).strip()                    
                        )
                #print "Icao:",ad['icao']
                assert re.match(r"[A-Z]{4}",ad['icao'])
                if not filtericao(ad): continue
                if len(items)>=3:
                    #print "Coord?:",items[2].text
                    m=re.match(r".*(\d{6}N)\s*(\d{7}E).*",items[2].text)
                    if m:
                        lat,lon=m.groups()
                        ad['pos']=parse_coords(lat,lon)           
                        #print "Items3:",items[3:]   
                        elev=re.findall(r"(\d{1,5})\s*ft"," ".join(t.text for t in items[3:]))
                        #print "Elev:",elev
                        assert len(elev)==1
                        ad['elev']=int(elev[0])                        
                                     
                ads.append(ad)

        
    big_ad=set()        
    for ad in ads:
        if not ad.has_key('pos'):
            big_ad.add(ad['icao'])
            
    for ad in ads:        
        icao=ad['icao']
        if icao in big_ad:            
            if icao in ['ESIB','ESNY','ESCM','ESPE']:
                continue                    
            
            try:
                p=Parser("/AIP/AD/AD 2/%s/ES_AD_2_%s_6_1_en.pdf"%(icao,icao))
            except:
                p=Parser("/AIP/AD/AD 2/%s/ES_AD_2_%s_6-1_en.pdf"%(icao,icao))

            ad['aipvacurl']=p.get_url()
            for pagenr in xrange(p.get_num_pages()):
                page=p.parse_page_to_items(pagenr)
                
                """
                for altline in exitlines:
                    m=re.match(r"(\w+)\s+(\d+N)\s*(\d+E.*)",altline)
                    if not m: continue
                    name,lat,lon=m.groups()
                    try:
                        coord=parse_coords(lat,lon)
                    except Exception:
                        continue
                    points.append(dict(name=name,pos=coord))
                """
                
                for kind in xrange(2):
                    if kind==0:
                        hits=page.get_by_regex(r"H[Oo][Ll][Dd][Ii][Nn][Gg]")
                        kind="holding point"
                    if kind==1:
                        hits=page.get_by_regex(r"[Ee]ntry.*[Ee]xit.*point")                    
                        kind="entry/exit point"
                    if len(hits)==0: continue
                    for holdingheading in hits:

                        items=sorted(page.get_partially_in_rect(holdingheading.x1+2.0,holdingheading.y2+0.1,holdingheading.x1+0.5,100),
                            key=lambda x:x.y1)
                        items=[x for x in items if not x.text.startswith(" ")]
                        #print "Holding items:",items
                        for idx,item in enumerate(items):
                            print "Holding item",item
                            y1=item.y1
                            if idx==len(items)-1:
                                y2=100
                            else:
                                y2=items[idx+1].y1
                            items2=[x for x in page.get_partially_in_rect(item.x1+1,y1+0.3,item.x1+40,y2-0.1) if x.x1>=item.x1-0.25 and x.y1>=y1-0.05 and x.y1<y2-0.05]
                            s=(" ".join(page.get_lines(items2))).strip()
                            print "Holding lines:",repr(page.get_lines(items2))
                            #if s.startswith("ft Left/3"): #Special case for ESOK
                            #    s,=re.match("ft Left/3.*?([A-Z]{4,}.*)",s).groups()
                            #m=re.match("ft Left/\d+.*?([A-Z]{4,}.*)",s)
                            #if m:
                            #    s,=m.groups()
                                
                            if s.startswith("LjUNG"): #Really strange problem with ESCF
                                s=s[0]+"J"+s[2:]
                            if s.lower().startswith("holding"):
                                sl=s.split(" ",1)
                                if len(sl)>1:
                                    s=sl[1]
                            s=s.strip()
                            if kind=="entry/exit point" and s.startswith("HOLDING"):
                                continue #reached HOLDING-part of VAC
                                
                            #Check for other headings
                            #Fixup strange formatting of points in some holding items: (whitespace between coord and 'E')                            
                            s=re.sub(ur"(\d+)\s*(N)\s*(\d+)\s*(E)",lambda x:"".join(x.groups()),s)

                            m=re.match(r"([A-Z]{2,}).*?(\d+N)\s*(\d+E).*",s)
                            if not m:                                
                                m=re.match(r".*?(\d+N)\s*(\d+E).*",s) 
                                if not m:
                                    continue
                                assert m
                                lat,lon=m.groups()
                                #skavsta
                                if icao=="ESKN":
                                    if s.startswith(u"Hold north of T"):
                                        name="NORTH"
                                    elif s.startswith(u"Hold south of B"):
                                        name="SOUTH"                     
                                    else:
                                        assert 0
                                #add more specials here            
                                else:
                                    continue
                            else:
                                name,lat,lon=m.groups()
                            try:
                                coord=parse_coords(lat,lon)
                            except Exception:
                                print "Couldn't parse:",lat,lon
                                continue
                            #print name,lat,lon,mapper.format_lfv(*mapper.from_str(coord))
                            
                            if name.count("REMARK") or len(name)<=2:
                                print "Suspicious name: ",name
                                #sys.exit(1)
                                continue
                            points[icao+' '+name]=dict(name=icao+' '+name,icao=icao,pos=coord,kind=kind)


    #for point in points.items():
    #    print point


    #sys.exit(1)

    def fixhex11(s):
        out=[]
        for c in s:
            i=ord(c)
            if i>=0x20:
                out.append(c)
                continue
            if i in [0x9,0xa,0xd]:
                out.append(c)
                continue
            out.append(' ')
            
        return "".join(out)
        
    for ad in ads:
        icao=ad['icao']
        if icao in big_ad:
            #print "Parsing ",icao
            p=Parser("/AIP/AD/AD 2/%s/ES_AD_2_%s_en.pdf"%(icao,icao),loadhook=fixhex11)
            ad['aiptexturl']=p.get_url()
            firstpage=p.parse_page_to_items(0)
            te="\n".join(firstpage.get_all_lines())                        
            #print te
            coords=re.findall(r"ARP.*(\d{6}N)\s*(\d{7}E)",te)
            if len(coords)>1:
                raise Exception("First page of airport info (%s) does not contain exactly ONE set of coordinates"%(icao,))
            if len(coords)==0:
                print "Couldn't find coords for ",icao
            #print "Coords:",coords
            ad['pos']=parse_coords(*coords[0])

            elev=re.findall(r"Elevation.*?(\d{1,5})\s*ft",te,re.DOTALL)
            if len(elev)>1:
                raise Exception("First page of airport info (%s) does not contain exactly ONE elevation in ft"%(icao,))
            if len(elev)==0:
                print "Couldn't find elev for ",icao                
            ad['elev']=int(elev[0])
            freqs=[]
            found=False
            thrs=[]
            #uprint("-------------------------------------")
            for pagenr in xrange(p.get_num_pages()):
                page=p.parse_page_to_items(pagenr)
                #uprint("Looking on page %d"%(pagenr,))
                if 0: #opening hours are no longer stored in a separate document for any airports. No need to detect which any more (since none are).
                    for item in page.get_by_regex(".*OPERATIONAL HOURS.*"):
                        lines=page.get_lines(page.get_partially_in_rect(0,item.y2+0.1,100,100))
                        for line in lines:
                            things=["ATS","Fuelling","Operating"]
                            if not line.count("AIP SUP"): continue
                            for thing in things:
                                if line.count(thing):
                                    ad['aipsup']=True
                        
                    
                for item in page.get_by_regex(".*\s*RUNWAY\s*PHYSICAL\s*CHARACTERISTICS\s*.*"):
                    #uprint("Physical char on page")
                    lines=page.get_lines(page.get_partially_in_rect(0,item.y2+0.1,100,100))
                    seen_end_rwy_text=False
                    for line,nextline in izip(lines,lines[1:]+[None]):
                        #uprint("MAtching: <%s>"%(line,))
                        if re.match(ur"AD\s+2.13",line): break
                        if line.count("Slope of"): break
                        if line.lower().count("end rwy:"): seen_end_rwy_text=True
                        if line.lower().count("bgn rwy:"): seen_end_rwy_text=True
                        m=re.match(ur".*(\d{6}\.\d+)[\s\(\)\*]*(N).*",line)
                        if not m:continue
                        m2=re.match(ur".*(\d{6,7}\.\d+)\s*[\s\(\)\*]*(E).*",nextline)                            
                        if not m2:continue
                        latd,n=m.groups()
                        lond,e=m2.groups()
                        assert n=="N"
                        assert e=="E"
                        lat=latd+n
                        lon=lond+e
                        rwytxts=page.get_lines(page.get_partially_in_rect(0,line.y1+0.05,12,nextline.y2-0.05))
                        uprint("Rwytxts:",rwytxts)
                        rwy=None
                        for rwytxt in rwytxts:
                            #uprint("lat,lon:%s,%s"%(lat,lon))
                            #uprint("rwytext:",rwytxt)
                            m=re.match(ur"\s*(\d{2}[LRCM]?)\b.*",rwytxt)
                            if m:
                                assert rwy==None
                                rwy=m.groups()[0]
                        if rwy==None and seen_end_rwy_text:
                            continue
                        print "Cur airport:",icao
                        already=False
                        assert rwy!=None
                        seen_end_rwy_text=False
                        for thr in thrs:
                            if thr['thr']==rwy:
                                raise Exception("Same runway twice on airfield:"+icao)
                        thrs.append(dict(pos=mapper.parse_coords(lat,lon),thr=rwy))
            assert len(thrs)>=2
            for pagenr in xrange(0,p.get_num_pages()):
                page=p.parse_page_to_items(pagenr)                                              
                
                matches=page.get_by_regex(r".*ATS\s+COMMUNICATION\s+FACILITIES.*")
                #print "Matches of ATS COMMUNICATION FACILITIES on page %d: %s"%(pagenr,matches)
                if len(matches)>0:
                    commitem=matches[0]
                    curname=None
                    
                    callsign=page.get_by_regex_in_rect(ur"Call\s*sign",0,commitem.y1,100,commitem.y2+8)[0]
                    
                    
                    for idx,item in enumerate(page.get_lines(page.get_partially_in_rect(callsign.x1-0.5,commitem.y1,100,100),fudge=0.3,order_fudge=15)):
                        if item.strip()=="":
                            curname=None
                        if re.match(".*RADIO\s+NAVIGATION\s+AND\s+LANDING\s+AIDS.*",item):
                            break
                        #print "Matching:",item
                        m=re.match(r"(.*?)\s*(\d{3}\.\d{1,3})\s*MHz.*",item)
                        #print "MHZ-match:",m
                        if not m: continue
                        #print "MHZ-match:",m.groups()
                        who,sfreq=m.groups()
                        freq=float(sfreq)
                        if abs(freq-121.5)<1e-4:
                            if who.strip():
                                curname=who
                            continue #Ignore emergency frequency, it is understood
                        if not who.strip():
                            if curname==None: continue
                        else:
                            curname=who
                        freqs.append((curname.strip().rstrip("/"),freq))


            for pagenr in xrange(0,p.get_num_pages()):
                page=p.parse_page_to_items(pagenr)                                              
                                
                matches=page.get_by_regex(r".*ATS\s*AIRSPACE.*")
                #print "Matches of ATS_AIRSPACE on page %d: %s"%(pagenr,matches)
                if len(matches)>0:
                    heading=matches[0]
                    desigitem,=page.get_by_regex("Designation and lateral limits")
                    vertitem,=page.get_by_regex("Vertical limits")
                    airspaceclass,=page.get_by_regex("Airspace classification")
                    
                    lastname=None
                    subspacelines=dict()
                    subspacealts=dict()
                    for idx,item in enumerate(page.get_lines(page.get_partially_in_rect(desigitem.x2+1,desigitem.y1,100,vertitem.y1-1))):
                        
                        if item.count("ATS airspace not established"):
                            assert idx==0
                            break
                            
                        if item.strip()=="": continue
                        m=re.match(r"(.*?)(\d{6}N\s+.*)",item)
                        if m:
                            name,coords=m.groups()                            
                            name=name.strip()
                        else:
                            name=item.strip()
                            coords=None
                        if name:
                            lastname=name
                        if coords:
                            subspacelines.setdefault(lastname,[]).append(coords)
                        assert lastname
                    lastname=None

                    #print "Spaces:",subspacelines
                    #print "ICAO",ad['icao']
                    #altlines=page.get_lines(page.get_partially_in_rect(vertitem.x2+1,vertitem.y1,100,airspaceclass.y1-0.2))
                    
                    #print "Altlines:",altlines
                    subspacealts=dict()
                    subspacekeys=subspacelines.keys()
                        
                    allaltlines=" ".join(page.get_lines(page.get_partially_in_rect(vertitem.x1+0.5,vertitem.y1+0.5,100,airspaceclass.y1-0.2)))
                    single_vertlim=False
                    totalts=list(mapper.parse_all_alts(allaltlines))
                    #print "totalts:",totalts 
                    if len(totalts)==2:
                        single_vertlim=True
                    
                    for subspacename in subspacekeys:
                        ceil=None
                        floor=None
                        subnames=[subspacename]
                        if subspacename.split(" ")[-1].strip() in ["TIA","TIZ","CTR","CTR/TIZ"]:
                            subnames.append(subspacename.split(" ")[-1].strip())
                        #print "Parsing alts for ",subspacename,subnames
                        try:                        
                            for nametry in subnames:
                                if single_vertlim: #there's only one subspace, parse all of vertical limits field for this single one.
                                    items=[vertitem]
                                else:
                                    items=page.get_by_regex_in_rect(nametry,vertitem.x2+1,vertitem.y1,100,airspaceclass.y1-0.2)
                                for item in items: 
                                    alts=[]
                                    for line in page.get_lines(page.get_partially_in_rect(item.x1+0.5,item.y1+0.5,100,airspaceclass.y1-0.2)):
                                        #print "Parsing:",line
                                        line=line.replace(nametry,"").lower().strip()
                                        parsed=list(mapper.parse_all_alts(line))
                                        if len(parsed):
                                            alts.append(mapper.altformat(*parsed[0]))
                                        if len(alts)==2: break
                                    if alts:
                                        #print "alts:",alts
                                        ceil,floor=alts
                                        raise StopIteration
                        except StopIteration:
                            pass
                        assert ceil and floor
                        subspacealts[subspacename]=dict(ceil=ceil,floor=floor)             
                        
                    spaces=[]                                        
                    for spacename in subspacelines.keys():
                        altspacename=spacename
                        #print "Altspacename: %s, subspacesalts: %s"%(altspacename,subspacealts)
                        space=dict(
                            name=spacename,
                            ceil=subspacealts[altspacename]['ceil'],
                            floor=subspacealts[altspacename]['floor'],
                            points=parse_coord_str(" ".join(subspacelines[spacename])),
                            freqs=list(set(freqs))
                            )
                        
                        if True:
                            vs=[]
                            for p in space['points']:
                                x,y=mapper.latlon2merc(mapper.from_str(p),13)
                                vs.append(Vertex(int(x),int(y)))                    
                            p=Polygon(vvector(vs))
                            if p.calc_area()<=30*30:
                                pass#print space
                                pass#print "Area:",p.calc_area()
                            assert p.calc_area()>30*30
                            #print "Area: %f"%(p.calc_area(),)
                        
                        spaces.append(space)
                        #print space
                    ad['spaces']=spaces
                    found=True
                if found:
                    break
            assert found                            
            ad['runways']=rwy_constructor.get_rwys(thrs)
                            
                            
            #Now find any ATS-airspace
    chartblobnames=[]
    for ad in ads:        
        icao=ad['icao']
        if icao in big_ad:          
            parse_landing_chart.help_plc(ad,"/AIP/AD/AD 2/%s/ES_AD_2_%s_2-1_en.pdf"%(icao,icao),
                            icao,ad['pos'],"se",variant="")
            parse_landing_chart.help_plc(ad,"/AIP/AD/AD 2/%s/ES_AD_2_%s_6-1_en.pdf"%(icao,icao),
                            icao,ad['pos'],"se",variant="vac")

            parse_landing_chart.help_plc(ad,"/AIP/AD/AD 2/%s/ES_AD_2_%s_2-3_en.pdf"%(icao,icao),
                            icao,ad['pos'],"se",variant="parking")
            
            
            #aip_text_documents.help_parse_doc(ad,"/AIP/AD/AD 2/%s/ES_AD_2_%s_6_1_en.pdf"%(icao,icao),
            #            icao,"se",title="General Information",category="general")
                                    
            
            aip_text_documents.help_parse_doc(ad,"/AIP/AD/AD 2/%s/ES_AD_2_%s_en.pdf"%(icao,icao),
                        icao,"se",title="General Information",category="general")
            
                  

    
    #if purge:
    #    parse_landing_chart.purge_old(chartblobnames,country="se")        
    
    #sys.exit(1)

    for extra in extra_airfields.extra_airfields:
        if filtericao(extra):
            ads.append(extra)
    print
    print
    for k,v in sorted(points.items()):
        print k,v,mapper.format_lfv(*mapper.from_str(v['pos']))
        
    #print "Num points:",len(points)
    
    origads=list(ads)    
    for flygkartan_id,name,lat,lon,dummy in csv.reader(open("fplan/extract/flygkartan.csv"),delimiter=";"):
        found=None
        lat=float(lat)
        lon=float(lon)
        if type(name)==str:
            name=unicode(name,'utf8')
        mercf=mapper.latlon2merc((lat,lon),13)
        for a in origads:
            merca=mapper.latlon2merc(mapper.from_str(a['pos']),13)
            dist=math.sqrt((merca[0]-mercf[0])**2+(merca[1]-mercf[1])**2)
            if dist<120:
                found=a
                break
        if found:
            found['flygkartan_id']=flygkartan_id
        else:
            d=dict(
                    icao='ZZZZ',
                    name=name,
                    pos=mapper.to_str((lat,lon)),
                    elev=int(get_terrain_elev((lat,lon))),
                    flygkartan_id=flygkartan_id)
            if filtericao(d):
                ads.append(d)
                    
    minor_ad_charts=extra_airfields.minor_ad_charts
        
                    
    for ad in ads:     
        if ad['name'].count(u"Långtora"):            
            ad['pos']=mapper.to_str(mapper.from_aviation_format("5944.83N01708.20E"))
            
        if ad['name'] in minor_ad_charts:
            charturl=minor_ad_charts[ad['name']]
            arp=ad['pos']
            if 'icao' in ad and ad['icao'].upper()!='ZZZZ':
                icao=ad['icao'].upper()
            else:
                icao=ad['fake_icao']
                
            parse_landing_chart.help_plc(ad,charturl,icao,arp,country='raw',variant="landing")
            """
            assert icao!=None
            lc=parse_landing_chart.parse_landing_chart(
                    charturl,
                    icao=icao,
                    arppos=arp,country="raw")
            assert lc
            if lc:
                ad['adcharturl']=lc['url']
                ad['adchart']=lc
            """
            
    #print ads
    for ad in ads:
        print "%s: %s - %s (%s ft) (%s)"%(ad['icao'],ad['name'],ad['pos'],ad['elev'],ad.get('flygkartan_id','inte i flygkartan'))
        for space in ad.get('spaces',[]):
            for freq in space.get('freqs',[]):
                print "   ",freq
        #if 'spaces' in ad:
        #    print "   spaces: %s"%(ad['spaces'],)
        #if 'aiptext' in ad:
        #    print "Aip texts:",ad['aiptext']
        #else:
        #    print "No aiptext"
    print "Points:"
    for point in sorted(points.values(),key=lambda x:x['name']):
        print point
        
    f=codecs.open("extract_airfields.regress.txt","w",'utf8')    
    for ad in ads:
        r=repr(ad)
        d=md5.md5(r).hexdigest()
        f.write("%s - %s - %s\n"%(ad['icao'],ad['name'],d))
    f.close()
    f=codecs.open("extract_airfields.regress-details.txt","w",'utf8')    
    for ad in ads:
        r=repr(ad)
        f.write(u"%s - %s - %s\n"%(ad['icao'],ad['name'],r))
    f.close()
    
    return ads,points.values()
Exemplo n.º 22
0
def fi_parse_ats_rte(tmapolys=[]):
    p = parse.Parser("/ais/eaip/pdf/enr/EF_ENR_3_3_EN.pdf",
                     lambda x: x,
                     country='fi')
    out = []
    for pagenr in xrange(p.get_num_pages()):
        page = p.parse_page_to_items(pagenr)

        def isol_routes():
            cur = None
            accum = []
            for line in page.get_lines(page.get_all_items()):
                uprint("Looking at ", line)
                m = re.match(ur"(^[A-Z]{1,2}\d+)\s+\(.*", line)
                if m and line.x1 < 25:
                    if cur:
                        uprint("Yielding %s: %s because of found name:%s" %
                               (cur, accum, m.groups()))
                        yield cur, accum
                        accum = []
                    cur, = m.groups()
                    continue
                m = re.match(ur"(\d{6}N)\s*(\d{7}E).*", line)
                if m:
                    accum.append((line.y1, line.y2, " ".join(m.groups())))
            if cur:
                uprint("Yielding %s: %s because of end of page" % (cur, accum))
                yield cur, accum
                accum = []

        def getsig(coords, altspecs):
            poss = []
            #print "Coords: <%s>"%(coords,)
            for y1, y2, pos in coords:
                poss.append(pos)
            uprint("poss: <%s>" % (poss, ))
            s = "-".join(poss)
            s2 = "-".join(altspecs)
            return md5.md5(s.encode('utf8') + s2.encode('utf8')).hexdigest()

        def low_routes(routes):
            for routename, coords in routes:
                uprint("Found route: %s, with %s cords" % (routename, coords))
                assert len(coords) >= 2
                y1 = coords[0][0]
                y2 = coords[-1][1]
                foundlow = False
                altspec = []
                for item in page.get_partially_in_rect(0, y1, 100, y2):
                    uprint("Looking for alt for %s in :" % (routename, ),
                           item.text)
                    m = re.match(ur".*FL\s+(\d{2,3})\b(?:\s.*|$)", item.text)
                    if m:
                        fl, = m.groups()
                        uprint("Matched alt:", m.groups())
                        fli = int(fl, 10)
                        if fli < 95:
                            uprint("Foundlow for route %s: %d" %
                                   (routename, fli))
                            foundlow = True
                    altspec.append(item.text)
                if foundlow:
                    yield routename, coords, altspec

        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))

        i1 = isol_routes()
        low1 = low_routes(i1)
        out.extend(list(get_airspaces(low1)))

    out2 = []
    for space in out:
        mypoly = makepoly.poly[space['points']]
        for tmapoly in tmapolys:
            mypoly = shapemerge2d.shape_difference(mypoly, tmapoly)
        t = []
        for mx, my in [(v.get_x(), v.get_y()) for v in mypoly.get_vertices()]:
            t.append(mapper.to_str(mapper.merc2latlon((mx, my), 13)))
        space['points'] = t
    return out2
Exemplo n.º 23
0
def no_obstacles():
    out=[]
    fnames=["/home/anders/saker/avl_fplan_world/norway_obst/20120903pkt.shp",
        "/home/anders/saker/avl_fplan_world/norway_obst/20120903linpkt.shp",
        "/home/anders/saker/avl_fplan_world/norway_obst/20120903lin.shp"]

    for fname in fnames:
        r=shapefile.Reader(fname)
        utm = Proj(proj='utm',zone=33,ellps='WGS84')
        wgs84 = Proj(init='epsg:4326')
    
        untrans=set()
        osts={unicode('Vindm\xef\xbf\xbdlle','utf8'):'Wind turbine',
              u'T\ufffdrn':'Tower',
              u'Mast TELE':'Mast',
              u'Annet':'Antenna',    
            u'Heisekran':'Crane',
            u'Tank':'Tank',
            u'Fyr':'Lighthouse',
            u'Bru':'Bridge',
            u'Mast EL':'Mast',
            u'Pipe':'Chimney',
            u'Oljeinstallasjon':'Oil Platform',
            u'Mast/stolpe veilys':'Mast',
            u'Bygning':'Building',
            u'Hoppbakke':'Ski-jump',
            u'Silo':'Silo',
            u'Skiheis':'Ski lift',
            u'Kraftlinespenn':'Power lines', 
           u'LuftledningLH':'Power lines', 
           u'Gondolheis':'Ski lift', 
           u'Taubane':'Aerial tramway', 
           u'L\ufffdypestreng':'Power lines'
            }
        """
    "Wind turbine",
    "Mast",
    "Cathedral",
    "Pylon",
    "Building",
    "Platform",
    "Chimney",
    "Mine hoist",
    "Bridge pylon",
    "Crane",
    "W Tower",
    "Church",
    "Silo",
    "City Hall",
    "Gasometer",
    "Tower",
    "Bridge pylon, 60 per minute"]
    """
        columns=[x[0] for x in r.fields]

        for rec in r.shapeRecords():
            #print "col:",columns
            #print "rec:",rec.record
            d=dict(zip(columns[1:],rec.record))
            def fixname(n):
                n=n.strip()
                if n=="":
                    n="Unknown"
                return n
            nortype=unicode(d['hindertype'],'utf8')
            engtype=osts.get(nortype,nortype)
            if not nortype in osts:
                untrans.add(nortype)
            base=dict(
                      name=fixname(unicode(d['lfh_navn'],'utf8')),
                      height=int(d['hoeydeover']/0.3048),
                      elev=int(d['totalhoeyd']/0.3048),
                      lighting=unicode(d['lyssetting'],'utf8'),
                      kind=engtype,                      
                      date=datetime(2012,9,1))
            if base['height']<300:
                continue
            for point in rec.shape.points:
                x,y=point
                lon,lat=transform(utm,wgs84,x,y)
                #print "Input: ",d,x,y,"output:",lat,lon
                cur=copy(base)
                cur['pos']=mapper.to_str((lat,lon))
                out.append(cur)
            #break
        print "missing translations",untrans
    return out
Exemplo n.º 24
0
def fi_parse_ats_rte(tmapolys=[]):
    p=parse.Parser("/ais/eaip/pdf/enr/EF_ENR_3_3_EN.pdf",lambda x: x,country='fi')
    out=[]
    for pagenr in xrange(p.get_num_pages()):        
        page=p.parse_page_to_items(pagenr)
        
        def isol_routes():
            cur=None
            accum=[]
            for line in page.get_lines(page.get_all_items()):
                uprint("Looking at ",line)
                m=re.match(ur"(^[A-Z]{1,2}\d+)\s+\(.*",line)
                if m and line.x1<25:
                    if cur:
                        uprint("Yielding %s: %s because of found name:%s"%(cur,accum,m.groups()))
                        yield cur,accum
                        accum=[]
                    cur,=m.groups()
                    continue
                m=re.match(ur"(\d{6}N)\s*(\d{7}E).*",line)
                if m:
                    accum.append((line.y1,line.y2," ".join(m.groups())))
            if cur:
                uprint("Yielding %s: %s because of end of page"%(cur,accum))
                yield cur,accum
                accum=[]
        def getsig(coords,altspecs):
            poss=[]
            #print "Coords: <%s>"%(coords,)
            for y1,y2,pos in coords:
                poss.append(pos)
            uprint("poss: <%s>"%(poss,))
            s="-".join(poss)
            s2="-".join(altspecs)
            return md5.md5(s.encode('utf8')+s2.encode('utf8')).hexdigest()
        def low_routes(routes):
            for routename,coords in routes:
                uprint("Found route: %s, with %s cords"%(routename,coords))
                assert len(coords)>=2
                y1=coords[0][0]
                y2=coords[-1][1]
                foundlow=False
                altspec=[]
                for item in page.get_partially_in_rect(0,y1,100,y2):
                    uprint("Looking for alt for %s in :"%(routename,),item.text)
                    m=re.match(ur".*FL\s+(\d{2,3})\b(?:\s.*|$)",item.text)
                    if m:
                        fl,=m.groups()
                        uprint("Matched alt:",m.groups())
                        fli=int(fl,10)
                        if fli<95:
                            uprint("Foundlow for route %s: %d"%(routename,fli))
                            foundlow=True
                    altspec.append(item.text)
                if foundlow: 
                    yield routename,coords,altspec

        
        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))
        i1=isol_routes()
        low1=low_routes(i1)
        out.extend(list(get_airspaces(low1)))

    out2=[]
    for space in out:
        mypoly=makepoly.poly[space['points']]
        for tmapoly in tmapolys:
            mypoly=shapemerge2d.shape_difference(mypoly,tmapoly)
        t=[]
        for mx,my in [(v.get_x(),v.get_y()) for v in  mypoly.get_vertices()]:
            t.append(mapper.to_str(mapper.merc2latlon((mx,my),13)))
        space['points']=t
    return out2