Biblioteka geometrii

  1. Omówienie
  2. Pojęcia związane z geometrią sferyczną
    1. Funkcje odległości i powierzchni
    2. Funkcje nawigacyjne
  3. Kodowanie geometrii
  4. Funkcje wielokątów i linii łamanych
    1. containsLocation()
    2. isLocationOnEdge()
    3. Sprawdzanie geofence i promienia bezpiecznej strefy

Przegląd

Pojęcia opisane 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ć wyraźnie określona za pomocą parametru bootstrap libraries. Więcej informacji znajdziesz w omówieniu bibliotek.

Biblioteka geometrii interfejsu Maps JavaScript API udostępnia funkcje użytkowe 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 obszarów na podstawie szerokości i długości geograficznej.
  • encoding zawiera narzędzia do kodowania i dekodowania ścieżek linii łamanych zgodnie z algorytmem zakodowanej linii łamanej.
  • poly zawiera funkcje użytkowe do obliczeń obejmujących wielokąty i linie łamane.

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

Pojęcia dotyczące geometrii sferycznej

Obrazy w interfejsie Maps JavaScript API są dwuwymiarowe i „płaskie”. Ziemia jest jednak trójwymiarowa i często jest przybliżana jako elipsoida obrotowa lub kula. W interfejsie API Map Google używamy kuli, a do przedstawienia Ziemi na dwuwymiarowej płaskiej powierzchni, takiej jak ekran komputera, interfejs API Map Google używa rzutu.

W przypadku projekcji 2D pozory mogą mylić. Ponieważ rzutowanie mapy wymaga pewnych zniekształceń, prosta geometria euklidesowa często nie ma zastosowania. Na przykład najkrótsza odległość między 2 punktami na kuli nie jest linią prostą, ale kołem wielkim (rodzajem linii geodezyjnej), a kąty tworzące trójkąt na powierzchni kuli dają w sumie więcej niż 180 stopni.

Z powodu tych różnic funkcje geometryczne na kuli (lub jej rzucie) wymagają użycia geometrii sferycznej do obliczania takich wartoś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 API Map Google. Ta przestrzeń nazw udostępnia metody statyczne do obliczania wartości skalarnych na podstawie współrzędnych sferycznych (szerokości i długości geograficznej).

Funkcje pomiaru 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ę geodezyjną. Na sferze wszystkie geodezyjne są segmentami 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 użyć computeLength(), aby obliczyć długość danej ścieżki.

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

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

Podczas nawigacji po kuli kierunek to kąt kierunku od stałego punktu odniesienia, zwykle północy geograficznej. W interfejsie API Map Google kierunek jest określany w stopniach od północy geograficznej, gdzie kierunki są mierzone zgodnie z ruchem wskazówek zegara od północy geograficznej (0 stopni). Możesz obliczyć ten kierunek między 2 lokalizacjami za pomocą metody computeHeading(), przekazując jej 2 obiekty from i to LatLng.

Jeśli masz określony kierunek, lokalizację początkową i odległość do przebycia (w metrach), możesz obliczyć współrzędne miejsca docelowego za pomocą metody 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 lokalizacjami, gdzie wartość wskazuje ułamkową odległość do przebycia wzdłuż ścieżki od punktu początkowego do miejsca docelowego.

W poniższym przykładzie po kliknięciu 2 punktów na mapie tworzone są 2 krzywe łamane – jedna geodezyjna i jedna „prosta” łącząca te 2 lokalizacje – oraz obliczany jest kierunek podróży między tymi 2 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

Metody kodowania

Ścieżki w Maps JavaScript API są często określane jako Array obiektów LatLng. Jednak przekazywanie takiej tablicy jest często uciążliwe. Zamiast tego możesz użyć algorytmu kodowania linii łamanych Google, aby skompresować daną ścieżkę, którą możesz później 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żesz przekazać tablicę LatLng lub MVCArray (zwracaną przez Polyline.getPath()).

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

Poniższy przykład pokazuje mapę Oxfordu w Mississippi. Kliknięcie na mapie dodaje punkt do linii łamanej. Podczas tworzenia linii łamanej pod spodem pojawia się jej kodowanie.

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

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 okręgu albo w pobliżu wielokąta lub linii łamanej.

containsLocation()

containsLocation(point:LatLng|LatLngLiteral, polygon:Polygon|Circle|CircleLiteral)

Aby sprawdzić, czy dany punkt znajduje się wewnątrz wielokąta lub okręgu, przekaż punkt i google.maps.Polygon, google.maps.Circle lub google.maps.CircleLiteral do google.maps.geometry.poly.containsLocation(). Funkcja zwraca wartość true, jeśli punkt znajduje się wewnątrz kształtu lub na jego krawędzi.

Poniższy kod zapisuje w konsoli przeglądarki wartość „true”, jeśli kliknięcie użytkownika mieści się w zdefiniowanym trójkącie, lub „false”, jeśli tak nie jest.

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 – czerwone koło:

Zobacz przykład

isLocationOnEdge()

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

Aby określić, czy punkt znajduje się na linii łamanej lub w jej pobliżu albo na krawędzi wielokąta lub w jej pobliżu, przekaż punkt, linię łamaną lub wielokąt i opcjonalnie wartość tolerancji w stopniach do 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ślonej tolerancji. Domyślna wartość tolerancji to 10-9 stopnia.

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

Sprawdzanie promienia geofence i bezpiecznej strefy

Aby sprawdzić, czy współrzędne na żywo (np. pojazdu, zasobu lub lokalizacji użytkownika) znajdują się w obrębie geofence lub bezpiecznej strefy na mapie, połącz kształty na mapie z biblioteką geometry: