@bubaley

Как сжать массив координат?

В базе данных есть полигоны с большим количеством координат. Когда пользователь заходит в web-приложение происходит запрос к этим полигонам и отрисовка их на карте. Вес ответа составляет 7мб+, где почти вся часть этого веса это координаты.
Часто эти полигоны редактируются, поэтому постоянно кешировать их не вариант. Хотелось бы представить координаты полигонов в виде строк (чтобы уменьшить вес, надеюсь есть какие-то алгоритмы для этого), а потом на фронте их распарсить обратно в массивы координат.
Я понимаю, что при запросе и так работает gzip, но этого все равно мало.
Как можно решить это задачу?
  • Вопрос задан
  • 369 просмотров
Решения вопроса 1
@bubaley Автор вопроса
В итоге использовал следующий шаги для сжатия координат. Сразу о результатах до этих действий:
Было:
10 секунд загрузки
7.5 мб данных
Стало:
2 секунды загрузки
540 кб

Пример:
python
1. Shapely.simplify() для сглаживания координат (показатель подбирал для себя)
2. Дельта кодирования, для уменьшения объема данных
polygon = Polygon(coords).simplify(0.00015)
    coords = list(polygon.exterior.coords)
    lng_list = list()
    last_lng = None
    lat_list = list()
    last_lat = None
    for val in coords:
        if not last_lng:
            lng_list.append(val[0])
            lat_list.append(val[1])
        else:
            lng_list.append(round(val[0] - last_lng, 6))
            lat_list.append(round(val[1] - last_lat, 6))
        last_lng = val[0]
        last_lat = val[1]
    return {
        'lat': lat_list,
        'lng': lng_list
    }

3. Компрессия данных:
Делается в одну строку
b64encode(zlib.compress(json.dumps(data).encode('utf-8')))

JavaScript
4. Приведение к объекту JS из сжатой строки
let newData = atob(data)
    newData = newData.split('').map(function (e) {
        return e.charCodeAt(0)
    })
    newData = new Uint8Array(newData)
    newData = pako.inflate(newData)
    newData = new TextDecoder().decode(newData)
    return JSON.parse(newData)

5. Преобразование к нормальному виду координат из дельта-закодированных данных
let lastLat = null
    let lastLng = null
    let result = []
            coords.forEach(val => {
            let newCoords = []
            for (const [index, el] of val.lat.entries()) {
                if (!index) {
                    lastLat = val.lat[0]
                    lastLng = val.lng[0]
                } else {
                    lastLng += val.lng[index]
                    lastLat += val.lat[index]
                }
                newCoords.push([lastLng, lastLat])
            }
            result.push(newCoords)
        })
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
fox_12
@fox_12 Куратор тега Python
Расставляю биты, управляю заряженными частицами
Прочитайте про protobuff - возможно это вам поможет.
Ответ написан
Комментировать
MayorPlay
@MayorPlay
!Программист
Если передавать их в виде строки, которую можно будет распарсить, то передавай данные через JSON
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы