def test_calc_area(): polya=Polygon(vvector([ Vertex(0,0),Vertex(1,0),Vertex(1,1),Vertex(0,1)])) assert abs(polya.calc_area()-1)<1e-5 polyb=Polygon(vvector([ Vertex(0,0),Vertex(1,0),Vertex(2,1),Vertex(0,1)])) assert abs(polyb.calc_area()-1.5)<1e-5 polyc=Polygon(vvector([ Vertex(0,0),Vertex(2,0),Vertex(2,2),Vertex(1,0),Vertex(0,2)])) assert abs(polyc.calc_area()-2)<1e-5
def cleanup_poly(latlonpoints, name="?"): for minstep in [0, 10, 100, 1000, 10000, 100000]: mercpoints = [] lastmerc = None for latlon in latlonpoints: merc = mapper.latlon2merc(latlon, 13) if lastmerc != None: dist = math.sqrt( sum([(lastmerc[i] - merc[i])**2 for i in xrange(2)])) if dist < minstep: continue if merc == lastmerc: continue lastmerc = merc mercpoints.append(Vertex(int(merc[0]), int(merc[1]))) if len(mercpoints) < 50: break if len(mercpoints) <= 2: return None if mercpoints[0] == mercpoints[-1]: del mercpoints[-1] if len(mercpoints) <= 2: return None poly = Polygon(vvector(mercpoints)) if len(mercpoints) == 4: swapped = [mercpoints[1], mercpoints[0]] + mercpoints[2:] swappedpoly = Polygon(vvector(swapped)) #print "Found 4-corner area: ",name," areas:",swappedpoly.calc_area(),poly.calc_area() if abs(swappedpoly.calc_area()) > abs(1.1 * poly.calc_area()): print "Untwisting an area", name mercpoints = swapped poly = swappedpoly backtomerc = [ mapper.merc2latlon((m.get_x(), m.get_y()), 13) for m in mercpoints ] if poly.is_ccw(): return backtomerc else: #print "Reversed "+latlonpoints return reversed(backtomerc)
def cleanup_poly(latlonpoints,name="?"): for minstep in [0,10,100,1000,10000,100000]: mercpoints=[] lastmerc=None for latlon in latlonpoints: merc=mapper.latlon2merc(latlon,13) if lastmerc!=None: dist=math.sqrt(sum([(lastmerc[i]-merc[i])**2 for i in xrange(2)])) if dist<minstep: continue if merc==lastmerc: continue lastmerc=merc mercpoints.append(Vertex(int(merc[0]),int(merc[1]))) if len(mercpoints)<50: break if len(mercpoints)<=2: return None if mercpoints[0]==mercpoints[-1]: del mercpoints[-1] if len(mercpoints)<=2: return None poly=Polygon(vvector(mercpoints)) if len(mercpoints)==4: swapped=[mercpoints[1],mercpoints[0]]+mercpoints[2:] swappedpoly=Polygon(vvector(swapped)) #print "Found 4-corner area: ",name," areas:",swappedpoly.calc_area(),poly.calc_area() if abs(swappedpoly.calc_area())>abs(1.1*poly.calc_area()): print "Untwisting an area",name mercpoints=swapped poly=swappedpoly backtomerc=[mapper.merc2latlon((m.get_x(),m.get_y()),13) for m in mercpoints] if poly.is_ccw(): return backtomerc else: #print "Reversed "+latlonpoints return reversed(backtomerc)
def check_area(self,nr2tri): if len(self.triangles)==0: return totarea=0.0 for trinr in self.triangles: tri=nr2tri[trinr] coords=[] for v in tri.vobjs: print "Pos: %s"%((int(v.merc[0]),int(v.merc[1])),) coords.append(pyshapemerge2d.Vertex(int(v.merc[0]),int(v.merc[1]))) poly=Polygon(vvector(coords)) assert not poly.is_ccw() area=-poly.calc_area() print "Tri:%s area = %s"%([x.nr for x in tri.vobjs],area) totarea+=area print "Area should be: %s (since size = %d)"%(self.size*self.size,self.size) print "Area is: %s"%(totarea) assert abs(totarea-(self.size*self.size))<10.0*10.0
pa['ceiling'] = ceiling if mapper.parse_elev(floor) >= 9500: continue #uprint("Arealines:\n================\n%s\n============\n"%(arealines[:last_coord_idx])) #print pa areacoords = " ".join(arealines[:last_coord_idx]) pa['points'] = parse_coord_str(areacoords) vs = [] for p in pa['points']: #print "from_str:",repr(p) 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 pa #print "Area:",p.calc_area() assert p.calc_area() > 30 * 30 #print "Area: %f"%(p.calc_area(),) #print "Point-counts:",len(pa['points']) for p in pa['points']: assert p.count(",") == 1 pa['type'] = kind for thirdcol in thirdcols: if thirdcol in d: atc = d[thirdcol] break else: raise Exception("missing thirdcol") #print "ATc: <%s>"%(repr(atc),)
def parse_page(parser,pagenr,kind="TMA",last_sector=dict()): if kind=="TMA": thirdcols=["ATC unit","AFIS unit"] elif kind=="sector": thirdcols=["FREQ"] elif kind=="R": thirdcols=["Remarks (nature of hazard,"] else: raise Exception("Bad kind") page=parser.parse_page_to_items(pagenr) items=page.items #print "Items:",pitems #print "Possible Areas:" headings=[] for item in items: if item.text==None: continue item.text=item.text.strip() if item.text=="": continue if item.text=="Name": continue if item.y1<25 and item.text in (["Lateral limits","Vertical limits"]+thirdcols): headings.append(item) headings.sort(key=lambda x:x.x1) #print "found candidates:",zone_candidates if len(headings)==0: return [] avg_heading_y=sum(h.y1 for h in headings)/float(len(headings)) uprint("Found headings:",headings) zone_candidates=[] for item in items: if item.text==None or item.text.strip()=="": continue if item.text.strip().startswith("AMDT"): continue if item.text.strip().startswith("The LFV Group"): continue if re.match(ur"\s*LFV\s*AIRAC\s*AMDT\s*\d+/\d+\s*",item.text): continue if item.text.strip()=="LFV": continue if item.text.count('Terminal Information Areas'): continue if item.text.strip().startswith("AIRAC"): continue if kind=="R" and not is_r_or_danger_area_name(item.text.strip()): continue if item.y1>avg_heading_y+1 and item.x1<12 and not item.text in ["Name",'None',"LFV"]: if item.text.count("Established") or item.text.count(u'TROLLHÄTTAN TWR') or item.text.count(u'and/or SÅTENÄS') or item.text.count(u'TWR/TMC') or item.text.strip().endswith("TWR") or item.text.strip().endswith("TWR."): continue if item.text.count("operational hours") or item.text.count("See AIP DENMARK"): continue if item.text.count("hours of"): continue if item.text.count("Upper limit"): continue if item.text.count("that part") or item.text.count("coincides"): continue if item.text.count(u'Danger area EK D395 and') or item.text.count(u'D396 are situated within') or item.text.strip()=="TMA": continue if item.text.count(u'ÖSTGÖTA TMC is closed') or item.text.count(u'and SKAVSTA TWR is') or item.text.strip()=='open.': continue if item.text.count("SAT 0530"): continue if item.text.strip()=='OPS': continue if item.text.strip()==u'ÖSTGÖTA TMC:': continue if item.text.count(u'is open') or item.text.count('is closed'): continue if item.text.count('MON-FRI') or item.text.count('2150'): continue lines2=page.get_lines(page.get_partially_in_rect(12,item.y1+0.2,40,item.y2-0.2)) if len(lines2): zone_candidates.append(item) uprint("Found cands:",zone_candidates) zone_candidates.sort(key=lambda x:x.y1) for zone in zone_candidates: #uprint("Zone:",zone) #assert not zone.text.count("AOR") assert not zone.text.count("FIR") uprint("Headings:",headings) print "Pagenr:",pagenr assert len(headings)==3 ret=[] for i in xrange(len(zone_candidates)): d=dict() cand=zone_candidates[i] if i<len(zone_candidates)-1: nextcand=zone_candidates[i+1] else: nextcand=None y1=cand.y1-0.25 y2=100 if nextcand: y2=nextcand.y1-0.75 for j in xrange(len(headings)): head=headings[j] if j<len(headings)-1: nexthead=headings[j+1] else: nexthead=None x1=head.x1 x2=head.x2 if j==len(headings)-1: x1=headings[j-1].x2+3 x2=100 lines=page.get_lines(page.get_partially_in_rect(x1,y1,x2,y2,xsort=True,ysort=True)) #print ("Parsed %s y,%d-%d, %s: <%s>\n\n"%(cand.text,y1,y2,head.text,lines)).encode('utf8') d[head.text]=lines if kind=="R": if y2==100: y2=y1+3 d['name']=" ".join(x.strip() for x in filter_head_foot(page.get_lines(page.get_partially_in_rect(0,y1,10,y2,xsort=True,ysort=True)))) else: d['name']=cand.text.strip() ret.append(d) allow_head=2 print "Doing fixups--------------------------------------------------" tret=[] for x in ret: #print "Fixing up",x,"allow:",allow_head area="".join(x['Lateral limits']).strip() if allow_head==2 and area!="" and x['name'].strip()!="": allow_head=1 if allow_head!=1: if len(tret): tret[-1]['Lateral limits']+=x['Lateral limits'] tret[-1]['Vertical limits']+=x['Vertical limits'] else: tret.append(x) if allow_head==1: allow_head=0 if not area.endswith('-') and area!="": allow_head=2 #print " Fixed up up",x ret=tret for line in ret: print "Fixed:",line['name']," = ",line['Lateral limits'],line['Vertical limits'] out=[] for d in ret: pa=dict() curname=d['name'] if curname.count(u'Förteckning över'): continue print "D:",d arealines=[l for l in d['Lateral limits'] if l.strip()!=""] last_coord_idx=None #uprint("D:<%s> (area:%s)"%(d,arealines)) if 'FREQ' in d: freqs=[("SWEDEN CONTROL",float(x)) for x in re.findall(r"\d{3}\.\d{3}","\n".join(d['FREQ']))] #print "Parsed freqs:",freqs if freqs: last_sector['freqs']=freqs if kind=='sector': m=re.match(r"ES[A-Z]{2}\s*ACC\s*sector\s*([0-9a-zA-Z]*)",d['name']) if m: last_sector['major']=d['name'] last_sector['majorsector'],=m.groups() if len(arealines)==0: last_sector['name']=d['name'] continue if d['name'].count("Control Area and Upper Control Area"): continue if d['name'].count("SUECIA CTA"): continue if d['name'].count("SUECIA UTA"): continue m=re.match(r"([0-9a-zA-Z]*)(:.*)",d['name']) if m and 'majorsector' in last_sector: sectorname,sub=m.groups() if sectorname==last_sector['majorsector']: d['name']=last_sector['major']+sub #uprint("Fixed up name: ",d['name']) #print "Arealines:",arealines assert len(arealines) if arealines[0].strip()=="Danger area EK D395 and D396 are": arealines=arealines[1:] if arealines[0].strip()=="situated within TMA": arealines=arealines[1:] if arealines==u'Förteckning över CTA / Lists of CTA' or arealines=='Lateral limits': continue for idx in xrange(len(arealines)): if arealines[idx].lower().startswith("established"): last_coord_idx=idx pa['established']=" ".join(l for l in arealines[idx:]) break if arealines[idx].lower().startswith("danger area"): last_coord_idx=idx break if arealines[idx].strip()=="LFV": last_coord_idx=idx break if last_coord_idx==None: last_coord_idx=len(arealines) #uprint("ARealines:",arealines) #uprint("Last coord:",arealines[last_coord_idx-1]) if len(arealines)>last_coord_idx: if arealines[last_coord_idx-1:last_coord_idx+1]==[u'571324N 0161129E -', u'Established during operational hours of']: arealines[last_coord_idx-1]=arealines[last_coord_idx-1].strip("-") #uprint("Last fixed:",arealines[last_coord_idx-1]) assert not arealines[last_coord_idx-1].strip().endswith("-") #for idx in xrange(last_coord_idx-1): # print "arealine: <%s>"%(arealines[idx].strip(),) # assert arealines[idx].strip().endswith("-") or arealines[idx].strip().endswith("to") vertlim=u" ".join(d['Vertical limits']) if vertlim.strip()=="": #print "Object with no vertical limits: %s"%(repr(d['name']),) continue if d['name']=='Control Area': continue uprint("Vertlim: ",vertlim) heightst=re.findall(r"(FL\s*\d{3})|(\d+\s*ft\s*(?:\s*/\s*\d+\s*.\s*GND)?(?:\s*GND)?)|(GND)|(UNL)",vertlim) uprint("Height candidates:",heightst) heights=[] for fl,ht,gnd,unl in heightst: if fl: heights.append(fl) if ht: heights.append(ht.strip()) if gnd: heights.append(gnd.strip()) if unl: heights.append(unl.strip()) uprint("heights for ",d['name'],":",repr(heights)) if len(heights)==0 and d['name']==u'GÖTEBORG TMA': heights=['GND','FL95'] if len(heights)==1 and d['name']==u'Göteborg TMA': heights=['4500','FL95'] assert len(heights)==2 ceiling=heights[0].strip() floor=heights[1].strip() pa['name']=d['name'] pa['floor']=floor pa['ceiling']=ceiling if mapper.parse_elev(floor)>=9500: continue #uprint("Arealines:\n================\n%s\n============\n"%(arealines[:last_coord_idx])) #print pa areacoords=" ".join(arealines[:last_coord_idx]) pa['points']=parse_coord_str(areacoords) vs=[] for p in pa['points']: #print "from_str:",repr(p) 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 pa #print "Area:",p.calc_area() assert p.calc_area()>30*30 #print "Area: %f"%(p.calc_area(),) #print "Point-counts:",len(pa['points']) for p in pa['points']: assert p.count(",")==1 pa['type']=kind for thirdcol in thirdcols: if thirdcol in d: atc=d[thirdcol] break else: raise Exception("missing thirdcol") #print "ATc: <%s>"%(repr(atc),) freqs=[(y,float(x)) for x,y in re.findall(r"(\d{3}\.\d{3})\s*MHz\n(.*)","\n".join(atc))] if not freqs: freqs=last_sector.get('freqs',[]) #print repr(freqs) pa['freqs']=freqs #uprint("Cleaning up ",pa['name']) for cleaned in clean_up_polygon(list(pa['points'])): d=dict(pa) #print "cleaned",cleaned for i,tup in enumerate(cleaned): assert type(tup)==str latlon=mapper.from_str(tup) lat,lon=latlon assert lat>=-85 and lat<=85 d['points']=cleaned #uprint("cleaned:",pa['name'],len(cleaned),cleaned) #print "name:",d['name'] #print "cleaned points:",d['points'] #print "from:",areacoords #raise Exception() out.append(d) #if pa['name'].lower().count("esrange"): # print "Exit esrange" # sys.exit(1) return out