UTFGrid: растровые тайлы с атрибутикой: различия между версиями

Материал из GIS-Lab
Перейти к навигации Перейти к поиску
Нет описания правки
 
(не показано 17 промежуточных версий 3 участников)
Строка 1: Строка 1:
{{Статья|Черновик}}
{{Статья|Опубликована|utfgrid}}
{{Аннотация|Приведено описание стандарта UTFGrid и рассмотрен пример его использования.}}


== Введение ==
== Введение ==


Основное назначение любого картографического web-приложения - это предоставление клиенту пространственной информации, включающей геометрическую и атрибутивную составляющие. Поэтому, в любом случае, на начальном этапе каждый разработчик должен ответить на вопрос: "Какой формат передачи данных следует использовать в конкретном случае?" Как известно, все форматы передачи пространственной информации можно разделить на векторные и растровые. Использование векторных форматов (KML, GML, GeoJSON и т.д.) с одной стороны очень удобно: в клиентском приложении сразу становятся доступными и геометрическая, и атрибутивная составляющие, что обеспечивает простоту добавления приложению интерактивности. С другой же - область применения векторных форматов довольно ограничена и определяется главным образом объёмом передаваемых данных. Например, если векторный слой содержит несколько миллионов объектов, то во-первых, клиенту придется ждать пока эти данные будут загружены браузером, а во-вторых пока они будут отрисованы. При этом попытка изменения масштабного уровня вновь потребует перерисовки объектов, что также может занять продолжительное время. Естественно, что ни о каком комфорте при работе с таким приложением
Основное назначение любого картографического web-приложения - это предоставление клиенту пространственной информации, включающей геометрическую и атрибутивную составляющие. Поэтому, в любом случае, на начальном этапе каждый разработчик должен ответить на вопрос: "Какой формат передачи данных следует использовать в конкретном случае?" Как известно, все форматы передачи пространственной информации можно разделить на векторные и растровые. Использование векторных форматов (KML, GML, GeoJSON и т.д.) с одной стороны очень удобно: в клиентском приложении сразу становятся доступными и геометрическая, и атрибутивная составляющие, что обеспечивает простоту добавления приложению интерактивности. С другой же - область применения векторных форматов довольно ограничена и определяется главным образом объёмом передаваемых данных. Например, если векторный слой содержит несколько миллионов объектов, то во-первых, клиенту придется ждать пока эти данные будут загружены браузером, а во-вторых пока они будут отрисованы. При этом попытка изменения масштабного уровня вновь потребует перерисовки объектов, что также может занять продолжительное время. Естественно, что ни о каком комфорте при работе с таким приложением речи не идёт, что делает использование векторных форматов недопустимым. В этом случае более подходящим решением является использование растров.  
речи не идёт, что делает использование векторных форматов недопустимым. В этом случае более подходящим решением является использование растров. Однако как быть с интерактивностью? То есть пользователю нужна возможность получения атрибутивной информации об объекте, на который указывает указатель мыши. Конечно, можно реализовать некоторый серверный скрипт, которому будут передаваться текущие координаты, а в ответ возвращаться нужная информация (в случае WMS слоёв можно воспользоваться стандартной возможностью любого WMS-сервера - поддержкой запросов GetFeatureInfo). Однако в данной статье мы рассмотрим другой способ решения этой задачи, предложенный компанией [http://mapbox.com MapBox], известный под именем [https://github.com/mapbox/utfgrid-spec UTFGrid].


UTFGrid представляет собой стандарт, описывающий эффективный с точки зрения объёма передаваемых данных, способ кодирования атрибутивной информации объектов, представленных на растре. Данный стандарт был специально разработан для использования в Web-браузерах и может использоваться, например, для вывода всплывающих подсказок при перемещении указателя мыши. В качестве контейнера UTFGrid использует формат JSON. Рассмотрим пример данных, закодированных при помощи UTFGrid. Предположим, у нас есть некоторый растровый тайл:
Однако как быть с атрибутикой? Допустим, что пользователю нужна возможность получения информации об объекте, на который указывает указатель мыши. Конечно, можно реализовать серверный скрипт, которому будут передаваться текущие координаты, а в ответ возвращаться нужная информация (в случае WMS слоёв можно воспользоваться стандартной возможностью любого WMS-сервера - [http://gis-lab.info/qa/mapserver-getfeatureinfo.html поддержкой запросов GetFeatureInfo]). Однако в данной статье мы рассмотрим другой способ решения этой задачи, предложенный компанией [http://mapbox.com MapBox], известный под именем UTFGrid ([https://github.com/mapbox/utfgrid-spec спецификация]).
 
UTFGrid представляет собой стандарт, описывающий эффективный с точки зрения объёма передаваемых данных, способ кодирования атрибутивной информации объектов, представленных на растре. Данный стандарт был специально разработан для использования в Веб-браузерах и может использоваться, например, для вывода всплывающих подсказок при перемещении указателя мыши (например как [http://gis-lab.info/qa/tilemill-begin.html#.D0.9F.D1.83.D0.B1.D0.BB.D0.B8.D0.BA.D0.B0.D1.86.D0.B8.D1.8F_.D0.BA.D0.B0.D1.80.D1.82.D1.8B_.D0.B2_.D0.98.D0.BD.D1.82.D0.B5.D1.80.D0.BD.D0.B5.D1.82 здесь]). В качестве контейнера UTFGrid использует формат JSON.  
 
Рассмотрим пример данных, закодированных при помощи UTFGrid. Предположим, у нас есть некоторый растровый слой:


[[Файл:Moscow-tile.png|256px|thumb|center|<center>Пример исходного растра</center>]]
[[Файл:Moscow-tile.png|256px|thumb|center|<center>Пример исходного растра</center>]]
Строка 12: Строка 16:
тогда его представление при помощи UTFGrid будет выглядеть следующим образом:
тогда его представление при помощи UTFGrid будет выглядеть следующим образом:


<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript" line="GESHI_FANCY_LINE_NUMBERS">
{
{
     "data": {
     "data": {
         "0": {
         "BOG": {
             "name": "район Богородское"
             "name": "район Богородское"
         },  
         },  
         "1": {
         "VNUK": {
             "name": "район Внуково"
             "name": "район Внуково"
         },  
         },  
         "2": {
         "ALT": {
             "name": "Алтуфьевский район"
             "name": "Алтуфьевский район"
         },  
         },  
         "3": {
         "SIL": {
             "name": "район Силино"
             "name": "район Силино"
         },  
         },  
         "4": {
         "DOR": {
             "name": "район Дорогомилово"
             "name": "район Дорогомилово"
         },  
         },  
         "5": {
         "ZUZ": {
             "name": "район Зюзино"
             "name": "район Зюзино"
         },  
         },  
         "6": {
         "AIR": {
             "name": "район Аэропорт"
             "name": "район Аэропорт"
         },  
         },  
         "7": {
         "BIR": {
             "name": "район Бирюлево Восточное"
             "name": "район Бирюлево Восточное"
         },  
         },  
         "8": {
         "VESH": {
             "name": "район Вешняки"
             "name": "район Вешняки"
         },  
         },  
         "9": {
         "LEF": {
             "name": "район Лефортово"
             "name": "район Лефортово"
         }
         }
Строка 114: Строка 118:
     "keys": [
     "keys": [
         "",  
         "",  
         "3",  
         "SIL",  
         "0",  
         "BOG",  
         "2",  
         "ALT",  
         "6",  
         "AIR",  
         "4",  
         "DOR",  
         "1",  
         "VNUK",  
         "9",  
         "LEF",  
         "8",  
         "VESH",  
         "5",  
         "ZUZ",  
         "7"
         "BIR"
     ]
     ]
}
}
Строка 129: Строка 133:
</syntaxhighlight>
</syntaxhighlight>


== Как оно работает ==
== Структура UTFGrid-файла ==
 
Представленный файл содержит три основных свойства: <code>data</code>, <code>grid</code>, <code>keys</code>. Свойство <code>keys</code> содержит список идентификаторов всех объектов тайла, в <code>data</code> представлены атрибутивные значения этих объектов. Свойство <code>grid</code> содержит текстовое представление растрового тайла. В нашем примере <code>grid</code> содержит 64 строки по 64 символа в каждой, то есть каждый такой символ соответствует объекту размером 4x4 пиксела в оригинальном растре (согласно спецификации UTFGrid по умолчанию использует шаг дискретизации 2x2 пиксела, но этот размер можно изменять, что соответственным образом скажется на размере UTFGrid-файла).
 
== Как это работает ==
 
* Когда пользователь осуществляет некоторые действия (перемещает указатель мыши или кликает по карте) над тайлом, то происходит загрузка UTFGrid-файла, соответствующего этому тайлу;
* Определяется положение указателя мыши внутри тайла и этому положению ставится в соответствие символ из свойства <code>grid</code> загруженного UTFGrid-файла. Предположим, указатель мыши наведён на объект "район Аэропорт". Соответствующий символ грида - "%";
* Согласно [https://github.com/mapbox/utfgrid-spec спецификации] вычисляется порядковый номер идентификатора в списке <code>keys</code>: находим [http://www.utf8-chartable.de/unicode-utf8-table.pl?utf8=dec десятичный код] символа грида в нашем случае он равен 37, вычитаем из него 1 (так как 37 > 35) и вычитаем 32. Получаем 4 (в Python для выполнения этой операции можно воспользоваться командой <code>ord</code>, обратная операция выполняется при помощи <code>unichr</code>);
* В списке <code>keys</code> находим идентификатор, расположенный по указанному индексу (нумерация начинается с 0). В нашем случае <code>keys[4]="AIR"</code>;
* Внутри объекта <code>data</code> по полученному идентификатору находим атрибутивную информацию.
 
UTFGrid используется, в частности, в таком популярном продукте как [http://gis-lab.info/qa/tilemill-begin.html TileMil], [http://tiles.mapbox.com/answer42/map/geosample например]. Поддержка UTFGrid также реализована в библиотеке [http://dev.openlayers.org/releases/OpenLayers-2.12/examples/utfgrid.html OpenLayers]. Ознакомиться в интерактивном режиме с UTFGrid можно на сайте [http://mapbox.com/demo/visiblemap/ visible map].


Когда пользователь осуществляет некоторые действия (перемещает указатель мыши или кликает по карте) над тайлом, то происходит загрузка UTFGrid-файла, соответствующего этому тайлу.
== Преимущества и недостатки ==
С одной стороны, при небольшом количестве кликов на тайл, количество запросов будет сопоставимо с GetFeatureInfo для WMS-слоя. Однако объем переданных клиенту данных будет больше, так как веб-браузеру будет "в нагрузку" передана информация о тех объектах, которые не попадают в область его интересов. Так же клиенту будет передана "лишняя" информация в случае если один элемент будет размещен на нескольких тайлах, в том числе на тайлах разного уровня. С другой стороны, задача раздачи статического контента, как правило, куда менее затратна для веб-сервера с точки зрения потребляемых ресурсов и проще поддается масштабированию при росте нагрузки на сервер.  


По этой причине, вряд ли будет рационально использовать этот механизм для векторного слоя состоящего из миллионов объектов, в случае если им пользуется полтора пользователя. В проектах же с большой аудиторией, где регулярно происходит обращение к одним и тем же данным, использование UTFGrid видится вполне целесообразным.


http://mapbox.com/demo/visiblemap/
Так же, к недостаткам можно отнести то факт, что если растровый тайл построен на базе векторных данных, содержащих перекрывающиеся объекты, то с помощью UTFGrid мы не сможем закодировать информацию о таких объектах, то есть элементы списка <code>keys</code> сами по себе не могут быть списками.


== Техническая сторона ==
== Заключение ==
вы


== Недостатки ==
Мы рассмотрели лишь описание стандарта UTFGrid, пример создание полноценного сервиса с поддержкой UTFGrid будет рассмотрен в одной из следующих статей. Пример UTFGrid, представленный в статье, был сгенерирован при помощи [https://github.com/springmeyer/utfgrid-example-writers/blob/master/ogr_renderer.py ogr_renderer.py].
выв

Текущая версия от 19:58, 5 сентября 2012

Эта страница опубликована в основном списке статей сайта
по адресу http://gis-lab.info/qa/utfgrid.html


Приведено описание стандарта UTFGrid и рассмотрен пример его использования.

Введение

Основное назначение любого картографического web-приложения - это предоставление клиенту пространственной информации, включающей геометрическую и атрибутивную составляющие. Поэтому, в любом случае, на начальном этапе каждый разработчик должен ответить на вопрос: "Какой формат передачи данных следует использовать в конкретном случае?" Как известно, все форматы передачи пространственной информации можно разделить на векторные и растровые. Использование векторных форматов (KML, GML, GeoJSON и т.д.) с одной стороны очень удобно: в клиентском приложении сразу становятся доступными и геометрическая, и атрибутивная составляющие, что обеспечивает простоту добавления приложению интерактивности. С другой же - область применения векторных форматов довольно ограничена и определяется главным образом объёмом передаваемых данных. Например, если векторный слой содержит несколько миллионов объектов, то во-первых, клиенту придется ждать пока эти данные будут загружены браузером, а во-вторых пока они будут отрисованы. При этом попытка изменения масштабного уровня вновь потребует перерисовки объектов, что также может занять продолжительное время. Естественно, что ни о каком комфорте при работе с таким приложением речи не идёт, что делает использование векторных форматов недопустимым. В этом случае более подходящим решением является использование растров.

Однако как быть с атрибутикой? Допустим, что пользователю нужна возможность получения информации об объекте, на который указывает указатель мыши. Конечно, можно реализовать серверный скрипт, которому будут передаваться текущие координаты, а в ответ возвращаться нужная информация (в случае WMS слоёв можно воспользоваться стандартной возможностью любого WMS-сервера - поддержкой запросов GetFeatureInfo). Однако в данной статье мы рассмотрим другой способ решения этой задачи, предложенный компанией MapBox, известный под именем UTFGrid (спецификация).

UTFGrid представляет собой стандарт, описывающий эффективный с точки зрения объёма передаваемых данных, способ кодирования атрибутивной информации объектов, представленных на растре. Данный стандарт был специально разработан для использования в Веб-браузерах и может использоваться, например, для вывода всплывающих подсказок при перемещении указателя мыши (например как здесь). В качестве контейнера UTFGrid использует формат JSON.

Рассмотрим пример данных, закодированных при помощи UTFGrid. Предположим, у нас есть некоторый растровый слой:

Пример исходного растра

тогда его представление при помощи UTFGrid будет выглядеть следующим образом:

{
    "data": {
        "BOG": {
            "name": "район Богородское"
        }, 
        "VNUK": {
            "name": "район Внуково"
        }, 
        "ALT": {
            "name": "Алтуфьевский район"
        }, 
        "SIL": {
            "name": "район Силино"
        }, 
        "DOR": {
            "name": "район Дорогомилово"
        }, 
        "ZUZ": {
            "name": "район Зюзино"
        }, 
        "AIR": {
            "name": "район Аэропорт"
        }, 
        "BIR": {
            "name": "район Бирюлево Восточное"
        }, 
        "VESH": {
            "name": "район Вешняки"
        }, 
        "LEF": {
            "name": "район Лефортово"
        }
    }, 
    "grid": [
        "    !                                                           ", 
        " !!!!!!                                                         ", 
        " !!!!!!!!                                          #            ", 
        "  !!!!!!!!            !                                         ", 
        " !!!!!!!!!!           !!                                        ", 
        "  !!!!! !!!         !!!!!!                                      ", 
        " !!!!!!   !        !!!!!!                                       ", 
        " !!!!!                !                                         ", 
        "    !!!         !!!            $$$$                             ", 
        "                !!!!!!          $$                              ", 
        "                !!!!!!        $$$$                              ", 
        "                !!!!!!         $$$                              ", 
        "                   !!          $$                               ", 
        "                  !!           $$ $$                            ", 
        "                  !!          %$$$$$$$                          ", 
        "                  !!!        %%%%$$$$$$$$$$$                    ", 
        "                   !!!     %%%%%%%$$$$$$$$$$$$                  ", 
        "                   !!!!!%%%%%%%%%%$$$$$$$$$$$$$                 ", 
        "                      !!!%%%%%%%%%$$$$$$$$$$$###                ", 
        "                 !!! !!!!%%%%%%%%%$$$$$$$$$$$####               ", 
        "                !!!!!!!!!!%%%%%%%%$$$$$$$$$#$$#####             ", 
        "                !!!!!!!!!!%%%%%%%%&&$$$$$$$#########            ", 
        "                !!!!!!!!!!!%%%%%%%%&&&&&&&###########           ", 
        "                 !!!!!!!!!!%%%%%%%&&&&&&&&############          ", 
        "                 !  !!!!!!!!%%%%%%&&&&&&&&############# ###     ", 
        "                   '!!!!!!!!%%%%%%%&&&&&&#################      ", 
        "                    !!!!!!!!%%%%%%%&&&&&###############         ", 
        "                   !!!!!!!!!!%%%%%%&&&&&###############         ", 
        "                 ''!!!!!!!!!!%%%%%%&&&&&###############         ", 
        "                '' !!!!!!!!!!%%%%%%&&&&&&&&&###########         ", 
        "               '' ''''''''!!!!%&&&&&&&&&&&&&&##########         ", 
        "                  ''''''''!''!%&&&&&&&&&&&&(((#########         ", 
        "                  ''''''''!'''&&&&&&&&&&&&(((#######))#         ", 
        "                   '''''!!'''''&&&&&&&&&&&&(((#####)))# )))     ", 
        "                   '''''''''''&&&&&&&&&&&&&&((((##))))))))      ", 
        "                   '''''''''&&''&&&&&&&&&&&&(((((()))))))    )  ", 
        "                   '''''''''''''&&&&&&&&((((((((((()))))))))))) ", 
        "                   ''''''''''''''&&&(((((((((((())()))))))))))  ", 
        "                    '''''''''''''((((((((((((((()))))))))))     ", 
        "                     '''''''''''(((((((((((((((())))))))))    ) ", 
        "                      '''''''''(((((((((((((((())))))))))    )))", 
        "                      ''''''''***((((((((((((()))))))) ))   ))))", 
        "                     ''''''''''****((((((((((()))))))))         ", 
        "                 '''  ''''''''********((((((())))))))))         ", 
        "                ''''''  '''''********(++(+((())))))))))         ", 
        "                ''''''   ''**********(+++++()))))++)))          ", 
        "                ''''''   '*********(((+++++++++++++)))          ", 
        "                  ''''    *********(((+++++++++++++)            ", 
        "      '                    ********++++++++++++++++             ", 
        "     ''' ''''''             *******+++++++++++++++              ", 
        "    '''' '''''              *******++++++++++++++               ", 
        "      '  ''''''              ******+++++++++++++                ", 
        "        ''''                   ****++++++++++++                 ", 
        "                                ***++++++++++                   ", 
        "                               *****  ++++++                    ", 
        "                                 ****                           ", 
        "                                 ***                            ", 
        "                              *****                             ", 
        "                           ********                             ", 
        "                           ********                             ", 
        "                              *****                             ", 
        "                               *****                            ", 
        "                               ** **                            ", 
        "                                  ***                           "
    ], 
    "keys": [
        "", 
        "SIL", 
        "BOG", 
        "ALT", 
        "AIR", 
        "DOR", 
        "VNUK", 
        "LEF", 
        "VESH", 
        "ZUZ", 
        "BIR"
    ]
}

Структура UTFGrid-файла

Представленный файл содержит три основных свойства: data, grid, keys. Свойство keys содержит список идентификаторов всех объектов тайла, в data представлены атрибутивные значения этих объектов. Свойство grid содержит текстовое представление растрового тайла. В нашем примере grid содержит 64 строки по 64 символа в каждой, то есть каждый такой символ соответствует объекту размером 4x4 пиксела в оригинальном растре (согласно спецификации UTFGrid по умолчанию использует шаг дискретизации 2x2 пиксела, но этот размер можно изменять, что соответственным образом скажется на размере UTFGrid-файла).

Как это работает

  • Когда пользователь осуществляет некоторые действия (перемещает указатель мыши или кликает по карте) над тайлом, то происходит загрузка UTFGrid-файла, соответствующего этому тайлу;
  • Определяется положение указателя мыши внутри тайла и этому положению ставится в соответствие символ из свойства grid загруженного UTFGrid-файла. Предположим, указатель мыши наведён на объект "район Аэропорт". Соответствующий символ грида - "%";
  • Согласно спецификации вычисляется порядковый номер идентификатора в списке keys: находим десятичный код символа грида в нашем случае он равен 37, вычитаем из него 1 (так как 37 > 35) и вычитаем 32. Получаем 4 (в Python для выполнения этой операции можно воспользоваться командой ord, обратная операция выполняется при помощи unichr);
  • В списке keys находим идентификатор, расположенный по указанному индексу (нумерация начинается с 0). В нашем случае keys[4]="AIR";
  • Внутри объекта data по полученному идентификатору находим атрибутивную информацию.

UTFGrid используется, в частности, в таком популярном продукте как TileMil, например. Поддержка UTFGrid также реализована в библиотеке OpenLayers. Ознакомиться в интерактивном режиме с UTFGrid можно на сайте visible map.

Преимущества и недостатки

С одной стороны, при небольшом количестве кликов на тайл, количество запросов будет сопоставимо с GetFeatureInfo для WMS-слоя. Однако объем переданных клиенту данных будет больше, так как веб-браузеру будет "в нагрузку" передана информация о тех объектах, которые не попадают в область его интересов. Так же клиенту будет передана "лишняя" информация в случае если один элемент будет размещен на нескольких тайлах, в том числе на тайлах разного уровня. С другой стороны, задача раздачи статического контента, как правило, куда менее затратна для веб-сервера с точки зрения потребляемых ресурсов и проще поддается масштабированию при росте нагрузки на сервер.

По этой причине, вряд ли будет рационально использовать этот механизм для векторного слоя состоящего из миллионов объектов, в случае если им пользуется полтора пользователя. В проектах же с большой аудиторией, где регулярно происходит обращение к одним и тем же данным, использование UTFGrid видится вполне целесообразным.

Так же, к недостаткам можно отнести то факт, что если растровый тайл построен на базе векторных данных, содержащих перекрывающиеся объекты, то с помощью UTFGrid мы не сможем закодировать информацию о таких объектах, то есть элементы списка keys сами по себе не могут быть списками.

Заключение

Мы рассмотрели лишь описание стандарта UTFGrid, пример создание полноценного сервиса с поддержкой UTFGrid будет рассмотрен в одной из следующих статей. Пример UTFGrid, представленный в статье, был сгенерирован при помощи ogr_renderer.py.