Libreria di geometrie

  1. Panoramica
  2. Concetti di geometria sferica
    1. Funzioni di distanza e area
    2. Funzioni di navigazione
  3. Codifica della geometria
  4. Funzioni di poligono e polilinea
    1. containsLocation()
    2. isLocationOnEdge()

Panoramica

I concetti contenuti in questo documento si riferiscono alle funzionalità disponibili solo all'interno della libreria google.maps.geometry. Questa libreria non viene caricata per impostazione predefinita quando carichi l'API Maps JavaScript, ma deve essere specificata esplicitamente tramite l'uso di un parametro di bootstrap libraries. Per maggiori informazioni, consulta la panoramica sulle librerie.

La libreria geometrica dell'API Maps JavaScript fornisce funzioni di utilità per il calcolo dei dati geometrici sulla superficie della Terra. La libreria include tre spazi dei nomi:

  • spherical contiene utilità di geometria sferica che consentono di calcolare angoli, distanze e aree a partire da latitudini e longitudini.
  • encoding contiene utilità per la codifica e la decodifica dei percorsi delle polilinee in base all'algoritmo della polilinea codificata.
  • poly contiene funzioni di utilità per i calcoli relativi a poligoni e polilinee.

La libreria google.maps.geometry non contiene classi, ma contiene metodi statici negli spazi dei nomi precedenti.

Concetti della geometria sferica

Le immagini all'interno dell'API Maps JavaScript sono bidimensionali e "piatte". La Terra, tuttavia, è tridimensionale e spesso è approssimata a uno sferoide oblato o più a una sfera. Nell'API di Google Maps utilizziamo una sfera e per rappresentare la Terra su una superficie piana bidimensionale (ad esempio lo schermo del tuo computer), l'API di Google Maps utilizza una proiezione.

Nell'ambito delle proiezioni in 2D, a volte le apparenze possono ingannare. Poiché la proiezione della mappa richiede necessariamente una certa distorsione, la semplice geometria euclidiana spesso non è applicabile. Ad esempio, la distanza più breve tra due punti su una sfera non è una linea retta, ma un grande cerchio (un tipo di geodetica) e la somma degli angoli che compongono un triangolo sulla superficie di una sfera può superare i 180 gradi.

A causa di queste differenze, le funzioni geometriche su una sfera (o sulla sua proiezione) richiedono l'utilizzo della geometria sferica per calcolare questi costrutti come distanza, intestazione e area. Le utilità per calcolare questi costrutti geometrici sferici sono contenute nello spazio dei nomi google.maps.geometry.spherical dell'API di Google Maps. Questo spazio dei nomi fornisce metodi statici per calcolare valori scalari da coordinate sferiche (latitudine e longitudine).

Funzioni di distanza e area

La distanza tra due punti è la lunghezza del percorso più breve tra i due punti. Questo percorso più breve è chiamato geodetica. Su una sfera, tutte le geodetiche sono segmenti di un grande cerchio. Per calcolare questa distanza, chiama computeDistanceBetween(), passandogli due oggetti LatLng.

In alternativa, puoi utilizzare computeLength() per calcolare la lunghezza di un determinato percorso se disponi di più località.

I risultati relativi alla distanza sono espressi in metri.

Per calcolare l'area (in metri quadrati) di un'area poligonale, chiama computeArea(), passando l'array di LatLng oggetti che definiscono un ciclo chiuso.

Quando navighi su una sfera, un'intestazione è l'angolo di una direzione a partire da un punto di riferimento fisso, di solito verso nord. Nell'API di Google Maps, un'intestazione viene definita in gradi dal nord vero, dove le intestazioni vengono misurate in senso orario dal nord vero (0 gradi). Puoi calcolare questa intestazione tra due località con il metodo computeHeading(), passando due oggetti from e to LatLng.

Data un'intestazione specifica, una località di partenza e la distanza da percorrere (in metri), puoi calcolare le coordinate della destinazione utilizzando computeOffset().

Dati due oggetti LatLng e un valore compreso tra 0 e 1, puoi anche calcolare una destinazione tra di loro utilizzando il metodo interpolate(), che esegue l'interpolazione lineare sferica tra le due località, dove il valore indica la distanza frazionata da percorrere lungo il percorso dall'origine alla destinazione.

L'esempio seguente crea due polilinee quando fai clic su due punti sulla mappa (una geodetica e una "retta" che collega le due località) e calcola l'intestazione per spostarsi tra i due punti:

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;
Visualizza esempio

Prova Samples

Metodi di codifica

I percorsi all'interno dell'API Maps JavaScript sono spesso specificati come Array di oggetti LatLng. Tuttavia, il passaggio di un array di questo tipo è spesso ingombrante. Puoi utilizzare invece l'algoritmo di codifica delle poliline di Google per comprimere un determinato percorso, che potrai poi decomprimere in un secondo momento tramite la decodifica.

La libreria geometry contiene uno spazio dei nomi encoding per le utilità, che consente di codificare e decodificare le polilinee.

Il metodo statico encodePath() codifica il percorso specificato. Puoi passare un array di LatLng o un MVCArray (restituito da Polyline.getPath()).

Per decodificare un percorso codificato, chiama decodePath() per passare la stringa codificata al metodo.

L'esempio seguente mostra una mappa di Oxford, Mississippi. Se fai clic sulla mappa, viene aggiunto un punto a una polilinea. Una volta creata la polilinea, la codifica viene visualizzata al di sotto.

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;
Visualizza esempio

Prova Samples

Funzioni di poligono e polilinea

Lo spazio dei nomi poly della libreria di geometria contiene funzioni di utilità che determinano se un determinato punto si trova all'interno o vicino a un poligono o a una polilinea.

containsLocation()

containsLocation(point:LatLng, polygon:Polygon)

Per scoprire se un determinato punto rientra in un poligono, passa il punto e il poligono a google.maps.geometry.poly.containsLocation(). La funzione restituisce true se il punto si trova all'interno del poligono o sul bordo.

Il seguente codice scrive "true" nella console del browser se il clic dell'utente rientra nel triangolo definito, altrimenti scrive "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);

Un'altra versione di questo codice disegna un triangolo blu sulla mappa se il clic rientra all'interno del triangolo delle Bermuda, mentre un cerchio rosso negli altri casi:

Visualizza esempio

isLocationOnEdge()

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

Per determinare se un punto cade sopra o vicino a una polilinea oppure sul bordo o vicino al bordo di un poligono, passa il punto, la polilinea/il poligono e, facoltativamente, un valore di tolleranza in gradi a google.maps.geometry.poly.isLocationOnEdge(). La funzione restituisce true se la distanza tra il punto e il punto più vicino sulla linea o sul bordo rientra nella tolleranza specificata. Il valore predefinito della tolleranza è di 10-9 gradi.

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);