public final void loop(
      final Canvas pCanvas,
      final String pCacheKey,
      final float pZoomLevel,
      final int pTileSizePx,
      final Rect pViewPort,
      final Rect pClipRect) {
    // Calculate the amount of tiles needed for each side around the center one.
    Projection.pixelXYToTileXY(pViewPort.left, pViewPort.top, mUpperLeft);
    mUpperLeft.offset(-1, -1);

    Projection.pixelXYToTileXY(pViewPort.right, pViewPort.bottom, mLowerRight);
    mLowerRight.offset(1, 1);

    center.set((mUpperLeft.x + mLowerRight.x) / 2, (mUpperLeft.y + mLowerRight.y) / 2);

    final int roundedZoom = (int) Math.floor(pZoomLevel);
    final int mapTileUpperBound = 1 << roundedZoom;
    initializeLoop(pZoomLevel, pTileSizePx);

    int tileX, tileY;

    for (int y = mUpperLeft.y; y <= mLowerRight.y; y++) {
      for (int x = mUpperLeft.x; x <= mLowerRight.x; x++) {
        tileY = GeometryMath.mod(y, mapTileUpperBound);
        tileX = GeometryMath.mod(x, mapTileUpperBound);
        final MapTile tile = new MapTile(pCacheKey, roundedZoom, tileX, tileY);
        handleTile(pCanvas, pCacheKey, pTileSizePx, tile, x, y, pClipRect);
      }
    }
    finalizeLoop();
  }
  @Override
  public List<Coord2D> projectPathIntoMap(List<Coord2D> pathPoints) {
    final List<Coord2D> coords = new ArrayList<Coord2D>();

    Projection projection = mMapView.getProjection();
    for (Coord2D point : pathPoints) {
      ILatLng coord = projection.fromPixels((float) point.getX(), (float) point.getY());
      coords.add(DroneHelper.ILatLngToCoord(coord));
    }
    return coords;
  }