Re-integrating index data requests

Start working on re-integrating the SQL queries to feed the index (not
functional right now).

Signed-off-by: Maxime Petazzoni <maxime.petazzoni@bulix.org>
stable
Maxime Petazzoni 2010-08-07 09:49:12 +02:00
rodzic c0e5d094dd
commit 7b1e07d292
2 zmienionych plików z 160 dodań i 72 usunięć

Wyświetl plik

@ -222,7 +222,7 @@ class OCitySMap:
_regexp_polygon = re.compile('^POLYGON\(\(([^)]*)\)\)$')
def _get_shade_wkt(self, bounding_box, osmid):
def _get_osmid_area(self, osmid):
l.info('Looking for contour around OSM ID %d...' % osmid)
cursor = self._db.cursor()
cursor.execute("""select st_astext(st_transform(st_buildarea(way), 4002))
@ -237,9 +237,10 @@ class OCitySMap:
l.error('Invalid database structure!')
return None
if not polygon:
return None
return polygon
def _get_shade_wkt(self, bounding_box, polygon):
"""..."""
matches = self._regexp_polygon.match(polygon)
if not matches:
l.error('Administrative boundary looks invalid!')
@ -309,27 +310,34 @@ class OCitySMap:
renderer.create_map_canvas()
if config.osmid:
shade_wkt = self._get_shade_wkt(
renderer.canvas.get_actual_bounding_box(),
config.osmid)
renderer.render_shade(shade_wkt)
polygon = self._get_osmid_area(config.osmid)
if polygon:
shade_wkt = self._get_shade_wkt(
renderer.canvas.get_actual_bounding_box(),
polygon)
renderer.render_shade(shade_wkt)
else:
polygon = None
renderer.canvas.render()
street_index = index.StreetIndex(config.osmid,
street_index = index.StreetIndex(self._db, config.osmid,
renderer.canvas.get_actual_bounding_box(),
self._i18n, renderer.grid)
self._i18n, renderer.grid,
polygon)
street_index_renderer = index.StreetIndexRenderer(self._i18n, [], [])
try:
for output_format in output_formats:
output_filename = '%s.%s' % (file_prefix, output_format)
self._render_one(renderer, street_index, output_filename,
output_format)
self._render_one(renderer, street_index_renderer,
output_filename, output_format)
# TODO: street_index.as_csv()
finally:
self._cleanup_tempdir(tmpdir)
def _render_one(self, renderer, street_index, filename, output_format):
def _render_one(self, renderer, street_index_renderer, filename, output_format):
l.info('Rendering %s...' % filename)
factory = None
@ -362,8 +370,9 @@ class OCitySMap:
'Unsupported output format: %s!' % output_format.upper()
surface = factory(renderer.paper_width_pt, renderer.paper_height_pt)
rs = renderer.create_rendering_session(surface, street_index, dpi)
renderer.render(rs)
# rs = renderer.create_rendering_session(surface, street_index, dpi)
# renderer.render(rs)
street_index_renderer.render(surface, 50, 50, 1000, 1000, 'height', 'top')
if output_format == 'png':
surface.write_to_png(filename)
@ -383,4 +392,4 @@ if __name__ == '__main__':
c.paper_height_mm = 297
c.stylesheet = o.get_stylesheet_by_name('Default')
o.render(c, 'plain', ['png', 'pdf'], '/tmp/mymap')
o.render(c, 'plain', ['pdf'], '/tmp/mymap')

Wyświetl plik

@ -23,15 +23,19 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import cairo
import logging
import math
import pango
import pangocairo
import random # TODO: remove
import string
import coords
import grid
l = logging.getLogger('ocitysmap')
class IndexEmptyError(Exception):
pass
class IndexDoesNotFitError(Exception):
pass
@ -166,19 +170,15 @@ class IndexItem:
line_end - line_start - fheight/2)
ctx.restore()
class StreetIndex:
class StreetIndexRenderer:
"""
The StreetIndex class encapsulate all the logic related to the querying and
rendering of the street index.
"""
def __init__(self, osmid, bounding_box, i18n, grid):
self._osmid = osmid
self._bbox = bounding_box
def __init__(self, i18n, streets, amenities):
self._i18n = i18n
self._grid = grid
self._data = self._get_streets() + self._get_amenities()
self._data = streets + amenities
self._label_fd = pango.FontDescription('DejaVu')
self._header_fd = pango.FontDescription('Georgia Bold')
@ -210,6 +210,8 @@ class StreetIndex:
alignment not in ('left', 'right'))):
raise ValueError, 'Incompatible freedom direction and alignment!'
if not self._data:
raise IndexEmptyError
ctx = cairo.Context(surface)
ctx.move_to(x, y)
@ -247,25 +249,19 @@ class StreetIndex:
print "index: (%d x %d)" % (index_width, index_height)
print
if alignment == 'top':
base_offset_x = 0
base_offset_y = 0
elif alignment == 'bottom':
base_offset_x = 0
base_offset_x = 0
base_offset_y = 0
if alignment == 'bottom':
base_offset_y = h - index_height
elif alignment == 'left':
base_offset_x = 0
base_offset_y = 0
elif alignment == 'right':
if alignment == 'right':
base_offset_x = w - index_width
base_offset_y = 0
if not self._i18n.isrtl():
delta_x = column_width
offset_x = 0
else:
delta_x = - column_width
offset_x = w + delta_x
offset_x = index_width + delta_x
offset_y = 0
for category in self._data:
@ -292,37 +288,7 @@ class StreetIndex:
offset_y += label_fheight
ctx.save()
ctx.rectangle(x, y, w, h)
ctx.stroke()
ctx.restore()
ctx.save()
ctx.set_source_rgba(1.0, 0.0, 0.0, 0.3)
ctx.rectangle(x + base_offset_x, y + base_offset_y,
index_width, index_height)
ctx.fill()
ctx.restore()
# return new_x, new_y, new_w, new_h
def as_csv(self, fobj):
"""Saves the street index as CSV to the provided file object."""
# TODO: write to CSV
raise NotImplementedError
def _get_streets(self):
streets = []
for i in ['A', 'B', 'C', 'D', 'E', 'Schools', 'Public buildings']:
streets.append(IndexCategory(i,
[IndexItem(l,s) for l,s in
[(''.join(random.choice(string.letters) for i in xrange(random.randint(1, 10))), 'A1')]*4]))
return streets
def _get_amenities(self):
return []
return base_offset_x, base_offset_y, index_width, index_height
def _create_layout_with_font(self, pc, font_desc):
layout = pc.create_layout()
@ -456,24 +422,137 @@ class StreetIndex:
raise ValueError, 'Invalid freedom direction!'
class StreetIndex:
def __init__(self, db, osmid, bounding_box, i18n, grid, polygon):
self._db = db
self._osmid = osmid
self._bounding_box = bounding_box
self._i18n = i18n
self._grid = grid
self._polygon = polygon
def _humanize_street_label(self, street):
return (self._i18n.user_readable_street(street[0]),
self._user_readable_label(street[1]))
def _humanize_street_list(self, sl):
"""Given a list of street and their corresponding squares, do some
cleanup and pass it through the internationalization layer to
get proper sorting, filtering of common prefixes, etc.
Args:
sl (list): list of streets, each in the form [(name, squares)].
Returns the humanized street list.
"""
# We transform the string representing the squares list into a
# Python list
sl = [(street[0],
[map(int, x.split(',')) for x in street[1].split(';')[:-1]])
for street in sl]
# Street prefixes are postfixed, a human readable label is
# built to represent the list of squares, and the list is
# alphabetically-sorted.
prev_locale = locale.getlocale(locale.LC_COLLATE)
locale.setlocale(locale.LC_COLLATE, self._i18n.language_code())
try:
sl = sorted(map(self._humanize_street_label, sl),
lambda x, y: locale.strcoll(x[0].lower(), y[0].lower()))
finally:
locale.setlocale(locale.LC_COLLATE, prev_locale)
result = []
first_letter = None
current_category = None
for street in sl:
if not self._i18n.first_letter_equal(street[0][0], first_letter):
current_category = IndexCategory(street[0])
result.append(current_category)
current_category.items.append(IndexItem(street[0], street[1]))
return result
def get_streets(self):
"""Get the list of streets in the administrative area if city is
defined or in the bounding box otherwise, and for each
street, the list of squares that it intersects.
Returns a list of the form [(street_name, 'A-B1'),
(street2_name, 'B3')]
"""
cursor = self._db.cursor()
l.info("Getting streets...")
intersect = 'true'
if self._polygon:
intersect = """st_intersects(way, st_transform(
GeomFromText('%s', 4002), 900913))""" % self._polygon
cursor.execute("""select name, textcat_all(x || ',' || y || ';')
from (select distinct name, x, y
from planet_osm_line
join %s
on st_intersects(way, st_transform(geom, 900913))
where trim(name) != '' and highway is not null
and %s)
as foo
group by name
order by name;""" % \
(self._map_areas_table_name,
intersect))
sl = cursor.fetchall()
l.debug("Got streets (%d)." % len(sl))
return self.humanize_street_list(sl)
if __name__ == '__main__':
import random
import string
random.seed(42)
bbox = coords.BoundingBox(48.8162, 2.3417, 48.8063, 2.3699)
grid = grid.Grid(bbox)
surface = cairo.PDFSurface('/tmp/index.pdf', 1000, 1000)
class i18nMock:
def __init__(self, rtl):
self.rtl = rtl
def isrtl(self):
return False
return self.rtl
index = StreetIndex(None, bbox, i18nMock(), grid)
index.render(surface, 50, 50, 800, 520, 'height', 'top')
margin = 50
width = 800
height = 500
streets = []
for i in ['A', 'B', 'C', 'D', 'E', 'Schools', 'Public buildings']:
streets.append(IndexCategory(i, [IndexItem(l,s) for l,s in
[(''.join(random.choice(string.letters) for i in xrange(random.randint(1, 10))), 'A1')]*4]))
index = StreetIndexRenderer(i18nMock(False), streets, [])
index.render(surface, 50, 50, width, height, 'height', 'top')
surface.show_page()
index.render(surface, 50, 50, 800, 520, 'height', 'bottom')
index.render(surface, 50, 50, width, height, 'height', 'bottom')
surface.show_page()
index.render(surface, 50, 50, 800, 520, 'width', 'left')
index.render(surface, 50, 50, width, height, 'width', 'left')
surface.show_page()
index.render(surface, 50, 50, 800, 520, 'width', 'right')
index.render(surface, 50, 50, width, height, 'width', 'right')
surface.show_page()
index = StreetIndexRenderer(i18nMock(True), streets, [])
index.render(surface, 50, 50, width, height, 'height', 'top')
surface.show_page()
index.render(surface, 50, 50, width, height, 'height', 'bottom')
surface.show_page()
index.render(surface, 50, 50, width, height, 'width', 'left')
surface.show_page()
index.render(surface, 50, 50, width, height, 'width', 'right')
surface.finish()