Перевод qrst - 0123 - Z,X,Y


Введение

Подробное разъяснение алгоритма перевода GIS карт из формата qrst (0123) в формат масштаб, координата X, координата Y.

В последнее время в интернете появилось много карт:
maps.google.com,
maps.yandex.ru,
OpenStreetMap.org...
И много ещё других. Причём в каждой из систем есть виды карт (со спутника, схематическая, для велосипедистов, гибридная, народная и т.д.). Да ещё и спутниковые снимки бывают сделаны в разное время (зиой, летом, пару лет спустя). Бывает, возникает необходимость совмещения разных типов карт. Я, например, легче всего воспринимаю карту со спутника с наложенной на неё картой высот. Проблема заключается в том, что тайлы карт (составные кусочки) в разных системах называются по-разному. Нельзя сказать какая система лучше, а какая хуже. Просто они разные. Это как, для сравнения, европейцы едят вилками, а китайцы палочками. И нельзя сказать как лучше. И так и так можно есть. Просто по-другому.

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

Разъяснение на простых примерах

Чтобы не путаться - qrst = 0123:

q = 0
r = 1
s = 2
t = 3

q
0
0,0
r
1
1,0
s
2
0,1
t
3
1,1
Как видите вся Земля разделена на 4 части по экватору и нулевому меридиану. Порядок их счёта слева направо и сверху вниз: северо-запад, северо-восток, юго-запад, юго-восток. Рассмотрим один участок Земли в разных системах координат. Это Евразия - северное полушарие, восточная часть. По кодировке qrst - 1 (или r), а по кодировке X,Y - 1/1/0 (масштаб 1, x = 1, y = 0).

Регионqrst0123zoomXY
Северная Америкаq0100
Евразияr1110
Южная Америкаs2101
Африка, Австралияt3111

А вот как этот участок прописан в разных системах координат. В одной - a1.jpeg, а в другой - 1/1/0.png:

http://ecn.t2.tiles.virtualearth.net/tiles/a1.jpeg?g=1
http://b.tile.thunderforest.com/cycle/1/1/0.png
 qrst  x   y        qrst  x   y
   0 = 0 / 0          0 = 0,  0
   1 = 1 / 0          1 = 1,  0
   2 = 0 / 1          2 = 0,  1
   3 = 1 / 1          3 = 1,  1
   
 qrst = y*2 + x

Очень напоминает двоичную систему счисления.

      Система счисления      Координаты
Десятиричная    Двоичная        Y  X
     0             00           0  0
     1             01           0  1
     2             10           1  0
     3             11           1  1

А теперь нам надо приблизиться. Увеличить масштаб в 2 раза. К примеру, приблизиться к Чёрному морю. Если карту Евразии так же разделить на 4 части и каждую из них пронумеровать q, r, s, t (или 0, 1, 2, 3), то нас интересует участок с буквой s (он же с цифрой 2). Первый символ r (1), останется. Тогда получится номер участка rs (12). Какими же будут координаты в системе XY? Масштаб - 2. Предыдущее значение по X увеличиваем в 2 раза и прибавляем 0, так как по X не смещаемся, то есть получим 2. А Y был равен 0, умножение на 2 оставит ноль нолём, но мы смещаемся на нижний квадрат, следовательно, добавляем 1. Результат - Y = 1. Получаем 2/2/1.
Вот как это выглядит в трёх системах кодирования:

qrst
qqqrrqrr
qsqtrsrt
sqsrtqtr
sssttstt

0123
00011011
02031213
20213031
22233233

2/X/Y
0/01/02/03/0
0/11/12/13/1
0/21/22/23/2
0/31/32/33/3



http://ecn.t2.tiles.virtualearth.net/tiles/a12.jpeg?g=1
http://b.tile.thunderforest.com/cycle/2/2/1.png
 qrst     x      y
   10 = 2 + 0, 0 + 0 
   11 = 2 + 1, 0 + 0
   12 = 2 + 0, 0 + 1
   13 = 2 + 1, 0 + 1

Теперь же, если продолжить деление на четверти, Чёрное море будет находиться в левой верхней четверти, то есть q, 0 или по ХY 0,0. Следовательно её адрес будет rsq, 120 или 3/4/2:


120 = 4, 2
Теперь будем увеличивать и брать правый нижний квадрат t, 3, 1/1.


1203 = (4*2+1), (2*2+1) = 9, 5

Пятый уровень:

12033 = (9*2+1), (5*2+1) = 19, 11

Шестой уровень:

http://ecn.t2.tiles.virtualearth.net/tiles/a120333.jpeg?g=1
http://b.tile.thunderforest.com/cycle/6/39/23.png

qrst = 120333
   x = 100111 = 32 + 4 + 2 + 1 = 39
   y = 010111 = 16 + 4 + 2 + 1 = 23
Как видите, легко прослеживается закономерность. Если всё поняли, то попробуйте самостоятельно приблизиться к городу Сочи. (Для проверки: ссылка на морпорт города Сочи 17-го уровня в кодировке 0123)

Вычисление

Нужно разложить код qrst поразрядно на два двоичных числа x и y по следующему правилу:

qrst = 0 1 2 3
   x = 0 1 0 1
   y = 0 0 1 1
Если разряд qrst нечётный - х будет равен 1, иначе 0.
Если разряд qrst больше или равен 2, то y будет равен 1, иначе 0.
Потом полученные двоичные числа нужно перевести в десятичные, не забыв при этом указать уровень масштаба.

Возьмём произвольный участок 17-го уровня:

qrst = 12131321201220221   (17) 
   x = 10111101001000001 = 96833
   y = 01010110100110110 = 44342
http://ecn.t2.tiles.virtualearth.net/tiles/a12131321201220221.jpeg?g=1 http://b.tile.thunderforest.com/cycle/17/96833/44342.png


Программирование

А теперь реализуем это в скрипте. Создадим функции для перевода из qrst в XY и обратно, а так же добавим функцию добавления к qrst смещения по X и Y.

#!/usr/bin/perl

$q="12131321201220221";
($l,$x,$y)=QRST2XY($q);
print "$q = $l/$x/$y\n";

$x++;
$q2=XY2QRST($l,$x,$y);
print "$l, $x, $y = $q2\n";

$dx=0;
$dy=1;
$newXY=ShiftQRST($q,$dx,$dy);
print "$q + $dx + $dy ===> $newXY\n"; 

#######################################

sub QRST2XY {
  # print QRST2XY("12131321201220221");
  # (17,96833,44342)
  my $qrst=shift;
  my @X=(0,1,0,1);
  my @Y=(0,0,1,1);
  my $z=$qrst;
  my $x=0;
  my $y=0;
  my $l=0;
  for $n(0..(length $qrst)-1){
    $z=~s/(.)$//;
    my $w=$1;
    $x+=$X[$w]*2**$n;
    $y+=$Y[$w]*2**$n;
    $l++;
  }
  return ($l,$x,$y);
}

sub XY2QRST {
  # print XY2QRST(17,96833,44342);
  # 12131321201220221
  my ($l, $x, $y)=@_;
  my $format="\%0${l}b";
  my $bx=sprintf($format,$x);
  my $by=sprintf($format,$y);
  my ($z,$wx,$wy);
  for $n(1..$l){
    $bx=~s/(.)$//;
    $wx=$1;
    $by=~s/(.)$//;
    $wy=$1;
    $z=($wx+$wy*2).$z;
  }
  return $z;
}

sub ShiftQRST{
  my ($qrst,$dx,$dy)=@_;
  my ($l,$x,$y)=QRST2XY($qrst);
  $x+=$dx;
  $y+=$dy;
  return XY2QRST($l,$x,$y);
}

Примечание: если qrst код картинки будет не цифровой 12131321201220221, а буквенный rsrtrtsrsqrssqssr, то перевести его в цифры можно одной командой:

tr/qrst/0123/;

Пример использования

Пример карт в разных форматах с регулируемой прозрачностью между ними.
Проведите мышкой над градиентом.




Автор: Андрей Илларионов
illari.ru
ноябрь 2014 г.