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

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

ภาพรวม

แนวคิดภายในเอกสารฉบับนี้อ้างอิงถึงฟีเจอร์ที่มีอยู่ในไลบรารี google.maps.geometry เท่านั้น เมื่อคุณโหลด Maps JavaScript API ค่าเริ่มต้นจะไม่โหลดไลบรารีนี้ แต่ต้องระบุอย่างชัดแจ้งโดยใช้พารามิเตอร์ Bootstrap libraries ดูข้อมูลเพิ่มเติมได้ที่ภาพรวมของคลังภาพ

ไลบรารีเรขาคณิตของ Maps JavaScript API มีฟังก์ชันยูทิลิตีสำหรับการคำนวณข้อมูลเรขาคณิตบนพื้นผิวโลก ไลบรารีมีเนมสเปซ 3 รายการ ได้แก่

  • spherical มียูทิลิตีเรขาคณิตทรงกลมที่ช่วยให้คุณคำนวณมุม ระยะทาง และพื้นที่จากละติจูดและลองจิจูดได้
  • encoding มียูทิลิตีสำหรับการเข้ารหัสและถอดรหัสเส้นทางโพลีไลน์ตามอัลกอริทึมโพลีไลน์ที่เข้ารหัส
  • poly มีฟังก์ชันยูทิลิตีสําหรับการคํานวณที่เกี่ยวข้องกับรูปหลายเหลี่ยมและโพลีไลน์

ไลบรารี google.maps.geometry ไม่มีคลาสใดๆ แต่ไลบรารีดังกล่าวมีเมธอดแบบคงที่ในเนมสเปซข้างต้น

แนวคิดของเรขาคณิตทรงกลม

รูปภาพภายใน Maps JavaScript API เป็นแบบ 2 มิติและ "แบน" อย่างไรก็ตาม โลกของเรามี 3 มิติ และมักมีการประมาณว่า เป็นแบบสเฟียรอยด์ทรงกลม หรือมากกว่านั้นเป็นทรงกลม ภายใน Maps API เราใช้ทรงกลมและเป็นตัวแทนของโลกบนพื้นผิวราบเรียบ 2 มิติ เช่น หน้าจอคอมพิวเตอร์ของคุณ Maps API ใช้ การฉายภาพ

ในบางครั้งการฉายภาพ 2 มิติอาจหลอกลวงได้ เนื่องจากเส้นโครงแผนที่จำเป็นต้องมีการบิดเบี้ยวในระดับหนึ่ง รูปเรขาคณิตแบบยูคลิเดียนอย่างง่ายจึงมักไม่สามารถใช้งานได้ เช่น ระยะทางที่สั้นที่สุดระหว่าง 2 จุดบนทรงกลมไม่ใช่เส้นตรง แต่เป็นวงกลมขนาดใหญ่ (ทรงกลม) และมุมต่างๆ ที่เป็นรูปสามเหลี่ยมบนพื้นผิวของทรงกลมรวมกันแล้วเกิน 180 องศา

เนื่องจากความแตกต่างเหล่านี้ ฟังก์ชันทางเรขาคณิตในทรงกลม (หรือบนการฉายภาพ) จึงจำเป็นต้องใช้เรขาคณิตทรงกลมเพื่อคำนวณโครงสร้างดังกล่าวว่าเป็นระยะทาง ส่วนหัว และพื้นที่ ยูทิลิตีในการคำนวณโครงสร้างเรขาคณิตทรงกลมเหล่านี้จะอยู่ในเนมสเปซ google.maps.geometry.spherical ของ Maps API เนมสเปซนี้ให้วิธีการคงที่สำหรับการคำนวณค่าสเกลาร์จากพิกัดทรงกลม (ละติจูดและลองจิจูด)

ฟังก์ชันระยะทางและพื้นที่

ระยะทางระหว่าง 2 จุดคือความยาวของเส้นทางที่สั้นที่สุดระหว่างจุดทั้งสอง เส้นทางที่สั้นที่สุดนี้เรียกว่าพื้นที่ทางภูมิศาสตร์ บนทรงกลม ภูมิศาสตร์ทั้งหมดคือ ส่วนของวงกลมใหญ่ หากต้องการคำนวณระยะทางนี้ ให้เรียก computeDistanceBetween() โดยส่งผ่านออบเจ็กต์ LatLng 2 รายการ

คุณอาจใช้ computeLength() เพื่อคำนวณความยาวของเส้นทางที่กำหนดแทนหากมีสถานที่หลายแห่ง

ผลการวัดระยะทางจะแสดงเป็นเมตร

หากต้องการคำนวณพื้นที่ (เป็นตารางเมตร) ของพื้นที่รูปหลายเหลี่ยม ให้เรียกใช้ computeArea() โดยใช้อาร์เรย์ของออบเจ็กต์ LatLng รายการที่กำหนดลูปปิด

เมื่อนำทางในทรงกลม ส่วนหัวจะเป็นมุมของทิศทางจากจุดอ้างอิงแบบคงที่ ซึ่งมักจะเป็นทางเหนือจริงๆ ภายใน Google แผนที่ API ส่วนหัวจะกำหนดเป็นองศาจากทิศเหนือจริง โดยหัววัดตามเข็มนาฬิกาจากทิศเหนือจริง (0 องศา) คุณอาจคำนวณส่วนหัวนี้ระหว่าง 2 ตำแหน่งด้วยเมธอด computeHeading() โดยส่งผ่านออบเจ็กต์ from 2 รายการและ to LatLng รายการ

คุณคำนวณพิกัดปลายทางได้โดยใช้ computeOffset() โดยพิจารณาจากส่วนหัวที่เฉพาะเจาะจง ตำแหน่งต้นทาง และระยะทางในการเดินทาง (หน่วยเป็นเมตร)

หากมีออบเจ็กต์ LatLng 2 รายการและค่าระหว่าง 0 ถึง 1 คุณอาจคำนวณปลายทางระหว่างวัตถุเหล่านั้นได้โดยใช้เมธอด interpolate() ซึ่งทำการประมาณค่าเชิงเส้นแบบทรงกลมระหว่าง 2 ตำแหน่ง โดยค่าจะระบุระยะทางเป็นเศษส่วนในการเดินทางไปตามเส้นทางจากต้นทางไปยังปลายทาง

ตัวอย่างต่อไปนี้สร้างเส้นประกอบ 2 เส้นเมื่อคุณคลิก 2 จุดบนแผนที่ โดยหนึ่งเส้นภูมิศาสตร์และเส้น "ตรง" 1 เส้นเชื่อมทั้ง 2 ตำแหน่งเข้าด้วยกัน แล้วคำนวณส่วนหัวสำหรับการเดินทางระหว่าง 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);