CSV данные с координатами

CSV-файлы с координатами остаются одним из самых распространённых способов передачи геоданных в прикладных задачах: логистика, трекинг, анализ точек продаж, экспорт из GPS-устройств, выгрузки из CRM и телематики. В контексте работы с HERE Maps API такие данные чаще всего используются для динамического построения объектов на карте — маркеров, кластеров, маршрутов и слоёв визуализации.

Типичная CSV-структура для картографических задач содержит как минимум два столбца:

latitude,longitude
55.7558,37.6173
51.5074,-0.1278
48.8566,2.3522

Однако на практике почти всегда добавляются дополнительные поля:

id,name,latitude,longitude,category,timestamp
1,Moscow,55.7558,37.6173,city,2026-06-01T10:00:00Z
2,London,51.5074,-0.1278,city,2026-06-01T10:05:00Z

Ключевой момент при работе с картографическими API — строгая интерпретация координат:

  • latitude (широта) — первый параметр географической позиции по оси Y
  • longitude (долгота) — второй параметр по оси X
  • порядок должен быть строго соблюдён, так как многие ошибки визуализации связаны именно с его нарушением

Парсинг CSV в JavaScript

Для обработки CSV в браузере или Node.js часто используется ручной разбор или специализированные библиотеки. При интеграции с HERE Maps API достаточно привести данные к массиву объектов.

Ручной парсинг:

function parseCSV(text) {
    const lines = text.trim().split("\n");
    const headers = lines[0].split(",");

    return lines.slice(1).map(line => {
        const values = line.split(",");
        const obj = {};

        headers.forEach((h, i) => {
            obj[h.trim()] = values[i].trim();
        });

        return obj;
    });
}

После преобразования данные приобретают структуру:

[
  { latitude: "55.7558", longitude: "37.6173", name: "Moscow" },
  { latitude: "51.5074", longitude: "-0.1278", name: "London" }
]

Для работы с картой значения координат должны быть приведены к числам:

const points = parsed.map(p => ({
    lat: parseFloat(p.latitude),
    lng: parseFloat(p.longitude),
    name: p.name
}));

Создание карты и базовая интеграция HERE Maps API

Инициализация карты требует платформы, слоя отображения и объекта карты.

const platform = new H.service.Platform({
    apikey: "YOUR_API_KEY"
});

const defaultLayers = platform.createDefaultLayers();

const map = new H.Map(
    document.getElementById("map"),
    defaultLayers.vector.normal.map,
    {
        center: { lat: 0, lng: 0 },
        zoom: 2,
        pixelRatio: window.devicePixelRatio || 1
    }
);

const beh * avior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
const ui = H.ui.UI.createDefault(map, defaultLayers);

Отображение точек из CSV как маркеров

После преобразования CSV в массив координат формируются объекты H.map.Marker.

const group = new H.map.Group();

points.forEach(point => {
    const marker = new H.map.Marker({
        lat: point.lat,
        lng: point.lng
    });

    marker.setData(point.name);
    group.addObject(marker);
});

map.addObject(group);
map.setCenter(group.getBoundingBox().getCenter());
map.getViewModel().setLookAtData({
    bounds: group.getBoundingBox()
});

Использование группы объектов позволяет управлять всей коллекцией точек как единым слоем.


Обработка больших CSV-файлов

При работе с тысячами или десятками тысяч координат прямое добавление маркеров становится неэффективным. Основные проблемы:

  • рост нагрузки на DOM и WebGL слой
  • замедление перерисовки карты
  • увеличение времени инициализации

Для оптимизации применяется:

1. Кластеризация точек

const clusteringProvider = new H.clustering.Provider(points.map(p => ({
    lat: p.lat,
    lng: p.lng
})));

const clusteringLayer = new H.map.layer.ObjectLayer(clusteringProvider);
map.addLayer(clusteringLayer);

Кластеризация автоматически объединяет близкие точки в группы, снижая визуальную нагрузку.


2. Ленивый рендеринг (chunking)

function addInChunks(points, chunkSize = 500) {
    let index = 0;

    function processChunk() {
        const slice = points.slice(index, index + chunkSize);

        slice.forEach(p => {
            const marker = new H.map.Marker({ lat: p.lat, lng: p.lng });
            map.addObject(marker);
        });

        index += chunkSize;

        if (index < points.length) {
            requestAnimationFrame(processChunk);
        }
    }

    processChunk();
}

Такой подход предотвращает блокировку основного потока.


Преобразование CSV в GeoJSON

Многие функции HERE Maps API работают эффективнее с GeoJSON-структурами.

function toGeoJSON(points) {
    return {
        type: "FeatureCollection",
        features: points.map(p => ({
            type: "Feature",
            geometry: {
                type: "Point",
                coordinates: [p.lng, p.lat]
            },
            properties: {
                name: p.name
            }
        }))
    };
}

GeoJSON можно использовать как промежуточный слой для аналитики, фильтрации и стилизации.


Загрузка CSV из внешнего источника

Часто CSV поступает через HTTP-запрос:

fetch("/data/points.csv")
    .then(res => res.text())
    .then(text => {
        const data = parseCSV(text);
        const points = data.map(p => ({
            lat: parseFloat(p.latitude),
            lng: parseFloat(p.longitude),
            name: p.name
        }));

        addInChunks(points);
    });

При работе с удалёнными источниками важно учитывать:

  • CORS-политику сервера
  • кодировку UTF-8
  • наличие заголовков CSV
  • корректность разделителей (, или ;)

Валидация координат

Перед добавлением на карту данные должны проходить фильтрацию:

function isValidLatLng(lat, lng) {
    return (
        typeof lat === "number" &&
        typeof lng === "number" &&
        lat >= -90 && lat <= 90 &&
        lng >= -180 && lng <= 180
    );
}

Применение:

const clean = points.filter(p => isValidLatLng(p.lat, p.lng));

Работа с ошибками данных CSV

Типичные проблемы:

  • пустые строки в файле
  • пропущенные координаты
  • некорректные разделители
  • смешение десятичной запятой и точки

Решение заключается в нормализации:

function normalizeNumber(value) {
    return parseFloat(String(value).replace(",", "."));
}

Связь CSV и слоёв карты

CSV-данные редко отображаются как единый слой. Чаще формируются логические группы:

  • транспортные точки
  • точки продаж
  • события
  • геозоны

Пример группировки:

const groups = points.reduce((acc, p) => {
    if (!acc[p.category]) acc[p.category] = [];
    acc[p.category].push(p);
    return acc;
}, {});

Каждая группа может быть вынесена в отдельный слой карты:

Object.keys(groups).forEach(key => {
    const layer = new H.map.Group();

    groups[key].forEach(p => {
        layer.addObject(new H.map.Marker({ lat: p.lat, lng: p.lng }));
    });

    map.addObject(layer);
});

Производительность при потоковой обработке CSV

При работе с потоковыми данными используется подход incremental parsing:

const reader = response.body.getReader();
const decoder = new TextDecoder();

let csvBuffer = "";

while (true) {
    const { value, done } = await reader.read();
    if (done) break;

    csvBuffer += decoder.decode(value, { stream: true });

    const lines = csvBuffer.split("\n");
    csvBuffer = lines.pop();

    lines.forEach(line => {
        const [lat, lng] = line.split(",");
        if (lat && lng) {
            map.addObject(new H.map.Marker({
                lat: parseFloat(lat),
                lng: parseFloat(lng)
            }));
        }
    });
}

CSV как источник геоданных в связке с HERE Maps API формирует универсальный механизм визуализации пространственной информации, где ключевую роль играет корректная нормализация координат, контроль структуры данных и выбор стратегии рендеринга в зависимости от объёма входящего массива.