總覽
本文件所述概念僅適用於 google.maps.geometry
程式庫所提供的功能。根據預設,當您載入 Maps JavaScript API 時,不會載入此程式庫。您必須使用 libraries
Bootstrap 參數明確指定此程式庫。詳情請參閱程式庫總覽。
Maps JavaScript API 幾何圖形程式庫所提供的公用函式,可用於計算地表的幾何圖形資料。此程式庫包含三個命名空間:
spherical
包含球面幾何圖形公用程式,以便您根據經緯度計算角度、距離及面積。encoding
包含一些公用程式,可用來根據編碼折線演算法對折線路徑進行編碼及解碼。poly
包含一些公用函式,可用來進行多邊形和折線相關計算。
google.maps.geometry
程式庫不含任何類別,只會提供上述命名空間的靜態方法。
球面幾何圖形概念
Maps JavaScript API 中的圖片都是 2D 平面圖片,而地球是 3D 結構,比較像扁球體或是球體。Maps API 使用投影法在 2D 平面 (例如您的電腦畫面) 上繪製球體代表地球。
在 2D 投影之下,顯示內容可能會出現一些假象,這是因為地圖投影難免會出現失真的情況,因此簡單的歐幾里得幾何圖形往往不適用。舉例來說,在球體上,兩點之間最短的距離不是直線,而是大圓線 (一種測地線),同時球體表面上的三角形角度總合也會大於 180 度。
這幾種差異造成球體上 (或球體投影上) 的幾何函式在計算距離、頂角和面積等建構項目時,必須使用球面幾何圖形。Maps API 的 google.maps.geometry.spherical
命名空間納入計算這些球面幾何建構項目的公用程式。此命名空間提供一些靜態方法,可用來計算球面座標 (經緯度) 純量值。
距離與面積函式
兩點間的距離是指兩點間最短的路徑長度,稱為測地線。在球體上,所有的測地線都是大圓線。如要計算這個距離,可以呼叫 computeDistanceBetween()
,並傳遞兩個 LatLng
物件給這個函式。
如果您有數個位置,也可改用 computeLength()
計算指定路徑的長度。
距離的計算結果會以公尺表示。
如要計算多邊形區域的面積 (以平方公尺為單位),可以呼叫 computeArea()
,並傳遞 LatLng
物件陣列定義封閉區域。
瀏覽函式
在球體上進行瀏覽時,頂角就是固定參照點 (通常是正北方) 的方向角。Google Maps API 會將頂角定義為相對於正北方的角度,也就是頂角與正北方 (0 度) 的順時針方向夾角角度。您可以使用 computeHeading()
方法,並傳遞兩個 from
和 to
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」傳回瀏覽器控制台,反之則傳回「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);