Biblioteka geometrii

  1. Omówienie
  2. Pojęcia związane z geometrią sferyczną
    1. Funkcje odległości i powierzchni
    2. Funkcje nawigacji
  3. Kodowanie geometrii
  4. Funkcje dotyczące wielokątów i wielokątów otwartych
    1. containsLocation()
    2. isLocationOnEdge()

Omówienie

Pojęcia w tym dokumencie odnoszą się tylko do funkcji dostępnych w bibliotece google.maps.geometry. Ta biblioteka nie jest wczytywana domyślnie podczas wczytywania interfejsu Maps JavaScript API, ale musi być jawnie określona za pomocą parametru bootstrap libraries. Więcej informacji znajdziesz w artykule Omówienie bibliotek.

Biblioteka geometryczna Maps JavaScript API udostępnia funkcje pomocnicze do obliczania danych geometrycznych na powierzchni Ziemi. Biblioteka zawiera 3 przestrzenie nazw:

  • spherical zawiera narzędzia do geometrii sferycznej, które umożliwiają obliczanie kątów, odległości i powierzchni na podstawie szerokości i długości geograficznej.
  • encoding zawiera narzędzia do kodowania i dekodowania ścieżek linii łamanych zgodnie z algorytmem Encoded Polyline Algorithm.
  • poly zawiera funkcje pomocnicze do obliczeń dotyczących wielokątów i linii łamanych.

Biblioteka google.maps.geometry nie zawiera żadnych klas, ale zawiera metody statyczne w wymienionych powyżej przestrzeniach nazw.

Pojęcia związane z geometrią sferyczną

Obrazy w Maps JavaScript API są dwuwymiarowe i „płaskie”. Ziemia jest jednak trójwymiarowa i często przybliżana jako spłaszczony sferoid lub jako kula. W interfejsie Map API używamy kuli ziemskiej, a aby przedstawić Ziemię na płaskiej powierzchni, np. na ekranie komputera, interfejs Map API korzysta z  projekcji.

W projekcjach 2D wygląd może czasami wprowadzać w błąd. Projekcja mapy wymaga pewnego zniekształcenia, dlatego prosta geometria euklidesowa często nie jest odpowiednia. Na przykład najkrótsza odległość pomiędzy dwoma punktami na sferze nie jest linią prostą, ale wielkim kręgiem (rodzaj geodezyjnym), a kąty tworzące trójkąt na powierzchni sfery dają w sumie więcej niż 180°.

Z tego powodu funkcje geometryczne na sferze (lub na jej projekcji) wymagają stosowania geometrii sferycznej do obliczania takich wielkości jak odległość, kierunek i powierzchnia. Narzędzia do obliczania tych sferycznych konstrukcji geometrycznych znajdują się w przestrzeni nazw google.maps.geometry.spherical interfejsu Maps API. Ten obszar nazw udostępnia metody statyczne do obliczania wartości skalarnych na podstawie współrzędnych sferycznych (szerokości i długości geograficznej).

Funkcje odległości i powierzchni

Odległość między 2 punktami to długość najkrótszej ścieżki między nimi. Ta najkrótsza ścieżka nazywa się geodezyjna. Na sferze wszystkie geodezyjne linie są odcinkami wielkiego koła. Aby obliczyć tę odległość, wywołaj funkcję computeDistanceBetween(), przekazując jej 2 obiekty LatLng.

Jeśli masz kilka lokalizacji, możesz zamiast tego użyć funkcji computeLength() do obliczenia długości danej ścieżki.

Wyniki odległości są wyrażone w metrach.

Aby obliczyć pole (w metrach kwadratowych) obszaru wielokąta, wywołaj funkcję computeArea(), przekazując tablicę obiektów LatLng definiujących zamkniętą pętlę.

Podczas nawigacji na sferze kierunek to kąt kierunku od stałego punktu odniesienia, zwykle geograficznej północy. W interfejsie API Map Google kierunek jest definiowany w stopniach od prawdziwego północy, gdzie kierunki są mierzone zgodnie z kierunkiem wskazówek zegara od prawdziwego północy (0 stopni). Możesz obliczyć ten kierunek między dwoma lokalizacjami za pomocą metody computeHeading(), przekazując jej obiekty fromto LatLng.

Na podstawie określonego kierunku, miejsca pochodzenia i odległości do przebycia (w metrach) możesz obliczyć współrzędne miejsca docelowego za pomocą funkcji computeOffset().

Jeśli masz 2 obiekty LatLng i wartość z zakresu od 0 do 1, możesz też obliczyć miejsce docelowe między nimi za pomocą metody interpolate(), która wykonuje sferyczną interpolację liniową między tymi 2 miejscami, gdzie wartość wskazuje ułamkową odległość do przebycia na ścieżce od punktu początkowego do docelowego.

W tym przykładzie po kliknięciu 2 punktów na mapie tworzone są 2 wielolinie – jedna geodezyjna i jedna „prosta” łącząca 2 lokalizacje – oraz obliczany jest kierunek podróży między tymi punktami:

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;
Zobacz przykład

Wypróbuj próbkę

Metody kodowania

Ścieżki w Maps JavaScript API są często określane jako Array obiektów LatLng. Przekazywanie takiej tablicy jest jednak często kłopotliwe. Zamiast tego możesz użyć algorytmu kodowania polyline Google, aby skompresować daną ścieżkę. Następnie możesz ją odzyskać, dekodując ją.

Biblioteka geometry zawiera przestrzeń nazw encodingdla narzędzi do kodowania i dekodowania ścieżek wielokątów.

Metoda statyczna encodePath() koduje podany ścieżkę. Możesz przekazać tablicę elementów LatLng lub obiekt MVCArray (zwracany przez funkcję Polyline.getPath()).

Aby zdekodować zakodowaną ścieżkę, wywołaj metodę decodePath(), przekazując zakodowany ciąg znaków.

Ten przykład pokazuje mapę Oxford w Mississippi. Kliknięcie mapy powoduje dodanie punktu do linii złożonej. Gdy tworzysz ścieżkę wielopunktową, jej kodowanie pojawia się poniżej.

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;
Zobacz przykład

Wypróbuj próbkę

Funkcje wielokąta i linii złożonej

Przestrzeń nazw biblioteki geometrycznej poly zawiera funkcje pomocnicze, które określają, czy dany punkt znajduje się wewnątrz wielokąta lub polilinii albo w pobliżu tych obiektów.

containsLocation()

containsLocation(point:LatLng, polygon:Polygon)

Aby sprawdzić, czy dany punkt znajduje się w wielokącie, prześlij punkt i wielokąt do funkcji google.maps.geometry.poly.containsLocation(). Funkcja zwraca wartość true, jeśli punkt znajduje się w wieloboku lub na jego krawędzi.

Poniższy kod zapisuje w konsoli przeglądarki wartość „true” (prawda), jeśli kliknięcie użytkownika znajduje się w określonym trójkącie. W przeciwnym razie zapisuje wartość „false” (fałsz).

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

Inna wersja tego kodu rysuje na mapie niebieski trójkąt, jeśli kliknięcie nastąpi w Trójkącie Bermudzkim, a w przeciwnym razie – czerwony okrąg:

Zobacz przykład

isLocationOnEdge()

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

Aby określić, czy punkt znajduje się na wielokącie lub w pobliżu niego albo na krawędzi wielokąta lub w pobliżu niej, prześlij punkt, wielokąt lub wielokąt zamknięty oraz opcjonalnie wartość tolerancji w stopniach do funkcji google.maps.geometry.poly.isLocationOnEdge(). Funkcja zwraca wartość true, jeśli odległość między punktem a najbliższym punktem na linii lub krawędzi mieści się w określonym zakresie tolerancji. Wartość domyślna tolerancji to 10-9 stopni.

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