<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xml:lang="en"
   >
  <title type="text">Thinking in GIS</title>
  <subtitle type="text">a blog about GIS from a urban geogeek living at the countryside</subtitle>

  <updated>2012-05-10T16:57:48Z</updated>
  <generator uri="http://blogofile.com/">Blogofile</generator>

  <link rel="alternate" type="text/html" href="None" />
  <id>None/feed/atom/</id>
  <link rel="self" type="application/atom+xml" href="None/feed/atom/" />
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[The power of GDAL virtual formats]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2012/03/08/gdal_virtual_formats/" />
    <id>http://www.paolocorti.net/2012/03/08/gdal_virtual_formats/</id>
    <updated>2012-03-08T18:30:00Z</updated>
    <published>2012-03-08T18:30:00Z</published>
    <category scheme="None" term="python" />
    <category scheme="None" term="qgis" />
    <category scheme="None" term="mapserver" />
    <category scheme="None" term="GIS" />
    <category scheme="None" term="GDAL" />
    <summary type="html"><![CDATA[The power of GDAL virtual formats]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2012/03/08/gdal_virtual_formats/"><![CDATA[<p><a href=" http://www.gdal.org">GDAL</a> is most likely the most powerfull <a href=" http://en.wikipedia.org/wiki/Geographic_information_system">GIS</a> toolset out there, with very geekish features that may seem complicated at first, but become extremely powerful and simple at the same time once you master them. <br />
One of these features I most like is the virtual format concept, valid both for raster data sources (GDAL) and for vectorial data sources (<a href=" http://www.gdal.org/ogr/">OGR</a>).
Basically GDAL gives to the user a very simple mechanism to create virtual formats from some different sources.<br />
Let's analyze this feature, with a couple of samples derived from real world scenarios I have been envolved in the last weeks.</p>
<h3>Raster GDAL Virtual Formats</h3>
<p>GDAL gives the possibility to create <a href="http://www.gdal.org/gdal_vrttut.html">GDAL virtual formats</a>: it is possible to create a GDAL dataset <em>"composed from other GDAL datasets with repositioning, and algorithms potentially applied as well as various kinds of metadata altered or added. VRT descriptions of datasets can be saved in an XML format normally given the extension .vrt."</em><br />
In the virtual GDAL dataset it is possible, by simply using some <a href=" http://en.wikipedia.org/wiki/Xml">xml</a>, to manage, alter, and add important elements of a raster, like the spatial reference, the six values for the affine geotransformation, the metadata, the mask band.<br />
For each band of the resulting raster, it is possible to manage important parameters like the NoDataValue, the ColorTable the vertical units, just to name a few ones.<br /></p>
<p>In a recent project I had a <a href=" http://www.gdal.org/frmt_netcdf.html">NetCDF</a> dataset, composed of 104 subdatasets (weather forecast variables), each of them composed of 10 bands (each band with the forecast for one of the next 10 following days).<br />
I wanted to have a single virtual raster managing the values of 3 of the 107 variables for each forecast day, for using it within <a href=" http://mapserver.gis.umn.edu">MapServer</a> (and at some extent in <a href=" http://www.qgis.org/">QGIS</a>).</p>
<p>This is what I have been using in xml for creating the virtual raster composed of 3 bands with the values of the 3 variables in each band for the 7th day of the forecast:</p>
<div class="pygments_murphy"><pre><span class="nt">&lt;VRTDataset</span> <span class="na">rasterXSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">rasterYSize=</span><span class="s">&quot;640&quot;</span><span class="nt">&gt;</span>
  <span class="nt">&lt;SRS&gt;</span>GEOGCS[&quot;WGS 84&quot;,
    DATUM[&quot;WGS_1984&quot;,
        SPHEROID[&quot;WGS 84&quot;,6378137,298.257223563,
            AUTHORITY[&quot;EPSG&quot;,&quot;7030&quot;]],
        AUTHORITY[&quot;EPSG&quot;,&quot;6326&quot;]],
    PRIMEM[&quot;Greenwich&quot;,0,
        AUTHORITY[&quot;EPSG&quot;,&quot;8901&quot;]],
    UNIT[&quot;degree&quot;,0.0174532925199433,
        AUTHORITY[&quot;EPSG&quot;,&quot;9122&quot;]],
    AUTHORITY[&quot;EPSG&quot;,&quot;4326&quot;]]<span class="nt">&lt;/SRS&gt;</span>
  <span class="nt">&lt;GeoTransform&gt;</span> -1.4062500000000000e-01,  2.8125000000000000e-01,  0.0000000000000000e+00,  8.9925385321783935e+01,  0.0000000000000000e+00, -2.8101682913057480e-01<span class="nt">&lt;/GeoTransform&gt;</span>
  <span class="nt">&lt;Metadata&gt;</span>
    <span class="nt">&lt;MDI</span> <span class="na">key=</span><span class="s">&quot;raster_sample_key&quot;</span><span class="nt">&gt;</span>My metadata for my virtual raster<span class="nt">&lt;/MDI&gt;</span>
  <span class="nt">&lt;/Metadata&gt;</span>
  <span class="nt">&lt;VRTRasterBand</span> <span class="na">dataType=</span><span class="s">&quot;Float32&quot;</span> <span class="na">band=</span><span class="s">&quot;1&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Metadata&gt;</span>
      <span class="nt">&lt;MDI</span> <span class="na">key=</span><span class="s">&quot;band_sample_key&quot;</span><span class="nt">&gt;</span>My metadata for my virtual raster band variable 1<span class="nt">&lt;/MDI&gt;</span>
    <span class="nt">&lt;/Metadata&gt;</span>
    <span class="nt">&lt;NoDataValue&gt;</span>0<span class="nt">&lt;/NoDataValue&gt;</span>
    <span class="nt">&lt;SimpleSource&gt;</span>
      <span class="nt">&lt;SourceFilename</span> <span class="na">relativeToVRT=</span><span class="s">&quot;0&quot;</span><span class="nt">&gt;</span>NETCDF:/path/to/ncdf/mydatset.nc4:my_var_1<span class="nt">&lt;/SourceFilename&gt;</span>
      <span class="nt">&lt;SourceBand&gt;</span>7<span class="nt">&lt;/SourceBand&gt;</span>
      <span class="nt">&lt;SourceProperties</span> <span class="na">RasterXSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">RasterYSize=</span><span class="s">&quot;640&quot;</span> <span class="na">DataType=</span><span class="s">&quot;Float32&quot;</span> <span class="na">BlockXSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">BlockYSize=</span><span class="s">&quot;1&quot;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;SrcRect</span> <span class="na">xOff=</span><span class="s">&quot;0&quot;</span> <span class="na">yOff=</span><span class="s">&quot;0&quot;</span> <span class="na">xSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">ySize=</span><span class="s">&quot;640&quot;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;DstRect</span> <span class="na">xOff=</span><span class="s">&quot;0&quot;</span> <span class="na">yOff=</span><span class="s">&quot;0&quot;</span> <span class="na">xSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">ySize=</span><span class="s">&quot;640&quot;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/SimpleSource&gt;</span>
  <span class="nt">&lt;/VRTRasterBand&gt;</span>
  <span class="nt">&lt;VRTRasterBand</span> <span class="na">dataType=</span><span class="s">&quot;Float32&quot;</span> <span class="na">band=</span><span class="s">&quot;2&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Metadata&gt;</span>
      <span class="nt">&lt;MDI</span> <span class="na">key=</span><span class="s">&quot;band_sample_key&quot;</span><span class="nt">&gt;</span>My metadata for my virtual raster band variable 2<span class="nt">&lt;/MDI&gt;</span>
    <span class="nt">&lt;/Metadata&gt;</span>
    <span class="nt">&lt;NoDataValue&gt;</span>0<span class="nt">&lt;/NoDataValue&gt;</span>
    <span class="nt">&lt;SimpleSource&gt;</span>
      <span class="nt">&lt;SourceFilename</span> <span class="na">relativeToVRT=</span><span class="s">&quot;0&quot;</span><span class="nt">&gt;</span>NETCDF:/path/to/ncdf/mydatset.nc4:my_var_2<span class="nt">&lt;/SourceFilename&gt;</span>
      <span class="nt">&lt;SourceBand&gt;</span>7<span class="nt">&lt;/SourceBand&gt;</span>
      <span class="nt">&lt;SourceProperties</span> <span class="na">RasterXSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">RasterYSize=</span><span class="s">&quot;640&quot;</span> <span class="na">DataType=</span><span class="s">&quot;Float32&quot;</span> <span class="na">BlockXSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">BlockYSize=</span><span class="s">&quot;1&quot;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;SrcRect</span> <span class="na">xOff=</span><span class="s">&quot;0&quot;</span> <span class="na">yOff=</span><span class="s">&quot;0&quot;</span> <span class="na">xSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">ySize=</span><span class="s">&quot;640&quot;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;DstRect</span> <span class="na">xOff=</span><span class="s">&quot;0&quot;</span> <span class="na">yOff=</span><span class="s">&quot;0&quot;</span> <span class="na">xSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">ySize=</span><span class="s">&quot;640&quot;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/SimpleSource&gt;</span>
  <span class="nt">&lt;/VRTRasterBand&gt;</span>
  <span class="nt">&lt;VRTRasterBand</span> <span class="na">dataType=</span><span class="s">&quot;Float32&quot;</span> <span class="na">band=</span><span class="s">&quot;3&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Metadata&gt;</span>
      <span class="nt">&lt;MDI</span> <span class="na">key=</span><span class="s">&quot;band_sample_key&quot;</span><span class="nt">&gt;</span>My metadata for my virtual raster band variable 3<span class="nt">&lt;/MDI&gt;</span>
    <span class="nt">&lt;/Metadata&gt;</span>
    <span class="nt">&lt;NoDataValue&gt;</span>0<span class="nt">&lt;/NoDataValue&gt;</span>
    <span class="nt">&lt;SimpleSource&gt;</span>
      <span class="nt">&lt;SourceFilename</span> <span class="na">relativeToVRT=</span><span class="s">&quot;0&quot;</span><span class="nt">&gt;</span>NETCDF:/path/to/ncdf/mydatset.nc4:my_var_3<span class="nt">&lt;/SourceFilename&gt;</span>
      <span class="nt">&lt;SourceBand&gt;</span>7<span class="nt">&lt;/SourceBand&gt;</span>
      <span class="nt">&lt;SourceProperties</span> <span class="na">RasterXSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">RasterYSize=</span><span class="s">&quot;640&quot;</span> <span class="na">DataType=</span><span class="s">&quot;Float32&quot;</span> <span class="na">BlockXSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">BlockYSize=</span><span class="s">&quot;1&quot;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;SrcRect</span> <span class="na">xOff=</span><span class="s">&quot;0&quot;</span> <span class="na">yOff=</span><span class="s">&quot;0&quot;</span> <span class="na">xSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">ySize=</span><span class="s">&quot;640&quot;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;DstRect</span> <span class="na">xOff=</span><span class="s">&quot;0&quot;</span> <span class="na">yOff=</span><span class="s">&quot;0&quot;</span> <span class="na">xSize=</span><span class="s">&quot;1280&quot;</span> <span class="na">ySize=</span><span class="s">&quot;640&quot;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/SimpleSource&gt;</span>
  <span class="nt">&lt;/VRTRasterBand&gt;</span>
<span class="nt">&lt;/VRTDataset&gt;</span>
</pre></div>
<p>At this point this is effectively a raster for GDAL and all the software and tools based on it.<br />
For example it will be easily possible to query it with <a href=" http://www.gdal.org/gdalinfo.html">gdalinfo</a> or manipulate it with some other GDAL command line utilities, to display it with MapServer or desktop software like QGIS or even to access it programmatically with the GDAL API.</p>
<p>The GDAL command line utility gdalinfo will produce the following output:</p>
<pre><code>$ gdalinfo my_vrt_raster.vrt 
Driver: VRT/Virtual Raster
Files: my_vrt_raster.vrt
Size is 1280, 640
Coordinate System is:
GEOGCS["WGS 84",
    DATUM["WGS_1984",
        SPHEROID["WGS 84",6378137,298.257223563,
            AUTHORITY["EPSG","7030"]],
        AUTHORITY["EPSG","6326"]],
    PRIMEM["Greenwich",0,
        AUTHORITY["EPSG","8901"]],
    UNIT["degree",0.0174532925199433,
        AUTHORITY["EPSG","9122"]],
    AUTHORITY["EPSG","4326"]]
Origin = (-0.140625000000000,89.925385321783935)
Pixel Size = (0.281250000000000,-0.281016829130575)
Metadata:
  raster_sample_key=My metadata for my virtual raster
Corner Coordinates:
Upper Left  (  -0.1406250,  89.9253853) (  0d 8'26.25"W, 89d55'31.39"N)
Lower Left  (  -0.1406250, -89.9253853) (  0d 8'26.25"W, 89d55'31.39"S)
Upper Right (     359.859,      89.925) (359d51'33.75"E, 89d55'31.39"N)
Lower Right (     359.859,     -89.925) (359d51'33.75"E, 89d55'31.39"S)
Center      ( 179.8593750,   0.0000000) (179d51'33.75"E,  0d 0' 0.01"N)
Band 1 Block=128x128 Type=Float32, ColorInterp=Undefined
  NoData Value=0
  Metadata:
    band_sample_key=My metadata for my virtual raster band variable 1
Band 2 Block=128x128 Type=Float32, ColorInterp=Undefined
  NoData Value=0
  Metadata:
    band_sample_key=My metadata for my virtual raster band variable 2
Band 3 Block=128x128 Type=Float32, ColorInterp=Undefined
  NoData Value=0
  Metadata:
    band_sample_key=My metadata for my virtual raster band variable 3
</code></pre>
<p>It will be possible to convert this virtual raster to a different raster format with <a href=" http://www.gdal.org/gdal_translate.html">gdal_translate</a> (the reverse is also possible, of course):</p>
<pre><code>$ gdal_translate -of JPEG my_vrt_raster.vrt my_raster.jpeg
</code></pre>
<p>MapServer directly support this virtual GDAL format, and this is how I defined the layer in the mapfile:</p>
<pre><code># virtual raster
LAYER
    NAME "virtualraster"
    DATA "/path/to/vrt/my_vrt_raster.vrt.vrt"
    STATUS ON
    TEMPLATE     "data/my_vrt_raster_template.html"
    PROJECTION
       "init=epsg:4326"
    END
    TYPE RASTER
    METADATA
        "wms_title"           "WMS Virtual Raster"
        "wms_srs"             "EPSG:4326"
    END
END
</code></pre>
<p>QGIS will correctly display it using the GDAL Virtual Raster driver, and finally it will be accessible programmatically using the GDAL API: for example this is how in <a href=" http://www.python.org/">Python</a> is is possible to get the metadata information of the first band:</p>
<div class="pygments_murphy"><pre><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">osgeo</span> <span class="kn">import</span> <span class="n">gdal</span>
<span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">osgeo.gdalconst</span> <span class="kn">import</span> <span class="o">*</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">dataset</span> <span class="o">=</span> <span class="n">gdal</span><span class="o">.</span><span class="n">Open</span><span class="p">(</span><span class="s">&#39;/path/to/vrt/my_vrt_raster.vrt.vrt&#39;</span><span class="p">,</span> <span class="n">GA_ReadOnly</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">band1</span> <span class="o">=</span> <span class="n">dataset</span><span class="o">.</span><span class="n">GetRasterBand</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="k">print</span> <span class="n">band1</span><span class="o">.</span><span class="n">GetMetadata_List</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">band_sample_key</span><span class="o">=</span><span class="n">My</span> <span class="n">metadata</span> <span class="k">for</span> <span class="n">my</span> <span class="n">virtual</span> <span class="n">raster</span> <span class="n">band</span> <span class="n">variable</span> <span class="mi">1</span>
</pre></div>
<p>Note that he <a href=" http://www.gdal.org/gdalbuildvrt.html">gdalbuildvrt</a> GDAL command will build a vrt from a list of datasets, and it is very handy if you want to generate the vrt file without too much effort.</p>
<h3>Vectorial OGR Virtual Formats</h3>
<p>In OGR, the vectorial "part" of GDAL, there is also the possibility to compose <a href="http://www.gdal.org/ogr/drv_vrt.html">virtual formats</a>.<br />
This format is an excellent possibility if you need to derive spatial layers from formats that are not directly spatially enabled like flat files and flat database tables with spatial information not stored in common formats like wkt or wkb.<br />
You can create a virtual format mapping the original data source with an xml file: after creating this file it will be possible to read (and if some basic condition is met even to write!) the original datasource without using interchange formats.</p>
<p>A couple of situation I have met in my latest projects: in the first one I had to read a flat table in <a href=" http://www.oracle.com">Oracle</a> storing point geometries, with the geographic information stored as two double fields (x, y), and at the same time filtering the results on a CATEGORY field value.<br />
This is how I ended up creating the virtual driver to the table (using the GeometryField xml subelement for defining where the geometric information is stored):</p>
<div class="pygments_murphy"><pre><span class="nt">&lt;OGRVRTDataSource&gt;</span>
    <span class="nt">&lt;OGRVRTLayer</span> <span class="na">name=</span><span class="s">&quot;my_table&quot;</span><span class="nt">&gt;</span>
        <span class="nt">&lt;SrcDataSource&gt;</span>OCI:user/password@server/schema<span class="nt">&lt;/SrcDataSource&gt;</span> 
        <span class="nt">&lt;SrcSQL&gt;</span>select * from MY_TABLE where CATEGORY = 1<span class="nt">&lt;/SrcSQL&gt;</span> 
        <span class="nt">&lt;GeometryType&gt;</span>wkbPoint<span class="nt">&lt;/GeometryType&gt;</span> 
            <span class="nt">&lt;LayerSRS&gt;</span>WGS84<span class="nt">&lt;/LayerSRS&gt;</span>
        <span class="nt">&lt;GeometryField</span> <span class="na">encoding=</span><span class="s">&quot;PointFromColumns&quot;</span> <span class="na">x=</span><span class="s">&quot;x&quot;</span> <span class="na">y=</span><span class="s">&quot;y&quot;</span><span class="nt">/&gt;</span> 
    <span class="nt">&lt;/OGRVRTLayer&gt;</span>
<span class="nt">&lt;/OGRVRTDataSource&gt;</span>
</pre></div>
<p>In another scenario, my data source was some csv files storing point coordinates in two different columns: I had the need to generate a <a href=" http://www.opengeospatial.org/standards/wms">WMS</a> service with MapServer.</p>
<p>This is an extract of the original datasource (mydata.csv file):</p>
<pre><code>LATITUDE,LONGITUDE, ...
-12.935,142.612, ...
-15.075,141.975, ...
-15.084,141.958, ...
...
</code></pre>
<p>I ended up to use also in this case the virtual driver, without the need to generate a copy of the information in a different file storage (for example as shapefiles):</p>
<div class="pygments_murphy"><pre><span class="nt">&lt;OGRVRTDataSource&gt;</span>
    <span class="nt">&lt;OGRVRTLayer</span> <span class="na">name=</span><span class="s">&quot;mydata&quot;</span><span class="nt">&gt;</span>
        <span class="nt">&lt;SrcDataSource&gt;</span>CSV:/path/to/csv/mydata.csv<span class="nt">&lt;/SrcDataSource&gt;</span>
        <span class="nt">&lt;GeometryType&gt;</span>wkbPoint<span class="nt">&lt;/GeometryType&gt;</span>
        <span class="nt">&lt;LayerSRS&gt;</span>WGS84<span class="nt">&lt;/LayerSRS&gt;</span>
        <span class="nt">&lt;GeometryField</span> <span class="na">encoding=</span><span class="s">&quot;PointFromColumns&quot;</span> <span class="na">x=</span><span class="s">&quot;LONGITUDE&quot;</span> <span class="na">y=</span><span class="s">&quot;LATITUDE&quot;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/OGRVRTLayer&gt;</span>
<span class="nt">&lt;/OGRVRTDataSource&gt;</span>
</pre></div>
<p>Referring to the latter xml file, this virtual dataset is now effectively supported from software using GDAL.</p>
<p>We can obtain information about it by using the <a href=" http://www.gdal.org/ogrinfo.html">ogrinfo</a> command:</p>
<pre><code>$ ogrinfo mydata.vrt -al -ro -fid 900
INFO: Open of `mydata.vrt'
      using driver `VRT' successful.
Layer name: mydata
Geometry: Point
Feature Count: 14771
Extent: (-155.117000, -40.521000) - (153.450000, 67.718000)
Layer SRS WKT:
GEOGCS["WGS 84",
    DATUM["WGS_1984",
        SPHEROID["WGS 84",6378137,298.257223563,
            AUTHORITY["EPSG","7030"]],
        TOWGS84[0,0,0,0,0,0,0],
        AUTHORITY["EPSG","6326"]],
    PRIMEM["Greenwich",0,
        AUTHORITY["EPSG","8901"]],
    UNIT["degree",0.0174532925199433,
        AUTHORITY["EPSG","9108"]],
    AUTHORITY["EPSG","4326"]]
LATITUDE: String (0.0)
LONGITUDE: String (0.0)
...
OGRFeature(MCD14DL.2011273):900
  LATITUDE (String) = -27.387
  LONGITUDE (String) = 139.468
  ...
</code></pre>
<p>Or we could eventually convert it to a different format by using the <a href=" http://www.gdal.org/ogr2ogr.html">ogr2ogr</a> commmand:</p>
<pre><code>$ ogr2ogr mydata mydata.vrt
</code></pre>
<p>By using the OGR virtual datasource driver, it is possible to open the layer in QGIS.</p>
<p>This is how I am using the layer in the MapServer's mapfile to generate a WMS service:</p>
<pre><code>LAYER
    NAME mydata
    TYPE POINT
    DATA mydata
    CONNECTIONTYPE OGR
    CONNECTION "/path/to/data/mydata.vrt"
    STATUS ON
    TEMPLATE     "/path/to/templates/mytemplate.html"
    METADATA
        "wms_title"             "WMS virtual ogr my_data"
        "wms_srs"               "EPSG:4326"
        "wms_extent"            "-180 -90 180 90"
        "wms_enable_request"    "*"
    END
    CLASS
        SYMBOL 'circle'
        SIZE 2
        COLOR        255 0 0
    END
END
</code></pre>
<p>As for virtual format for raster, also for OGR virtual layers there is the possibility to use the GDAL API.<br />
For example here I access to the virtual raster and check how many features are stored in it:</p>
<div class="pygments_murphy"><pre><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">osgeo</span> <span class="kn">import</span> <span class="n">ogr</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">driver</span> <span class="o">=</span> <span class="n">ogr</span><span class="o">.</span><span class="n">GetDriverByName</span><span class="p">(</span><span class="s">&#39;VRT&#39;</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">ds</span> <span class="o">=</span> <span class="n">driver</span><span class="o">.</span><span class="n">Open</span><span class="p">(</span><span class="s">&#39;/path/to/data/mydata.vrt&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">layer</span> <span class="o">=</span> <span class="n">ds</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">layer</span><span class="o">.</span><span class="n">GetFeatureCount</span><span class="p">()</span>
<span class="o">&gt;&gt;&gt;</span> <span class="mi">14771</span>
</pre></div>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[Python for geospatial developers]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2012/02/03/python_for_geospatial_developers/" />
    <id>http://www.paolocorti.net/2012/02/03/python_for_geospatial_developers/</id>
    <updated>2012-02-03T16:15:00Z</updated>
    <published>2012-02-03T16:15:00Z</published>
    <category scheme="None" term="geodjango" />
    <category scheme="None" term="GIS" />
    <category scheme="None" term="shapely" />
    <category scheme="None" term="python" />
    <category scheme="None" term="owslib" />
    <category scheme="None" term="pyproj" />
    <category scheme="None" term="qgis" />
    <category scheme="None" term="mapserver" />
    <category scheme="None" term="mapnik" />
    <category scheme="None" term="fiona" />
    <category scheme="None" term="geopy" />
    <category scheme="None" term="GDAL" />
    <summary type="html"><![CDATA[Python for geospatial developers]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2012/02/03/python_for_geospatial_developers/"><![CDATA[<p>There is a recurring question at <a href=" http://en.wikipedia.org/wiki/Geographic_information_system">GIS</a> mailing lists, forum and at some extent in my 
mailbox: what is the best way to master <a href=" http://www.python.org/">Python</a> for developing geospatial applications?
I myself had this question far away in 2006 when I started switching from proprietary
software to <a href=" http://www.fsf.org/">Open Source</a>, and had identified in Python the way to go.</p>
<p>In this post I will try to quickly summarize what is the best way to go in my opinion.</p>
<h3>Python basics</h3>
<p>If you are completely new to Python, first things to check out, are some very basic 
and popular resources, like these ones:</p>
<ul>
<li><a href="http://docs.python.org/tutorial/">the official Python tutorial</a></li>
<li><a href="http://www.diveintopython.net/">the "Dive into Python book"</a></li>
</ul>
<p>Obviously it does not hurt that they are, like most of resurces I will provide in this
post, free resources like in beer.</p>
<h3>Play with some Python GIS library</h3>
<p>As soon as you have some basic skills for writing simple Python programs, start
using the Python core library with some of the most popular GIS Python libraries, 
choosing the ones that are more relevant to the context of your background:</p>
<ul>
<li><a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPython">GDAL/OGR Python bindings</a></li>
<li><a href="http://trac.gispython.org/lab/wiki/Shapely">shapely</a></li>
<li><a href="https://code.google.com/p/pyproj/">pyproj</a></li>
<li><a href="https://github.com/Toblerity/Fiona">Fiona</a></li>
<li><a href="http://www.qgis.org/wiki/Writing_Python_Plugins">QGIS</a></li>
<li><a href="http://code.google.com/p/geopy/">geopy</a></li>
<li><a href="http://geodjango.org/">geodjango</a></li>
<li><a href=" http://mapfish.org/">MapFish</a></li>
<li><a href="http://trac.gispython.org/lab/wiki/OwsLib">owslib</a></li>
<li><a href="http://mapserver.org/mapscript/python.html">MapServer</a></li>
<li><a href="http://mapnik.org/">Mapnik</a></li>
</ul>
<p>Before even writing any programs, test these Python APIs with a beautiful and 
unique feature of Python:  <a href="http://docs.python.org/tutorial/interpreter.html">the command line interpreter</a></p>
<p>For making it even more powerful, don't forget to check out <a href=" http://ipython.org/">IPython</a> and <a href=" http://pypi.python.org/pypi/ipdb">ipdb</a>.</p>
<h3>Do not complicate things with an IDE, keep it simple</h3>
<p>Don't use heavy IDE, now and later, but keep things simple using basic but powerful 
editors like <a href=" http://www.vim.org/">vi</a> and/or <a href=" http://projects.gnome.org/gedit/">gedit</a>.</p>
<p>They are very light and still both provide features like syntax highlight and 
indentation.</p>
<p>You will still be able to debug code in an excellent manner using pdb, or - 
 even better - ipdb together with IPython.</p>
<h3>Time for something more challenging</h3>
<p>When you will be ready for mastering more challenging stuff in order to become a 
real Python hacker :), these resources are definitely a must-read:</p>
<ul>
<li><a href="http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html">"Code Like a Pythonista: Idiomatic Python"</a></li>
<li><a href="http://python.org/dev/peps/">the  Python Enhancement Proposals (PEPs)</a></li>
<li><a href="http://shop.oreilly.com/product/9780596001674.do">"Python Cookbook" book</a></li>
</ul>
<h3>Some more resources on Python and geospatial software</h3>
<p>Other Python resources, related to the geospatial sphere, worth to be mentioned are:</p>
<ul>
<li>the <a href="http://lists.gispython.org/mailman/listinfo/community">gispython mailing list</a></li>
<li><a href=" http://sgillies.net/">Sean Gillies</a> Blog</li>
<li>the questions tagged "<a href=" http://www.python.org/">Python</a>" @ <a href="http://gis.stackexchange.com/questions/tagged/python">gis.stackexchange</a></li>
<li>the <a href="http://www.packtpub.com/python-geospatial-development/book">"Python Geospatial Development" book</a> from <a href=" http://www.packtpub.com/">Packt</a>. This book gives you
a really nice overview of the main things to know for Python geospatial developers:
nothing you cannot figure out from free web resources, but it is really nice to have all this
packed together in a single book</li>
<li>the <a href="http://www.slideshare.net/capooti/developing-geospatial-software-with-python-part-1">"Developing Geospatial software with Python" presentation</a> that <a href=" http://www.itopen.it/">Alessandro Pasotti</a> and me 
gave at the 2010 Italian GFOSS Day</li>
</ul>
<h3>Some best practices you should adopt</h3>
<p>This is a quick list of best practices you should follow when developing with Python 
(but this is the same for other languages as well!):</p>
<ul>
<li>write documentation using <a href=" http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>, and managing and rendering it with tools like 
<a href=" http://docutils.sourceforge.net/">docutils</a> and <a href=" http://sphinx.pocoo.org/">Sphinx</a></li>
<li>write tests</li>
<li>use a source control management system like <a href=" http://git-scm.com/">git</a> or <a href=" http://mercurial.selenic.com/">Mercurial</a>. If you don't want
to create the SCM infrastructure yourself, use the excellent and free services by 
<a href=" https://github.com/">gitHub</a> and <a href=" https://bitbucket.org/">bitbucket</a></li>
</ul>
<h3>Understand the jargon</h3>
<p>Last but not least, please be sure to have a good understanding of the jargon 
background with <a href="http://www.youtube.com/watch?v=anwy2MPT5RE">these guys</a> :)</p>
<p>Please, if you think I forget anything from this post, send me your feedback and
I will be very happy to integrate it with yours suggestion ;)
Have fun!</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[Playing with the Esri File Geodatabase and the Google Fusion Tables GDAL drivers]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2012/01/10/gdal_19_released/" />
    <id>http://www.paolocorti.net/2012/01/10/gdal_19_released/</id>
    <updated>2012-01-10T20:00:00Z</updated>
    <published>2012-01-10T20:00:00Z</published>
    <category scheme="None" term="GIS" />
    <category scheme="None" term="GFT" />
    <category scheme="None" term="GDAL" />
    <summary type="html"><![CDATA[Playing with the Esri File Geodatabase and the Google Fusion Tables GDAL drivers]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2012/01/10/gdal_19_released/"><![CDATA[<p>Today in the <a href=" http://www.gdal.org">GDAL</a> mailing list <a href="http://home.gdal.org/warmerda/">Frank Warmerdam</a> has announced that GDAL 1.9.0 has finally been <a href="http://lists.osgeo.org/pipermail/gdal-dev/2012-January/031450.html">released</a>.
Being a major new release, it offers many new features, but what I was waiting for is the support for <a href="http://www.gdal.org/ogr/drv_filegdb.html">Esri File GDB</a> and <a href="http://www.gdal.org/ogr/drv_gft.html">Google Fusion Table</a>.
So I couldn't resist to install it and giving a try.</p>
<h3>Using GDAL with Esri File Geodatabase</h3>
<p>For using the File Geodatabase driver I had to dowload the <a href=" http://www.esri.com">Esri</a> File Geodatabase API (you need to be registered for downloading it).</p>
<p>It was then just a matter of setting the value of the library path in the LD_LIBRARY_PATH variable, and using the --with-fgdb GDAL configuration option when configuring before compilation for obtaining support for FGDB in GDAL.</p>
<p>After compilation I could verify that I had this format supported by using the --formats option of the <a href=" http://www.gdal.org/ogrinfo.html">ogrinfo</a> command:</p>
<pre><code>$ ogrinfo --formats
-&gt; "ESRI Shapefile" (read/write)
-&gt; "MapInfo File" (read/write)
...
-&gt; "FileGDB" (read/write)
...
</code></pre>
<p>I could then easily import a <a href=" http://en.wikipedia.org/wiki/Shapefile">Shapefile</a> to a new file <a href=" http://www.esri.com/software/arcgis/geodatabase/index.html">GDB</a>, by using the <a href=" http://www.gdal.org/ogr2ogr.html">ogr2ogr</a> command:</p>
<pre><code>$ ogr2ogr -f "FileGDB" mygdb.gdb ~/data/shapefile/country.shp
</code></pre>
<h3>Support for Google Fusion Tables</h3>
<p><a href=" http://www.google.com/fusiontables/Home/">Google Fusion Tables</a> support is the first cloud storage supported by GDAL natively.
I guess many others drivers will come for other cloud computing storages, but at the moment this is a big plus for Google, if compared to others.</p>
<p>For using the GFT driver, you need to have <a href=" http://curl.haxx.se/">curl</a> on your system, and configuring GDAL with the --with-<a href=" http://curl.haxx.se/">curl</a> option before compiling.</p>
<p>After compilation you can easily verify that your GDAL installation is supporting the GFT format:</p>
<pre><code>$ ogrinfo --formats
-&gt; "ESRI Shapefile" (read/write)
-&gt; "MapInfo File" (read/write)
...
--&gt; "GFT" (read/write)
...
</code></pre>
<p>After installation, I could then import a shapefile straight to the Google cloud, by using the ogr2ogr command with the GFT driver:</p>
<pre><code>$ ogr2ogr -f GFT "GFT:email=myuser@gmail.com password=mypassword" ~/data/shapefile/country.shp
</code></pre>
<p>And as soon as my shapefile was uploaded to the cloud, I could easily <a href="https://www.google.com/fusiontables/DataSource?snapid=S355557avFt">access it with the Google Maps API</a></p>
<p>So, now that we have the GDAL support for this formats, next step will be to support them in the plethora of <a href=" http://en.wikipedia.org/wiki/Geographic_information_system">GIS</a> tools using the GDAL library (<a href=" http://www.qgis.org/">QGIS</a>, <a href=" http://mapserver.gis.umn.edu">MapServer</a>, <a href=" http://geoserver.org/">GeoServer</a>....).</p>
<p>Brilliant!</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[Managing documentation's translations with Open Source tools]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2012/01/05/managing_documentation_translations_with_open_source_tools/" />
    <id>http://www.paolocorti.net/2012/01/05/managing_documentation_translations_with_open_source_tools/</id>
    <updated>2012-01-05T23:00:00Z</updated>
    <published>2012-01-05T23:00:00Z</published>
    <category scheme="None" term="Sphinx" />
    <category scheme="None" term="GIS" />
    <category scheme="None" term="po4a" />
    <category scheme="None" term="reST" />
    <summary type="html"><![CDATA[Managing documentation's translations with Open Source tools]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2012/01/05/managing_documentation_translations_with_open_source_tools/"><![CDATA[<p>Today together with <a href="http://www.faunalia.it/">Paolo Cavallini</a>, I have been trying to figure out a workflow for managing documentation's translations for <a href=" http://www.qgis.org/">QGIS</a>.</p>
<p>There are many tools for managing documentation workflows out there: a common approach to which I have been exposed by following both the <a href=" http://www.python.org/">Python</a> and the <a href=" http://www.osgeo.org/">OSGeo</a> communities is to keep the documentation source files in the <a href=" http://docutils.sourceforge.net/rst.html">reStructured Text</a> markup format, and to generate the end user documentation with tools like <a href=" http://docutils.sourceforge.net/">docutils</a> and <a href=" http://sphinx.pocoo.org/">Sphinx</a> to a bunch of different formats (i.e. html, odt, pdf, latex... just to name a few).</p>
<p>Python documentation itself and two wide spread <a href=" http://en.wikipedia.org/wiki/Geographic_information_system">GIS</a> projects like <a href=" http://mapserver.gis.umn.edu">MapServer</a> and <a href=" http://geoserver.org/">GeoServer</a> are following these workflows. Other projects follow different approaches, for example <a href=" http://www.gdal.org">GDAL</a> and <a href=" http://postgis.refractions.net">PostGIS</a> use <a href=" http://www.docbook.org/">Docbook</a> with <a href=" http://www.stack.nl/~dimitri/doxygen/index.html">Doxygen</a>.</p>
<p>While this formats, workflows and tools (<a href=" http://docutils.sourceforge.net/rst.html">reStructured Text</a>, <a href=" http://docutils.sourceforge.net/">docutils</a>, Sphinx...) are invaluable for managing the documentation of a projects, they do not provide a specific tool for managing the multiple translations of the documentation itself, in the same fashion like the <a href=" http://en.wikipedia.org/wiki/Gettext">gettext</a> tool help developers to manage GUI software localizations.
What is needed in the management of the localization of documentation, is to find a way to manage different versions of each documentation files for each language. But we have a good news here: there is a toolset, from the Perl world, named <a href=" http://po4a.alioth.debian.org/man/man7/po4a.7.php">po4a</a>, that can be combined together with docutils and/or <a href=" http://sphinx.pocoo.org/">Sphinx</a> for this purpose.</p>
<p>In a few words, as suggested at the website, "the whole point of po4a is to make the documentation translation maintainable. The idea is to reuse the gettext methodology to this new field. Like in gettext, texts are extracted from their original locations in order to be presented in a uniform format to the translators. The classical gettext tools help them updating their works when a new release of the original comes out. But to the difference of the classical gettext model, the translations are then re-injected in the structure of the original document so that they can be processed and distributed just like the English version." </p>
<p>So an optimal approach to manage documentation translations could be the combined use of restructured text and po4a. Let's give it a try.</p>
<h3>Setup the environment</h3>
<p>First, let's create an empty .rst file with some content in it. For this purporse you could use <a href="http://docs.geoserver.org/stable/en/user/_sources/introduction/history.txt">this</a> .rst file from the GeoServer documentation sources.
Let's name this file original.rst.</p>
<p>You may render thir .rst file at any time as html by using the docutils rst2html command:</p>
<pre><code>$ rst2html original.rst original.html
</code></pre>
<p>As initial step, we need to create the template of the translation file with the po4a-gettextize command:</p>
<pre><code>$ po4a-gettextize -f text -m original.rst -p translation.pot
</code></pre>
<p>We need to make a copy of this file for each language for which we need to make a translation. Let's create a copy for the Italian translation:</p>
<pre><code>$ cp translation.pot translation.IT.po
</code></pre>
<h3>Translate the files</h3>
<p>Now you can safely translate the translation.IT.po file. You will need to add a translation for each msgid in the msgstr field.
For example, for the first paragraph we will have this translation:</p>
<pre><code>#. type: Plain text
#: original.rst:7
msgid ""
"GeoServer is an open source software server written in Java that allows "
"users to share and edit geospatial data. Designed for interoperability, it "
"publishes data from any major spatial data source using open standards."
msgstr ""
"GeoServer e' un software server Open Source scritto in Java che consente"
"agli utenti di condividere ed editare informazione geografica."
"Sviluppato per l'interoperabilita', consente la pubblicazione di dati"
"da tutte le piu' importanti sorgenti dati usando standard open."
</code></pre>
<h3>Get the translated file</h3>
<p>Finally we can get the translation of the original rst file, by using the po4a-translate command:</p>
<pre><code>$ po4a-translate -f text -m original.rst -p translation.IT.po -l IT.rst -k 40
</code></pre>
<p>You can finally look at the final result, for example by converting the IT.rst file to html using docutils:</p>
<pre><code>$ rst2html IT.rst IT.html
</code></pre>
<p>Open the IT.html file in a web browser, and see yourself the results.</p>
<h3>Mananging updates</h3>
<p>The real value of the po4a toolset is in the fact that it greatly helps to manage the updates to source files to be translated during the life of the project.
Any time the original file is updated/rearranged the user will be able to identify what it needs to be changed on the translation file by using the pro4a-updatepo command:</p>
<pre><code>$ po4a-updatepo -f text -m original.rst -p translation.IT.po
</code></pre>
<p>After running the po4a-updatepo command, the translation.IT.po file will be synced with the original.rst changed file. New paragraphs will be added, and modified paragraphs will be marked by a "fuzzy" tag in the file itself.
For example, if we try to modify the first paragraph of the file, after running the po4a-updatepo command this is what we will get in the translation.IT.po file:</p>
<pre><code>#. type: Plain text
#: original.rst:9
#, fuzzy
msgid ""
"GeoServer is an open source software server written in Java that allows "
"users to share and edit geospatial data. Designed for interoperability, it "
"publishes data from any major spatial data source using open standards "
"(little modification)."
msgstr ""
"GeoServer e' un software server Open Source scritto in Java che consenteagli "
"utenti di condividere ed editare informazione geografica.Sviluppato per "
"l'interoperabilita', consente la pubblicazione di datida tutte le piu' "
"importanti sorgenti dati usando standards open."
</code></pre>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[PostGIS in action]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2011/04/25/postgis-in-action/" />
    <id>http://www.paolocorti.net/2011/04/25/postgis-in-action/</id>
    <updated>2011-04-25T23:00:00Z</updated>
    <published>2011-04-25T23:00:00Z</published>
    <category scheme="None" term="books" />
    <category scheme="None" term="GIS" />
    <category scheme="None" term="Postgres" />
    <category scheme="None" term="PostGIS" />
    <summary type="html"><![CDATA[PostGIS in action]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2011/04/25/postgis-in-action/"><![CDATA[<p><a href="http://www.manning.com/obe/">PostGIS in action</a> has landed: finally a book about <a href=" http://postgis.refractions.net">PostGIS</a>, we were all missing it!<br />
A software project that has a public visibility since almost 10 years, with a large community and a long series of use cases, finally has its deserved book.</p>
<p>I started using PostGIS in 2006 in a situation where the company I were working for at that time had to cut the cost of licenses and maintenance. Opting for FOSS gave us also the possibility to eliminate long administrative times needed to change any of the requirements in the licenses.<br />
But above all, we knew to select a technology that could provide more sustainable conditions as only <a href=" http://www.fsf.org/">Open Source</a> software can provide.<br />
With all this in my mind, I identified in PostGIS (and <a href=" http://www.postgresql.org/">Postgres</a>) a perfect replacement for the system that was in production at that time (based on <a href=" http://www.esri.com/software/arcgis/arcsde/index.html">ArcSDE</a> and MS <a href=" http://www.microsoft.com/sqlserver/en/us/default.aspx">SQL Server</a>): we would have never switch back.</p>
<p>At that time the software was already excellent, but the documentation was not yet at the current level.<br />
Though, there was (and it is still there) an indispensable resource that came handy for requiring help: the mailing list.<br />
And you could count on the fact that at any time of the day, Regina and Leo, the authors of the "PostGIS in Action" book, were there to try to give you an answer or helping you to find one.</p>
<p>Now I have to admit that having this book at that time it would have been a dream!<br />
But even now, after five years of experience and hacks on the best open source spatial database out there, I can safely say that reading the book has given me (and will give me) many benefits.<br />
The reading of the material assembled for this book by the authors that I made during these months of the <a href=" http://www.manning.com/">Manning</a> Early Access Program (Manning is a great publishing company that, as <a href=" http://www.packtpub.com/">Packt</a> and <a href=" http://www.apress.com/">apress</a> gives a great choices of book titles about FOSS) has been impressive.</p>
<p>And now I am here to say that, if at some extent I was thinking to have an extensive knowledge of this excellent open source spatial database, after reading the book of Regina and Leo I realized how actually I was wrong!<br />
I found in the book lots of different ideas, and my knowledge of PostGIS has been definitely improved.<br />
In simple words, I think that the book is an effective reading not only for the experienced developer and <a href=" http://en.wikipedia.org/wiki/Geographic_information_system">GIS</a> analyst, but even people getting started with PostGIS will find many benefits reading it. Any GIS developer or architect willing to do any serious development with PostGIS should have a copy of this book always available around.</p>
<h3>PART I</h3>
<p>The book is an impressive block of over 500 pages, but the reading is always very fluent. It is divided into three parts: the first part describes the base concepts, starting from the definition and the features of a spatial database and following with a description and a brief history of the Postgres and PostGIS projects. Finally it provides a first quick and illuminating example (<strong>Chapter 1</strong>).</p>
<p><strong>Chapter 2</strong> introduces the supported geometry type: here there is an explanation about the aims of the geometry_columns table, about the concept of dimension and spatial reference system (SRID).<br />
Then there is a discussion of the main functions that interact with the geometry_columns table, particularly AddGeometryColumn, DropGeometryColumn, UpdateGeometrySRID and Populate_Geometry_Columns.<br />
The chapter concludes with an overview of the different geometries according to the <a href=" http://www.opengeospatial.org">OGC</a> specification, with a parallel of their description and the use of them within PostGIS: useful examples are given here (as indeed throughout the whole course of the book).</p>
<p>The <strong>third chapter</strong> attempts to illustrate the different approaches for the storage of spatial information (heterogeneous and homogeneous geometry columns), with the pros and cons of each approach.<br />
There is then a description of the concept of inheritance of tables in Postgres and its usefulness.<br />
The chapter concludes with a real use case in which the various approaches described earlier are applied, with an additional description of database rules and triggers.</p>
<p><strong>Chapter 4</strong>, together with chapter 5, possibly constitute the core of the book: there is an extended description of the main spatial functions included with PostGIS.<br />
After a quick overview of geometry constructors functions (ST_GeomFromText, ST_GeomFromEWKT, ST_GeomFromWKB and similiars), the chapter describes the output functions such as ST_AsGML.<br />
It follows a quick description of the main geometric supported formats (WKT, EWKT, WKB, GML, <a href=" http://www.opengeospatial.org/standards/kml">KML</a>, <a href=" http://trac.gispython.org/lab/wiki/GeoJSON">GeoJSON</a>, .. .) and the geometric types conversion functions.<br />
It is then explained which functions to use to project a geometry of a spatial reference system to another and then how to verify the validity of a geometry. Following there is an overview of the measurement functions (ST_Length, ST_Length3D, ST_Area, and ST_Perimeter), functions of decomposition (ST_Box2D, ST_Envelope), the ST_X and ST_Y functions to get the coordinates of points, ST_Boundary and functions to obtain the centroid, the point on surface ant the nth point (ST_Centroid, ST_PointOnSurface, ST_PointN).<br />
Finally the chapter introduces an overview of the functions for collection geometries and multi Breaking down (ST_GeometryN ST_Dump), of the functions of composition (ST_Point and ST_MakePoint for making points, ST_MakePolygon, ST_BuildArea and ST_Polygonize for making polygons, ST_Multi for promoting single to multi geometries) and of the functions for simplification (ST_SnapToGrid, ST_Simplify, and ST_SimplifyPreserveTopology).</p>
<p>In the <strong>fifth chapter</strong>, first the authors introduce the functions of relationship between geometries. Then there is an analysis of functions like ST_Intersects, ST_Contains, ST_Within, ST_Covers, ST_ContainsProperly, ST_Touches, ST_Crosses, ST_Disjoint, ST_Difference, ST_SymDifference.<br />
There is then a description of nearest-neighbor functions like ST_DWithin and ST_Distance.
Finally the chapter concludes with an overview of the functions of equality (ST_Equals, ST_OrderingEquals), and the use of the intersection matrix with ST_Relate.</p>
<p>In <strong>Chapter 6</strong> spatial reference systems are introduced and extensively described. After some theoretical concepts (particularly useful for those who are beginners with GIS), there is a list of considerations about which system to choose to store data on the database, particularly on consequences if you are choosing the WGS 84 lat lon (EPSG: 4326) - a very common choice - and why if you choose such a system it is sometimes preferable to use the new Geography data type available in PostGIS 1.5.<br />
The chapter concludes with some considerations on how to determine the spatial reference system (SRID) of an existing spatial dataset, such as <a href=" http://en.wikipedia.org/wiki/Shapefile">Shapefile</a> from a .prj file.</p>
<p>The first part of the book ends with <strong>Chapter 7</strong>, which describes the tool (from the CLI and UI) available for import and export data from <a href=" http://www.postgresql.org/">PostgreSQL</a> (psql, copy, pgAdmin III, pg_dump and pg_restore ) and PostGIS (shp2pgsql, shp2pgsql-gui, pgsql2shp).<br />
The chapter then introduces the powerful <a href=" http://www.gdal.org/ogr2ogr.html">ogr2ogr</a> command (included in <a href=" http://www.gdal.org">GDAL</a>), some <a href=" http://www.qgis.org/">QGIS</a> tools for loading data in PostGIS, the osm2pgsql command for loading <a href=" http://www.openstreetmap.org">OpenStreetMap</a> data and the pgsql2shp command to export a PostGIS layer to a shapefile.<br />
The descriptions are accompanied with brief and useful tutorials very focused on the concepts.</p>
<h3>PART II</h3>
<p>Part two of the book consists of only two chapters, which describe techniques for solving spatial problems using the features and functions described in previous chapters (Chapter 8) and how to make successful performance tuning (Chapter 9).<br />
<strong>Chapter 8</strong> in particular is divided into techniques for the proximity analysis, data tagging and slicing and splicing of LineString and Polygon.<br />
It closes with a section on how to do a translation, scaling and rotation of a geometry.</p>
<p><strong>Chapter 9</strong> provides an extensive overview on performance tuning to optimize the response time of the database. After a description of the query planner tool for PostgreSQL, there is an overview of the explain plans  and of the importance of choosing the correct keys and indexes.<br />
It follows a description of some typical SQL pattern (subselect, from subselect, self-joins) and how they can impact on performance.<br />
Finally the chapter describes the possible effectiveness of some system settings and functions, and make some remarks on problems generated by the geometries (for example, to avoid invalid geometry, to use simplification of shapes, to remove holes and clustering).</p>
<h3>PART III</h3>
<p>The last part of the book, part three, is possibly the most interesting part, being the most applicative one: it describes the use of PostGIS with other tools and frameworks.</p>
<p>In particular, <strong>Chapter 10</strong> describes how to expand the capabilities of Postgres SQL with add ons such as the TIGER geocoder (specific to U.S. data of U.S. Census), the pgRouting library, which allows the resolution of numerical optimization problems on graphs (shortest path algorithms and traveling salesperson problem) and the extension of functionality of Postgres with another language, such as <a href=" http://www.python.org/">Python</a> or <a href=" http://www.r-project.org/">R</a> (but there is support for many others), by using PLs.<br />
At this point there is an extensive and interesting tutorial that shows the interface with R, the well-known statistical language, through PL/R, to develop stored procedures with statistics functions. The tutorial introduces rgdal as well (the library interface R/GDAL), by which there is an interface to spatial data outside the database.<br />
Python developers will find interesting the following tutorial, that explains how it is possible to extend Postgres using Python libraries with PL/Python. The tutorials shows how to quick access to external data (for example an Excel file) and how to do geocoding (with the googlemaps library, but you could get similar results with <a href=" http://code.google.com/p/geopy/">GeoPy</a> for querying other services like Geonames).</p>
<p><strong>Chapter 11</strong> shows some typical use cases of PostGIS in the development of web applications. After a quick look at some technologies, the authors present a nice tutorial mixing <a href=" http://openlayers.org/">OpenLayers</a> (with <a href=" http://www.geoext.org/">GeoExt</a>), JavaScript and use of OGC services like <a href=" http://www.opengeospatial.org/standards/wms">WMS</a>/<a href=" http://en.wikipedia.org/wiki/Web_Feature_Service">WFS</a> from <a href=" http://mapserver.gis.umn.edu">MapServer</a> and/or <a href=" http://geoserver.org/">GeoServer</a>.<br />
At this point there is another tutorial that shows how you can interact with PostGIS from within <a href=" http://www.php.net">PHP</a> (but the code can be easily adapted to other languages) to dynamically generate a KML file for viewing a PostGIS layer on Google Earth.<br />
There is then an example about how to produce a GeoJSON file dynamically using PHP from a PostGIS table. This GeoJSON dynamically generated is then used for feeding a layer in OpenLayer (within GeoExt).<br />
Obviously, given that the subject of this chapter is very large, this chapter can be regarded only as a quick overview, which must certainly be supplemented by further readings if you are interested in the topic.</p>
<p><strong>Chapter 12</strong> introduces some main Desktop GIS software that works well in conjunction with PostGIS: <a href=" http://www.openjump.org/">OpenJump</a>, QGIS (my favorite), <a href=" http://udig.refractions.net/confluence/display/UDIG/Home">UDig</a> and <a href=" http://www.gvsig.org/">gvSIG</a>.</p>
<p><strong>Chapter 13</strong>, the last one of the book, introduces the new PostGIS Raster module (formerly known as WKT Raster in the first release candidate). This module offers the great possibility to finally manage raster data in PostGIS.<br />
In the current PostGIS version (1.5), you will need to install separately  this module.<br />
In PostGIS 2.0, which should be released in the upcoming weeks, the module will be part of the core software.<br />
The chapter explains how to store and load raster in PostGIS (using the Python raster2pgsql.py utility, which supports input in any format based on GDAL), and major commands necessary to obtain information from raster loaded in the spatial database.<br />
Then there is a full explanation of the purpose of the raster_columns table (similar to geometry_columns table for vector data) and the function AddRasterColumn (similiar to tAddGeometryColumn for vector data).<br />
The book then moves on to an overview of the main functions for raster (ST_Value, ST_BandNoDataValue, ST_SetBandNoDataValue, ST_Envelope, ST_Polygon, ST_ConvexHull, ST_SetGeoReference, ST_SetSRID, ST_SetUpperLeft, ST_SetScale, ST_Intersection). This overview are accompanied with the usual lighting tutorials: in one of them there is an interesting example about how to add the z-coordinate to a LineString from 2D pixel starting from a DEM in the spatial database.<br />
The chapter ends with the explanation of PostGIS raster export to other formats. I guess you will not be surprised to see how it comes back into game again the universal GDAL: through the new "PostGIS WKT Raster" driver (from version 1.7) you will be able to export to the plethora of supported GDAL raster formats.<br />
Other GDAL commands that comes very handy are the well-known <a href=" http://www.gdal.org/gdal_translate.html">gdal_translate</a> command (to perform several operations on raster) and the gdalwarp command (to reproject and warp raster). Finally the chapter shows how to use PostGIS raster from MapServer using the "PostGIS WKT Raster" driver.</p>
<p>The book terminates with four appendices: <strong>Appendix A</strong> shows a series of resources and websites focused on PostGIS.<br />
<strong>Appendix B</strong> provides instructions for installation, compilation and upgrade of Postgres and PostGIS on Linux, Windows and Mac OS X. It also explains how to create your PostGIS template and your first spatial database.<br />
<strong>Appendix C</strong> provides a quick SQL tutorial, for those who come from one a non-relational world (like those of you that have always being using flat files as data sources).<br />
Finally, <strong>Appendix D</strong> provides a brief overview and tutorial on Postgres, to make the reader immediately productive before starting to read the book, if he has never been exposed to this powerful relational database.<br />
</p>
<p>The book has been available since many months as a PDF ebook: now, since a few days, it is finally possible to buy the print book version from the <a href="http://www.manning.com/obe/">Manning web site</a> or <a href="http://www.amazon.com/PostGIS-Action-Regina-Obe/dp/1935182269/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1303395068&amp;sr=8-1">Amazon</a>.<br />
I think anyone of us interested in GIS should get a copy of it: this is one of those books that we will keep with us on our desk for years and to which we will return occasionally to take an extensive read!</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[A quick look at the WFS GDAL Driver]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2011/03/23/a-quick-look-at-the-wfs-gdal-driver/" />
    <id>http://www.paolocorti.net/2011/03/23/a-quick-look-at-the-wfs-gdal-driver/</id>
    <updated>2011-03-23T23:00:00Z</updated>
    <published>2011-03-23T23:00:00Z</published>
    <category scheme="None" term="Python" />
    <category scheme="None" term="WFS" />
    <category scheme="None" term="GIS" />
    <category scheme="None" term="GDAL" />
    <category scheme="None" term="OGR" />
    <summary type="html"><![CDATA[A quick look at the WFS GDAL Driver]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2011/03/23/a-quick-look-at-the-wfs-gdal-driver/"><![CDATA[<p>If you have ever tried to interact with a <a href=" http://en.wikipedia.org/wiki/Web_Feature_Service">WFS</a> (via a browser, or <a href=" http://curl.haxx.se/">curl</a>, or <a href=" http://openlayers.org/">OpenLayers</a> or whatever), you are fully aware that it has alway been a pain to interact with, and until now the only <a href=" http://www.python.org/">Python</a> library that made life simpler was the excellent <a href=" http://trac.gispython.org/lab/wiki/OwsLib">OWSlib</a> by <a href=" http://sgillies.net/">Sean Gillies</a> (that, BTW, will deserve itself another post at this blog in the next weeks).</p>
<p>But since some weeks, from the release of the <a href=" http://www.gdal.org">GDAL</a> version 1.8.0, a new toolset is available to <a href=" http://en.wikipedia.org/wiki/Geographic_information_system">GIS</a> users and developers via the new included GDAL WFS Driver (that will now make good company to the already existing <a href=" http://www.opengeospatial.org/standards/wcs">WCS</a> and <a href=" http://www.opengeospatial.org/standards/wms">WMS</a> GDAL drivers).</p>
<p>Thanks to this driver, GDAL, in particoular the <a href=" http://www.gdal.org/ogr/">OGR</a> part of it (dedicated to vectorial dataset) is fully interoperable with WFS, and a WFS has for both the GDAL command line utilities (<a href=" http://www.gdal.org/ogrinfo.html">ogrinfo</a> and <a href=" http://www.gdal.org/ogr2ogr.html">ogr2ogr</a>) and as well for the GDAL API, the same dignity as other vectorial datasources like <a href=" http://en.wikipedia.org/wiki/Shapefile">Shapefile</a>, <a href=" http://postgis.refractions.net">PostGIS</a> layers, <a href=" http://www.gaia-gis.it/spatialite/">SpatiaLite</a> tables and so on.</p>
<p>Today I finally had some time to give a try to this new driver and I must admit that, as far as I have seen, I am greatly impressed by it!</p>
<h3>Using the WFS driver with GDAL/OGR command line utilities</h3>
<p>The first task I wanted to accomplish was to investigate, query and export some of the WFSs we have packaged here at my job place.</p>
<p>For the first two tasks (investigate, query) the ogrinfo was the perfect tool to use, for the last task (query) I have found in ogr2ogr, as always, an invaluable utility to export (and import in case you are using a <a href=" http://www.opengeospatial.org/standards/wfs">WFS-T</a>!) data from a WFS to the plethora of vectorial formats supported by GDAL.</p>
<p>So in the following lines there are the results of what I got so far.</p>
<h4>Listing the layers of a WFS server</h4>
<p>For getting some information about the layers and their metadata in the WFS layer, ogrinfo is absolutely the way to go:</p>
<pre><code>$ ogrinfo -ro WFS:"http://geohub.jrc.ec.europa.eu/effis/ows"
INFO: Open of `WFS:http://geohub.jrc.ec.europa.eu/effis/ows'
      using driver `WFS' successful.
1: EFFIS:FireNews (Point)
2: EFFIS:Fires30Days (Point)
3: EFFIS:Fires7Days (Point)
4: EFFIS:FiresAll (Point)
5: EFFIS:Hotspots1Day (Point)
6: EFFIS:Hotspots7Days (Point)
7: EFFIS:HotspotsAll (Point)
</code></pre>
<h4>Querying a layer in a WFS server</h4>
<p>Still ogrinfo is a very handy way to query metadata and features in a layer (note how with the -where option it is very handy to filter out features. Note that this can be made also with spatial filters):</p>
<pre><code>$ ogrinfo -ro WFS:"http://geohub.jrc.ec.europa.eu/effis/ows" FiresAll -where "Country = 'PT' AND Area_HA &gt; 200"
INFO: Open of `WFS:http://geohub.jrc.ec.europa.eu/effis/ows'
      using driver `WFS' successful.

Layer name: EFFIS:FiresAll
Geometry: Point
Feature Count: 2
Extent: (-8.280308, 40.457099) - (-7.537176, 42.016641)
Layer SRS WKT:
GEOGCS["WGS 84",
    DATUM["WGS_1984",
        SPHEROID["WGS 84",6378137,298.257223563,
            AUTHORITY["EPSG","7030"]],
        AUTHORITY["EPSG","6326"]],
    PRIMEM["Greenwich",0,
        AUTHORITY["EPSG","8901"]],
    UNIT["degree",0.0174532925199433,
        AUTHORITY["EPSG","9122"]],
    AUTHORITY["EPSG","4326"]]
Geometry Column = the_geom
gml_id: String (0.0)
FireDate: String (0.0)
Country: String (0.0)
Province: String (0.0)
Commune: String (0.0)
Area_HA: Real (0.0)
CountryFul: String (0.0)
Class: String (0.0)
X: Real (0.0)
Y: Real (0.0)
LastUpdate: String (0.0)
OGRFeature(EFFIS:FiresAll):7
  gml_id (String) = FiresAll.7
  FireDate (String) = 06-02-2011
  Country (String) = PT
  Province (String) = Serra da Estrela
  Commune (String) = Gouveia (Sao Pedro)
  Area_HA (Real) = 237
  CountryFul (String) = Portugal
  Class (String) = 30DAYS
  X (Real) = 2841252.28
  Y (Real) = 2101233.83
  LastUpdate (String) = 07-02-2011
  POINT (-7.537176271069066 40.457099360980237)

OGRFeature(EFFIS:FiresAll):10
  gml_id (String) = FiresAll.10
  FireDate (String) = 26-01-2011
  Country (String) = PT
  Province (String) = Minho-Lima
  Commune (String) = Gave
  Area_HA (Real) = 316
  CountryFul (String) = Portugal
  Class (String) = 30DAYS
  X (Real) = 2818227.42
  Y (Real) = 2284948.54
  LastUpdate (String) = 06-02-2011
  POINT (-8.280307882823605 42.016640863507767)
</code></pre>
<h4>Exporting a WFS layer to a shapefile (or to whatever)</h4>
<p>Finally, for exporting some features from a WFS layer to an OGR format like <a href=" http://en.wikipedia.org/wiki/Shapefile">Shapefile</a>, the ubiquitous ogr2ogr did the job with great efficiency:</p>
<pre><code>$ ogr2ogr -f 'ESRI Shapefile' fires WFS:"http://geohub.jrc.ec.europa.eu/effis/ows" FiresAll
</code></pre>
<h3>Using the WFS driver with the  GDAL API bindings</h3>
<p>The real power of GDAL is the API behind it, with which also the command line utilities like ogrinfo and ogr2ogr that we have previously used are written.</p>
<p>For the convenience of the developers, several bindings to different languages are offered (via <a href=" http://www.swig.org/">SWIG</a>).</p>
<p>As far as I am a very big fun of Python, here I will show how, with some simple lines of this language, you can access to the data behind a WFS in the same manner as with other vectorial datasets.</p>
<h4>Accessing to WFS metadata by code</h4>
<p>In this first sample script, I want to show how easy it is to access to the metadata of a WFS server, i.e. the list of the layers, and some of their attributes.</p>
<p>As always the starting point is to create an OGR driver (in this case a WFS one), and then the access to all the classes of the API are just the same like for other OGR drivers (for example for a shapefile).</p>
<p>(sample.py)</p>
<div class="pygments_murphy"><pre><span class="kn">from</span> <span class="nn">osgeo</span> <span class="kn">import</span> <span class="n">ogr</span>
<span class="n">driver</span> <span class="o">=</span> <span class="n">ogr</span><span class="o">.</span><span class="n">GetDriverByName</span><span class="p">(</span><span class="s">&#39;WFS&#39;</span><span class="p">)</span>
<span class="n">wfs</span> <span class="o">=</span> <span class="n">driver</span><span class="o">.</span><span class="n">Open</span><span class="p">(</span><span class="s">&quot;WFS:http://geohub.jrc.ec.europa.eu/effis/ows&quot;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">wfs</span><span class="o">.</span><span class="n">GetLayerCount</span><span class="p">()):</span>
    <span class="n">layer</span> <span class="o">=</span> <span class="n">wfs</span><span class="o">.</span><span class="n">GetLayerByIndex</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
    <span class="n">sr</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">GetSpatialRef</span><span class="p">()</span>
    <span class="k">print</span> <span class="s">&#39;Layer: </span><span class="si">%s</span><span class="s">, Features: </span><span class="si">%s</span><span class="s">, SR: </span><span class="si">%s</span><span class="s">...&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">layer</span><span class="o">.</span><span class="n">GetName</span><span class="p">(),</span> <span class="n">layer</span><span class="o">.</span><span class="n">GetFeatureCount</span><span class="p">(),</span> <span class="n">sr</span><span class="o">.</span><span class="n">ExportToWkt</span><span class="p">()[</span><span class="mi">0</span><span class="p">:</span><span class="mi">50</span><span class="p">])</span>
</pre></div>
<pre><code>$ python sample.py 
Layer: EFFIS:FireNews, Features: 7, SR: GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84"...
Layer: EFFIS:Fires30Days, Features: 14, SR: GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84"...
Layer: EFFIS:Fires7Days, Features: 0, SR: GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84"...
</code></pre>
<h4>Accessing to WFS features by code</h4>
<p>In this second sample script, I am iterating through all the features of a layer and for each feature I get the <a href=" http://en.wikipedia.org/wiki/Json">JSON</a> representation.</p>
<p>(sample2.py)</p>
<div class="pygments_murphy"><pre><span class="kn">from</span> <span class="nn">osgeo</span> <span class="kn">import</span> <span class="n">ogr</span>
<span class="n">driver</span> <span class="o">=</span> <span class="n">ogr</span><span class="o">.</span><span class="n">GetDriverByName</span><span class="p">(</span><span class="s">&#39;WFS&#39;</span><span class="p">)</span>
<span class="n">wfs</span> <span class="o">=</span> <span class="n">driver</span><span class="o">.</span><span class="n">Open</span><span class="p">(</span><span class="s">&quot;WFS:http://geohub.jrc.ec.europa.eu/effis/ows&quot;</span><span class="p">)</span>
<span class="n">layer</span> <span class="o">=</span> <span class="n">wfs</span><span class="o">.</span><span class="n">GetLayerByName</span><span class="p">(</span><span class="s">&#39;FiresAll&#39;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">feature</span> <span class="ow">in</span> <span class="n">layer</span><span class="p">:</span>
    <span class="k">print</span> <span class="s">&#39;Json representation for Feature: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">feature</span><span class="o">.</span><span class="n">GetFID</span><span class="p">()</span>
    <span class="k">print</span> <span class="n">feature</span><span class="o">.</span><span class="n">ExportToJson</span><span class="p">()</span>
</pre></div>
<pre><code>$ python sample2.py 
Json representation for Feature: 1
{"geometry": {"type": "Point", "coordinates": [-7.0855540000000001, 42.070912999999997]}, "type": "Feature", "properties": {"Province": "Ourense", "Commune": "Gudina, A", "LastUpdate": "11-02-2011", "FireDate": "06-02-2011", "Country": "ES", "Y": 2267694.6600000001, "gml_id": "FiresAll.1", "CountryFul": "Spain", "Area_HA": 55.0, "X": 2915712.1400000001, "Class": "30DAYS"}, "id": 1}
Json representation for Feature: 2
{"geometry": {"type": "Point", "coordinates": [-7.1695520000000004, 42.141610999999997]}, "type": "Feature", "properties": {"Province": "Ourense", "Commune": "Viana do Bolo", "LastUpdate": "11-02-2011", "FireDate": "06-02-2011", "Country": "ES", "Y": 2276947.27, "gml_id": "FiresAll.2", "CountryFul": "Spain", "Area_HA": 58.0, "X": 2910589.8399999999, "Class": "30DAYS"}, "id": 2}
</code></pre>
<p>So far as I have seen, once again GDAL reveals itself an invaluable toolsets and API that any serious GIS developers should master.</p>
<p>Brilliant!</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[Compiling GDAL with Oracle Spatial support]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2011/03/22/compiling-gdal-with-oracle-support/" />
    <id>http://www.paolocorti.net/2011/03/22/compiling-gdal-with-oracle-support/</id>
    <updated>2011-03-22T17:00:00Z</updated>
    <published>2011-03-22T17:00:00Z</published>
    <category scheme="None" term="Oracle Spatial" />
    <category scheme="None" term="GeoDjango" />
    <category scheme="None" term="GIS" />
    <category scheme="None" term="GDAL" />
    <summary type="html"><![CDATA[Compiling GDAL with Oracle Spatial support]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2011/03/22/compiling-gdal-with-oracle-support/"><![CDATA[<p>These are my quick notes for installing <a href=" http://www.oracle.com">Oracle</a> Instant Client on a Linux box (currently I have tested this on a <a href=" http://www.ubuntu.com/">Ubuntu</a> 10.10 64 bit box and with Oracle 11.2 and <a href=" http://www.gdal.org">GDAL</a> 1.8.0), and then configuring GDAL for using Oracle (<a href=" http://www.gdal.org/ogr/drv_oci.html">OCI</a> and <a href=" http://www.gdal.org/frmt_georaster.html">GeoRaster</a> drivers support).</p>
<p>Finally I will show how to configure <a href=" http://geodjango.org/">GeoDjango</a> to use an Oracle spatial database by using the <a href=" http://cx-oracle.sourceforge.net/">Cx_Oracle</a> <a href=" http://www.python.org/">Python</a> library.</p>
<h3>Installation of Oracle Instant Client</h3>
<p>First download Oracle Client files from <a href="http://www.oracle.com/technetwork/topics/linuxsoft-082809.html">here</a>  or <a href="http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html">here if you are on a 64 bit architecture</a>.</p>
<p>You need to download the following 3 zip archives:</p>
<pre><code>~/software/oracle$ ls
instantclient-basic-linux-x86-64-11.2.0.2.0.zip  instantclient-sdk-linux-x86-64-11.2.0.2.0.zip  instantclient-sqlplus-linux-x86-64-11.2.0.2.0.zip
</code></pre>
<p>Then extract the archives to a location you prefer:</p>
<pre><code>~/software/oracle$ unzip instantclient-basic-linux-x86-64-11.2.0.2.0.zip 
~/software/oracle$ unzip instantclient-sqlplus-linux-x86-64-11.2.0.2.0.zip 
~/software/oracle$ unzip instantclient-sdk-linux-x86-64-11.2.0.2.0.zip
</code></pre>
<p>You then need to set the following environment variables, for example editing the .bashrc file in your home directory:</p>
<pre><code>nano ~/.bashrc

...
# Oracle (OCI)
export ORACLE_HOME=/home/pcorti/software/oracle/instantclient_11_2
export PATH=$PATH:$ORACLE_HOME
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME
</code></pre>
<p>Finally create the following soft links:</p>
<pre><code>~/software/oracle$ cd $ORACLE_HOME
~/software/oracle/instantclient_11_2$ ln -s libclntsh.so.11.1 libclntsh.so
</code></pre>
<p>You should be able now to connect to an Oracle database with the SQL*Plus Instant Client:</p>
<pre><code>sqlplus hr/your_password@//mymachine.mydomain:port/MYDB
SQL&gt; SELECT * FROM MYTABLE;
...
</code></pre>
<h3>Installation of GDAL with OCI and GeoRaster support</h3>
<p>For compiling GDAL with OCI and GeoRaster support, you first need to add this soft link:</p>
<pre><code>cd $ORACLE_HOME
~/software/oracle/instantclient_11_2$ ln -s . lib
</code></pre>
<p>Now <a href="http://download.osgeo.org/gdal/gdal-1.8.0.tar.gz">download</a>, extract, configure and compile GDAL, for example:</p>
<pre><code>./configure --with-oci-include=/home/pcorti/software/oracle/instantclient_11_2/sdk/include --with-oci-lib=/home/pcorti/software/oracle/instantclient_11_2 --with-python --with-pg
make
sudo make install
</code></pre>
<p>when configuring make sure OCI and <a href=" http://www.gdal.org/frmt_georaster.html">GeoRaster</a> are enabled:</p>
<pre><code>OCI support:               yes
GEORASTER support:         yes
</code></pre>
<p>After installing make sure you have OCI and GeoRaster as supported formats:</p>
<pre><code>:~/training/gdal/oracle$ ogr2ogr --formats
Supported Formats:
  -&gt; "ESRI Shapefile" (read/write)
    ...
  -&gt; "OCI" (read/write)
    ...

~/training/gdal/oracle$ gdalinfo --formats
Supported Formats:
  VRT (rw+v): Virtual Raster
  GTiff (rw+v): GeoTIFF
  ...
  GeoRaster (rw+): Oracle Spatial GeoRaster
  ..
</code></pre>
<h3>Testing GDAL and Oracle</h3>
<p>Finally some GDAL tests with Oracle. We will use a connection string composed in this way:</p>
<pre><code>OCI:user/password@server:port/schema:table
</code></pre>
<h4>Sample 1: export from an Oracle table to a shapefile:</h4>
<pre><code>$ ogr2ogr -f "ESRI Shapefile" test.shp OCI:user/password@server:port/schema:MY_TABLE
</code></pre>
<h4>Sample 2: import in a Oracle table from a shapefile</h4>
<pre><code>$ ogr2ogr -f OCI OCI:user/password@server:port/schema:MY_TABLE2 test.shp
</code></pre>
<h4>Sample 3: how to get information about an Oracle table:</h4>
<pre><code>$ ~/training/gdal/oracle$ ogrinfo -al -fid 1 OCI:user/password@server:port/schema:MY_TABLE
INFO: Open of `OCI:user/password@server:port/schema:MY_TABLE'
      using driver `OCI' successful.

Layer name: MY_TABLE
Geometry: Unknown (any)
Feature Count: 688
Extent: (-17.116400, 1.040350) - (38.761000, 65.833230)
Layer SRS WKT:
GEOGCS["WGS 84",
    DATUM["World Geodetic System 1984 (EPSG ID 6326)",
        SPHEROID["WGS 84 (EPSG ID 7030)",6378137.0,298.257223563]],
    PRIMEM["Greenwich",0.000000],
    UNIT["Decimal Degree",0.0174532925199433],
    AUTHORITY["EPSG. See 3D CRS for original information source.","4326"]]
Geometry Column = GEOMETRY
ID: Integer (11.0)
PLACE: String (765.0)
...
  POINT (23.7332 35.3379 0)
</code></pre>
<h4>Sample 4: how to create a GeoRaster from a raster</h4>
<pre><code>$ gdal_translate -of georaster input.tif georaster:user/pwd@host:1521/db,out_img,raster
Input file size is 3212, 2148
0...10...20...30...40...50...60...70...80...90...100 - done.
Ouput dataset: (geor:user/pwd@host:1521/db,RDT_72$,72) on RDAPRD.OUT_IMG,RASTER

$ gdalinfo georaster:user/pwd@host:1521/db
Driver: GeoRaster/Oracle Spatial GeoRaster
Files: none associated
Size is 512, 512
Coordinate System is `'
Subdatasets:
  SUBDATASET_3_NAME=geor:user/pwd@host:1521/db,RDAPRD.OUT_IMG
  SUBDATASET_3_DESC=RDAPRD.Table=OUT_IMG
Corner Coordinates:
Upper Left  (    0.0,    0.0)
Lower Left  (    0.0,  512.0)
Upper Right (  512.0,    0.0)
Lower Right (  512.0,  512.0)
Center      (  256.0,  256.0)
</code></pre>
<h3>Configuring GeoDjango for using an Oracle Spatial backend</h3>
<p>Finally, these are my quick notes for using GeoDjango with an Oracle spatial backend.</p>
<p>First you need to install <a href=" http://cx-oracle.sourceforge.net/">Cx_Oracle</a>, a Python db API for Oracle.
The version that is working well for me is cx_Oracle 5.0.1 (current version, 5.1 is throwing an error from Oracle, so I had to downgrade).</p>
<p>For installing cx_Oracle, if, like me, you are in a virtualenv, then just type:</p>
<pre><code>pip install http://sourceforge.net/projects/cx-oracle/files/5.0.1/cx_Oracle-5.0.1.tar.gz/download
</code></pre>
<p>Or, download the source code from the same location and as a sudo run the setup.py file:</p>
<pre><code>sudo python setup.py install
</code></pre>
<p>Finally, in the settings.py file of your GeoDjango application, don't forget to update the database settings:</p>
<pre><code>DATABASES = {
    'default': {
        'ENGINE': 'django.contrib.gis.db.backends.oracle',
        'NAME': 'database',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': 'host',
        'PORT': '1521',
    }
}
</code></pre>
<h3>REFERENCES</h3>
<ul>
<li><a href="http://forums.oracle.com/forums/thread.jspa?messageID=4570333">Oracle Forum</a></li>
<li><a href="http://blog.thinkside.co.uk/?p=218">A blog post from thinkside</a></li>
</ul>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[Why I have moved my blog to Blogofile]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2011/03/09/why-I-have-moved-my-blog-to-blogofile" />
    <id>http://www.paolocorti.net/2011/03/09/why-I-have-moved-my-blog-to-blogofile</id>
    <updated>2011-03-09T19:59:10Z</updated>
    <published>2011-03-09T19:59:10Z</published>
    <category scheme="None" term="Python" />
    <category scheme="None" term="blogofile" />
    <category scheme="None" term="GIS" />
    <summary type="html"><![CDATA[Why I have moved my blog to Blogofile]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2011/03/09/why-I-have-moved-my-blog-to-blogofile"><![CDATA[<p>So, after five years of blogging I have sent <a href="http://oldblog.paolocorti.net/">my Wordpress blog to pension</a> and I have moved my blog to <a href=" http://www.blogofile.com/">Blogofile</a>.</p>
<p>You may wonder why I have moved my blog from a spread and fully featured platform to an almost unknown exotic one.
Basically I wanted to have the following advantages:</p>
<ul>
<li><a href=" http://www.python.org/">Python</a> framework, with the possibility to write in this language plugins and extensions</li>
<li>ability to write my blog posts offline, in a markup format like <a href=" http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a> or <a href=" http://en.wikipedia.org/wiki/Markdown">Markdown</a>, with <a href=" http://www.vim.org/">vi</a></li>
<li>blog system able to generate static content from the posts written in the markup language, in a <a href=" http://sphinx.pocoo.org/">Sphinx</a> fashion, without the overhead of a database and a server language. Note that static also means: highly reliable, secure and inexpensive hosting</li>
<li>possibility to commit the posts to <a href=" http://git-scm.com/">git</a>, and automatically update the blog site after push</li>
</ul>
<p>Thanks to <a href=" http://dougalmatthews.com/">Matthews Dougal</a>, I have found out that Blogofile, by <a href=" http://enigmacurry.com">Ryan McGuire</a>, is an awesome answer to all this request, and I have now became a proudly early adopter of this blog engine.</p>
<p>I am actually using the latest development version from <a href=" https://github.com/">gitHub</a>, and I could easily import all of my blog posts, categories and tags from <a href=" http://wordpress.com/">Wordpress</a> via a Python script included in the source (there is a script also to import from Blogger).
I then converted all posts to markdown (I have found out that it was the easier way to go from html to a markup format, without messing too much the html Wordpress post text).
I did not want to loose the possibility to have comments at my posts, so I have opted to use the excellent <a href=" http://disqus.com/">Disqus</a> service, that let you import your comments from the main blog platforms as well: Blogofile seamless integrates with Disqus comments in your posts.</p>
<p>The only thing that Blogofile could not offer me at this time was the ability to automatically creates links for certain keywords at my post.
I did not want to loose this feature (from <a href="http://wordpress.org/extend/plugins/seo-automatic-links/">SEO Smart Links plugin in Wordpress</a>), and it was quiete easy to write a <a href="https://github.com/EnigmaCurry/blogofile/pull/85">Python filter</a> that is doing the trick for me.</p>
<p>Finally I created a hook in my git repository at my host, this way every time a pull is performed in git, the html of the blog is rebuilt and is live at the website: brilliant!</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[After the GFOSS Day 2010, the Italian FOSS4G event]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2010/11/29/after-the-gfoss-day-2010-the-italian-foss4g-event/" />
    <id>http://www.paolocorti.net/2010/11/29/after-the-gfoss-day-2010-the-italian-foss4g-event/</id>
    <updated>2010-11-29T11:24:10Z</updated>
    <published>2010-11-29T11:24:10Z</published>
    <category scheme="None" term="GIS" />
    <category scheme="None" term="Shapely" />
    <category scheme="None" term="conferences" />
    <category scheme="None" term="Python" />
    <category scheme="None" term="GeoAlchemy" />
    <category scheme="None" term="GeoDjango" />
    <category scheme="None" term="GDAL" />
    <category scheme="None" term="Uncategorized" />
    <summary type="html"><![CDATA[After the GFOSS Day 2010, the Italian FOSS4G event]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2010/11/29/after-the-gfoss-day-2010-the-italian-foss4g-event/"><![CDATA[<p>Last week I have been attending the <a href="http://www.gfoss.it/drupal/gfossday2010">GFOSS Day 2010</a> in <a href="http://www.openstreetmap.org/?lat=42.9562&amp;lon=12.7033&amp;zoom=13&amp;layers=M">Foligno</a>, basically the FOSS4G Italian Event that is held every year.
The conference was split in <a href="http://www.gfoss.it/drupal/gfossday2010/programma">two days</a>: in the first days a good number of workshop and tutorials were given, related to a number of geospatial technologies.
In the second day there were the instutional talks, mostly related on the open data theme.
This year I myself gave two talks at the conference: in the first day, togheter with <a href="http://www.itopen.it/">Alessandro Pasotti</a>, we have been giving an extended tutorial about developing geospatial software with <a href=" http://www.python.org/">Python</a>, here are the slides:</p>
<div style="width:425px" id="__ss_5755093"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/capooti/developing-geospatial-software-with-python-part-1" title="Developing Geospatial software with Python, Part 1">Developing Geospatial software with Python, Part 1</a></strong><object id="__sse5755093" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=pythongispart1-101112083509-phpapp01&amp;stripped_title=developing-geospatial-software-with-python-part-1&amp;userName=capooti"></param><param name="allowFullScreen" value="true"></param><param name="allowScriptAccess" value="always"><embed name="__sse5755093" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=pythongispart1-101112083509-phpapp01&amp;stripped_title=developing-geospatial-software-with-python-part-1&amp;userName=capooti" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></param></object><div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/capooti">Paolo Corti</a>.</div></div>
<p>Basically in the first part, after introducing common groundblocks used by almost any geospatial application for geodata managment (<a href=" http://www.gdal.org">GDAL</a>, <a href=" http://trac.osgeo.org/geos/">GEOS</a>, <a href=" http://trac.osgeo.org/proj">proj</a>.4), I have been talking about the most common Python libraries available for using the functionalities of that groundblocks: <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPython">GDAL Python Bindings</a>, <a href=" http://geodjango.org/">GeoDjango</a>, <a href=" http://trac.gispython.org/lab/wiki/Shapely">Shapely</a> and <a href=" http://www.geoalchemy.org/">GeoAlchemy</a>.
In the second part Alessandro, after introducing commonly used geospatial web services, both standard (<a href=" http://www.opengeospatial.org">OGC</a>) and not standard, has been talking the various Python approach to interact with them with some Python libraries (<a href=" http://trac.gispython.org/lab/wiki/OwsLib">OWSlib</a>, <a href=" http://code.google.com/p/geopy/">GeoPy</a>). He has then been introducing a couple of Python libraries for web mapping (<a href=" http://mapnik.org/">Mapnik</a> and <a href="http://mapserver.org/mapscript/python.html">MapScript</a>) and finally he described the possible kinds of customizing <a href=" http://www.qgis.org/">QGIS</a> and <a href=" http://grass.fbk.eu/">GRASS</a> using Python.</p>
<p>All the material of this tutorial (including the second part and the sample code) is <a href="https://github.com/elpaso/python-gis-workshop">here</a>.</p>
<p>In the second day, I have been presenting the <a href=" http://effis.jrc.ec.europa.eu/">EFFIS</a> (the European Forest Fire Information System), the <a href=" http://en.wikipedia.org/wiki/Geographic_information_system">GIS</a> system I am currently working on here at <a href=" http://ec.europa.eu/dgs/jrc/index.cfm">Joint Research Centre</a>, <a href=" http://ies.jrc.ec.europa.eu/">Institute for Environment and Sustainability</a>: slides are <a href="http://www.gfoss.it/drupal/files/Corti_EFFIS2_0.pdf">here</a> (in Italian).
The presentation was basically an Italian version of the <a href="http://2010.foss4g.org/presentations_show.php?id=3693">talk</a> that my collegue Cristiano Giovando gave at the last FOSS4G in Barcelona.</p>
<p>Some final noteS on the GFOSS Day: the event was a success, with over 150 attenders and an excellent set of talks, workshop and tutorials. The organization was great and I am already looking forward for the next event, possibly the <a href="http://events.unitn.it/foss4g2011">XII GRASS and GFOSS meeting in Trento</a>.</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>None</uri>
    </author>
    <title type="html"><![CDATA[Geocoding in web applications: OpenLayers and geoPy to the rescue!]]></title>
    <link rel="alternate" type="text/html" href="http://www.paolocorti.net/2010/09/17/geocoding-in-web-applications-openlayers-and-geopy-to-the-rescue/" />
    <id>http://www.paolocorti.net/2010/09/17/geocoding-in-web-applications-openlayers-and-geopy-to-the-rescue/</id>
    <updated>2010-09-17T21:00:27Z</updated>
    <published>2010-09-17T21:00:27Z</published>
    <category scheme="None" term="jQuery" />
    <category scheme="None" term="GIS" />
    <category scheme="None" term="Python" />
    <category scheme="None" term="Django" />
    <category scheme="None" term="OpenLayers" />
    <category scheme="None" term="Tutorials" />
    <category scheme="None" term="geopy" />
    <category scheme="None" term="Uncategorized" />
    <summary type="html"><![CDATA[Geocoding in web applications: OpenLayers and geoPy to the rescue!]]></summary>
    <content type="html" xml:base="http://www.paolocorti.net/2010/09/17/geocoding-in-web-applications-openlayers-and-geopy-to-the-rescue/"><![CDATA[<p>In many situations, in your web applications, you will need a feature for geocoding an address, a city, a country...
A possible approach is to use the Javascript API of the main geocoding services (Google Maps, Yahoo! Maps, GeoNames...).
But as I have showed in a <a href="http://www.paolocorti.net/2009/10/14/geocoding-with-geopy/">previous post</a>, if you are using <a href=" http://www.python.org/">Python</a>, there is an excellent API that will take care of this, without Javascript headaches: <a href=" http://code.google.com/p/geopy/">GeoPy</a>.</p>
<p>In this post I will show how to use geoPy, <a href=" http://openlayers.org/">OpenLayers</a> and a bit of <a href=" http://jquery.com/">JQuery</a> to assemble a simple but nice tool for geocoding within OpenLayers.
In my server code I will use <a href=" http://www.djangoproject.com/">Django</a> but you may opt for any Python web framework (<a href=" http://pylonshq.com/">Pylons</a>, <a href=" http://zope.org/">Zope</a>, <a href=" http://turbogears.org/">TurboGears</a>, <a href=" http://www.web2py.com/">web2py</a>...) with very slight modifications to the code.
You could even adapt the Javascript code of this sample (a mix of OpenLayers and jQuery) for using it without geoPy but with a different API (server or Javascript).</p>
<p>Basically this is what the tool will do: typing an address or place in a jQuery dialog, the dialog will be filled with results from three major gecoding services (Google, Yahoo! and GeoNames). Each result will be a link, and clicking on it there will be a zoom at that place in the OpenLayers map.</p>
<img src="http://www.paolocorti.net/wp-content/uploads/2010/09/olandgeopy.png" alt="OpenLayers and geoPy to the rescue!" title="olandgeopy" width="400" />
<p>As suggested we have a mix of client (Javascript) and server (Django) code.
The idea is to expose a Django view accepting a string parameter (the place name to geocode) giving an <a href=" http://en.wikipedia.org/wiki/Xml">xml</a> output like this one:</p>
<div class="pygments_murphy"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot; ?&gt;</span>
<span class="nt">&lt;geoservices&gt;</span>
  <span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;google&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;location</span> <span class="na">lat=</span><span class="s">&quot;42.2057962&quot;</span> <span class="na">lon=</span><span class="s">&quot;13.5203333&quot;</span> <span class="na">name=</span><span class="s">&quot;67048 Rocca di Mezzo L&#39;Aquila, Italy&quot;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;/service&gt;</span>
  <span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;yahoo&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;location</span> <span class="na">lat=</span><span class="s">&quot;42.204762&quot;</span> <span class="na">lon=</span><span class="s">&quot;13.51869&quot;</span> <span class="na">name=</span><span class="s">&quot;Rocca di Mezzo AQ, Italy, IT&quot;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;location</span> <span class="na">lat=</span><span class="s">&quot;41.96497&quot;</span> <span class="na">lon=</span><span class="s">&quot;13.01067&quot;</span> <span class="na">name=</span><span class="s">&quot;00020 Rocca di Mezzo RM, Italy, IT&quot;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;/service&gt;</span>
  <span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;geonames&quot;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;location</span> <span class="na">lat=</span><span class="s">&quot;42.2058&quot;</span> <span class="na">lon=</span><span class="s">&quot;13.52033&quot;</span> <span class="na">name=</span><span class="s">&quot;Rocca Di Mezzo, IT 67048&quot;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;location</span> <span class="na">lat=</span><span class="s">&quot;42.17704&quot;</span> <span class="na">lon=</span><span class="s">&quot;13.51706&quot;</span> <span class="na">name=</span><span class="s">&quot;Rovere Di Rocca Di Mezzo, IT 67048&quot;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;/service&gt;</span>
<span class="nt">&lt;/geoservices&gt;</span>
</pre></div>
<p>This is the Django view implementing this functionality:</p>
<div class="pygments_murphy"><pre><span class="kn">from</span> <span class="nn">django.shortcuts</span> <span class="kn">import</span> <span class="n">render_to_response</span>
<span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> <span class="n">HttpResponse</span>
<span class="kn">from</span> <span class="nn">django.template</span> <span class="kn">import</span> <span class="n">RequestContext</span>
<span class="kn">from</span> <span class="nn">olgeopy</span> <span class="kn">import</span> <span class="n">settings</span>
<span class="kn">from</span> <span class="nn">xml.dom.minidom</span> <span class="kn">import</span> <span class="n">Document</span>
<span class="kn">from</span> <span class="nn">geopy</span> <span class="kn">import</span> <span class="n">geocoders</span>

<p><span class="k">def</span> <span class="nf">geolocate</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Geolocate an address returning an xml response.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="c"># get address from querystring</span>
    <span class="n">address</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
    <span class="k">if</span> <span class="s">&#39;address&#39;</span> <span class="ow">in</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="p">:</span>
        <span class="n">address</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;address&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span>
    <span class="c"># Create the minidom document</span>
    <span class="n">doc</span> <span class="o">=</span> <span class="n">Document</span><span class="p">()</span>
    <span class="c"># Create the &lt;geoservices&gt; base element</span>
    <span class="n">geoservices</span> <span class="o">=</span> <span class="n">doc</span><span class="o">.</span><span class="n">createElement</span><span class="p">(</span><span class="s">&quot;geoservices&quot;</span><span class="p">)</span>
    <span class="n">doc</span><span class="o">.</span><span class="n">appendChild</span><span class="p">(</span><span class="n">geoservices</span><span class="p">)</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="c"># google</span>
        <span class="n">g</span> <span class="o">=</span> <span class="n">geocoders</span><span class="o">.</span><span class="n">Google</span><span class="p">(</span><span class="n">settings</span><span class="o">.</span><span class="n">GOOGLE_API_KEY</span><span class="p">)</span>
        <span class="n">google_service</span> <span class="o">=</span> <span class="n">get_service_element</span><span class="p">(</span><span class="n">doc</span><span class="p">,</span> <span class="s">&#39;google&#39;</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">address</span><span class="p">)</span>
        <span class="n">geoservices</span><span class="o">.</span><span class="n">appendChild</span><span class="p">(</span><span class="n">google_service</span><span class="p">)</span>
        <span class="c"># yahoo</span>
        <span class="n">y</span> <span class="o">=</span> <span class="n">geocoders</span><span class="o">.</span><span class="n">Yahoo</span><span class="p">(</span><span class="n">settings</span><span class="o">.</span><span class="n">YAHOO_APP_ID</span><span class="p">)</span>
        <span class="n">yahoo_service</span> <span class="o">=</span> <span class="n">get_service_element</span><span class="p">(</span><span class="n">doc</span><span class="p">,</span> <span class="s">&#39;yahoo&#39;</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">address</span><span class="p">)</span>
        <span class="n">geoservices</span><span class="o">.</span><span class="n">appendChild</span><span class="p">(</span><span class="n">yahoo_service</span><span class="p">)</span>
        <span class="c"># geonames</span>
        <span class="n">n</span> <span class="o">=</span> <span class="n">geocoders</span><span class="o">.</span><span class="n">GeoNames</span><span class="p">()</span>
        <span class="n">geonames_service</span> <span class="o">=</span> <span class="n">get_service_element</span><span class="p">(</span><span class="n">doc</span><span class="p">,</span> <span class="s">&#39;geonames&#39;</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">address</span><span class="p">)</span>
        <span class="n">geoservices</span><span class="o">.</span><span class="n">appendChild</span><span class="p">(</span><span class="n">geonames_service</span><span class="p">)</span>
    <span class="k">except</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&#39;Error...&#39;</span>
    <span class="n">resp</span> <span class="o">=</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">doc</span><span class="o">.</span><span class="n">toprettyxml</span><span class="p">(</span><span class="n">indent</span><span class="o">=</span><span class="s">&quot;  &quot;</span><span class="p">),</span> <span class="n">mimetype</span><span class="o">=</span><span class="s">&#39;text/xml&#39;</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">resp</span></p>
<p><span class="k">def</span> <span class="nf">get_service_element</span><span class="p">(</span><span class="n">doc</span><span class="p">,</span> <span class="n">service_name</span><span class="p">,</span> <span class="n">geocoder</span><span class="p">,</span> <span class="n">address</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Generate an xml element for a geolocation service.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="c"># Create the main service element</span>
    <span class="n">service</span> <span class="o">=</span> <span class="n">doc</span><span class="o">.</span><span class="n">createElement</span><span class="p">(</span><span class="s">&quot;service&quot;</span><span class="p">)</span>
    <span class="n">service</span><span class="o">.</span><span class="n">setAttribute</span><span class="p">(</span><span class="s">&quot;name&quot;</span><span class="p">,</span> <span class="n">service_name</span><span class="p">)</span>
    <span class="c"># Get places list from geocoder</span>
    <span class="n">places</span> <span class="o">=</span> <span class="n">geocoder</span><span class="o">.</span><span class="n">geocode</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="n">exactly_one</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
    <span class="c"># Create the location elements for each service</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">place</span> <span class="o">=</span> <span class="n">places</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
            <span class="k">print</span><span class="p">(</span><span class="n">place</span><span class="p">)</span>
            <span class="n">location</span> <span class="o">=</span> <span class="n">doc</span><span class="o">.</span><span class="n">createElement</span><span class="p">(</span><span class="s">&quot;location&quot;</span><span class="p">)</span>
            <span class="n">location</span><span class="o">.</span><span class="n">setAttribute</span><span class="p">(</span><span class="s">&#39;lon&#39;</span><span class="p">,</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">place</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span>
            <span class="n">location</span><span class="o">.</span><span class="n">setAttribute</span><span class="p">(</span><span class="s">&#39;lat&#39;</span><span class="p">,</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">place</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
            <span class="n">location</span><span class="o">.</span><span class="n">setAttribute</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">,</span> <span class="n">place</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
            <span class="n">service</span><span class="o">.</span><span class="n">appendChild</span><span class="p">(</span><span class="n">location</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
            <span class="k">break</span>
    <span class="k">return</span> <span class="n">service</span>
</p></pre></div>
<p>Basically the geolocate view checks if in the request there is the address string to geocode, and then by using the minidom API it creates the output xml.
Note that each location node is built by querying the geocoding service with a geoPy's geocoder object.</p>
<p>On the client side, there will be an html page with an OpenLayers map in it, and the jQuery dialog needed from the application.
This is an extract of it:</p>
<div class="pygments_murphy"><pre><span class="c">&lt;!-- search --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&quot;search-dialog&quot;</span> <span class="na">title=</span><span class="s">&quot;Find a location&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;#&quot;</span> <span class="na">onclick=</span><span class="s">&quot;setResources(map,&#39;{% url geolocate-addresses %}&#39;);jQuery(&#39;#search-dialog&#39;).dialog(&#39;open&#39;); return false&quot;</span><span class="nt">&gt;</span>Find a location<span class="nt">&lt;/a&gt;</span>

<p><span class="c">&lt;!-- Map --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&quot;map-id&quot;</span><span class="nt">&gt;&lt;/div&gt;</span>
</p></pre></div>
<p>At this point, clicking on the search link, the dialog will open, linked to the map, and the Django view will be requested to get the necessary xml.</p>
<p>This is the Javascript code doing the trick:</p>
<div class="pygments_murphy"><pre><span class="kd">var</span> <span class="nx">map</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">urlxml</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">xmlreq</span><span class="p">;</span>

<p><span class="kd">function</span> <span class="nx">getLocations</span><span class="p">(</span><span class="nx">searchtext</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">//search only at least if there are 2 chars</span>
    <span class="k">if</span><span class="p">(</span><span class="nx">searchtext</span><span class="p">.</span><span class="nx">length</span><span class="o">&gt;</span><span class="mi">1</span><span class="p">){</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">xmlreq</span> <span class="o">!=</span> <span class="kc">undefined</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">xmlreq</span><span class="p">.</span><span class="nx">abort</span><span class="p">();</span>
        <span class="p">};</span>
        <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#results&quot;</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="s1">&#39;&lt;br /&gt;&lt;div id=&quot;progress&quot;&gt;&lt;p&gt;Geocoding &#39;</span> <span class="o">+</span> <span class="nx">searchtext</span> <span class="o">+</span> <span class="s1">&#39;...&lt;/p&gt;&lt;/div&gt;&#39;</span><span class="p">);</span>
        <span class="nx">outxml</span> <span class="o">=</span> <span class="nx">urlxml</span> <span class="o">+</span> <span class="nx">searchtext</span><span class="p">;</span>
        <span class="c1">//read xml</span>
        <span class="nx">xmlreq</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
            <span class="nx">type</span><span class="o">:</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span>
            <span class="nx">data</span><span class="o">:</span> <span class="s1">&#39;&#39;</span><span class="p">,</span>
            <span class="nx">url</span><span class="o">:</span> <span class="nx">outxml</span><span class="p">,</span>
            <span class="nx">dataType</span><span class="o">:</span> <span class="s2">&quot;xml&quot;</span><span class="p">,</span>
            <span class="nx">success</span><span class="o">:</span> <span class="nx">parseXml</span>
        <span class="p">});</span>
    <span class="p">}</span>
    <span class="k">else</span><span class="p">{</span>
        <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#results&quot;</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="s1">&#39;No results.&#39;</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span></p>
<p><span class="kd">function</span> <span class="nx">setResources</span><span class="p">(</span><span class="nx">ol_map</span><span class="p">,</span><span class="nx">geocoded_xml</span><span class="p">){</span>
    <span class="nx">map</span> <span class="o">=</span> <span class="nx">ol_map</span><span class="p">;</span>
    <span class="nx">urlxml</span> <span class="o">=</span> <span class="nx">geocoded_xml</span> <span class="o">+</span> <span class="s1">&#39;?address=&#39;</span><span class="p">;</span>
<span class="p">}</span></p>
<p><span class="kd">function</span> <span class="nx">setMapCenter</span><span class="p">(</span><span class="nx">lon</span><span class="p">,</span> <span class="nx">lat</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kd">var</span> <span class="nx">proj</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">OpenLayers</span><span class="p">.</span><span class="nx">Projection</span><span class="p">(</span><span class="s2">&quot;EPSG:4326&quot;</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">point</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">OpenLayers</span><span class="p">.</span><span class="nx">LonLat</span><span class="p">(</span><span class="nx">lon</span><span class="p">,</span> <span class="nx">lat</span><span class="p">);</span>
    <span class="nx">map</span><span class="p">.</span><span class="nx">setCenter</span><span class="p">(</span><span class="nx">point</span><span class="p">.</span><span class="nx">transform</span><span class="p">(</span><span class="nx">proj</span><span class="p">,</span> <span class="nx">map</span><span class="p">.</span><span class="nx">getProjectionObject</span><span class="p">()));</span>
<span class="p">}</span></p>
<p><span class="kd">function</span> <span class="nx">parseXml</span><span class="p">(</span><span class="nx">xml</span><span class="p">)</span>
<span class="p">{</span>
    <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#results&quot;</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="s1">&#39;&lt;br /&gt;&#39;</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">searchtext</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#txtAddress&quot;</span><span class="p">).</span><span class="nx">val</span><span class="p">();</span>
    <span class="c1">//for each service (Google, Yahoo, Geonames...)</span>
    <span class="nx">$</span><span class="p">(</span><span class="nx">xml</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="s2">&quot;service&quot;</span><span class="p">).</span><span class="nx">each</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="kd">var</span> <span class="nx">service_name</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="s2">&quot;name&quot;</span><span class="p">);</span>
        <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#results&quot;</span><span class="p">).</span><span class="nx">append</span><span class="p">(</span><span class="s1">&#39;&lt;strong&gt;Results for &quot;&#39;</span> <span class="o">+</span> <span class="nx">searchtext</span> <span class="o">+</span> <span class="s1">&#39;&quot; from &#39;</span> <span class="o">+</span> <span class="nx">service_name</span> <span class="o">+</span> <span class="s2">&quot;&lt;/strong&gt;:&lt;br /&gt;&quot;</span><span class="p">);</span>
        <span class="c1">//for each location result in that service</span>
        <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="s2">&quot;location&quot;</span><span class="p">).</span><span class="nx">each</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="kd">var</span> <span class="nx">loc_name</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="s2">&quot;name&quot;</span><span class="p">);</span>
            <span class="kd">var</span> <span class="nx">lon</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="s2">&quot;lon&quot;</span><span class="p">);</span>
            <span class="kd">var</span> <span class="nx">lat</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="s2">&quot;lat&quot;</span><span class="p">);</span>
            <span class="nx">html_location</span> <span class="o">=</span> <span class="s1">&#39;&lt;a href=&quot;&quot; OnClick=&quot;javascript:setMapCenter(&#39;</span> <span class="o">+</span> <span class="nx">lon</span> <span class="o">+</span> <span class="s1">&#39;,&#39;</span> <span class="o">+</span> <span class="nx">lat</span> <span class="o">+</span> <span class="s1">&#39;);return false;&quot;&gt;&#39;</span> <span class="o">+</span> <span class="nx">loc_name</span> <span class="o">+</span> <span class="s1">&#39;&lt;/a&gt;&#39;</span><span class="p">;</span>
            <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#results&quot;</span><span class="p">).</span><span class="nx">append</span><span class="p">(</span><span class="nx">html_location</span> <span class="o">+</span> <span class="s2">&quot;&lt;br /&gt;&quot;</span><span class="p">);</span>
        <span class="p">});</span>
        <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#results&quot;</span><span class="p">).</span><span class="nx">append</span><span class="p">(</span><span class="s1">&#39;&lt;br /&gt;&#39;</span><span class="p">);</span>
    <span class="p">});</span>
<span class="p">};</span></p>
<p><span class="nx">$</span><span class="p">.</span><span class="nx">fx</span><span class="p">.</span><span class="nx">speeds</span><span class="p">.</span><span class="nx">_default</span> <span class="o">=</span> <span class="mi">700</span><span class="p">;</span>
<span class="nx">$</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">search_form</span> <span class="o">=</span> <span class="s2">&quot; &lt;/span&gt;
<span class="s2">        &lt;div class=&#39;search-id&#39;&gt; &lt;/span&gt;
<span class="s2">            &lt;div id=&#39;dialog&#39; title=&#39;Geolocated results&#39;&gt; &lt;/span&gt;
<span class="s2">                &lt;form&gt; &lt;/span&gt;
<span class="s2">                    &lt;input id=&#39;txtAddress&#39; type=&#39;text&#39; name=&#39;txtAddress&#39; /&gt; &lt;/span&gt;
<span class="s2">                &lt;/form&gt; &lt;/span&gt;
<span class="s2">            &lt;/div&gt; &lt;/span&gt;
<span class="s2">            &lt;div id=&#39;results&#39;&gt;&lt;/div&gt; &lt;/span&gt;
<span class="s2">        &lt;/div&gt; &lt;/span&gt;
<span class="s2">        &lt;script&gt; &lt;/span&gt;
<span class="s2">            $(&#39;#txtAddress&#39;).keyup(function(e) { &lt;/span&gt;
<span class="s2">                getLocations($(&#39;#txtAddress&#39;).val()); &lt;/span&gt;
<span class="s2">            }); &lt;/span&gt;
<span class="s2">        &lt;/script&gt;&quot;</span>
    <span class="c1">// dialog</span>
    <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#search-dialog&quot;</span><span class="p">).</span><span class="nx">dialog</span><span class="p">({</span>
        <span class="nx">autoOpen</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
        <span class="nx">autoClose</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
        <span class="nx">show</span><span class="o">:</span> <span class="s1">&#39;blind&#39;</span><span class="p">,</span>
        <span class="nx">hide</span><span class="o">:</span> <span class="s1">&#39;explode&#39;</span><span class="p">,</span>
        <span class="nx">height</span><span class="o">:</span> <span class="mi">300</span><span class="p">,</span>
        <span class="nx">width</span><span class="o">:</span> <span class="mi">400</span><span class="p">,</span>
        <span class="nx">zIndex</span><span class="o">:</span> <span class="mi">4000</span>
    <span class="p">});</span>
    <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#search-dialog&#39;</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="nx">search_form</span><span class="p">);</span>
  <span class="p">});</span>
</span></span></span></span></span></span></span></span></span></span></span></span></span></p></pre></div>
<p>Basically, when the search-dialog opens and the user types a search string in the txtAddress input, the getLocations method is invoked.
This method will send an AJAX xml request to the Django view and, in case of success, will parse the xml Django response to compose the geolink list in the dialog.</p>
<p>The complete source code is <a href="http://www.paolocorti.net/wp-content/uploads/2010/09/olgeopy.zip">here</a>, have fun!</p>]]></content>
  </entry>
</feed>

