ספרייה גיאומטרית

  1. סקירה כללית
  2. מושגים גיאומטריים כדוריים
    1. פונקציות מרחק ואזור
    2. פונקציות ניווט
  3. קידוד גיאומטרי
  4. פונקציות פוליגון ופוליגונים
    1. מכיל מיקום()
    2. isLocationOnEdge()

סקירה כללית

המושגים במסמך זה מתייחסים לתכונות הזמינות רק בספרייה google.maps.geometry. הספרייה הזו לא נטענת כברירת מחדל כשטוענים את ה-API של מפות Google JavaScript, אבל צריך לציין אותה באופן מפורש באמצעות פרמטר libraries של תוכנת אתחול. מידע נוסף זמין בסקירה הכללית של הספריות.

הספרייה הגיאומטרית של JavaScript ב-Maps מספקת פונקציות של כלי עזר לחישוב נתונים גיאומטריים על פני השטח של כדור הארץ. הספרייה כוללת שלושה מרחבי שמות:

  • spherical מכיל כלים גיאומטריים כדוריים שמאפשרים לחשב זוויות, מרחקים ושטחים מקווי אורך ורוחב.
  • encoding מכיל כלים לקידוד ולפענוח של נתיבי פוליגונים לפי האלגוריתם של פוליגון מקודד.
  • poly מכיל פונקציות של שירות חישוב עבור פוליגונים ופוליגונים.

הספרייה google.maps.geometry לא מכילה כיתות. במקום זאת, הספרייה מכילה שיטות סטטיות במרחבי השמות שלמעלה.

מושגים גיאומטריים כדוריים

התמונות ב-Maps JavaScript API הן דו-ממדיות ושטוחות. יחד עם זאת, כדור הארץ הוא תלת-ממדי ולרוב משמש כספרה אובלית או יותר ככדור הארץ. בממשק ה-API של מפות Google אנחנו משתמשים ב-zone, וכדי לייצג את כדור הארץ על פני שטח דו-מימדי שטוח – כמו מסך המחשב שלכם – ה-API של מפות Google משתמש ב הקרנה.

בתחזיות דו-ממדיות, לפעמים המראה עשוי להיראות מטעה. תחזית המפה דורשת בדרך כלל עיוות, ולכן לעתים קרובות לא ניתן להשתמש בגיאומטריה אוקלידית פשוטה. לדוגמה, המרחק הקצר ביותר בין שתי נקודות בעיגול אינו קו ישר, אלא עיגול גדול (סוג גיאודזי), והזוויות שמורכבות מהמשולש על פני השטח של כדור משותף מסתכמות ביותר מ-180 מעלות.

בשל ההבדלים האלה, פונקציות גיאומטריות בכדור הארץ (או ב הקרנה שלו) מחייבות שימוש בגיאומטריה פוטוספרית כדי לחשב את המבנים האלו בתור מרחק, כותרת ושטח. כלי עזר לחישוב המבנים הגיאומטריים ההיקפיים האלה נמצאים במרחב השמות google.maps.geometry.spherical של ה-API של מפות Google. מרחב השמות הזה מספק שיטות סטטיות לחישוב ערכים סקלריים מקואורדינטות היקפיות (קווי רוחב ואורך).

פונקציות מרחק ושטח

המרחק בין שתי הנקודות הוא האורך של המסלול הקצר ביותר ביניהן. הנתיב הקצר הזה נקרא גיאודזית. בכדור הארץ, כל הגיאוספירה היא פלחים של מעגל נהדר. כדי לחשב את המרחק הזה, צריך להפעיל את computeDistanceBetween() על סמך שני האובייקטים LatLng.

אם יש לכם כמה מיקומים, תוכלו להשתמש ב- computeLength() כדי לחשב את אורך הנתיב הנתון.

תוצאות המרחק מוצגות במטרים.

כדי לחשב את האזור (במטרים רבועים) של אזור פוליגונים, צריך להתקשר אל computeArea() ולהעביר את המערך של LatLng אובייקטים כדי להגדיר לולאה סגורה.

במהלך הניווט בכדור הארץ, הכותרת היא הזווית של הכיוון מנקודת התייחסות קבועה, בדרך כלל צפון. ב-API של מפות Google, כותרת מוגדרת במעלות מצפון אמיתי, כאשר הכותרות נמדדות בכיוון השעון מצפון אמיתי (0 מעלות). אפשר לחשב את הכותרת הזו בין שני מיקומים באמצעות השיטה computeHeading(), ולהעביר אותה לשני אובייקטים from ו-to LatLng.

על סמך כותרת מסוימת, מיקום מוצא ומרחק הנסיעה (במטרים), תוכלו לחשב את הקואורדינטות של היעד באמצעות computeOffset().

בהינתן שני אובייקטים וערך של LatLng בין 0 ל-1, תוכלו גם לחשב יעד ביניהם באמצעות שיטת interpolate(), שמבצעת אינטרפולציה לינארית היקפית בין שני המיקומים, שבה הערך מציין את המרחק העשרוני של הנתיב מהמקור אל היעד.

בדוגמה הבאה יוצרים שני רכיבי קו (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;
דוגמה

לדגימה

שיטות קידוד

נתיבים ב-API של JavaScript ב-Maps מסומנים בדרך כלל כ-Array מתוך LatLng אובייקטים. עם זאת, העברה של מערך כזה היא הרבה פעמים גדולה. במקום זאת, תוכלו להשתמש באלגוריתם הקידוד של Polyline של 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 של הספרייה הגיאומטרית מכיל פונקציות עזר שקובעות אם נקודה מסוימת נמצאת בתוך פוליגון או פוליגון, או קרוב אליה.

מכיל LocationLocation()

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