среда, 16 июля 2008 г.

Тестирование spatialite-2.1

Alessandro Furieri прислал письмо с сообщением о выходе альфа-версии spatialite-2.1 со множеством приятных новшеств:


I've just released SpatiaLite 2.1-alpha
[OGC Spatials for SQLite]

http://www.gaia-gis.it/spatialite-2.1

This is not a stable release, and is simply
an "ad interim" one:

- now supporting Libiconv (full implementation
for locale charsets and Unicode UTF-8)

- now including an useful GUI management tool
(very similar to mysql-query-browser and
pgAdmin3)
** There are lots of GUI tools already
** supporting SQLite, but none of them
** allows dynamic extension loading,
** so they cannot be used for Spatial
** processing

D. Richard Hipp announced that SQLite's new
version [3.6] will officially support RTree
Spatial Index; public release is planned in
the next few days.

This explains why SpatiaLite 2.1-alpha is
a short-lived release; the stable SpatiaLite 2.1
will be released in August, so to include
sqlite-3.6 and the final, stable implementation
for SQLite's RTree
SpatiaLite 2.1-alpha still includes sqlite-3.5.9,
and consequently uses the experimental version of
RTree Spatial Index


Раз так, то надо протестировать, чтобы в августе получить качественный релиз. Итак, запускаем GUI и выбираем в меню подключение шейпфайла. Беру слой с домами по Н. Новгороду (более 40 тысяч объектов), кодировку указываю cp-1251. Автоматически составляется следующий sql-запрос, который и выполняю:

CREATE VIRTUAL TABLE nn_ppab
USING VirtualShape('/var/www/mbg/mobigroup.ru/res/maps/map_ru_52_nn/nn_ppab',
CP1251, -1)


Проверяем:

select count(*) from nn_ppab;
41608

select * from nn_ppab limit 1;
1 BLOB sz=260 GEOMETRY 1.0000 БОГДАНОВИЧА УЛИЦА жилой 7 Нижегородский 7 БОГДАНОВИЧА УЛИЦА 7

select * from nn_ppab where street='БОГДАНОВИЧА' limit 10;
1 BLOB sz=260 GEOMETRY 1.0000 БОГДАНОВИЧА УЛИЦА жилой 7 Нижегородский 7 БОГДАНОВИЧА УЛИЦА 7
2 BLOB sz=132 GEOMETRY 2.0000 БОГДАНОВИЧА УЛИЦА жилой 7 корп.2 Нижегородский 7 к.2 БОГДАНОВИЧА УЛИЦА 7 к.2
3 BLOB sz=260 GEOMETRY 3.0000 БОГДАНОВИЧА УЛИЦА жилой 7 корп.1 Нижегородский 7 к.1 БОГДАНОВИЧА УЛИЦА 7 к.1
6 BLOB sz=132 GEOMETRY 6.0000 БОГДАНОВИЧА УЛИЦА жилой 1 корп.1 Нижегородский 1 к.1 БОГДАНОВИЧА УЛИЦА 1 к.1
35665 BLOB sz=164 GEOMETRY 35675.0000 БОГДАНОВИЧА УЛИЦА жилой 1 корп.2 Нижегородский 1 к.2 БОГДАНОВИЧА УЛИЦА 1 к.2
37953 BLOB sz=260 GEOMETRY 37963.0000 БОГДАНОВИЧА УЛИЦА жилой 1 Нижегородский 1 БОГДАНОВИЧА УЛИЦА 1


Как видим, русский язык работает, информация из шейпфайла доступна с помощью sql-запроса.

Попробуем выполнить пространственные запросы. Для этого нужно загрузить файл init_spatialite.sql с описаниями координатных систем.


select AsText(Geometry) from nn_ppab where street='БОГДАНОВИЧА' limit 1;
POLYGON((442528.805533 6238209.748202, 442618.534136 6238207.367538, 442619.050719 6238209.3142, 442628.264127 6238209.891515, 442628.11679 6238213.850828, 442644.874392 6238213.5352, 442644.684053 6238197.728526, 442642.240754 6238196.709443, 442641.069658 6238190.84432, 442619.145452 6238191.509989, 442618.882569 6238193.507226, 442528.363387 6238196.790178, 442528.805533 6238209.748202))

select AsText(Transform(SetSRID(Geometry,28468),4326)) from nn_ppab where street='БОГДАНОВИЧА' limit 1;
POLYGON((44.072601 56.261807, 44.07405 56.261796, 44.074057 56.261814, 44.074206 56.26182, 44.074203 56.261856, 44.074473 56.261855, 44.074474 56.261713, 44.074434 56.261704, 44.074417 56.261651, 44.074063 56.261654, 44.074058 56.261672, 44.072597 56.26169, 44.072601 56.261807))



Как видим, преобразование координат работает.

понедельник, 14 июля 2008 г.

sqlite в ГИС - продолжение

Приятная новость - индекс R-tree входит в состав версии 3.6.0 (впрочем, и сейчас можно скомпилировать загружаемую библиотеку для поддержки этого индекса, и многие разработчики так и делают, разве что на "маках" есть какие-то проблемы, но эта ОСь мне лично до лампочки), которая будет выпущена в среду. Вот что по этому поводу написал в рассылку сам автор SQLite:


The current plan is to release SQLite version 3.6.0 on Wednesday,
2008-07-16.

Draft documentation on version 3.6.0 is available at http://www.sqlite.org/draft/doc/index.html
. Please pay particular attention to:

http://www.sqlite.org/draft/doc/35to36.html

If you sees any problems with the upcoming release, or finds omissions
or errors or ambiguities in the documentation, now would be a very
good time to speak up. Thank you for your attention.

D. Richard Hipp
drh@hwaci.com


Вот отсюда http://www.gaia-gis.it/spatialite-2.0/index.html можно взять аналог PostGIS для SQLite. Кстати, этот аналог обладает интересным свойством - с его помощью можно подключать шейпфайлы к базе и работать с ними. А можно просто импортировать шейпы и, разумеется, экспортировать геоданные в этот формат.
Список функций см. на этой странице
SpatiaLite SQL functions reference list

В настоящий момент индекс R-tree поддерживает только значения типа float, однако ведется дискуссия по поводу включения поддержки типа int - патч предложен, однако пока неясно, как именно переключаться между этими типами. Выбирать тип на этапе компиляции не выход, поскольку в одной БД могут понадобиться оба типа (например, для периода времени и координат), этот аргумент уже озвучен.

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

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

суббота, 19 апреля 2008 г.

Немного о GeoServer

Несмотря на мое сугубо отрицательное отношение к технологии ява и созданных на ее основе проектах, предложу вашему вниманию небольшой обзор GeoServer из тех соображений, что учиться лучше на чужих ошибках.

Начало работы с GeoServer

среда, 19 марта 2008 г.

sqlite в ГИС

Никого уже не удивить пространственными расширениями для баз данных - ими давно обзавелись многие коммерческие СУБД и открытые догоняют. Например, для постгреса это модуль PostGIS, о котором я уже не раз упоминал. Возможностей в нем и в самом деле много, а вот с остальным беда - например, производительность отрисовки данных с пространственным индексом из БД примерно в 10 раз ниже отрисовки из шейпов с пространственным индексом. Печально и заставляет задуматься. Кроме того, отнимает время администрирование БД. Перечисленные проблемы относятся к любой из подобных реализаций, поскольку клиент-серверная модель взаимодействия требует определенной платы за предоставляемые возможности (как и все в этом мире, в сущности).

В противовес "тяжелым" реализациям идут так называемые файл-ориентированные и в первую очередь, разумеется, это шейпфайлы. Хранение данных в локальных файлах имеет очевидные преимущества в простоте управления ими, обеспечивает высокое быстродействие, не требует администрирования. Однако шейпфайлы не вершина эволюции, поскольку требуют целый набор файлов (минимум три файла) для хранения данных (пространственная информация, индекс объектов и атрибутивная информация, а также может создаваться файл с пространственным индексом и другие файлы). Вдобавок атрибуты хранятся в устаревшем формате dbase. Об xml-форматах промолчим, поскольку xml это лишь формат обмена информацией (о чем часто забывают и работают с ним напрямую, что приводит к множеству проблем). Отличной реализацией будет хранение данных в базе данных, представляющей из себя единственный файл. И такая база есть - SQLite. Заметим, что в настоящий момент имеются некоторые серьезные ограничения - sqlite не поддерживает R-tree индекс, что делает невозможным построение пространственного индекса (с версии 3.6.0 поддерживает). Тем не менее, в определенных случаях использовать sqlite для хранения пространственных данных вполне можно. Например, если поиск по координатам объекта не требуется и нужен поиск только по атрибутивной информации, или если необходимо хранить только точечные объекты, или просто объем данных небольшой.

Как индексировать точечные объекты, можно прочитать вот здесь
Re: [sqlite] Spatial searches.

Хранить координаты удобно в формате WKT (Well-known text).

Также существуют утилиты для обработки данных, сохраненных в sqlite в формате WKT
SQLite RDBMS

OGR SQL.

А от небольшой пример сохранения данных из шейпфайлов в sqlite:

ogr2ogr -s_srs "EPSG:32638" -t_srs "EPSG:32638" -f SQLite out.db nn_tsp.shp

ogr2ogr -s_srs "EPSG:32638" -t_srs "EPSG:4326" -f SQLite out.db nn_tsp.shp


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

В качестве заключения: поддержка индекса R-tree для sqlite планируется, после реализации этой возможности можно будет полноценно использовать sqlite для хранения пространственных данных. Неоднократно упомянутый postgis является не более чем оберткой для внешних библиотек обработки пространственных данных, сделать аналогичную обертку для sqlite задача не слишком сложная. Далее, сейчас в браузеры встраивается поддержка sqlite, что позволяет работать с данными непосредственно на клиенте, используя javascript (в 3-й версии браузера мозилла встроенная поддержка, для других браузеров существуют плугины). Jabascript библиотеки для поддержки WKT также уже готовы, например, библиотека OpanLayers умеет отображать WKT-данные на карте. Для повышения быстродействия можно хранить данные в двоичном формате WKB на сервере и преобразовывать в WKT для удобства использования клиентами.

понедельник, 17 марта 2008 г.

Картографические приложения с помощью библиотеки OpenLayers

Гора не сходится с горой,
Но жизнь свершает круг,
И старый недруг нам порой
Милей, чем новый друг.
Вадим Шефнер
"Лачуга должника"


Некоторое время тому назад мы уже знакомились с технологией создания картсервера с помощью одноименного приложения mapserver. И все было хорошо - великолепная отрисовка множества векторных и растровых слоев, работа с разнообразными проекциями и источниками данных. Пользовательских интерфейсов для mapserver тоже хватает - и на яваскрипт, и флэшовые, и на ява-аплетах, не говоря уже про простой хтмл. Сложность только одна - где бы взять необходимые нам векторные данные, широко доступное изобилие которых наблюдается на территории западных стран? Вот эта мелочь и является камнем преткновения. Ну еще чисто технические сложности - нужны подготовленные к публикации данные, файл проекта с описанием свойств карты и всех слоев (map-файл), что в общем тоже требует много времени. Сегодня мы поговорим о решениях для бизнеса - есть у нас задача по визуализации сети торговых точек, или трэков со спутниковых навигаторов или... Рассмотрим прикладной аспект - есть данные с географической привязкой, которые надо отобразить на карте и как можно меньше заморачиваясь на саму карту и все с ней связанное. Бизнес сегодня успешно глобализуется, так что карты города уже мало, нужно работать как минимум с картой региона, а то и страны или картой всей планеты. да и деловая жизнь все ускоряется - пользователю необходим простой и вместе с тем функциональный и надежный инструмент. И такой инструмент уже есть, нужно лишь научиться с ним обращаться.

Начнем с постановки задачи: требуется полнофункциональный кроссплатформенный и веб-ориентированный интерфейс (ajax), работа с картой должна быть быстрой и не заставлять ждать загрузки очередной карты и не нагружать сервер даже при одновременной работе многих пользователей (растровая мозаика), а также возможность отображать и изменять произвольные векторные данные (асинхронная подгрузка данных в форматах kml,georss,wkt). Все это доступно при использовании клиентской библиотеки OpenLayers, которая на самом деле умеет намного больше. Но сегодня мы не будет интересоваться интеграцией своих карт с картами гугл и работой с mapserver (да, можно и его карты использовать, да еще и разными способами - как запрашивая через cgi-интерфейс нужные картинки и метаинформацию, так и взаимодействуя со встроенными WMS/WFS серверами), а ограничимся самым простым и эффективным решением нашей задачи.

Вот пример, иллюстрирующий использование растровой подложки для интерактивного отображения так называемых "точек интересов" (POI). Элементы мозаики, на которые разделен растр, являются обычными статичными изображениями, и их может эффективно публиковать практически любой веб-сервер (aolserver, nginx, lighttpd, thttpd, etc.) и кэшировать прокси-сервер и сам браузер пользователя. Таким образом, достаточно любого хостинга и нет требований к ресурсам сервера (разве что к объему жесткого диска, но в наше время терабайтных винчестеров карта размером в сотни мегабайт кажется сущей безделицей). Отображение точек интересов происходит интерактивно - при переходе к просмотру очередной части карты отправляется асинхронный запрос к серверу на получение файла со списком нужных объектов для отображаемых квадрантов карты. Этот файл может быть как статическим, так и динамическим - в любом случае его размер обычно невелик по сравнению с размером растровой подложки карты. Работая с сервером в локальной сети или через прокси можно комфортно перемещаться по карте и масштабировать ее, не тратя время на ожидание загрузки данных.

Для любознательных - протестировав отрисовку разных наборов данных (точки, линии, полигоны) я убедился в том, что в течении секунды успевают отрисоваться объекты из многих тысяч точек, так что отображение векторной информации в браузере пользователя не мешает работе. Притом используемый мною браузер Iceweasel (Mozilla Firefox) 2.0.0.11 далеко не самый быстрый на сегодня.

Множество примеров доступно на официальном сайте проекта OpenLayers, там же можно скачать как саму библиотеку, так и примеры.

Замечу еще, что работа с проецированными растрами поддерживается, хотя немного странно, проще всего работать в системе координат EPSG:41001. Для построения пирамиды из растра (файл привязки не обязателен) можно воспользоваться утилитой GDAL2Tiles Project.

Код на яваскрипт для клиентской части занимает одну-две страницы, так что подробно на этом останавливаться смысла не вижу, тем более, что примеров много и они работают :-)

Визуализация данных при помощи PyNGL

Попалась на глаза статья, посвященная визуализации научных данных с помощью питоновских библиотек. Не то чтобы я сторонник питона, но отход от использования явы в ГИС-приложениях и смежных областях очень радует, ибо мое отношение к яве "ни за что и никогда". К питону претензия только одна - язык объектный, что чревато всякими нехорошими эффектами (наподобии проблемы с параллельным выполнением кода, отсутствия средств для генерации кода и его последующего выполнения и проч.). Зато вызывает уважение, что питон сумел потеснить перл и яву, на фоне этих артефактов объектная модель питона смотрится привлекательно. Как раз вот сегодня пользовался утилитами из комплекта FWTools, а если быть точным, то питоновской оберткой к gdal, в очередной раз ругался на странную с моей точки зрения идеологию разбора параметров командной строки :-)

А вот и сама статья статья

вторник, 4 марта 2008 г.

Руководство по GRASS 6.0

В сети появился русский перевод руководства по GRASS 6.0.

Учебное руководство по ГИС GRASS 6.0

Вот еще статья там же появилась:
Использование Doxygen для работы с исходным программным кодом ПО ГИС

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

понедельник, 4 февраля 2008 г.

Карты гугл в бизнесе

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

Юниаструм банк. Карта России. Дополнительные офисы и филиалы.

пятница, 1 февраля 2008 г.

Сервер WMS и библиотека OpenLayers и Google API

Mapserver предоставляет возможность создания серверов WMS и WFS. Такой подход позволяет разделить картсервер и наборы карт от логики (и кода) визуализации, а также пользоваться сторонними WMS/WFS серверами. Кроме того, клиентская часть может быть написана на различных языках под разные платформы. Вот некоторые примеры: яваскрипт библиотека OpenLayers и гугловая версия API, десктопная программа QGIS и другие.

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

OpenLayers: начало работы

А вот пример карты НН с моего сервера, отображаемой на карте Гугл (когда-то в блоге эта карта висела, при переносе картсервера я этот пример удалил).



wms236.js


var MAGIC_NUMBER=6356752.3142;
var WGS84_SEMI_MAJOR_AXIS = 6378137.0;
var WGS84_ECCENTRICITY = 0.0818191913108718138;

var DEG2RAD=0.0174532922519943;
var PI=3.14159267;

var FORMAT_DEFAULT="image/png";

var MERC_ZOOM_DEFAULT = 15;
function dd2MercMetersLng(p_lng) {
return WGS84_SEMI_MAJOR_AXIS * (p_lng*DEG2RAD);
}

function dd2MercMetersLat(p_lat) {
var lat_rad = p_lat * DEG2RAD;
return WGS84_SEMI_MAJOR_AXIS * Math.log(Math.tan((lat_rad + PI / 2) / 2) * Math.pow( ((1 - WGS84_ECCENTRICITY * Math.sin(lat_rad)) / (1 + WGS84_ECCENTRICITY * Math.sin(lat_rad))), (WGS84_ECCENTRICITY/2)));
}

CustomGetTileUrl=function(a,b,c) {
if (this.myMercZoomLevel == undefined) {
this.myMercZoomLevel = MERC_ZOOM_DEFAULT;
}

if (this.myFormat == undefined) {
this.myFormat = FORMAT_DEFAULT;
}

if (typeof(window['this.myStyles'])=="undefined") this.myStyles="";
var lULP = new GPoint(a.x*256,(a.y+1)*256);
var lLRP = new GPoint((a.x+1)*256,a.y*256);
var lUL = G_NORMAL_MAP.getProjection().fromPixelToLatLng(lULP,b,c);
var lLR = G_NORMAL_MAP.getProjection().fromPixelToLatLng(lLRP,b,c);

var lBbox=dd2MercMetersLng(lUL.x)+","+dd2MercMetersLat(lUL.y)+","+dd2MercMetersLng(lLR.x)+","+dd2MercMetersLat(lLR.y);
var lSRS="EPSG:41001";
var lURL=this.myBaseURL;
lURL+="&REQUEST=GetMap";
lURL+="&SERVICE=WMS";
lURL+="&VERSION=1.1.1";
lURL+="&LAYERS="+this.myLayers;
lURL+="&STYLES="+this.myStyles;
lURL+="&FORMAT="+this.myFormat;
lURL+="&BGCOLOR=0xFFFFFF";
lURL+="&TRANSPARENT=TRUE";
lURL+="&SRS="+lSRS;
lURL+="&BBOX="+lBbox;
lURL+="&WIDTH=256";
lURL+="&HEIGHT=256";
lURL+="&reaspect=false";
//document.write(lURL + "
")
//alert(" url is " + lURL);
return lURL;
}

function customOpacity() { return this.myOpacity; }


wms_ru_52_nn.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1251"/>
</head>
<body>
<div id="map" style="width: 480px; height: 360px"></div>
<script src="http://maps.google.com/maps?file=api&v=2.47&key=ABQIAAAA3_I9SMdcHuWV4-_KzNVuFRTANUniEb_EzjeFkl9Mls1H2avqJBQUx0CKpyG9m5g8AKED-XD5sPCO6Q" type="text/javascript"></script>
<script src="http://support.mobigroup.ru/files/wms/wms236.js" type="text/javascript"></script>

<script type="text/javascript">

var map = new GMap(document.getElementById("map"));
map.addControl(new GScaleControl());

// Create tile layers
var tile1= new GTileLayer(new GCopyrightCollection(""),1,17);
tile1.myLayers='nn_poa,nn_ppab';
tile1.myFormat='image/png';
tile1.myBaseURL='http://dload.mobigroup.ru/ru_52_nn/mapserv?';
tile1.getTileUrl=CustomGetTileUrl;

var layer3=[G_HYBRID_MAP.getTileLayers()[0],tile1];
var custommap3 = new GMapType(layer3, G_SATELLITE_MAP.getProjection(), "WMS 1", G_HYBRID_MAP);

map.getMapTypes().length = 0;
map.addMapType(custommap3);

map.setCenter(new GLatLng(56.293, 44.065), 16);
map.addControl(new GLargeMapControl());

</script>
<br>
</body>
</html>




Про создание собственного WMS-сервера можно почитать здесь Создание WMS-сервиса с помощью Mapserver и, разумеется, в первоисточнике WMS Servers with MapServer.

среда, 30 января 2008 г.

GMT - Generic Mapping Tools

Попалась на глаза пара ссылок по работе с библиотекой Generic Mapping Tools (GMT). Как ни странно, я умудрился еще ни разу об этой коллекции утилит не упомянуть, а она явно заслуживает большего к себе внимания. Времени сейчас нет (все время и силы отнимает написание нового блока аналитики для системы мерчендайзинга), так что ограничусь краткой справкой.

Вот описание дебиановского пакета gmt:

Generic Mapping Tools

Свободная коллекция около 60 утилит UNIX для работы с двумерными и трехмерными наборами данных, включая фильтры, построение трэндов, поверхностей, сеток поверхностей, проекций и проч. Утилиты создают Encapsulated PostScript File (EPS) двумерные изображения поверхностей в виде контурных карт и трехмерные виды с учетом перспективы в черно-белом цветах, оттенках серого и 24-битном цвете.

GMT поддерживает 25 картографических проекции плюс линейный, логарифмический, степенной масштабы и различные типы исходных данных, к примеру, береговые линии, реки и административные районы.


А вот пара полезных ссылок:

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

Создание простейшей карты в GMT


В дебиане ленни есть целый набор соответствующих пакетов, которые можно посмотреть командой
aptitude search gmt


gmt - Generic Mapping Tools
gmt-coast-low - Low resolution coastlines for the Generic Mapping Tools
gmt-coastline-data -
gmt-doc - HTML documentation for GMT, the Generic Mapping Tools
gmt-doc-pdf - PDF docs for GMT, the Generic Mapping Tools
gmt-doc-ps - PostScript docs for the Generic Mapping Tools
gmt-examples - Example scripts illustrating the use of GMT
gmt-manpages - Manpages for the Generic Mapping Tools
gmt-tutorial - Data files needed to reproduce the tutorial examples of GMT
gmt-tutorial-pdf - Tutorial for GMT, the Generic Mapping Tools (PDF)
gmt-tutorial-ps - Tutorial for the Generic Mapping Tools (PostScript)


Вот еще статья появилась на эту же тему:
Начало работы с GMT

(C) Alexey Pechnikov aka MBG, mobigroup.ru