Благодарю за пояснение! Понимаю, что всегда бывают недочеты, приятно, что при их наличии SAS.Планета разрослась в такой полезный и многофункциональный инструмент! Жалко, только, что для реализации различных ярлыков на карте нельзя использовать KMZ-файлы, в силу не полной поддержи их средствами SAS.Планета. Из-за этого пришлось изобретать велосипед, хотя можно было проще реализовывать задачу средствами стороннего ПО.zed писал(а):Это было очень неудачное решение на заре развития программы. Писать её начинали студенты-программисты, поэтому вот такое наследие: и мусорные 4 байта и монструозный Extended.
lonlatarr="ADDdJAaB...b8EQAAwX" ...
-
Banzay
- Новичок
- Сообщения: 2
- Зарегистрирован: 02 апр 2015, 00:21
- Откуда: РФ, Саратов
- Благодарил (а): 1 раз
- Контактная информация:
Re: lonlatarr="ADDdJAaB...b8EQAAwX" ...
- Cheetos
- Новичок
- Сообщения: 11
- Зарегистрирован: 30 мар 2015, 20:03
- Откуда: РФ, Тула
- Благодарил (а): 2 раза
Не прошло и года... вроде как удалось победить lonlatarr
1. В uses добавляем EDBase64
2. Объявляем следующие типы:
3. Юзаем функцию LonLatArr, где в качестве параметра передаем координаты точки в градусах:
2. Объявляем следующие типы:
Код: Выделить всё
type
TExtendedPoint = packed record
X: Extended;
Y: Extended;
Reserved: LongWord;
end;
type
TDoublePoint = record
X: Double;
Y: Double;
end;Код: Выделить всё
function LonLatArr(DP: TDoublePoint): String;
var
AStream: TMemoryStream;
S: AnsiString;
ExtPoint: TExtendedPoint;
begin
try
AStream:=TMemoryStream.Create;
ExtPoint.X := DP.X;
ExtPoint.Y := DP.Y;
ExtPoint.Reserved:=0;
AStream.Write(ExtPoint, SizeOf(ExtPoint));
AStream.Position:=0;
SetString(S, PAnsiChar(AStream.Memory), AStream.Size);
Result:=Base64Encode(S);
finally
AStream.Free;
end;
end;
Последний раз редактировалось Cheetos 03 апр 2015, 20:21, всего редактировалось 1 раз.
- Cheetos
- Новичок
- Сообщения: 11
- Зарегистрирован: 30 мар 2015, 20:03
- Откуда: РФ, Тула
- Благодарил (а): 2 раза
Re: lonlatarr="ADDdJAaB...b8EQAAwX" ...
to zed:
1. Выражаю огромную благодарность за оказанную помощь.
2. В отношении директивы {$A4} для решения конкретной задачи - она не обязательна - packed record ее игнорирует.
1. Выражаю огромную благодарность за оказанную помощь.
2. В отношении директивы {$A4} для решения конкретной задачи - она не обязательна - packed record ее игнорирует.
- Cheetos
- Новичок
- Сообщения: 11
- Зарегистрирован: 30 мар 2015, 20:03
- Откуда: РФ, Тула
- Благодарил (а): 2 раза
Re: lonlatarr="ADDdJAaB...b8EQAAwX" ...
МожноBanzay писал(а):Благодарю за пояснение! Понимаю, что всегда бывают недочеты, приятно, что при их наличии SAS.Планета разрослась в такой полезный и многофункциональный инструмент! Жалко, только, что для реализации различных ярлыков на карте нельзя использовать KMZ-файлы, в силу не полной поддержи их средствами SAS.Планета. Из-за этого пришлось изобретать велосипед, хотя можно было проще реализовывать задачу средствами стороннего ПО.zed писал(а):Это было очень неудачное решение на заре развития программы. Писать её начинали студенты-программисты, поэтому вот такое наследие: и мусорные 4 байта и монструозный Extended.
-
zed
- Гуру
- Сообщения: 2888
- Зарегистрирован: 16 авг 2008, 20:21
- Благодарил (а): 89 раз
- Поблагодарили: 568 раз
Re: lonlatarr="ADDdJAaB...b8EQAAwX" ...
Ну так присылайте пул-реквесты, глядишь и поддержка появитсяBanzay писал(а):нельзя использовать KMZ-файлы, в силу не полной поддержи их средствами SAS.Планета
По-моему, можно проще:Cheetos писал(а):3. Юзаем функцию LonLatArr
Код: Выделить всё
function LonLatArr(DP: TDoublePoint): String;
var
ExtPoint: TExtendedPoint;
begin
ExtPoint.X := DP.X;
ExtPoint.Y := DP.Y;
ExtPoint.Reserved := 0;
Result := Base64Encode(PAnsiChar(@ExtPoint), SizeOf(ExtPoint));
end;- Cheetos
- Новичок
- Сообщения: 11
- Зарегистрирован: 30 мар 2015, 20:03
- Откуда: РФ, Тула
- Благодарил (а): 2 раза
Re: lonlatarr="ADDdJAaB...b8EQAAwX" ...
Совершенству нет пределаzed писал(а): По-моему, можно проще:Код: Выделить всё
function LonLatArr(DP: TDoublePoint): String; var ExtPoint: TExtendedPoint; begin ExtPoint.X := DP.X; ExtPoint.Y := DP.Y; ExtPoint.Reserved := 0; Result := Base64Encode(PAnsiChar(@ExtPoint), SizeOf(ExtPoint)); end;
В рамках поставленной задачи (получение строки LonLatArr из координат точки) этого более чем достаточноzed писал(а): Но это если всего одна точка. А вообще, имейте в виду, что SAS умеет оперировать мультиполигонами и полилиниями (особенно это стоит учитывать при чтении lonlatarr, а то могут быть сюрпризы).
- OverPaw
- Новичок
- Сообщения: 24
- Зарегистрирован: 12 янв 2013, 13:14
- Откуда: Киев
- Благодарил (а): 14 раз
- Поблагодарили: 3 раза
- Контактная информация:
Re: lonlatarr="ADDdJAaB...b8EQAAwX" ...
Cheetos, zed, спасибо за алгоритм, но непосредственно сам ваш код в FreePascal у меня не заработал.
Пришлось немного допилить - взять что-то от каждого и адаптировать к встроенной библиотеке Base64.
Привожу рабочий вариант для FreePascal 3.0.4 с примером конвертации координат.
Пришлось немного допилить - взять что-то от каждого и адаптировать к встроенной библиотеке Base64.
Привожу рабочий вариант для FreePascal 3.0.4 с примером конвертации координат.
Код: Выделить всё
uses Base64;
type
TExtendedPoint = packed record
X: Extended;
Y: Extended;
Reserved: LongWord;
end;
type
TDoublePoint = record
X: Double;
Y: Double;
end;
function LonLatArr(DP: TDoublePoint): String;
var
S: AnsiString;
ExtPoint: TExtendedPoint;
begin
ExtPoint.X := DP.X;
ExtPoint.Y := DP.Y;
ExtPoint.Reserved:=0;
SetString(S, PAnsiChar(@ExtPoint), SizeOf(ExtPoint));
LonLatArr := EncodeStringBase64(S);
end;
var
lonlat: TDoublePoint;
begin
lonlat.X := 47.817875;
lonlat.Y := 52.022758;
writeln(LonLatArr(lonlat));
readln();
end.-
stepanxxx
- Новичок
- Сообщения: 15
- Зарегистрирован: 19 фев 2014, 11:48
- Благодарил (а): 3 раза
- Поблагодарили: 1 раз
Re: lonlatarr="ADDdJAaB...b8EQAAwX" ...
Уже несколько дней пытаюсь самостоятельно конвертировать SML в KML на Python для автоматизации одного из процессов. Данные хранятся в SML, и основная загвоздка — в массиве lonlatarr. Изучил тему вдоль и поперек, но пока безуспешно.
Может, кто-то сталкивался с подобным и знает, как корректно извлечь координаты из lonlatarr? Буду благодарен за любые идеи!
Может, кто-то сталкивался с подобным и знает, как корректно извлечь координаты из lonlatarr? Буду благодарен за любые идеи!
-
mate
- Новичок
- Сообщения: 48
- Зарегистрирован: 14 июн 2018, 11:52
- Благодарил (а): 1 раз
- Поблагодарили: 19 раз
Re: lonlatarr="ADDdJAaB...b8EQAAwX" ...
Из python вам будет гораздо проще работать с метками в sqlite3 формате, т.к. там данные хранятся в WKB формате. В python есть готовая либа для него: https://github.com/thehappycheese/parse_wkb
Что касается SML, то в python вам придётся напрячься, для преобразования 80-битного float в нормальный 64-битный double.
Что касается SML, то в python вам придётся напрячься, для преобразования 80-битного float в нормальный 64-битный double.
-
mate
- Новичок
- Сообщения: 48
- Зарегистрирован: 14 июн 2018, 11:52
- Благодарил (а): 1 раз
- Поблагодарили: 19 раз
Re: lonlatarr="ADDdJAaB...b8EQAAwX" ...
Хотя, нейронки вот что-то похожее на правду пишут (не проверял). По крайней мере, есть от чего исходить:
Copilot:
ChatGPT:
Чтобы преобразовать 80-битное представление с плавающей точкой (например, формат `long double` в C) в 64-битное представление (`double`) в Python без использования сторонних библиотек, можно вручную извлечь компоненты числа (знак, экспоненту и мантиссу) из 80-битного формата и затем подогнать их под 64-битный формат. В 64-битном формате мантисса имеет меньше бит, а экспонента должна быть приведена к другому диапазону.
Вот шаги, которые вам нужно выполнить:
1. Прочитайте 80-битное число, представленное в виде 10 байт.
2. Извлеките следующие компоненты:
- Знак (1 бит).
- Экспонента (15 бит).
- Мантисса (64 бита).
3. Преобразуйте эти компоненты в 64-битный формат, изменив экспоненту и мантиссу, чтобы соответствовать стандарту IEEE 754 для 64-битных чисел.
4. Получите итоговое 64-битное число.
Пример кода для конверсии из 80-битного формата в 64-битный:
Этот код:
1. Преобразует 80-битный формат (который представлен 10 байтами) в структуру с плавающей точкой 64-бит.
2. Выполняет преобразование с учетом мантиссы и экспоненты в стандарт IEEE 754.
Пожалуйста, учитывайте, что в реальных приложениях точность может быть потеряна при таком преобразовании, поскольку 64 бита имеют меньшую точность и диапазон, чем 80 бит.
Copilot:
Код: Выделить всё
import math
# Пример 80-битного числа (в виде строки байтов)
float80_bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
def convert_80bit_to_double(float80_bytes):
# Разбор 80-битного числа на составляющие
sign = (float80_bytes[9] & 0x80) >> 7
exponent = ((float80_bytes[9] & 0x7F) << 8) | float80_bytes[8]
mantissa = float80_bytes[:8] # 64-битная мантисса
# Преобразование мантиссы в дробное число
mantissa_value = int.from_bytes(mantissa, byteorder='little') / (2**64)
# Вычисление 64-битного числа
value = ((-1) ** sign) * (2 ** (exponent - 16383)) * mantissa_value
return value
# Преобразование и вывод результата
float64 = convert_80bit_to_double(float80_bytes)
print(float64)
Чтобы преобразовать 80-битное представление с плавающей точкой (например, формат `long double` в C) в 64-битное представление (`double`) в Python без использования сторонних библиотек, можно вручную извлечь компоненты числа (знак, экспоненту и мантиссу) из 80-битного формата и затем подогнать их под 64-битный формат. В 64-битном формате мантисса имеет меньше бит, а экспонента должна быть приведена к другому диапазону.
Вот шаги, которые вам нужно выполнить:
1. Прочитайте 80-битное число, представленное в виде 10 байт.
2. Извлеките следующие компоненты:
- Знак (1 бит).
- Экспонента (15 бит).
- Мантисса (64 бита).
3. Преобразуйте эти компоненты в 64-битный формат, изменив экспоненту и мантиссу, чтобы соответствовать стандарту IEEE 754 для 64-битных чисел.
4. Получите итоговое 64-битное число.
Пример кода для конверсии из 80-битного формата в 64-битный:
Код: Выделить всё
def float80_to_double(bytes_80):
# Проверяем, что вход — это 10 байт (80 бит)
if len(bytes_80) != 10:
raise ValueError("Input must be 10 bytes long for 80-bit float")
# Разбираем 10 байт на компоненты 80-битного числа:
sign = (bytes_80[9] >> 7) & 0x01 # 1 бит
exponent = ((bytes_80[9] & 0x7F) << 8) | bytes_80[8] # 15 бит
mantissa = (bytes_80[7] << 56) | (bytes_80[6] << 48) | (bytes_80[5] << 40) | \
(bytes_80[4] << 32) | (bytes_80[3] << 24) | (bytes_80[2] << 16) | \
(bytes_80[1] << 8) | bytes_80[0] # 64 бита
# Смещаем экспоненту для 64-битного формата (например, с 15 бит на 11 бит)
# Стандарт IEEE 754 для 64-битных чисел: экспонента имеет смещение 1023
exponent_64 = exponent - 16383 + 1023
# Обрабатываем выходные данные:
# Если экспонента выходит за пределы 64-битного диапазона, например, слишком мала или велика
if exponent_64 <= 0:
return 0.0 # Нормализованный выходной результат
if exponent_64 >= 0x7FF:
return float('inf') if sign == 0 else float('-inf')
# Преобразуем мантиссу и экспоненту в 64-битный формат
mantissa_64 = mantissa >> 11 # Оставляем только верхние 52 бита мантиссы
result = (sign << 63) | (exponent_64 << 52) | mantissa_64
# Преобразуем в число
return struct.unpack('d', struct.pack('Q', result))[0]
import struct
# Пример 80-битного числа (10 байт)
bytes_80 = bytearray([0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
# Преобразуем в 64-битное число
double_value = float80_to_double(bytes_80)
print(double_value)
1. Преобразует 80-битный формат (который представлен 10 байтами) в структуру с плавающей точкой 64-бит.
2. Выполняет преобразование с учетом мантиссы и экспоненты в стандарт IEEE 754.
Пожалуйста, учитывайте, что в реальных приложениях точность может быть потеряна при таком преобразовании, поскольку 64 бита имеют меньшую точность и диапазон, чем 80 бит.