X-Git-Url: https://source.tree.se/git?a=blobdiff_plain;f=xinclude%2Faddress.py;h=c99f51ad0e86bca424f21a1d613f77a7d26e268b;hb=676fd9d928d47c787b38ca66011de179ae034beb;hp=fd5fe9664d7d30ff031343129ba796c45c251709;hpb=9326578627f1f3b91de54304713d04078cf2c280;p=treecutter.git diff --git a/xinclude/address.py b/xinclude/address.py index fd5fe96..c99f51a 100755 --- a/xinclude/address.py +++ b/xinclude/address.py @@ -2,15 +2,18 @@ # -*- coding: utf-8 -*- import time +import sys from os import path from httplib2 import Http -import urllib -from math import * +from urllib import urlencode +from math import log,tan,pi,cos,radians,ceil,floor 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,131 +24,189 @@ ZOOMRANGE = range(1, 18) # tile size TS = 256 - h = Http(".cache") -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(self, zoom): + tile = ((self.longitude + 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' - if path.isfile(filename): - if path.getctime(filename) > time.time() - 60*60*24*2: - return + def lattile(self, zoom): + rad = radians(self.latitude) + tile = (1-log(tan(rad)+1/cos(rad))/pi)/2*2**zoom + return tile + + def offset(self,zoom): + x = self.lontile(zoom) + y = self.lattile(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 direct(self, direction, lenght): + point = Geodesic.WGS84.Direct(self.latitude, self.longitude, + direction, length) + return self.__class__(point['lat2'],point['lon2']) + + def png(self,zoom=15,size=(400,150)): + filename = encode(self.latitude, self.longitude)+'.png' +# if path.isfile(filename): +# if path.getctime(filename) > time.time() - 60*60*24*2: +# return im = Image.new("RGB", size, None) - center = (size[0]/2, size[1]/2) - nst = ceil(center[0]-TS/2)/TS - ewt = ceil(center[1]-TS/2)/TS - x, y = offset(co,zoom) - (ns, ew) = coordtile(co,zoom) - if x < TS/2: - e = 1 - w = 0 - if x > TS/2: - e = 0 - w = 1 - if y < TS/2: - n = 1 - s = 0 - if y > TS/2: - n = 0 - s = 1 - ul = (ns-nst-n, ew-ewt-e) - lr = (ns+nst+s, ew+ewt+w) - lattiles = range(int(ul[0]),int(lr[0])+1) - lontiles = range(int(ul[1]),int(lr[1])+1) -# url = link(c,zoom) - size = (len(lontiles)*TS,len(lattiles)*TS) - grid = Image.new("RGB", size, None) - img = [] + + ew = int(self.lontile(zoom)) + ns = int(self.lattile(zoom)) + + (xo, yo) = self.offset(zoom) + et = int(floor((xo - ceil(size[0]/2))/TS)) + nt = int(floor((yo - ceil(size[1]/2))/TS)) + wt = int(floor((xo + ceil(size[0]/2))/TS)) + st = int(floor((yo + ceil(size[1]/2))/TS)) + + lontiles = range(ew+et,ew+wt+1) + lattiles = range(ns+nt,ns+st+1) + imsize = (len(lontiles)*TS,len(lattiles)*TS) + grid = Image.new("RGB", imsize, None) for yi, y in enumerate(lattiles): for xi, x in enumerate(lontiles): - url = tile(x,y,zoom) -# print url - time.sleep(1) + url = 'http://tile.openstreetmap.org/%s/%s/%s.png' % (zoom,x,y) request, content = h.request(url) img = Image.open(StringIO(content)) +# dr = ImageDraw.Draw(img) +# dr.rectangle([0,0,TS,TS], outline=0) box = (xi*TS, yi*TS) grid.paste(img, box) - t = coordtile(co,zoom) - o = offset(co,zoom) - yp = [i for i,x in enumerate(lattiles) if x == int(t[0])][0]*TS+o[1] - xp = [i for i,x in enumerate(lontiles) if x == int(t[1])][0]*TS+o[0] + + yp = [i for i,j in enumerate(lattiles) if j == int(ns)][0]*TS+yo + xp = [i for i,j in enumerate(lontiles) if j == int(ew)][0]*TS+xo mark(grid, (xp,yp)) - gridc = grid.crop((xp-TS/2,yp-TS/2,xp+TS/2,yp+TS/2)) + xc = int(ceil(size[0]/2)) + yc = int(ceil(size[1]/2)) + +# draw = ImageDraw.Draw(grid) +# draw.rectangle([xp-xc,yp-yc,xp+xc,yp+yc], outline="red") + gridc = grid.crop((xp-xc,yp-yc,xp+xc,yp+yc)) gridc.save(filename) - else: + + def db_xml(self): + self.png() + 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)) + ), + self.dms(), + **{const.XLINK+"href": self.osmlink()})) + return uri + + +class Address(object): + """Address object to contain everything known about an address""" + def __init__(self,street=None,postcode=None,city=None,country=None): + self.name = None + self.street = street + self.postcode = postcode + self.city = city + self.country = country + self.phone = '' + self.coord = None + + def geocode(self): + base_url = 'http://nominatim.openstreetmap.org/search?%s' + params = { 'addressdetails': 1, + 'limit': 1, + 'format': 'xml', + 'polygon': 0 } + + if self.country: + t = etree.parse('/usr/share/xml/iso-codes/iso_3166.xml') + r = t.xpath('//iso_3166_entry[@name="'+self.country+'"]') + if len(r)==1: + params['countrycodes'] = r[0].get("alpha_2_code") + + addrlist=[] + if self.name and len(self.name)>0: + addrlist.append(u''+self.name+', '+self.street+', '+self.city) + addrlist.append(u''+self.street+', '+self.postcode+', '+self.city) + addrlist.append(u''+self.street+', '+self.city) + + for addr in addrlist: + params['q'] = addr.encode('utf-8') + url = base_url % urlencode(params) + time.sleep(1) + resp, content = h.request(url) + root = etree.fromstring(content) + places = int(root.xpath('count(//place[@place_id])')) + if places == 1: + place = root.find("place") + self.coord=Coord(place.get("lat"),place.get("lon")) + return + sys.stderr.write(u'FAILURE: Did not find:\n') + sys.stderr.write(addrlist[0].encode('utf-8')) + sys.stderr.write(url) + + def add_phone(self, phone): + self.phone = phone + + def set_name(self, name): + self.name = name + + def db_xml(self): + db = ElementMaker(namespace=const.DB_NS, nsmap=const.NSMAP) + adr = db.address(db.street(self.street), + db.postcode(self.postcode), + db.city(self.city), + db.country(self.country), + db.phone(self.phone), + self.coord.db_xml()) +# type=self.type, + return adr + + +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 @@ -218,3 +279,24 @@ def mapimage(coords, zoom=15,size=(TS,TS)): gridc = grid.crop((xp,yp,xpl,ypl)) gridc.show() # gridc.save("cap-un.png") + +if __name__ == "__main__": + for arg in sys.argv[1:]: + al = arg.split("=") + if al[0] == "lang": + lang = al[1] + if al[0] == "xptr": + argument = al[1].decode('utf-8') + + addrlist = argument.split(',') + addrfmt = "street,postcode,city,country" + adict = addrfmt.split(',') + argdict = dict(zip(adict,addrlist)) + addr = Address(**argdict) + addr.geocode() + axml = addr.db_xml() +# clean_db(axml) + + #print(etree.tostring(cxml, pretty_print=True)) + #sys.stdout.write(out.encode('utf-8')) + sys.stdout.write(etree.tostring(axml,encoding='UTF-8',pretty_print=False))