Пример #1
0
 def get_worklist(self):
     worklist=[]
     for ad in sorted(ec.get_airfields(),key=lambda x:x['name']):
         print "Airfield:",ad
         if not 'adcharts' in ad: continue
         for adchart in ad['adcharts'].values():
                                 
             projurl=h.url_for(controller='airportproj',action="show",ad=ad['name'],checksum=adchart['checksum'])
             found=False
             for proj in meta.Session.query(AirportProjection).filter(sa.and_(
                     AirportProjection.user==session['user'],
                     AirportProjection.airport==ad['name'])).order_by(AirportProjection.updated).all():
                 current=(proj.mapchecksum==str(adchart['checksum']))
                 date=proj.updated
                 airport=proj.airport
                 marks=meta.Session.query(AirportMarker).filter(sa.and_(
                     AirportMarker.user==session['user'],
                     AirportMarker.airport==ad['name'])).all()
                 
                 if current:
                     if len(proj.matrix)==0 or all([x==0 for x in proj.matrix]):
                         needwork=True
                     else:
                         needwork=False
                     worklist.append(dict(current=current,updated=date,airport=airport,url=projurl,marks=marks,needwork=needwork,variant=adchart['variant'],cksum=str(adchart['checksum'])))
                     found=True
             if not found:
                 worklist.append(dict(current=False,updated=None,airport=ad['name'],url=projurl,marks=[],needwork=True,variant=adchart['variant'],cksum=str(adchart['checksum'])))
     return worklist
Пример #2
0
def get_pos_elev(latlon):
    for airf in cache.get_airfields():
        #print "Considering:",airf
        apos=mapper.from_str(airf['pos'])
        dx=apos[0]-latlon[0]
        dy=apos[1]-latlon[1]
        if abs(dx)+abs(dy)<0.25*1.0/60.0 and 'elev' in airf:
            return airf['elev']
    return get_terrain_elev(latlon)
Пример #3
0
    def search(self):
        searchstr=request.params.get('search','')
        ordi=int(request.params.get('ordinal',0))
        #print "searching:",searchstr,ordi
        #time.sleep(1.5*f.random())
        latlon_match=re.match(r"(\d+)\.(\d+)([NS])(\d+)\.(\d+)([EW])",searchstr)
        if latlon_match:
            latdeg,latdec,ns,londeg,londec,ew=latlon_match.groups()
            lat=float(latdeg)+float("0."+latdec)
            lon=float(londeg)+float("0."+londec)
            if ns in ['S','s']:
                lat=-lat
            if ew in ['W','w']:
                lon=-lon
            return json.dumps(dict(ordinal=ordi,hits=[['Unknown Waypoint',[lat,lon],'Unknown Waypoint']]))                

        dec_match=re.match(r"\s*(\d+\.\d+)\s*,\s*(\d+\.\d+)\s*",searchstr)
        if dec_match:
            latdec,londec=dec_match.groups()
            lat=float(latdec)
            lon=float(londec)
            return json.dumps(dict(ordinal=ordi,hits=[['Unknown Waypoint',[lat,lon],'Unknown Waypoint']]))                

        #print "Searching for ",searchstr
        searchstr=strip_accents(searchstr).lower()
        apoints=[]
        for airp in get_airfields():
            if strip_accents(airp['name']).lower().count(searchstr) or \
                airp['icao'].lower().count(searchstr):
                d=dict(airp)
                d['kind']='airport'
                apoints.append(d)  
        spoints=[]        
        for sigpoint in get_sig_points():
            if strip_accents(sigpoint['name']).lower().count(searchstr):
                spoints.append(sigpoint)
        def namekey(x):
            return x['name']
        points=list(sorted(apoints,key=namekey))
        points.extend(sorted(spoints,key=namekey))
        if len(points)==0:
            return ""
        #points.sort(key=lambda x:x['name'])
        def extract_name(x):
            if 'kind' in x:
                return "%s (%s)"%(x['name'],x['kind'])
            return x.get('name','unknown item')
        
        hits=[[extract_name(x),mapper.from_str(x['pos']),x.get('name','unknown item')] for x in points[:15]]
        ret=json.dumps(dict(ordinal=ordi,hits=hits))
        #print "returning json:",ret
        return ret
Пример #4
0
 def load(self):
     name = request.params['name']
     #print "Loading",repr(name)
     ret = json.dumps(dict(runways=[]))
     for ac in ec.get_airfields():
         if not filter(ac): continue
         if ac['name'] == name:
             physical = []
             if 'runways' in ac:
                 ret = self.load_ad_json(ac)
                 break
     response.headers['Content-Type'] = 'application/json'
     return ret
Пример #5
0
 def load(self):
     name=request.params['name']
     #print "Loading",repr(name)
     ret=json.dumps(dict(runways=[]))
     for ac in ec.get_airfields():
         if not filter(ac): continue
         if ac['name']==name:
             physical=[]
             if 'runways' in ac:
                 ret=self.load_ad_json(ac)
                 break                                
     response.headers['Content-Type'] = 'application/json'
     return ret
Пример #6
0
    def get_worklist(self):
        worklist = []
        for ad in sorted(ec.get_airfields(), key=lambda x: x['name']):
            print "Airfield:", ad
            if not 'adcharts' in ad: continue
            for adchart in ad['adcharts'].values():

                projurl = h.url_for(controller='airportproj',
                                    action="show",
                                    ad=ad['name'],
                                    checksum=adchart['checksum'])
                found = False
                for proj in meta.Session.query(AirportProjection).filter(
                        sa.and_(
                            AirportProjection.user == session['user'],
                            AirportProjection.airport == ad['name'])).order_by(
                                AirportProjection.updated).all():
                    current = (proj.mapchecksum == str(adchart['checksum']))
                    date = proj.updated
                    airport = proj.airport
                    marks = meta.Session.query(AirportMarker).filter(
                        sa.and_(AirportMarker.user == session['user'],
                                AirportMarker.airport == ad['name'])).all()

                    if current:
                        if len(proj.matrix) == 0 or all(
                            [x == 0 for x in proj.matrix]):
                            needwork = True
                        else:
                            needwork = False
                        worklist.append(
                            dict(current=current,
                                 updated=date,
                                 airport=airport,
                                 url=projurl,
                                 marks=marks,
                                 needwork=needwork,
                                 variant=adchart['variant'],
                                 cksum=str(adchart['checksum'])))
                        found = True
                if not found:
                    worklist.append(
                        dict(current=False,
                             updated=None,
                             airport=ad['name'],
                             url=projurl,
                             marks=[],
                             needwork=True,
                             variant=adchart['variant'],
                             cksum=str(adchart['checksum'])))
        return worklist
Пример #7
0
    def search(self):
        print "Search called:", request.params

        term = strip_accents(request.params['term']).lower()
        if len(term) < 3:
            return json.dumps([])
        response.headers['Content-Type'] = 'application/json'

        hits = []
        for ac in ec.get_airfields():
            if not filter(ac): continue
            if (strip_accents(ac['name']).lower().count(term)):
                hits.append(ac['name'])
        hits.sort()
        return json.dumps(hits[:10])
Пример #8
0
 def search(self):
     print "Search called:",request.params
     
     term=strip_accents(request.params['term']).lower()
     if len(term)<3:
         return json.dumps([])
     response.headers['Content-Type'] = 'application/json'
     
     hits=[]
     for ac in ec.get_airfields():
         if not filter(ac): continue
         if (strip_accents(ac['name']).lower().count(term)):
             hits.append(ac['name'])
     hits.sort()
     return json.dumps(hits[:10])
Пример #9
0
 def invent_matrix(self,cksum,variant):
     print "Variant:",variant
     for ad in ec.get_airfields():
         if not 'adcharts' in ad: continue
         dbb=False
         for adchart in ad['adcharts'].values():
             if adchart['checksum']==cksum:
                 lat,lon=mapper.from_str(ad['pos'])
                 w,h=adchart['render_width'],adchart['render_height']
                 print "adpos:",ad['pos'],lat,lon
                 dbb=True
                 break
         if dbb:break
     else:
         raise Exception("Can't find this chart in aipdata")
     
   
     
     
     if variant.lower().count('vac'):
         mercsizex=w
         mercsizey=h
         scale=7
     else:
         mercsizex=w
         mercsizey=h
         scale=1
     
     print "lat,lon",lat,lon
     m1=mapper.latlon2merc((lat,lon),13)
     print "corner merc",m1
     ns=[]
     for offx,offy in [(0,0),
                       (mercsizex,0),
                       (0,mercsizey),
                       (mercsizex,mercsizey)]:
         merc2=(m1[0]+(offx-mercsizex/2)*scale,m1[1]+(offy-mercsizey/2)*scale)
         n=AirportMarker()
         n.latitude,n.longitude=mapper.merc2latlon(merc2,13)
         n.x,n.y=(offx,offy)
         ns.append(n)
     error,A,T=customproj.solve(ns)
     matrix=list(A)+list(T)            
     print "Fake projection:",matrix
     return matrix
Пример #10
0
    def invent_matrix(self, cksum, variant):
        print "Variant:", variant
        for ad in ec.get_airfields():
            if not 'adcharts' in ad: continue
            dbb = False
            for adchart in ad['adcharts'].values():
                if adchart['checksum'] == cksum:
                    lat, lon = mapper.from_str(ad['pos'])
                    w, h = adchart['render_width'], adchart['render_height']
                    print "adpos:", ad['pos'], lat, lon
                    dbb = True
                    break
            if dbb: break
        else:
            raise Exception("Can't find this chart in aipdata")

        if variant.lower().count('vac'):
            mercsizex = w
            mercsizey = h
            scale = 7
        else:
            mercsizex = w
            mercsizey = h
            scale = 1

        print "lat,lon", lat, lon
        m1 = mapper.latlon2merc((lat, lon), 13)
        print "corner merc", m1
        ns = []
        for offx, offy in [(0, 0), (mercsizex, 0), (0, mercsizey),
                           (mercsizex, mercsizey)]:
            merc2 = (m1[0] + (offx - mercsizex / 2) * scale,
                     m1[1] + (offy - mercsizey / 2) * scale)
            n = AirportMarker()
            n.latitude, n.longitude = mapper.merc2latlon(merc2, 13)
            n.x, n.y = (offx, offy)
            ns.append(n)
        error, A, T = customproj.solve(ns)
        matrix = list(A) + list(T)
        print "Fake projection:", matrix
        return matrix
Пример #11
0
    def search(self):
        searchstr = request.params.get('search', '')
        ordi = int(request.params.get('ordinal', 0))
        #print "searching:",searchstr,ordi
        #time.sleep(1.5*f.random())
        latlon_match = re.match(r"(\d+)\.(\d+)([NS])(\d+)\.(\d+)([EW])",
                                searchstr)
        if latlon_match:
            latdeg, latdec, ns, londeg, londec, ew = latlon_match.groups()
            lat = float(latdeg) + float("0." + latdec)
            lon = float(londeg) + float("0." + londec)
            if ns in ['S', 's']:
                lat = -lat
            if ew in ['W', 'w']:
                lon = -lon
            return json.dumps(
                dict(
                    ordinal=ordi,
                    hits=[['Unknown Waypoint', [lat, lon],
                           'Unknown Waypoint']]))

        dec_match = re.match(r"\s*(\d+\.\d+)\s*,\s*(\d+\.\d+)\s*", searchstr)
        if dec_match:
            latdec, londec = dec_match.groups()
            lat = float(latdec)
            lon = float(londec)
            return json.dumps(
                dict(
                    ordinal=ordi,
                    hits=[['Unknown Waypoint', [lat, lon],
                           'Unknown Waypoint']]))

        #print "Searching for ",searchstr
        searchstr = strip_accents(searchstr).lower()
        apoints = []
        for airp in get_airfields():
            if strip_accents(airp['name']).lower().count(searchstr) or \
                airp['icao'].lower().count(searchstr):
                d = dict(airp)
                d['kind'] = 'airport'
                apoints.append(d)
        spoints = []
        for sigpoint in get_sig_points():
            if strip_accents(sigpoint['name']).lower().count(searchstr):
                spoints.append(sigpoint)

        def namekey(x):
            return x['name']

        points = list(sorted(apoints, key=namekey))
        points.extend(sorted(spoints, key=namekey))
        if len(points) == 0:
            return ""
        #points.sort(key=lambda x:x['name'])
        def extract_name(x):
            if 'kind' in x:
                return "%s (%s)" % (x['name'], x['kind'])
            return x.get('name', 'unknown item')

        hits = [[
            extract_name(x),
            mapper.from_str(x['pos']),
            x.get('name', 'unknown item')
        ] for x in points[:15]]
        ret = json.dumps(dict(ordinal=ordi, hits=hits))
        #print "returning json:",ret
        return ret
Пример #12
0
    def save(self):
        print request.params

        ad = request.params['ad']
        chartobj = None
        mapchecksum = request.params['mapchecksum']
        for adobj in ec.get_airfields():
            if adobj['name'] == ad:
                bb = False
                for adchart in adobj['adcharts'].values():
                    if adchart['checksum'] == mapchecksum:
                        chartobj = adchart
                        bb = True
                        break
                if bb: break
        else:
            self.error("No such airport" + ad)
        marks = dict()
        for param, val in request.params.items():
            if param in [
                    "save", "ad", 'mapchecksum', 'scroll_x', 'scroll_y',
                    'maptype', 'scale', 'north'
            ]:
                continue
            if param.startswith("del"):
                continue
            if param.startswith("set_"):
                x, y = [int(v) for v in param.split("_")[1:]]
                session['curadmarker'] = (x, y)
                session.save()
                continue
            if param == "add":
                xs = meta.Session.query(AirportMarker.x).filter(
                    sa.and_(AirportMarker.user == session['user'],
                            AirportMarker.airport == ad)).all()
                if xs:
                    maxx = max(xs)[0] + 1
                else:
                    maxx = 0
                marks[(maxx, 0)] = dict(latitude=None,
                                        longitude=None,
                                        x=maxx,
                                        y=0)
                session['curadmarker'] = (maxx, 0)
                session.save()
                continue

            sx, sy, attrib = re.match(ur"mark_(\d+)_(\d+)_(\w*)",
                                      param).groups()
            x = int(sx)
            y = int(sy)
            marks.setdefault((x, y), dict())[attrib] = val

        thresholds = dict()
        for rwy in adobj.get('runways', []):
            ends = rwy['ends']
            for end in ends:
                thresholds[end['thr']] = mapper.from_str(end['pos'])

        for param, val in request.params.items():
            if param.startswith("del_"):
                x, y = [int(v) for v in param.split("_")[1:]]
                marks.pop((x, y))
                continue

        meta.Session.query(AirportMarker).filter(
            sa.and_(AirportMarker.user == session['user'],
                    AirportMarker.airport == ad)).delete()
        ms = []
        arppos = mapper.from_str(adobj['pos'])

        for (x, y), val in marks.items():
            m = AirportMarker()
            m.user = session['user']
            m.airport = ad
            m.mapchecksum = str(mapchecksum)
            m.x = int(val['x'])
            m.y = int(val['y'])

            m.latitude, w1 = parselatlon(val['latitude'], arppos, thresholds,
                                         0)
            m.longitude, w2 = parselatlon(val['longitude'], arppos, thresholds,
                                          1)
            if w1 or w2:
                m.weight = w1 + w2
            else:
                m.weigth = 1

            meta.Session.add(m)
            ms.append(m)

        proj = meta.Session.query(AirportProjection).filter(
            sa.and_(AirportProjection.user == session['user'],
                    AirportProjection.airport == ad,
                    AirportProjection.mapchecksum == str(mapchecksum))).one()

        try:
            proj.scale = float(request.params['scale'].strip())
        except:
            proj.scale = None
        try:
            proj.north = float(request.params['north'].strip())
        except:
            proj.north = None

        def both_lat_lon(x):
            return x.latitude and x.longitude

        def neither_lat_lon(x):
            return not x.latitude and not x.longitude

        def just_lat(x):
            return x.latitude and not x.longitude

        def just_lon(x):
            return not x.latitude and x.longitude

        ms = [m for m in ms if not neither_lat_lon(m)]
        """
        if (len(ms)==4 and
            len([m for m in ms if just_lat(m)])==2 and
            len([m for m in ms if just_lon(m)])==2):
            extra=[]
            for m in ms:
                n=AirportMarker()
                n.x=m.x
                n.y=m.y                    
                if just_lat(m):
                    n.latitude=m.latitude
                    n.x+=1000
                    extra.append(n)
                if just_lon(m):
                    n.y+=1000                    
                    n.longitude=m.longitude
                    extra.append(n)
            ms.extend(extra)
        """

        if len(ms) == 1 and both_lat_lon(
                ms[0]) and proj.scale and proj.north != None:
            print "Scale/north triggered"
            print "Adchart:", chartobj
            if chartobj != None:
                render_height = chartobj['render_height']

                mark, = ms
                pixelpos = (mark.x, mark.y)
                mapsize = adchart.get('mapsize', (210, 297))
                mapheight_meter = mapsize[1] / 1000.0 * proj.scale
                mapheight_km = mapheight_meter / 1000.0

                merc = mapper.latlon2merc((mark.latitude, mark.longitude), 17)

                pixels = mapper.approx_scale(merc, 17, mapheight_km / 1.852)

                newmerc = (merc[0], merc[1] - pixels)
                northrad = proj.north / (180.0 / math.pi)
                newpixelpos = (pixelpos[0] +
                               render_height * math.sin(northrad),
                               pixelpos[1] -
                               render_height * math.cos(northrad))

                m = AirportMarker()
                m.x = newpixelpos[0]
                m.y = newpixelpos[1]
                latlon = mapper.merc2latlon(newmerc, 17)
                m.latitude = latlon[0]
                m.longitude = latlon[1]
                m.weight = 1
                ms.append(m)

        if len(ms) == 2 and all(both_lat_lon(x) for x in ms):
            print "Have exactly two marks now"
            mark1, mark2 = ms
            lm1, lm2 = [
                mapper.latlon2merc((mark.latitude, mark.longitude), 17)
                for mark in [mark1, mark2]
            ]
            ld = (lm2[0] - lm1[0], lm2[1] - lm1[1])
            pd = (mark2.x - mark1.x, mark2.y - mark1.y)
            lm3 = (lm1[0] - ld[1], lm1[1] + ld[0])
            pm3 = (mark1.x - pd[1], mark1.y + pd[0])
            llm3 = mapper.merc2latlon(lm3, 17)

            m = AirportMarker()
            m.x = pm3[0]
            m.y = pm3[1]
            m.latitude, w1 = llm3[0], 1
            m.longitude, w2 = llm3[1], 1
            ms.append(m)
            print "delta pixels", pd
            print "delta latlon", ld
            print "extra end pixels", m.x, m.y
            print "extra end latlon", m.latitude, m.longitude

        eqns = 0
        for m in ms:
            if both_lat_lon(m): eqns += 2
            elif just_lat(m): eqns += 1
            elif just_lon(m): eqns += 1

        try:
            if eqns < 4: raise Exception("Unsolvable")
            error, A, T = customproj.solve(ms)
            matrix = list(A) + list(T)
            if proj.matrix:
                oldmatrix = list(proj.matrix)
                newmatrix = list(A) + list(T)
                diff = sum(abs(a - b) for a, b in zip(oldmatrix, newmatrix))
            else:
                diff = 1e30  #enough to trigger update
            if diff > 1e-12:
                proj.matrix = tuple(newmatrix)
                proj.updated = datetime.utcnow().replace(microsecond=0)
        except Exception, cause:
            print "Couldn't solve projection equation %s" % (cause, )
            proj.matrix = [1, 0, 0, 1, 0, 0]
            proj.updated = datetime.utcnow().replace(microsecond=0)
            meta.Session.add(proj)
Пример #13
0
    def show(self):
        ad = request.params['ad']
        cksum = request.params['checksum']
        chartobj = None
        for adobj in ec.get_airfields():
            bb = False
            if adobj['name'] == ad and 'adcharts' in adobj:
                for adchart in adobj['adcharts'].values():
                    if adchart['checksum'] == cksum:
                        chartobj = adchart
                        bb = True
                        break
            if bb: break
        else:
            self.error("No such airport/picture " + ad + "/" + cksum)
        projs = meta.Session.query(AirportProjection).filter(
            sa.and_(
                AirportProjection.user == session['user'],
                AirportProjection.airport == ad,
                AirportProjection.mapchecksum == adchart['checksum'])).all()
        c.markers = meta.Session.query(AirportMarker).filter(
            sa.and_(
                AirportMarker.user == session['user'],
                AirportMarker.airport == ad,
                AirportMarker.mapchecksum == adchart['checksum'])).order_by(
                    AirportMarker.latitude, AirportMarker.longitude,
                    AirportMarker.x, AirportMarker.y).all()
        if not projs:
            proj = AirportProjection()
            proj.user = session['user']
            proj.airport = ad
            proj.mapchecksum = str(adchart['checksum'])
            proj.updated = datetime.utcnow()
            proj.matrix = (1, 0, 0, 1, 0, 0)
            proj.scale = None
            proj.north = None
            meta.Session.add(proj)
            meta.Session.flush()
            meta.Session.commit()

        else:
            proj, = projs
            proj.mapchecksum = str(proj.mapchecksum)

        if all([x == 0 for x in proj.matrix[4:6]]):
            projmatrix = self.invent_matrix(proj.mapchecksum,
                                            adchart['variant'])
        else:
            projmatrix = proj.matrix

        A = projmatrix[0:4]
        T = projmatrix[4:6]
        transform = customproj.Transform(A, T)
        c.matrix = projmatrix
        c.initial_scroll_x = request.params.get("scroll_x", 0)
        c.initial_scroll_y = request.params.get("scroll_y", 0)
        c.maptype = request.params.get("maptype", "chart")

        c.variant = adchart['variant']
        c.curadmarker = session.get('curadmarker', (0, 0))
        c.img = adchart['blobname'] + "," + adchart['checksum']
        c.flash = None
        c.ad = ad
        c.mapchecksum = adchart['checksum']
        c.mapsize = adchart.get('mapsize', (210, 297))
        c.scale = proj.scale if proj.scale != None else ""
        c.north = proj.north if proj.north != None else ""
        c.runways = []
        c.arp = transform.to_pixels(mapper.from_str(adobj['pos']))
        arp1m = mapper.latlon2merc(mapper.from_str(adobj['pos']), 17)
        arp2m = mapper.latlon2merc(mapper.from_str(adobj['pos']), 17)
        arp1m = (arp1m[0], arp1m[1] - 250)
        arp2m = (arp2m[0] + 250, arp2m[1])
        c.arp1 = transform.to_pixels(mapper.merc2latlon(arp1m, 17))
        c.arp2 = transform.to_pixels(mapper.merc2latlon(arp2m, 17))

        def dist(x, y):
            return math.sqrt((x[0] - y[0])**2 + (x[1] - y[1])**2)

        c.ratio = abs(dist(c.arp, c.arp1) - dist(c.arp, c.arp2)) / max(
            dist(c.arp, c.arp1), dist(c.arp, c.arp2))

        c.transform_reasonable = True
        x, y = c.arp
        if x < -200 or y < -200 or x >= 4000 or y >= 4000:
            c.transform_reasonable = False
        c.revmarkers = []
        c.width, c.height = chartobj['render_width'], chartobj['render_height']

        try:
            c.base_coords=\
                [mapper.latlon2merc(transform.to_latlon((0,0)),13),
                mapper.latlon2merc(transform.to_latlon((c.width,0)),13),
                mapper.latlon2merc(transform.to_latlon((0,c.height)),13),
                mapper.latlon2merc(transform.to_latlon((c.width,c.height)),13)]
        except Exception:
            print "problem with basecoords:", traceback.format_exc()
            c.base_coords = [(0, 0) for x in xrange(4)]

        for mark in c.markers:
            lat, lon = transform.to_latlon((mark.x, mark.y))
            if mark.latitude:
                lat = mark.latitude
            if mark.longitude:
                lon = mark.longitude
            pos = transform.to_pixels((lat, lon))
            c.revmarkers.append(pos)
        for rwy in adobj.get('runways', []):
            ends = rwy['ends']
            latlon1 = mapper.from_str(ends[0]['pos'])
            latlon2 = mapper.from_str(ends[1]['pos'])
            print rwy, "Runway pos", latlon1, " to ", latlon2
            p1 = transform.to_pixels(latlon1)
            p2 = transform.to_pixels(latlon2)
            for p in [p1, p2]:
                x, y = p
                if x < -200 or y < -200 or x >= 4000 or y >= 4000:
                    c.transform_reasonable = False
            c.runways.append(
                ((int(p1[0]), int(p1[1])), (int(p2[0]), int(p2[1]))))

        c.random = md5.md5(pickle.dumps(projmatrix)).hexdigest()

        return render('/airportproj.mako')
Пример #14
0
    def get_airspaces(self):
        print "Get airspaces called"

        getsectors = int(request.params.get("sectors", "0"))

        out = []
        if 1:
            for space in extracted_cache.get_airspaces(
            ) + get_notam_objs_cached(
            )['areas'] + extracted_cache.get_aip_sup_areas():
                lat, lon = mapper.from_str(space['points'][0])
                #if lat<57 or lat>62:
                #    continue
                if getsectors == 0 and space.get('type', None) == 'sector':
                    continue
                name = space['name']
                if space['type'] == "notamarea":
                    name = "NOTAM:" + name
                clnd = cleanup_poly(
                    [mapper.from_str(x) for x in space['points']], name)
                if not clnd:
                    print "Skipped area", name, space
                    continue
                out.append(
                    dict(
                        name=name,
                        freqs=space['freqs'] if space.get('freqs', "") else [],
                        floor=space.get('floor', ""),
                        type=space['type'],
                        ceiling=space.get('ceiling', ""),
                        points=[dict(lat=p[0], lon=p[1]) for p in clnd]))

        aiptexts = []
        points = []
        version = request.params.get("version", None)
        getaiptext = int(request.params.get("aip", "0"))
        print "version", version
        if version and int(version.strip()) >= 5:
            user_aipgen = request.params.get("aipgen", "")
        else:
            user_aipgen = ""
        for airp in extracted_cache.get_airfields():
            lat, lon = mapper.from_str(airp['pos'])
            if lat < 54 or lon < 4 or lon >= 30.5:
                try:
                    if not version or int(version.strip()) <= 7:
                        continue
                except:
                    continue

            #if lat<58.5 or lat>60.5:
            #    continue
            aname = airp['name']

            notams = []
            icao = None
            taf = None
            metar = None
            kind = 'field'
            if airp.get('icao', 'zzzz').lower() != 'zzzz':
                icao = airp['icao']
                notams = notam_geo_search.get_notam_for_airport(icao)
                metar = metartaf.get_metar(icao)
                taf = metartaf.get_taf(icao)
                kind = 'port'

            ap = dict(name=aname,
                      lat=lat,
                      lon=lon,
                      kind=kind,
                      notams=notams,
                      remark=airp.get('remark', ''),
                      alt=float(airp.get('elev', 0)))
            if 'runways' in airp:
                ap['runways'] = airp['runways']
            if icao:
                ap['icao'] = icao
                if taf.text:
                    ap['taf'] = taf.text
                if metar.text:
                    ap['metar'] = metar.text

                if getaiptext and 'aiptext' in airp:
                    for aiptext in airp['aiptext']:
                        if aip_text_documents.check_doc(
                                aiptext['icao'], aiptext['category'],
                                aiptext['checksum']):
                            #^^^Okay, this really needs an explanation^^^
                            #Nominally, each aiptext item in aipdata.cache (from which the get_airfields() function
                            #ultimately gets all its data, should always have its corresponding aiptext in html format
                            #available on disk. Now, if the on-disk file is deleted (should never happen), we will
                            #get an exception later down where we try to send this data (with the checksum we have here)
                            #over http to the client. Unfortunately, the routine that sends the data is not at liberty
                            #to modify "what was sent", so the entire sync operation fails. This hack here makes the
                            #failure happen earlier, and in that case the given aiptext-document is suppressed
                            #completely, meaning that the sync operation succeeds, albeit without one specific document
                            #(hey, better than nothing!).
                            #
                            #Of course, the real question is why a document may be missing. A bug of some sort right now,
                            #2012-08-28, makes this bug occur every now and then. Investigation is ongoing.
                            aiptexts.append(
                                dict(name=icao + "_" + aiptext['category'],
                                     icao=icao,
                                     data=aiptext))

            if 'adcharts' in airp and '' in airp['adcharts'] and airp[
                    'adcharts'][""]['blobname']:
                ret = airp['adcharts'][""]
                try:
                    cksum = ret['checksum']
                    try:
                        aprojmatrix = get_proj(cksum).matrix
                    except Exception:
                        #print traceback.format_exc()
                        #print "Using 0-proj for ",aname
                        aprojmatrix = [0 for x in xrange(6)]

                    ap['adchart_matrix'] = list(aprojmatrix)
                    ap['adchart_width'] = ret['render_width']
                    ap['adchart_height'] = ret['render_height']
                    ap['adchart_name'] = ret['blobname']
                    ap['adchart_checksum'] = cksum
                    ap['adchart_url'] = ret['url']
                except Exception, cause:
                    print "Couldn't get projection for airport %s (%s)" % (
                        aname, cause)

            points.append(ap)
Пример #15
0
        charts = []

        print "Client request params", request.params

        if version <= 3:
            prevstamp = int(request.params["stamp"])
            print "getnewadchart, prevstamp:", prevstamp

            #Make any sort of race impossible by substracting 5 minutes from now.
            #A race will now only happen if a file is modified on disk, after this
            #routine started, but ends up with a timestamp 5 minutes earlier in
            #time, but that can't happen.
            nowstamp = utcdatetime2stamp_inexact(datetime.utcnow()) - 60 * 5
            assert version in [1, 2, 3]
            print "Old stamp", prevstamp
            for ad in extracted_cache.get_airfields():
                if ad.get('icao', 'ZZZZ').upper() == 'ZZZZ':
                    continue  #Ignore non-icao airports
                if 'adcharts' in ad:
                    for adc in ad['adcharts'].values():
                        newer = False
                        try:
                            cksum, proj = self.get_sel_cksum(adc['blobname'])
                            if proj and proj.updated > datetime.utcfromtimestamp(
                                    prevstamp):
                                newer = True
                            #print "selected",cksum,"for",adc
                            if version <= 2 and adc['variant'] != '':
                                continue  #Don't send all kinds of charts to old clients
                            if cksum == None: continue
                            for level in xrange(5):
Пример #16
0
 def index(self):
     
     ack_cnt = meta.Session.query(NotamAck.appearnotam,NotamAck.appearline,sa.func.count('*').label('acks')).filter(NotamAck.user==session.get('user',None)).group_by(NotamAck.appearnotam,NotamAck.appearline).subquery()
 
     c.items=meta.Session.query(NotamUpdate,ack_cnt.c.acks,Notam.downloaded).outerjoin(
             (ack_cnt,sa.and_(                    
                 NotamUpdate.appearnotam==ack_cnt.c.appearnotam,
                 NotamUpdate.appearline==ack_cnt.c.appearline))).outerjoin(
             (Notam,Notam.ordinal==NotamUpdate.appearnotam)
              ).order_by(sa.desc(Notam.downloaded)).filter(
                     NotamUpdate.disappearnotam==sa.null()).all()
     c.categories=set([notamupdate.category for notamupdate,acks,downloaded in c.items])
     user=meta.Session.query(User).filter(User.user==session['user']).one()
     c.showobst=user.showobst
     
     
     
     def vandalize(x):
         x=x.replace(u"Å",u"A")
         x=x.replace(u"Ä",u"A")
         x=x.replace(u"Ö",u"O")
         return x
     for air in get_airfields():
         c.categories.add(vandalize(u"%s/%s"%(air['icao'].upper(),air['name'].upper())))
     c.sel_cat=set(x.category for x in meta.Session.query(NotamCategoryFilter).filter(NotamCategoryFilter.user==session['user']))
     c.shown=[]
     c.show_cnt=0
     c.hide_cnt=0
     c.countries=[
        dict(name="Sweden",sel=False,short="ES"),
        dict(name="Finland",sel=False,short="EF"),
        dict(name="Estonia",sel=False,short="EE"),
        dict(name="Latvia",sel=False,short="EV"),
        dict(name="Denmark",sel=False,short="EK"),
     ]
     if 1:
         for ct in meta.Session.query(NotamCountryFilter).filter(
                 NotamCountryFilter.user==session['user']).all():
             for countrydict in c.countries:
                 if countrydict['name']==ct.country:
                     countrydict['sel']=True
     selcountries=set()
     for ct in c.countries:
         if ct['sel']:
             selcountries.add(ct['short'])
     if len(selcountries)==0:
         selcountries=None
     ms=[]
     ms.append(re.compile(r".*\bOBST\s+ERECTED\b.*"))
     ms.append(re.compile(r".*TURBINE?S?\s+ERECTED\b.*"))
     ms.append(re.compile(r".*\bMASTS?\s+ERECTED\b.*"))
     ms.append(re.compile(r".*\bCRANES?\s+ERECTED\b.*"))
     ms.append(re.compile(r".*LIGHTS?.*OUT\s+OF\s+SERVICE.*",re.DOTALL))
     for notamupdate,acks,downloaded in c.items:
         if not c.showobst:
             match=False
             for m in ms:
                 if m.match(notamupdate.text):
                     match=True
                     break
             if match:
                 c.hide_cnt+=1
                 continue
             
         if (len(c.sel_cat)==0 or notamupdate.category in c.sel_cat) and \
             (selcountries==None or notamupdate.category==None or notamupdate.category[:2] in selcountries):
             c.shown.append((notamupdate,acks,downloaded))
             c.show_cnt+=1
         else:
             c.hide_cnt+=1
     print "Start rendering mako"
     return render('/notam.mako')
Пример #17
0
        charts=[]
        
        print "Client request params",request.params

        if version<=3:
            prevstamp=int(request.params["stamp"])
            print "getnewadchart, prevstamp:",prevstamp
            
            #Make any sort of race impossible by substracting 5 minutes from now.
            #A race will now only happen if a file is modified on disk, after this
            #routine started, but ends up with a timestamp 5 minutes earlier in
            #time, but that can't happen.            
            nowstamp=utcdatetime2stamp_inexact(datetime.utcnow())-60*5
            assert version in [1,2,3]
            print "Old stamp",prevstamp
            for ad in extracted_cache.get_airfields():
                if ad.get('icao','ZZZZ').upper()=='ZZZZ':continue #Ignore non-icao airports 
                if 'adcharts' in ad:
                    for adc in ad['adcharts'].values():
                        newer=False
                        try:
                            cksum,proj=self.get_sel_cksum(adc['blobname'])
                            if proj and proj.updated>datetime.utcfromtimestamp(prevstamp):
                                newer=True 
                            #print "selected",cksum,"for",adc
                            if version<=2 and adc['variant']!='':
                                continue #Don't send all kinds of charts to old clients
                            if cksum==None: continue
                            for level in xrange(5):
                                cstamp=parse_landing_chart.get_timestamp(adc['blobname'],cksum,level)                        
                                #print "Read file stamp:",cstamp,"prevstamp:",prevstamp
Пример #18
0
    def get_airspaces(self):
        print "Get airspaces called"
        
        getsectors=int(request.params.get("sectors","0"))
        
        out=[]
        if 1:
            for space in extracted_cache.get_airspaces()+get_notam_objs_cached()['areas']+extracted_cache.get_aip_sup_areas():
                lat,lon=mapper.from_str(space['points'][0])
                #if lat<57 or lat>62:
                #    continue
                if getsectors==0 and space.get('type',None)=='sector':
                    continue
                name=space['name']
                if space['type']=="notamarea":
                    name="NOTAM:"+name
                clnd=cleanup_poly([mapper.from_str(x) for x in space['points']],name)
                if not clnd:
                    print "Skipped area",name,space 
                    continue
                out.append(dict(
                    name=name,
                    freqs=space['freqs'] if space.get('freqs',"") else [],
                    floor=space.get('floor',""),
                    type=space['type'],
                    ceiling=space.get('ceiling',""),
                    points=[dict(lat=p[0],lon=p[1]) for p in clnd]))
            
        aiptexts=[]
        points=[]
        version=request.params.get("version",None)
        getaiptext=int(request.params.get("aip","0"))
        print "version",version
        if version and int(version.strip())>=5:
            user_aipgen=request.params.get("aipgen","")
        else:
            user_aipgen=""
        for airp in extracted_cache.get_airfields():
            lat,lon=mapper.from_str(airp['pos'])
            if lat<54 or lon<4 or lon>=30.5:
                try:
                    if not version or int(version.strip())<=7:
                        continue
                except:
                    continue

            #if lat<58.5 or lat>60.5:
            #    continue
            aname=airp['name']
            
            notams=[]
            icao=None
            taf=None
            metar=None
            kind='field'
            if airp.get('icao','zzzz').lower()!='zzzz':
                icao=airp['icao']
                notams=notam_geo_search.get_notam_for_airport(icao)
                metar=metartaf.get_metar(icao)
                taf=metartaf.get_taf(icao)
                kind='port'
                
            ap=dict(
                name=aname,
                lat=lat,
                lon=lon,
                kind=kind,
                notams=notams,
                remark=airp.get('remark',''),
                alt=float(airp.get('elev',0)))
            if 'runways' in airp:
                ap['runways']=airp['runways']
            if icao:
                ap['icao']=icao
                if taf.text:
                    ap['taf']=taf.text
                if metar.text:
                    ap['metar']=metar.text
            
                if getaiptext and 'aiptext' in airp:
                    for aiptext in airp['aiptext']:
                        if aip_text_documents.check_doc(aiptext['icao'],aiptext['category'],aiptext['checksum']):
                            #^^^Okay, this really needs an explanation^^^
                            #Nominally, each aiptext item in aipdata.cache (from which the get_airfields() function
                            #ultimately gets all its data, should always have its corresponding aiptext in html format
                            #available on disk. Now, if the on-disk file is deleted (should never happen), we will
                            #get an exception later down where we try to send this data (with the checksum we have here)
                            #over http to the client. Unfortunately, the routine that sends the data is not at liberty
                            #to modify "what was sent", so the entire sync operation fails. This hack here makes the
                            #failure happen earlier, and in that case the given aiptext-document is suppressed
                            #completely, meaning that the sync operation succeeds, albeit without one specific document
                            #(hey, better than nothing!).
                            #
                            #Of course, the real question is why a document may be missing. A bug of some sort right now,
                            #2012-08-28, makes this bug occur every now and then. Investigation is ongoing.
                            aiptexts.append(
                                dict(name=icao+"_"+aiptext['category'],
                                     icao=icao,
                                     data=aiptext))
                        
            if 'adcharts' in airp and '' in airp['adcharts'] and airp['adcharts'][""]['blobname']:
                ret=airp['adcharts'][""]
                try:
                    cksum=ret['checksum']
                    try:
                        aprojmatrix=get_proj(cksum).matrix
                    except Exception:
                        #print traceback.format_exc()
                        #print "Using 0-proj for ",aname
                        aprojmatrix=[0 for x in xrange(6)]
                        
                    ap['adchart_matrix']=list(aprojmatrix)
                    ap['adchart_width']=ret['render_width']
                    ap['adchart_height']=ret['render_height']
                    ap['adchart_name']=ret['blobname']
                    ap['adchart_checksum']=cksum
                    ap['adchart_url']=ret['url']                    
                except Exception,cause:
                    print "Couldn't get projection for airport %s (%s)"%(aname,cause)
            
            points.append(ap)            
Пример #19
0
    def show(self):
        ad=request.params['ad']
        cksum=request.params['checksum']
        chartobj=None
        for adobj in ec.get_airfields():
            bb=False
            if adobj['name']==ad and 'adcharts' in adobj:                
                for adchart in adobj['adcharts'].values():
                    if adchart['checksum']==cksum:
                        chartobj=adchart
                        bb=True
                        break
            if bb: break
        else:
            self.error("No such airport/picture "+ad+"/"+cksum)
        projs=meta.Session.query(AirportProjection).filter(sa.and_(
                    AirportProjection.user==session['user'],
                    AirportProjection.airport==ad,
                    AirportProjection.mapchecksum==adchart['checksum'])).all()
        c.markers=meta.Session.query(AirportMarker).filter(sa.and_(
                    AirportMarker.user==session['user'],
                    AirportMarker.airport==ad,
                    AirportMarker.mapchecksum==adchart['checksum'])).order_by(AirportMarker.latitude,AirportMarker.longitude,AirportMarker.x,AirportMarker.y).all()
        if not projs:            
            proj=AirportProjection()
            proj.user=session['user']
            proj.airport=ad
            proj.mapchecksum=str(adchart['checksum'])
            proj.updated=datetime.utcnow()
            proj.matrix=(1,0,0,1,0,0)
            proj.scale=None
            proj.north=None
            meta.Session.add(proj)
            meta.Session.flush()
            meta.Session.commit()
            
        else:
            proj,=projs
            proj.mapchecksum=str(proj.mapchecksum)
        
        if all([x==0 for x in proj.matrix[4:6]]):
            projmatrix=self.invent_matrix(proj.mapchecksum,adchart['variant'])
        else:            
            projmatrix=proj.matrix
            
        A=projmatrix[0:4]
        T=projmatrix[4:6]
        transform=customproj.Transform(A,T)
        c.matrix=projmatrix
        c.initial_scroll_x=request.params.get("scroll_x",0)
        c.initial_scroll_y=request.params.get("scroll_y",0)
        c.maptype=request.params.get("maptype","chart")
        
        c.variant=adchart['variant']
        c.curadmarker=session.get('curadmarker',(0,0))
        c.img=adchart['blobname']+","+adchart['checksum']
        c.flash=None
        c.ad=ad
        c.mapchecksum=adchart['checksum']
        c.mapsize=adchart.get('mapsize',(210,297))
        c.scale=proj.scale if proj.scale!=None else ""
        c.north=proj.north if proj.north!=None else ""
        c.runways=[]
        c.arp=transform.to_pixels(mapper.from_str(adobj['pos']))
        arp1m=mapper.latlon2merc(mapper.from_str(adobj['pos']),17)
        arp2m=mapper.latlon2merc(mapper.from_str(adobj['pos']),17)
        arp1m=(arp1m[0],arp1m[1]-250)
        arp2m=(arp2m[0]+250,arp2m[1])
        c.arp1=transform.to_pixels(mapper.merc2latlon(arp1m,17))
        c.arp2=transform.to_pixels(mapper.merc2latlon(arp2m,17))
        def dist(x,y):
            return math.sqrt((x[0]-y[0])**2+(x[1]-y[1])**2)
        c.ratio=abs(dist(c.arp,c.arp1)-dist(c.arp,c.arp2))/max(dist(c.arp,c.arp1),dist(c.arp,c.arp2));

        c.transform_reasonable=True
        x,y=c.arp
        if x<-200 or y<-200 or x>=4000 or y>=4000:
            c.transform_reasonable=False   
        c.revmarkers=[]
        c.width,c.height=chartobj['render_width'],chartobj['render_height']
        
        try:
            c.base_coords=\
                [mapper.latlon2merc(transform.to_latlon((0,0)),13),
                mapper.latlon2merc(transform.to_latlon((c.width,0)),13),
                mapper.latlon2merc(transform.to_latlon((0,c.height)),13),
                mapper.latlon2merc(transform.to_latlon((c.width,c.height)),13)]
        except Exception:
            print "problem with basecoords:",traceback.format_exc()
            c.base_coords=[(0,0) for x in xrange(4)]

        
        for mark in c.markers:
            lat,lon=transform.to_latlon((mark.x,mark.y))
            if mark.latitude:
                lat=mark.latitude
            if mark.longitude:
                lon=mark.longitude
            pos=transform.to_pixels((lat,lon))
            c.revmarkers.append(pos)
        for rwy in adobj.get('runways',[]):
            ends=rwy['ends']
            latlon1=mapper.from_str(ends[0]['pos'])
            latlon2=mapper.from_str(ends[1]['pos'])
            print rwy,"Runway pos",latlon1," to ",latlon2
            p1=transform.to_pixels(latlon1)
            p2=transform.to_pixels(latlon2)
            for p in [p1,p2]:
                x,y=p
                if x<-200 or y<-200 or x>=4000 or y>=4000:
                    c.transform_reasonable=False
            c.runways.append((
                              (int(p1[0]),int(p1[1])),
                              (int(p2[0]),int(p2[1]))
                              ))

        c.random=md5.md5(pickle.dumps(projmatrix)).hexdigest()
        
        return render('/airportproj.mako')
Пример #20
0
    def save(self):
        print request.params
        
        ad=request.params['ad']
        chartobj=None        
        mapchecksum=request.params['mapchecksum']
        for adobj in ec.get_airfields():
            if adobj['name']==ad:
                bb=False
                for adchart in adobj['adcharts'].values():
                    if adchart['checksum']==mapchecksum:
                        chartobj=adchart
                        bb=True
                        break
                if bb: break
        else:
            self.error("No such airport"+ad)
        marks=dict()
        for param,val in request.params.items():
            if param in ["save","ad",'mapchecksum','scroll_x','scroll_y','maptype','scale','north']:
                continue
            if param.startswith("del"):
                continue
            if param.startswith("set_"):
                x,y=[int(v) for v in param.split("_")[1:]]
                session['curadmarker']=(x,y)
                session.save()
                continue            
            if param=="add":
                xs=meta.Session.query(AirportMarker.x).filter(sa.and_(
                    AirportMarker.user==session['user'],
                    AirportMarker.airport==ad
                    )).all()
                if xs:
                    maxx=max(xs)[0]+1
                else:
                    maxx=0
                marks[(maxx,0)]=dict(latitude=None,longitude=None,x=maxx,y=0)
                session['curadmarker']=(maxx,0)
                session.save()
                continue
            
            sx,sy,attrib=re.match(ur"mark_(\d+)_(\d+)_(\w*)",param).groups()
            x=int(sx)
            y=int(sy)
            marks.setdefault((x,y),dict())[attrib]=val
        
        thresholds=dict()
        for rwy in adobj.get('runways',[]):
            ends=rwy['ends']
            for end in ends:
                thresholds[end['thr']]=mapper.from_str(end['pos'])
            
        for param,val in request.params.items():
            if param.startswith("del_"):
                x,y=[int(v) for v in param.split("_")[1:]]
                marks.pop((x,y))
                continue
            
        meta.Session.query(AirportMarker).filter(sa.and_(
                AirportMarker.user==session['user'],
                AirportMarker.airport==ad)).delete()
        ms=[]
        arppos=mapper.from_str(adobj['pos'])
        
        
        for (x,y),val in marks.items():
            m=AirportMarker()
            m.user=session['user']
            m.airport=ad
            m.mapchecksum=str(mapchecksum)
            m.x=int(val['x'])
            m.y=int(val['y'])
            
            m.latitude,w1=parselatlon(val['latitude'],arppos,thresholds,0)
            m.longitude,w2=parselatlon(val['longitude'],arppos,thresholds,1)
            if w1 or w2:
                m.weight=w1+w2
            else:
                m.weigth=1
                
            meta.Session.add(m)
            ms.append(m)

        proj=meta.Session.query(AirportProjection).filter(sa.and_(
            AirportProjection.user==session['user'],
            AirportProjection.airport==ad,
            AirportProjection.mapchecksum==str(mapchecksum))).one()
            
        try:
            proj.scale=float(request.params['scale'].strip())
        except:
            proj.scale=None
        try:
            proj.north=float(request.params['north'].strip())
        except:
            proj.north=None
                    
            

        def both_lat_lon(x):
            return x.latitude and x.longitude
        def neither_lat_lon(x):
            return not x.latitude and not x.longitude
        def just_lat(x):
            return x.latitude and not x.longitude
        def just_lon(x):
            return not x.latitude and x.longitude
        ms=[m for m in ms if not neither_lat_lon(m)]
        
        """
        if (len(ms)==4 and
            len([m for m in ms if just_lat(m)])==2 and
            len([m for m in ms if just_lon(m)])==2):
            extra=[]
            for m in ms:
                n=AirportMarker()
                n.x=m.x
                n.y=m.y                    
                if just_lat(m):
                    n.latitude=m.latitude
                    n.x+=1000
                    extra.append(n)
                if just_lon(m):
                    n.y+=1000                    
                    n.longitude=m.longitude
                    extra.append(n)
            ms.extend(extra)
        """
        
        if len(ms)==1 and both_lat_lon(ms[0]) and proj.scale and proj.north!=None:
            print "Scale/north triggered"
            print "Adchart:",chartobj
            if chartobj!=None:
                render_height=chartobj['render_height']

                mark,=ms
                pixelpos=(mark.x,mark.y)
                mapsize=adchart.get('mapsize',(210,297))
                mapheight_meter=mapsize[1]/1000.0 * proj.scale
                mapheight_km=mapheight_meter/1000.0
                
                merc=mapper.latlon2merc((mark.latitude,mark.longitude),17)
                                            
                pixels=mapper.approx_scale(merc,17,mapheight_km/1.852)
                
                newmerc=(merc[0],merc[1]-pixels)
                northrad=proj.north/(180.0/math.pi)
                newpixelpos=(pixelpos[0]+render_height*math.sin(northrad),
                             pixelpos[1]-render_height*math.cos(northrad))

                m=AirportMarker()
                m.x=newpixelpos[0]
                m.y=newpixelpos[1]
                latlon=mapper.merc2latlon(newmerc,17)
                m.latitude=latlon[0]
                m.longitude=latlon[1]
                m.weight=1
                ms.append(m)
                             
                        
            
        if len(ms)==2 and all(both_lat_lon(x) for x in ms):
            print "Have exactly two marks now"
            mark1,mark2=ms            
            lm1,lm2=[mapper.latlon2merc((mark.latitude,mark.longitude),17) for mark in [mark1,mark2]]
            ld=(lm2[0]-lm1[0],lm2[1]-lm1[1])
            pd=(mark2.x-mark1.x,mark2.y-mark1.y)
            lm3=(lm1[0]-ld[1],lm1[1]+ld[0])
            pm3=(mark1.x-pd[1],mark1.y+pd[0])
            llm3=mapper.merc2latlon(lm3,17)
            
            m=AirportMarker()
            m.x=pm3[0]
            m.y=pm3[1]
            m.latitude,w1=llm3[0],1
            m.longitude,w2=llm3[1],1
            ms.append(m)
            print "delta pixels",pd
            print "delta latlon",ld
            print "extra end pixels",m.x,m.y
            print "extra end latlon",m.latitude,m.longitude
            
        eqns=0
        for m in ms:
            if both_lat_lon(m): eqns+=2
            elif just_lat(m): eqns+=1
            elif just_lon(m): eqns+=1
            
        try:
            if eqns<4: raise Exception("Unsolvable")
            error,A,T=customproj.solve(ms)
            matrix=list(A)+list(T)
            if proj.matrix:
                oldmatrix=list(proj.matrix)
                newmatrix=list(A)+list(T)
                diff=sum(abs(a-b) for a,b in zip(oldmatrix,newmatrix))
            else:
                diff=1e30 #enough to trigger update
            if diff>1e-12:
                proj.matrix=tuple(newmatrix)
                proj.updated=datetime.utcnow().replace(microsecond=0)
        except Exception,cause:
            print "Couldn't solve projection equation %s"%(cause,)
            proj.matrix=[1,0,0,1,0,0]
            proj.updated=datetime.utcnow().replace(microsecond=0)
            meta.Session.add(proj)