שימוש בעוגנים גיאו-מרחביים כדי למקם תוכן מהעולם האמיתי ב-iOS

עוגנים גיאו-מרחביים הם סוג של עוגן שמאפשר להציב תוכן תלת-ממדי בעולם האמיתי.

סוגים של עוגנים גיאו-מרחביים

קיימים שלושה סוגים של עוגנים גיאו-מרחביים, שכל אחד מהם מטפל בגובה באופן שונה:

  1. עוגני WGS84:
    עוגנים של WGS84 מאפשרים להציב תוכן בתלת-ממד בכל קו רוחב, קו אורך וגובה נתונים.

  2. עוגנים לפני השטח:
    עוגנים לפני השטח מאפשרים להציב תוכן רק באמצעות קווי אורך ורוחב, עם גובה ביחס לפני השטח במיקום הזה. הגובה נקבע ביחס לקרקע או לרצפה, שנקרא על ידי VPS.

  3. דיגנים לגגות:
    דיבלים לגג מאפשרים להציב תוכן רק לפי קווי אורך ורוחב, בגובה ביחס לגג המבנה במיקום הזה. הגובה נקבע ביחס לחלק העליון של המבנה, כפי שמוכר באמצעות גיאומטריה של Streetscape. כאשר אינה ממוקמת על מבנה, ברירת המחדל של ההגדרה הזו היא גובה פני השטח.

WGS84 פני השטח גג רכב
מיקום אופקי קו רוחב, קו אורך קו רוחב, קו אורך קו רוחב, קו אורך
מיקום אנכי ביחס לגובה WGS84 ביחס לרמת פני השטח הנקבעת על ידי מפות Google יחסית לרמת הגג הנקבעת על ידי מפות Google
צריך לפתור בעיה בשרת? לא כן כן

דרישות מוקדמות

לפני שממשיכים, חשוב להפעיל את ה-Geospatial API.

מיקום עוגנים גיאו-מרחביים

לכל סוג עוגן יש ממשקי API ייעודיים שנועדו ליצור אותם. מידע נוסף זמין במאמר סוגים של עוגנים גיאו-מרחביים.

יצירת עוגן מבדיקה של היט

אפשר גם ליצור עוגן גיאו-מרחבי מתוצאת בדיקת ההיט. משתמשים בטרנספורמציה מבדיקת ההיט וממירים אותה ל-GARGeospatialTransform. ניתן להשתמש בו כדי למקם כל אחד מ-3 סוגי העוגנים שמתוארים.

קבלת המרה גיאו-מרחבית מטרנספורמציה ב-AR

GARSession.geospatialTransformFromTransform:error: מספקת דרך נוספת לקביעת קווי האורך והרוחב על ידי המרה של טרנספורמציה AR לטרנספורמציה גיאו-מרחבית.

השגתם של טרנספורמציה ב-AR מטרנספורמציה גיאו-מרחבית

GARSession.transformFromGeospatialCoordinate:altitude:eastUpSouthQTarget:error: ממירה מיקום אופקי, גובה וסיבוב רבעים שצוינו על-ידי כדור הארץ ביחס למסגרת קואורדינטית ממזרח-לדרום לטרנספורמציה AR ביחס לקואורדינטה העולמית GL.

בחירת השיטה המתאימה לתרחיש לדוגמה

לכל שיטה ליצירת עוגן יש תוספות שחשוב לזכור:

  • כשמשתמשים בגיאומטריה של Streetscape, כדאי להשתמש ב-hit-test כדי לצרף תוכן לבניין.
  • יש עדיפות לעוגנים בפני שטח או לגג על פני עוגנים מסוג WGS84, מאחר שהם משתמשים בערכי גובה שנקבעים על ידי מפות Google.

קביעת קווי האורך והרוחב של מיקום

יש שלוש דרכים שבאמצעותן אפשר לחשב את קווי האורך והרוחב של מיקום:

  • אפשר להשתמש ב-Geospatial Creator כדי להציג ולהעשיר את העולם באמצעות תוכן בתלת-ממד, מבלי להגיע פיזית למיקום. כך ניתן למקם תוכן תלת-ממדי עשיר באופן חזותי באמצעות מפות Google בעורך Unity. קו הרוחב, קו האורך, הסיבוב והגובה של התוכן יחושבו בשבילכם באופן אוטומטי.
  • שימוש במפות Google
  • שימוש ב-Google Earth. חשוב לשים לב שהשגת קואורדינטות אלה באמצעות Google Earth, בניגוד למפות Google, תספק מרווח שגיאה של עד כמה מטרים.
  • מעבר למיקום הפיזי

שימוש במפות Google

כדי לקבל את קווי האורך והרוחב של מיקום באמצעות מפות Google:

  1. נכנסים למפות Google במחשב.

  2. מנווטים אל שכבות > עוד.

  3. משנים את סוג המפה ללוויין ומנקים את תיבת הסימון תצוגת כדור הארץ בפינה הימנית התחתונה של המסך.

    כך תכפה פרספקטיבה דו-ממדית ותבטל שגיאות אפשריות שעשויות להגיע מתצוגה תלת-ממדית בזווית.

  4. במפה, לוחצים לחיצה ימנית על המיקום ובוחרים את קו האורך/רוחב כדי להעתיק אותו ללוח.

שימוש ב-Google Earth

אפשר לחשב את קווי האורך והרוחב של מיקום מסוים ב-Google Earth על ידי לחיצה על מיקום בממשק המשתמש וקריאת הנתונים מפרטי הסמן.

כדי לקבל את קווי האורך והרוחב של מיקום מסוים באמצעות Google Earth:

  1. עוברים אל Google Earth במחשב.

  2. מנווטים לתפריט ההמבורגר ובוחרים באפשרות סגנון המפה.

  3. מעבירים את המתג בניינים בתלת-ממד למצב מושבת.

  4. לאחר השבתת המתג בניינים בתלת-ממד, לוחצים על סמל הסיכה כדי להוסיף סמן במיקום שנבחר.

  5. מציינים את הפרויקט שרוצים להכיל את הסמן ולוחצים על Save (שמירה).

  6. בשדה כותרת של הסמן, נותנים שם לסמן.

  7. לוחצים על החץ חזרה בחלונית הפרויקט ובוחרים בתפריט פעולות נוספות.

  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 הוא סוג של עוגן שמאפשר למקם תוכן בתלת-ממד בכל קו רוחב, קו אורך וגובה נתונים. כדי למקם אותו בעולם האמיתי, הוא מתבסס על טרנספורמציה ועל כיוון. המיקום מורכב מקווי רוחב, קווי אורך וגובה, שמצוינים במערכת הקואורדינטות WGS84. הכיוון כולל סיבוב קווטרניון.

הגובה מדווח במטרים מעל לאליפסואיד WGS84 שאליו מתייחסים פני הקרקע לא באפס. האפליקציה שלך אחראית לספק את הקואורדינטות האלה עבור כל עוגן שנוצר.

מציבים עוגן WGS84 בעולם האמיתי

איך לקבוע את הגובה של מיקום מסוים

יש כמה דרכים לקבוע את הגובה של מיקום כדי למקם בו עוגנים:

  • אם מיקום העוגן נמצא פיזית בקרבת המשתמש, אפשר להשתמש בגובה שדומה לגובה המכשיר של המשתמש.
  • אחרי שמזינים את קווי האורך והרוחב, משתמשים ב-Elevation API כדי לקבל גובה לפי המפרט של EGM96. צריך להמיר את הגובה EGM96 של ה-API של מפות Google ל-WGS84 לצורך השוואה מול הגובה GARGeospatialTransform. אפשר לראות את ה-GeoidEval שכולל גם שורת פקודה וגם ממשק HTML. ה-API של מפות Google מדווח על קווי אורך ורוחב בהתאם למפרט WGS84, ללא אריזה.
  • את קו הרוחב, קו האורך והגובה של מיקום מסוים אפשר לקבל מ-Google Earth. כך מתקבל מרווח שגיאה של עד כמה מטרים. בקובץ ה-KML יש להשתמש בקווי אורך ורוחב מתגי <coordinates>, ולא מתגי <LookAt>.
  • אם עוגן קיים נמצא בקרבת מקום וגם אם אתם לא על שיפוע תלול, ייתכן שתוכלו להשתמש בגובה מהGARGeospatialTransform של המצלמה בלי להשתמש במקור אחר, כמו ה-API של מפות Google.

יצירת מודעות עוגן

אחרי שמזינים את קווי הרוחב, קו האורך, הגובה והסיבוב, משתמשים ב-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];

בדיקת מצב העתיד

לעתיד יהיה GARFutureState משויך.

ארץ התיאור
GARFutureStatePending הפעולה עדיין בהמתנה.
GARFutureStateDone הפעולה הושלמה והתוצאה זמינה.
GARFutureStateCancelled הפעולה בוטלה.

בדיקת מצב עוגן פני השטח של התוצאה העתידית

הערך GARTerrainAnchorState שייך לפעולה האסינכרונית והוא חלק מהתוצאה העתידית הסופית.

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 החדש

העוגן לא יהיה מוכן מיד וצריך להיפתר.

כדי ליצור עוגן בגג ולהציב אותו, יש להפעיל את המספר GARSession.createAnchorWithCoordinate:altitudeAboveRooftop:eastUpSouthQAnchor:completionHandler:error:. באופן דומה לעוגנים בפני שטח, תהיה לכם גישה גם ל-GARFutureState של העתיד. לאחר מכן תוכלו לבדוק את התוצאה העתידית כדי לגשת אל GARRooftopAnchorState.

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

בדיקת מצב העתיד

לעתיד יהיה GARFutureState משויך. מידע נוסף זמין בטבלה שלמעלה.

בדיקת מצב העוגן בגג של התוצאה העתידית

הערך GARRooftopAnchorState שייך לפעולה האסינכרונית והוא חלק מהתוצאה העתידית הסופית.

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;
}

המאמרים הבאים