Thư viện hình học

  1. Tổng quan
  2. Khái niệm về hình học hình cầu
    1. Hàm khoảng cách và diện tích
    2. Hàm điều hướng
  3. Mã hoá hình học
  4. Hàm đa giác và đa tuyến
    1. containsLocation()
    2. isLocationOnEdge()

Tổng quan

Các khái niệm trong tài liệu này đề cập đến các tính năng chỉ có trong thư viện google.maps.geometry. Thư viện này không được tải theo mặc định khi bạn tải API JavaScript của Maps, nhưng phải được chỉ định rõ ràng thông qua việc sử dụng tham số khởi động libraries. Để biết thêm thông tin, hãy xem bài viết Tổng quan về thư viện.

Thư viện hình học API Maps JavaScript cung cấp các hàm tiện ích để tính toán dữ liệu hình học trên bề mặt Trái đất. Thư viện này bao gồm 3 không gian tên:

  • spherical chứa các tiện ích hình học hình cầu cho phép bạn tính toán các góc, khoảng cách và diện tích từ vĩ độ và kinh độ.
  • encoding chứa các tiện ích để mã hoá và giải mã đường dẫn đa tuyến theo Thuật toán đa tuyến được mã hoá.
  • poly chứa các hàm tiện ích cho các phép tính liên quan đến đa giác và nhiều đường.

Thư viện google.maps.geometry không chứa bất kỳ lớp nào; thay vào đó, thư viện chứa các phương thức tĩnh trên các không gian tên ở trên.

Khái niệm về hình học hình cầu

Hình ảnh trong API JavaScript của Maps là hai chiều và "phẳng". Tuy nhiên, Trái Đất có ba chiều và thường được coi là một hình elip xoay dẹt hoặc gần giống như một hình cầu. Trong API Maps, chúng ta sử dụng một hình cầu và để biểu thị Trái đất trên một bề mặt phẳng hai chiều (chẳng hạn như màn hình máy tính), API Maps sử dụng một thực chiếu.

Trong các phép chiếu 2D, hình thức đôi khi có thể đánh lừa. Vì phép chiếu bản đồ cần phải có một số độ méo, nên hình học Euclid đơn giản thường không áp dụng được. Ví dụ: khoảng cách ngắn nhất giữa hai điểm trên một hình cầu không phải là một đường thẳng, mà là một vòng tròn lớn (một loại đường trắc địa) và các góc tạo nên một tam giác trên bề mặt của hình cầu cộng lại hơn 180 độ.

Do những khác biệt này, các hàm hình học trên một hình cầu (hoặc trên hình chiếu của hình cầu đó) cần phải sử dụng Hình học hình cầu để tính toán các cấu trúc như khoảng cách, hướng và diện tích. Các tiện ích để tính toán các cấu trúc hình học hình cầu này nằm trong không gian tên google.maps.geometry.spherical của API Maps. Không gian tên này cung cấp các phương thức tĩnh để tính toán các giá trị vô hướng từ toạ độ hình cầu (vĩ độ và kinh độ).

Hàm khoảng cách và diện tích

Khoảng cách giữa hai điểm là chiều dài của đường đi ngắn nhất giữa hai điểm đó. Đường ngắn nhất này được gọi là đường trắc địa. Trên một hình cầu, tất cả các đường trắc địa đều là các đoạn của một vòng tròn lớn. Để tính khoảng cách này, hãy gọi computeDistanceBetween(), truyền vào đó hai đối tượng LatLng.

Thay vào đó, bạn có thể sử dụng computeLength() để tính toán chiều dài của một đường dẫn nhất định nếu có nhiều vị trí.

Kết quả khoảng cách được thể hiện bằng mét.

Để tính diện tích (tính bằng mét vuông) của một khu vực đa giác, hãy gọi computeArea(), truyền mảng các đối tượng LatLng xác định một vòng lặp kín.

Khi di chuyển trên một hình cầu, hướng là góc của một hướng từ một điểm tham chiếu cố định, thường là hướng bắc thực. Trong API Google Maps, hướng được xác định theo độ từ hướng bắc thực, trong đó hướng được đo theo chiều kim đồng hồ từ hướng bắc thực (0 độ). Bạn có thể tính toán tiêu đề này giữa hai vị trí bằng phương thức computeHeading(), truyền vào đó hai đối tượng fromto LatLng.

Với một hướng cụ thể, vị trí xuất phát và quãng đường cần đi (tính bằng mét), bạn có thể tính toạ độ đích đến bằng cách sử dụng computeOffset().

Với hai đối tượng LatLng và giá trị từ 0 đến 1, bạn cũng có thể tính toán một đích đến giữa hai đối tượng đó bằng cách sử dụng phương thức interpolate(). Phương thức này thực hiện nội suy tuyến tính hình cầu giữa hai vị trí, trong đó giá trị cho biết khoảng cách phân đoạn cần di chuyển dọc theo đường dẫn từ điểm gốc đến đích đến.

Ví dụ sau đây tạo hai đa tuyến khi bạn nhấp vào hai điểm trên bản đồ — một đường trắc địa và một đường "thẳng" nối hai vị trí — và tính toán hướng di chuyển giữa hai điểm:

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;
Xem ví dụ

Thử mẫu

Phương thức mã hoá

Các đường dẫn trong API Maps JavaScript thường được chỉ định dưới dạng Array của các đối tượng LatLng. Tuy nhiên, việc truyền một mảng như vậy thường rất cồng kềnh. Thay vào đó, bạn có thể sử dụng thuật toán mã hoá đường đa tuyến của Google để nén một đường dẫn nhất định. Sau đó, bạn có thể giải nén đường dẫn đó thông qua quá trình giải mã.

Thư viện geometry chứa một không gian tên encoding cho các tiện ích để mã hoá và giải mã đa tuyến.

Phương thức tĩnh encodePath() mã hoá đường dẫn đã cho. Bạn có thể truyền một mảng LatLng hoặc một MVCArray (do Polyline.getPath() trả về).

Để giải mã một đường dẫn đã mã hoá, hãy gọi decodePath() truyền phương thức chuỗi đã mã hoá.

Ví dụ sau đây hiển thị bản đồ của Oxford, Mississippi. Thao tác nhấp vào bản đồ sẽ thêm một điểm vào đa tuyến. Khi đường đa tuyến được tạo, mã hoá của đường đa tuyến sẽ xuất hiện bên dưới.

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;
Xem ví dụ

Thử mẫu

Hàm đa giác và đa tuyến

Không gian tên poly của thư viện hình học chứa các hàm tiện ích xác định xem một điểm nhất định có nằm bên trong hay gần một đa giác hoặc đa tuyến hay không.

containsLocation()

containsLocation(point:LatLng, polygon:Polygon)

Để tìm xem một điểm nhất định có nằm trong đa giác hay không, hãy truyền điểm và đa giác đó đến google.maps.geometry.poly.containsLocation(). Hàm này trả về true nếu điểm nằm trong đa giác hoặc trên cạnh của đa giác.

Mã sau đây sẽ ghi "true" vào bảng điều khiển trình duyệt nếu lượt nhấp của người dùng nằm trong tam giác đã xác định; nếu không, mã sẽ ghi "false".

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

Một phiên bản khác của mã này vẽ một tam giác màu xanh dương trên bản đồ nếu lượt nhấp nằm trong Tam giác Bermuda và một vòng tròn màu đỏ nếu không:

Xem ví dụ

isLocationOnEdge()

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

Để xác định xem một điểm có nằm trên hoặc gần một đa tuyến hay không, hoặc nằm trên hoặc gần cạnh của một đa giác hay không, hãy truyền điểm, đa tuyến/đa giác và tuỳ ý truyền giá trị dung sai theo độ cho google.maps.geometry.poly.isLocationOnEdge(). Hàm này trả về true nếu khoảng cách giữa điểm và điểm gần nhất trên đường hoặc cạnh nằm trong dung sai đã chỉ định. Giá trị dung sai mặc định là 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);