Contents

Preparing the Steps Parameter

Preparing the steps Parameter for Toll Calculation

The Adastra Toll API’s steps parameter is crucial for calculating accurate toll costs for a given route. It requires a specific format: a string of semicolon-separated latitude and longitude pairs, with each coordinate value rounded to exactly 5 decimal places. Failing to adhere to this format can lead to incorrect or failed toll calculations.

This guide will walk you through how to obtain and format the steps parameter correctly, specifically focusing on data retrieved from Google Maps Platform APIs.

steps Parameter Format Requirement

  • Type: string
  • Description: The route’s coordinates string, representing the path the vehicle will take.
  • Format: "latitude,longitude;latitude,longitude;..."
  • Decimal Places: Each latitude and longitude value must be rounded to 5 decimal places.
  • Separator: Points must be separated by a semicolon (;). Latitude and longitude within a point must be separated by a comma (,).
  • Example: "40.90878,29.31577;41.00305,28.96113;41.00312,28.96123"

Obtaining Route Coordinates from Google Maps Platform

The method you use to generate your route will determine how you extract and prepare the coordinate data. We’ll cover the two primary Google Maps Platform APIs for this purpose:

  1. Routes API (routes.googleapis.com/directions/v2:computeRoutes)
  2. Maps JavaScript API (google.maps.DirectionsService)

1. From Google Maps Routes API (computeRoutes)

The Routes API’s computeRoutes method returns the route’s geometry as an encodedPolyline string. This string is a compact, URL-safe representation of the path and needs to be decoded into individual latitude and longitude points before it can be formatted for the Adastra Toll API.

Step 1: Make a computeRoutes Request

Ensure your computeRoutes request is configured to return the encodedPolyline. Using X-Goog-FieldMask: routes.polyline.encodedPolyline is recommended to optimize the response payload.

Example computeRoutes Request Body:

{
  "origin": {
    "location": {
      "latLng": {
        "latitude": 40.712776,
        "longitude": -74.005974
      }
    }
  },
  "destination": {
    "location": {
      "latLng": {
        "latitude": 34.052235,
        "longitude": -118.243683
      }
    }
  },
  "travelMode": "DRIVE",
  "routingPreference": "TRAFFIC_AWARE",
  "computeAlternativeRoutes": false,
  "routeModifiers": {
    "avoidFerries": true
  },
  "languageCode": "en",
  "units": "METRIC",
  "polylineQuality": "HIGH_QUALITY"
}

Step 2: Decode the encodedPolyline

Once you receive the encodedPolyline from the Routes API response, you need to decode it into a series of latitude and longitude coordinates. Many client libraries offer built-in polyline decoding functions. If not, you can use a custom decoder.

JavaScript Example (Decoding and Formatting):

// Helper function to decode an encoded polyline string (standard algorithm)
function decodePolyline(encodedPolyline) {
  const points = [];
  let index = 0;
  let lat = 0;
  let lng = 0;

  while (index < encodedPolyline.length) {
    let b;
    let shift = 0;
    let result = 0;
    do {
      b = encodedPolyline.charCodeAt(index++) - 63;
      result |= (b & 0x1f) << shift;
      shift += 5;
    } while (b >= 0x20);
    const dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
    lat += dlat;

    shift = 0;
    result = 0;
    do {
      b = encodedPolyline.charCodeAt(index++) - 63;
      result |= (b & 0x1f) << shift;
      shift += 5;
    } while (b >= 0x20);
    const dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
    lng += dlng;

    points.push({ latitude: lat / 1e5, longitude: lng / 1e5 });
  }
  return points;
}

// --- Main logic: Fetching from Routes API, decoding, and formatting ---

const originPayload = { /* ... define your origin ... */ };
const destinationPayload = { /* ... define your destination ... */ };
const googleMapsApiKey = 'YOUR_GOOGLE_MAPS_API_KEY';

async function getFormattedAdastraStepsFromRoutesAPI() {
  const routeRequestData = {
    origin: originPayload,
    destination: destinationPayload,
    travelMode: 'DRIVE',
    routingPreference: 'TRAFFIC_AWARE',
    computeAlternativeRoutes: false,
    routeModifiers: { avoidFerries: true },
    languageCode: 'en',
    units: 'METRIC',
    polylineQuality: "HIGH_QUALITY" // Important for detailed routes
  };

  try {
    const response = await fetch(`https://routes.googleapis.com/directions/v2:computeRoutes`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Goog-Api-Key': googleMapsApiKey,
        'X-Goog-FieldMask': 'routes.polyline.encodedPolyline', // Request only the polyline
      },
      body: JSON.stringify(routeRequestData),
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(`Routes API Error: ${response.status} - ${errorData.error.message}`);
    }

    const result = await response.json();

    if (result.routes && result.routes.length > 0) {
      const encodedPolyline = result.routes[0].polyline.encodedPolyline;
      console.log("Routes API Encoded Polyline:", encodedPolyline);

      // 1. Decode the polyline into an array of {latitude, longitude} objects
      const decodedPoints = decodePolyline(encodedPolyline);

      // 2. Format each point to 5 decimal places and join with semicolons
      const stepsString = decodedPoints.map(point =>
        `${point.latitude.toFixed(5)},${point.longitude.toFixed(5)}`
      ).join(';');

      console.log("Formatted Adastra Toll API Steps String (from Routes API):", stepsString);
      return stepsString;

    } else {
      console.warn("No routes found by Google Routes API.");
      return "";
    }

  } catch (error) {
    console.error("Error processing route data from Routes API:", error);
    return "";
  }
}

// Example usage:
// getFormattedAdastraStepsFromRoutesAPI().then(adastraSteps => {
//   if (adastraSteps) {
//     console.log("Adastra Toll API 'steps' parameter ready:", adastraSteps);
//     // Now you can call the Adastra Toll API with this 'steps' string
//     // const adastraTollRequest = { vehicleTypeId: "1", mapsource: "google", steps: adastraSteps };
//     // fetch('https://api.adastrai.com/toll?key=YOUR_ADASTRA_API_KEY', { /* ... */ });
//   }
// });

2. From Google Maps JavaScript API (DirectionsService)

When using the google.maps.DirectionsService (typically in a web browser), the route information is provided in a DirectionsResult object. This object contains routes, each with legs, and each leg contains steps. Every step object has a polyline property, which itself has a path property, an array of google.maps.LatLng objects.

You need to extract these LatLng objects from all steps, combine them into a single array, and then format them.

Step 1: Perform a DirectionsService.route() Request

Ensure your DirectionsService request is made and successfully returns a DirectionsResult.

JavaScript Example (Extracting and Formatting):

// This function assumes you have a `google.maps.DirectionsResult` object
// obtained from a successful `directionsService.route()` call.
async function getFormattedAdastraStepsFromDirectionsService(directionsResult) {
  if (!directionsResult || !directionsResult.routes || directionsResult.routes.length === 0) {
    console.warn("No routes found in DirectionsResult.");
    return "";
  }

  const route = directionsResult.routes[0]; // Usually, you'd pick the first route

  let allRoutePoints = [];

  // Iterate through all legs (segments between waypoints) of the route
  for (const leg of route.legs) {
    // Iterate through all individual steps within each leg
    for (const step of leg.steps) {
      // Each step.polyline.path is an array of google.maps.LatLng objects
      const stepPoints = step.polyline.path.map(latLng => ({
        latitude: latLng.lat(),
        longitude: latLng.lng(),
      }));
      // Concatenate points from this step to the overall list
      allRoutePoints = allRoutePoints.concat(stepPoints);
    }
  }

  // 1. Format the combined points to 5 decimal places
  //    DirectionsService usually provides distinct points, so no explicit deduplication is needed.
  const stepsString = allRoutePoints.map(point =>
    `${point.latitude.toFixed(5)},${point.longitude.toFixed(5)}`
  ).join(';');

  console.log("Formatted Adastra Toll API Steps String (from DirectionsService):", stepsString);
  return stepsString;
}

// Example usage within your DirectionsService callback:
/*
// Assuming 'map' is your google.maps.Map object
// Assuming 'directionsService' is your google.maps.DirectionsService object
// Assuming 'directionsRenderer' is your google.maps.DirectionsRenderer object

function initMapAndCalculateRoute() {
  const request = {
    origin: "Istanbul, Turkey",
    destination: "Ankara, Turkey",
    travelMode: google.maps.TravelMode.DRIVING,
    unitSystem: google.maps.UnitSystem.METRIC,
    avoidFerries: true,
  };

  directionsService.route(request, function(result, status) {
    if (status === google.maps.DirectionsStatus.OK) {
      directionsRenderer.setDirections(result); // Renders the route on the map

      getFormattedAdastraStepsFromDirectionsService(result).then(adastraSteps => {
        if (adastraSteps) {
          console.log("Adastra Toll API 'steps' parameter ready (from DirectionsService):", adastraSteps);
          // Now you can call the Adastra Toll API with this 'steps' string
          // const adastraTollRequest = { vehicleTypeId: "1", mapsource: "google", steps: adastraSteps };
          // fetch('https://api.adastrai.com/toll?key=YOUR_ADASTRA_API_KEY', { /* ... */ });
        }
      });
    } else {
      window.alert("Directions request failed due to " + status);
    }
  });
}

// Call initMapAndCalculateRoute after the Google Maps JavaScript API has loaded.
// Make sure to include the 'routes' library in your API script tag:
// <script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_MAPS_API_KEY&libraries=routes&callback=initMapAndCalculateRoute"></script>
*/

General JavaScript Formatting Example

If you already have your route points in an array of { latitude: number, longitude: number } objects, the final formatting step is straightforward:

// This array represents a hypothetical set of route points.
// You would obtain this from a polyline decoder or by extracting from API responses.
const rawRoutePoints = [
    { latitude: 40.90878345, longitude: 29.31577123 },
    { latitude: 41.00305489, longitude: 28.96112578 },
    { latitude: 41.00312345, longitude: 28.96123456 },
    { latitude: 40.90878000, longitude: 29.31577000 }, // Example with more trailing zeros
];

// Format each point to exactly 5 decimal places and join them with semicolons
const formattedStepsString = rawRoutePoints.map(point =>
    `${point.latitude.toFixed(5)},${point.longitude.toFixed(5)}`
).join(';');

console.log("General formatted steps string:", formattedStepsString);
// Expected output: "40.90878,29.31577;41.00305,28.96113;41.00312,28.96123;40.90878,29.31577"

// This `formattedStepsString` is now ready to be used as the `steps` parameter
// in your Adastra Toll API request.

Important Considerations for steps

  • Decimal Precision: Always ensure you round to exactly 5 decimal places. Using more or fewer decimal places can lead to errors in toll calculation, as the API might not recognize the exact route segments.
  • Coordinate Order: The order of latitude,longitude pairs in the steps string defines the direction of the route. Ensure your points are ordered sequentially from origin to destination.
  • Completeness: Provide a sufficiently detailed set of steps that accurately represents the entire route, especially sections that might include toll roads. Missing segments could result in incomplete or incorrect toll calculations.
  • API Key: Remember to use your correct Google Maps Platform API Key for routing requests and your Adastra Toll API Key for toll calculation requests.
  • Error Handling: Implement robust error handling for both Google Maps API calls and Adastra Toll API calls to gracefully manage issues like invalid routes, API key problems, or unavailable pricing data.

By carefully preparing your steps parameter using the guidelines and examples above, you can ensure accurate and reliable toll calculations with the Adastra Toll API.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "headline": "Preparing the Steps Parameter",
  "description": "Detailed guide on how to prepare the `steps` parameter for the Adastra Toll API, including examples from Google Maps Routes API and Maps JavaScript API.",
  "image": "https://tollapidocs.adastrai.com/featured-image.png",
  "author": {
    "@type": "Organization",
    "name": "Adastra"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Adastra",
    "logo": {
      "@type": "ImageObject",
      "url": "https://tollapidocs.adastrai.com/logo.png"
    }
  },
  "datePublished": "2024-01-03T11:30:00+00:00",
  "dateModified": "2024-01-03T11:30:00+00:00"
}
</script>