Устройство хранения данных широты/Долготы и сжатие в C

olliej's округление метод является неправильным при отрицательных числах

  • , 2,4 округленных равняются 2 (метод olliej разбирается в этом)
  • , в€ ’2,4 округленных является в€ ’2 (метод olliej возвращается-1)

, Вот альтернатива

  int myInt = (int)(myDouble + (myDouble>0 ? 0.5 : -0.5))

, Вы могли, конечно, использовать округляющуюся функцию от math.h

24
задан luvieere 7 October 2009 в 22:03
поделиться

8 ответов

Лично я бы использовал 32-битное десятичное представление с фиксированной запятой, разделив на 1000000 в соответствии с ответом Эвана и моими комментариями.

Однако, если пространство действительно ограничено, вот некоторые дополнительные идеи:

  • Вы можете использовать 26-битное представление с фиксированной точкой на проводе. Это потребует маршалинга и демаршалинга широты и долготы в большой массив байтов, но сэкономит вам 12 бит для каждого местоположения по сравнению с 32-битным представлением значения - почти 19% экономии, так что это вполне может оказаться стоящим.

  • могли бы воспользоваться тем фактом, что для значений долготы требуется меньшая точность по мере приближения к полюсам - им нужно всего 26 бит на экваторе. Таким образом, вы можете написать схему, в которой количество битов, используемых для кодирования долготы, зависит от значения широты.

  • Если ваши данные имеют другие сжимаемые атрибуты - скажем, все точки обычно расположены довольно близко друг к другу - вы можете воспользоваться конкретным преимуществом из них, например, используя схему дельта-кодирования (где каждая точка, кроме первой, может быть закодирована как дельта из последнего пункта).

15
ответ дан 28 November 2019 в 23:21
поделиться

Окружность Земли составляет прибл. 40 000 км или 24900 миль.

Вам нужна точность в один метр (3 фута), чтобы иметь возможность превосходить точность GPS на порядок.

Следовательно, вам нужна точность для хранения 40 000 000 различных значений. Это минимум 26 бит информации. Подойдет 32-битное число с плавающей запятой или int.

10
ответ дан 28 November 2019 в 23:21
поделиться

Поплавков было бы более чем достаточно для хранения координат GPS, даже если бы устройства GPS потребительского уровня имели точность, близкую к заявленной для них. . Если вы не верите, что это правда, попробуйте эти два простых эксперимента:

  1. Вынесите два или более GPS-устройства в одно место где-нибудь на поле и запишите координаты, измеренные каждым устройством. Вернитесь внутрь и нанесите точки с каждого устройства на карту (я думаю, что у Google есть что-то, что сделает это за вас). Вы удивитесь, насколько далеко друг от друга расположены точки (даже если они Предполагается, что все они измеряют одно и то же место).
  2. Возьмите ваше (предположительно) самое точное устройство и поместите его где-нибудь, где он сможет найти спутник, но не попадет на него дождь, и запишите серию выполненных измерений через пару дней. Постройте все показания (как в №1). Опять же, вы будете удивлены тем, как точки (которые должны быть одинаковыми или почти одинаковыми) перемещаются по всей карте, иногда на несколько сотен футов.

Я писал приложения для GPS -подключенные КПК в течение многих лет, и я проверял это на сомнительных покупателях снова и снова (я даже выигрывал пари таким образом). Существуют более качественные устройства GPS, которые обеспечивают лучшую точность, чем эта, но лучшая точность достигается с более дорогими наборами микросхем, и устройства остаются на одном месте в течение нескольких дней или даже недель, с усреднением показаний по времени.

Четырехбайтовое число с плавающей запятой намного точнее, чем сами устройства . Конечно, вам совсем не повредит использовать вместо него двойной, если множитель 2Х для вас не проблема.

5
ответ дан 28 November 2019 в 23:21
поделиться

23 бита точности на 179 градусах долготы дают точность менее 10 метров, что является лучшим показателем, который дают обычные устройства GPS. На экваторе:

% gps distance "0.0, 179.0" "0.0, $((179 * (1 + 2**-23)))"
From 0.0, 179.0 to 0.0, 179.00002133846283 is 7.79 feet E
From 0.0, 179.0 to 0.0, 179.00002133846283 is 2.38 meters E

Таким образом, число с плавающей запятой одинарной точности IEEE 754, известное вашему компилятору C как float , будет как раз подходящим для представления. Остерегайтесь использования чисел с плавающей запятой для расширенных вычислений! Ошибка округления может съесть ваш обед. Проконсультируйтесь с численным аналитиком.

2
ответ дан 28 November 2019 в 23:21
поделиться

РЕДАКТИРОВАТЬ: добавил несколько пунктов из комментариев, 32-битные значения должны обеспечивать достаточную точность.

Я бы использовал 32-битное представление с фиксированной точкой. Если значения:

42.915512 , -99.521654 , я бы сохранил значения * 100000 в int32_t (они могут быть отрицательным).

int32_t lat = 42915512;
int32_t lon = -99521654;

Это хороший компромисс между простым и точным ( 5 десятичных знаков обычно достаточно, вы всегда можете увеличить его до 1000000 , чтобы получить 6 , если необходимо).

Чтобы отобразить пользователю, выполните то, что предлагает caf :

... чтобы отобразить пользователю - используйте целое число разделить и по модулю, например printf ("Lat = % d.% 06d \ n ", lat / 1000000, abs (lat)% 1000000)

Их также можно будет эффективно сравнивать / сортировать, так как относительный порядок будет сохранен.

РЕДАКТИРОВАТЬ: Дополнительным преимуществом является то, что его можно отправлять по сети или сохранять на диск в двоичном формате. форматировать переносимым способом.

9
ответ дан 28 November 2019 в 23:21
поделиться

Я удивлен, что никто не опубликовал тот факт, что долгота / широта - ужасный способ хранения данных на сфере (кто-то упомянул, что долгота требует меньшей точности вблизи полюсов).

В основном вы можете сохранять данные о координатах X и Y в метрах. Представьте себе куб вокруг Земли, который точно соответствует (ха-ха, хорошо почти ему подходит). Вам нужно сохранить только координаты X и Y, а не все 3 координаты, потому что 3-я координата может быть получена из редиуса Земли, r = квадратный корень [x ^ 2 + y ^ 2 + z ^ 2] .

Итак, преобразуйте широту / долготу в x / y в метрах. Вам понадобится всего 12756200 м на координату (это диаметры земли). Таким образом, ваше общее значение должно быть только от 0 до 25 512 400 (кто-то еще заявил 40 000 000, потому что они использовали долгую / широту), чтобы быть точным с точностью до +/- 0,5 м.

Это даст всего 25 бит на позицию. На вашем месте я бы просто сделал точность в пределах 2 м и использовал 24 бита на позицию, так как это аккуратные 3 байта.

Также, если вы сохраняете информацию о путевых точках на пути, вы можете сохранять каждую путевую точку как смещение от последней путевой точки. Как начать с 24-битной координаты x / y. И затем есть 16-битное «обновление», которое регулирует положение, добавляя / вычитая метры x / y. 16-битный позволит обновить маршрутную точку на расстоянии более 400 метров. Так что, если вы знаете, что устройство не предназначено для самолетов и периодических обновлений, это тоже может быть приемлемо.

Как начать с 24-битной координаты x / y. А затем есть 16-битное «обновление», которое регулирует положение, добавляя / вычитая значения x / y. 16-битный позволит обновить маршрутную точку на расстоянии более 400 метров. Так что, если вы знаете, что устройство не предназначено для самолетов и периодических обновлений, это тоже может быть приемлемо.

Как начать с 24-битной координаты x / y. И затем есть 16-битное «обновление», которое регулирует положение, добавляя / вычитая метры x / y. 16-битный позволит обновить маршрутную точку на расстоянии более 400 метров. Так что, если вы знаете, что устройство не предназначено для самолетов и периодических обновлений, это тоже может быть приемлемо.

0
ответ дан 28 November 2019 в 23:21
поделиться

Вы можете упаковать значения широты и долготы в одно одно 32-битное целое число с разрешением худшее ~ 2,4 метра / пиксель (на экваторе), если вы используете рекурсивную систему листов. Используя два бита на уровень, вы можете сохранить 16 уровней в 32 бита. Вы можете получить представление о том, как это будет работать, просмотрев эту статью о тайловой системе виртуальной Земли . Здесь используется Меркатор, поэтому для полюсов возникнут проблемы. Вместо этого вы можете использовать другую проекцию и по-прежнему получать очень похожие результаты.

Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).

4 метра / пиксель (на экваторе), если вы используете рекурсивную систему листов. Используя два бита на уровень, вы можете сохранить 16 уровней в 32 бита. Вы можете получить представление о том, как это будет работать, просмотрев эту статью о тайловой системе виртуальной Земли . Здесь используется Меркатор, поэтому для полюсов возникнут проблемы. Вместо этого вы можете использовать другую проекцию и по-прежнему получать очень похожие результаты.

Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).

4 метра / пиксель (на экваторе), если вы используете рекурсивную систему листов. Используя два бита на уровень, вы можете сохранить 16 уровней в 32 бита. Вы можете получить представление о том, как это будет работать, просмотрев эту статью о тайловой системе виртуальной Земли . Здесь используется Меркатор, поэтому для полюсов возникнут проблемы. Вместо этого вы можете использовать другую проекцию и по-прежнему получать очень похожие результаты.

Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).

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

Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).

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

Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).

1
ответ дан 28 November 2019 в 23:21
поделиться

В формате карты Garmin IMG они хранят координаты внутри ограничивающих рамок, используя числа с плавающей запятой для установки краев прямоугольников. Координаты внутри полей определяются с использованием переменного числа битов, которые просто линейны между минимальным и максимальным значениями в зависимости от необходимой точности.

Например: minlat = 49.0, maxlat = 50.0, minlon = 122.0, maxlon = 123,0, количество бит = 16

Таким образом, значение:
32768 32768 будет преобразовано в 49,5, 122,5
16384,0 будет 49,25, 122,0

Если вам нужна меньшая точность, тот же результат может быть сгенерирован с количеством бит = 4
8,8 будет преобразовано в 49,5, 122,5
4,0 будет 49,25, 122,0

2
ответ дан 28 November 2019 в 23:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: