Bibliothèque de géométrie

  1. Présentation
  2. Concepts de géométrie sphérique
    1. Fonctions de distance et de superficie
    2. Fonctions de navigation
  3. Encodage des géométries
  4. Fonctions de polygone et de polyligne
    1. containsLocation()
    2. isLocationOnEdge()

Présentation

Les concepts présentés dans ce document font référence aux fonctionnalités disponibles uniquement dans la bibliothèque google.maps.geometry. Cette bibliothèque n'est pas chargée par défaut lorsque vous chargez l'API Maps JavaScript, mais doit être spécifiée explicitement à l'aide d'un paramètre bootstrap libraries. Pour en savoir plus, consultez la présentation des bibliothèques.

La bibliothèque de géométrie de l'API Maps JavaScript fournit des fonctions utilitaires permettant de calculer des données géométriques à la surface de la Terre. Cette bibliothèque comprend trois espaces de noms :

  • spherical contient des utilitaires de géométrie sphérique qui vous permettent de calculer des angles, des distances et des zones à partir de latitudes et de longitudes.
  • encoding contient les utilitaires d'encodage et de décodage des tracés de polylignes conformément à l'algorithme de polyligne encodée.
  • poly contient des fonctions utilitaires pour les calculs impliquant des polygones et des polylignes.

La bibliothèque google.maps.geometry ne contient aucune classe, mais des méthodes statiques sur les espaces de noms ci-dessus.

Concepts de géométrie sphérique

Les images de l'API Maps JavaScript sont bidimensionnelles et "plates". Cependant, la Terre est tridimensionnelle et est souvent décrite comme s'approchant d'un sphéroïde oblate ou, plus souvent, d'une sphère. Dans l'API Google Maps, nous utilisons une sphère. Pour représenter la Terre sur une surface plane bidimensionnelle (telle que l'écran de votre ordinateur), l'API Google Maps utilise une projection.

Dans les projections en 2D, les apparences peuvent parfois être trompeuses. Dans la mesure où une projection de carte implique nécessairement un certain degré de distorsion, la simple géométrie euclidienne n'est souvent pas applicable. Par exemple, la distance la plus courte entre deux points sur une sphère n'est pas la ligne droite, mais un grand cercle (un type de géodésique). Quant aux angles qui forment un triangle sur la surface d'une sphère, leur somme est supérieure à 180 degrés.

En raison de ces différences, les fonctions géométriques sur une sphère (ou sur sa projection) nécessitent d'utiliser la géométrie sphérique pour calculer des structures telles que la distance, le cap et la superficie. Les utilitaires permettant de calculer ces structures géométriques sphériques sont contenus dans l'espace de noms google.maps.geometry.spherical de l'API Maps. Cet espace de noms fournit des méthodes statiques pour le calcul des valeurs scalaires à partir de coordonnées sphériques (latitudes et longitudes).

Fonctions de distance et de superficie

La distance entre deux points est la longueur du tracé le plus court entre ces deux points. Ce tracé le plus court est appelé une géodésique. Sur une sphère, toutes les géodésiques sont les segments d'un grand cercle. Pour calculer cette distance, appelez computeDistanceBetween() en lui transmettant deux objets LatLng.

Vous pouvez également utiliser computeLength() pour calculer la longueur d'un tracé donné si vous disposez de plusieurs emplacements.

Les résultats de distance sont exprimés en mètres.

Pour calculer la superficie (en mètres carrés) d'une zone polygonale, appelez computeArea(), en transmettant le tableau d'objets LatLng définissant une boucle fermée.

Lorsque l'on navigue sur une sphère, on appelle cap l'angle d'une direction à partir d'un point de référence fixe, généralement le nord géographique. Dans l'API Google Maps, les caps sont définis en degrés et mesurés dans le sens horaire à partir du nord géographique (0 degré). Vous pouvez calculer ce cap entre deux emplacements à l'aide de la méthode computeHeading() en lui transmettant deux objets from etto LatLng.

Avec un cap, un lieu de départ et la distance à parcourir (en mètres), vous pouvez calculer les coordonnées de destination à l'aide de computeOffset().

Pour deux objets LatLng dont la valeur est comprise entre 0 et 1, vous pouvez également calculer une destination entre eux à l'aide de la méthode interpolate(), qui effectue une interpolation linéaire sphérique entre les deux emplacements, où la valeur indique la distance fractionnaire à parcourir le long du tracé du point de départ à la destination.

L'exemple suivant crée deux polylignes lorsque vous cliquez sur deux points de la carte (une géodésique et une ligne "droite" connectant les deux points géographiques) et calcule le cap pour se rendre d'un point à l'autre :

TypeScript

// This example requires the Geometry library. Include the libraries=geometry
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry">

let marker1: google.maps.Marker, marker2: google.maps.Marker;
let poly: google.maps.Polyline, geodesicPoly: google.maps.Polyline;

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 4,
      center: { lat: 34, lng: -40.605 },
    }
  );

  map.controls[google.maps.ControlPosition.TOP_CENTER].push(
    document.getElementById("info") as HTMLElement
  );

  marker1 = new google.maps.Marker({
    map,
    draggable: true,
    position: { lat: 40.714, lng: -74.006 },
  });

  marker2 = new google.maps.Marker({
    map,
    draggable: true,
    position: { lat: 48.857, lng: 2.352 },
  });

  const bounds = new google.maps.LatLngBounds(
    marker1.getPosition() as google.maps.LatLng,
    marker2.getPosition() as google.maps.LatLng
  );

  map.fitBounds(bounds);

  google.maps.event.addListener(marker1, "position_changed", update);
  google.maps.event.addListener(marker2, "position_changed", update);

  poly = new google.maps.Polyline({
    strokeColor: "#FF0000",
    strokeOpacity: 1.0,
    strokeWeight: 3,
    map: map,
  });

  geodesicPoly = new google.maps.Polyline({
    strokeColor: "#CC0099",
    strokeOpacity: 1.0,
    strokeWeight: 3,
    geodesic: true,
    map: map,
  });

  update();
}

function update() {
  const path = [
    marker1.getPosition() as google.maps.LatLng,
    marker2.getPosition() as google.maps.LatLng,
  ];

  poly.setPath(path);
  geodesicPoly.setPath(path);

  const heading = google.maps.geometry.spherical.computeHeading(
    path[0],
    path[1]
  );

  (document.getElementById("heading") as HTMLInputElement).value =
    String(heading);
  (document.getElementById("origin") as HTMLInputElement).value = String(
    path[0]
  );
  (document.getElementById("destination") as HTMLInputElement).value = String(
    path[1]
  );
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

// This example requires the Geometry library. Include the libraries=geometry
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry">
let marker1, marker2;
let poly, geodesicPoly;

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: { lat: 34, lng: -40.605 },
  });

  map.controls[google.maps.ControlPosition.TOP_CENTER].push(
    document.getElementById("info"),
  );
  marker1 = new google.maps.Marker({
    map,
    draggable: true,
    position: { lat: 40.714, lng: -74.006 },
  });
  marker2 = new google.maps.Marker({
    map,
    draggable: true,
    position: { lat: 48.857, lng: 2.352 },
  });

  const bounds = new google.maps.LatLngBounds(
    marker1.getPosition(),
    marker2.getPosition(),
  );

  map.fitBounds(bounds);
  google.maps.event.addListener(marker1, "position_changed", update);
  google.maps.event.addListener(marker2, "position_changed", update);
  poly = new google.maps.Polyline({
    strokeColor: "#FF0000",
    strokeOpacity: 1.0,
    strokeWeight: 3,
    map: map,
  });
  geodesicPoly = new google.maps.Polyline({
    strokeColor: "#CC0099",
    strokeOpacity: 1.0,
    strokeWeight: 3,
    geodesic: true,
    map: map,
  });
  update();
}

function update() {
  const path = [marker1.getPosition(), marker2.getPosition()];

  poly.setPath(path);
  geodesicPoly.setPath(path);

  const heading = google.maps.geometry.spherical.computeHeading(
    path[0],
    path[1],
  );

  document.getElementById("heading").value = String(heading);
  document.getElementById("origin").value = String(path[0]);
  document.getElementById("destination").value = String(path[1]);
}

window.initMap = initMap;
Voir l'exemple

Essayer l'exemple

Méthodes d'encodage

Les trajets dans l'API Maps JavaScript sont souvent spécifiés en tant qu'Array des objets LatLng. Ce type de tableau est toutefois volumineux, ce qui rend sa transmission difficile. À la place, vous pouvez utiliser l'algorithme d'encodage de polyligne de Google pour compresser un tracé, que vous pouvez décompresser plus tard par décodage.

La bibliothèque geometry contient un espace de noms encoding permettant aux utilitaires d'encoder et de décoder les polylignes.

La méthode statique encodePath() encode le tracé donné. Vous pouvez transmettre un tableau de plusieurs LatLng ou un MVCArray (renvoyé par Polyline.getPath()).

Pour décoder un tracé encodé, appelez decodePath() en transmettant la méthode à la chaîne encodée.

L'exemple suivant montre un plan d'Oxford, Mississippi. Cliquer sur le plan permet d'ajouter un point à une polyligne. À mesure que la polyligne est construite, son encodage apparaît en dessous.

TypeScript

// This example requires the Geometry library. Include the libraries=geometry
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry">

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 14,
      center: { lat: 34.366, lng: -89.519 },
    }
  );
  const poly = new google.maps.Polyline({
    strokeColor: "#000000",
    strokeOpacity: 1,
    strokeWeight: 3,
    map: map,
  });

  // Add a listener for the click event
  google.maps.event.addListener(map, "click", (event) => {
    addLatLngToPoly(event.latLng, poly);
  });
}

/**
 * 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 addLatLngToPoly(
  latLng: google.maps.LatLng,
  poly: google.maps.Polyline
) {
  const path = poly.getPath();

  // Because path is an MVCArray, we can simply append a new coordinate
  // and it will automatically appear
  path.push(latLng);

  // Update the text field to display the polyline encodings
  const encodeString = google.maps.geometry.encoding.encodePath(path);

  if (encodeString) {
    (document.getElementById("encoded-polyline") as HTMLInputElement).value =
      encodeString;
  }
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

// This example requires the Geometry library. Include the libraries=geometry
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry">
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 14,
    center: { lat: 34.366, lng: -89.519 },
  });
  const poly = new google.maps.Polyline({
    strokeColor: "#000000",
    strokeOpacity: 1,
    strokeWeight: 3,
    map: map,
  });

  // Add a listener for the click event
  google.maps.event.addListener(map, "click", (event) => {
    addLatLngToPoly(event.latLng, poly);
  });
}

/**
 * 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 addLatLngToPoly(latLng, poly) {
  const path = poly.getPath();

  // Because path is an MVCArray, we can simply append a new coordinate
  // and it will automatically appear
  path.push(latLng);

  // Update the text field to display the polyline encodings
  const encodeString = google.maps.geometry.encoding.encodePath(path);

  if (encodeString) {
    document.getElementById("encoded-polyline").value = encodeString;
  }
}

window.initMap = initMap;
Voir l'exemple

Essayer l'exemple

Fonctions de polygone et de polyligne

L'espace de noms poly de la bibliothèque de géométrie contient des fonctions utilitaires qui déterminent si un point donné se trouve à l'intérieur ou à proximité d'un polygone ou d'une polyligne.

containsLocation()

containsLocation(point:LatLng, polygon:Polygon)

Pour déterminer si un point donné se trouve dans un polygone, transmettez ces deux éléments à google.maps.geometry.poly.containsLocation(). Les fonctions renvoient "true" si le point se trouve à l'intérieur ou sur le périmètre du polygone.

Le code suivant écrit "true" dans la console du navigateur si l'utilisateur clique dans le triangle défini. Dans le cas contraire, il écrit "false".

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

  var map = new google.maps.Map(document.getElementById('map'),
      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);

Une autre version de ce code dessine un triangle bleu sur la carte si l'utilisateur clique dans le triangle des Bermudes, et un cercle rouge s'il clique ailleurs :

Voir un exemple

isLocationOnEdge()

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

Pour déterminer si un point se trouve sur une polyligne ou à proximité, ou sur le périmètre d'un polygone ou à proximité, transmettez le point, la polyligne/le polygone, et éventuellement une valeur de tolérance en degrés à google.maps.geometry.poly.isLocationOnEdge(). La fonction renvoie "true" si la distance entre le point et le point le plus proche sur la ligne ou le périmètre se trouve dans la tolérance spécifiée. La valeur de tolérance par défaut est de 10-9 degrés.

function initialize() {
  var myPosition = new google.maps.LatLng(46.0, -125.9);

  var mapOptions = {
    zoom: 5,
    center: myPosition,
    mapTypeId: 'terrain'
  };

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

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

  cascadiaFault.setMap(map);

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

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