Google Streetview: Convert between FOV and Zoom

Does anyone know a formula that I can use to convert from Zoom to the Google Maps Android API: https://developers.google.com/maps/documentation/android-api/streetview to the FOV used in the Google StreetView Image API: https: //developers.google.com/maps/documentation/streetview/intro ?

I found here some old formulas:

Then I put them to the test according to which the FOV will be calculated when I scale the camera on my Android phone:

FOV1: 3.9018*Math.pow(streetViewPanoramaCamera.zoom,2) - 42.432*streetViewPanoramaCamera.zoom + 123

FOV2: Math.abs(streetViewPanoramaCamera.zoom/5*108-120

FOV3: 180/Math.pow(2,streetViewPanoramaCamera.zoom)

@Override
public void onStreetViewPanoramaCameraChange(StreetViewPanoramaCamera streetViewPanoramaCamera) {

    Log.e("Pano", "Bearing: " + streetViewPanoramaCamera.bearing + " Tilt: " + streetViewPanoramaCamera.tilt +
            " Zoom: " + streetViewPanoramaCamera.zoom +
    " FOV1: "+ String.valueOf(3.9018*Math.pow(streetViewPanoramaCamera.zoom,2) - 42.432*streetViewPanoramaCamera.zoom + 123) +" FOV2: "+
            Math.abs(streetViewPanoramaCamera.zoom/5*108-120) +" FOV3: "+ 180/Math.pow(2,streetViewPanoramaCamera.zoom) ) ;

}

0.0 FOV:

09-27 15: 53: 52.322 E/Pano: : 228.28955 : 14.516191 Zoom: 0,0 FOV1:123,0 FOV2: 120,0 FOV3: 180,0

FOV 120, FOV2 , 2 , 76.8, :

09-27 16: 01: 48.235 E/Pano: : 223.11241 : 1.852709 Zoom: 2.0 FOV1: 53,7432 FOV2: 76,8 FOV3: 45,0

2- :

Google Map Android Streetview

, Google Streetview Image API FOV 76.8 (https://maps.googleapis.com/maps/api/streetview?size=600x300&location=-33.87365,151.20689&heading=223.11241&pitch=1.852709&fov=76.8&key=APIKEY):

GoogleStreetView Image API 76.8

, Google Streetview Image API FOV 45 (https://maps.googleapis.com/maps/api/streetview?size=600x300&location=-33.87365,151.20689&heading=223.11241&pitch=1.852709&fov=45&key=APIKEY):

GoogleStreetView Image API 45

, , - FOV 26, - FOV 26:

GoogleStreetView Image API 26

+2
3

, , .

FOV, , : http://www.had2know.com/academics/regression-calculator-statistics-best-fit.html

:

FOV (ZOOM FOV)

120 (0)

50 (1)

45 (1.2)

37 (1.5)

26 (2)

69 (0,5)

78 (0,3)

31 (1.9)

, "" , - , , .

, Y - FOV, X - .

Y = 103,7587 (0,5051 × X)

= -0.9882

+1

( JavaScript):

  • fov :

    zoom = Math.log(180/ fov )/(Math.log(2))

  • fov:

    fov = 180 / Math.pow(2, zoom )

0

. , , , Zoom vs FOV: https://developers.google.com/maps/documentation/javascript/streetview#TilingPanoramas

. Android , , , Android ( ).

, Android API: StreetViewPanorama.orientationToPoint( StreetViewPanoramaOrientation)

, , . , null, , , ; , , , . 180 , , , , , .

. . !

. HORIZONTAL. , . , point.x point.y, screenSize.x screenSize.y, streetViewPanoramaCamera.bearing streetViewPanoramaCamera.tilt :

orientation = new StreetViewPanoramaOrientation(streetViewPanoramaCamera.tilt, angleCheck);

orientation = new StreetViewPanoramaOrientation(angleCheck, streetViewPanoramaCamera.bearing);

, -90 +90 , 180 (: , 0 , ):

private StreetViewPanorama mStreetViewPanorama;

private float mZoom = -1f;
private int mFieldOfViewDegrees;

private void onOrientationUpdate(StreetViewPanoramaCamera streetViewPanoramaCamera) {

    if (streetViewPanoramaCamera.zoom != mZoom) {
        mFieldOfViewDegrees = getFieldOfView(streetViewPanoramaCamera);
        mZoom = streetViewPanoramaCamera.zoom;
    }
}

private int getFieldOfView(StreetViewPanoramaCamera streetViewPanoramaCamera) {

    WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();
    Point screenSize = new Point();
    display.getSize(screenSize);

    StreetViewPanoramaOrientation orientation;
    Integer lowerFovDegrees = null;
    Integer upperFovDegrees = null;

    for (int angleCheck = (int) streetViewPanoramaCamera.bearing - 90;
         angleCheck <= (int) streetViewPanoramaCamera.bearing + 90;
         angleCheck++) {
        orientation = new StreetViewPanoramaOrientation(streetViewPanoramaCamera.tilt, angleCheck);
        Point point = mStreetViewPanorama.orientationToPoint(orientation);

        if (lowerFovDegrees == null) {
            if ((point != null) && (point.x >= 0)) {
                lowerFovDegrees = angleCheck;
            }
        } else if (upperFovDegrees == null) {
            if ((point == null) || (point.x > screenSize.x)) {
                upperFovDegrees = angleCheck - 1;
                break;
            }
        }
    }

    int fieldOfViewDegrees = upperFovDegrees - lowerFovDegrees;

    return fieldOfViewDegrees;
}

ToPoint() , 180 . , ( ), 13 . . , , FOV ; null. , , , , FOV , , , FOV ( ).

private StreetViewPanorama mStreetViewPanorama;

private float mZoom = -1f;
private float mFieldOfViewDegrees;

private void onOrientationUpdate(StreetViewPanoramaCamera streetViewPanoramaCamera) {

    if (streetViewPanoramaCamera.zoom != mZoom) {
        Float fieldOfViewDegrees = getFieldOfView(streetViewPanoramaCamera);
        if (fieldOfViewDegrees == null) { // If FOV cannot be determined, hide any overlay UI overlay elements so they don't display misaligned
            mZoom = -1f;
            // Hide UI overlay elements
        } else {
            mFieldOfViewDegrees = fieldOfViewDegrees;
            mZoom = streetViewPanoramaCamera.zoom;
            // Show UI overlay elements
        }
    }
}


/*
 * Determine field of view. Must use roundabout way since the info is not provided directly.
 * StreetViewPanorama.orientationToPoint() will tell us if a particular orientation is visible on the
 * screen, so we can loop from looking left (-90) to right (+90) and see how much of the 180 degrees is in
 * the field of view.
 *
 * This is is CPU intensive, so instead of a simple loop we use a recursive binary search, and make sure
 * to only call this function when the zoom has changed.
 *
 * WARNING: This method of getting the FOV only works if the equator is still in view. If the user tilts
 * too far down or up, it will return null.
 */
private Float getFieldOfView(StreetViewPanoramaCamera streetViewPanoramaCamera) {

    WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();
    Point screenSize = new Point();
    display.getSize(screenSize);

    // If the equator is no longer in view, FOV cannot be accurately calculated
    StreetViewPanoramaOrientation orientation =
            new StreetViewPanoramaOrientation(0, streetViewPanoramaCamera.bearing);
    Point point = mStreetViewPanorama.orientationToPoint(orientation);
    if (point.y < 0 || point.y > screenSize.y) {
        return null;
    }

    Float lowerFovDegrees = getLowerFieldOfViewDegrees(
            streetViewPanoramaCamera,
            screenSize,
            streetViewPanoramaCamera.bearing - 90f,
            streetViewPanoramaCamera.bearing + 90f);
    Float upperFovDegrees = getUpperFieldOfViewDegrees(
            streetViewPanoramaCamera,
            screenSize,
            streetViewPanoramaCamera.bearing - 90f,
            streetViewPanoramaCamera.bearing + 90f);

    if ((lowerFovDegrees == null) || (upperFovDegrees == null)) return null;

    float fieldOfViewDegrees = upperFovDegrees - lowerFovDegrees;

    return fieldOfViewDegrees;
}

// Recursive binary search function
private Float getLowerFieldOfViewDegrees(StreetViewPanoramaCamera streetViewPanoramaCamera,
                                         Point screenSize,
                                         float startDegrees,
                                         float endDegrees) {
    StreetViewPanoramaOrientation orientation;
    float midpointDegrees = (int) (startDegrees + ((endDegrees - startDegrees) / 2f));

    orientation = new StreetViewPanoramaOrientation(0, midpointDegrees);
    Point point = mStreetViewPanorama.orientationToPoint(orientation);

    if ((point == null) || (point.x < 0)) {
        if (endDegrees - midpointDegrees <= 1f) {
            return endDegrees;
        }

        return getLowerFieldOfViewDegrees(
                streetViewPanoramaCamera,
                screenSize,
                midpointDegrees,
                endDegrees);
    } else {
        if (midpointDegrees - startDegrees <= 1f) {
            return midpointDegrees;
        }

        return getLowerFieldOfViewDegrees(
                streetViewPanoramaCamera,
                screenSize,
                startDegrees,
                midpointDegrees);
    }
}

// Recursive binary search function
private Float getUpperFieldOfViewDegrees(StreetViewPanoramaCamera streetViewPanoramaCamera,
                                         Point screenSize,
                                         float startDegrees,
                                         float endDegrees) {
    StreetViewPanoramaOrientation orientation;
    float midpointDegrees = (int) (startDegrees + ((endDegrees - startDegrees) / 2f));

    orientation = new StreetViewPanoramaOrientation(0, midpointDegrees);
    Point point = mStreetViewPanorama.orientationToPoint(orientation);

    if ((point == null) || (point.x > screenSize.x)) {
        if (midpointDegrees - startDegrees <= 1f) {
            return startDegrees;
        }

        return getUpperFieldOfViewDegrees(
                streetViewPanoramaCamera,
                screenSize,
                startDegrees,
                midpointDegrees);
    } else {
        if (endDegrees - midpointDegrees <= 1f) {
            return midpointDegrees;
        }

        return getUpperFieldOfViewDegrees(
                streetViewPanoramaCamera,
                screenSize,
                midpointDegrees,
                endDegrees);
    }
}

The granularity of the above function is in the near future. You can change it to provide less granularity, but it will take longer to start. Since this can already lead to graphic stuttering, I did not.

I hope this helps someone else, as this seems to be a common question, and I have not seen its solution for Android.

0
source

Source: https://habr.com/ru/post/1628211/


All Articles