Библиотека Geometry

  1. Обзор
  2. Концепции сферической геометрии
    1. Функции расстояния и площади
    2. Функции навигации
  3. Кодирование геометрии
  4. Функции многоугольника и ломаной линии
    1. содержитМестоположение()
    2. isLocationOnEdge()

Обзор

Понятия в этом документе относятся к функциям, доступным только в библиотеке google.maps.geometry . Эта библиотека не загружается по умолчанию при загрузке API Javascript Карт, но ее необходимо явно указать с помощью параметра начальной загрузки libraries . Для получения дополнительной информации см. Обзор библиотек .

Библиотека геометрии Maps JavaScript API предоставляет служебные функции для вычисления геометрических данных на поверхности Земли. Библиотека включает в себя три пространства имен:

  • spherical содержит утилиты сферической геометрии, позволяющие вычислять углы, расстояния и площади по широте и долготе.
  • encoding содержит утилиты для кодирования и декодирования путей ломаных линий согласно алгоритму Encoded Polyline Algorithm .
  • poly содержит служебные функции для вычислений с участием полигонов и полилиний.

Библиотека google.maps.geometry не содержит классов; вместо этого библиотека содержит статические методы в указанных выше пространствах имен.

Концепции сферической геометрии

Изображения в Maps JavaScript API являются двухмерными и «плоскими». Земля, однако, трехмерна и часто представляется либо сплюснутым сфероидом, либо скорее сферой. В API Карт мы используем сферу, а для представления Земли на плоской двумерной поверхности (например, на экране вашего компьютера) API Карт использует проекцию .

В 2D-проекциях внешний вид иногда может быть обманчивым. Поскольку картографическая проекция обязательно требует некоторого искажения, простая евклидова геометрия часто неприменима. Например, кратчайшее расстояние между двумя точками на сфере — это не прямая линия, а большой круг (разновидность геодезической), а сумма углов, составляющих треугольник на поверхности сферы, составляет более 180 градусов. .

Из-за этих различий геометрические функции на сфере (или ее проекции) требуют использования сферической геометрии для расчета таких конструкций, как расстояние, направление и площадь. Утилиты для расчета этих сферических геометрических конструкций содержатся в пространстве имен google.maps.geometry.spherical Maps API. Это пространство имен предоставляет статические методы для вычисления скалярных значений из сферических координат (широты и долготы).

Функции расстояния и площади

Расстояние между двумя точками — это длина кратчайшего пути между ними. Этот кратчайший путь называется геодезической. На сфере все геодезические являются отрезками большого круга. Чтобы вычислить это расстояние, вызовите computeDistanceBetween() , передав ему два объекта LatLng .

Вместо этого вы можете использовать computeLength() для расчета длины заданного пути, если у вас есть несколько местоположений.

Результаты расстояния выражаются в метрах.

Чтобы вычислить площадь (в квадратных метрах) многоугольной области, вызовите computeArea() , передав массив объектов LatLng , определяющих замкнутый цикл.

При навигации по сфере курс — это угол направления от фиксированной контрольной точки, обычно истинного севера. В API Карт Google курс определяется в градусах от истинного севера, при этом направления измеряются по часовой стрелке от истинного севера (0 градусов). Вы можете вычислить этот заголовок между двумя местоположениями с помощью computeHeading() , передав его два объекта LatLng to from

Учитывая конкретный курс, исходное местоположение и расстояние, которое необходимо преодолеть (в метрах), вы можете вычислить координаты пункта назначения с помощью computeOffset() .

Учитывая два объекта LatLng и значение от 0 до 1, вы также можете вычислить пункт назначения между ними, используя метод interpolate() , который выполняет сферическую линейную интерполяцию между двумя местоположениями, где значение указывает дробное расстояние, которое необходимо пройти по пути от объекта LatLng. происхождения до пункта назначения.

В следующем примере создаются две полилинии, когда вы щелкаете две точки на карте — одну геодезическую и одну «прямую» линию, соединяющую два местоположения, — и вычисляет направление для путешествия между двумя точками:

Машинопись

// 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;
Посмотреть пример

Попробуйте образец

Методы кодирования

Пути в Maps JavaScript API часто указываются как Array объектов LatLng . Однако передача такого массива часто оказывается громоздкой. Вместо этого вы можете использовать алгоритм кодирования полилиний Google для сжатия заданного пути, который позже можно распаковать посредством декодирования.

Библиотека geometry содержит пространство имен encoding для утилит кодирования и декодирования полилиний.

Статический метод encodePath() кодирует заданный путь. Вы можете передать либо массив LatLng , либо MVCArray (который возвращается Polyline.getPath() ).

Чтобы декодировать закодированный путь, вызовите decodePath() , передав методу закодированную строку.

В следующем примере показана карта Оксфорда, штат Миссисипи. Щелчок по карте добавляет точку к полилинии. По мере построения ломаной линии ее кодировка отображается под ней.

Машинопись

// 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;
Посмотреть пример

Попробуйте образец

Функции многоугольника и полилинии

Пространство имен библиотеки геометрии poly содержит служебные функции, которые определяют, находится ли данная точка внутри или рядом с многоугольником или полилинией.

содержитМестоположение()

containsLocation(point:LatLng, polygon:Polygon)

Чтобы узнать, попадает ли данная точка в многоугольник, передайте точку и многоугольник в google.maps.geometry.poly.containsLocation() . Функции возвращают true, если точка находится внутри многоугольника или на его краю.

Следующий код записывает в консоль браузера значение true, если щелчок пользователя попадает в пределы определенного треугольника; в противном случае он пишет «ложь».

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

Другая версия этого кода рисует на карте синий треугольник, если щелчок попадает в Бермудский треугольник, и красный кружок в противном случае:

Посмотреть пример

isLocationOnEdge()

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

Чтобы определить, попадает ли точка на полилинию или рядом с ней, или на край многоугольника или рядом с ним, передайте точку, ломаную линию или многоугольник и, при необходимости, значение допуска в градусах в google.maps.geometry.poly.isLocationOnEdge() . Функция возвращает значение true, если расстояние между точкой и ближайшей точкой на линии или ребре находится в пределах указанного допуска. Значение допуска по умолчанию составляет 10 -9 градусов.

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