@Override
 public void onZoomEnded(double relativeToStart, float angleRelative) {
   // 1.5 works better even on dm.density=1 devices
   float dz = (float) (Math.log(relativeToStart) / Math.log(2)) * 1.5f;
   setIntZoom(Math.round(dz) + initialViewport.getZoom());
   if (Math.abs(angleRelative) < ANGLE_THRESHOLD) {
     angleRelative = 0;
   }
   rotateToAnimate(initialViewport.getRotate() + angleRelative);
   final int newZoom = getZoom();
   if (application.getInternalAPI().accessibilityEnabled()) {
     if (newZoom != initialViewport.getZoom()) {
       showMessage(getContext().getString(R.string.zoomIs) + " " + newZoom); // $NON-NLS-1$
     } else {
       final LatLon p1 = initialViewport.getLatLonFromPixel(x1, y1);
       final LatLon p2 = initialViewport.getLatLonFromPixel(x2, y2);
       showMessage(
           OsmAndFormatter.getFormattedDistance(
               (float)
                   MapUtils.getDistance(
                       p1.getLatitude(), p1.getLongitude(), p2.getLatitude(), p2.getLongitude()),
               application));
     }
   }
 }
  public void moveTo(float dx, float dy) {
    final QuadPoint cp = currentViewport.getCenterPixelPoint();
    final LatLon latlon = currentViewport.getLatLonFromPixel(cp.x + dx, cp.y + dy);
    currentViewport.setLatLonCenter(latlon.getLatitude(), latlon.getLongitude());
    refreshMap();
    // do not notify here listener

  }
 @Override
 public void onZoomStarted(PointF centerPoint) {
   initialMultiTouchCenterPoint = centerPoint;
   initialViewport = getCurrentRotatedTileBox().copy();
   initialCenterLatLon =
       initialViewport.getLatLonFromPixel(
           initialMultiTouchCenterPoint.x, initialMultiTouchCenterPoint.y);
   startRotating = false;
 }
  private void adjustMapPosition(int y, boolean animated) {
    double markerLat = menu.getLatLon().getLatitude();
    double markerLon = menu.getLatLon().getLongitude();
    RotatedTileBox box = map.getCurrentRotatedTileBox().copy();

    LatLon latlon = mapCenter;
    if (menu.isLandscapeLayout()) {
      int markerX = (int) box.getPixXFromLatLon(markerLat, markerLon);
      int x = dpToPx(menu.getLandscapeWidthDp());
      if (markerX - markerPaddingXPx < x || markerX > origMarkerX) {
        int dx = (x + markerPaddingXPx) - markerX;
        if (markerX - dx <= origMarkerX) {
          QuadPoint cp = box.getCenterPixelPoint();
          latlon = box.getLatLonFromPixel(cp.x - dx, cp.y);
        } else {
          latlon = box.getCenterLatLon();
        }
      }
    } else {
      int markerY = (int) box.getPixYFromLatLon(markerLat, markerLon);
      if (markerY + markerPaddingPx > y || markerY < origMarkerY) {
        int dy = markerY - (y - markerPaddingPx);
        if (markerY - dy <= origMarkerY) {
          QuadPoint cp = box.getCenterPixelPoint();
          latlon = box.getLatLonFromPixel(cp.x + 0, cp.y + dy);
        }
      }
    }

    if (map.getLatitude() == latlon.getLatitude() && map.getLongitude() == latlon.getLongitude()) {
      return;
    }

    if (animated) {
      showOnMap(latlon, false, true);
    } else {
      map.setLatLon(latlon.getLatitude(), latlon.getLongitude());
    }
  }
    private void changeZoomPosition(float dz, float angle) {
      final QuadPoint cp = initialViewport.getCenterPixelPoint();
      float dx = cp.x - initialMultiTouchCenterPoint.x;
      float dy = cp.y - initialMultiTouchCenterPoint.y;
      final RotatedTileBox calc = initialViewport.copy();
      calc.setLatLonCenter(initialCenterLatLon.getLatitude(), initialCenterLatLon.getLongitude());

      float calcZoom = initialViewport.getZoom() + dz + initialViewport.getZoomScale();
      float calcRotate = calc.getRotate() + angle;
      calc.setRotate(calcRotate);
      calc.setZoomAnimation(dz);
      final LatLon r = calc.getLatLonFromPixel(cp.x + dx, cp.y + dy);
      setLatLon(r.getLatitude(), r.getLongitude());
      zoomToAnimate(calcZoom, true);
      rotateToAnimate(calcRotate);
    }
  private LatLon getAdjustedMarkerLocation(
      int y, LatLon reqMarkerLocation, boolean center, int zoom) {
    double markerLat = reqMarkerLocation.getLatitude();
    double markerLon = reqMarkerLocation.getLongitude();
    RotatedTileBox box = getBox();
    // box.setCenterLocation(0.5f, map.getMapPosition() == OsmandSettings.BOTTOM_CONSTANT ? 0.15f :
    // 0.5f);
    box.setZoom(zoom);
    int markerMapCenterX =
        (int) box.getPixXFromLatLon(mapCenter.getLatitude(), mapCenter.getLongitude());
    int markerMapCenterY =
        (int) box.getPixYFromLatLon(mapCenter.getLatitude(), mapCenter.getLongitude());
    float cpyOrig = box.getCenterPixelPoint().y;

    box.setCenterLocation(0.5f, 0.5f);
    int markerX = (int) box.getPixXFromLatLon(markerLat, markerLon);
    int markerY = (int) box.getPixYFromLatLon(markerLat, markerLon);
    QuadPoint cp = box.getCenterPixelPoint();
    float cpx = cp.x;
    float cpy = cp.y;

    float cpyDelta = menu.isLandscapeLayout() ? 0 : cpyOrig - cpy;

    markerY += cpyDelta;
    y += cpyDelta;
    float origMarkerY = this.origMarkerY + cpyDelta;

    LatLon latlon;
    if (center) {
      latlon = reqMarkerLocation;
    } else {
      latlon = box.getLatLonFromPixel(markerMapCenterX, markerMapCenterY);
    }
    if (menu.isLandscapeLayout()) {
      int x = menu.getLandscapeWidthPx();
      if (markerX - markerPaddingXPx < x || markerX > origMarkerX) {
        int dx = (x + markerPaddingXPx) - markerX;
        int dy = 0;
        if (center) {
          dy = (int) cpy - markerY;
        } else {
          cpy = cpyOrig;
        }
        if (dx >= 0 || center) {
          latlon = box.getLatLonFromPixel(cpx - dx, cpy - dy);
        }
      }
    } else {
      if (markerY + markerPaddingPx > y || markerY < origMarkerY) {
        int dx = 0;
        int dy = markerY - (y - markerPaddingPx);
        if (markerY - dy <= origMarkerY) {
          if (center) {
            dx = markerX - (int) cpx;
          }
          latlon = box.getLatLonFromPixel(cpx + dx, cpy + dy);
        }
      }
    }
    return latlon;
  }