def __init__(self, db, rc, tmpdir, dpi, file_prefix, index_position="side"): """ Create the renderer. Args: rc (RenderingConfiguration): rendering parameters. tmpdir (os.path): Path to a temp dir that can hold temp files. index_position (str): None or 'side' (index on side), 'bottom' (index at bottom). """ Renderer.__init__(self, db, rc, tmpdir, dpi) # Prepare the index self.street_index = StreetIndex(db, rc.polygon_wkt, rc.i18n) if not self.street_index.categories: LOG.warning("Designated area leads to an empty index") self.street_index = None self._grid_legend_margin_pt = min( Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_width_pt, Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_height_pt, ) self._title_margin_pt = 0.05 * self.paper_height_pt self._copyright_margin_pt = 0.02 * self.paper_height_pt self._usable_area_width_pt = self.paper_width_pt - 2 * Renderer.PRINT_SAFE_MARGIN_PT self._usable_area_height_pt = self.paper_height_pt - ( 2 * Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt + self._copyright_margin_pt ) # Prepare the Index (may raise a IndexDoesNotFitError) if index_position and self.street_index and self.street_index.categories: self._index_renderer, self._index_area = self._create_index_rendering(index_position == "side") else: self._index_renderer, self._index_area = None, None # Prepare the layout of the whole page if not self._index_area: # No index displayed self._map_coords = ( Renderer.PRINT_SAFE_MARGIN_PT, (Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt), self._usable_area_width_pt, self._usable_area_height_pt, ) elif index_position == "side": # Index present, displayed on the side if self._index_area.x > Renderer.PRINT_SAFE_MARGIN_PT: # Index on the right -> map on the left self._map_coords = ( Renderer.PRINT_SAFE_MARGIN_PT, (Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt), (self._usable_area_width_pt - self._index_area.w), self._usable_area_height_pt, ) else: # Index on the left -> map on the right self._map_coords = ( self._index_area.x + self._index_area.w, (Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt), (self._usable_area_width_pt - self._index_area.w), self._usable_area_height_pt, ) elif index_position == "bottom": # Index present, displayed at the bottom -> map on top self._map_coords = ( Renderer.PRINT_SAFE_MARGIN_PT, (Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt), self._usable_area_width_pt, (self._usable_area_height_pt - self._index_area.h), ) else: raise AssertionError("Invalid index position %s" % repr(index_position)) # Prepare the map self._map_canvas = self._create_map_canvas( float(self._map_coords[2]), float(self._map_coords[3]), dpi, rc.osmid is not None # W # H ) # Prepare map overlay if self.rc.overlay: self._overlay_canvas = MapCanvas( self.rc.overlay, self.rc.bounding_box, float(self._map_coords[2]), # W float(self._map_coords[3]), # H dpi, ) # Prepare map overlay if self.rc.overlay: self._overlay_canvas = MapCanvas( self.rc.overlay, self.rc.bounding_box, float(self._map_coords[2]), # W float(self._map_coords[3]), # H dpi, ) # Prepare map overlay if self.rc.overlay: self._overlay_canvas = MapCanvas( self.rc.overlay, self.rc.bounding_box, float(self._map_coords[2]), # W float(self._map_coords[3]), # H dpi, ) # Prepare the grid self.grid = self._create_grid(self._map_canvas, dpi) # Update the street_index to reflect the grid's actual position if self.grid and self.street_index: self.street_index.apply_grid(self.grid) # Dump the CSV street index if self.street_index: self.street_index.write_to_csv(rc.title, "%s.csv" % file_prefix) # Commit the internal rendering stack of the map self._map_canvas.render() if self.rc.overlay: self._overlay_canvas.render()
def __init__(self, db, rc, tmpdir, dpi, file_prefix, index_position = 'side'): """ Create the renderer. Args: rc (RenderingConfiguration): rendering parameters. tmpdir (os.path): Path to a temp dir that can hold temp files. index_position (str): None or 'side' (index on side), 'bottom' (index at bottom). """ Renderer.__init__(self, db, rc, tmpdir, dpi) # Prepare the index self.street_index = StreetIndex(db, rc.polygon_wkt, rc.i18n) if not self.street_index.categories: LOG.warning("Designated area leads to an empty index") self.street_index = None self._grid_legend_margin_pt = \ min(Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_width_pt, Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_height_pt) self._title_margin_pt = 0.05 * self.paper_height_pt self._copyright_margin_pt = 0.02 * self.paper_height_pt self._usable_area_width_pt = (self.paper_width_pt - 2 * Renderer.PRINT_SAFE_MARGIN_PT) self._usable_area_height_pt = (self.paper_height_pt - (2 * Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt + self._copyright_margin_pt)) # Prepare the Index (may raise a IndexDoesNotFitError) if ( index_position and self.street_index and self.street_index.categories ): self._index_renderer, self._index_area \ = self._create_index_rendering(index_position == "side") else: self._index_renderer, self._index_area = None, None # Prepare the layout of the whole page if not self._index_area: # No index displayed self._map_coords = ( Renderer.PRINT_SAFE_MARGIN_PT, ( Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt ), self._usable_area_width_pt, self._usable_area_height_pt ) elif index_position == 'side': # Index present, displayed on the side if self._index_area.x > Renderer.PRINT_SAFE_MARGIN_PT: # Index on the right -> map on the left self._map_coords = ( Renderer.PRINT_SAFE_MARGIN_PT, ( Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt ), ( self._usable_area_width_pt - self._index_area.w ), self._usable_area_height_pt ) else: # Index on the left -> map on the right self._map_coords = ( self._index_area.x + self._index_area.w, ( Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt ), ( self._usable_area_width_pt - self._index_area.w ), self._usable_area_height_pt ) elif index_position == 'bottom': # Index present, displayed at the bottom -> map on top self._map_coords = ( Renderer.PRINT_SAFE_MARGIN_PT, ( Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt ), self._usable_area_width_pt, ( self._usable_area_height_pt - self._index_area.h ) ) else: raise AssertionError("Invalid index position %s" % repr(index_position)) # Prepare the map self._map_canvas = self._create_map_canvas( float(self._map_coords[2]), # W float(self._map_coords[3]), # H dpi ) # Prepare the grid self.grid = self._create_grid(self._map_canvas) # Update the street_index to reflect the grid's actual position if self.grid and self.street_index: self.street_index.apply_grid(self.grid) # Dump the CSV street index if self.street_index: self.street_index.write_to_csv(rc.title, '%s.csv' % file_prefix) # Commit the internal rendering stack of the map self._map_canvas.render()
def __init__(self, db, rc, tmpdir, dpi, file_prefix): Renderer.__init__(self, db, rc, tmpdir, dpi) self._grid_legend_margin_pt = \ min(Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_width_pt, Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_height_pt) # Compute the usable area per page self._usable_area_width_pt = (self.paper_width_pt - (2 * Renderer.PRINT_SAFE_MARGIN_PT)) self._usable_area_height_pt = (self.paper_height_pt - (2 * Renderer.PRINT_SAFE_MARGIN_PT)) scale_denom = Renderer.DEFAULT_SCALE # the mapnik scale depends on the latitude. However we are # always using Mapnik conversion functions (lat,lon <-> # mercator_meters) so we don't need to take into account # latitude in following computations # by convention, mapnik uses 90 ppi whereas cairo uses 72 ppi scale_denom *= float(72) / 90 GRAYED_MARGIN_MM = 10 OVERLAP_MARGIN_MM = 20 # Debug: show original bounding box as JS code # print self.rc.bounding_box.as_javascript("original", "#00ff00") # Convert the original Bounding box into Mercator meters self._proj = mapnik.Projection(coords._MAPNIK_PROJECTION) orig_envelope = self._project_envelope(self.rc.bounding_box) # Extend the bounding box to take into account the lost outter # margin off_x = orig_envelope.minx - (GRAYED_MARGIN_MM * scale_denom) / 1000 off_y = orig_envelope.miny - (GRAYED_MARGIN_MM * scale_denom) / 1000 width = orig_envelope.width() + (2 * GRAYED_MARGIN_MM * scale_denom) / 1000 height = orig_envelope.height() + (2 * GRAYED_MARGIN_MM * scale_denom) / 1000 # Calculate the total width and height of paper needed to # render the geographical area at the current scale. total_width_pt = commons.convert_mm_to_pt( float(width) * 1000 / scale_denom) total_height_pt = commons.convert_mm_to_pt( float(height) * 1000 / scale_denom) self.grayed_margin_pt = commons.convert_mm_to_pt(GRAYED_MARGIN_MM) overlap_margin_pt = commons.convert_mm_to_pt(OVERLAP_MARGIN_MM) # Calculate the number of pages needed in both directions if total_width_pt < self._usable_area_width_pt: nb_pages_width = 1 else: nb_pages_width = \ (float(total_width_pt - self._usable_area_width_pt) / \ (self._usable_area_width_pt - overlap_margin_pt)) + 1 if total_height_pt < self._usable_area_height_pt: nb_pages_height = 1 else: nb_pages_height = \ (float(total_height_pt - self._usable_area_height_pt) / \ (self._usable_area_height_pt - overlap_margin_pt)) + 1 # Round up the number of pages needed so that we have integer # number of pages self.nb_pages_width = int(math.ceil(nb_pages_width)) self.nb_pages_height = int(math.ceil(nb_pages_height)) # Calculate the entire paper area available total_width_pt_after_extension = self._usable_area_width_pt + \ (self._usable_area_width_pt - overlap_margin_pt) * (self.nb_pages_width - 1) total_height_pt_after_extension = self._usable_area_height_pt + \ (self._usable_area_height_pt - overlap_margin_pt) * (self.nb_pages_height - 1) # Convert this paper area available in the number of Mercator # meters that can be rendered on the map total_width_merc = \ commons.convert_pt_to_mm(total_width_pt_after_extension) * scale_denom / 1000 total_height_merc = \ commons.convert_pt_to_mm(total_height_pt_after_extension) * scale_denom / 1000 # Extend the geographical boundaries so that we completely # fill the available paper size. We are careful to extend the # boundaries evenly on all directions (so the center of the # previous boundaries remain the same as the new one) off_x -= (total_width_merc - width) / 2 width = total_width_merc off_y -= (total_height_merc - height) / 2 height = total_height_merc # Calculate what is the final global bounding box that we will render envelope = mapnik.Box2d(off_x, off_y, off_x + width, off_y + height) self._geo_bbox = self._inverse_envelope(envelope) # Debug: show transformed bounding box as JS code # print self._geo_bbox.as_javascript("extended", "#0f0f0f") # Convert the usable area on each sheet of paper into the # amount of Mercator meters we can render in this area. usable_area_merc_m_width = commons.convert_pt_to_mm( self._usable_area_width_pt) * scale_denom / 1000 usable_area_merc_m_height = commons.convert_pt_to_mm( self._usable_area_height_pt) * scale_denom / 1000 grayed_margin_merc_m = (GRAYED_MARGIN_MM * scale_denom) / 1000 overlap_margin_merc_m = (OVERLAP_MARGIN_MM * scale_denom) / 1000 # Calculate all the bounding boxes that correspond to the # geographical area that will be rendered on each sheet of # paper. area_polygon = shapely.wkt.loads(self.rc.polygon_wkt) bboxes = [] self.page_disposition, map_number = {}, 0 for j in reversed(range(0, self.nb_pages_height)): col = self.nb_pages_height - j - 1 self.page_disposition[col] = [] for i in range(0, self.nb_pages_width): cur_x = off_x + i * (usable_area_merc_m_width - overlap_margin_merc_m) cur_y = off_y + j * (usable_area_merc_m_height - overlap_margin_merc_m) envelope = mapnik.Box2d(cur_x, cur_y, cur_x + usable_area_merc_m_width, cur_y + usable_area_merc_m_height) envelope_inner = mapnik.Box2d( cur_x + grayed_margin_merc_m, cur_y + grayed_margin_merc_m, cur_x + usable_area_merc_m_width - grayed_margin_merc_m, cur_y + usable_area_merc_m_height - grayed_margin_merc_m) inner_bb = self._inverse_envelope(envelope_inner) if not area_polygon.disjoint( shapely.wkt.loads(inner_bb.as_wkt())): self.page_disposition[col].append(map_number) map_number += 1 bboxes.append((self._inverse_envelope(envelope), inner_bb)) else: self.page_disposition[col].append(None) # Debug: show per-page bounding boxes as JS code # for i, (bb, bb_inner) in enumerate(bboxes): # print bb.as_javascript(name="p%d" % i) self.pages = [] # Create an overview map overview_bb = self._geo_bbox.create_expanded(0.001, 0.001) # Create the overview grid self.overview_grid = OverviewGrid( overview_bb, [bb_inner for bb, bb_inner in bboxes], self.rc.i18n.isrtl()) grid_shape = self.overview_grid.generate_shape_file( os.path.join(self.tmpdir, 'grid_overview.shp')) # Create a canvas for the overview page self.overview_canvas = MapCanvas(self.rc.stylesheet, overview_bb, self._usable_area_width_pt, self._usable_area_height_pt, dpi, extend_bbox_to_ratio=True) # Create the gray shape around the overview map exterior = shapely.wkt.loads(self.overview_canvas.get_actual_bounding_box()\ .as_wkt()) interior = shapely.wkt.loads(self.rc.polygon_wkt) shade_wkt = exterior.difference(interior).wkt shade = maplib.shapes.PolyShapeFile( self.rc.bounding_box, os.path.join(self.tmpdir, 'shape_overview.shp'), 'shade-overview') shade.add_shade_from_wkt(shade_wkt) self.overview_canvas.add_shape_file(shade) self.overview_canvas.add_shape_file(grid_shape, self.rc.stylesheet.grid_line_color, 1, self.rc.stylesheet.grid_line_width) self.overview_canvas.render() # Create the map canvas for each page indexes = [] for i, (bb, bb_inner) in enumerate(bboxes): # Create the gray shape around the map exterior = shapely.wkt.loads(bb.as_wkt()) interior = shapely.wkt.loads(bb_inner.as_wkt()) shade_wkt = exterior.difference(interior).wkt shade = maplib.shapes.PolyShapeFile( bb, os.path.join(self.tmpdir, 'shade%d.shp' % i), 'shade%d' % i) shade.add_shade_from_wkt(shade_wkt) # Create the contour shade # Area to keep visible interior_contour = shapely.wkt.loads(self.rc.polygon_wkt) # Determine the shade WKT shade_contour_wkt = interior.difference(interior_contour).wkt # Prepare the shade SHP shade_contour = maplib.shapes.PolyShapeFile( bb, os.path.join(self.tmpdir, 'shade_contour%d.shp' % i), 'shade_contour%d' % i) shade_contour.add_shade_from_wkt(shade_contour_wkt) # Create one canvas for the current page map_canvas = MapCanvas(self.rc.stylesheet, bb, self._usable_area_width_pt, self._usable_area_height_pt, dpi, extend_bbox_to_ratio=False) # Create canvas for overlay on current page overla_canvas = None if self.rc.overlay: overlay_canvas = MapCanvas(self.rc.overlay, bb, self._usable_area_width_pt, self._usable_area_height_pt, dpi, extend_bbox_to_ratio=False) # Create the grid map_grid = Grid(bb_inner, map_canvas.get_actual_scale(), self.rc.i18n.isrtl()) grid_shape = map_grid.generate_shape_file( os.path.join(self.tmpdir, 'grid%d.shp' % i)) map_canvas.add_shape_file(shade) map_canvas.add_shape_file(shade_contour, self.rc.stylesheet.shade_color_2, self.rc.stylesheet.shade_alpha_2) map_canvas.add_shape_file(grid_shape, self.rc.stylesheet.grid_line_color, self.rc.stylesheet.grid_line_alpha, self.rc.stylesheet.grid_line_width) map_canvas.render() if overlay_canvas: overlay_canvas.render() self.pages.append((map_canvas, map_grid, overlay_canvas)) # Create the index for the current page inside_contour_wkt = interior_contour.intersection(interior).wkt index = StreetIndex(self.db, inside_contour_wkt, self.rc.i18n, page_number=(i + 4)) index.apply_grid(map_grid) indexes.append(index) # Merge all indexes self.index_categories = self._merge_page_indexes(indexes) # Prepare the small map for the front page self._front_page_map = self._prepare_front_page_map(dpi)
def __init__(self, rc, tmpdir, street_index = None, index_position = 'side'): """ Create the renderer. Args: rc (RenderingConfiguration): rendering parameters. tmpdir (os.path): Path to a temp dir that can hold temp files. street_index (StreetIndex): None or the street index object. index_position (str): None or 'side' (index on side), 'bottom' (index at bottom). """ Renderer.__init__(self, rc, tmpdir, street_index) self._grid_legend_margin_pt = \ min(Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_width_pt, Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_height_pt) self._title_margin_pt = 0.05 * self.paper_height_pt self._copyright_margin_pt = 0.02 * self.paper_height_pt self._usable_area_width_pt = (self.paper_width_pt - 2 * Renderer.PRINT_SAFE_MARGIN_PT) self._usable_area_height_pt = (self.paper_height_pt - (2 * Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt + self._copyright_margin_pt)) # Prepare the Index (may raise a IndexDoesNotFitError) if ( index_position and self.street_index and self.street_index.categories ): self._index_renderer, self._index_area \ = self._create_index_rendering(index_position == "side") else: self._index_renderer, self._index_area = None, None # Prepare the layout of the whole page if not self._index_area: # No index displayed self._map_coords = ( Renderer.PRINT_SAFE_MARGIN_PT, ( Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt ), self._usable_area_width_pt, self._usable_area_height_pt ) elif index_position == 'side': # Index present, displayed on the side if self._index_area.x > Renderer.PRINT_SAFE_MARGIN_PT: # Index on the right -> map on the left self._map_coords = ( Renderer.PRINT_SAFE_MARGIN_PT, ( Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt ), ( self._usable_area_width_pt - self._index_area.w ), self._usable_area_height_pt ) else: # Index on the left -> map on the right self._map_coords = ( self._index_area.x + self._index_area.w, ( Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt ), ( self._usable_area_width_pt - self._index_area.w ), self._usable_area_height_pt ) elif index_position == 'bottom': # Index present, displayed at the bottom -> map on top self._map_coords = ( Renderer.PRINT_SAFE_MARGIN_PT, ( Renderer.PRINT_SAFE_MARGIN_PT + self._title_margin_pt ), self._usable_area_width_pt, ( self._usable_area_height_pt - self._index_area.h ) ) else: raise AssertionError("Invalid index position %s" % repr(index_position)) # Prepare the map self._map_canvas = self._create_map_canvas( (float(self._map_coords[2]), float(self._map_coords[3])) ) # H # Prepare the grid self.grid = self._create_grid(self._map_canvas) # Commit the internal rendering stack of the map self._map_canvas.render()
def __init__(self, db, rc, tmpdir, dpi, file_prefix): Renderer.__init__(self, db, rc, tmpdir, dpi) self._grid_legend_margin_pt = \ min(Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_width_pt, Renderer.GRID_LEGEND_MARGIN_RATIO * self.paper_height_pt) # Compute the usable area per page self._usable_area_width_pt = (self.paper_width_pt - (2 * Renderer.PRINT_SAFE_MARGIN_PT)) self._usable_area_height_pt = (self.paper_height_pt - (2 * Renderer.PRINT_SAFE_MARGIN_PT)) scale_denom = Renderer.DEFAULT_SCALE # the mapnik scale depends on the latitude. However we are # always using Mapnik conversion functions (lat,lon <-> # mercator_meters) so we don't need to take into account # latitude in following computations # by convention, mapnik uses 90 ppi whereas cairo uses 72 ppi scale_denom *= float(72) / 90 GRAYED_MARGIN_MM = 10 OVERLAP_MARGIN_MM = 20 # Debug: show original bounding box as JS code # print self.rc.bounding_box.as_javascript("original", "#00ff00") # Convert the original Bounding box into Mercator meters self._proj = mapnik.Projection(coords._MAPNIK_PROJECTION) orig_envelope = self._project_envelope(self.rc.bounding_box) # Extend the bounding box to take into account the lost outter # margin off_x = orig_envelope.minx - (GRAYED_MARGIN_MM * scale_denom) / 1000 off_y = orig_envelope.miny - (GRAYED_MARGIN_MM * scale_denom) / 1000 width = orig_envelope.width() + (2 * GRAYED_MARGIN_MM * scale_denom) / 1000 height = orig_envelope.height() + (2 * GRAYED_MARGIN_MM * scale_denom) / 1000 # Calculate the total width and height of paper needed to # render the geographical area at the current scale. total_width_pt = commons.convert_mm_to_pt(float(width) * 1000 / scale_denom) total_height_pt = commons.convert_mm_to_pt(float(height) * 1000 / scale_denom) self.grayed_margin_pt = commons.convert_mm_to_pt(GRAYED_MARGIN_MM) overlap_margin_pt = commons.convert_mm_to_pt(OVERLAP_MARGIN_MM) # Calculate the number of pages needed in both directions if total_width_pt < self._usable_area_width_pt: nb_pages_width = 1 else: nb_pages_width = \ (float(total_width_pt - self._usable_area_width_pt) / \ (self._usable_area_width_pt - overlap_margin_pt)) + 1 if total_height_pt < self._usable_area_height_pt: nb_pages_height = 1 else: nb_pages_height = \ (float(total_height_pt - self._usable_area_height_pt) / \ (self._usable_area_height_pt - overlap_margin_pt)) + 1 # Round up the number of pages needed so that we have integer # number of pages self.nb_pages_width = int(math.ceil(nb_pages_width)) self.nb_pages_height = int(math.ceil(nb_pages_height)) # Calculate the entire paper area available total_width_pt_after_extension = self._usable_area_width_pt + \ (self._usable_area_width_pt - overlap_margin_pt) * (self.nb_pages_width - 1) total_height_pt_after_extension = self._usable_area_height_pt + \ (self._usable_area_height_pt - overlap_margin_pt) * (self.nb_pages_height - 1) # Convert this paper area available in the number of Mercator # meters that can be rendered on the map total_width_merc = \ commons.convert_pt_to_mm(total_width_pt_after_extension) * scale_denom / 1000 total_height_merc = \ commons.convert_pt_to_mm(total_height_pt_after_extension) * scale_denom / 1000 # Extend the geographical boundaries so that we completely # fill the available paper size. We are careful to extend the # boundaries evenly on all directions (so the center of the # previous boundaries remain the same as the new one) off_x -= (total_width_merc - width) / 2 width = total_width_merc off_y -= (total_height_merc - height) / 2 height = total_height_merc # Calculate what is the final global bounding box that we will render envelope = mapnik.Box2d(off_x, off_y, off_x + width, off_y + height) self._geo_bbox = self._inverse_envelope(envelope) # Debug: show transformed bounding box as JS code # print self._geo_bbox.as_javascript("extended", "#0f0f0f") # Convert the usable area on each sheet of paper into the # amount of Mercator meters we can render in this area. usable_area_merc_m_width = commons.convert_pt_to_mm(self._usable_area_width_pt) * scale_denom / 1000 usable_area_merc_m_height = commons.convert_pt_to_mm(self._usable_area_height_pt) * scale_denom / 1000 grayed_margin_merc_m = (GRAYED_MARGIN_MM * scale_denom) / 1000 overlap_margin_merc_m = (OVERLAP_MARGIN_MM * scale_denom) / 1000 # Calculate all the bounding boxes that correspond to the # geographical area that will be rendered on each sheet of # paper. area_polygon = shapely.wkt.loads(self.rc.polygon_wkt) bboxes = [] self.page_disposition, map_number = {}, 0 for j in reversed(range(0, self.nb_pages_height)): col = self.nb_pages_height - j - 1 self.page_disposition[col] = [] for i in range(0, self.nb_pages_width): cur_x = off_x + i * (usable_area_merc_m_width - overlap_margin_merc_m) cur_y = off_y + j * (usable_area_merc_m_height - overlap_margin_merc_m) envelope = mapnik.Box2d(cur_x, cur_y, cur_x+usable_area_merc_m_width, cur_y+usable_area_merc_m_height) envelope_inner = mapnik.Box2d(cur_x + grayed_margin_merc_m, cur_y + grayed_margin_merc_m, cur_x + usable_area_merc_m_width - grayed_margin_merc_m, cur_y + usable_area_merc_m_height - grayed_margin_merc_m) inner_bb = self._inverse_envelope(envelope_inner) if not area_polygon.disjoint(shapely.wkt.loads( inner_bb.as_wkt())): self.page_disposition[col].append(map_number) map_number += 1 bboxes.append((self._inverse_envelope(envelope), inner_bb)) else: self.page_disposition[col].append(None) # Debug: show per-page bounding boxes as JS code # for i, (bb, bb_inner) in enumerate(bboxes): # print bb.as_javascript(name="p%d" % i) self.pages = [] # Create an overview map overview_bb = self._geo_bbox.create_expanded(0.001, 0.001) # Create the overview grid self.overview_grid = OverviewGrid(overview_bb, [bb_inner for bb, bb_inner in bboxes], self.rc.i18n.isrtl()) grid_shape = self.overview_grid.generate_shape_file( os.path.join(self.tmpdir, 'grid_overview.shp')) # Create a canvas for the overview page self.overview_canvas = MapCanvas(self.rc.stylesheet, overview_bb, self._usable_area_width_pt, self._usable_area_height_pt, dpi, extend_bbox_to_ratio=True) # Create the gray shape around the overview map exterior = shapely.wkt.loads(self.overview_canvas.get_actual_bounding_box()\ .as_wkt()) interior = shapely.wkt.loads(self.rc.polygon_wkt) shade_wkt = exterior.difference(interior).wkt shade = maplib.shapes.PolyShapeFile(self.rc.bounding_box, os.path.join(self.tmpdir, 'shape_overview.shp'), 'shade-overview') shade.add_shade_from_wkt(shade_wkt) self.overview_canvas.add_shape_file(shade) self.overview_canvas.add_shape_file(grid_shape, self.rc.stylesheet.grid_line_color, 1, self.rc.stylesheet.grid_line_width) self.overview_canvas.render() # Create the map canvas for each page indexes = [] for i, (bb, bb_inner) in enumerate(bboxes): # Create the gray shape around the map exterior = shapely.wkt.loads(bb.as_wkt()) interior = shapely.wkt.loads(bb_inner.as_wkt()) shade_wkt = exterior.difference(interior).wkt shade = maplib.shapes.PolyShapeFile( bb, os.path.join(self.tmpdir, 'shade%d.shp' % i), 'shade%d' % i) shade.add_shade_from_wkt(shade_wkt) # Create the contour shade # Area to keep visible interior_contour = shapely.wkt.loads(self.rc.polygon_wkt) # Determine the shade WKT shade_contour_wkt = interior.difference(interior_contour).wkt # Prepare the shade SHP shade_contour = maplib.shapes.PolyShapeFile(bb, os.path.join(self.tmpdir, 'shade_contour%d.shp' % i), 'shade_contour%d' % i) shade_contour.add_shade_from_wkt(shade_contour_wkt) # Create one canvas for the current page map_canvas = MapCanvas(self.rc.stylesheet, bb, self._usable_area_width_pt, self._usable_area_height_pt, dpi, extend_bbox_to_ratio=False) # Create the grid map_grid = Grid(bb_inner, map_canvas.get_actual_scale(), self.rc.i18n.isrtl()) grid_shape = map_grid.generate_shape_file( os.path.join(self.tmpdir, 'grid%d.shp' % i)) map_canvas.add_shape_file(shade) map_canvas.add_shape_file(shade_contour, self.rc.stylesheet.shade_color_2, self.rc.stylesheet.shade_alpha_2) map_canvas.add_shape_file(grid_shape, self.rc.stylesheet.grid_line_color, self.rc.stylesheet.grid_line_alpha, self.rc.stylesheet.grid_line_width) map_canvas.render() self.pages.append((map_canvas, map_grid)) # Create the index for the current page inside_contour_wkt = interior_contour.intersection(interior).wkt index = StreetIndex(self.db, inside_contour_wkt, self.rc.i18n, page_number=(i + 4)) index.apply_grid(map_grid) indexes.append(index) # Merge all indexes self.index_categories = self._merge_page_indexes(indexes) # Prepare the small map for the front page self._front_page_map = self._prepare_front_page_map(dpi)