Thư viện hình học

  1. Tổng quan
  2. Khái niệm hình học hình cầu
    1. Hàm khoảng cách và hàm 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à hàm nhiều đường
    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. Theo mặc định, thư viện này sẽ không được tải khi bạn tải API JavaScript của Maps, nhưng bạn phải chỉ định rõ ràng thông qua tham số tự khởi động libraries. Để biết thêm thông tin, hãy xem phần Tổng quan về thư viện.

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

  • spherical chứa các tiện ích hình cầu cho phép bạn tính toán góc, khoảng cách và diện tích theo vĩ độ và kinh độ.
  • encoding chứa các tiện ích để mã hoá và giải mã đường dẫn nhiều đường theo Thuật toán Polyline được mã hoá.
  • poly chứa các hàm hiệu dụng để tính toán liên quan đến đa giác và hình 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 này chứa các phương thức tĩnh cho các không gian tên ở trên.

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

Các hình ảnh trong API JavaScript của Maps có dạng hai chiều và "bằng phẳng". Tuy nhiên, Trái Đất có tính ba chiều và thường gần đúng như một hình cầu phẳng hoặc hình cầu. Trong API Maps, chúng tôi sử dụng một hình cầu và để thể hiện 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 phép chiếu.

Trong các phép chiếu 2D, hình ảnh xuất hiện đôi khi có thể gây nhầm lẫn. Do phép chiếu bản đồ nhất thiết phải có một số hiệu ứng biến dạng, nên hình học Châu Âu đơ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 thành một tam giác trên bề mặt hình cầu cộng lại thành 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 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 có 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 giá trị vô hướng từ các 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à độ dài của đường đi ngắn nhất giữa hai điểm. Đường đi 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 phân đoạn của một đường tròn lớn. Để tính toán khoảng cách này, hãy gọi computeDistanceBetween(), truyền vào đó 2 đối tượng LatLng.

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

Kết quả về khoảng cách được biểu thị bằng mét.

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

Khi điều hướng trên một hình cầu, tiêu đề 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. Trong API Google Maps, tiêu đề được xác định theo độ so với hướng bắc thực sự, trong đó tiêu đề được đo theo chiều kim đồng hồ tính từ hướng bắc thực sự (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 tiêu đề cụ thể, vị trí điểm khởi hành và khoảng cách cần đi (tính bằng mét), bạn có thể tính toán toạ độ đích đến bằng cách sử dụng computeOffset().

Với hai đối tượng LatLng và giá trị nằm trong khoảng từ 0 đến 1, bạn cũng có thể tính toán một đích đến giữa chú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 số để đi dọc theo đường dẫn từ điểm gốc đến đích.

Ví dụ sau đây sẽ tạo ra hai hình nhiều đường 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" kết nối hai vị trí — và tính toán tiêu đề để 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ử dùng mẫu

Phương thức mã hoá

Đường dẫn trong API JavaScript của Maps thường được chỉ định là Array của đố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á nhiều đường của Google để nén một đường dẫn nhất định, sau đó bạn có thể giải nén bằng cách 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ã hình nhiều đường.

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 (được 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 được mã hoá.

Ví dụ sau thể hiện bản đồ Oxford, Mississippi. Nhấp vào bản đồ sẽ thêm một điểm vào một hình nhiều đường. Khi hình nhiều đường được xây dựng, phương thức mã hoá của hình nhiều đường đó 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ử dùng mẫu

Hàm đa giác và hàm nhiều đường

Không gian tên poly của thư viện hình học chứa các hàm hiệu dụng xác định xem một điểm nhất định nằm bên trong hay ở gần một đa giác hoặc hình nhiều đường.

containsLocation()

containsLocation(point:LatLng, polygon:Polygon)

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

Mã sau đây ghi "true" vào bảng điều khiển của trình duyệt nếu lượt nhấp của người dùng nằm trong hình tam giác đã xác định; nếu không, mã này 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 sẽ vẽ một hình 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 đỏ khác:

Xem ví dụ

isLocationOnEdge()

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

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