<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Linfiniti Geo Blog</title>
	<atom:link href="http://linfiniti.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://linfiniti.com</link>
	<description>GIS for Open Source People</description>
	<lastBuildDate>Thu, 02 Sep 2010 08:22:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Welcome to our first employee!</title>
		<link>http://linfiniti.com/2010/09/welcome-to-our-first-employee/</link>
		<comments>http://linfiniti.com/2010/09/welcome-to-our-first-employee/#comments</comments>
		<pubDate>Thu, 02 Sep 2010 08:22:10 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[QGIS]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=549</guid>
		<description><![CDATA[This week we have taken on our first employee! Samantha Booysen will be working as office manager. She will keep things running smoothly so that the geek in residence can focus on coding. She is all set up with an Ubuntu computer to do her work on and we will include her on our training [...]]]></description>
			<content:encoded><![CDATA[<p>This week we have taken on our first employee! Samantha Booysen will be working as office manager. She will keep things running smoothly so that the geek in residence can focus on coding. She is all set up with an Ubuntu computer to do her work on and we will include her on our training courses so that she starts to learn about FOSS GIS too. Samantha doesn&#8217;t have an IT background but she is very interested in social upliftment which is something close to our hearts here at Linfiniti so we are sure she will fit right in. Welcome Samantha, we hope you enjoy working here!</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4950295567/"><img src="http://farm5.static.flickr.com/4095/4950295567_c3375b80f3_m.jpg"></a></p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=549&amp;ts=1283493828" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/09/welcome-to-our-first-employee/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A week in Tanzania</title>
		<link>http://linfiniti.com/2010/09/a-week-in-tanzania/</link>
		<comments>http://linfiniti.com/2010/09/a-week-in-tanzania/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 21:19:54 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[General FOSSGIS]]></category>
		<category><![CDATA[Postgres & PostGIS]]></category>
		<category><![CDATA[QGIS]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=545</guid>
		<description><![CDATA[I spent most of last week in Dar es Salaam, Tanzania. A lovely tropical country in the heart of Africa. I was there as part of a project I am working to create tools for Biodiversity Informatics practitioners. Of course the tools are based on Free Software: Quantum GIS and openModeller. The attendees at the [...]]]></description>
			<content:encoded><![CDATA[<p>I spent most of last week in Dar es Salaam, Tanzania. A lovely tropical country in the heart of Africa. I was there as part of a project I am working to create tools for Biodiversity Informatics practitioners. Of course the tools are based on Free Software:<a href="http://qgis.org"> Quantum GIS</a> and <a href="http://openmodeller.sf.net">openModeller</a>.</p>
<p>The attendees at the workshop were entertained by my <a href="/downloads/FossHighLevel.pdf">talk about what FOSS</a> is and why it is important, an <a href="/downloads/IntroducingQGISShort.pdf">introduction to QGIS slideshow</a> (superbly presented by Marco Hugentobler), and ending with a <a href="/downloads/openModellerIntroduction.pdf">tour of openModellerDesktop</a>. We also did some live demonstrations of QGIS and openModeller, before going on to discuss details about how these tools can be used to support their Biodiversity Informatics workflows. </p>
<p>The meeting was funded by the <a href="http://gbif.org">Global Biodiversity Information Facility (GBIF)</a> with Juan Bello as their representitive, and hosted by the Tanzanian Commission for Science and Technology (COSTECH).</p>
<p>In case you are unfamiliar with the aims of GBIF, they are facilitating the digitisation  (or digitization for our american readers) of the worlds biodiversity records &#8211; herbarium records, museum collections and so on. COSTECH provides the local infrastructure and staff for the &#8216;TanBif&#8217; node in Tanzania.</p>
<p>The meeting also included &#8216;in-country&#8217; experts in the fields of GIS, Meteorology, Ecology, IT and so on. I think for all of the attendees, the concept of FOSS was a real eye-opener. African economies can&#8217;t compare with those in Europe and the USA and the capital outlay for proprietary software that presents an irritation in the Western world is a major burden in the third world. So just knowing that they could dive in and use QGIS was a great revelation.</p>
<p>We finished our workshop a little early on the Friday so Marco and I offered to go along to the COSTECH offices and geo-enable their PostgreSQL species occurrence database and install QGIS on their desktop PC&#8217;s running Windows XP. In the space of a couple of hours we were done &#8211; the major part of which was spent showing the TanBif staff members how to bring up the PostGIS layer in QGIS, perform simple queries and make maps. Having spent days in the past trying to get proprietary software like Oracle and Arc*** configured, optimised, licensed and generally usable, I was struck by just how easy and quick it is to get someone up and running with a robust enterprise ready PostGIS geospatial datastore and a user friendly Free Software desktop GIS like QGIS.</p>
<p>Thanks to the friendly Tanzanian folks for their hospitality &#8211; I look forward to my next visit! Here are some piccies from the trip&#8230;</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4932775956/"><img src="http://farm5.static.flickr.com/4078/4932775956_d36c66ec6c_m.jpg"></a></p>
<p>Juan Bello telling us about the cool things you can do with a good Biodiversity Information repository.</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4932772076/"><img src="http://farm5.static.flickr.com/4121/4932772076_9d82a8fe50_m.jpg"></a></p>
<p>The workshop attendees (Marco and Juan out of shot)</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4932178361/"><img src="http://farm5.static.flickr.com/4093/4932178361_7f738b617d_m.jpg"></a><br />
Marco showing Godfrey how to use QGIS to bring up their PostGIS Biodiversity dataset.</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4932768936/"><img src="http://farm5.static.flickr.com/4097/4932768936_771f9b61ae_m.jpg"></a></p>
<p>Godfrey proudly showing off his first map (made with QGIS)!</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4932767362/"><img src="http://farm5.static.flickr.com/4116/4932767362_5ef0b046ec_m.jpg"></a></p>
<p>Marco killing a mosquito &#8211; he became something of an expert!</p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=545&amp;ts=1283493828" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/09/a-week-in-tanzania/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>QGIS Mapserver &#8211; A WMS Server for the masses</title>
		<link>http://linfiniti.com/2010/08/qgis-mapserver-a-wms-server-for-the-masses/</link>
		<comments>http://linfiniti.com/2010/08/qgis-mapserver-a-wms-server-for-the-masses/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 20:18:50 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[QGIS]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=535</guid>
		<description><![CDATA[Marco Hugentobler recently included his QGIS WMS Server work into QGIS trunk. You may have noticed QGIS being mentioned in Paul Ramsey&#8217;s post about the WMS Shootout at OSGEO2010 and thought to yourself &#8220;huh? whats that?&#8221;. Well let me introduce you&#8230;. The QGIS mapserver project implements a WMS server on top of the QGIS libraries [...]]]></description>
			<content:encoded><![CDATA[<p>Marco Hugentobler <a href="http://lists.osgeo.org/pipermail/qgis-developer/2010-August/010731.html">recently included</a> his QGIS WMS Server work into QGIS trunk. You may have noticed QGIS being <a href="http://blog.opengeo.org/2010/08/16/wms-benchmarking/">mentioned in Paul Ramsey&#8217;s post</a> about the WMS Shootout at OSGEO2010 and thought to yourself &#8220;huh? whats that?&#8221;. Well let me introduce you&#8230;.</p>
<blockquote><p>The QGIS mapserver project implements a WMS server on top of the QGIS<br />
libraries (funded by the EU projects Orchestra, Sany and the city of Uster).</p></blockquote>
<p> &#8211; Marco Hugentobler</p>
<h2>Building</h2>
<p>You need to be using QGIS Trunk (or a nightly build with OSGEO4W for Windows users). On my Linux system I needed to install the fast cgi dev files:</p>
<pre>
sudo apt-get install libfcgi-dev
</pre>
<p>Then just recompile and install QGIS. After its built you will find a new item in the bin dir. On my system I build QGIS into ~/apps so my QGIS Server binary was here:</p>
<pre>
/home/timlinux/apps/bin/qgis_mapserv.fcgi
</pre>
<h2>Configuration</h2>
<p>Since I build my QGIS into a non system dir, I had to tell apache about the library path for my CGI. Something like this:</p>
<pre>
  ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
  &lt;Directory "/usr/lib/cgi-bin"&gt;
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
    # Next for QGIS Mapserver
    SetEnv LD_LIBRARY_PATH /home/timlinux/apps/lib
  &lt;/Directory&gt;
</pre>
<p>Next I went to the cgi bin dir:</p>
<pre>
 cd /usr/lib/cgi-bin/
</pre>
<p>And then I made a project directory. The rule is: <strong>one directory per QGIS project you want to serve</strong>.</p>
<pre>
sudo mkdir world
cd world
</pre>
<p>Next I <em>linked</em> in the qgis cgi:</p>
<pre>
sudo ln -s /home/timlinux/apps/bin/qgis_mapserv.fcgi .
</pre>
<p>and then <em>copied</em> in the project file:</p>
<pre>
sudo cp /home/timlinux/gisdata/QGISProjects/world.qgs .
</pre>
<p>Symlinking of the project file may work for you &#8211; check your apache configs to allow symlinking I guess.</p>
<p>One other thing to do is copy the capabilities document into the world directory. Actually the server still works without it but we want to be neat &amp; tidy right?</p>
<pre>
sudo cp /home/timlinux/dev/cpp/qgis/src/mapserver/wms_metadata.xml .
</pre>
<p>Now edit that file and set your details as appopriate.</p>
<p>I guess you are waiting to carry on with the next 25 pages of configuration instructions&#8230;.right? Wrong! Thats all you need to do!</p>
<h2>Testing</h2>
<p>First you want to make a nice QGIS project and save the .qgs file in the project directory as outlined above. Here is what my QGIS project looked like:</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4921277092"><img src="http://farm5.static.flickr.com/4121/4921277092_b419763df8.jpg"/></a></p>
<p>To test you can point your web browser at your server:</p>
<pre>

http://localhost/cgi-bin/world/qgis_mapserv.fcgi?SERVICE=WMS&#038;

    VERSION=1.3.0&#038;REQUEST=GetCapabilities
</pre>
<p>Which makes a capabilities doc something like this:</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4921277062"><img src="http://farm5.static.flickr.com/4141/4921277062_d00ef9663b.jpg"/></a></p>
<p>And how about a nice map?</p>
<pre>

http://localhost/cgi-bin/world/qgis_mapserv.fcgi?SERVICE=WMS&#038;VERSION=1.3.0&#038;

REQUEST=GetMap&#038;BBOX=-36.215710,6.817432,-9.700450,58.551008&#038;
CRS=EPSG:4326&#038;WIDTH=1077&#038;HEIGHT=552&#038;LAYERS=Continent,Country,Cities&#038;
STYLES=,,&#038;FORMAT=image/jpeg&#038;DPI=96
</pre>
<p>Which produced this:</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4921277074/"><img src="http://farm5.static.flickr.com/4140/4921277074_98a83ce14c.jpg"/></a></p>
<p>And just to be really meta, lets load the WMS source back into QGIS from where it started!</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4921277084/"><img src="http://farm5.static.flickr.com/4080/4921277084_1d97fe60be.jpg"></a></p>
<p>You see the map renders <strong>exactly</strong> the same as our original project &#8211; marvelous!</p>
<h2>Things to note</h2>
<ul>
<li>The project should use relative paths (see project properties dialog)&#8230;or better yet load your data into PostGIS and forget shapefiles.</li>
<li>Dont forget to copy over your capabilities document and edit it with appropriate details</li>
<li>This is <strong>not</strong> a &#8216;robotosed&#8217; GUI ala early versions of ArcIMS which took over your desktop application. Its a full &#8216;headless&#8217; cgi web service.</li>
<li>You can use all the nice new symbology and labelling features of QGIS to make top quality maps</li>
</ul>
<p>Thanks to Marco (and those who sponsored him)!</p>
<h2>Addendum to notes added Aug 23, 11:17pm (provided by Andreas Neuman)</h2>
<p>* QGIS Mapserver (or however it will be called) implements WMS 1.3 only (not WMS 1.1.1)<br />
* GetFeatureInfo should support: text, html, xml<br />
* GetFeatureInfo honors some of the attribute settings of a QGIS layer: hidden attributes are suppressed, column aliases are used if present.<br />
* When doing the GetCapabilities, the answer can be very slow and big, because for every layer, QGIS will return all available CRS. You can limit this list by using adding the following XML elements to the properties section:</p>
<pre>
&lt;properties&gt;
&lt;WMSEpsgList type="QStringList"&gt;
&lt;value>21781&lt;/value&gt;
&lt;value>4326&lt;/value&gt;
&lt;/WMSEpsgList&gt;
&lt;/properties&gt;
</pre>
<p>QGIS will not remove these settings from the .qgs file after saving it from the desktop version, but currently there is no GUI to do the WMS settings.</p>
<p>* By default, QGIS Mapserver will advertise the maximum extent of all involved layers. This can be overridden by the following setting, again in the
<properties> section of a .qgs file; replace with your own min/max settings:</p>
<pre>
&lt;properties&gt;
&lt;WMSExtent type="QStringList"&gt;
&lt;value>692000&lt;/value&gt;
&lt;value>241500&lt;/value&gt;
&lt;value>700100&lt;/value&gt;
&lt;value>249000&lt;/value&gt;
&lt;/WMSExtent&gt;
&lt;/properties&gt;
</pre>
<p>* GetLegendGraphics should work, e.g. </p>
<pre>

http://yourserver/cgi/qgis_mapserv.fcgi?map=/home/qgisprojects/myproject.qgs&#038;SERVICE=WMS&#038;

REQUEST=GetLegendGraphics&#038;FORMAT=image/png&#038;LAYERS=hydrology&#038;WIDTH=400
</pre>
<p>* QGIS Mapserver can handle multiple project files with one fcgi binary. On a first request of a newly started Apache server, the request will be slower, because the .qgs file has to be parsed, later requests are fast, because there is a cache for more .qgs files. You can use the &#8220;map=/home/path/to/your/project.qgs&#8221; parameter to specify which project you want to access.</p>
<p>It would be nice if we could expose some of the &#8220;hidden&#8221; WMS properties in a GUI, somewhere in the QGIS project properties. Maybe a Server-Settings tab.</p>
<p>Thanks for the additional comments Andreas!</p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=535&amp;ts=1283493829" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/08/qgis-mapserver-a-wms-server-for-the-masses/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Overpainting with Mapnik</title>
		<link>http://linfiniti.com/2010/08/overpainting-with-mapnik/</link>
		<comments>http://linfiniti.com/2010/08/overpainting-with-mapnik/#comments</comments>
		<pubDate>Sat, 21 Aug 2010 21:00:32 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[General FOSSGIS]]></category>
		<category><![CDATA[Postgres & PostGIS]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=529</guid>
		<description><![CDATA[The problem I&#8217;ve been having a little poke around with Mapnik today (awesome software!). One of the things on my todo list has been to sort out rendering issues with roads we have been having. Our last iteration described roads something like this: A style&#8230; &#60;Style name="Freeway30th_style"&#62; &#60;Rule&#62; &#60;LineSymbolizer&#62; &#60;CssParameter name="stroke"&#62;rgb(169,170,153)&#60;/CssParameter&#62; &#60;CssParameter name="stroke-width"&#62;12.26&#60;/CssParameter&#62; &#60;CssParameter name="stroke-linejoin"&#62;bevel&#60;/CssParameter&#62; [...]]]></description>
			<content:encoded><![CDATA[<h2>The problem</h2>
<p>I&#8217;ve been having a little poke around with <a href="http://mapnik.org/">Mapnik</a> today (awesome software!). One of the things on my todo list has been to sort out rendering issues with roads we have been having. Our last iteration described roads something like this:</p>
<p>A style&#8230;</p>
<pre>
    &lt;Style name="Freeway30th_style"&gt;
        &lt;Rule&gt;
            &lt;LineSymbolizer&gt;
                &lt;CssParameter name="stroke"&gt;rgb(169,170,153)&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-width"&gt;12.26&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-linejoin"&gt;bevel&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-linecap"&gt;round&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-opacity"&gt;1&lt;/CssParameter&gt;
            &lt;/LineSymbolizer&gt;
            &lt;LineSymbolizer&gt;
                &lt;CssParameter name="stroke"&gt;rgb(255,172,88)&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-width"&gt;12.16&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-linejoin"&gt;miter&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-linecap"&gt;round&lt;/CssParameter&gt;
            &lt;/LineSymbolizer&gt;
        &lt;/Rule&gt;
    &lt;/Style&gt;
</pre>
<p>&#8230;and this layer definition&#8230;</p>
<pre>
        &lt;Layer name="Freeway30th" srs="+init=epsg:&srid;" maxzoom="39105.90277777778"&gt;
        &lt;StyleName&gt;Freeway30th_style&lt;/StyleName&gt;
        &lt;Datasource&gt;
            &lt;Parameter name="dbname"&gt;&dbname;&lt;/Parameter&gt;
            &lt;Parameter name="estimate_extent"&gt;0&lt;/Parameter&gt;
            &lt;Parameter name="extent"&gt;&extent;&lt;/Parameter&gt;
            &lt;Parameter name="geometry_field"&gt;&#038;geometry_field;&lt;/Parameter&gt;
            &lt;Parameter name="host"&gt;&host;&lt;/Parameter&gt;
            &lt;Parameter name="password"&gt;&password;&lt;/Parameter&gt;
            &lt;Parameter name="port"&gt;&port;&lt;/Parameter&gt;
            &lt;Parameter name="srid"&gt;&srid;&lt;/Parameter&gt;
            &lt;Parameter name="table"&gt;(SELECT * FROM "l_roads" WHERE "type" = \
            'Freeway' ORDER BY LENGTH(&#038;geometry_field;) DESC) as "l_roads"&lt;/Parameter&gt;
            &lt;Parameter name="type"&gt;&#038;datasourcetype;&lt;/Parameter&gt;
            &lt;Parameter name="user"&gt;&password;&lt;/Parameter&gt;
        &lt;/Datasource&gt;
    &lt;/Layer&gt;
</pre>
<p>With the idea being to render freeways with a gray outline and orange center. Unfortunately, it doesnt produce good results:</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4913592225"><img src="http://farm5.static.flickr.com/4139/4913592225_eb4e83322d.jpg"/></a></p>
<p>The problem being those little line ends you see making gray splodges at the end of each segment.</p>
<h2>The solution</h2>
<p>Michael Migurski&#8217;s blog discusses this issue a little <a href="http://mike.teczno.com/notes/mapnik.html">in this article</a> but doesnt directly explain how to achieve the desired effect. So here is what you do:</p>
<p>First the styles are split into two&#8230;</p>
<pre>
     &lt;Style name="Freeway30th_style-bottom"&gt;
        &lt;Rule&gt;
            &lt;LineSymbolizer&gt;
                &lt;CssParameter name="stroke"&gt;rgb(169,170,153)&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-width"&gt;12.26&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-linejoin"&gt;bevel&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-linecap"&gt;round&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-opacity"&gt;1&lt;/CssParameter&gt;
            &lt;/LineSymbolizer&gt;
        &lt;/Rule&gt;
    &lt;/Style&gt;
    &lt;Style name="Freeway30th_style-top"&gt;
        &lt;Rule&gt;
            &lt;LineSymbolizer&gt;
                &lt;CssParameter name="stroke"&gt;rgb(255,172,88)&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-width"&gt;12.16&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-linejoin"&gt;miter&lt;/CssParameter&gt;
                &lt;CssParameter name="stroke-linecap"&gt;round&lt;/CssParameter&gt;
            &lt;/LineSymbolizer&gt;
        &lt;/Rule&gt;
    &lt;/Style&gt;
</pre>
<p>and then the layer is now rendered as two layers, the bottom layer first, then the top:</p>
<pre>
    &lt;Layer name="Freeway30th-bottom" srs="+init=epsg:&srid;" maxzoom="39105.90277777778"&gt;
        &lt;StyleName&gt;Freeway30th_style-bottom&lt;/StyleName&gt;
        &lt;Datasource&gt;
            &lt;Parameter name="dbname"&gt;&dbname;&lt;/Parameter&gt;
            &lt;Parameter name="estimate_extent"&gt;0&lt;/Parameter&gt;
            &lt;Parameter name="extent"&gt;&extent;&lt;/Parameter&gt;
            &lt;Parameter name="geometry_field"&gt;&#038;geometry_field;&lt;/Parameter&gt;
            &lt;Parameter name="host"&gt;&host;&lt;/Parameter&gt;
            &lt;Parameter name="password"&gt;&password;&lt;/Parameter&gt;
            &lt;Parameter name="port"&gt;&port;&lt;/Parameter&gt;
            &lt;Parameter name="srid"&gt;&srid;&lt;/Parameter&gt;
            &lt;Parameter name="table"&gt;(SELECT * FROM "l_roads" WHERE "type" = \
            'Freeway' ORDER BY LENGTH(&#038;geometry_field;) DESC) as "l_roads"&lt;/Parameter&gt;
            &lt;Parameter name="type"&gt;&#038;datasourcetype;&lt;/Parameter&gt;
            &lt;Parameter name="user"&gt;&password;&lt;/Parameter&gt;
        &lt;/Datasource&gt;
    &lt;/Layer&gt;
    &lt;Layer name="Freeway30th-top" srs="+init=epsg:&srid;" maxzoom="39105.90277777778"&gt;
        &lt;StyleName&gt;Freeway30th_style-top&lt;/StyleName&gt;
        &lt;Datasource&gt;
            &lt;Parameter name="dbname"&gt;&dbname;&lt;/Parameter&gt;
            &lt;Parameter name="estimate_extent"&gt;0&lt;/Parameter&gt;
            &lt;Parameter name="extent"&gt;&extent;&lt;/Parameter&gt;
            &lt;Parameter name="geometry_field"&gt;&#038;geometry_field;&lt;/Parameter&gt;
            &lt;Parameter name="host"&gt;&host;&lt;/Parameter&gt;
            &lt;Parameter name="password"&gt;&password;&lt;/Parameter&gt;
            &lt;Parameter name="port"&gt;&port;&lt;/Parameter&gt;
            &lt;Parameter name="srid"&gt;&srid;&lt;/Parameter&gt;
            &lt;Parameter name="table"&gt;(SELECT * FROM "l_roads" WHERE "type" = \
            'Freeway' ORDER BY LENGTH(&#038;geometry_field;) DESC) as "l_roads"&lt;/Parameter&gt;
            &lt;Parameter name="type"&gt;&#038;datasourcetype;&lt;/Parameter&gt;
            &lt;Parameter name="user"&gt;&password;&lt;/Parameter&gt;
         &lt;/Datasource&gt;
    &lt;/Layer&gt;
</pre>
<p><a href="http://www.flickr.com/photos/linfiniti/4913592213"><img src="http://farm5.static.flickr.com/4141/4913592213_684a7fe00f.jpg"/></a></p>
<p>A much cleaner rendering!</p>
<h2>Note</h2>
<p>This approach consumes more cpu time and hits your database harder than the &#8216;messier&#8217; approach shown first.</p>
<p>Also you can see in the example above, I have adopted Michaels approach of rendering long lines first.</p>
<p>Have fun with your mapnik maps!</p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=529&amp;ts=1283493829" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/08/overpainting-with-mapnik/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Introduction to PostGIS</title>
		<link>http://linfiniti.com/2010/08/introduction-to-postgis/</link>
		<comments>http://linfiniti.com/2010/08/introduction-to-postgis/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 21:50:23 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[FOSS Training]]></category>
		<category><![CDATA[Postgres & PostGIS]]></category>
		<category><![CDATA[QGIS]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=527</guid>
		<description><![CDATA[Horst and I are spending the week up in Johannesburg at the Satellite Applications Center in Hartebeeshoek. We are doing yet another week long training course (I hope I&#8217;m not working the poor guy too hard ). This time we are doing: - Two days QGIS (with a little GRASS) - One day PostGIS - [...]]]></description>
			<content:encoded><![CDATA[<p>Horst and I are spending the week up in Johannesburg at the <a href="http://www.csir.co.za/SAC/">Satellite Applications Center</a> in Hartebeeshoek. We are doing yet another week long training course (I hope I&#8217;m not working the poor guy too hard <img src='http://linfiniti.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' />  ). This time we are doing:</p>
<p>- Two days QGIS (with a little GRASS)<br />
- One day PostGIS<br />
- Two days geospatial programming with Bash, Python and QGIS</p>
<p>Tomorrow we start with the PostGIS component. Horst and I have been compiling some course notes for the PostGIS module which we are <a href="/downloads/pgtraining.pdf">making available</a> to the world as per usual. The pdf still has some rendering issues &#8211; we are aware of that. The document tries to walk the reader through the basics of using SQL and then some basic activities with PostGIS and working with geometries.</p>
<p>I hope some of you out there find it useful &#8211; let us know if you do! Also if you have any improvements to make, we&#8217;d love to hear from you. </p>
<p>Here is a quick pic or two from the course:</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4902137471/"><img src="http://farm5.static.flickr.com/4100/4902137471_fc83c4041c_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4902132015/"><img src="http://farm5.static.flickr.com/4080/4902132015_5651e31261_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4902124455/"><img src="http://farm5.static.flickr.com/4079/4902124455_af88d9713f_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4902703040/"><img src="http://farm5.static.flickr.com/4120/4902703040_f8eb2c4816_m.jpg"/></a></p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=527&amp;ts=1283493829" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/08/introduction-to-postgis/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A little bit of Ubuntu eye-candy</title>
		<link>http://linfiniti.com/2010/08/a-little-bit-of-ubuntu-eye-candy/</link>
		<comments>http://linfiniti.com/2010/08/a-little-bit-of-ubuntu-eye-candy/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 21:26:35 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[QGIS]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=525</guid>
		<description><![CDATA[I am always up for a little bit of eye-candy on my desktop. Here is a great theme and icon set: sudo add-apt-repository ppa:tiheum/equinox sudo apt-get update sudo apt-get install gtk2-engines-equinox equinox-theme \ equinox-ubuntu-theme faenza-icon-theme Taken from the original article here.]]></description>
			<content:encoded><![CDATA[<p>I am always up for a little bit of eye-candy on my desktop. Here is a great theme and icon set:</p>
<pre>
sudo add-apt-repository ppa:tiheum/equinox
sudo apt-get update
sudo apt-get install gtk2-engines-equinox equinox-theme \
       equinox-ubuntu-theme faenza-icon-theme
</pre>
<p>Taken from the <a href="http://www.techdrivein.com/2010/08/equinox-gtk-theme-faenza-icon-theme.html">original article here</a>.</p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=525&amp;ts=1283493829" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/08/a-little-bit-of-ubuntu-eye-candy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A QGIS Mass Workshop in Franschhoek, SA</title>
		<link>http://linfiniti.com/2010/08/a-qgis-mass-workshop-in-franschhoek-sa/</link>
		<comments>http://linfiniti.com/2010/08/a-qgis-mass-workshop-in-franschhoek-sa/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 21:05:57 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[QGIS]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=522</guid>
		<description><![CDATA[Today was a great day. Gavin Fleming (http://www.afrispatial.co.za/), Horst Duester (visiting FOSSGIS guru in residence) and myself presented a one day mass QGIS workshop. There were around 110 people present! It was a feat of logistics on the part of Gavin, his wife Bridget and the IT staff and students from the Bridge House school [...]]]></description>
			<content:encoded><![CDATA[<p>Today was a great day. Gavin Fleming (<a href="http://www.afrispatial.co.za/">http://www.afrispatial.co.za/</a>), Horst Duester (visiting FOSSGIS guru in residence) and myself presented a one day mass QGIS workshop. There were around 110 people present! It was a feat of logistics on the part of Gavin, his wife Bridget and the IT staff and students from the Bridge House school (which played host for the day).  60 pcs running Windows were set up and had Jurgen Fischer&#8217;s excellent all-in-one windows installer for QGIS installed on them. People sat &#8216;two up&#8217; at each computer and watched us walk QGIS through the process of loading vector and raster data, digitising data, doing some simple analysis, and producing a print ready map. </p>
<p>A nominal fee or R150 (around USD15) was charged to cover lunch and tea. The remaining profits were donated to the school to sponsor the purchase of some sensors for monitoring river water quality in a local river. The presentors and organisers all donated their time. Those attendees that couldn&#8217;t afford the R150 charge were admitted for free.</p>
<p>To be honest when Gavin proposed admitting around 80 people into the day workshop rather than the originally planned 20 Horst and I thought he was mad (little did we then know the actual turnout would hit 110). But I have to say Gavin and Bridget did a brilliant job and it was such a thrill to look out over a sea of interested and attentive faces all absorbing every morsel of knowledge about QGIS and FOSSGIS they could glean. It definitely left me feeling like it was a worthwhile experience and feeling positive about the demand and interest for FOSSGIS in the Western Cape.</p>
<p>I am off to crash for the night now after a long day, but I will leave you with these pics:</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4892023630/"><img src="http://farm5.static.flickr.com/4074/4892023630_4f2db21d22_z.jpg"/></a><br />
(above photo courtesy H. Duester)</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4891934106/"><img src="http://farm5.static.flickr.com/4096/4891934106_312cc55a96_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891336965/"><img src="http://farm5.static.flickr.com/4098/4891336965_2f74a79e83_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891935900/"><img src="http://farm5.static.flickr.com/4098/4891935900_fc6227ef1d_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891338765/"><img src="http://farm5.static.flickr.com/4117/4891338765_68cb2b19d9_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891339647/"><img src="http://farm5.static.flickr.com/4143/4891339647_22dcdc1bc4_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891938724/"><img src="http://farm5.static.flickr.com/4140/4891938724_6763d96a14_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891341485/"><img src="http://farm5.static.flickr.com/4141/4891341485_f0b3dfdd8a_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891342321/"><img src="http://farm5.static.flickr.com/4077/4891342321_50c57a8d20_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891940862/"><img src="http://farm5.static.flickr.com/4119/4891940862_f0ae25ce9a_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891941676/"><img src="http://farm5.static.flickr.com/4082/4891941676_9a936972dd_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891942448/"><img src="http://farm5.static.flickr.com/4115/4891942448_124016637a_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891345015/"><img src="http://farm5.static.flickr.com/4117/4891345015_01f55b93f6_m.jpg"/></a><br />
<a href="http://www.flickr.com/photos/linfiniti/4891943944/"><img src="http://farm5.static.flickr.com/4073/4891943944_b1c3c8c86b_m.jpg"/></a></p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=522&amp;ts=1283493829" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/08/a-qgis-mass-workshop-in-franschhoek-sa/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A simple QGIS python plugin tutorial</title>
		<link>http://linfiniti.com/2010/08/a-simple-qgis-python-tutorial/</link>
		<comments>http://linfiniti.com/2010/08/a-simple-qgis-python-tutorial/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 13:19:40 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[QGIS]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=510</guid>
		<description><![CDATA[Introduction to Python Plugins and QGIS Note: This tutorial requires QGIS 1.6 (not yet released at time of writing) or QGIS Trunk r14052 (available from osgeo4w as a nightly build or build it yourself on linux from source). Generating your plugin There is an online tool for [creating a plugin http://pyqgis.org/builder/plugin_builder.py]. Simply fill in the [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction to Python Plugins and QGIS</h2>
<p><strong>Note: </strong>This tutorial requires QGIS 1.6 (not yet released at time of writing) or QGIS Trunk r14052 (available from osgeo4w as a nightly build or build it yourself on linux from source).</p>
<h3>Generating your plugin</h3>
<p>There is an online tool for [creating a plugin http://pyqgis.org/builder/plugin_builder.py]. Simply fill in the blanks and it will generate a simple plugin framework for you. We are going to make a simple<br />
plugin to perform a histogram stretch based on the min max values in the current view extents. Lets start by filling in some details in the plugin builder:</p>
<pre>Class name (use CamelCase)     : RasterScale
Short descriptive title        : Raster Local Histogram Stretch
Description                    : Scale the min max of the raster to
                                 the min max within the view.
Version number                 : 0.1
Minimum required QGIS version  : 1.5
Text for the menu item         : Raster
Author/Company name            : Linfiniti Consulting CC
Email address                  : tim@linfiniti.com</pre>
<p>After clicking the &#8216;build it&#8217; link you will see a screen like this:</p>
<pre>Generation complete for RasterScale. You can download it here.
What Next?
Unzip the plugin into your QGIS plugin directory and test it.
Modify it by editing the implementation file RasterScale.py
Create your own custom icon, replacing default icon.png
Modify your user interface by opening RasterScale.ui in
Qt Designer (don't forget to compile it with pyuic4
after changing it)
Use the Makefile to compile your Ui and resource files
if you make changes to them (requires gmake)</pre>
<p>Click the download link and save it to your local disk.</p>
<h3>Testing your plugin</h3>
<p>Use your operating system to extract the plugin to your home directory .qgis folder:</p>
<pre>/home/[yourname]/.qgis/python/plugins/</pre>
<p>If this directory does not already exist, you should create it.</p>
<p>Now open QGIS.</p>
<p>Next do:</p>
<pre>Plugins -&gt; Manage Plugins</pre>
<p>In the filter box enter</p>
<pre>Stretch</pre>
<p>Now tick the box next to the plugin to enable it then click &#8216;OK&#8217;.  An icon will appear in the plugin toolbar and if you click it, your plugin will run!</p>
<h3>Install the plugin reloader plugin in QGIS</h3>
<p>Normally when you change a plugin you have to close and reopen QGIS to see the result of your changes. This can become a little tedious. To work around this, you can install the plugin reloader plugin like this:</p>
<pre>
Start QGIS
Plugins -&gt; Fetch Python Plugins
Repositories tab
Click the 'Add 3rd party repositories button' and click Ok for the message that appears.
Wait a few moments while the repository list is updated.
On the Options tab, check the 'Show all plugins, even those marked experimental' radio button
In the Plugins tab, type reload into the filter box
Select the Plugin Reloader plugin from the list
Click Install, then Ok
</pre>
<p>Now we want to configure the plugin reloader to reload our raster scale plugin so do this:</p>
<pre>
Press Shift+F5
Choose rasterscale from the plugin list
Press Ok
</pre>
<p>Now whenever you press the F5 key, your plugin will be reloaded along with any changes you might have made to it.</p>
<h3>First tweaks to our plugin</h3>
<p>Lets make our first little tweaks to our plugin &#8211; just to test out the development process. Look at the name of your plugin:</p>
<pre>
click Plugins -&gt; Raster
</pre>
<p>In the raster submenu you will see our plugin is named &#8220;Raster&#8220;. Lets rename it to &#8220;Raster Scale&#8220;. To do this, in Eric, open the RasterScale.py file from the list of files in your project on the left. Now look at the initiGui method and change the line that creates the menu action &#8211; it looks like this:</p>
<pre>
self.action = QAction(QIcon(":/plugins/rasterscale/icon.png"), \
"Raster", self.iface.mainWindow())
</pre>
<p>Now change it so that it looks like this:</p>
<pre>
self.action = QAction(QIcon(":/plugins/rasterscale/icon.png"), \
"Raster Scale", self.iface.mainWindow())
</pre>
<p>You will see above that I have simply added the characters &#8216;Scale&#8217; to the QAction&#8217;s name.</p>
<p>Now save that file and go back to QGIS. Hit the &#8220;F5&#8220; key to reload your plugin. Now once again do</p>
<pre>
click Plugins -&gt; Raster
</pre>
<p>You should see the submenu is now named &#8216;Raster Scale&#8217; instead of just &#8216;Raster&#8217;.</p>
<p>This is the general process you should follow when writing a plugin -</p>
<pre>
Edit code

Save source file

Reload plugin in QGIS (F5)

Test
</pre>
<p>In the units that follow we will assume that you do this each time we ask you to modify your plugin sources.</p>
<h3>First steps into the QGIS api</h3>
<p>Writing python plugins in QGIS requires knowledge of three things:</p>
<p>1 Python<br />
2 <a href="http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/classes.html">PyQt</a> &#8211; the Python language bindings for the Qt4 framework<br />
3 The <a href="http://doc.qgis.org/head/">QGIS api</a></p>
<p>A really good resource for learning PyQt is the <a href=" http://www.commandprompt.com/community/pyqt/">command prompt reference</a></p>
<p>Each of these three things is documented and generally searchable with google. We will look at the documentation in a little while. but first lets get our hands dirty and start modifying our plugin.</p>
<p>The first thing I would like to do is outline the functionality that we are going to give our plugin. Here is the logic flow:</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4882425660"><img src="http://farm5.static.flickr.com/4136/4882425660_de036a3d7f_z.jpg"/></a></p>
<h3>Getting and checking the active layer</h3>
<p>As a first step, we are going to replace the run() method in RasterScale.py with our own logic &#8211; the comments in the code explain step for step what is going on:</p>
<pre>
# run method that performs all the real work
def run(self):
  # get the currently active layer (if any)
  layer = self.iface.mapCanvas().currentLayer()
  # test if a valid layer was returned
  if layer:
    # test if the layer is a raster from a local file (not a wms)
    if layer.type() == layer.RasterLayer and ( not layer.usesProvider() ):
      # Test if the raster is single band greyscale
      if layer.rasterType()==QgsRasterLayer.GrayOrUndefined:
        #Everything looks fine so show a little message and exit
        QMessageBox.information(None,"Raster Scale","Layer is ok")
        return
  # One of our tests above failed - show and error message and exit
  QMessageBox.information(None,"Raster Scale", \
      "A single band greyscale raster layer must be selected")
  return
</pre>
<p>Now press F5 in QGIS to reload the plugin (since we have changed its code) and then click the plugin icon with no layers loaded in your project. You should get a message telling you that there needs to be a layer available.</p>
<p>Next add a greyscale raster (e.g. a dem) and then click on the plugin icon again. This time you should get a &#8216;Layer is Ok&#8217; message.</p>
<h3>Computing the min max values within the view extent for the layer</h3>
<p>Now we want to answer the question: &#8216;what is the minimum and maximum value in my current view extent?&#8217; Fortunately its pretty easy to do &#8211; using the raster layer computeMinimumMaximumFromLastExtent method e.g.:</p>
<pre>
# compute the min and max for the current extent
extentMin, extentMax = layer.computeMinimumMaximumFromLastExtent( band )
</pre>
<p>If for example our current view extent contains pixels with values from 20 to 140, extentMin will now be assigned a value of 20 and extentMax will now be assigned a value of 140. The idea is to then scale the colour assigments made to each pixel to this range, such that a pixel of value 20 will be painted black and a pixel of value 140 will be painted white. The image below tries to explain this better:</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4882415924/"><img src="http://farm5.static.flickr.com/4101/4882415924_67bfba72f0.jpg"/></a></p>
<h3>Setting the band min and max values</h3>
<p>Now what we need to do is tell the raster layer to consider the min max values from the current extent to be the min max values for the whole layer, and then to stretch the colour pallette accross the new min/max value range for the layer.</p>
<p>Ok so to do this we can use the following api calls:</p>
<pre>
# For greyscale layers there is only ever one band
band = layer.bandNumber( layer.grayBandName() ) # base 1 counting in gdal
# We don't want to create a lookup table
generateLookupTableFlag = False
# set the layer min value for this band
layer.setMinimumValue( band, extentMin, generateLookupTableFlag );
# set the layer max value for this band
layer.setMaximumValue( band, extentMax, generateLookupTableFlag );
</pre>
<p>This should be self explanatory except maybe the part about a lookup table. Lookup tables are used for creating custom colour pallettes. Since in our case we are not interested in creating a custom colour pallette, we can leave it out of the equation for now by setting it to false.</p>
<h3>Extra house keeping</h3>
<p>Just a little extra house keeping is needed. First we have to ensure that standard deviations are disabled as it will affect the values given to each pixel. Next we let the raster layer know that we are using a user defined min and max range rather than the true range of the data in the raster. Next we clear any cached image for the raster (used to speed up drawing in some situations). Lastly we tell the layer to redraw itself!</p>
<pre>
# ensure that stddev is set to zero
layer.setStandardDeviations( 0.0 );
# let the layer know that the min max are user defined
layer.setUserDefinedGrayMinimumMaximum( True );
# ensure any cached render data for this layer is cleared
layer.setCacheImage( None );
# make sure the layer is redrawn
layer.triggerRepaint();
</pre>
<h3>Putting it all together</h3>
<p>Lets look at our complete run method now:</p>
<pre>
# run method that performs all the real work
def run(self):
  # get the currently active layer (if any)
  layer = self.iface.mapCanvas().currentLayer()
  # test if a valid layer was returned
  if layer:
    # test if the layer is a raster from a local file (not a wms)
    if layer.type() == layer.RasterLayer and ( not layer.usesProvider() ):
      # Test if the raster is single band greyscale
      if layer.rasterType()==QgsRasterLayer.GrayOrUndefined:
        #Everything looks fine so set stretch and exit
        #For greyscale layers there is only ever one band
        band = layer.bandNumber( layer.grayBandName() )
        extentMin = 0.0
        extentMax = 0.0
        generateLookupTableFlag = False
        # compute the min and max for the current extent
        extentMin, extentMax = \
                         layer.computeMinimumMaximumFromLastExtent( band )
        # set the layer min value for this band
        layer.setMinimumValue( band, extentMin, generateLookupTableFlag )
        # set the layer max value for this band
        layer.setMaximumValue( band, extentMax, generateLookupTableFlag )
        # ensure that stddev is set to zero
        layer.setStandardDeviations( 0.0 );
        # let the layer know that the min max are user defined
        layer.setUserDefinedGrayMinimumMaximum( True )
        # ensure any cached render data for this layer is cleared
        layer.setCacheImage( None )
        # make sure the layer is redrawn
        layer.triggerRepaint()
        #QMessageBox.information(None, 'Raster Scale', \
          "Min %s : Max %s" % ( extentMin , extentMax ))
        return
  # One of our tests above failed - show and error message and exit
  QMessageBox.information(None,"Raster Scale", \
        "A single band raster layer must be selected")
  return
</pre>
<h3>Testing</h3>
<p>Refresh the plugin using the plugin reloader F5 keyboard shortcut. Now zoom to an area on your greyscale raster and then click the RasterScale plugin icon. You should see something happen like that shown below:</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4882415928/"><img src="http://farm5.static.flickr.com/4081/4882415928_a3259ab196_z.jpg"/></a><br />
Before scaling</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4882415930"><img src="http://farm5.static.flickr.com/4114/4882415930_33430aabc9_z.jpg"/></a><br />
After scaling</p>
<h3>Exercise</h3>
<p>See if you can update the plugin so that it works for RGB and palletted images too!</p>
<h3> Exercise Solution </h3>
<pre>
/***************************************************************************
RasterScale
A QGIS plugin
Scale the min max of the raster to the min max within the view.
               -------------------
begin        : 2010-08-05
copyright      : (C) 2010 by Linfiniti Consulting CC.
email        : tim@linfiniti.com
 ***************************************************************************/

/***************************************************************************
 *                                     *
 *  This program is free software; you can redistribute it and/or modify *
 *  it under the terms of the GNU General Public License as published by *
 *  the Free Software Foundation; either version 2 of the License, or   *
 *  (at your option) any later version.                  *
 *                                     *
 ***************************************************************************/
"""
# Import the PyQt and QGIS libraries
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *

# Initialize Qt resources from file resources.py
import resources
# Import the code for the dialog
from RasterScaleDialog import RasterScaleDialog

class RasterScale: 

 def __init__(self, iface):
  # Save reference to the QGIS interface
  self.iface = iface

 def initGui(self):
  # Create action that will start plugin configuration
  self.action = QAction(QIcon(":/plugins/rasterscale/icon.png"), \
    "Raster Scale", self.iface.mainWindow())
  # connect the action to the run method
  QObject.connect(self.action, SIGNAL("triggered()"), self.run) 

  # Add toolbar button and menu item
  self.iface.addToolBarIcon(self.action)
  self.iface.addPluginToMenu("&#038;Raster", self.action)

 def unload(self):
  # Remove the plugin menu item and icon
  self.iface.removePluginMenu("&#038;Raster",self.action)
  self.iface.removeToolBarIcon(self.action)

 # run method that performs all the real work
 def run(self):
  # Allowed drawing styles that can have a local histogram stretch:

  allowedGreyStyles = [ QgsRasterLayer.SingleBandGray,
             QgsRasterLayer.MultiBandSingleBandPseudoColor,
             QgsRasterLayer.MultiBandSingleBandGray,
             QgsRasterLayer.SingleBandPseudoColor ]
  allowedRgbStyles = [ QgsRasterLayer.MultiBandColor ]
  # get the currently active layer (if any)
  layer = self.iface.mapCanvas().currentLayer()
  # test if a valid layer was returned
  if layer:
    # test if the layer is a raster from a local file (not a wms)
    if layer.type() == layer.RasterLayer and ( not layer.usesProvider() ):
      # Test if the raster is single band greyscale
      if layer.drawingStyle() in allowedGreyStyles:
        #Everything looks fine so set stretch and exit
        #For greyscale layers there is only ever one band
        band = layer.bandNumber( layer.grayBandName() ) # base 1 counting in gdal
        extentMin = 0.0
        extentMax = 0.0
        generateLookupTableFlag = False
        # compute the min and max for the current extent
        extentMin, extentMax = \
                          layer.computeMinimumMaximumFromLastExtent( band )
        # set the layer min value for this band
        layer.setMinimumValue( band, extentMin, generateLookupTableFlag )
        # set the layer max value for this band
        layer.setMaximumValue( band, extentMax, generateLookupTableFlag )
        # ensure that stddev is set to zero
        layer.setStandardDeviations( 0.0 )
        # let the layer know that the min max are user defined
        layer.setUserDefinedGrayMinimumMaximum( True )
        # ensure any cached render data for this layer is cleared
        layer.setCacheImage( None )
        # make sure the layer is redrawn
        layer.triggerRepaint()
        return
      if layer.drawingStyle() in allowedRgbStyles:
        #Everything looks fine so set stretch and exit
        redBand = layer.bandNumber( layer.redBandName() )
        greenBand = layer.bandNumber( layer.greenBandName() )
        blueBand = layer.bandNumber( layer.blueBandName() )
        extentRedMin = 0.0
        extentRedMax = 0.0
        extentGreenMin = 0.0
        extentGreenMax = 0.0
        extentBlueMin = 0.0
        extentBlueMax = 0.0
        generateLookupTableFlag = False
        # compute the min and max for the current extent
        extentRedMin, extentRedMax = layer.computeMinimumMaximumFromLastExtent( redBand )
        extentGreenMin, extentGreenMax = layer.computeMinimumMaximumFromLastExtent( greenBand )
        extentBlueMin, extentBlueMax = layer.computeMinimumMaximumFromLastExtent( blueBand )
        # set the layer min max value for the red band
        layer.setMinimumValue( redBand, extentRedMin, generateLookupTableFlag )
        layer.setMaximumValue( redBand, extentRedMax, generateLookupTableFlag )
        # set the layer min max value for the red band
        layer.setMinimumValue( greenBand, extentGreenMin, generateLookupTableFlag )
        layer.setMaximumValue( greenBand, extentGreenMax, generateLookupTableFlag )
        # set the layer min max value for the red band
        layer.setMinimumValue( blueBand, extentBlueMin, generateLookupTableFlag )
        layer.setMaximumValue( blueBand, extentBlueMax, generateLookupTableFlag )
        # ensure that stddev is set to zero
        layer.setStandardDeviations( 0.0 )
        # let the layer know that the min max are user defined
        layer.setUserDefinedRGBMinimumMaximum( True )
        # ensure any cached render data for this layer is cleared
        layer.setCacheImage( None )
        # make sure the layer is redrawn
        layer.triggerRepaint()
        return
  # One of our tests above failed - show and error message and exit
  QMessageBox.information(None,"Raster Scale", \
        "A single band raster layer must be selected")
  return
</pre>
<h3>Complete Plugin</h3>
<p>The complete plugin is available <a href="downloads/rasterscale.zip">here</a>. I will add it to a plugin repository once QGIS 1.6 comes out.</p>
<p><b>Updated to remove all those semi-colons from the end of lines&#8230;..</b></p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=510&amp;ts=1283493829" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/08/a-simple-qgis-python-tutorial/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>3 New Case Studies for QGIS</title>
		<link>http://linfiniti.com/2010/08/3-new-case-studies-for-qgis/</link>
		<comments>http://linfiniti.com/2010/08/3-new-case-studies-for-qgis/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 22:32:49 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[QGIS]]></category>
		<category><![CDATA[qgis case studies]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=507</guid>
		<description><![CDATA[Otto Dassau has posted 3 new case studies of QGIS in use in a production environment. It&#8217;s always gratifying to see people using QGIS to run their businesses, do their studies and get on with their daily work. I&#8217;m looking forward to seeing more case studies arrive on the QGIS home page &#8211; if you [...]]]></description>
			<content:encoded><![CDATA[<p>Otto Dassau has posted <a href="http://www.qgis.org/en/community/qgis-case-studies.html">3 new case studies</a> of QGIS in use in a production environment. It&#8217;s always gratifying to see people using QGIS to run their businesses, do their studies and get on with their daily work.</p>
<p>I&#8217;m looking forward to seeing more case studies arrive on the QGIS home page &#8211; if you are doing something interesting with QGIS, do let Otto know about it!</p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=507&amp;ts=1283493829" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/08/3-new-case-studies-for-qgis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A week of FOSSGIS training at Linfiniti</title>
		<link>http://linfiniti.com/2010/08/a-week-of-fossgis-training-at-linfiniti/</link>
		<comments>http://linfiniti.com/2010/08/a-week-of-fossgis-training-at-linfiniti/#comments</comments>
		<pubDate>Sat, 07 Aug 2010 08:27:25 +0000</pubDate>
		<dc:creator>Tim Sutton</dc:creator>
				<category><![CDATA[QGIS]]></category>

		<guid isPermaLink="false">http://linfiniti.com/?p=501</guid>
		<description><![CDATA[Its been another great week here at Linfiniti. Last weekend we (the QGIS project) released QGIS 1.5 Tethys &#8211; its great to have another release out the door. Also making my week a good one was the fact that we ran a week long FOSSGIS course here at Linfiniti HQ in Swellendam, Western Cape, South [...]]]></description>
			<content:encoded><![CDATA[<p>Its been another great week here at Linfiniti. Last weekend we (the QGIS project) <a href="http://blog.qgis.org/node/145/">released QGIS 1.5 Tethys</a> &#8211; its great to have another release out the door. </p>
<p>Also making my week a good one was the fact that we ran a week long FOSSGIS course here at Linfiniti HQ in Swellendam, Western Cape, South Africa. </p>
<p><strong>The Presenter</strong></p>
<p><a href="http://www.flickr.com/photos/linfiniti/4868177644/"><img src="http://farm5.static.flickr.com/4081/4868177644_1ec54326b6_z.jpg"/></a></p>
<p>Horst Duester &#8211; Linfiniti&#8217;s &#8216;FOSSGIS Guru in Residence&#8217; for the months of July and August ran the course. Horst has very kindly donated his time and considerable expertise over his two month sabbatical to the development of FOSSGIS GIS skills in South Africa. The course consisted of 2 days&#8217; QGIS, 3 days PostGIS. With these two projects you can address a huge range of GIS functionality, and having a whole week to dedicate to the topic let Horst really go in depth into the subject. </p>
<p><strong>The Particpants</strong></p>
<p><a href="http://www.flickr.com/photos/linfiniti/4868177646"><img src="http://farm5.static.flickr.com/4095/4868177646_173e2ee9c1_z.jpg"/></a></p>
<p>We had four participants for the course &#8211; all of whom have some experience in GIS in general and who wanted to get a deeper understanding of QGIS and PostGIS.</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4868177642"><img src="http://farm5.static.flickr.com/4122/4868177642_6b0ddf3d54_z.jpg"/></a></p>
<p>Andiswa Silinga works out of Johannesburg where she runs a small business &#8211; GGES (Gemini GIS and Environmental Services) &#8211; which provides GIS solutions to government and enterprise customers. GGES also has special skills in the area of Environmental GIS.</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4868177640"><img src="http://farm5.static.flickr.com/4098/4868177640_8b7bdb7712_z.jpg"/></a></p>
<p>Originally from Zimbabwe, Petronella Tizora was a former intern with Linfiniti consulting. Petronella currently works at GGES with Andiswa and is applying her FOSSGIS skills to her daily work. </p>
<p><a href="http://www.flickr.com/photos/linfiniti/4868177638/"><img src="http://farm5.static.flickr.com/4139/4868177638_2f93b92247_z.jpg"/></a></p>
<p>Sindile Bidla works out of East London in the Eastern Cape, South Africa. Sindile&#8217;s small GIS consulting business Intengu Technologies provides solutions &#8211; he is currently involved in a project to map informal settlements. Sindile formerly worked for the Dept. Land Affairs where he was the principle instigator of the <a href='/dla/'>Gentle Introduction to GIS</a> project which saw the introduction of FOSSGIS into the school curriculum in the Eastern Cape.</p>
<p><a href="http://www.flickr.com/photos/linfiniti/4868177634"><img src="http://farm5.static.flickr.com/4115/4868177634_e8ab285d86_z.jpg"/></a></p>
<p>Brendon runs a small consulting company &#8211; Integrated Geodata &#8211; from his offices in Pretoria, South Africa. Brendon&#8217;s company provides general GIS consulting services, with a special interest in providing services to the water industry.</p>
<p>The course was really well received by the attendees, and Horst thoroughly enjoyed the work of presenting it. It is really gratifying to see how &#8211; with a little training &#8211; FOSSGIS can provide a basis for building sophisticated GIS solutions for the enterprise. Better still it provides these entrepreneurs a fantastic edge &#8211; the ability to offer their clients a solution that has no vendor lock in with maximum value for money.</p>
<p>In the coming months I am planning to formalise the course content developed by Horst and try to increase my focus on training &#8211; the course certainly reaffirmed the notion for me that providing good quality, affordable training is the best way to maximise the penetration of FOSSGIS into the market place.</p>
<img src="http://linfiniti.com/wp-content/plugins/pixelstats/trackingpixel.php?post_id=501&amp;ts=1283493829" style="display:none;" alt="pixelstats trackingpixel"/>]]></content:encoded>
			<wfw:commentRss>http://linfiniti.com/2010/08/a-week-of-fossgis-training-at-linfiniti/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
