ห้องสมุดเรขาคณิต

  1. ภาพรวม
  2. แนวคิดเรขาคณิตแบบทรงกลม
    1. ฟังก์ชันระยะทางและพื้นที่
    2. ฟังก์ชันการนำทาง
  3. การเข้ารหัสเรขาคณิต
  4. ฟังก์ชันรูปหลายเหลี่ยมและรูปหลายเหลี่ยม
    1. containsLocation()
    2. isLocationOnEdge()

ภาพรวม

แนวคิดในเอกสารนี้อ้างถึงฟีเจอร์ที่มีให้ใช้งานภายในไลบรารี 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);