ภาพรวม
แนวคิดในเอกสารนี้อ้างถึงฟีเจอร์ที่มีให้ใช้งานภายในไลบรารี google.maps.geometry
เท่านั้น ระบบจะไม่โหลดไลบรารีนี้โดยค่าเริ่มต้นเมื่อโหลด JavaScript API ของ Maps แต่ต้องระบุอย่างชัดแจ้งผ่านการใช้พารามิเตอร์ Bootstrap ของ libraries
ดูข้อมูลเพิ่มเติมได้ที่ภาพรวมของห้องสมุด
ไลบรารีเรขาคณิตของ Maps JavaScript API มีฟังก์ชันที่เ��็นประโยชน์สำหรับการคำนวณข้อมูลเรขาคณิตบนพื้นผิวโลก ไลบรารีดังกล่าวมีเนมสเปซ 3 รายการ ได้แก่
spherical
มียูทิลิตีเรขาคณิตทรงกลมที่ช่วยคุณคำนวณมุม ระยะทาง และพื้นที่จากละติจูดและลองจิจูดได้encoding
มียูทิลิตีสำหรับการเข้ารหัสและถอดรหัสเส้นทางโพลีไลน์ตามอัลกอริทึม Polyline ที่เข้ารหัสpoly
มีฟังก์ชันยูทิลิตีสำหรับการคำนวณที่เกี่ยวข้องกับรูปหลายเหลี่ยมและโพลีไลน์
ไลบรารี google.maps.geometry
ไม่มีคลาสใดๆ แต่ไลบรารีมีเมธอดแบบคงที่ในเนมสเปซด้านบน
แนวคิดเรขาคณิตแบบทรงกลม
ภาพใน Maps JavaScript API เป็นแบบ 2 มิติ และเป็นแบบ "แบน" อย่างไรก็ตาม โลกเป็น 3 มิติและมักมีค่าประมาณของ สเฟียร์ทรงกลม ขึ้นไปเป็นทรงกลม ภายในแผนที่ API เราใช้ทรงกลมและเพื่อแสดงแทนโลกบนพื้นผิวราบเรียบ 2 มิติ เช่น หน้าจอคอมพิวเตอร์ Maps API จะใช้ เส้นโครง
ในการคาดการณ์แบบ 2 มิติ บางครั้งการปรากฏตัวอาจหลอกลวงได้ เนื่องจากเส้นโครงแผนที่จำเป็นต้องมีการบิดเบี้ยวบางอย่าง เรขาคณิตแบบยุคลิเดียนที่เรียบง่ายมักจะไม่สามารถใช้ได้ ตัวอย่างเช่น ระยะทางที่สั้นที่สุดระหว่างจุด 2 จุดบนทรงกลมไม่ได้เป็นเส้นตรง แต่เป็นวงกลมที่ยิ่งใหญ่ (เรขาคณิตประเภทหนึ่ง) และมุมที่ประกอบกันเป็นรูปสามเหลี่ยมบนพื้นผิวของทรงกลมเมื่อรวมกันแล้วเกิน 180 องศา
เนื่องจากความแตกต่างเหล่านี้ ฟังก์ชันเรขาคณิตในทรงกลม (หรือในการฉายภาพ) จึงจำเป็นต้องใช้เรขาคณิตแบบทรงกลมเพื่อคำนวณสิ่งที่เป็นระยะทาง ส่วนหัว และพื้นที่ ยูทิลิตีในการคำนวณโครงสร้างเรขาคณิตแบบทรงกลมเหล่านี้อยู่ในเนมสเปซ google.maps.geometry.spherical
ของ Maps API เนมสเปซนี้ระบุวิธีการแบบคงที่ในการคำนวณค่าสเกลาร์จากพิกัดทรงกลม (ละติจูดและลองจิจูด)
ฟังก์ชันระยะทางและพื้นที่
ระยะทางระหว่าง 2 จุดคือความยาวของเส้นทางที่สั้นที่สุดระหว่างจุดเหล่านั้น เส้นทางที่สั้นที่สุดนี้เรียกว่าเส้นธรณี ในทรงกลม เรขาคณิตทั้งหมด
คือส่วนของวงกลมที่ยิ่งใหญ่ หากต้องการคำนวณระยะทางนี้ ให้เรียกใช้ computeDistanceBetween()
โดยส่งผ่านออบเจ็กต์ LatLng
2 รายการ
คุณอาจใช้
computeLength()
เพื่อคำนวณความยาวของเส้นทางแทนหากมีหลายตำแหน่ง
ผลการวัดระยะทางแสดงเป็นหน่วยเมตร
หากต้องการคำนวณพื้นที่ (เป็นตารางเมตร) ของพื้นที่รูปหลายเหลี่ยม ให้เรียกใช้ computeArea()
โดยส่งผ่านอาร์เรย์ของออบเจ็กต์ LatLng
รายการที่กำหนดลูปปิด
ฟังก์ชันการนำทาง
เมื่อนำทางไปตามทรงกลม ส่วนหัวคือมุมของทิศทาง
จากจุดอ้างอิงแบบคงที่ซึ่งมักจะเป็นทิศเหนือจริง ภายใน Google Maps API ส่วนหัวจะกำหนดเป็นองศาจากทิศเหนือจริง โดยวัดส่วนหัวตามเข็มนาฬิกาจากทิศเหนือจริง (0 องศา) คุณอาจคำนวณส่วนหัวนี้ระหว่างตำแหน่ง 2 แห่งด้วยเมธอด computeHeading()
โดยส่งผ่านออบเจ็กต์ from
2 รายการและ to
LatLng
ออบเจ็กต์
เมื่อมีส่วนหัวเฉพาะ ตำแหน่งต้นทาง และระยะทางในการเดินทาง (เป็นเมตร) คุณจะคำนวณพิกัดจุดหมายได้โดยใช้ computeOffset()
เมื่อ��ิ��า������จากออบเจ็กต์ LatLng
2 รายการและค่าระหว่าง 0 ถึง 1 คุณอาจคำนวณปลายทางระหว่างวัตถุเหล่านั้นโดยใช้เมธอด interpolate()
ซึ่งแสดงการประมาณค่าเชิงเส้นแบบทรงกลมระหว่างตำแหน่งทั้ง 2 แห่ง โดยค่าจะแสดงระยะทางเป็นเศษส่วนที่จะเดินทางตามเส้นทางจากต้นทางไปยังปลายทาง
ตัวอย่างต่อไปนี้จะสร้างเส้นประกอบ 2 เส้นเมื่อคุณคลิกจุด 2 จุดบนแผนที่ — เส้นเรขาคณิต 1 เส้นและเส้น "ตรง" 1 เส้นที่เชื่อมระหว่างตำแหน่งทั้งสอง และคำนวณหัวข้อสำหรับการเดินทางระหว่าง 2 จุดนี้
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 มักระบุเป็นออบเจ็กต์ Array
จาก LatLng
รายการ อย่างไรก็ตาม การส่งผ่านอาร์เรย์ดังกล่า��
มักมีขนาดใหญ่ คุณอาจใช้อัลกอริทึมการเข้ารหัสโพลีไลน์ของ 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" ไปยังคอนโซลของเบราว์เซอร์ หากการคลิกของผู้ใช้อยู่ในสามเหลี่ยมที่กำหนด มิเช่นนั้น จะเขียนว่า "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()
ฟังก์ชันนี้จะแสดงค่า "จริง" หากระยะห่างระหว่างจุดและจุดที่ใกล้ที่สุดในเส้นหรือขอบอยู่ภายใน���วามคลาดเคลื่อนที่ระบุ ค่าความคลาดเคลื่อนเริ่มต้นคือ 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);