使用地理空間錨點在 iOS 上定位實際內容

地理空間錨定是錨定的一種,用來在現實世界中放置 3D 內容。

地理空間錨點類型

地理空間錨點有三種,每種類型處理海拔高度的方式皆不同:

  1. WGS84 錨點
    您可使用 WGS84 錨定標記在任何經緯度放置 3D 內容 經度和海拔高度

  2. 地形錨點
    地形錨點可以僅使用經緯度 經度與該位置的地形相對的高度。 海拔高度是相對於地面或樓層的已知高度 上傳者:VPS

  3. 屋頂錨點
    透過屋頂錨定標記,您可以只使用緯度和 相對於建築物屋頂的高度。 海拔高度是相對於建築物頂端的位置 (稱為 製作者:Streetscape Geometry。 未放置在建築物上時,系統預設會使用地形海拔高度。

WGS84 地形 屋頂
水平位置 緯度, 經度 緯度, 經度 緯度, 經度
垂直位置 相對於 WGS84 高度 相對於 Google 地圖所決定地形等級的比較 相對於 Google 地圖判定的屋頂樓層
需要由伺服器解決嗎?

必要條件

請務必先啟用 Geospatial API,再繼續操作。

地點地理空間錨點

每個錨定類型都有專屬 API 來建立這些錨定標記;詳情請參閱「地理空間錨點類型」。

根據命中測試建立錨定廣告

您也可以透過命中測試結果建立地理空間錨點。 使用命中測試中的 Transform,並將其轉換為 GARGeospatialTransform。可用來放置上述 3 種錨定類型。

透過 AR 轉換取得地理空間轉換

GARSession.geospatialTransformFromTransform:error: 可將 AR 轉換轉換為地理空間轉換,提供另一種判斷經緯度的方法。

取得地理空間轉換的 AR 轉換

GARSession.transformFromGeospatialCoordinate:altitude:eastUpSouthQTarget:error: 會將地球指定的水平位置、高度和四元旋轉,對應到相對於 GL 世界座標的 AR Transform 。

選擇符合您用途的方法

每個建立錨點的方法都需留意相關優缺點:

  • 使用「Streetscape 幾何圖形」時 請使用點擊測試將內容附加到建築物上
  • 優先使用 Terrain 或 Rooftop 錨點,而不是 WGS84 錨點,因為它們使用 Google 地圖判定的海拔高度值。

判斷某個位置的經緯度

計算地點經緯度的方式有三種:

  • 善用地理空間創作者,透過 3D 內容飽覽並擴增世界,完全不必親臨當地。這可讓您在 Unity 編輯器中使用 Google 地圖,以視覺化方式放置 3D 沉浸式內容。並自動計算內容的緯度、經度、旋轉和高度。
  • 使用 Google 地圖
  • 使用 Google 地球。請注意,使用「Google 地球」取得這些座標時,您得到的誤差範圍只有幾公尺,而非「Google 地圖」。
  • 前往實際位置

使用 Google 地圖

如何透過 Google 地圖取得地點的經緯度:

  1. 透過電腦前往 Google 地圖

  2. 前往 [圖層] >更多

  3. 將 [地圖類型] 變更為 [衛星],並取消勾選畫面左下角的 [地球視圖] 核取方塊。

    這會強制採用 2D 視角,並消除 3D 檢視中可能產生的錯誤。

  4. 在地圖上,用滑鼠右鍵按一下該地點,然後選取經緯度,即可複製到剪貼簿。

使用 Google 地球

只要在使用者介面中按一下某個位置,即可讀取地標詳細資料的資料,在 Google 地球中計算位置的經緯度。

如要透過 Google 地球取得特定地點的經緯度,請按照下列步驟操作:

  1. 在電腦上前往 Google 地球

  2. 前往漢堡選單 ,然後選取「地圖樣式」

  3. 將「3D 建築物」切換按鈕設為關閉。

  4. 關閉「3D 建築物」開關後,按一下圖釘圖示 ,即可在所選位置新增地標。

  5. 指定要包含地標的專案,然後按一下「儲存」

  6. 在地標的「標題」欄位中,輸入地標名稱。

  7. 按一下專案窗格中的返回箭頭 ,然後選取 「More Actions」選單。

  8. 從選單中選擇「匯出成 KML 檔案」

KLM 檔案會回報 <coordinates> 標記中地標的經緯度和海拔高度 (以半形逗號分隔),如下所示:

<coordinates>-122.0755182435043,37.41347299422944,7.420342565583832</coordinates>

請「不要」使用 <LookAt> 標記中的經緯度;這些標記指定了攝影機位置,而非位置。

前往實際位置

如要計算某地點的海拔高度,請實際前往現場進行當地觀察。

取得旋轉四元數

GARGeospatialTransform.eastUpSouthQTarget 從地理空間轉換中擷取方向,並輸出代表旋轉矩陣,將向量從目標轉換為東南 (EUS) 座標系統的旋轉矩陣。X+ 點往東、Y+ 點向上,以及 Z+ 點朝南。值會依 {x, y, z, w} 順序寫入。

WGS84 錨點

WGS84 Anchor 是一種錨點,可讓您在任何指定的經緯度及高度位置放置 3D 內容。它仰賴 Transform (轉換) 和方向,因此需要放置在真實世界中。位置包含經緯度和海拔高度,(於 WGS84 座標系統中指定)。方向包含四元數旋轉。

海拔高度值於參考 WGS84 橢圓球體上方以公尺為單位,因此地面等級「不是」0。您的應用程式負責為每個已建立的錨點提供這些座標。

在現實世界中放置 WGS84 錨點

判斷位置的海拔高度

您可以透過下列幾種方式判斷位置的海拔高度:

  • 如果錨點的位置與使用者裝置的海拔高度相近,您可以使用與使用者裝置的高度相似的海拔高度,
  • 取得經緯度後,您可以使用 Elevation API,根據 EGM96 規格取得海拔高度。如要與 GARGeospatialTransform 高度進行比較,您必須將 Maps API EGM96 高度轉換成 WGS84。請參閱含有指令列和 HTML 介面的 GeoidEval。Maps API 會根據內建的 WGS84 規格,回報經緯度。
  • 你可以從 Google 地球取得特定地點的經緯度。所提供的誤差範圍最多可達數公尺。請使用 KML 檔案中的 <coordinates> 標記 (「不是」<LookAt> 標記),使用經緯度和海拔高度。
  • 如果現有錨點在靠近附近不是陡坡,即使不使用其他來源 (例如 Maps API),也可以使用相機 GARGeospatialTransform 中的海拔高度。

建立錨定標記

取得緯度、經度、高度和旋轉四元後,即可使用 createAnchorWithCoordinate:altitude:eastUpSouthQAnchor:error: 將內容錨定在您指定的地理座標。

  NSError *error = nil;
  GARAnchor *anchor = [self.garSession createAnchorWithCoordinate:coordinate
                                                         altitude:altitude
                                               eastUpSouthQAnchor:eastUpSouthQAnchor
                                                            error:&error];

地形錨點

地形錨點是一種錨點,可讓您僅利用經緯度放置 AR 物件,並運用 VPS 資訊,找出地面上的精確海拔高度。

您不必輸入所需海拔高度,而是提供地形上方的海拔高度。當此值為零時,錨點就會與地形水平。

設定飛機搜尋模式

平面發現項目為選用項目,且不一定要使用錨點。請注意,僅使用水平平面。水平平面可協助地面上地形錨點的動態對齊方式。

使用 ARWorldTrackingConfiguration.PlaneDetection 選取應用程式偵測飛機的方式。

使用新的 Async API 建立地形錨點

如要建立及放置地形錨點,請呼叫 GARSession.createAnchorWithCoordinate:altitudeAboveTerrain:eastUpSouthQAnchor:completionHandler:error:

錨定廣告可能無法立即使用,需要解決問題。問題解決後,就會在 GARCreateAnchorOnTerrainFuture中顯示。

GARCreateAnchorOnTerrainFuture *future = [self.garSession createAnchorWithCoordinate:coordinate
                                                                altitudeAboveTerrain:altitude
                                                                  eastUpSouthQAnchor:eastUpSouthQTarget
                                                                   completionHandler:^(GARAnchor *anchor, GARTerrainAnchorState state) {
                                                                     // handle completion
                                                                   }
                                                                               error:&error];

查看未來狀況

Future 會有相關聯的 GARFutureState

說明
GARFutureStatePending 這項作業仍待處理。
GARFutureStateDone 作業完成且結果可供使用。
GARFutureStateCancelled 作業已取消。

查看未來結果的地形錨點狀態

GARTerrainAnchorState 屬於非同步作業,屬於 Future 結果的一部分。

switch (future.resultTerrainAnchorState) {
  case GARTerrainAnchorStateSuccess:
    // Terrain anchor finished resolving.
    break;
  case GARTerrainAnchorStateErrorUnsupportedLocation:
    // The requested anchor is in a location that isn't supported by the Geospatial API.
    break;
  case GARTerrainAnchorStateErrorNotAuthorized:
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/ios/group/GARTerrainAnchorState#garterrainanchorstateerrornotauthorized
    // for troubleshooting steps.
    break;
  case GARTerrainAnchorStateErrorInternal:
    // The Terrain anchor could not be resolved due to an internal error.
    break;
  default:
    break;
}

屋頂錨栓

屋頂錨點英雄

屋頂錨點是一種錨點,與上述的地形錨點十分類似。不同之處在於您需要提供屋頂上的海拔高度,而非地形上方的海拔高度。

使用新的 Async API 建立 Rooftop 錨點

錨定廣告可能無法立即使用,需要解決問題。

如要建立及放置屋頂錨點,請呼叫 GARSession.createAnchorWithCoordinate:altitudeAboveRooftop:eastUpSouthQAnchor:completionHandler:error:。與地形錨點類似,您還可以存取 Future 的 GARFutureState。然後,您可以查看 Future 結果,以存取 GARRooftopAnchorState

GARCreateAnchorOnRooftopFuture *future = [self.garSession createAnchorWithCoordinate:coordinate
                                                                altitudeAboveRooftop:altitude
                                                                  eastUpSouthQAnchor:eastUpSouthQTarget
                                                                   completionHandler:^(GARAnchor *anchor, GARRooftopAnchorState state) {
                                                                     // handle completion
                                                                   }
                                                                               error:&error];

查看未來狀況

Future 會有相關聯的 GARFutureState,請參閱上文表格

檢查未來結果的屋頂錨點狀態

GARRooftopAnchorState 屬於非同步作業,屬於 Future 結果的一部分。

switch (future.resultRooftopAnchorState) {
  case GARRooftopAnchorStateSuccess:
    // Rooftop anchor finished resolving.
    break;
  case GARRooftopAnchorStateErrorUnsupportedLocation:
    // The requested anchor is in a location that isn't supported by the Geospatial API.
    break;
  case GARRooftopAnchorStateErrorNotAuthorized:
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/ios/group/GARRooftopAnchorState#garrooftopanchorstateerrornotauthorized
    // for troubleshooting steps.
    break;
  case GARRooftopAnchorStateErrorInternal:
    // The Rooftop anchor could not be resolved due to an internal error.
    break;
  default:
    break;
}

後續步驟