幾何圖形程式庫

  1. 簡介
  2. 球面幾何圖形概念
    1. 距離和面積函式
    2. 導覽函式
  3. 幾何圖形編碼
  4. 多邊形和折線函式
    1. containsLocation()
    2. isLocationOnEdge()

總覽

本文件中的概念是指 google.maps.geometry 程式庫所提供的功能。根據預設,您載入 Maps JavaScript API 時,不會載入此程式庫,但您必須使用 libraries 啟動參數明確指定。詳情請參閱程式庫總覽

Maps JavaScript API 幾何圖形程式庫提供公用函式,可用於計算地球表面上的幾何圖形資料。此程式庫包含三個命名空間:

  • spherical 包含球面幾何圖形公用程式,可讓您從緯度和經度來計算角度、距離和面積。
  • encoding 包含根據編碼折線演算法,為折線路徑進行編碼及解碼的公用程式。
  • poly 包含與多邊形和折線相關的運算函式。

google.maps.geometry 程式庫不含任何類別;相反地,程式庫包含上述命名空間的靜態方法。

球面幾何圖形概念

Maps JavaScript API 中的圖片是 2D 和 Futtt 圖片。但是,地球是 3D 特徵,且大致會顯示為覆蓋球形或球體。在 Maps API 中,我們使用一個球體,並在二維平面 (例如電腦螢幕) 上代表地球,並使用投影

在 2D 投影中,外觀有時可能會欺騙。 由於地圖投影需要需要扭曲變形,因此簡易的 Elilidian 幾何圖形通常不適用。舉例來說,在球體上兩點之間的最短距離不是直線,而是大圓圓形 (測地線的一種),以及構成球面三角形上的角度加起來超過 180 度。

因為這些差異,球體 (或其投影) 中的幾何圖形函式必須使用球面幾何圖形,才能計算距離、方向和面積等這類結構。Maps API 的 google.maps.geometry.spherical 命名空間包含用於計算這些球面幾何圖形結構的公用程式。此命名空間提供從球面座標 (緯度和經度) 計算純量值的靜態方法。

距離與區域函式

兩點之間的距離是指兩點之間的最短路徑長度。稱為測地線。在球子上,所有測地線段都是大圓形的區隔。如要計算這個距離,請呼叫 computeDistanceBetween(),並向其傳遞兩個 LatLng 物件。

如果您有多個地點,可以改用 computeLength() 計算特定路徑的長度。

距離的計算結果會以公尺表示。

如要計算多邊形區域的面積 (以平方公尺為單位),請呼叫 computeArea(),並傳遞定義封閉迴圈的 LatLng 物件陣列。

在球面上瀏覽時,標題是來自固定參照點的方向角度 (通常為北方)。在 Google Maps API 中,標題是以正北方為基準的度數,以正北方 (0 度) 為順時針方向測量。你可以使用 computeHeading() 方法計算兩個位置之間的這個標題,然後傳送兩個 fromto LatLng 物件。

指定特定標題、起點位置和移動距離 (單位為公尺) 即可利用 computeOffset() 計算目的地座標。

若有兩個 LatLng 物件,以及 0 到 1 之間的值,您也可以使用 interpolate() 方法計算這些物件之間的目的地,以便執行兩個位置之間的球型線性內插。這個值會表示從起點到目的地之間的行駛距離。

下列範例在您按一下地圖上的兩個點 (一個測地線,以及連接兩個位置的「直線」) 時,建立兩個折線,並計算在兩個點之間移動的方向:

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;
查看範例

查看範例

編碼方法

Maps JavaScript API 中的路徑通常會指定為 LatLng 物件的 Array。但是,傳遞這類陣列通常十分龐大。建議您改用 Google 的折線編碼演算法壓縮特定路徑,以便稍後透過解碼進行解壓縮。

geometry 程式庫包含 encoding 命名空間,可供公用程式對折線進行編碼及解碼。

靜態方法 encodePath() 會對指定路徑進行編碼。 您可以傳遞 LatLng 的陣列或 MVCArray (由 Polyline.getPath() 傳回)。

如要解碼編碼路徑,請呼叫 decodePath() 以傳遞編碼字串的方法。

以下範例顯示密西西比州牛津大學的地圖。您可以按一下地圖,在折線中加入點。折線進行建構後,編碼就會顯示在下方。

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;
查看範例

查看範例

多邊形與折線函式

幾何圖形程式庫的 poly 命名空間包含公用程式函式,可判斷特定點是否位於多邊形或折線內部或附近。

containsLocation()

containsLocation(point:LatLng, polygon:Polygon)

如要確認特定點是否落在多邊形內,請將該點和多邊形傳送至 google.maps.geometry.poly.containsLocation()。如果點位於多邊形或邊緣,函式會傳回 true。

如果使用者的程式碼點擊在定義的三角形中,程式碼就會寫入 'true';否則則會寫入 ##9;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);

如果點擊落在百慕達三角範圍內,此程式碼的另一個版本會在地圖上繪製一個藍色三角形,反之則另外顯示一個紅色圓圈:

查看範例

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