חיפוש לאורך המסלול באמצעות Places API

במסמך הזה מוסבר איך למצוא מלון, מסעדה או תחנת דלק לאורך מסלול מתוכנן. תלמדו איך להשתמש ב-Routes API כדי לקבל קו פוליגון של מסלול, ולהשתמש בו בבקשה של Places APISearch Along Route‏ (SAR). בנוסף, תלמדו איך לקבל את התוצאות הטובות ביותר על ידי הגדרת נקודת המוצא לחיפוש לאורך המסלול, למשל שעתיים אחרי תחילת הנסיעה.

Routes API

כדי לחפש מקומות לאורך המסלול, נשתמש ב-Routes API. נתוני המסלול בתגובה מ-Routes API הם סדרה של קואורדינטות LatLong מהמקור ליעד. נתוני המסלול מכילים שלבים וקטעים שמתבססים על רשת הכבישים.

המסלולים מוחזרים גם כקווים פוליגונים מקודדים, שאותם מעבירים כפרמטר קלט לבקשת ה-SAR. קידוד של קווים פוליגונים הוא אלגוריתם דחיסה עם אובדן נתונים שמאפשר לאחסן סדרה של קואורדינטות כמחרוזת אחת. לא חובה לקבל את קו הפוליגון מ-Routes API. אפשר ליצור את הנתונים בעצמכם, אבל לצורך הדוגמה הזו, Routes API הוא דרך מהירה ומאובטחת לקבל את הנתונים הנדרשים.

במדריך הזה נשתמש במסלול מלונדון (-37.8167,144.9619) למנצ'סטר (-37.8155, 144.9663)

מסלול מלונדון למנצ'סטר

המסלול בדוגמה: לונדון למנצ'סטר

שלב 1: אחזור מסלול מ-Routes API

כדי לקבל מסלול מ-Routes API, צריך לספק את הפרטים הבאים:

  • המיקומים של נקודת המוצא ונקודת היעד
  • אמצעי התחבורה (נהיגה, הליכה וכו')
  • נקודות דרך (אופציונלי)
  • העדפות כלשהן (הימנעות מכבישי אגרה, הימנעות מכבישים מהירים וכו')
  • העדפת ניתוב מבוססת-תנועה תיתן לכם את האומדנים המדויקים ביותר, אבל היא דורשת יותר חישובים, ולכן היא מגדילה את זמן האחזור של התגובה.
{"origin":{
    "location": {
        "latLng":{
            "latitude":  -37.8167,
            "longitude": 144.9619
        }
    }
},
"destination":{
    "location": {
        "latLng":{
            "latitude":-37.8155,
            "longitude": 144.9663
        }
    }
},
"routingPreference":"TRAFFIC_AWARE",
"travelMode":"DRIVE"
}

כשמבצעים את הקריאה, חשוב לכלול את השדה encodedPolyline במסכת השדות של הכותרות.

headers = {
    "Content-Type": "application/json",
    "X-Goog-FieldMask": "routes.distanceMeters,routes.duration,routes.legs,routes.polyline.encodedPolyline"
}

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

אחרי שמספקים את המידע הזה בבקשה, Routes API מחזיר אובייקט מסלול. אובייקט המסלול יכיל את הפרטים הבאים:

  • המרחק הכולל של המסלול
  • משך הזמן הכולל של המסלול
  • השלבים והקטעים של המסלול
  • הקו הפוליגוני המקודד של המסלול, השלבים והקטעים.
{
  "routes": [
    {
      "legs": [
        {
          "distanceMeters": 321799,
          "duration": "15401s",
          "staticDuration": "14518s",
          "polyline": {
            "encodedPolyline": "y_kyH`_XOr@q@xKGnBBZ|AlGPj@Y^k@^MEqAfAQLK?eI … <rest of content removed for readability>"
          },
          "startLocation": {
            "latLng": {
              "latitude": 51.507334500000006,
              "longitude": -0.1280107
            }
          },
          "endLocation": {
            "latLng": {
              "latitude": 53.4808513,
              "longitude": -2.2425864
            }
          },
          "steps": [
            {
              "distanceMeters": 320,
              "staticDuration": "82s",
              "polyline": {
                "encodedPolyline": "y_kyH`_XOr@q@xKGnBBZ|AlG"
              },
              "startLocation": {
                "latLng": {
                  "latitude": 51.507334500000006,
                  "longitude": -0.1280107
                }
              },
              "endLocation": {
                "latLng": {
                  "latitude": 51.507207,
                  "longitude": -0.1323681
                }
              },
              "navigationInstruction": {
                "maneuver": "DEPART",
                "instructions": "Head northwest on Trafalgar Sq/A4 toward Spring Gardens\nContinue to follow A4\nLeaving toll zone\nEntering toll zone\nLeaving toll zone in 210m at Haymarket"
              },
              "localizedValues": {
                "distance": {
                  "text": "0.3 km"
                },
                "staticDuration": {
                  "text": "1 min"
                }
              },
# rest of the response removed for readability

שלב 2: בקשה לחיפוש לאורך המסלול

לחיפוש טקסט ב-Places API יש בקשה לחיפוש לאורך מסלול שמאפשרת לחפש מקומות לאורך מסלול. כדי לשלוח בקשה ל'חיפוש לאורך המסלול', תצטרכו לספק את הפרטים המינימליים הבאים:

  • אנונימיזציה של השדות שיוחזרו בתגובה
  • מפתח API תקין לממשק ה-API שהופעל במסוף Google Cloud
  • מחפשים מחרוזת טקסט שמציינת את המקומות שאתם מחפשים, לדוגמה: "מסעדה צמחונית חריפות"
  • קו הפוליגון המקודד של המסלול, שאוחזר מהקריאה הקודמת ל-Routes API
  • כתובת URL של נקודת הקצה של Places Text Search API
import requests

url = 'https://places.googleapis.com/v1/places:searchText'
api_key = 'YOUR_API_KEY'  # Replace with your actual API key
route_polyline = 'YOUR_ROUTE_POLYLINE'  # Replace with your encoded route polyline

headers = {
    'Content-Type': 'application/json',
    'X-Goog-Api-Key': api_key,
    'X-Goog-FieldMask': 'places.displayName,places.formattedAddress,places.priceLevel'
}

data = {
    "textQuery":
 "Spicy Vegetarian Food",
    "searchAlongRouteParameters": {
        "polyline": {
            "encodedPolyline": route_polyline
        }
    }
}

response = requests.post(url, headers=headers, json=data)

נתוני בקשה לדוגמה

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

{
  "places": [
    {
      "formattedAddress": "33 Haymarket, London SW1Y 4HA, UK",
      "displayName": {
        "text": "xxx",
        "languageCode": "en"
      }
    },
    {
      "formattedAddress": "224 Piccadilly, London W1J 9HP, UK",
      "priceLevel": "PRICE_LEVEL_MODERATE",
      "displayName": {
        "text": "yyy",
        "languageCode": "en"
      }
    },
    {
      "formattedAddress": "63 Neal St, London WC2H 9PJ, UK",
      "displayName": {
        "text": "zzz",
        "languageCode": "en"
      }
    },

נתוני תגובה לדוגמה

סיכום מסלול וזמני מעקף

מצוין שאפשר למצוא את המיקומים, אבל כדאי להוסיף מידע על משך הנסיעה למיקומים האלה. SAR בחיפוש טקסט של Places API יכול גם להחזיר שדה routing summaries שמכיל את משך הנסיעה ואת המרחק. שדה הנתונים של סיכומי הניתוב הוא צאצא של שורש התגובה, לכן אסור לכלול את הקידומת places. במסכת השדה.

'X-Goog-FieldMask': 'places.displayName,places.formattedAddress,places.priceLevel,routingSummaries'

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

"routingParameters": {
      "origin": {
        "latitude":  -37.8167,
        "longitude": 144.9619
      }
    }

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

"routingSummaries": [
    {
      "legs": [
        {
          "duration": "662s",
          "distanceMeters": 3093
        }
      ]
    },

בשלב הבא נסביר איך אפשר להגדיר איפה במסלול החיפוש יתחיל.

שלב 3: קבלת מיקום שעתיים לאורך המסלול

נניח שמדובר בתרחיש לדוגמה שבו הנהג רוצה למצוא מסעדות לא בתחילת המסלול, אלא בהמשך הדרך. בדוגמה שלנו, הנסיעה מלונדון למנצ'סטר נמשכת כ-4 שעות. הנהג או הנהגת רוצים למצוא מסעדה שנמצאת במסלול, במרחק שעתיים נסיעה. הבקשה הזו מאפשרת לנו לקבל את משך הזמן: 120 דקות * 60 שניות = 7,200 שניות.

בתגובה של Routes API מופיע משך הזמן של כל מקטע במסלול וכל שלב במקטע. חשוב לכלול את השדה legs במסכת השדות בבקשה. חוזרים על השלבים והקטעים עד שהמשך הזמן המצטבר מגיע למגבלה של שעתיים או 7,200 שניות. לאחר מכן, אנחנו מוצאים את החלק והשלב שרוצים להגדיר כמקור של בקשת ה-SAR.

כדי לזרז את העבודה, כדאי לנסות את ספריית polyline ל-Python. אפשר להשתמש בו כדי לקבל את הקואורדינטות משדה הנתונים polyline.endodedPolyline.

מריצים את הפקודות הבאות במסוף הסביבה.

> pip install polyline
import requests
import polyline

# We've covered getting a Routes API response earlier,
data = response.json()

  # Extract the first route and its encoded polyline
  route = data["routes"][0]
  polyline_points = polyline.decode(route["polyline"]["encodedPolyline"])

  # Calculate total duration of the route in seconds
  total_duration_seconds = route["duration"]

  # Calculate the desired time offset in seconds, 2h = 120 minutes * 60
  desired_time_offset_seconds = time_offset_minutes * 60

  # Iterate through the legs and steps to find the point at the desired time offset
  elapsed_time_seconds = 0
  for leg in route["legs"]:
      for step in leg["steps"]:
          step_duration_seconds = step["staticDuration"]

          # Check if the desired time offset falls within this step, remove last "s" from string and convert to int
          second_value = int(step_duration_seconds[:-1])
          if elapsed_time_seconds + second_value >= desired_time_offset_seconds:
              # Interpolate to find the exact point within the step
              fraction_of_step = (desired_time_offset_seconds - elapsed_time_seconds) / second_value
              step_polyline_points = polyline.decode(step["polyline"]["encodedPolyline"])
              index = int(len(step_polyline_points) * fraction_of_step)
              return step_polyline_points[index]

          elapsed_time_seconds += second_value

  # If the point is not found (e.g., time offset exceeds route duration)
  return None

עכשיו, אחרי שמצאנו את המיקום במסלול שנמצא שעתיים אחרי תחילת הנסיעה, אנחנו יכולים להשתמש בו בבקשה. פשוט מוסיפים את קו הרוחב ואת קו האורך בפרמטר 'origin', שהוא חלק מהפרמטר 'routingParameters'. מומלץ להשתמש בשדה הנתונים routingSummaries, שבו עסקנו קודם. אם רוצים, אפשר גם להוסיף פרמטרים נוספים כמו אופן הנסיעה והוראות להתחמק מתשלום אגרה.


"routingParameters": {
    "origin": {
      "latitude": xx.xxxx,
      "longitude": yy.yyyy
    },
    "travelMode":"DRIVE",
    "routeModifiers": {
      "avoidTolls": true
    }
  }

מסלול עם תוצאות חיפוש

תוצאות לדוגמה (סמל המכונית נוסף כדי להציג את מקור החיפוש).

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

סיכום

במדריך הזה למדנו איך לשלב בין שני ממשקי API של Google Maps Platform, Routes ו-Places, כדי לתכנן נסיעה ולמצוא מקומות לאכול אחרי שעתיים בנסיעה. כדי לקבל את התוצאות הטובות ביותר, צריך לקבל קו פוליגון מקודד שמכיל את קואורדינטות הרוחב והאורך של כל שלב בדרך ולהגדיר את המקור של הבקשה 'חיפוש לאורך הנתיב'.

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

השלבים הבאים

מקורות מידע נוספים:

שותפים ביצירת התוכן

Google היא הבעלים של המסמך הזה. הבעלים המקורי של התוכן הוא הגורם הבא.

המחבר הראשי: Mikko Toivanen | מהנדס פתרונות בפלטפורמה של מפות Google