> ## 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 — это набор из 60 поперечных проекций Меркатора, каждая из которых охватывает зону по долготе шириной 6° и отображает географические координаты на плоскую сетку в метрах. Зона автоматически выбирается по долготе с учетом стандартных исключений для Норвегии и Шпицбергена, если явно не указана `zone`. UTM определена только для широт в диапазоне `[-80°, 84°]`; для полярных областей используется отдельная система UPS.

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

**Аргументы**

* `longitude` — Долгота в градусах. Диапазон: `[-180°, 180°]`. [`Float32`](/docs/ru/reference/data-types/float)/[`Float64`](/docs/ru/reference/data-types/float).
* `latitude` — Широта в градусах. Диапазон: `[-80°, 84°]`. [`Float32`](/docs/ru/reference/data-types/float)/[`Float64`](/docs/ru/reference/data-types/float).
* `zone` — Необязательно. Принудительно использовать эту зону UTM для проекции вместо автоматического выбора. Диапазон: `[1, 60]`. [`(U)Int*`](/docs/ru/reference/data-types/int-uint).

**Возвращаемое значение**

Именованный кортеж `(easting, northing, zone, band)`: `easting` и `northing` в метрах ([`Float64`](/docs/ru/reference/data-types/float)), номер зоны UTM `zone` ([`UInt8`](/docs/ru/reference/data-types/int-uint)) и буква широтной полосы MGRS `band` ([`FixedString(1)`](/docs/ru/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 `(longitude, latitude)`. Это функция, обратная [`geoToUTM`](#geotoutm).

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

**Аргументы**

* `easting` — восточное смещение в метрах (включая ложное восточное смещение 500000 м). [`(U)Int*`](/docs/ru/reference/data-types/int-uint)/[`Float*`](/docs/ru/reference/data-types/float).
* `northing` — северное смещение в метрах (включая ложное северное смещение 10000000 м для южного полушария). [`(U)Int*`](/docs/ru/reference/data-types/int-uint)/[`Float*`](/docs/ru/reference/data-types/float).
* `zone` — номер зоны UTM. Диапазон: `[1, 60]`. [`(U)Int*`](/docs/ru/reference/data-types/int-uint).
* `is_north` — полушарие: `1` для северного полушария, `0` для южного. [`(U)Int*`](/docs/ru/reference/data-types/int-uint).

**Возвращаемое значение**

Именованный кортеж `(longitude, latitude)` в градусах. [`Tuple(Float64, Float64)`](/docs/ru/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 м, `4` для 10 м, `3` для 100 м, `2` для 1 км, `1` для 10 км и `0` — только для квадрата сетки 100 км. Система MGRS определена только для широт в диапазоне `[-80°, 84°]`.

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

**Аргументы**

* `longitude` — Долгота в градусах. Диапазон: `[-180°, 180°]`. [`Float32`](/docs/ru/reference/data-types/float)/[`Float64`](/docs/ru/reference/data-types/float).
* `latitude` — Широта в градусах. Диапазон: `[-80°, 84°]`. [`Float32`](/docs/ru/reference/data-types/float)/[`Float64`](/docs/ru/reference/data-types/float).
* `precision` — Необязательно. Количество цифр для значений восточного и северного смещения. По умолчанию: `5`. Диапазон: `[0, 5]`. [`(U)Int*`](/docs/ru/reference/data-types/int-uint).

**Возвращаемое значение**

Строка координат MGRS. [`String`](/docs/ru/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 `(долгота, широта)`. Это обратная операция по отношению к [`geoToMGRS`](#geotomgrs).

Возвращаемая точка — центр соответствующего квадрата сетки, поэтому точность результата соответствует точности, закодированной в строке. Пробельные символы во входных данных игнорируются, а регистр букв не учитывается.

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

**Аргументы**

* `mgrs` — строка координат MGRS для декодирования. [`String`](/docs/ru/reference/data-types/string)/[`FixedString`](/docs/ru/reference/data-types/fixedstring).

**Возвращаемое значение**

Именованный кортеж `(longitude, latitude)` в градусах. [`Tuple(Float64, Float64)`](/docs/ru/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/ru/reference/data-types/tuple) — кортеж из двух чисел или [Point](/docs/ru/reference/data-types/geo#point).
* `[(a, b), (c, d) ...]` — Вершины полигона. Тип данных — [Array](/docs/ru/reference/data-types/array) или [Ring](/docs/ru/reference/data-types/geo#ring). Каждая вершина задаётся парой координат `(a, b)`. Вершины следует указывать по часовой стрелке или против часовой стрелки. Минимальное число вершин — 3.
* Функция поддерживает полигоны с отверстиями (вырезанными областями). Тип данных — [Polygon](/docs/ru/reference/data-types/geo#polygon). Либо передайте весь `Polygon` как второй аргумент, либо сначала передайте внешний Ring, а затем каждое отверстие как отдельный дополнительный аргумент.
* Функция также поддерживает `MultiPolygon`. Тип данных — [MultiPolygon](/docs/ru/reference/data-types/geo#multipolygon). Либо передайте весь `MultiPolygon` как второй аргумент, либо перечислите каждый входящий в него полигон как отдельный аргумент.
* Аргумент полигона также может быть столбцом [Geometry](/docs/ru/reference/data-types/geo#geometry), содержащим значения полигональных типов (`Ring`, `Polygon` или `MultiPolygon`).

Полигональные типы ([Ring](/docs/ru/reference/data-types/geo#ring), [Polygon](/docs/ru/reference/data-types/geo#polygon), [MultiPolygon](/docs/ru/reference/data-types/geo#multipolygon) и [Geometry](/docs/ru/reference/data-types/geo#geometry)) можно передавать либо как константы, либо как обычные (неконстантные) столбцы таблицы. Когда полигон передаётся через несколько отдельных аргументов (внешний Ring, за которым следуют отверстия, или несколько полигонов в составе мультиполигона), все эти аргументы должны быть константами.

**Возвращаемые значения**

`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`, чтобы отключить проверку геометрии.
> • `pointInPolygon` исходит из того, что каждый полигон сформирован корректно. Если входной полигон самопересекается, содержит кольца в неправильном порядке или перекрывающиеся рёбра, результаты становятся ненадёжными — особенно для точек, которые лежат точно на ребре, в вершине или внутри самопересечения, где невозможно однозначно определить, что считать "внутри", а что — "снаружи".
> • Когда аргумент полигона является константой, а точка задаётся с использованием индексируемых столбцов ключа (например, `pointInPolygon((x, y), constant_polygon)` в таблице, где `x, y` входят в `PRIMARY KEY` или покрываются индексом `minmax`), ClickHouse может использовать и первичный ключ, и индексы пропуска данных `minmax`, чтобы отсечь нерелевантные гранулы.
