도형 라이브러리

  1. 개요
  2. 구면기하학 개념
    1. 거리 및 면적 함수
    2. 탐색 함수
  3. 도형 인코딩
  4. 다각형 및 다중선 함수
    1. containsLocation()
    2. isLocationOnEdge()

개요

이 문서에 포함된 개념은 google.maps.geometry 라이브러리 내에서만 사용할 수 있는 기능과 관련이 있습니다. 이 라이브러리는 Maps JavaScript API를 로드할 때 기본적으로 로드되지 않으며 libraries 부트스트랩 매개변수를 사용하여 명시적으로 지정해야 합니다. 자세한 내용은 라이브러리 개요를 참고하세요.

Maps JavaScript API 도형 라이브러리는 지표면의 도형 데이터 계산을 위한 유틸리티 함수를 제공합니다. 이 라이브러리에는 세 개의 네임스페이스가 포함되어 있습니다.

  • spherical에는 각도 및 위도와 경도에서 각도, 거리 및 면적을 계산할 수 있는 구면기하학 유틸리티가 포함되어 있습니다.
  • encoding에는 인코딩된 다중선 알고리즘에 따라 다중선 경로를 인코딩 및 디코딩하는 유틸리티가 포함되어 있습니다.
  • poly에는 다각형 및 다중선과 관련된 계산을 하는 유틸리티 함수가 포함되어 있습니다.

google.maps.geometry 라이브러리에는 클래스가 포함되어 있지 않으며 대신 위의 네임스페이스에 대한 정적 메서드가 포함되어 있습니다.

구면기하학 개념

Maps JavaScript API 내의 이미지는 2차원이며 '평면'입니다. 하지만 지구는 3차원이며 대략적으로 편구면 또는 보다 단순하게는 구입니다. 지도 API 내에서는 구가 사용되며 컴퓨터 화면과 같은 2차원 평면에 지구를 표현하기 위해 투영을 사용합니다.

2D 투영에서는 모양이 실제와 다르게 표시될 수 있습니다. 지도 투영에서는 일부 왜곡이 발생할 수밖에 없으므로 일반 유클리드 기하학이 적용되지 않는 경우가 많습니다. 예를 들어 구에서 두 점 사이의 최단 거리는 직선이 아니라 큰 원(측지선의 한 유형)이며 구의 표면에서 삼각형을 이루는 각도의 합이 180도 이상이 되기도 합니다.

이러한 차이로 인해 구 또는 구의 투영의 도형 함수에서 거리, 방위, 면적과 같은 구성체를 계산하기 위해서는 구면기하학을 사용해야 합니다. Maps API의 google.maps.geometry.spherical 네임스페이스에는 구형 도형 구성체를 계산하기 위한 유틸리티가 포함되어 있습니다. 이 네임스페이스는 구의 좌표(위도와 경도)에서 스칼라 값을 계산하기 위한 정적 메서드를 제공합니다.

거리 및 면적 함수

두 점 사이의 거리는 두 점 사이의 최단 경로의 길이입니다. 이 최단 경로를 측지선이라고 합니다. 구에서 모든 측지선은 큰 원의 활꼴입니다. 이 거리를 계산하려면 computeDistanceBetween()을 호출하고 두 LatLng 객체에 전달하세요.

위치가 여러 개인 경우 대신 computeLength()를 사용하여 지정된 경로의 길이를 계산할 수 있습니다.

거리 결과는 미터 단위로 표현됩니다.

다각형 영역의 면적을 (제곱미터로) 계산하려면 닫힌 루프를 정의하는 computeArea()를 호출하고 LatLng 객체의 배열을 전달하세요.

구에서 탐색할 때 방위는 고정된 기준점(일반적으로 진북)으로부터 방향의 각도입니다. Google Maps API에서 방위는 진북으로부터 도 단위로 정의되며 진북(0도)으로부터 시계 방향으로 측정합니다. 두 위치 사이의 방위는 computeHeading() 메서드로 fromto 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 내 경로는 LatLng 객체의 Array로 지정될 때가 많습니다. 하지만 이러한 배열은 전달하기에 용량이 큰 경우가 많습니다. 대신 Google의 다중선 인코딩 알고리즘을 사용하여 지정된 경로를 압축하고 나중에 디코딩을 통해 압축을 해제할 수 있습니다.

geometry 라이브러리에는 유틸리티가 다중선을 인코딩 및 디코딩할 수 있는 encoding 네임스페이스가 포함되어 있습니다.

정적 메서드 encodePath()는 지정된 경로를 인코딩합니다. LatLng의 배열 또는 (Polyline.getPath()에서 반환하는) MVCArray를 전달할 수도 있습니다.

인코딩된 경로를 디코딩하려면 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);