Пример #1
0
 def __init__(self, x0, y0, x1, y1):
     utils.Assert(IsNumber(x0))
     utils.Assert(IsNumber(y0))
     utils.Assert(IsNumber(x1))
     utils.Assert(IsNumber(y1))
     self.x0 = x0
     self.y0 = y0
     self.x1 = x1
     self.y1 = y1
Пример #2
0
def CalcZoomLevel(log_extent, total_log_extent, pixel_extent):
    """Calculates zoom level.

  We want a zoom level that has enough detail to match the user's request
  (i.e., we do our best not to give stretched-out pixels). A bigger zoom ==
  more pixels + detail. But, it would be wasteful to use a higher zoom
  level than necessary.

  Args:
      log_extent: map-space width, height.
      total_log_extent: total defined map-space extent (size of projection
        bounds, in its output coordinates).
      pixel_extent: desired width, height of the final pixel image.

  Returns:
       zoom level with at least as much detail as required.
  """
    utils.Assert(isinstance(log_extent, geom.Pair))
    utils.Assert(isinstance(total_log_extent, geom.Pair))
    utils.Assert(isinstance(pixel_extent, geom.Pair))

    # Simple, component-wise division.
    fraction_of_total = log_extent / total_log_extent
    total_pixel_extent_needed = pixel_extent / fraction_of_total
    logger.debug("Pixel extent needed %s", str(total_pixel_extent_needed))

    # We want to round the zoom level up; ie, have /at least/ 1 tile pixel
    # per requested pixel.
    # 256 x 2^zoom >= totalpixelextent => zoom = log_2(totalpixelextent / 256)
    x_zoom = int(
        math.log(
            math.ceil(total_pixel_extent_needed.x / float(_TILE_PIXEL_SIZE)),
            2))
    y_zoom = int(
        math.log(
            math.ceil(total_pixel_extent_needed.y / float(_TILE_PIXEL_SIZE)),
            2))

    logger.debug("Zoom:x,y %d, %d", x_zoom, y_zoom)
    zoom = max(x_zoom, y_zoom)
    if _MAX_ZOOM < zoom:
        logger.warning(
            "WHOA; wild zoom (%d - should be max %d), "
            "alert Google. Limiting to %d.", zoom, _MAX_ZOOM, _MAX_ZOOM)
        zoom = _MAX_ZOOM

    return zoom
Пример #3
0
    def AddImage(self, col, row, image):
        """Add an image to this 2D array.

    Args:
        col: x [0..ncols)
        row: y [0..nrows)
        image: the 256x256 tile image to add.
    """
        if not isinstance(image, Image.Image):
            logger.error("Image parameter is not of type Image.Image")
        if not (0 <= col and col < self.ncols):
            logger.error("Column %d out of bounds: 0 - %d", col, self.ncols)
            utils.Assert(False)
        if not (0 <= row and row < self.nrows):
            logger.error("Row %d out of bounds: 0 - %d", row, self.nrows)
            utils.Assert(False)

        self.images[row][col] = image
Пример #4
0
def CalcTileRects(proj, bbox, zoom_level):
    """Tile calculations.

  Args:
      proj: the projection to use.
      bbox: is BBOX, ie desired rectangle in map, aka logical coordinates.
      zoom_level: The zoom level the tiles must come from. For the server.

  Returns:
      tilepixel_rect: The desired tile pixel space rect of our image
        gotten from the server, at a given zoom level. Unscaled; still
        needs to be shrunk (most of the time) to fit the final image.
      rect_of_tiles: <tilepixel_rect> 'rounded out' to whole tiles.
        There's one tile address extra at both the right, and down,
        for cleaner loops.
  """
    utils.Assert(isinstance(bbox, geom.Rect), 'bbox not Rect')

    total_log_rect = proj.internalLogOuterBounds()

    total_tilepixel_length = TotalTilepixelExtent(zoom_level)
    # Is exclusive
    total_tilepixel_rect = geom.Rect(0, 0, total_tilepixel_length,
                                     total_tilepixel_length)
    # flip log because the corners have to correspond, and tiles' 0,0 is
    # upper left, log's -max, -max is lower left.
    mapping = xform.WindowViewportMapping(
        total_log_rect,
        geom.Rect.fromLlAndExtent(
            total_tilepixel_rect.xy0,
            # We leave this exclusive, here, because that acts more like
            # an 'ideal', real-valued rectangle, as our logical rect is
            # pretty much 'ideal' at 4e7 pixels. It matters with
            # more-zoomed-out, -> smaller tilepixel spaces.
            total_tilepixel_rect.Extent()).flippedVertically())
    utils.logger.debug('bbox: %s' % str(bbox))
    tilepixel_rect = mapping.LogRectToPhys(bbox).asInts()

    # TODO: eliminate double flipping.
    if tilepixel_rect.isFlippedVertically():
        tilepixel_rect = tilepixel_rect.flippedVertically()

    utils.logger.debug('tilepixel_rect: %s' % str(tilepixel_rect))

    # A pixel will land somewhere within /some/ tile, and that's
    # the tile we want.
    rect_of_tiles = tilepixel_rect / 256

    utils.logger.debug('rect_of_tiles %s' % str(rect_of_tiles))
    # Tiles and pixels are all 'graphics space', ie origin is upper-left.
    # Make the rects exclusive on the lower right, for looping convenience.
    rect_of_tiles.x1 += 1
    rect_of_tiles.y1 += 1

    utils.logger.debug('high-exclusive rect_of_tiles %s' % str(rect_of_tiles))

    return tilepixel_rect, rect_of_tiles
Пример #5
0
    def LogXYFromlonLat(self, lonlat):
        """Projects the lon, lat point, in degrees, to logical.

    Args:
        lonlat: Pair of lon, lat to be projected.
    Returns:
        Logical point projected from lon, lat.
    """
        utils.Assert(isinstance(lonlat, geom.Pair))
        return geom.Pair(self.MercX(lonlat.x), self.MercY(lonlat.y))
Пример #6
0
    def LonLatFromLogXY(self, log_xy):
        """Inverse projection; log_x/y are scaled to planet_radius.

    Args:
        log_xy: logical point to be 'inverted' (ie find lon, lat).
    Returns:
        Pair of lon, lat.
    """
        utils.Assert(isinstance(log_xy, geom.Pair))

        return geom.Pair(self._Lon(log_xy.x), self._Lat(log_xy.y))
Пример #7
0
    def LonLatFromLogXY(self, log_xy):
        """Inverse projection from the Mercator map coordinates.

    Args:
        log_xy: Pair- point of logical space to be reverse-projected back into
            a lon,lat.
    Returns:
        A Pair of the resulting lon, lat.
    """
        utils.Assert(isinstance(log_xy, geom.Pair))
        return geom.Pair(self._Lon(log_xy.x), self._Lat(log_xy.y))
Пример #8
0
def TotalTilepixelExtent(zoom):
    """Number of pixels on a side, at a given zoom.

  Args:
      zoom: zoom level.
  Returns:
       Whole tilepixel space extent for this zoom level.
       Height == width so, just one number is returned.
  """
    utils.Assert(geom.IsNumber(zoom))
    total = 256 * (2**zoom)
    utils.logger.debug('total pixels:%s' % str(total))
    return total
Пример #9
0
def TotalTilepixelExtent(zoom):
    """Number of pixels on a side, at a given zoom.

  Args:
    zoom: zoom level.
  Returns:
    Whole tilepixel space extent for this zoom level.
    Height == width so, just one number is returned.
  """
    utils.Assert(geom.IsNumber(zoom))

    total = _TILE_PIXEL_SIZE * (2**zoom)
    logger.debug("Total pixels:%d", total)

    return total
Пример #10
0
    def LogPtToPhys(self, log_pt):
        """Find tilepixel space point, of <log_pt>.

    Args:
        log_pt: window point.

    Returns:
        Corresponding viewport, for us tilepixel space, point.
    """
        utils.Assert(isinstance(log_pt, geom.Pair), "logpt is not a geom.Pair")

        phys_x = (log_pt.x * self._logical_to_physical_x_scale +
                  self._physical_x_offset)
        phys_y = (log_pt.y * self._logical_to_physical_y_scale +
                  self._physical_y_offset)

        return geom.Pair(phys_x, phys_y)