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

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

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

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

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

TypeScript

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

async function init(): Promise<void> {
    //  Request the needed libraries.
    const [
        { Map },
        { Place },
        { AdvancedMarkerElement, PinElement },
        { RouteMatrix },
        { LatLngBounds, UnitSystem },
    ] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('places'),
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('routes'),
        google.maps.importLibrary('core'),
    ]);

    const bounds = new LatLngBounds();

    map = new Map(document.getElementById('map')!, {
        zoom: 8,
        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 destinations = [destinationA, destinationB];
    const origins = [origin1, origin2];
    const request: google.maps.routes.ComputeRouteMatrixRequest = {
        origins,
        destinations,
        travelMode: 'DRIVING',
        units: 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 origins) {
        if (origin.location) {
            const pin = new PinElement({
                glyphText: 'O',
                glyphColor: 'white',
                background: '#137333',
                borderColor: 'white',
            });
            const marker = new AdvancedMarkerElement({
                map,
                position: origin.location,
                title: `Origin: ${origin.displayName}`,
            });
            marker.append(pin);
            markers.push(marker);
            bounds.extend(origin.location);
        }
    }

    // Add markers for the destinations.
    for (const destination of destinations) {
        if (destination.location) {
            const pin = new PinElement({
                glyphText: 'D',
                glyphColor: 'white',
                background: '#C5221F',
                borderColor: 'white',
            });

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

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

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

void init();

JavaScript

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

async function init() {
    //  Request the needed libraries.
    const [
        { Map },
        { Place },
        { AdvancedMarkerElement, PinElement },
        { RouteMatrix },
        { LatLngBounds, UnitSystem },
    ] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('places'),
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('routes'),
        google.maps.importLibrary('core'),
    ]);

    const bounds = new LatLngBounds();

    map = new Map(document.getElementById('map'), {
        zoom: 8,
        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 destinations = [destinationA, destinationB];
    const origins = [origin1, origin2];
    const request = {
        origins,
        destinations,
        travelMode: 'DRIVING',
        units: 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 origins) {
        if (origin.location) {
            const pin = new PinElement({
                glyphText: 'O',
                glyphColor: 'white',
                background: '#137333',
                borderColor: 'white',
            });
            const marker = new AdvancedMarkerElement({
                map,
                position: origin.location,
                title: `Origin: ${origin.displayName}`,
            });
            marker.append(pin);
            markers.push(marker);
            bounds.extend(origin.location);
        }
    }

    // Add markers for the destinations.
    for (const destination of destinations) {
        if (destination.location) {
            const pin = new PinElement({
                glyphText: 'D',
                glyphColor: 'white',
                background: '#C5221F',
                borderColor: 'white',
            });

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

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

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

void init();

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>
        <script>
            // prettier-ignore
            (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: "GOOGLE_MAPS_API_KEY"
            });
        </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>
    </body>
</html>

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

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

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

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

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

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

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

TypeScript

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

JavaScript

const destinations = [destinationA, destinationB];
const origins = [origin1, origin2];
const request = {
    origins,
    destinations,
    travelMode: 'DRIVING',
    units: 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.

מידע נוסף על מסלולי מעבר