קבלת מטריצת מסלול

מפתחים באזור הכלכלי האירופי (EEA)

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

קוד מקור מלא לדוגמה

בדוגמה הזו מוצג איך להשתמש במחלקה Route Matrix כדי לחשב את המרחקים ומשך הנסיעה בין כמה נקודות מוצא ליעדים.

TypeScript

// Initialize and add the map.
let map;
let markers: google.maps.marker.AdvancedMarkerElement[] = [];
let center = { lat: 51.55, lng: -1.8 };

async function initMap(): Promise<void> {
  //  Request the needed libraries.
  //@ts-ignore
  const [{Map}, {Place}, {AdvancedMarkerElement, PinElement}, {RouteMatrix}] = await Promise.all([
    google.maps.importLibrary('maps') as Promise<google.maps.MapsLibrary>,
    google.maps.importLibrary('places') as Promise<google.maps.PlacesLibrary>,
    google.maps.importLibrary('marker') as Promise<google.maps.MarkerLibrary>,
    google.maps.importLibrary('routes') as Promise<google.maps.RoutesLibrary>
  ]);

  const bounds = new google.maps.LatLngBounds();

  map = new Map(document.getElementById('map') as HTMLElement, {
    zoom: 8,
    center: center,
    mapId: 'DEMO_MAP_ID',
  });

  // Build the request using Place instances.
  const origin1 = new Place({
    id: "ChIJ83WZp86p2EcRbMrkYqGncBQ", // Greenwich, London, UK
  });
  const origin2 = new Place({
    id: "ChIJCSkVvleJc0gR8HHaTGpajKc", // Southampton, UK
  });
  const destinationA = new Place({
    id: "ChIJYdizgWaDcUgRH9eaSy6y5I4", // Bristol, UK
  });
  const destinationB = new Place({
    id: "ChIJ9VPsNNQCbkgRDmeGZdsGNBQ", // Cardiff, UK
  });

  await Promise.all([
    origin1.fetchFields({ fields: ['location', 'displayName']}),
    origin2.fetchFields({ fields: ['location', 'displayName']}),
    destinationA.fetchFields({ fields: ['location', 'displayName']}),
    destinationB.fetchFields({ fields: ['location', 'displayName']}),
  ]);

  const request = {
    origins: [origin1, origin2], 
    destinations: [destinationA, destinationB],
    travelMode: 'DRIVING',
    units: google.maps.UnitSystem.METRIC,
    fields: ['distanceMeters', 'durationMillis', 'condition'],
  };

  // Show the request.
  (document.getElementById("request") as HTMLDivElement).innerText =
    JSON.stringify(request, null, 2);

  // Get the RouteMatrix response.
  const response = await RouteMatrix.computeRouteMatrix(request); 

  // Show the response.
  (document.getElementById("response") as HTMLDivElement).innerText =
    JSON.stringify(response, null, 2);

  // Add markers for the origins.
  for (const origin of request.origins) {
    if (origin.location) {
      const pin = new PinElement({
        //@ts-ignore
        glyphText: "O",
        glyphColor: "white",
        background: "#137333",
        borderColor: "white",
      });
      const marker = new AdvancedMarkerElement({
        map,
        position: origin.location,
        content: pin.element,
        title: `Origin: ${origin.displayName}`,
      });
      markers.push(marker);
      bounds.extend(origin.location);
    }
  }

  // Add markers for the destinations.
  for (let i = 0; i < request.destinations.length; i++) {
    const destination = request.destinations[i];
    if (destination.location) {
      const pin = new PinElement({
        //@ts-ignore
        glyphText: "D",
        glyphColor: "white",
        background: "#C5221F",
        borderColor: "white",
      });

      const marker = new AdvancedMarkerElement({
        map,
        position: destination.location,
        content: pin.element,
        title: `Destination: ${destination.displayName}`,
      });

      markers.push(marker);
      bounds.extend(destination.location);
    }
  }

  // Fit the map to the bounds of all markers.
  map.fitBounds(bounds);
}

initMap();

JavaScript

// Initialize and add the map.
let map;
let markers = [];
let center = { lat: 51.55, lng: -1.8 };
async function initMap() {
    //  Request the needed libraries.
    //@ts-ignore
    const [{ Map }, { Place }, { AdvancedMarkerElement, PinElement }, { RouteMatrix }] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('places'),
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('routes')
    ]);
    const bounds = new google.maps.LatLngBounds();
    map = new Map(document.getElementById('map'), {
        zoom: 8,
        center: center,
        mapId: 'DEMO_MAP_ID',
    });
    // Build the request using Place instances.
    const origin1 = new Place({
        id: "ChIJ83WZp86p2EcRbMrkYqGncBQ", // Greenwich, London, UK
    });
    const origin2 = new Place({
        id: "ChIJCSkVvleJc0gR8HHaTGpajKc", // Southampton, UK
    });
    const destinationA = new Place({
        id: "ChIJYdizgWaDcUgRH9eaSy6y5I4", // Bristol, UK
    });
    const destinationB = new Place({
        id: "ChIJ9VPsNNQCbkgRDmeGZdsGNBQ", // Cardiff, UK
    });
    await Promise.all([
        origin1.fetchFields({ fields: ['location', 'displayName'] }),
        origin2.fetchFields({ fields: ['location', 'displayName'] }),
        destinationA.fetchFields({ fields: ['location', 'displayName'] }),
        destinationB.fetchFields({ fields: ['location', 'displayName'] }),
    ]);
    const request = {
        origins: [origin1, origin2],
        destinations: [destinationA, destinationB],
        travelMode: 'DRIVING',
        units: google.maps.UnitSystem.METRIC,
        fields: ['distanceMeters', 'durationMillis', 'condition'],
    };
    // Show the request.
    document.getElementById("request").innerText =
        JSON.stringify(request, null, 2);
    // Get the RouteMatrix response.
    const response = await RouteMatrix.computeRouteMatrix(request);
    // Show the response.
    document.getElementById("response").innerText =
        JSON.stringify(response, null, 2);
    // Add markers for the origins.
    for (const origin of request.origins) {
        if (origin.location) {
            const pin = new PinElement({
                //@ts-ignore
                glyphText: "O",
                glyphColor: "white",
                background: "#137333",
                borderColor: "white",
            });
            const marker = new AdvancedMarkerElement({
                map,
                position: origin.location,
                content: pin.element,
                title: `Origin: ${origin.displayName}`,
            });
            markers.push(marker);
            bounds.extend(origin.location);
        }
    }
    // Add markers for the destinations.
    for (let i = 0; i < request.destinations.length; i++) {
        const destination = request.destinations[i];
        if (destination.location) {
            const pin = new PinElement({
                //@ts-ignore
                glyphText: "D",
                glyphColor: "white",
                background: "#C5221F",
                borderColor: "white",
            });
            const marker = new AdvancedMarkerElement({
                map,
                position: destination.location,
                content: pin.element,
                title: `Destination: ${destination.displayName}`,
            });
            markers.push(marker);
            bounds.extend(destination.location);
        }
    }
    // Fit the map to the bounds of all markers.
    map.fitBounds(bounds);
}
initMap();

CSS

/*
 * Always set the map height explicitly to define the size of the div element
 * that contains the map.
 */
/* Optional: Makes the sample page fill the window. */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#container {
  height: 100%;
  display: flex;
}

#sidebar {
  flex-basis: 15rem;
  flex-grow: 1;
  padding: 1rem;
  max-width: 30rem;
  height: 100%;
  box-sizing: border-box;
  overflow: auto;
}

#map {
  flex-basis: 0;
  flex-grow: 4;
  height: 100%;
}

#sidebar {
  flex-direction: column;
}

HTML

<html>
  <head>
    <title>Route matrix</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="container">
      <div id="map"></div>
      <div id="sidebar">
        <h3 style="flex-grow: 0">Request</h3>
        <pre style="flex-grow: 1" id="request"></pre>
        <h3 style="flex-grow: 0">Response</h3>
        <pre style="flex-grow: 1" id="response"></pre>
      </div>
    </div>
    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "beta"});</script>
  </body>
</html>

דוגמה לניסיון

מגבלות על בקשות

השיטה computeRouteMatrix אוכפת את מגבלות הבקשה הבאות לנקודות ציון באמצעות כתובת או מופעים של מקומות, ולפריטים. הפריטים הם המסלולים בין כל נקודת מוצא לכל יעד במטריצת מסלולים, ולכן מספר הפריטים הוא מספר נקודות המוצא כפול מספר היעדים. לדוגמה, אם יש לכם 10 נקודות מוצא ו-10 יעדים, יהיו לכם 100 פריטים:

  • מספר הפריטים לא יכול להיות גדול מ-625 במסלולים שהם לא מסלולי TRANSIT.
  • אם מציינים TRANSIT נתיב, מספר הפריטים לא יכול להיות יותר מ-100.
  • אם מציינים TRAFFIC_AWARE_OPTIMAL, מספר הפריטים לא יכול להיות גדול מ-100.
  • אם מציינים מקורות או יעדים באמצעות כתובות או מופעים של מקומות, אפשר לציין עד 50 בסך הכול בדרך הזו.

פרטים נוספים זמינים במאמר בנושא קבלת מסלול לתחבורה ציבורית.

דוגמה לבקשה של מטריצת מסלולים

בדוגמה הבאה מוצג ComputeRouteMatrixRequest. בדוגמה הזו: הפעולות הבאות מתבצעות:

  • הדוגמה מראה איך מציינים מערך של שתי נקודות מוצא ושתי נקודות יעד. השיטה מחשבת מסלול מכל נקודת מוצא לכל נקודת יעד, כך שהתשובה מכילה ארבעה מסלולים.
    במערך, האינדקס של הרכיב הראשון הוא 0, האינדקס של הרכיב השני הוא 1 וכן הלאה.
  • מציינים את השדות שיוחזרו. בדוגמה הזו, הבקשה מוגדרת להחזרת הערכים durationMillis, distanceMeters ו-condition לכל מסלול.

TypeScript

const request = {
  origins: [origin1, origin2], 
  destinations: [destinationA, destinationB],
  travelMode: 'DRIVING',
  units: google.maps.UnitSystem.METRIC,
  fields: ['distanceMeters', 'durationMillis', 'condition'],
};

JavaScript

const request = {
    origins: [origin1, origin2],
    destinations: [destinationA, destinationB],
    travelMode: 'DRIVING',
    units: google.maps.UnitSystem.METRIC,
    fields: ['distanceMeters', 'durationMillis', 'condition'],
};

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

"matrix": {
  "rows": [
    {
      "items": [
        {
          "condition": "ROUTE_EXISTS",
          "distanceMeters": 202587,
          "durationMillis": 10040000
        },
        {
          "condition": "ROUTE_EXISTS",
          "distanceMeters": 252734,
          "durationMillis": 12240000
        }
      ]
    },
    {
      "items": [
        {
          "condition": "ROUTE_EXISTS",
          "distanceMeters": 166135,
          "durationMillis": 6596000
        },
        {
          "condition": "ROUTE_EXISTS",
          "distanceMeters": 216282,
          "durationMillis": 8797000
        }
      ]
    }
  ]
}
    

כדי לזהות כל נתיב בתוצאה, משתמשים באינדקס של נקודת המוצא והיעד כדי למצוא את הערך RouteMatrixItem המתאים במערך הדו-ממדי. לדוגמה, הרכיב RouteMatrixItem שמתאר את המסלול שמחושב מנקודת המוצא באינדקס 1 ועד ליעד באינדקס 0 בבקשה יהיה ברכיב השני במערך RouteMatrix.rows וברכיב הראשון במערך RouteMatrixRow.items.

קטע הקוד הבא מראה איך לזהות את RouteMatrixItem כדי למצוא את המסלול בין נקודת מוצא ליעד ספציפיים:

// Find the route for origin 'x' and destination 'y'.
const {matrix} = await RouteMatrix.computeRouteMatrix(request);
const myRouteMatrixItem = matrix.rows[x].items[y];
    

בחירת שדות להחזרה

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

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

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

fields: ['durationMillis', 'distanceMeters', 'condition'],
    

קובעים באילו מסכות שדות להשתמש

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

  1. שליחת בקשה לכל השדות באמצעות מסכת שדות של ['*'].
  2. מעיינים בהיררכיה של השדות בכיתה RouteMatrixItem כדי למצוא את השדות הרצויים.
  3. בוחרים את שדות המידע באמצעות ההיררכיה של השדות שמוצגת בשלב הקודם, בפורמט הבא:

    topLevelField[.secondLevelField][.thirdLevelField][...]

לדוגמה, עבור ה-RouteMatrixItem הזה:

  "travelAdvisory": {
    "fuelConsumptionMicroliters": 0,
    "tollInfo": {
      "estimatedPrices": [
        {
          "currencyCode": "USD",
          "units": 4,
          "nanos": 400000000
        }
      ]
    }
  },
    

אם רוצים להחזיר רק את השדה tollInfo עבור RouteMatrixItem, מסכת השדות תהיה כדלקמן:

fields: ['travelAdvisory.tollInfo']

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

fields: ['travelAdvisory.fuelConsumptionMicroliters']

אם רוצים לבקש את שניהם, מסכת השדות תהיה:

fields: ['travelAdvisory.fuelConsumptionMicroliters', 'travelAdvisory.tollInfo']

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

fields: ['travelAdvisory']

בקשה למטריצת מסלולי תחבורה ציבורית

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

  • הגדרת travelMode לערך TRANSIT
  • מבקשים את השדה travelAdvisory.

מידע נוסף על מסלולי תחבורה ציבורית