Changeset cf06a02 in osmose-frontend


Ignore:
Timestamp:
Nov 24, 2012 5:59:55 PM (5 years ago)
Author:
Frédéric Rodrigo <frodrigo@…>
Branches:
master
Children:
90ce398
Parents:
c32ea78
git-author:
Frédéric Rodrigo <frodrigo@…> (05/11/2012 22:26:19)
git-committer:
Frédéric Rodrigo <frodrigo@…> (24/11/2012 17:59:55)
Message:

Add errors heatmap

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • map.py

    r80a9930 rcf06a02  
    2525import datetime 
    2626import json 
     27import math, StringIO 
     28from PIL import Image 
     29import ImageDraw 
    2730 
    2831 
     
    135138 
    136139 
     140def build_where_item(item, table): 
     141    if item == '': 
     142        where = "1=2" 
     143    elif item == None or item == 'xxxx': 
     144        where = "1=1" 
     145    else: 
     146        where = [] 
     147        l = [] 
     148        for i in item.split(','): 
     149            try: 
     150                if 'xxx' in i: 
     151                    where.append("%s.item/1000 = %s" % (table, int(i[0]))) 
     152                else: 
     153                    l.append(str(int(i))) 
     154            except: 
     155                pass 
     156        if l != []: 
     157            where.append("%s.item IN (%s)" % (table, ','.join(l))) 
     158        if where != []: 
     159            where = "(%s)" % ' OR '.join(where) 
     160        else: 
     161            where = "1=1" 
     162    return where 
     163 
     164 
     165def build_param(source, item, level, user): 
     166    join = "" 
     167    if source: 
     168        sources = source.split(",") 
     169        source2 = [] 
     170        for source in sources: 
     171            source = source.split("-") 
     172            if len(source)==1: 
     173                source2.append("(marker.source=%d)"%int(source[0])) 
     174            else: 
     175                source2.append("(marker.source=%d AND marker.class=%d)"%(int(source[0]), int(source[1]))) 
     176        sources2 = " OR ".join(source2) 
     177        where = "(%s)" % sources2 
     178    elif item != None: 
     179        where = build_where_item(item, "marker") 
     180    else: 
     181        where = "1=1" 
     182 
     183    if level: 
     184        join += """ 
     185        JOIN dynpoi_class ON 
     186            marker.source = dynpoi_class.source AND 
     187            marker.class = dynpoi_class.class 
     188        """ 
     189        where += " AND dynpoi_class.level IN (%s)" % level 
     190 
     191    if user: 
     192        join += """ 
     193        JOIN marker_elem ON 
     194            marker_elem.marker_id = marker.id 
     195        """ 
     196        where += " AND marker_elem.username = '%s'" % user 
     197 
     198    return (join, where) 
     199 
     200 
     201def num2deg(xtile, ytile, zoom): 
     202    n = 2.0 ** zoom 
     203    lon_deg = xtile / n * 360.0 - 180.0 
     204    lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n))) 
     205    lat_deg = math.degrees(lat_rad) 
     206    return (lat_deg, lon_deg) 
     207 
     208@route('/map/heat/<z:int>/<x:int>/<y:int>.png') 
     209def heat(db, z, x, y): 
     210    x2,y1 = num2deg(x,y,z) 
     211    x1,y2 = num2deg(x+1,y+1,z) 
     212 
     213    item   = request.params.get('item') 
     214    source = request.params.get('source', default='') 
     215    user   = utils.pg_escape(unicode(request.params.get('user', default=''))) 
     216    level  = request.params.get('level', default='1') 
     217 
     218    COUNT=32 
     219 
     220    items = build_where_item(item, "dynpoi_item") 
     221 
     222    db.execute(""" 
     223SELECT 
     224    SUM((SELECT SUM(t) FROM UNNEST(number) t)) 
     225FROM 
     226    dynpoi_item 
     227WHERE 
     228""" + items) 
     229    max = db.fetchone() 
     230    if max and max[0]: 
     231        max = float(max[0]) 
     232    else: 
     233        # FIXME redirect empty tile 
     234        max = 0 
     235 
     236    join, where = build_param(source, item, level, user) 
     237 
     238    db.execute(""" 
     239SELECT 
     240    COUNT(*), 
     241    (((lon-%(y1)s))*%(count)s/(%(y2)s-%(y1)s)-0.5)::int AS latn, 
     242    (((lat-%(x1)s))*%(count)s/(%(x2)s-%(x1)s)-0.5)::int AS lonn 
     243FROM 
     244    marker 
     245""" + join + """ 
     246WHERE 
     247""" + where + """ AND 
     248    lat>%(x1)s::int AND 
     249    lon>%(y1)s::int AND 
     250    lat<%(x2)s::int AND 
     251    lon<%(y2)s::int 
     252GROUP BY 
     253    latn, 
     254    lonn 
     255""", {"x1":x1*10e5, "y1":y1*10e5, "x2":x2*10e5, "y2":y2*10e5, "count":COUNT}) 
     256    im = Image.new("RGB", (256,256), "#ff0000") 
     257    draw = ImageDraw.Draw(im) 
     258 
     259    transparent_area = (0,0,256,256) 
     260    mask = Image.new('L', im.size, color=255) 
     261    mask_draw = ImageDraw.Draw(mask) 
     262    mask_draw.rectangle(transparent_area, fill=0) 
     263 
     264    for row in db.fetchall(): 
     265        count, x, y = row 
     266        count = int(math.log(count) / math.log(max / ((z-4+1+math.sqrt(COUNT))**2)) * 255) 
     267        count = 255 if count > 255 else count 
     268        r = [(x*256/COUNT,(COUNT-1-y)*256/COUNT), ((x+1)*256/COUNT-1,((COUNT-1-y+1)*256/COUNT-1))] 
     269        mask_draw.rectangle(r, fill=count) 
     270 
     271    im.putalpha(mask) 
     272    del draw 
     273 
     274    buf = StringIO.StringIO() 
     275    im.save(buf, 'PNG') 
     276    response.content_type = 'image/png' 
     277    return buf.getvalue() 
     278 
     279 
    137280@route('/map/markers') 
    138281def markers(db, lang): 
     
    194337    """ 
    195338 
    196     join = "" 
    197     if source: 
    198         sources = source.split(",") 
    199         source2 = [] 
    200         for source in sources: 
    201             source = source.split("-") 
    202             if len(source)==1: 
    203                 source2.append("(marker.source=%d)"%int(source[0])) 
    204             else: 
    205                 source2.append("(marker.source=%d AND marker.class=%d)"%(int(source[0]), int(source[1]))) 
    206         sources2 = " OR ".join(source2) 
    207         where = "(%s)" % sources2 
    208     elif item != None: 
    209         if item == '': 
    210             where = "1=2" 
    211         elif item == 'xxxx': 
    212             where = "1=1" 
    213         else: 
    214             where = [] 
    215             l = [] 
    216             for i in item.split(','): 
    217                 try: 
    218                     if 'xxx' in i: 
    219                         where.append("marker.item/1000 = %s" % int(i[0])) 
    220                     else: 
    221                         l.append(str(int(i))) 
    222                 except: 
    223                     pass 
    224             if l != []: 
    225                 where.append("marker.item IN (%s)" % ','.join(l)) 
    226             if where != []: 
    227                 where = "(%s)" % ' OR '.join(where) 
    228             else: 
    229                 where = "1=1" 
    230     else: 
    231         where = "1=1" 
    232  
    233     if level: 
    234         join += """ 
    235         JOIN dynpoi_class ON 
    236             marker.source = dynpoi_class.source AND 
    237             marker.class = dynpoi_class.class 
    238         """ 
    239         where += " AND dynpoi_class.level IN (%s)" % level 
    240  
    241     if user: 
    242         join += """ 
    243         JOIN marker_elem ON 
    244             marker_elem.marker_id = marker.id 
    245         """ 
    246         where += " AND marker_elem.username = '%s'" % user 
    247  
     339    join, where = build_param(source, item, level, user) 
    248340    db.execute(sqlbase % (join, where, minlat, maxlat, minlon, maxlon, lat, lon)) # FIXME pas de % 
    249341    results = db.fetchall() 
  • static/map/map.js

    rb490252 rcf06a02  
    44/* used to store old zoom factore to triger events when "going above" treshold */ 
    55var oldzoom = -1; 
     6var heat = null; 
    67 
    78//----------------------------------------// 
     
    5455    }); 
    5556    map.addLayer(bing); 
     57 
     58    heat = new OpenLayers.Layer.OSM("Heatmap", ["heat/${z}/${x}/${y}.png"], { 
     59        transitionEffect: 'resize', 
     60        isBaseLayer: false, 
     61    }); 
     62    map.addLayer(heat); 
    5663 
    5764    //var layerTilesAtHome = new OpenLayers.Layer.OSM.Osmarender("Osmarender"); 
     
    421428    bbox = bbox.transform(map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326")) 
    422429    bbox = bbox.toBBOX(); 
    423     var params = 
    424         "?lat=" + document.myform.lat.value + 
    425         "&lon=" + document.myform.lon.value + 
    426         "&zoom=" + document.myform.zoom.value + 
    427         "&source=" + document.myform.source.value + 
    428         "&user=" + document.myform.user.value + 
    429         "&item=" + ch + 
    430         "&level=" + document.myform.level.value + 
    431         "&bbox=" + bbox; 
    432430 
    433431    var permalink = plk.element; 
     
    436434 
    437435    pois.loadText(params); 
    438 } 
     436 
     437    if (heat.visibility) { 
     438        var params = 
     439            "?source=" + document.myform.source.value + 
     440            "&user=" + document.myform.user.value + 
     441            "&item=" + ch + 
     442            "&level=" + document.myform.level.value; 
     443        var url = "heat/${z}/${x}/${y}.png" + params; 
     444        if (heat.url != url) { 
     445            heat.setUrl(url); 
     446            heat.clearGrid(); 
     447            heat.redraw(); 
     448        } 
     449    } 
     450} 
Note: See TracChangeset for help on using the changeset viewer.