Работа с геопространственными данными в Turf.js неизбежно выходит за пределы идеального GeoJSON-мира, в котором каждый объект строго соответствует спецификации RFC 7946. Реальные данные приходят в смешанных форматах, с нарушенной структурой, дополнительными координатными измерениями, нестандартными системами координат и частично повреждёнными геометриями. Именно работа с такими представлениями определяет устойчивость геообработки.
GeoJSON задаёт строгую модель: координаты представлены как массивы
чисел [lon, lat], иногда с дополнительными измерениями
[lon, lat, alt]. На практике встречаются отклонения:
"37.61, 55.75"[lat, lon] вместо [lon, lat][lon, lat, timestamp]null,
undefinedTurf.js ожидает корректный GeoJSON, но не блокирует полностью нестандартные структуры до момента выполнения операций. Ошибки чаще проявляются при геометрических вычислениях, а не при парсинге.
Перед любыми пространственными операциями данные приводятся к единому виду. Базовая стратегия нормализации включает:
Типичная функция нормализации координат:
function normalizeCoord(coord) {
if (typeof coord === "string") {
const [a, b] = coord.split(",").map(Number);
return [a, b];
}
if (Array.isArray(coord)) {
return coord.slice(0, 2).map(Number);
}
return null;
}
После нормализации данные можно безопасно передавать в Turf-операции
вроде turf.point, turf.lineString или
turf.polygon.
GeoJSON допускает расширенные координаты:
[lon, lat, alt] — высота[lon, lat, m] — мера (M-значение)[lon, lat, alt, m] — комбинированный форматTurf.js в большинстве операций игнорирует дополнительные измерения, используя только первые два значения.
При необходимости сохранения Z-значений применяется стратегия сохранения метаданных:
function stripZKeepMeta(coord) {
return {
xy: [coord[0], coord[1]],
z: coord.length > 2 ? coord[2] : null
};
}
Это важно при моделировании рельефа, 3D-трассировке маршрутов и гидрологических данных, где высота влияет на анализ, но не поддерживается напрямую в геометрических функциях Turf.
Нестандартные данные часто содержат ошибки:
Turf предоставляет инструменты для диагностики и частичного исправления:
turf.cleanCoords — удаление лишних точекturf.booleanValid — проверка валидности геометрииturf.truncate — округление координатПример фильтрации:
function validateLine(line) {
const cleaned = turf.cleanCoords(line);
if (cleaned.geometry.coordinates.length < 2) {
return null;
}
return cleaned;
}
WKT не является нативным форматом GeoJSON, но широко используется в GIS-системах. Типичные примеры:
POINT (30 10)
LINESTRING (30 10, 10 30, 40 40)
POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))
Для интеграции WKT-данных применяется промежуточное преобразование:
function wktPointToGeoJSON(wkt) {
const match = wkt.match(/POINT\s*\(([^)]+)\)/);
const [x, y] = match[1].split(" ").map(Number);
return turf.point([x, y]);
}
При массовой обработке используется полноценный парсер, а не регулярные выражения.
KML (Keyhole Markup Language) часто содержит:
Перед использованием в Turf данные приводятся к GeoJSON через
промежуточные библиотеки (например, togeojson). После
конвертации важно:
Типичная проблема — смешение типов объектов:
{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "geometry": { "type": "Point" } },
{ "type": "Feature", "geometry": null },
{ "type": "Feature", "geometry": { "type": "LineString", "coordinates": [] } }
]
}
Фильтрация:
function filterValidFeatures(fc) {
return {
...fc,
features: fc.features.filter(f =>
f.geometry &&
f.geometry.coordinates &&
f.geometry.coordinates.length > 0
)
};
}
В реальных наборах данных часто встречаются:
Очистка выполняется через последовательные шаги:
function sanitizeCoords(coords) {
return coords
.filter(c => Array.isArray(c))
.map(c => c.map(Number))
.filter(c => c.every(n => Number.isFinite(n)));
}
После этого данные становятся пригодными для
turf.lineString и turf.polygon.
Turf.js работает исключительно в WGS84 (EPSG:4326). Поэтому любые входные данные из других систем координат требуют предварительного преобразования.
Типичный сценарий:
Преобразование выполняется через внешние библиотеки:
Пример:
function toWGS84([x, y]) {
return proj4("EPSG:3857", "EPSG:4326", [x, y]);
}
После трансформации данные становятся совместимыми с Turf-операциями.
При работе с большими файлами возникают проблемы:
Используется потоковая модель:
function processStream(features, fn) {
const results = [];
for (const feature of features) {
if (!feature.geometry) continue;
results.push(fn(feature));
}
return results;
}
Часто данные приходят одновременно из:
Унификация требует приведения всех источников к Feature:
function toFeature(input) {
if (Array.isArray(input)) {
return turf.point(input);
}
if (input.lat && input.lon) {
return turf.point([input.lon, input.lat]);
}
return null;
}
Нестандартные наборы могут содержать:
Перед анализом выполняется группировка по типу:
function groupByGeometry(fc) {
return fc.features.reduce((acc, f) => {
const type = f.geometry.type;
acc[type] = acc[type] || [];
acc[type].push(f);
return acc;
}, {});
}
Это позволяет применять разные Turf-функции к каждому классу объектов.
Геоданные часто приходят с ошибками сериализации:
Решение заключается в предварительной валидации и мягком парсинге:
function safeParse(json) {
try {
return JSON.parse(json);
} catch (e) {
return null;
}
}
При интеграции с Turf.js формируется многоуровневая цепочка:
Такая архитектура обеспечивает устойчивость к реальным геоданным, которые редко соответствуют идеальной спецификации.