Google Maps JavaScript API v3

Geometry Library

  1. Overview
  2. Spherical Geometry Concepts
    1. Distance and Area Functions
    2. Navigation Functions
  3. Geometry Encoding
  4. Polygon and Polyline Functions
    1. containsLocation()
    2. isLocationOnEdge()

Overview

The concepts within this document refer to features only available within the google.maps.geometry library. This library is not loaded by default when you load the Maps Javascript API but must be explicitly specified through use of a libraries bootstrap parameter.

See the Libraries Overview for more information.

The Google Maps JavaScript API V3 geometry library provides utility functions for the computation of geometric data on the surface of the Earth. The library includes three namespaces:

  • spherical contains spherical geometry utilities allowing you to compute angles, distances and areas from latitudes and longitudes.
  • encoding contains utilities for encoding and decoding polyline paths according to the Encoded Polyline Algorithm.
  • poly contains utility functions for computations involving polygons and polylines.

The google.maps.geometry library does not contain any classes; instead, the library contains static methods on the above namespaces.

Spherical Geometry Concepts

The images within the Google Maps Javascript API are two-dimensional and "flat." The Earth, however, is three-dimensional, and is often approximated as either an oblate spheroid or more simply as a sphere. Within the Maps API we use a sphere, and to represent the Earth on a two-dimensional flat surface — such as your computer screen — the Maps API uses a projection.

Within 2D projections, appearances can sometimes be deceiving. Because the map projection necessarily requires some distortion, simple Euclidian geometry often is not applicable. For example, the shortest distance between two points on a sphere is not a straight line, but a great circle (a type of geodesic), and the angles that make up a triangle on the surface of a sphere add up to more than 180 degrees.

Because of these differences, geometric functions on a sphere (or on its projection) necessitate using Spherical Geometry to calculate such constructs as distance, heading, and area. Utilities to calculate these spherical geometric constructs are contained within the Maps API's google.maps.geometry.spherical namespace. This namespace provides static methods for computing scalar values from spherical coordinates (latitudes and longitudes).

Distance and Area Functions

The distance between two points is the length of the shortest path between them. This shortest path is called a geodesic. On a sphere all geodesics are segments of a great circle. To compute this distance, call computeDistanceBetween(), passing it two LatLng objects.

You may instead use computeLength() to calculate the length of a given path if you have several locations.

Distance results are expressed in meters.

To compute the area (in square meters) of a polygonal area, call computeArea(), passing the array of LatLng objects defining a closed loop.

When navigating on a sphere, a heading is the angle of a direction from a fixed reference point, usually true north. Within the Google Maps API, a heading is defined in degrees from true north, where headings are measured clockwise from true north (0 degrees). You may compute this heading between two locations with the computeHeading() method, passing it two from and to LatLng objects.

Given a particular heading, an origin location, and the distance to travel (in meters), you can calculate the destination coordinates using computeOffset().

Given two LatLng objects and value between 0 and 1, you may also calculate a destination between them using the interpolate() method, which performs spherical linear interpolation between the two locations, where the value indicates the fractional distance to travel along the path from the origin to the destination.

The following example creates two polylines when you click two points on the map — one geodesic and one "straight" line connecting the two locations — and computes the heading for travelling between the two points:

var poly;
var geodesic;
var map;
var clickcount = 0;

function initialize() {
  var atlantic = new google.maps.LatLng(34, -40.605);
  var mapOptions = {
    zoom: 4,
    center: atlantic
  };

  map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

  var polyOptions = {
    strokeColor: '#FF0000',
    strokeOpacity: 1.0,
    strokeWeight: 3
  }
  poly = new google.maps.Polyline(polyOptions);
  poly.setMap(map);
  var geodesicOptions = {
    strokeColor: '#CC0099',
    strokeOpacity: 1.0,
    strokeWeight: 3,
    geodesic: true
  }
  geodesic = new google.maps.Polyline(geodesicOptions);
  geodesic.setMap(map);

  // Add a listener for the click event
  google.maps.event.addListener(map, 'click', addLocation);
}

function addLocation(event) {
  clickcount++;
  if (clickcount == 1) {
    addOrigin(event);
  }
  if (clickcount == 2) {
    addDestination(event);
  }
}

function addOrigin(event) {
  clearPaths();
  var path = poly.getPath();
  path.push(event.latLng);
  var gPath = geodesic.getPath();
  gPath.push(event.latLng);
}

function addDestination(event) {
  var path = poly.getPath();
  path.push(event.latLng);
  var gPath = geodesic.getPath();
  gPath.push(event.latLng);
  adjustHeading();
  clickcount = 0;
}

function clearPaths() {
  var path = poly.getPath();
  while (path.getLength()) {
    path.pop();
  }
  var gPath = geodesic.getPath();
  while (gPath.getLength()) {
    gPath.pop();
  }
}

function adjustHeading() {
  var path = poly.getPath();
  var pathSize = path.getLength();
  var heading = google.maps.geometry.spherical.computeHeading(path.getAt(0), path.getAt(pathSize - 1));
  document.getElementById('heading').value = heading;
  document.getElementById('origin').value = path.getAt(0).lat()
      + "," + path.getAt(0).lng();
  document.getElementById('destination').value = path.getAt(pathSize - 1).lat()
      + "," + path.getAt(pathSize - 1).lng();
}

View example (geometry-headings.html)

Encoding Methods

Paths within the Javascript Maps API V3 are often specified as an Array of LatLng objects. However, passing around such an array is often bulky. You may instead use Google's polyline encoding algorithm to compress a given path, which you can later decompress through decoding.

The geometry library contains an encoding namespace for utilities to encode and decode polylines.

The static method encodePath() encodes the given path. You may pass either an array of LatLngs or an MVCArray (which is returned by Polyline.getPath()).

To decode an encoded path, simply call decodePath() passing the method the encoded string.

The following example displays a map of Oxford, Mississippi. Clicking on the map adds a point to a polyline. As the polyline is constructed, its encoding appears underneath.

var poly;
var map;

function initialize() {
  var oxford = new google.maps.LatLng(34.3664951, -89.5192484);
  var mapOptions = {
    zoom: 14,
    center: oxford
  };

  map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

  var polyOptions = {
    strokeColor: '#000000',
    strokeOpacity: 1.0,
    strokeWeight: 3
  }
  poly = new google.maps.Polyline(polyOptions);
  poly.setMap(map);

  // Add a listener for the click event
  google.maps.event.addListener(map, 'click', addLatLng);
}

/**
 * Handles click events on a map, and adds a new point to the Polyline.
 * Updates the encoding text area with the path's encoded values.
 */
function addLatLng(event) {

  var path = poly.getPath();
  path.push(event.latLng);

  // Update the text field to display the polyline encodings
  var encodeString = google.maps.geometry.encoding.encodePath(path);
  if (encodeString != null) {
    document.getElementById('encodedPolyline').value = encodeString;
  }
}

View example (geometry-encodings.html)

Polygon and Polyline functions

The geometry library's poly namespace contains utility functions that determine whether a given point is inside or near a polygon or polyline.

containsLocation()

containsLocation(point:LatLng, polygon:Polygon)

To find whether a given point falls within a polygon, pass the point and the polygon to google.maps.geometry.poly.containsLocation(). The functions returns true if the point is within the polygon or on its edge.

The following code writes 'true' to the browser console if the user's click falls within the defined triangle; otherwise, it writes 'false'.

function initialize() {
  var mapOptions = {
    zoom: 5,
    center: new google.maps.LatLng(24.886, -70.269),
    mapTypeId: google.maps.MapTypeId.TERRAIN
  };

  var map = new google.maps.Map(document.getElementById('map-canvas'),
      mapOptions);

  var bermudaTriangle = new google.maps.Polygon({
    paths: [
      new google.maps.LatLng(25.774, -80.190),
      new google.maps.LatLng(18.466, -66.118),
      new google.maps.LatLng(32.321, -64.757)
    ]
  });

  google.maps.event.addListener(map, 'click', function(event) {
    console.log(google.maps.geometry.poly.containsLocation(event.latLng, bermudaTriangle));
  });
}

google.maps.event.addDomListener(window, 'load', initialize);

Another version of this code draws a red circle on the map if the click falls within the Bermuda Triangle, and green otherwise:

View example (poly-containsLocation)

isLocationOnEdge()

isLocationOnEdge(point:LatLng, poly:Polygon|Polyline, tolerance?:number)

To determine whether a point falls on or near a polyline, or on or near the edge of a polygon, pass the point, the polyline/polygon, and optionally a tolerance value in degrees to google.maps.geometry.poly.isLocationOnEdge(). The function returns true if the distance between the point and the closest point on the line or edge falls within the specified tolerance. The default tolerance value is 10-9 degrees.

function initialize() {
  var mapOptions = {
    zoom: 5,
    center: new google.maps.LatLng(24.886, -70.269),
    mapTypeId: google.maps.MapTypeId.TERRAIN
  };

  var map = new google.maps.Map(document.getElementById('map-canvas'),
      mapOptions);

  var cascadiaFault = new google.maps.Polyline({
    paths: [
      new google.maps.LatLng(49.95, -128.1),
      new google.maps.LatLng(46.26, -126.3),
      new google.maps.LatLng(40.3, -125.4)
    ]
  });

  var myPosition = new google.maps.LatLng(43.0, -125.9, 10e-7);

  if (google.maps.geometry.poly.isLocationOnEdge(myPosition, cascadiaFault)) {
    alert("Relocate!");
  }
}

google.maps.event.addDomListener(window, 'load', initialize);

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.