Switching to ElementMaker from Element/SubElement
[treecutter.git] / xinclude / address.py
index 4ae59df068161e07dba7e09829a2be8565e752fd..8ce6a6a7b77c581068cb8974afdd21c18b5a5357 100755 (executable)
@@ -7,10 +7,12 @@ from httplib2 import Http
 import urllib
 from math import *
 from lxml import etree
+from lxml.builder import ElementMaker
 from PIL import Image, ImageDraw
 from StringIO import StringIO
 from geohash import encode
 from geographiclib.geodesic import Geodesic
+from treecutter import constants as const
 
 # EC Equator lenght
 EC = 40075016.686 # meter
@@ -21,101 +23,65 @@ ZOOMRANGE = range(1, 18)
 # tile size
 TS = 256
 
-
 h = Http(".cache")
 
-class StaticOpenStreetMap(object):
-    """Setting up a static image from OSM with one or more markers"""
-    def __init__(self):
-        self._zoom = 0
-        self._width = 0
-        self._height = 0
-        self._markers = []
-        self._maptype = 'mapnik'
-
-    def add_marker(lon,lat):
-        self._markers.append((lon,lat))
-
-#    def construct_map(self):
-#        for coord in self._markers:
-#            print coord
-
-def lontile(lon, zoom):
-    tile = ((lon + 180) / 360) * (2**zoom)
-    return tile
-
-def lattile(lat, zoom):
-    tile = (1 - log(tan(lat * pi/180) + 1 / cos(lat* pi/180)) / pi) /2 * 2**zoom
-#    tile = (1-log(tan(radians(lat))+1/cos(radians(lat)))/pi)/2*2**zoom
-    return tile
-
-def coordtile(coord, zoom):
-    x = lontile(coord[1],zoom)
-    y = lattile(coord[0],zoom)
-    return (y,x)
-
-def tile(x,y,z):
-    return 'http://tile.openstreetmap.org/%s/%s/%s.png' % (z,x,y)
-
-def link(coord,zoom):
-    z = zoom
-    x = int(floor(lontile(coord[1],z)))
-    y = int(floor(lattile(coord[0],z)))
-    return tile(x,y,z)
-
-def offset(coord, zoom):
-    z = zoom
-    x = lontile(coord[1],z)
-    y = lattile(coord[0],z)
-    xo = int(floor((x-floor(x))*TS))
-    yo = int(floor((y-floor(y))*TS))
-    return (xo, yo)
+class Coord(object):
+    def __init__(self, lat, lon):
+        self.latitude  = float(lat)
+        self.longitude = float(lon)
+        self.image = None
 
-def distance(p1, p2):
-    res = Geodesic.WGS84.Inverse(p1[0], p1[1], p2[0], p2[1])
-    return res['s12']
+    def osmlink(self):
+        return "http://www.openstreetmap.org/?mlat=%s&mlon=%s&zoom=18&layers=M"\
+            % (self.latitude,self.longitude)
 
-def geocode(address,country=None):
-    params = { 'q': address,
-               'addressdetails': 1,
-               'limit': 1,
-               'format': 'xml',
-               'polygon': 0 }
-    time.sleep(1)
-    if country:
-        params['countrycodes'] = country
-
-    base_url = 'http://nominatim.openstreetmap.org/search?%s'
-    url = base_url % urllib.urlencode(params)
-    resp, content = h.request(url)
-#    print resp
-#    print content
-    root = etree.fromstring(content)
-    etree.tostring(root)
-#    print "%s" % (address)
-    lat = None
-    lon = None
-    for element in root.iter("place"):
-        lat = element.get("lat")
-        lon = element.get("lon")
-#        print(" : %s,%s" % (lat, lon))
-        break
-    if not lat or not lon:
-        print resp
-        print content
-    return (float(lat),float(lon))
+    def dms(self):
+        ns = self.latitude
+        ew = self.longitude
+        mnt,sec = divmod(ns*3600,60)
+        deg,mnt = divmod(mnt,60)
+        out = u'''%d°%2d'%5.2f"%s''' % ( deg,mnt,sec,'N')
+        mnt,sec = divmod(ew*3600,60)
+        deg,mnt = divmod(mnt,60)
+        out +=  u''' %d°%2d'%05.2f"%s''' % ( deg,mnt,sec,'E')
+        return out
 
-def mark(image, coord):
-    draw = ImageDraw.Draw(image)
-    x, y = coord
-    r = 5
-    bbox = (x-r, y-r, x+r, y+r)
-    draw.ellipse(bbox, outline="red")
+    def lontile(lon, zoom):
+        tile = ((lon + 180) / 360) * (2**zoom)
+        return tile
 
-def mapimage(coords, zoom=15,size=(TS,TS)):
-    if len(coords) == 1:
-        co = coords[0]
-        filename = encode(co[0],co[1])+'.png'
+    def lattile(lat, zoom):
+        tile = (1 - log(tan(lat * pi/180) + 1 / cos(lat* pi/180)) / pi) /2 * 2**zoom
+    #    tile = (1-log(tan(radians(lat))+1/cos(radians(lat)))/pi)/2*2**zoom
+        return tile
+
+    def coordtile(coord, zoom):
+        x = lontile(coord[1],zoom)
+        y = lattile(coord[0],zoom)
+        return (y,x)
+
+    def tile(x,y,z):
+        return 'http://tile.openstreetmap.org/%s/%s/%s.png' % (z,x,y)
+
+    def link(coord,zoom):
+        (x, y) = coordtile(coord,zoom)
+        x = int(floor(x))
+        y = int(floor(y))
+        return tile(x,y,zoom)
+
+    def offset(coord, zoom):
+        (x, y) = coordtile(coord,zoom)
+        xo = int(floor((x-floor(x))*TS))
+        yo = int(floor((y-floor(y))*TS))
+        return (xo, yo)
+
+    def distance(self, point):
+        res = Geodesic.WGS84.Inverse(self.latitude, self.longitude,
+                                     point.latitude, point.longitude)
+        return res['s12']
+
+    def png(self,zoom=15,size=(TS,TS)):
+        filename = encode(self.latitude, self.longitude)+'.png'
         if path.isfile(filename):
             if path.getctime(filename) > time.time() - 60*60*24*2:
                 return
@@ -144,11 +110,9 @@ def mapimage(coords, zoom=15,size=(TS,TS)):
 #        url = link(c,zoom)
         size = (len(lontiles)*TS,len(lattiles)*TS)
         grid = Image.new("RGB", size, None)
-        img = []
         for yi, y in enumerate(lattiles):
             for xi, x in enumerate(lontiles):
                 url = tile(x,y,zoom)
-#                print url
                 time.sleep(1)
                 request, content = h.request(url)
                 img = Image.open(StringIO(content))
@@ -161,7 +125,70 @@ def mapimage(coords, zoom=15,size=(TS,TS)):
         mark(grid, (xp,yp))
         gridc = grid.crop((xp-TS/2,yp-TS/2,xp+TS/2,yp+TS/2))
         gridc.save(filename)
-    else:
+
+    def db_xml(self):
+        img = encode(self.latitude, self.longitude)+'.png'
+        phr = "geo:"+str(self.latitude)+","+str(self.longitude)
+
+        db = ElementMaker(namespace=const.DB_NS, nsmap=const.NSMAP)
+        uri = db.uri(db.link(
+                db.inlinemediaobject(
+                    db.imageobject(db.imagedata(
+                            fileref=img,
+                            format='PNG'))
+                    db.textobject(db.phrase(phr))
+                    ),
+                db.para(self.dms())
+                **{const.XLINK+"href": self.osmlink()}))
+        return uri
+
+
+class Address(object):
+    """Address object to contain everything known about an address"""
+    def __init__(self,address):
+        self._address_string = address
+        self._coord = None
+
+    def geocode(self,country=None):
+        params = { 'q': self._address_string,
+                   'addressdetails': 1,
+                   'limit': 1,
+                   'format': 'xml',
+                   'polygon': 0 }
+
+        if country:
+            params['countrycodes'] = country
+
+        base_url = 'http://nominatim.openstreetmap.org/search?%s'
+        url = base_url % urllib.urlencode(params)
+        resp, content = h.request(url)
+        root = etree.fromstring(content)
+        place = root.find("place")
+        if place is not None:
+            print (etree.tostring(root, pretty_print=True))
+            self._coord=Coord(place.get("lat"),place.get("lon"))
+            return 1
+        else:
+            print resp
+            print content
+            return 0
+
+    def db_xml(self):
+        return self._coord.db_xml()
+
+
+def distance(p1, p2):
+    res = Geodesic.WGS84.Inverse(p1[0], p1[1], p2[0], p2[1])
+    return res['s12']
+
+def mark(image, coord):
+    draw = ImageDraw.Draw(image)
+    x, y = coord
+    r = 5
+    bbox = (x-r, y-r, x+r, y+r)
+    draw.ellipse(bbox, outline="red")
+
+def mapimages(coords, zoom=15,size=(TS,TS)):
         minlat = 1000
         maxlat = 0
         minlon = 1000