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
 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 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
 
 # EC Equator lenght
 EC = 40075016.686 # meter
@@ -21,101 +23,65 @@ ZOOMRANGE = range(1, 18)
 # tile size
 TS = 256
 
 # tile size
 TS = 256
 
-
 h = Http(".cache")
 
 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
         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)
 #        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)
         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))
                 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)
         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
         minlat = 1000
         maxlat = 0
         minlon = 1000