Форум русскоязычного сообщества Ubuntu


Увидели сообщение с непонятной ссылкой, спам, непристойность или оскорбление?
Воспользуйтесь ссылкой «Сообщить модератору» рядом с сообщением!

Автор Тема: Конвертирование минут и секунд в доли градуса, оптимизация решения  (Прочитано 2085 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн ArcFi

  • Автор темы
  • Старожил
  • *
  • Сообщений: 15189
    • Просмотр профиля
    • aetera.net
Требуется отконвертировать минуты и секунды в доли градуса:
65°54'15.6" > 65.9043333

Вот, сообразил на bash+awk:
Код: (bash) [Выделить]
D=$(awk --field-separator='\x22|\x27|\xc2\xb0' '{print $1}' <<< "$DMS")
M=$(awk --field-separator='\x22|\x27|\xc2\xb0' '{print $2}' <<< "$DMS")
S=$(awk --field-separator='\x22|\x27|\xc2\xb0' '{print $3}' <<< "$DMS")
DEG=$(bc <<< "scale=8;$D+$M/60+$S/3600")

Но скорость обработки меня не очень устраивает, т.к. в реале координат довольно много.
С другой стороны, не хочется далеко отходить от bash, awk, sed, perl, т.к. нужна гибкость.
Существуют ли пути оптимизации?
« Последнее редактирование: 09 Ноября 2012, 23:24:29 от arcfi »

Axa-Ru

  • Гость
« Последнее редактирование: 10 Ноября 2012, 00:14:50 от Axa-Ru »

Оффлайн SergeyIT

  • Зануда.
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 5743
  • Все по палатам!
    • Просмотр профиля
Самое быстрое на Си  :coolsmiley:
Извините, я все еще учусь

Оффлайн ArcFi

  • Автор темы
  • Старожил
  • *
  • Сообщений: 15189
    • Просмотр профиля
    • aetera.net
Вообще, исходная задача — написать XLS2KML-конвертер.
XLS парсить не очень удобно, поэтому задачу можно привести к виду CSV2KML.
Тем более, что XLS делается хз-кем и хз-как, не исключено, что вообще руками набивается.
Короче-говоря, можно считать, что набор входных данных формализован весьма относительно.
Так что есть вероятность необходимости внесения правок в скрипт для каждого входного файла.
Поэтому предпочтение отдаётся интерпретируемым языкам.

Пока получается так:
Код: (bash) [Выделить]
#!/bin/bash

# Coded by: ArcFi <arcfi[dot]x[at]gmail[dot]com>
# License: GNU General Public License (GPL) version 3+

dms2dd() {
DMS="$*"
DEG=$(awk --field-separator='[^0-9.]*' '{print $1}' <<< "$DMS")
MIN=$(awk --field-separator='[^0-9.]*' '{print $2}' <<< "$DMS")
SEC=$(awk --field-separator='[^0-9.]*' '{print $3}' <<< "$DMS")
DD=$(bc <<< "scale=8;$DEG+$MIN/60+$SEC/3600")
echo "$DD"
}

FILE_NAME="${1:?}"
CSV_SEP="${2:-|}"

exec >"${FILE_NAME%%.csv}.kml"

echo -e '<?xml version="1.0" encoding="UTF-8"?>\n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>'
sed 's/\x0d$//' "$FILE_NAME" | while read LINE
do
LABEL_NAME=$(awk --field-separator="$CSV_SEP" '{print $1}' <<< "$LINE")
LATITUDE_DMS=$(awk --field-separator="$CSV_SEP" '{print $2}' <<< "$LINE")
LONGTITUDE_DMS=$(awk --field-separator="$CSV_SEP" '{print $3}' <<< "$LINE")
LATITUDE=$(dms2dd "$LATITUDE_DMS")
LONGTITUDE=$(dms2dd "$LONGTITUDE_DMS")
ALTITUDE="0"
echo -e "<Placemark>\n\t<name>$LABEL_NAME</name>\n\t<Point>\n\t\t<coordinates>$LONGTITUDE,$LATITUDE,$ALTITUDE</coordinates>\n\t</Point>\n</Placemark>"
done
echo -e '</Document>\n</kml>'

exit 0

Код: (csv) [Выделить]
951|65°36'38.1"|33°12'04.0"
952|65°37'04.2"|33°11'23.1"
мост 952+665м|65°37'22.2"|33°10'50.4"
953|65°37'31.3"|33°10'35.8"
954|65°38'03.2"|33°10'17.8"
...

Код: (xml) [Выделить]
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Placemark>
<name>951</name>
<Point>
<coordinates>33.20111111,65.61058333,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>952</name>
<Point>
<coordinates>33.18974999,65.61783332,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>мост 952+665м</name>
<Point>
<coordinates>33.18066666,65.62283332,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>953</name>
<Point>
<coordinates>33.17661110,65.62536110,0</coordinates>
</Point>
</Placemark>
...
</Document>
</kml>

***
Axa-Ru, за ссылки спасибо, куда копать, понял.

***
Заменил 3 вызова awk на 1 sed:
Код: (bash) [Выделить]
dms2dd() {
read DEG MIN SEC <<< $(sed 's/[^0-9\.]\{1,\}/ /g' <<< "$*")
echo $(bc <<< "scale=8;$DEG+$MIN/60+$SEC/3600")
}

***
Вовсе избавился от awk:
Код: (bash) [Выделить]
IFS="$CSV_SEP" read LABEL_NAME LATITUDE_DMS LONGTITUDE_DMS <<< "$LINE"
***
Можно считать, что решено.

Такой вариант меня устраивает:
Код: (bash) [Выделить]
#!/bin/bash

# Coded by: ArcFi <arcfi[dot]x[at]gmail[dot]com>
# License: GNU General Public License (GPL) version 3+

# CSV2KML-converter

# Degrees, Minutes, Seconds to Decimal Degrees
dms2dd() {
read DEG MIN SEC <<< $(sed 's/[^0-9\.]\{1,\}/ /g' <<< "$*")
echo $(bc <<< "scale=8;$DEG+$MIN/60+$SEC/3600")
}

FILE_NAME="${1:?}"
CSV_SEP="${2:-|}"

exec >"${FILE_NAME%%.csv}.kml"

echo -e '<?xml version="1.0" encoding="UTF-8"?>\n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>'
sed 's/\x0d$//' "$FILE_NAME" | while read LINE
do
IFS="$CSV_SEP" read LABEL_NAME LATITUDE_DMS LONGTITUDE_DMS <<< "$LINE"
LATITUDE=$(dms2dd "$LATITUDE_DMS")
LONGTITUDE=$(dms2dd "$LONGTITUDE_DMS")
ALTITUDE="0"
echo -e "<Placemark>\n\t<name>$LABEL_NAME</name>\n\t<Point>\n\t\t<coordinates>$LONGTITUDE,$LATITUDE,$ALTITUDE</coordinates>\n\t</Point>\n</Placemark>"
done
echo -e '</Document>\n</kml>'

exit 0
« Последнее редактирование: 10 Ноября 2012, 22:05:13 от arcfi »

 

Страница сгенерирована за 0.018 секунд. Запросов: 22.