All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mapbox.mapboxsdk.camera.CameraUpdateFactory Maven / Gradle / Ivy

There is a newer version: 9.2.1
Show newest version
package com.mapbox.mapboxsdk.camera;

import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.RectF;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;

import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Projection;
import com.mapbox.mapboxsdk.maps.UiSettings;
import com.mapbox.mapboxsdk.utils.MathUtils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Factory for creating {@link CameraUpdate} objects.
 */
public final class CameraUpdateFactory {

    /**
     * Returns a CameraUpdate that moves the camera to a specified CameraPosition.
     *
     * @param cameraPosition Camera Position to change to
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate newCameraPosition(@NonNull CameraPosition cameraPosition) {
        return new CameraPositionUpdate(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom);
    }

    /**
     * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude
     * specified by a LatLng object. This centers the camera on the LatLng object.
     *
     * @param latLng Target location to change to
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate newLatLng(@NonNull LatLng latLng) {
        return new CameraPositionUpdate(-1, latLng, -1, -1);
    }

    /**
     * Returns a CameraUpdate that transforms the camera such that the specified latitude/longitude
     * bounds are centered on screen at the greatest possible zoom level.
     * You can specify padding, in order to inset the bounding box from the map view's edges.
     * The returned CameraUpdate has a bearing of 0 and a tilt of 0.
     *
     * @param bounds  Bounds to match Camera position with
     * @param padding Padding added to the bounds
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int padding) {
        return newLatLngBounds(bounds, padding, padding, padding, padding);
    }


    /**
     * Returns a CameraUpdate that transforms the camera such that the specified latitude/longitude
     * bounds are centered on screen at the greatest possible zoom level.
     * You can specify padding, in order to inset the bounding box from the map view's edges.
     * The returned CameraUpdate has a bearing of 0 and a tilt of 0.
     *
     * @param bounds        Bounds to base the Camera position out of
     * @param paddingLeft   Padding left of the bounds
     * @param paddingTop    Padding top of the bounds
     * @param paddingRight  Padding right of the bounds
     * @param paddingBottom Padding bottom of the bounds
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
        return new CameraBoundsUpdate(bounds, paddingLeft, paddingTop, paddingRight, paddingBottom);
    }

    /**
     * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude specified by a LatLng object,
     * and moves to the given zoom level.
     *
     * @param latLng Target location to change to
     * @param zoom   Zoom level to change to
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate newLatLngZoom(@NonNull LatLng latLng, float zoom) {
        return new CameraPositionUpdate(-1, latLng, -1, zoom);
    }

    /**
     * Returns a CameraUpdate that scrolls the camera over the map,
     * shifting the center of view by the specified number of pixels in the x and y directions.
     *
     * @param xPixel Amount of pixels to scroll to in x direction
     * @param yPixel Amount of pixels to scroll to in y direction
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate scrollBy(float xPixel, float yPixel) {
        return new CameraMoveUpdate(xPixel, yPixel);
    }

    /**
     * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint.
     *
     * @param amount Amount of zoom level to change with
     * @param focus  Focus point of zoom
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate zoomBy(float amount, Point focus) {
        return new ZoomUpdate(amount, focus.x, focus.y);
    }

    /**
     * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint.
     *
     * @param amount Amount of zoom level to change with
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate zoomBy(float amount) {
        return new ZoomUpdate(ZoomUpdate.ZOOM_BY, amount);
    }

    /**
     * Returns a CameraUpdate that zooms in on the map by moving the viewpoint's height closer to the Earth's surface. The zoom increment is 1.0.
     *
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate zoomIn() {
        return new ZoomUpdate(ZoomUpdate.ZOOM_IN);
    }

    /**
     * Returns a CameraUpdate that zooms out on the map by moving the viewpoint's height farther away from the Earth's surface. The zoom increment is -1.0.
     *
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate zoomOut() {
        return new ZoomUpdate(ZoomUpdate.ZOOM_OUT);
    }

    /**
     * Returns a CameraUpdate that moves the camera viewpoint to a particular zoom level.
     *
     * @param zoom Zoom level to change to
     * @return CameraUpdate Final Camera Position
     */
    public static CameraUpdate zoomTo(float zoom) {
        return new ZoomUpdate(ZoomUpdate.ZOOM_TO, zoom);
    }

    //
    // CameraUpdate types
    //

    static final class CameraPositionUpdate implements CameraUpdate {

        private final double bearing;
        private final LatLng target;
        private final double tilt;
        private final double zoom;

        CameraPositionUpdate(double bearing, LatLng target, double tilt, double zoom) {
            this.bearing = bearing;
            this.target = target;
            this.tilt = tilt;
            this.zoom = zoom;
        }

        public LatLng getTarget() {
            return target;
        }

        public double getBearing() {
            return bearing;
        }

        public double getTilt() {
            return tilt;
        }

        public double getZoom() {
            return zoom;
        }

        @Override
        public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
            CameraPosition previousPosition = mapboxMap.getCameraPosition();
            if (target == null) {
                return new CameraPosition.Builder(true)
                        .tilt(tilt)
                        .zoom(zoom)
                        .bearing(bearing)
                        .target(previousPosition.target)
                        .build();
            }
            return new CameraPosition.Builder(this).build();
        }
    }

    static final class CameraBoundsUpdate implements CameraUpdate {

        private LatLngBounds bounds;
        private RectF padding;

        public CameraBoundsUpdate(LatLngBounds bounds, RectF padding) {
            this.bounds = bounds;
            this.padding = padding;
        }

        public CameraBoundsUpdate(LatLngBounds bounds, int[] padding) {
            this(bounds, new RectF(padding[0], padding[1], padding[2], padding[3]));
        }

        public CameraBoundsUpdate(LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
            this(bounds, new int[]{paddingLeft, paddingTop, paddingRight, paddingBottom});
        }

        public LatLngBounds getBounds() {
            return bounds;
        }

        public RectF getPadding() {
            return padding;
        }

        @Override
        public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
            // Get required objects
            Projection projection = mapboxMap.getProjection();
            UiSettings uiSettings = mapboxMap.getUiSettings();
            RectF padding = getPadding();

            // Calculate the bounds of the possibly rotated shape with respect to the viewport
            PointF nePixel = new PointF(-10000, -10000);
            PointF swPixel = new PointF(10000, 10000);
            float viewportHeight = uiSettings.getHeight();
            for (LatLng latLng : getBounds().toLatLngs()) {
                PointF pixel = projection.toScreenLocation(latLng);
                swPixel.x = Math.min(swPixel.x, pixel.x);
                nePixel.x = Math.max(nePixel.x, pixel.x);
                swPixel.y = Math.min(swPixel.y, viewportHeight - pixel.y);
                nePixel.y = Math.max(nePixel.y, viewportHeight - pixel.y);
            }

            // Calculate wid=th/height
            float width = nePixel.x - swPixel.x;
            float height = nePixel.y - swPixel.y;

            // Calculate the zoom level
            float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width;
            float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height;
            float minScale = scaleX < scaleY ? scaleX : scaleY;
            double zoom = projection.calculateZoom(minScale);
            zoom = MathUtils.clamp(zoom, (float) mapboxMap.getMinZoom(), (float) mapboxMap.getMaxZoom());

            // Calculate the center point
            PointF paddedNEPixel = new PointF(nePixel.x + padding.right / minScale, nePixel.y + padding.top / minScale);
            PointF paddedSWPixel = new PointF(swPixel.x - padding.left / minScale, swPixel.y - padding.bottom / minScale);
            PointF centerPixel = new PointF((paddedNEPixel.x + paddedSWPixel.x) / 2, (paddedNEPixel.y + paddedSWPixel.y) / 2);
            centerPixel.y = viewportHeight - centerPixel.y;
            LatLng center = projection.fromScreenLocation(centerPixel);

            return new CameraPosition.Builder()
                    .target(center)
                    .zoom((float) zoom)
                    .tilt(0)
                    .bearing(0)
                    .build();
        }
    }

    static final class CameraMoveUpdate implements CameraUpdate {

        private float x;
        private float y;

        public CameraMoveUpdate(float x, float y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
            UiSettings uiSettings = mapboxMap.getUiSettings();
            Projection projection = mapboxMap.getProjection();

            // Calculate the new center point
            float viewPortWidth = uiSettings.getWidth();
            float viewPortHeight = uiSettings.getHeight();
            PointF targetPoint = new PointF(viewPortWidth / 2 + x, viewPortHeight / 2 + y);

            // Convert point to LatLng
            LatLng latLng = projection.fromScreenLocation(targetPoint);

            CameraPosition cameraPosition = mapboxMap.getCameraPosition();
            return new CameraPosition.Builder()
                    .target(latLng)
                    .zoom(cameraPosition.zoom)
                    .tilt(cameraPosition.tilt)
                    .bearing(cameraPosition.bearing)
                    .build();
        }
    }

    static final class ZoomUpdate implements CameraUpdate {

        @IntDef({ZOOM_IN, ZOOM_OUT, ZOOM_BY, ZOOM_TO, ZOOM_TO_POINT})
        @Retention(RetentionPolicy.SOURCE)
        public @interface Type {
        }

        public static final int ZOOM_IN = 0;
        public static final int ZOOM_OUT = 1;
        public static final int ZOOM_BY = 2;
        public static final int ZOOM_TO = 3;
        public static final int ZOOM_TO_POINT = 4;

        @Type
        private final int type;
        private final double zoom;
        private float x;
        private float y;

        ZoomUpdate(@Type int type) {
            this.type = type;
            this.zoom = 0;
        }

        ZoomUpdate(@Type int type, float zoom) {
            this.type = type;
            this.zoom = zoom;
        }

        ZoomUpdate(float zoom, float x, float y) {
            this.type = ZOOM_TO_POINT;
            this.zoom = zoom;
            this.x = x;
            this.y = y;
        }

        public double getZoom() {
            return zoom;
        }

        @Type
        public int getType() {
            return type;
        }

        public float getX() {
            return x;
        }

        public float getY() {
            return y;
        }

        public double transformZoom(double currentZoom) {
            switch (getType()) {
                case CameraUpdateFactory.ZoomUpdate.ZOOM_IN:
                    currentZoom++;
                    break;
                case CameraUpdateFactory.ZoomUpdate.ZOOM_OUT:
                    currentZoom--;
                    if (currentZoom < 0) {
                        currentZoom = 0;
                    }
                    break;
                case CameraUpdateFactory.ZoomUpdate.ZOOM_TO:
                    currentZoom = getZoom();
                    break;
                case CameraUpdateFactory.ZoomUpdate.ZOOM_BY:
                    currentZoom = currentZoom + getZoom();
                    break;
                case CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT:
                    currentZoom = currentZoom + getZoom();
                    break;
            }
            return currentZoom;
        }

        @Override
        public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
            CameraPosition cameraPosition = mapboxMap.getCameraPosition();
            if (getType() != CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT) {
                return new CameraPosition.Builder(cameraPosition)
                        .zoom(transformZoom(cameraPosition.zoom))
                        .build();
            } else {
                return new CameraPosition.Builder(cameraPosition)
                        .zoom(transformZoom(cameraPosition.zoom))
                        .target(mapboxMap.getProjection().fromScreenLocation(new PointF(getX(), getY())))
                        .build();
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy