> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> 지리 좌표 관련 문서

# 지리 좌표를 다루는 함수

<div id="greatcircledistance">
  ## greatCircleDistance
</div>

[대권 공식](https://en.wikipedia.org/wiki/Great-circle_distance)을 사용하여 지구 표면에 있는 두 지점 사이의 거리를 계산합니다.

```sql theme={null}
greatCircleDistance(lon1Deg, lat1Deg, lon2Deg, lat2Deg)
```

**입력 매개변수**

* `lon1Deg` — 첫 번째 지점의 경도(도)입니다. 범위: `[-180°, 180°]`.
* `lat1Deg` — 첫 번째 지점의 위도(도)입니다. 범위: `[-90°, 90°]`.
* `lon2Deg` — 두 번째 지점의 경도(도)입니다. 범위: `[-180°, 180°]`.
* `lat2Deg` — 두 번째 지점의 위도(도)입니다. 범위: `[-90°, 90°]`.

양수는 북위 및 동경을, 음수는 남위 및 서경을 나타냅니다.

**반환 값**

지구 표면의 두 지점 사이 거리이며, 단위는 미터입니다.

입력 매개변수 값이 범위를 벗어나면 예외가 발생합니다.

**예시**

```sql theme={null}
SELECT greatCircleDistance(55.755831, 37.617673, -55.755831, -37.617673) AS greatCircleDistance
```

```text theme={null}
┌─greatCircleDistance─┐
│            14128352 │
└─────────────────────┘
```

<div id="geodistance">
  ## geoDistance
</div>

`greatCircleDistance`와 유사하지만, 구면이 아니라 WGS-84 타원체에서 거리를 계산합니다. 이는 지구 지오이드를 더 정확하게 근사합니다.
성능은 `greatCircleDistance`와 동일하며(성능 저하 없음), 지구상 거리를 계산할 때는 `geoDistance`를 사용하는 것이 좋습니다.

기술 참고: 서로 충분히 가까운 지점의 경우, 좌표 중간점의 접평면 메트릭을 사용하는 평면 근사로 거리를 계산합니다.

```sql theme={null}
geoDistance(lon1Deg, lat1Deg, lon2Deg, lat2Deg)
```

**입력 매개변수**

* `lon1Deg` — 첫 번째 지점의 경도(도 단위)입니다. 범위: `[-180°, 180°]`.
* `lat1Deg` — 첫 번째 지점의 위도(도 단위)입니다. 범위: `[-90°, 90°]`.
* `lon2Deg` — 두 번째 지점의 경도(도 단위)입니다. 범위: `[-180°, 180°]`.
* `lat2Deg` — 두 번째 지점의 위도(도 단위)입니다. 범위: `[-90°, 90°]`.

양수는 북위와 동경을, 음수는 남위와 서경을 나타냅니다.

**반환 값**

지구 표면상의 두 지점 사이의 거리(미터)입니다.

입력 매개변수 값이 범위를 벗어나면 예외가 발생합니다.

**예시**

```sql theme={null}
SELECT geoDistance(38.8976, -77.0366, 39.9496, -75.1503) AS geoDistance
```

```text theme={null}
┌─geoDistance─┐
│   212458.73 │
└─────────────┘
```

<div id="greatcircleangle">
  ## greatCircleAngle
</div>

[대권 공식](https://en.wikipedia.org/wiki/Great-circle_distance)을 사용해 지구 표면의 두 지점 사이 중심각을 계산합니다.

```sql theme={null}
greatCircleAngle(lon1Deg, lat1Deg, lon2Deg, lat2Deg)
```

**입력 매개변수**

* `lon1Deg` — 첫 번째 지점의 경도이며, 단위는 도입니다.
* `lat1Deg` — 첫 번째 지점의 위도이며, 단위는 도입니다.
* `lon2Deg` — 두 번째 지점의 경도이며, 단위는 도입니다.
* `lat2Deg` — 두 번째 지점의 위도이며, 단위는 도입니다.

**반환 값**

두 지점 사이의 중심각입니다. 단위는 도입니다.

**예시**

```sql theme={null}
SELECT greatCircleAngle(0, 0, 45, 0) AS arc
```

```text theme={null}
┌─arc─┐
│  45 │
└─────┘
```

<div id="geotoutm">
  ## geoToUTM
</div>

WGS84 지리 좌표 `(longitude, latitude)`를 [Universal Transverse Mercator (UTM)](https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system) 좌표로 변환합니다.

UTM은 각각 경도 6° 너비의 구역을 포괄하는 60개의 횡축 메르카토르 투영으로 이루어진 체계로, 지리 좌표를 미터 단위의 평면 격자에 매핑합니다. 명시적으로 `zone`을 지정하지 않으면, 노르웨이와 스발바르에 대한 표준 예외를 적용하여 경도에 따라 구역을 자동으로 선택합니다. UTM은 위도 범위 `[-80°, 84°]`에서만 정의되며, 극지방에는 별도의 UPS 시스템을 사용합니다.

```sql theme={null}
geoToUTM(longitude, latitude[, zone])
```

**인수**

* `longitude` — 도 단위의 경도입니다. 범위: `[-180°, 180°]`. [`Float32`](/docs/ko/reference/data-types/float)/[`Float64`](/docs/ko/reference/data-types/float).
* `latitude` — 도 단위의 위도입니다. 범위: `[-80°, 84°]`. [`Float32`](/docs/ko/reference/data-types/float)/[`Float64`](/docs/ko/reference/data-types/float).
* `zone` — 선택 사항입니다. 자동으로 선택하지 않고 이 UTM 구역으로 투영하도록 강제합니다. 범위: `[1, 60]`. [`(U)Int*`](/docs/ko/reference/data-types/int-uint).

**반환 값**

named tuple `(easting, northing, zone, band)`입니다. `easting` 및 `northing`은 미터 단위([`Float64`](/docs/ko/reference/data-types/float))이고, `zone`은 UTM 구역 번호([`UInt8`](/docs/ko/reference/data-types/int-uint))이며, `band`는 MGRS 위도 밴드 문자([`FixedString(1)`](/docs/ko/reference/data-types/fixedstring))입니다. `band`가 `'N'` 이상이면 북반구를 나타냅니다.

위도가 `[-80°, 84°]` 범위를 벗어나거나 경도가 `[-180°, 180°]` 범위를 벗어나면 예외가 발생합니다.

**예시**

```sql theme={null}
SELECT geoToUTM(2.294497, 48.858222) AS utm; -- Eiffel Tower
```

```text theme={null}
(448251.5978370684,5411935.125629659,31,'U')
```

<div id="utmtogeo">
  ## UTMToGeo
</div>

[UTM](https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system) 좌표를 다시 WGS84 지리 좌표 `(경도, 위도)`로 변환합니다. [`geoToUTM`](#geotoutm)의 역변환입니다.

```sql theme={null}
UTMToGeo(easting, northing, zone, is_north)
```

**인수**

* `easting` — 미터 단위의 동향 좌표입니다(500000 m false easting 포함). [`(U)Int*`](/docs/ko/reference/data-types/int-uint)/[`Float*`](/docs/ko/reference/data-types/float).
* `northing` — 미터 단위의 북향 좌표입니다(남반구에서는 10000000 m false northing 포함). [`(U)Int*`](/docs/ko/reference/data-types/int-uint)/[`Float*`](/docs/ko/reference/data-types/float).
* `zone` — UTM 구역 번호입니다. 범위: `[1, 60]`. [`(U)Int*`](/docs/ko/reference/data-types/int-uint).
* `is_north` — 반구를 나타냅니다. 북반구는 `1`, 남반구는 `0`입니다. [`(U)Int*`](/docs/ko/reference/data-types/int-uint).

**반환 값**

도 단위의 named tuple `(longitude, latitude)`를 반환합니다. [`Tuple(Float64, Float64)`](/docs/ko/reference/data-types/tuple).

**예시**

```sql theme={null}
SELECT UTMToGeo(448251.6, 5411935.13, 31, 1) AS coord;
```

```text theme={null}
(2.2944970289079203,48.85822204127082)
```

<div id="geotomgrs">
  ## geoToMGRS
</div>

WGS84 지리 좌표 `(longitude, latitude)`를 [Military Grid Reference System (MGRS)](https://en.wikipedia.org/wiki/Military_Grid_Reference_System) 문자열로 인코딩합니다.

문자열은 `<zone><band><100km square><easting><northing>` 형식이며, 예를 들어 `31UDQ4825111935`와 같습니다. `precision` 인수는 easting과 northing에 각각 사용할 자릿수를 결정합니다. `5`(기본값)는 1 m, `4`는 10 m, `3`은 100 m, `2`는 1 km, `1`은 10 km, `0`은 100 km 그리드 사각형만을 나타냅니다. MGRS는 위도 범위 `[-80°, 84°]`에서만 정의됩니다.

```sql theme={null}
geoToMGRS(longitude, latitude[, precision])
```

**인수**

* `longitude` — 도 단위의 경도입니다. 범위: `[-180°, 180°]`. [`Float32`](/docs/ko/reference/data-types/float)/[`Float64`](/docs/ko/reference/data-types/float).
* `latitude` — 도 단위의 위도입니다. 범위: `[-80°, 84°]`. [`Float32`](/docs/ko/reference/data-types/float)/[`Float64`](/docs/ko/reference/data-types/float).
* `precision` — 선택 사항입니다. easting과 northing 각각의 자릿수입니다. 기본값: `5`. 범위: `[0, 5]`. [`(U)Int*`](/docs/ko/reference/data-types/int-uint).

**반환 값**

MGRS 참조 문자열입니다. [`String`](/docs/ko/reference/data-types/string).

**예시**

```sql theme={null}
SELECT geoToMGRS(2.294497, 48.858222) AS mgrs, geoToMGRS(2.294497, 48.858222, 3) AS mgrs_100m;
```

```text theme={null}
┌─mgrs────────────┬─mgrs_100m───┐
│ 31UDQ4825111935 │ 31UDQ482119 │
└─────────────────┴─────────────┘
```

<div id="mgrstogeo">
  ## MGRSToGeo
</div>

[MGRS](https://en.wikipedia.org/wiki/Military_Grid_Reference_System) 문자열을 WGS84 지리 좌표 `(longitude, latitude)`로 디코딩합니다. 이는 [`geoToMGRS`](#geotomgrs)의 역연산입니다.

반환되는 Point는 참조된 그리드 사각형의 중심이므로, 결과의 정밀도는 문자열에 인코딩된 정밀도와 일치합니다. 입력의 공백 문자는 무시되며 문자의 대소문자는 구분하지 않습니다.

```sql theme={null}
MGRSToGeo(mgrs)
```

**인수**

* `mgrs` — 디코딩할 MGRS 참조 문자열입니다. [`String`](/docs/ko/reference/data-types/string)/[`FixedString`](/docs/ko/reference/data-types/fixedstring).

**반환 값**

도 단위의 `(longitude, latitude)` named tuple을 반환합니다. [`Tuple(Float64, Float64)`](/docs/ko/reference/data-types/tuple).

**예시**

```sql theme={null}
SELECT MGRSToGeo('31UDQ4825111935') AS coord;
```

```text theme={null}
(2.294495618908297,48.85822536113692)
```

<div id="pointinellipses">
  ## pointInEllipses
</div>

점이 타원 중 하나 이상에 속하는지 확인합니다.
좌표는 데카르트 좌표계의 기하 좌표입니다.

```sql theme={null}
pointInEllipses(x, y, x₀, y₀, a₀, b₀,...,xₙ, yₙ, aₙ, bₙ)
```

**입력 매개변수**

* `x, y` — 평면 위 한 점의 좌표입니다.
* `xᵢ, yᵢ` — `i`번째 타원 중심의 좌표입니다.
* `aᵢ, bᵢ` — `i`번째 타원의 x축, y축 방향 반지름입니다.

입력 매개변수의 개수는 `2+4⋅n`이어야 하며, 여기서 `n`은 타원의 개수입니다.

**반환 값**

점이 하나 이상의 타원 내부에 있으면 `1`, 그렇지 않으면 `0`입니다.

**예시**

```sql theme={null}
SELECT pointInEllipses(10., 10., 10., 9.1, 1., 0.9999)
```

```text theme={null}
┌─pointInEllipses(10., 10., 10., 9.1, 1., 0.9999)─┐
│                                               1 │
└─────────────────────────────────────────────────┘
```

<div id="pointinpolygon">
  ## pointInPolygon
</div>

평면상에서 점이 폴리곤에 포함되는지 확인합니다.

```sql theme={null}
pointInPolygon((x, y), [(a, b), (c, d) ...], ...)
```

**입력 값**

* `(x, y)` — 평면 위 한 점의 좌표입니다. 데이터 타입 — [Tuple](/docs/ko/reference/data-types/tuple) — 두 개의 숫자로 이루어진 튜플 또는 [Point](/docs/ko/reference/data-types/geo#point)입니다.
* `[(a, b), (c, d) ...]` — 다각형의 꼭짓점입니다. 데이터 타입 — [Array](/docs/ko/reference/data-types/array) 또는 [Ring](/docs/ko/reference/data-types/geo#ring)입니다. 각 꼭짓점은 좌표 쌍 `(a, b)`로 표현됩니다. 꼭짓점은 시계 방향 또는 반시계 방향 순서로 지정해야 합니다. 꼭짓점의 최소 개수는 3개입니다.
* 이 함수는 구멍(비어 있는 내부 영역)이 있는 다각형도 지원합니다. 데이터 타입 — [Polygon](/docs/ko/reference/data-types/geo#polygon). 전체 `Polygon`을 두 번째 인수로 전달하거나, 바깥쪽 링을 먼저 전달한 다음 각 구멍을 별도의 추가 인수로 전달할 수 있습니다.
* 이 함수는 다중 다각형도 지원합니다. 데이터 타입 — [MultiPolygon](/docs/ko/reference/data-types/geo#multipolygon). 전체 `MultiPolygon`을 두 번째 인수로 전달하거나, 각 구성 다각형을 각각의 인수로 나열할 수 있습니다.
* 다각형 인수는 다각형 형태의 값(`Ring`, `Polygon` 또는 `MultiPolygon`)을 담고 있는 [Geometry](/docs/ko/reference/data-types/geo#geometry) 컬럼일 수도 있습니다.

다각형 형태의 타입([Ring](/docs/ko/reference/data-types/geo#ring), [Polygon](/docs/ko/reference/data-types/geo#polygon), [MultiPolygon](/docs/ko/reference/data-types/geo#multipolygon), [Geometry](/docs/ko/reference/data-types/geo#geometry))은 상수 또는 일반적인(비상수) 테이블 컬럼으로 전달할 수 있습니다. 다각형이 여러 개의 개별 인수(바깥쪽 링 뒤에 구멍이 오는 경우 또는 multipolygon의 여러 다각형)에 나뉘어 전달되는 경우, 해당 인수는 모두 상수여야 합니다.

**반환 값**

점이 다각형 내부에 있으면 `1`, 그렇지 않으면 `0`입니다.
점이 다각형 경계 위에 있으면 함수는 `0` 또는 `1`을 반환할 수 있습니다.

**예시**

```sql theme={null}
SELECT pointInPolygon((3., 3.), [(6, 0), (8, 4), (5, 8), (0, 2)]) AS res
```

```text theme={null}
┌─res─┐
│   1 │
└─────┘
```

다각형은 테이블 컬럼을 포함해, 이름이 지정된 기하 데이터 타입으로도 전달할 수 있습니다:

```sql theme={null}
CREATE TABLE poly (id UInt32, shape Polygon) ENGINE = Memory;
INSERT INTO poly VALUES (1, [[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (6, 4), (6, 6), (4, 6)]]);
SELECT id, pointInPolygon((2., 2.), shape) AS res FROM poly;
```

```text theme={null}
┌─id─┬─res─┐
│  1 │   1 │
└────┴─────┘
```

> **참고**
> • `validate_polygons = 0`을 설정하면 geometry 유효성 검사를 건너뛸 수 있습니다.
> • `pointInPolygon`은 모든 다각형이 올바른 형식이라고 가정합니다. 입력이 자기 교차하거나, Ring의 순서가 잘못되었거나, edge가 겹치면 결과를 신뢰할 수 없게 됩니다. 특히 edge나 vertex 위에 정확히 놓인 점이나, "inside"와 "outside"의 개념이 정의되지 않는 자기 교차 내부의 점에서는 더욱 그렇습니다.
> • 다각형 인수가 상수이고 점이 인덱스가 적용된 키 컬럼으로 표현되는 경우(예: `x, y`가 `PRIMARY KEY`의 일부이거나 `minmax` 인덱스로 처리되는 테이블에서 `pointInPolygon((x, y), constant_polygon)`를 사용하는 경우), ClickHouse는 프라이머리 키(primary key)와 `minmax` 데이터 스키핑 인덱스를 모두 사용해 관련 없는 그래뉼을 걸러낼 수 있습니다.
