Biblioteka geometryczna

  1. Overview
  2. Pojęcia związane z geometrią sferyczną
    1. Funkcje związane z odległością i powierzchnią
    2. Funkcje nawigacyjne
  3. Kodowanie geometryczne
  4. Funkcje wielokąta i linii łamanej
    1. containsLocation()
    2. isLocationOnEdge()

Przegląd

Pojęcia w tym dokumencie odnoszą się tylko do funkcji dostępnych w bibliotece google.maps.geometry. Ta biblioteka nie jest domyślnie ładowana podczas wczytywania interfejsu Maps JavaScript API, ale trzeba ją wyraźnie określić za pomocą parametru wczytywania libraries. Więcej informacji znajdziesz w artykule Omówienie bibliotek.

Biblioteka geometrii Maps JavaScript API udostępnia funkcje użytkowe do obliczania danych geometrycznych na powierzchni Ziemi. Biblioteka obejmuje 3 przestrzenie nazw:

  • spherical zawiera narzędzia do geometrii kulistej, 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 kodowanym algorytmem linii łamanej.
  • poly zawiera funkcje narzędziowe do obliczeń obejmujących wielokąty i linie łamane.

Biblioteka google.maps.geometry nie zawiera żadnych klas. Zamiast tego w wymienionych powyżej przestrzeniach nazw znajdują się metody statyczne.

Pojęcia geometrii sferycznej

Obrazy w Maps JavaScript API są dwuwymiarowe i „płaskie”. Ziemia jest jednak trójwymiarowa i często jest uznawana za obszerną sferoidę lub bardziej jako sferę. W interfejsie API Map Google wykorzystujemy kulę i do reprezentowania Ziemi na dwuwymiarowej płaskiej powierzchni, np. na ekranie komputera, wykorzystuje się odwzorowanie.

Podczas wyświetlania rzutów 2D pozory mogą być mylące. Odwzorowanie mapy zawsze wymaga pewnych zniekształceń, więc prosta geometria euklidyjska często nie ma zastosowania. Na przykład najkrótsza odległość między dwoma punktami na kuli nie jest linią prostą, a wielkim okręgiem (rodzajem geodezyjności), a kąty tworzące trójkąt na powierzchni kuli sumują się do ponad 180 stopni.

Z powodu tych różnic funkcje geometryczne kuli (lub jej rzutu) wymagają użycia geometrii sferycznej do obliczania takich konstrukcji, jak odległość, kierunek i powierzchnia. Narzędzia do obliczania tych kulistych konstrukcji geometrycznych znajdują się w przestrzeni nazw google.maps.geometry.spherical interfejsu API Map Google. Ta przestrzeń nazw zapewnia statyczne metody 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 dwoma punktami to długość najkrótszej między nimi. Ta najkrótsza ścieżka jest nazywana geodezyjną. Na kuli wszystkie obszary geodezyjne są odcinkami wielkiego okręgu. Aby obliczyć tę odległość, wywołaj computeDistanceBetween(), przesyłając 2 obiekty LatLng.

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

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

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

W przypadku nawigacji po kuli kierunek to kąt, który określa stały punkt odniesienia, zazwyczaj odnoszący się do północy. W interfejsie API Map Google kierunek jest określany w stopniach od rzeczywistej północy, gdzie kierunek jest mierzony w prawo od rzeczywistej północy (0 stopni). Nagłówek można obliczyć między 2 lokalizacjami za pomocą metody computeHeading(), przekazując 2 obiekty from i to LatLng.

Biorąc pod uwagę konkretny kierunek, lokalizację wylotu i odległość do przebycia (w metrach), możesz obliczyć współrzędne miejsca docelowego za pomocą narzędzia computeOffset().

Biorąc pod uwagę 2 obiekty LatLng o wartości z zakresu od 0 do 1, możesz też obliczyć miejsce docelowe między nimi za pomocą metody interpolate(), która wykonuje sferową interpolację liniową między tymi miejscami, gdzie wartość wskazuje odległość ułamkową, jaką musi przebyć ścieżka od punktu początkowego do miejsca docelowego.

W poniższym przykładzie po kliknięciu na mapie dwóch punktów – jednego geodezyjnego i jednej „prostej” linii łączącej te miejsca – powstaną dwie linie łamane, a następnie obliczamy kierunek podróży między tymi dwoma 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

Zobacz próbkę

Metody kodowania

Ścieżki w interfejsie Maps JavaScript API są często określane jako Array obiektów LatLng. Jednak przesyłanie wokół takiej tablicy jest często nieporęczne. Możesz zamiast tego użyć algorytmu kodowania łamanego Google do skompresowania danej ścieżki, którą następnie można zdekompresować przez dekodowanie.

Biblioteka geometry zawiera przestrzeń nazw encoding dla narzędzi do kodowania i dekodowania linii łamanych.

Metoda statyczna encodePath() koduje podaną ścieżkę. Można przekazać tablicę LatLng lub MVCArray (zwracaną przez Polyline.getPath()).

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

Poniższy przykład przedstawia mapę Oksfordu w stanie Missisipi. Kliknięcie na mapie powoduje dodanie punktu do linii łamanej. Gdy powstaje linia łamana, znajduje się ona pod spodem.

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

Zobacz próbkę

Funkcje wielokąta i linii łamanej

Przestrzeń nazw poly biblioteki geometrii zawiera funkcje użytkowe, które określają, czy dany punkt znajduje się wewnątrz wielokąta lub linii łamanej, czy w pobliżu.

containsLocation()

containsLocation(point:LatLng, polygon:Polygon)

Aby sprawdzić, czy dany punkt mieści się w wielokątie, przekaż go wraz z wielokątem na google.maps.geometry.poly.containsLocation(). Funkcje zwracają wartość „prawda”, jeśli punkt znajduje się w wielokątie lub na jego krawędzi.

Ten kod zapisuje „true” w konsoli przeglądarki, jeśli kliknięcie użytkownika mieści się w zdefiniowanym trójkącie. W przeciwnym razie zapisuje „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 znajduje się w Trójkącie Bermudzkim, a czerwone kółko:

Zobacz przykład

isLocationOnEdge()

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

Aby określić, czy punkt leży na linii łamanej lub w pobliżu jego krawędzi, bądź w pobliżu jego krawędzi, przekaż punkt, linię łamaną/wielokąt i opcjonalnie wartość tolerancji w stopniach na wartość google.maps.geometry.poly.isLocationOnEdge(). Funkcja zwraca wartość „prawda”, jeśli odległość między punktem a najbliższym punktem na linii lub krawędzi mieści się w podanej tolerancji. Domyślna wartość tolerancji wynosi 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);