Интерполяция высот в Turf.js строится вокруг представления
поверхности как набора дискретных точек с координатами вида
[lng, lat, z], где третья компонента z
отражает высоту. Основное ограничение исходных данных — нерегулярность
распределения точек: они редко образуют равномерную сетку, что делает
невозможным прямое использование простых растровых методов без
предварительной геометрической обработки.
Ключевым шагом становится преобразование набора точек в непрерывную аппроксимацию поверхности. В Turf.js для этого используются триангуляционные структуры и геометрические операции над полигонами и точками.
Формат исходного набора данных:
const points = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [71.4304, 51.1281, 345]
},
properties: {}
},
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [71.5002, 51.1407, 410]
},
properties: {}
}
]
};
Третья координата интерпретируется как высота над уровнем моря или условная отметка рельефа.
Для построения непрерывной модели используется триангуляция Делоне. Turf.js предоставляет инструмент, который преобразует облако точек в набор треугольников:
import * as turf from "@turf/turf";
const tin = turf.tin(points, "elevation");
Каждый треугольник хранит вершины исходных точек, а также атрибуты
высоты, привязанные к ним. Результатом является
FeatureCollection полигонов, где каждый полигон — это
треугольник поверхности.
Структура результата:
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [[[lng, lat], [lng, lat], [lng, lat], [lng, lat]]]
},
properties: {
a: 345,
b: 410,
c: 380
}
}
Каждое значение a, b, c
соответствует высоте вершины треугольника.
Триангуляция обеспечивает два критических свойства:
После разбиения пространства на треугольники задача сводится к вычислению высоты произвольной точки внутри конкретного треугольника.
Turf.js использует геометрический принцип плоскости: три точки определяют плоскость в трёхмерном пространстве, а любая точка внутри треугольника может быть выражена через барицентрические координаты.
Для вычисления высоты применяется turf.planepoint:
const triangle = tin.features[0];
const point = turf.point([71.45, 51.135]);
const elevation = turf.planepoint(point, triangle);
Пусть вершины треугольника имеют координаты:
Любая точка P(x, y) внутри треугольника задаётся коэффициентами:
Тогда высота:
Эта модель обеспечивает линейную интерполяцию без разрывов внутри одного треугольника.
Перед интерполяцией необходимо определить, в каком треугольнике находится точка. Turf.js выполняет пространственный поиск по коллекции полигонов:
let found = null;
for (const f of tin.features) {
if (turf.booleanPointInPolygon(point, f)) {
found = f;
break;
}
}
После нахождения соответствующего полигона выполняется интерполяция высоты.
Оптимизация для больших наборов данных обычно требует пространственных индексов, но базовая модель Turf.js работает через перебор.
Интерполяция часто используется не для одной точки, а для генерации непрерывного поля высот. Для этого создаётся сетка точек:
const bbox = turf.bbox(points);
const grid = turf.pointGrid(bbox, 0.01, {
units: "degrees"
});
Каждая точка сетки затем проецируется на триангулированную поверхность.
const result = grid.features.map(p => {
const tri = tin.features.find(f =>
turf.booleanPointInPolygon(p, f)
);
if (!tri) return null;
const z = turf.planepoint(p, tri);
return turf.point([...p.geometry.coordinates, z]);
});
Результатом становится плотная сетка высот, пригодная для визуализации или дальнейшего анализа.
Хотя Turf.js не реализует полноценный IDW (Inverse Distance Weighting) как встроенную функцию высотной интерполяции, подобная модель может быть построена поверх базовых инструментов.
Идея заключается в том, что высота точки вычисляется как взвешенная сумма соседних значений:
function idw(point, points) {
let num = 0;
let den = 0;
for (const f of points.features) {
const d = turf.distance(point, f, { units: "meters" });
const weight = 1 / Math.pow(d + 0.0001, 2);
num += f.geometry.coordinates[2] * weight;
den += weight;
}
return num / den;
}
Эта модель менее геометрически строгая, но более сглаженная и подходит для шумных данных.
Практическая интерполяция часто требует объединения двух методов:
После вычисления базовой высоты через planepoint можно
применить локальное усреднение:
function smoothElevation(point, neighbors) {
let sum = 0;
for (const n of neighbors) {
sum += n.geometry.coordinates[2];
}
return sum / neighbors.length;
}
Формируется двухуровневая модель:
Высотные данные часто требуются не в виде сетки, а вдоль маршрута: дорог, рек, треков.
Используется разбиение линии на сегменты и вычисление высоты для каждой промежуточной точки:
const line = turf.lineString([
[71.43, 51.12],
[71.50, 51.14]
]);
const along = turf.lineChunk(line, 0.01, { units: "kilometers" });
const enriched = along.features.map(seg => {
const mid = turf.along(seg, turf.length(seg) / 2);
const tri = tin.features.find(f =>
turf.booleanPointInPolygon(mid, f)
);
const z = tri ? turf.planepoint(mid, tri) : null;
return turf.point([...mid.geometry.coordinates, z]);
});
Таким образом формируется профиль высот вдоль маршрута.
Линейная интерполяция внутри TIN имеет ряд ограничений:
Для компенсации используются:
Интерполяция в Turf.js выполняется в географических координатах, что создаёт искажения расстояний при больших масштабах.
Для повышения точности часто применяется:
Это критично при работе с высокоточным рельефом, где градусная сетка неравномерна.
Полученные высоты часто используются для построения:
Контурные линии формируются через разбиение диапазона высот:
const breaks = [300, 350, 400, 450];
const contours = breaks.map(level => {
return result.filter(p => p.geometry.coordinates[2] >= level);
});
Интерполированные высоты применяются не только для визуализации, но и для анализа:
Уклон между двумя точками:
const slope =
(z2 - z1) /
turf.distance(p1, p2, { units: "meters" });
При увеличении объёма данных используется многоуровневая схема:
Так формируется воспроизводимая модель высотного поля, пригодная для масштабируемых геопространственных вычислений.