TileMap { @SuppressWarnings("NumericCastThatLosesPrecision") @Nonnull public static TileOffset convertLatLonToTileOffset(@Nonnull final GeoPoint point, final int zoomLevel) { final MercatorPoint mercs = MercatorPoint.latLonToMercs(point); assert mercs != null; assert MathUtils.isBetween(mercs.getMercX(), 0.0, 1.0) : mercs.getMercX(); assert MathUtils.isBetween(mercs.getMercY(), 0.0, 1.0) : mercs.getMercY(); final double nrTiles = (1L << zoomLevel); final long tileX = Math.min((long) (nrTiles - 1), (long) Math.floor(mercs.getMercX() * nrTiles)); final long tileY = Math.min((long) (nrTiles - 1), (long) Math.floor(mercs.getMercY() * nrTiles)); final TileKey key = new TileKey(tileX, tileY, zoomLevel); final double deltaMercX = mercs.getMercX() - ((double) tileX / nrTiles); final double deltaMercY = mercs.getMercY() - ((double) tileY / nrTiles); final long nrPixels = Math.round(nrTiles * MapConst.PIXELS_PER_TILE); final int offsetX = (int) Math.min(Math.round(deltaMercX * nrPixels), MapConst.PIXELS_PER_TILE); final int offsetY = (int) Math.min(Math.round(deltaMercY * nrPixels), MapConst.PIXELS_PER_TILE); assert MathUtils.isBetween(offsetX, 0, MapConst.PIXELS_PER_TILE) : offsetX; assert MathUtils.isBetween(offsetY, 0, MapConst.PIXELS_PER_TILE) : offsetY; return new TileOffset(key, offsetX, offsetY); } protected  TileMap(); protected  TileMap(final int bufferColumns, final int bufferRows); @Nullable abstract T getTile(@Nonnull final TileKey key); boolean isCacheEnabled(); void setPreCachingHint(final boolean preCaching); boolean isPreCacheEnabled(); void cacheTile(@Nonnull final TileKey key); @SuppressWarnings("ConstantConditions") void processViewportTiles(
            final int widthPixels, final int heightPixels,
            @Nonnull final GeoPoint mapCenter, final int zoomLevel,
            @Nonnull final ViewportTileProcessor<T> processor); @Nonnull Collection<ViewportTile<T>> collectViewportTiles(
            final int widthPixels, final int heightPixels,
            @Nonnull final GeoPoint mapCenter, final int zoomLevel); @SuppressWarnings("NumericCastThatLosesPrecision") @Nonnull static TileOffset convertLatLonToTileOffset(@Nonnull final GeoPoint point, final int zoomLevel); @Nonnull static GeoPoint convertTileOffsetToLatLon(@Nonnull final TileOffset tileOffset); @Nonnull static GeoPoint convertViewportXYToLatLon(final int posX, final int posY,
                                                     final int width, final int height, final int zoomLevel,
                                                     @Nonnull final GeoPoint mapCenter); @SuppressWarnings("NumericCastThatLosesPrecision") @Nullable static Tuple<Integer, Integer> convertLatLonToViewportXY(
            @Nonnull final GeoPoint point,
            final int width, final int height, final int zoomLevel,
            @Nonnull final GeoPoint mapCenter); @Nonnull static Tuple<Integer, GeoPoint> findZoomLevelAndMapCenter(
            final int width, final int height, final int borderWidth,
            @Nonnull final Collection<GeoPoint> points); @Nonnull static GeoPoint moveLatLonByViewportXY(
            final int deltaX, final int deltaY, final int zoomLevel,
            @Nonnull final GeoPoint mapCenter);  }
@Test public void testConvertLatLonToTileOffset() { LOG.info("testConvertLatLonToTileOffset"); Assert.assertEquals(new TileOffset(new TileKey(2, 2, 2), 0, 0), TileMap.convertLatLonToTileOffset(new GeoPoint(0.0, 0.0), 2)); Assert.assertEquals(new TileOffset(new TileKey(2, 0, 2), 0, 2), TileMap.convertLatLonToTileOffset(new GeoPoint(90.0, 0.0), 2)); Assert.assertEquals(new TileOffset(new TileKey(3, 2, 2), MapConst.PIXELS_PER_TILE, 0), TileMap.convertLatLonToTileOffset(new GeoPoint(0.0, Geo.LON180), 2)); Assert.assertEquals(new TileOffset(new TileKey(0, 2, 2), 0, 0), TileMap.convertLatLonToTileOffset(new GeoPoint(0.0, 180.0), 2)); Assert.assertEquals(new TileOffset(new TileKey(0, 2, 2), 0, 0), TileMap.convertLatLonToTileOffset(new GeoPoint(0.0, -180.0), 2)); Assert.assertEquals(new TileOffset(new TileKey(0, 2, 2), 0, 0), TileMap.convertLatLonToTileOffset(new GeoPoint(0.0, -Geo.LON180), 2)); }