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

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

סקירה כללית

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

ספריית הגיאומטריה של Maps JavaScript API מספקת תועלת לחישוב של נתונים גאומטריים על פני השטח Google Earth. הספרייה כוללת שלושה מרחבי שמות:

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

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

מושגים בנושא גיאומטריה כדורית

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

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

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

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

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

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