谷歌搜索這個答案,我只能找到網站的公式。網站是不同的,因爲首先,在文檔中有一個縮放與FOV圖表: https://developers.google.com/maps/documentation/javascript/streetview#TilingPanoramas
因此,可以拿出一個公式。 Android文檔沒有這樣的表格,而人們用於Web的公式並不適用於Android(甚至沒有關閉)。
然而有一些好消息,而正是這種功能可以在Android API中: StreetViewPanorama.orientationToPoint(StreetViewPanoramaOrientation orientation)
此功能使我們能夠提供一個方向,它會在屏幕上返回一個點,該方向的謊言。該功能的文檔說,如果該方向不在屏幕上,它將返回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;
}
但是,orientationToPoint()的代價很高,最多可以調用180次。我們可以使用二進制搜索來使這種效率更高(雖然更復雜),並將其降低到更像〜13個調用。在這種情況下,我使用遞歸函數來執行二進制搜索。此外還有一個侷限性,即水平赤道必須在視野內或FOV不能準確計算;在這種情況下,它返回null。只要用戶不會一直向下或向上傾斜,這並不是一個真正的問題,但是如果他們這樣做,FOV將返回null,並且您需要隱藏依賴於FOV的任何UI元素都是準確的(或者他們將不在正確的位置)。
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);
}
}
上面的函數的粒度是到最近的程度。您可以修改它以縮小粒度,但運行時間會更長。由於它可能已經導致圖形的口吃,我沒有這樣做。
我希望這可以幫助別人,因爲這似乎是一個常見問題,我沒有看到它解決了Android。
此公式不適用於Android。在Android中,特定縮放的FOV與網絡非常不同。 – OldSchool4664