Biblioteka geometryczna

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

Opis

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

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

  • spherical zawiera narzędzia geometryczne, 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 łamanej zgodnie z zakodowanym algorytmem łamanym.
  • poly zawiera funkcje użytkowe do wykonywania obliczeń na wielokątach i liniach łamanych.

Biblioteka google.maps.geometry nie zawiera żadnych klas. Zamiast tego w powyższych przestrzeniach nazw zawiera metody statyczne.

Koncepcje geometrii sferycznej

Obrazy w interfejsie Maps JavaScript API są dwuwymiarowe i „płaskie”. Ziemia jest jednak trójwymiarowa i często przedstawia ją w postaci okrągłej sferydy lub bardziej sfery. W interfejsie API Map Google stosujemy sferę, a aby odwzorować Ziemię na dwuwymiarowej, płaskiej powierzchni – np. na ekranie komputera – korzystamy z odwzorowania.

W ramach projekcji 2D wygląd może być mylący. Odwzorowanie mapy z koniecznością wymaga pewnych zniekształceń, więc prosta geometria euklidesowa często nie ma zastosowania. Na przykład najmniejsza odległość między dwoma punktami na powierzchni kuli nie jest linią prostą, ale dużym kołem (rodzajem geodezji), a kąty tworzące trójkąt na powierzchni kuli dają sumy ponad 180 stopni.

Z powodu tych różnic funkcje geometryczne na sferze (lub przy jej odwzorowaniu) wymagają użycia geometrii sferycznej do obliczania takich konstrukcji, jak odległość, kierunek i powierzchnię. Narzędzia do obliczania tych sferycznych konstrukcji geometrycznych znajdują się w przestrzeni nazw google.maps.geometry.spherical interfejsu API Map Google. Ta przestrzeń nazw udostępnia statyczne metody obliczania wartości skalarnych na podstawie współrzędnych sferycznych (długości i szerokości geograficznej).

Funkcje odległości i powierzchni

Odległość między dwoma punktami to długość najkrótszej między nimi ścieżki. Ta najkrótsza trasa jest nazywana geodezycją. Wszystkie elementy kuli ziemskiej są częścią wielkiego okręgu. Aby obliczyć tę odległość, wywołaj computeDistanceBetween(), przekazując mu 2 obiekty LatLng.

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

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

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

Podczas nawigacji po kuli z kierunkiem kierunek to kąt kierunku od ustalonego punktu odniesienia, który zazwyczaj jest ustawiony na północ. W interfejsie API Map Google kierunek jest zdefiniowany w stopniach, czyli w stopniach, czyli w stopniach rzeczywistej (0 stopni). Nagłówek można obliczyć między 2 lokalizacjami przy użyciu metody computeHeading(), przekazując 2 obiekty from i to LatLng.

Biorąc pod uwagę konkretny kierunek, lokalizację początkową i odległość do podróży (w metrach), możesz obliczyć współrzędne miejsca docelowego za pomocą funkcji computeOffset().

Biorąc pod uwagę 2 obiekty LatLng oraz wartość z zakresu od 0 do 1, możesz też obliczyć miejsce docelowe między nimi, korzystając z metody interpolate(), która przeprowadza sferyczną interpolację liniową między tymi dwoma lokalizacjami, gdzie wartość wskazuje ułamkową odległość, jaką pokonasz na ścieżce od punktu początkowego do miejsca docelowego.

Ten przykład powoduje utworzenie 2 linii łamanych po kliknięciu dwóch punktów na mapie (jednej geodezyjnej i jednej „prostej” łączącej te lokalizacje) i obliczenia kierunku ich podróży:

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 fragment

Metody kodowania

Ścieżki w interfejsie Maps JavaScript API są często określane jako Array z LatLng obiektów. Jednak przenoszenie takiej tablicy często jest utrudnione. Możesz zamiast tego skompresować daną ścieżkę, korzystając z opracowanego przez Google algorytmu kodowania polilinii, który potem możesz zdekompresować w trakcie dekodowania.

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

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

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

Poniższy przykład przedstawia mapę Oksfordu w stanie Missisipi. Kliknięcie mapy powoduje dodanie punktu do linii łamanej. Po utworzeniu linii łamanej 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 fragment

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 jego pobliżu.

containsLocation()

containsLocation(point:LatLng, polygon:Polygon)

Aby sprawdzić, czy dany punkt leży w obrębie wielokąta, przekaż go i wielokąt do funkcji google.maps.geometry.poly.containsLocation(). Jeśli punkt znajduje się w obrębie wielokąta lub na jego krawędzi, zwraca wartość „true” (prawda).

Ten kod zapisuje w konsoli przeglądarki wartość „true” (prawda), jeśli kliknięcie użytkownika mieści się w zdefiniowanym 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 przypada w Trójkącie Bermudzkim, a czerwone kółko w innym przypadku:

Zobacz przykład

isLocationOnEdge()

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

Aby określić, czy punkt leży na linii łamanej, w jej pobliżu bądź na krawędzi wielokąta lub w pobliżu, przekaż go, linię łamaną/wielokąt oraz opcjonalnie wartość tolerancji w stopniach do 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 określonej 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);