Пример #1
0
  // Returns the tile for zoom which covers given lat/lon coordinates"
  private static Tile latLonToTile(
      final double lat,
      final double lon,
      final int zoom,
      final int tilesize,
      final boolean excludeEdge) {
    final Pixel p = latLonToPixels(lat, lon, zoom, tilesize);

    if (excludeEdge) {
      TMSUtils.Tile tile = TMSUtils.pixelsToTile(p.px, p.py, tilesize);
      final TMSUtils.Tile t = TMSUtils.pixelsToTile(p.px - 1, p.py - 1, tilesize);

      // lon is on an x tile boundary, so we'll move it to the left
      if (t.tx < tile.tx) {
        tile = new TMSUtils.Tile(t.tx, tile.ty);
      }

      // lat is on a y tile boundary, so we'll move it down
      if (t.ty < tile.ty) {
        tile = new TMSUtils.Tile(tile.tx, t.ty);
      }

      return tile;
    }

    return pixelsToTile(p.px, p.py, tilesize);
  }
  @Test
  @Category(IntegrationTest.class)
  public void testGetOneWorker() throws Exception {
    // find a small enough tile bounds to 4 tiles
    TileBounds tb = new TileBounds(2764, 1365, 2765, 1366);
    Bounds bounds = TMSUtils.tileToBounds(tb, zoomLevel, tileSize);
    TiledInputFormatContext ifContext =
        new TiledInputFormatContext(
            zoomLevel,
            tileSize,
            new HashSet<String>(),
            bounds.convertNewToOldBounds(),
            new Properties());
    ifContext.save(conf);

    int numWorkers = CostDistanceWorkersConfiguration.getNumWorkers(metadata, conf);
    Assert.assertEquals(1, numWorkers);
  }
  @Test(expected = IllegalArgumentException.class)
  @Category(IntegrationTest.class)
  public void testMoreWorkersThanMapSlots() throws Exception {
    HadoopUtils.setupLocalRunner(conf);

    // find a large enough tile bounds
    TileBounds tb = new TileBounds(2764, 1365, 2878, 1479);
    Bounds bounds = TMSUtils.tileToBounds(tb, zoomLevel, tileSize);
    TiledInputFormatContext ifContext =
        new TiledInputFormatContext(
            zoomLevel,
            tileSize,
            new HashSet<String>(),
            bounds.convertNewToOldBounds(),
            new Properties());
    ifContext.save(conf);

    CostDistanceWorkersConfiguration.getNumWorkers(metadata, conf);
  }
  @Test
  @Category(IntegrationTest.class)
  public void testHardCodedWorkers() throws Exception {
    final int numExpectedWorkers = 5;
    MrGeoProperties.getInstance().setProperty("giraph.workers", String.valueOf(numExpectedWorkers));

    // find a large enough tile bounds
    TileBounds tb = new TileBounds(2764, 1365, 2878, 1479);
    Bounds bounds = TMSUtils.tileToBounds(tb, zoomLevel, tileSize);
    TiledInputFormatContext ifContext =
        new TiledInputFormatContext(
            zoomLevel,
            tileSize,
            new HashSet<String>(),
            bounds.convertNewToOldBounds(),
            new Properties());
    ifContext.save(conf);

    int numWorkers = CostDistanceWorkersConfiguration.getNumWorkers(metadata, conf);
    Assert.assertEquals(numExpectedWorkers, numWorkers);
    MrGeoProperties.getInstance().remove("giraph.workers");
  }
  // tests that numTiles is correctly computed - I had an off-by-one error due to assuming that
  // boundsToTile returns tile boundaries where the upper right is exclusive instead of inclusive
  @Test
  @Category(IntegrationTest.class)
  public void testNumTiles() throws Exception {
    conf.set("mapred.child.java.opts", "-Xmx2048M");
    conf.setInt("io.sort.mb", 100);

    // find a large enough tile bounds
    TileBounds tb = new TileBounds(50, 100, 1000, 100);
    Bounds bounds = TMSUtils.tileToBounds(tb, zoomLevel, tileSize);
    TiledInputFormatContext ifContext =
        new TiledInputFormatContext(
            zoomLevel,
            tileSize,
            new HashSet<String>(),
            bounds.convertNewToOldBounds(),
            new Properties());
    ifContext.save(conf);

    int numWorkers =
        CostDistanceWorkersConfiguration.getNumWorkers(
            metadata, conf, false /* disable map slots check */);
    Assert.assertEquals(4, numWorkers);
  }
Пример #6
0
 // Converts lat/lon bounds to the correct tile bounds, in lat/lon for a zoom level
 public static Bounds tileBounds(
     final TMSUtils.Bounds bounds, final int zoom, final int tilesize) {
   final TMSUtils.TileBounds tb = TMSUtils.boundsToTile(bounds, zoom, tilesize);
   return TMSUtils.tileToBounds(tb, zoom, tilesize);
 }
Пример #7
0
  public static Tile calculateTile(
      final Tile tile, final int srcZoom, final int dstZoom, final int tilesize) {
    final TMSUtils.Bounds bounds = TMSUtils.tileBounds(tile.tx, tile.ty, srcZoom, tilesize);

    return TMSUtils.latLonToTile(bounds.s, bounds.w, dstZoom, tilesize);
  }
Пример #8
0
  /**
   * BoundsCropper takes an image (actually, its metadata), a list of user bounds to crop, and a
   * zoom level, and gives back the metadata corresponding to the cropped image with the maximum
   * zoom level set to the one provided.
   *
   * <p>Additional details:
   *
   * <p>If there is only one user bounds, then the cropped image bounds corresponds to that
   * singleton bounds. If there is a list of user bounds, then the cropped image bounds corresponds
   * to an envelope around the list of user bounds.
   *
   * <p>The new image bounds are computed from the old using the following two transformations -
   * first, the user bounds are capped to the nearest tile boundaries. - second, the bounds from
   * above are then intersected with the original image boundaries
   *
   * <p>The new tile bounds are computed from the new image bounds.
   *
   * <p>If the user bounds are outside the image bounds (i.e., they have no overlap), then an
   * exception is thrown
   *
   * <p>If the provided zoom level is different from the maximum zoom level in the input metadata,
   * then care is taken to set the maximum zoom level of the returned data to the provided zoom
   * level.
   *
   * @param origMetadata
   * @param userBounds
   * @param zoomLevel
   * @return
   */
  public static MrsPyramidMetadata getCroppedMetadata(
      MrsPyramidMetadata origMetadata, List<Bounds> userBounds, int zoomLevel) {

    double minX = Double.POSITIVE_INFINITY, minY = Double.POSITIVE_INFINITY;
    double maxX = Double.NEGATIVE_INFINITY, maxY = Double.NEGATIVE_INFINITY;

    // if there is a list of user bounds, find the envelope surrounding it
    for (Bounds bounds : userBounds) {
      if (bounds.w < minX) minX = bounds.w;
      if (bounds.s < minY) minY = bounds.s;
      if (bounds.e > maxX) maxX = bounds.e;
      if (bounds.n > maxY) maxY = bounds.n;
    }

    Bounds cropBounds = new Bounds(minX, minY, maxX, maxY);

    // now cap it to the nearest outside tile boundaries
    Bounds cropTileBounds = TMSUtils.tileBounds(cropBounds, zoomLevel, origMetadata.getTilesize());

    // get the original image bounds
    Bounds imageBounds = Bounds.convertOldToNewBounds(origMetadata.getBounds());

    // complain if the user bounds has no overlap with
    if (!imageBounds.intersect(cropTileBounds)) {
      throw new IllegalArgumentException(
          String.format(
              "Oops - cropped bounds and image bounds "
                  + "do not overlap: cropped bounds=%s, image bounds=%s",
              cropTileBounds, imageBounds));
    }

    // now find the intersection of the cropped bounds and image bounds - this becomes the new
    // image bounds
    Bounds newImageBounds =
        new Bounds(
            Math.max(cropTileBounds.w, imageBounds.w),
            Math.max(cropTileBounds.s, imageBounds.s),
            Math.min(cropTileBounds.e, imageBounds.e),
            Math.min(cropTileBounds.n, imageBounds.n));

    // find the tile bounds corresponding to the new image bounds - this becomes the new tile bounds
    TMSUtils.TileBounds newTileBounds =
        TMSUtils.boundsToTile(newImageBounds, zoomLevel, origMetadata.getTilesize());

    final TMSUtils.Pixel lowerPx =
        TMSUtils.latLonToPixels(
            newImageBounds.s, newImageBounds.w, zoomLevel, origMetadata.getTilesize());
    final TMSUtils.Pixel upperPx =
        TMSUtils.latLonToPixels(
            newImageBounds.n, newImageBounds.e, zoomLevel, origMetadata.getTilesize());

    final LongRectangle pixelBounds =
        new LongRectangle(0, 0, upperPx.px - lowerPx.px, upperPx.py - lowerPx.py);

    // time to create the new metadata
    MrsPyramidMetadata croppedMetadata = new MrsPyramidMetadata();
    croppedMetadata.setPyramid(origMetadata.getPyramid());
    croppedMetadata.setBounds(Bounds.convertNewToOldBounds(newImageBounds));
    croppedMetadata.setTilesize(origMetadata.getTilesize());
    croppedMetadata.setTileType(origMetadata.getTileType());
    croppedMetadata.setBands(1);
    croppedMetadata.setDefaultValues(origMetadata.getDefaultValues());
    // max zoom should be input zoom not origMetadata.getMaxZoomLevel
    croppedMetadata.setMaxZoomLevel(zoomLevel);
    croppedMetadata.setName(zoomLevel, "" + zoomLevel);
    croppedMetadata.setTileBounds(zoomLevel, TileBounds.convertToLongRectangle(newTileBounds));
    croppedMetadata.setPixelBounds(zoomLevel, pixelBounds);
    croppedMetadata.setProtectionLevel(origMetadata.getProtectionLevel());
    return croppedMetadata;
  }