<?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>George MacKerron: code blog &#187; GIS</title>
	<atom:link href="http://blog.mackerron.com/category/gis/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mackerron.com</link>
	<description>GIS, software development, and other snippets</description>
	<lastBuildDate>Fri, 03 Feb 2012 18:35:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Polygons from PostGIS to Processing</title>
		<link>http://blog.mackerron.com/2011/11/17/polygons-from-postgis-to-processing/</link>
		<comments>http://blog.mackerron.com/2011/11/17/polygons-from-postgis-to-processing/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 11:28:43 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[GIS]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[Processing]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=942</guid>
		<description><![CDATA[There are plenty of ways to get spatial data from a PostGIS database into a Processing sketch. You can export to CSV or SVG and load it from there; you can query the database directly; or, depending on context, you might choose to generate Processing commands directly, which is the route I went to display [...]]]></description>
			<content:encoded><![CDATA[<p><strong>There are plenty of ways to get spatial data from a PostGIS database into a <a href="http://processing.org/">Processing</a> sketch.</strong></p>

<p>You can export to <span class="caps">CSV </span>or <span class="caps">SVG </span>and load it from there; you can <a href="http://bezier.de/processing/libs/sql/documentation/de/bezier/data/sql/PostgreSQL.html">query the database directly</a>; or, depending on context, you might choose to generate Processing commands directly, which is the route I went to display a background map of the UK in a recent visualization project.</p>

<p><span id="more-942"></span></p>

<p>First, I load outlines of the 4 constituent countries of the UK into my PostGIS database.</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">shp2pgsql <span style="color: #660033;">-d</span> <span style="color: #660033;">-D</span> <span style="color: #660033;">-I</span> <span style="color: #660033;">-s</span> <span style="color: #000000;">27700</span> <span style="color: #ff0000;">&quot;/pgdata/geodata/Nations/england.shp&quot;</span> eng \
  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #660033;">-u</span> postgres psql mappiness
shp2pgsql <span style="color: #660033;">-d</span> <span style="color: #660033;">-D</span> <span style="color: #660033;">-I</span> <span style="color: #660033;">-s</span> <span style="color: #000000;">27700</span> <span style="color: #ff0000;">&quot;/pgdata/geodata/Nations/wales.shp&quot;</span> wal \
  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #660033;">-u</span> postgres psql mappiness
shp2pgsql <span style="color: #660033;">-d</span> <span style="color: #660033;">-D</span> <span style="color: #660033;">-I</span> <span style="color: #660033;">-s</span> <span style="color: #000000;">27700</span> <span style="color: #ff0000;">&quot;/pgdata/geodata/Nations/scotland.shp&quot;</span> sco \
  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #660033;">-u</span> postgres psql mappiness
shp2pgsql <span style="color: #660033;">-d</span> <span style="color: #660033;">-D</span> <span style="color: #660033;">-I</span> <span style="color: #660033;">-s</span> <span style="color: #000000;">27700</span> <span style="color: #ff0000;">&quot;/pgdata/geodata/Nations/nireland_ol_2001.shp&quot;</span> ni \
  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #660033;">-u</span> postgres psql mappiness</pre></div></div>




<p>Next, I combine these into one table, using <code>st_simplifypreservetopology</code> to discard a lot of unnecessary detail and <code>st_dump</code> to dissolve some English <span class="caps">MULTIPOLYGON</span>s into simple <span class="caps">POLYGONS.</span></p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">create</span> <span style="color: #005500;">table</span> uk1km <span style="color: #005500;">as</span> <span style="color: #66cc66;">&#40;</span>
        <span style="color: #005500;">select</span> st_simplifypreservetopology<span style="color: #66cc66;">&#40;</span>the_geom, <span style="color: #cc66cc;">1000</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> the_geom <span style="color: #005500;">from</span> 
          <span style="color: #66cc66;">&#40;</span><span style="color: #005500;">select</span> <span style="color: #66cc66;">&#40;</span>st_dump<span style="color: #66cc66;">&#40;</span>the_geom<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>.geom <span style="color: #005500;">as</span> the_geom <span style="color: #005500;">from</span> eng<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> eng_single
  <span style="color: #005500;">union</span> <span style="color: #005500;">select</span> st_simplifypreservetopology<span style="color: #66cc66;">&#40;</span>the_geom, <span style="color: #cc66cc;">1000</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> the_geom <span style="color: #005500;">from</span> wal
  <span style="color: #005500;">union</span> <span style="color: #005500;">select</span> st_simplifypreservetopology<span style="color: #66cc66;">&#40;</span>the_geom, <span style="color: #cc66cc;">1000</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> the_geom <span style="color: #005500;">from</span> sco
  <span style="color: #005500;">union</span> <span style="color: #005500;">select</span> st_simplifypreservetopology<span style="color: #66cc66;">&#40;</span>the_geom, <span style="color: #cc66cc;">1000</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> the_geom <span style="color: #005500;">from</span> ni
<span style="color: #66cc66;">&#41;</span>;
<span style="color: #005500;">alter</span> <span style="color: #005500;">table</span> uk1km <span style="color: #005500;">add</span> <span style="color: #005500;">column</span> id serial <span style="color: #005500;">primary</span> <span style="color: #005500;">key</span>;
<span style="color: #005500;">drop</span> <span style="color: #005500;">table</span> eng; <span style="color: #005500;">drop</span> <span style="color: #005500;">table</span> wal; <span style="color: #005500;">drop</span> <span style="color: #005500;">table</span> sco; <span style="color: #005500;">drop</span> <span style="color: #005500;">table</span> ni;</pre></div></div>




<p>Finally, I use <code>string_agg</code> to produce the <code>vertex()</code> commands required to reproduce my polygons in Processing. I change the sign on the y-coordinate (from northings to &#8216;southings&#8217;, to match the Processing coordinate space). I scale the <span class="caps">OSGB36 </span>coordinates down from metres to kilometres (I could otherwise have done this with a <code>scale()</code> command in Processing). And I discard a lot of small polygons (comprising 20 <span class="caps">POINT</span>s or fewer) I don&#8217;t need in my output.</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">select</span> <span style="color: #ff0000;">'beginShape(); '</span> 
    <span style="color: #66cc66;">||</span> <span style="color: #333399;">string_agg</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'vertex('</span> <span style="color: #66cc66;">||</span> st_x<span style="color: #66cc66;">&#40;</span>geom<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">', '</span> <span style="color: #66cc66;">||</span> -st_y<span style="color: #66cc66;">&#40;</span>geom<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'); '</span>, <span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'endShape(CLOSE); '</span> 
<span style="color: #005500;">from</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #005500;">select</span> id, <span style="color: #66cc66;">&#40;</span>st_dumppoints<span style="color: #66cc66;">&#40;</span>st_exteriorring<span style="color: #66cc66;">&#40;</span>st_scale<span style="color: #66cc66;">&#40;</span>the_geom, <span style="color: #cc66cc;">0.001</span>, <span style="color: #cc66cc;">0.001</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>.geom <span style="color: #005500;">as</span> geom 
  <span style="color: #005500;">from</span> uk1km 
  <span style="color: #005500;">where</span> st_numpoints<span style="color: #66cc66;">&#40;</span>st_exteriorring<span style="color: #66cc66;">&#40;</span>the_geom<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">20</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> d
<span style="color: #005500;">group</span> <span style="color: #005500;">by</span> id;</pre></div></div>




<p>Then, to draw the UK in a sketch I do this.</p>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">size<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">350</span>, <span style="color: #cc66cc;">620</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
translate<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">10</span>, height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
scale<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0.5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// paste in the output of the previous query</span></pre></div></div>




<p>Which has this result (with thanks to <a href="http://edina.ac.uk"><span class="caps">EDINA</span></a> for the data):</p>

<p><img src="http://blog.mackerron.com/wp-content/uploads/2011/11/Screen-Shot-2011-11-17-at-11.19.44.png" alt="The UK as drawn by this method" /></p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2011/11/17/polygons-from-postgis-to-processing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Approximating kernel-weighted proportions in PostGIS</title>
		<link>http://blog.mackerron.com/2011/08/16/kernel-weighted-proportions-postgis/</link>
		<comments>http://blog.mackerron.com/2011/08/16/kernel-weighted-proportions-postgis/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 13:27:23 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[GIS]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=864</guid>
		<description><![CDATA[Imagine you want compare various locations in terms of the availability of a certain type of environment, such as fresh water. You might want to use a measure of the proximity of that environment &#8212; such as the nearest neighbour distance. You might want to use a measure of the quantity of that environment in [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/2010/09/Screen-shot-2010-09-29-at-29-Sep-14.20.53.png" alt="Kernel weighted proportion diagram" height="463" width="663" /></p>

<p><strong>Imagine you want compare various locations in terms of the availability of a certain type of environment, such as fresh water.</strong></p>

<p>You might want to use a measure of the proximity of that environment &#8212; such as the <a href="/2011/03/postgis-nearest-neighbour/">nearest neighbour</a> distance.</p>

<p>You might want to use a measure of the quantity of that environment in the vicinity &#8212; such as the proportion of land within a specific radius that is of that type.</p>

<p>Or you might ideally like a measure that combines both of these: one that incorporates the quantity of that environment, but gives greater weight to areas that are nearer, and lesser weight to those that are further away.</p>

<p>In that third case, what you probably want is a kernel-weighted proportion.</p>

<p><span id="more-864"></span></p>

<h3>How it works</h3>

<p>In this usage, a &#8216;kernel&#8217; just means a distribution function, such as the <a href="http://en.wikipedia.org/wiki/Kernel_%28statistics%29">normal (Gaussian), triangular, or Epanechnikov</a>. The kernel is used to decide what weight should be attached to places at varying distances from the location under consideration.</p>

<p>I find it helpful to imagine the weight assigned to each point as a third dimension: the height at each point. I then imagine the kernel as a solid object positioned with its centre over the point I&#8217;m measuring from. For the normal or Epanechnikov kernels, this object is bell-shaped; for the triangular kernel, it&#8217;s a cone; for the (trivial) uniform kernel, it&#8217;s a cylinder.</p>

<p>The total volume of this object is the denominator of the kernel-weighted proportion. Now I imagine removing all parts of the object that don&#8217;t lie directly above the type of environment being measured. The volume of the remaining parts of the object &#8212; those directly overlying the environment of interest &#8212; is the numerator of the kernel-weighted proportion.</p>

<h3>Implementation in PostGIS</h3>

<p>The following <span class="caps">SQL </span>functions enable you to approximate kernel-weighted proportions in PostGIS. They do so by splitting the 3-dimensional kernel into horizontal slices of equal height, but with radii differing according to the kernel and kernel parameters specified. They calculate the summed volume of the intersections of the slices with the supplied polygons, and divide that by the total summed volume of the complete slices. (Assign each slice a height of 1 and these volumes are helpfully the same as the areas).</p>

<p>This approach is illustrated, for the normal kernel, at the top of this post.</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- kernel functions</span>
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> uniform_pdf
<span style="color: #66cc66;">&#40;</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>              <span style="color: #808080; font-style: italic;">-- $1 = x</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">1.0</span>  <span style="color: #808080; font-style: italic;">-- $2 = bandwidth</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">0.0</span>  <span style="color: #808080; font-style: italic;">-- $3 = centre</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span>
    <span style="color: #005500;">case</span>
      <span style="color: #005500;">when</span> $1 <span style="color: #66cc66;">&gt;</span> $3 - $2 <span style="color: #005500;">and</span> $1 <span style="color: #66cc66;">&lt;</span> $3 + $2 <span style="color: #005500;">then</span> <span style="color: #66cc66;">&#40;</span>
        <span style="color: #005500;">select</span> cast<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0.5</span> <span style="color: #005500;">as</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#41;</span>
      <span style="color: #005500;">else</span> <span style="color: #cc66cc;">0</span>
    <span style="color: #005500;">end</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> triangular_pdf
<span style="color: #66cc66;">&#40;</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>              <span style="color: #808080; font-style: italic;">-- $1 = x</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">1.0</span>  <span style="color: #808080; font-style: italic;">-- $2 = bandwidth</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">0.0</span>  <span style="color: #808080; font-style: italic;">-- $3 = centre</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span>
    <span style="color: #005500;">case</span>
      <span style="color: #005500;">when</span> $1 <span style="color: #66cc66;">&gt;</span> $3 - $2 <span style="color: #005500;">and</span> $1 <span style="color: #66cc66;">&lt;</span> $3 + $2 <span style="color: #005500;">then</span> <span style="color: #66cc66;">&#40;</span>
        <span style="color: #005500;">select</span> <span style="color: #cc66cc;">1</span> - <span style="color: #333399;">abs</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>$1 - $3<span style="color: #66cc66;">&#41;</span> / $2<span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#41;</span>
      <span style="color: #005500;">else</span> <span style="color: #cc66cc;">0</span>
    <span style="color: #005500;">end</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> normal_pdf
<span style="color: #66cc66;">&#40;</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>              <span style="color: #808080; font-style: italic;">-- $1 = x</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">1.0</span>  <span style="color: #808080; font-style: italic;">-- $2 = std dev (bandwidth)</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">0.0</span>  <span style="color: #808080; font-style: italic;">-- $3 = mean (centre)</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1.0</span> / <span style="color: #66cc66;">&#40;</span><span style="color: #333399;">sqrt</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2.0</span> * <span style="color: #333399;">pi</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> * pow<span style="color: #66cc66;">&#40;</span>$2, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> 
       * <span style="color: #333399;">exp</span><span style="color: #66cc66;">&#40;</span>-pow<span style="color: #66cc66;">&#40;</span>$1 - $3, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span> / <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2.0</span> * pow<span style="color: #66cc66;">&#40;</span>$2, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> epanechnikov_pdf
<span style="color: #66cc66;">&#40;</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>              <span style="color: #808080; font-style: italic;">-- $1 = x</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">1.0</span>  <span style="color: #808080; font-style: italic;">-- $2 = bandwidth</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">0.0</span>  <span style="color: #808080; font-style: italic;">-- $3 = centre</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span>
    <span style="color: #005500;">case</span>
      <span style="color: #005500;">when</span> $1 <span style="color: #66cc66;">&gt;</span> $3 - $2 <span style="color: #005500;">and</span> $1 <span style="color: #66cc66;">&lt;</span> $3 + $2 <span style="color: #005500;">then</span> <span style="color: #66cc66;">&#40;</span>
        <span style="color: #005500;">select</span> <span style="color: #cc66cc;">0.75</span> * <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span> - pow<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>$1 - $3<span style="color: #66cc66;">&#41;</span> / $2, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#41;</span>
      <span style="color: #005500;">else</span> <span style="color: #cc66cc;">0</span>
    <span style="color: #005500;">end</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;">-- current kernel function </span>
<span style="color: #808080; font-style: italic;">-- (uncomment the kernel you want to use, and redefine: the normal is shown here)</span>
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> __current_kernel_pdf
<span style="color: #66cc66;">&#40;</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>              <span style="color: #808080; font-style: italic;">-- $1 = x</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">1.0</span>  <span style="color: #808080; font-style: italic;">-- $2 = std dev/bandwidth</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">default</span> <span style="color: #cc66cc;">0.0</span>  <span style="color: #808080; font-style: italic;">-- $3 = mean/centre</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span>
    normal_pdf
    <span style="color: #808080; font-style: italic;">-- epanechnikov_pdf</span>
    <span style="color: #808080; font-style: italic;">-- triangular_pdf</span>
    <span style="color: #808080; font-style: italic;">-- uniform_pdf</span>
    <span style="color: #66cc66;">&#40;</span>$1, $2, $3<span style="color: #66cc66;">&#41;</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;">-- support functions</span>
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> __slice_height
<span style="color: #66cc66;">&#40;</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $1 = kernel std dev</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $2 = kernel radius at top of slice</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $3 = kernel radius at bottom of slice</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span> __current_kernel_pdf<span style="color: #66cc66;">&#40;</span>$2, $1<span style="color: #66cc66;">&#41;</span> - __current_kernel_pdf<span style="color: #66cc66;">&#40;</span>$3, $1<span style="color: #66cc66;">&#41;</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> __slice_radius
<span style="color: #66cc66;">&#40;</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $1 = kernel radius at top of slice</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $2 = kernel radius at bottom of slice</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span> $1 + <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>$2 - $1<span style="color: #66cc66;">&#41;</span> / <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> __kernel_slice_volume
<span style="color: #66cc66;">&#40;</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $1 = kernel std dev</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $2 = kernel radius at top of slice</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $3 = kernel radius at bottom of slice</span>
, <span style="color: #993333;">int</span>               <span style="color: #808080; font-style: italic;">-- $4 = buffer precision</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span>
    <span style="color: #333399;">coalesce</span><span style="color: #66cc66;">&#40;</span>
      st_area<span style="color: #66cc66;">&#40;</span>
        st_buffer<span style="color: #66cc66;">&#40;</span>
          st_makepoint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>,
          __slice_radius<span style="color: #66cc66;">&#40;</span>$2, $3<span style="color: #66cc66;">&#41;</span>,
          $4
        <span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#41;</span>,
      <span style="color: #cc66cc;">0</span>
    <span style="color: #66cc66;">&#41;</span>
    * __slice_height<span style="color: #66cc66;">&#40;</span>$1, $2, $3<span style="color: #66cc66;">&#41;</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> __intersected_slice_volume
<span style="color: #66cc66;">&#40;</span> <span style="color: #993333;">geometry</span>          <span style="color: #808080; font-style: italic;">-- $1 = area geometry</span>
, <span style="color: #993333;">geometry</span>          <span style="color: #808080; font-style: italic;">-- $2 = kernel centre point geometry</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $3 = kernel std dev</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $4 = kernel radius at top of slice</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $5 = kernel radius at bottom of slice</span>
, <span style="color: #993333;">int</span>               <span style="color: #808080; font-style: italic;">-- $6 = buffer precision</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span>
    <span style="color: #333399;">coalesce</span><span style="color: #66cc66;">&#40;</span>
      st_area<span style="color: #66cc66;">&#40;</span>
        st_intersection<span style="color: #66cc66;">&#40;</span>
          $1,
          st_buffer<span style="color: #66cc66;">&#40;</span>
            $2,
            __slice_radius<span style="color: #66cc66;">&#40;</span>$4, $5<span style="color: #66cc66;">&#41;</span>,
            $6
          <span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#41;</span>,
      <span style="color: #cc66cc;">0</span>
    <span style="color: #66cc66;">&#41;</span>
    * __slice_height<span style="color: #66cc66;">&#40;</span>$3, $4, $5<span style="color: #66cc66;">&#41;</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;">-- main function</span>
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> kernel_weighted_local_proportion
<span style="color: #66cc66;">&#40;</span> <span style="color: #993333;">geometry</span>          <span style="color: #808080; font-style: italic;">-- $1 = area geometry</span>
, <span style="color: #993333;">geometry</span>          <span style="color: #808080; font-style: italic;">-- $2 = kernel centre point geometry</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $3 = kernel std dev</span>
, <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span>  <span style="color: #808080; font-style: italic;">-- $4 = truncation bandwidth (for normal only -- for others, repeat $3)</span>
, <span style="color: #993333;">int</span>               <span style="color: #808080; font-style: italic;">-- $5 = number of horizontal slices for approximation (for uniform, use 1)</span>
, <span style="color: #993333;">int</span>               <span style="color: #808080; font-style: italic;">-- $6 = buffer precision (number of points per 1/4 circle)</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">returns</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span>
    <span style="color: #333399;">sum</span><span style="color: #66cc66;">&#40;</span>__intersected_slice_volume<span style="color: #66cc66;">&#40;</span>
      $1, $2, $3,
      $4 * <span style="color: #66cc66;">&#40;</span>cast<span style="color: #66cc66;">&#40;</span>s <span style="color: #005500;">as</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span><span style="color: #66cc66;">&#41;</span> / $5<span style="color: #66cc66;">&#41;</span>,     <span style="color: #808080; font-style: italic;">-- kernel radius at top of slice</span>
      $4 * <span style="color: #66cc66;">&#40;</span>cast<span style="color: #66cc66;">&#40;</span>s + <span style="color: #cc66cc;">1</span> <span style="color: #005500;">as</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span><span style="color: #66cc66;">&#41;</span> / $5<span style="color: #66cc66;">&#41;</span>, <span style="color: #808080; font-style: italic;">-- kernel radius at bottom of slice</span>
      $6
    <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    /
    <span style="color: #333399;">sum</span><span style="color: #66cc66;">&#40;</span>__kernel_slice_volume<span style="color: #66cc66;">&#40;</span>
      $3,
      $4 * <span style="color: #66cc66;">&#40;</span>cast<span style="color: #66cc66;">&#40;</span>s <span style="color: #005500;">as</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span><span style="color: #66cc66;">&#41;</span> / $5<span style="color: #66cc66;">&#41;</span>,     <span style="color: #808080; font-style: italic;">-- kernel radius at top of slice</span>
      $4 * <span style="color: #66cc66;">&#40;</span>cast<span style="color: #66cc66;">&#40;</span>s + <span style="color: #cc66cc;">1</span> <span style="color: #005500;">as</span> <span style="color: #005500;">double</span> <span style="color: #005500;">precision</span><span style="color: #66cc66;">&#41;</span> / $5<span style="color: #66cc66;">&#41;</span>, <span style="color: #808080; font-style: italic;">-- kernel radius at bottom of slice</span>
      $6
    <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #005500;">from</span> <span style="color: #333399;">generate_series</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span>, $5 - <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> s;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span>;</pre></div></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2011/08/16/kernel-weighted-proportions-postgis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Overlapping markers on your Google Map? Meet OverlappingMarkerSpiderfier</title>
		<link>http://blog.mackerron.com/2011/06/22/overlapping-marker-spiderfier/</link>
		<comments>http://blog.mackerron.com/2011/06/22/overlapping-marker-spiderfier/#comments</comments>
		<pubDate>Wed, 22 Jun 2011 20:19:25 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[CoffeeScript]]></category>
		<category><![CDATA[GIS]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=553</guid>
		<description><![CDATA[Ever noticed how, in Google Earth, marker pins that overlap each other spring apart gracefully when you click them, so you can pick the one you meant? And ever noticed how, when using the Google Maps API, the exact same thing doesn&#8217;t happen? This code makes Google Maps API version 3 map markers behave in [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Ever noticed how, in Google Earth, marker pins that overlap each other spring apart gracefully when you click them, so you can pick the one you meant?</strong></p>

<p>And ever noticed how, when using the Google Maps <span class="caps">API, </span>the exact same thing <em>doesn&#8217;t</em> happen?</p>

<p>This code makes Google Maps <span class="caps">API </span>version 3 map markers behave in that Google Earth way. Small numbers of markers (up to 8, configurable) spiderfy into a circle. Larger numbers fan out into a (more space-efficient) spiral. </p>

<p><span id="more-553"></span></p>

<p>Try it! (You can reload this page to re-randomise the marker positions).</p>

<p><iframe src="http://jawj.github.com/OverlappingMarkerSpiderfier/demo.html" style="width: 694px; height: 500px; border: 1px solid #444;"></iframe></p>

<p>The code is <span class="caps">MIT </span>licenced, has no dependencies, and is under 3K compiled (from CoffeeScript), minified and gzipped. I wrote it as part of the data download feature for <a href="http://www.mappiness.org.uk">Mappiness</a>.</p>

<p>It&#8217;s on Github, where you can <a href="https://github.com/jawj/OverlappingMarkerSpiderfier">find out more, download or fork the code</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2011/06/22/overlapping-marker-spiderfier/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Simple PostGIS nearest neighbour function</title>
		<link>http://blog.mackerron.com/2011/03/10/postgis-nearest-neighbour/</link>
		<comments>http://blog.mackerron.com/2011/03/10/postgis-nearest-neighbour/#comments</comments>
		<pubDate>Thu, 10 Mar 2011 11:31:59 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[GIS]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=516</guid>
		<description><![CDATA[Here&#8217;s a less generic and slightly different nearest-neighbour function based on Regina&#8217;s generic nearest-neighbour function at Boston GIS. It follows the same basic idea of using series of enlarging search radii to restrict distance calculations to a manageable subset of things-that-might-be-near. The difference is that it uses a geometric progression of sizes (x, x * [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Here&#8217;s a less generic and slightly different nearest-neighbour function based on <a href="http://www.bostongis.com/?content_name=postgis_nearest_neighbor_generic">Regina&#8217;s generic nearest-neighbour function</a> at Boston <span class="caps">GIS.</span></strong></p>

<p>It follows the same basic idea of using series of enlarging search radii to restrict distance calculations to a manageable subset of things-that-might-be-near. The difference is that it uses a geometric progression of sizes (<code>x, x * y, x * y^2, x * y^3, ...</code>) instead of an arithmetic one (<code>x, x + y, x + 2y, x + 3y, ...</code>).</p>

<p>For some distributions of things-that-might-be-near, and tuned with the right parameters (<code>x, y</code>), this turns out substantially faster (I&#8217;ve used it to locate the nearest UK postcode to each <a href="http://mappin.es">mappiness</a> response).</p>

<p><span id="more-516"></span></p>

<p>Note that it&#8217;s a lot simpler and less generic than the Boston <span class="caps">GIS </span>alternative: it returns only one nearest neighbour, without the associated distance, and is also less flexible about what it accepts as input.</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> 
  nn<span style="color: #66cc66;">&#40;</span>nearTo                   <span style="color: #993333;">geometry</span>
   , initialDistance          <span style="color: #993333;">real</span>
   , distanceMultiplier       <span style="color: #993333;">real</span> 
   , maxPower                 <span style="color: #993333;">integer</span>
   , nearThings               <span style="color: #993333;">text</span>
   , nearThingsIdField        <span style="color: #993333;">text</span>
   , nearThingsGeometryField  <span style="color: #993333;">text</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #005500;">returns</span> <span style="color: #993333;">integer</span> <span style="color: #005500;">as</span> $$
<span style="color: #005500;">declare</span> 
  sql     <span style="color: #993333;">text</span>;
  result  <span style="color: #993333;">integer</span>;
<span style="color: #005500;">begin</span>
  sql :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">' select '</span> <span style="color: #66cc66;">||</span> <span style="color: #333399;">quote_ident</span><span style="color: #66cc66;">&#40;</span>nearThingsIdField<span style="color: #66cc66;">&#41;</span> 
      <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">' from '</span>   <span style="color: #66cc66;">||</span> <span style="color: #333399;">quote_ident</span><span style="color: #66cc66;">&#40;</span>nearThings<span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">' where st_dwithin($1, '</span> 
      <span style="color: #66cc66;">||</span>   <span style="color: #333399;">quote_ident</span><span style="color: #66cc66;">&#40;</span>nearThingsGeometryField<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">', $2 * ($3 ^ $4))'</span>
      <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">' order by st_distance($1, '</span> <span style="color: #66cc66;">||</span> <span style="color: #333399;">quote_ident</span><span style="color: #66cc66;">&#40;</span>nearThingsGeometryField<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">')'</span>
      <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">' limit 1'</span>;
  <span style="color: #005500;">for</span> i <span style="color: #005500;">in</span> <span style="color: #cc66cc;">0</span>..maxPower <span style="color: #005500;">loop</span>
    <span style="color: #005500;">execute</span> sql <span style="color: #005500;">into</span> result <span style="color: #005500;">using</span> nearTo              <span style="color: #808080; font-style: italic;">-- $1</span>
                                , initialDistance     <span style="color: #808080; font-style: italic;">-- $2</span>
                                , distanceMultiplier  <span style="color: #808080; font-style: italic;">-- $3</span>
                                , i;                  <span style="color: #808080; font-style: italic;">-- $4</span>
    <span style="color: #005500;">if</span> result <span style="color: #005500;">is</span> <span style="color: #005500;">not</span> <span style="color: #005500;">null</span> <span style="color: #005500;">then</span> <span style="color: #005500;">return</span> result; <span style="color: #005500;">end</span> <span style="color: #005500;">if</span>;
  <span style="color: #005500;">end</span> <span style="color: #005500;">loop</span>;
  <span style="color: #005500;">return</span> <span style="color: #005500;">null</span>;
<span style="color: #005500;">end</span>
$$ <span style="color: #005500;">language</span> <span style="color: #ff0000;">'plpgsql'</span> <span style="color: #005500;">stable</span>;</pre></div></div>




<p><strong>Update, August 2011</strong> &#8212; Looking at this again, I realise there was an error in the function originally posted above. Because it did only a simple bounding-box check at each step, it was possible for it to return a geometry that was not in fact the nearest, but could in the worst case be up to 41% (sqrt(2) times) further away than the nearest. The code has been updated to fix this by using <code>st_dwithin</code>. I&#8217;ve also tidied it up a bit.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2011/03/10/postgis-nearest-neighbour/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>as_kmldoc: easily visualise PostGIS queries as KML in Google Earth</title>
		<link>http://blog.mackerron.com/2010/09/29/as_kmldoc/</link>
		<comments>http://blog.mackerron.com/2010/09/29/as_kmldoc/#comments</comments>
		<pubDate>Wed, 29 Sep 2010 13:58:33 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[GIS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=222</guid>
		<description><![CDATA[PostGIS has an st_askml function. This turns geometries into fragments of KML, and thus takes you most of the way to easy visualisation of spatial queries using Google Earth. But not all the way: these fragments have then to be assembled into a complete document. I&#8217;ve written some wrapper and aggregate functions to automate this. [...]]]></description>
			<content:encoded><![CDATA[<p>PostGIS has an <a href="http://postgis.refractions.net/docs/ST_AsKML.html"><code>st_askml</code></a> function. This turns geometries into fragments of <span class="caps">KML, </span>and thus takes you most of the way to easy visualisation of spatial queries using Google Earth. But not all the way: these fragments have then to be assembled into a complete document.</p>

<p>I&#8217;ve written some wrapper and aggregate functions to automate this. They&#8217;re probably deeply inefficient &#8212; I wouldn&#8217;t advocate building your next web service on them &#8212; but for one-off eyeballing of query results I find them really useful. </p>

<p>The key functions are called <code>as_kmldoc</code>; you could see them as the missing aggregate versions of <code>st_askml</code>.</p>

<p><span id="more-222"></span></p>

<h2>How&#8217;s it used?</h2>

<p><code>as_kmldoc</code> has three flavours, differing only in the number of arguments (arity). There are versions for only a geometry, a geometry plus a textual field (which becomes an associated <code>&lt;name&gt;</code> KML element), or a geometry plus two textual fields (which become the <code>&lt;name&gt;</code> and <code>&lt;description&gt;</code> in that order).</p>

<h3>Example 1</h3>

<p>I have a table of polygons corresponding to areas marked as parks in the <a href="http://www.openstreetmap.org/">OpenStreetMap</a> data. I want to see some of these in Google Earth to check them against the satellite imagery. So I run:</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">select</span> as_kmldoc<span style="color: #66cc66;">&#40;</span>osgb36_polygon<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">from</span> osm_green_spaces;</pre></div></div>




<p>Then I paste the resulting <span class="caps">KML </span>string into Google Earth, and fiddle a little with the colour and transparency:</p>

<p><img src="/wp-content/uploads/2010/09/Screen-shot-2010-09-29-at-29-Sep-14.13.09.png" alt="OSM parks screenshot" height="276" width="497" /></p>

<h3>Example 2</h3>

<p>I have a table of weather station locations, and associated names and codes, as used by <a href="http://www.wunderground.com/">Weather Underground</a>. I can select all this data into a <span class="caps">KML </span>document by running:</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">select</span> as_kmldoc<span style="color: #66cc66;">&#40;</span>osgb_location, <span style="color: #005500;">name</span>, code<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">from</span> wunderground_stations;</pre></div></div>




<p>Which gives me:</p>

<p><img src="/wp-content/uploads/2010/09/Screen-shot-2010-09-29-at-29-Sep-14.36.24.png" alt="Weather Underground stations" height="435" width="495" /></p>

<h3>Example 3</h3>

<p>This one&#8217;s just showing off. Here I visualise the calculation of a kernel-weighted average &#8212; which I plan to post more about in future &#8212; using the Z dimension (height) to illustrate the relative weightings at different locations. </p>

<p>The complete query is a bit long and involved to reproduce here. But it makes use of one more new function, <code>join_kmldocs</code>, which enables you to combine any number of <span class="caps">KML </span>documents into one, by (slightly hackily) making each input document into a <code>&lt;Folder&gt;</code> element of the output document. </p>

<p><img src="/wp-content/uploads/2010/09/Screen-shot-2010-09-29-at-29-Sep-14.20.53.png" alt="Kernel weighted average visualisation" height="463" width="663" /></p>

<h2>How do I get it?</h2>

<p>To add these functions to your PostGIS database, run the following query:</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> xml_escape<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">text</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #005500;">returns</span> <span style="color: #993333;">text</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span> replace<span style="color: #66cc66;">&#40;</span>replace<span style="color: #66cc66;">&#40;</span>replace<span style="color: #66cc66;">&#40;</span>$1, <span style="color: #ff0000;">'&amp;'</span>, <span style="color: #ff0000;">'&amp;amp;'</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #ff0000;">'&lt;'</span>, <span style="color: #ff0000;">'&amp;lt;'</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #ff0000;">'&gt;'</span>, <span style="color: #ff0000;">'&amp;gt;'</span><span style="color: #66cc66;">&#41;</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span> <span style="color: #005500;">strict</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> kml_wrap<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">text</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #005500;">returns</span> <span style="color: #993333;">text</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span>
    <span style="color: #ff0000;">'&lt;kml xmlns=&quot;http://www.opengis.net/kml/2.2&quot;&gt;&lt;Document&gt;'</span>
    <span style="color: #66cc66;">||</span> $1 <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;/Document&gt;&lt;/kml&gt;'</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span> <span style="color: #005500;">strict</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> kml_concat<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">text</span>, <span style="color: #993333;">geometry</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #005500;">returns</span> <span style="color: #993333;">text</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span> $1 <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;Placemark&gt;'</span> <span style="color: #66cc66;">||</span> st_askml<span style="color: #66cc66;">&#40;</span>$2<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;/Placemark&gt;'</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span> <span style="color: #005500;">strict</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">aggregate</span> as_kmldoc<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">geometry</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>
    sfunc <span style="color: #66cc66;">=</span> kml_concat,
    finalfunc <span style="color: #66cc66;">=</span> kml_wrap,
    stype <span style="color: #66cc66;">=</span> <span style="color: #993333;">text</span>,
    initcond <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span>
<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> kml_concat<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">text</span>, <span style="color: #993333;">geometry</span>, anyelement<span style="color: #66cc66;">&#41;</span>
<span style="color: #005500;">returns</span> <span style="color: #993333;">text</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span> $1 <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;Placemark&gt;&lt;name&gt;'</span> <span style="color: #66cc66;">||</span> xml_escape<span style="color: #66cc66;">&#40;</span>cast<span style="color: #66cc66;">&#40;</span>$3 <span style="color: #005500;">as</span> <span style="color: #993333;">text</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;/name&gt;'</span>
  <span style="color: #66cc66;">||</span> st_askml<span style="color: #66cc66;">&#40;</span>$2<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;/Placemark&gt;'</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span> <span style="color: #005500;">strict</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">aggregate</span> as_kmldoc<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">geometry</span>, anyelement<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>
    sfunc <span style="color: #66cc66;">=</span> kml_concat,
    finalfunc <span style="color: #66cc66;">=</span> kml_wrap,
    stype <span style="color: #66cc66;">=</span> <span style="color: #993333;">text</span>,
    initcond <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span>
<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> kml_concat<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">text</span>, <span style="color: #993333;">geometry</span>, anyelement, anyelement<span style="color: #66cc66;">&#41;</span>
<span style="color: #005500;">returns</span> <span style="color: #993333;">text</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span> $1 <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;Placemark&gt;&lt;name&gt;'</span> <span style="color: #66cc66;">||</span> xml_escape<span style="color: #66cc66;">&#40;</span>cast<span style="color: #66cc66;">&#40;</span>$3 <span style="color: #005500;">as</span> <span style="color: #993333;">text</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;/name&gt;&lt;description&gt;'</span> <span style="color: #66cc66;">||</span> xml_escape<span style="color: #66cc66;">&#40;</span>cast<span style="color: #66cc66;">&#40;</span>$4 <span style="color: #005500;">as</span> <span style="color: #993333;">text</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;/description&gt;'</span> <span style="color: #66cc66;">||</span> st_askml<span style="color: #66cc66;">&#40;</span>$2<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">'&lt;/Placemark&gt;'</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span> <span style="color: #005500;">strict</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">aggregate</span> as_kmldoc<span style="color: #66cc66;">&#40;</span><span style="color: #993333;">geometry</span>, anyelement, anyelement<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>
    sfunc <span style="color: #66cc66;">=</span> kml_concat,
    finalfunc <span style="color: #66cc66;">=</span> kml_wrap,
    stype <span style="color: #66cc66;">=</span> <span style="color: #993333;">text</span>,
    initcond <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">''</span>
<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">or</span> <span style="color: #005500;">replace</span> <span style="color: #005500;">function</span> join_kmldocs<span style="color: #66cc66;">&#40;</span><span style="color: #005500;">variadic</span> <span style="color: #993333;">text</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #005500;">returns</span> <span style="color: #993333;">text</span> <span style="color: #005500;">as</span> $$
  <span style="color: #005500;">select</span> kml_wrap<span style="color: #66cc66;">&#40;</span>
    replace<span style="color: #66cc66;">&#40;</span>
      replace<span style="color: #66cc66;">&#40;</span>
        <span style="color: #333399;">array_to_string</span><span style="color: #66cc66;">&#40;</span>$1, <span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span>,
        <span style="color: #ff0000;">'&lt;kml xmlns=&quot;http://www.opengis.net/kml/2.2&quot;&gt;&lt;Document&gt;'</span>,
        <span style="color: #ff0000;">'&lt;Folder&gt;'</span>
       <span style="color: #66cc66;">&#41;</span>,
       <span style="color: #ff0000;">'&lt;/Document&gt;&lt;/kml&gt;'</span>,
       <span style="color: #ff0000;">'&lt;/Folder&gt;'</span>
    <span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#41;</span>;
$$ <span style="color: #005500;">language</span> sql <span style="color: #005500;">immutable</span> <span style="color: #005500;">strict</span>;</pre></div></div>




<h2>pgAdmin hint</h2>

<p>I work with PostGIS mostly via <a href="http://www.pgadmin.org/">pgAdmin</a>. If you&#8217;re using <code>as_kmldoc</code> via pgAdmin, you might find it useful to change pgAdmin&#8217;s &#8216;Result copy quoting&#8217; to &#8216;None&#8217; in Preferences &gt; Query Tool. That way, you can copy and paste from pgAdmin straight into Google Earth.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2010/09/29/as_kmldoc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using OS Code-Point Polygons in PostGIS</title>
		<link>http://blog.mackerron.com/2009/11/14/code-point-polygons-postgis/</link>
		<comments>http://blog.mackerron.com/2009/11/14/code-point-polygons-postgis/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 12:13:43 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[GIS]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=193</guid>
		<description><![CDATA[Ordnance Survey&#8217;s Code-Point with Polygons &#8220;provides a precise geographical location for each postcode unit in Great Britain&#8221;. It&#8217;s available in various formats, including ESRI .shp files. Many UK academics can access the data via institutional subscription to EDINA Digimap. I&#8217;m using it in my research into subjective wellbeing and environmental quality. This post shows how [...]]]></description>
			<content:encoded><![CDATA[<p>Ordnance Survey&#8217;s <a href="http://www.ordnancesurvey.co.uk/oswebsite/products/codepointpolygons/">Code-Point with Polygons</a> &#8220;provides a precise geographical location for each postcode unit in Great Britain&#8221;. It&#8217;s available in various formats, including <span class="caps">ESRI</span> .shp files. </p>

<p>Many UK academics can access the data via institutional subscription to <a href="http://edina.ac.uk/digimap/"><span class="caps">EDINA</span> Digimap</a>. I&#8217;m using it in <a href="http://personal.lse.ac.uk/MACKERRO/">my research into subjective wellbeing and environmental quality</a>.</p>

<p>This post shows how to:</p>


<ol>
<li><strong>import the data files</strong> into a <a href="http://postgis.refractions.net/">PostGIS</a> database; and</li>
<li><strong>de-normalise the data into a single table</strong>, where there&#8217;s a one-to-one mapping of postcodes to rows, and each row contains either all geographical locations covered by a postcode (as a single geometry column, of type multipolygon) or the reason why no such location is available</li>
</ol>



<p><span id="more-193"></span></p>

<h3>Why de-normalise?</h3>

<p>Step 2 above is required for my purposes because Code-Point data is supplied in a number of separate files per postcode area: </p>


<ul>
<li>a .shp file (and associated .shx and .dbf) mapping postcodes and &#8216;vertical streets&#8217; to the locations they cover;</li>
<li>an accompanying text file mapping postcodes to &#8216;vertical streets&#8217;; and</li>
<li>another text file listing postcodes with no associated locations, either because they represent PO boxes or because the data just isn&#8217;t available.</li>
</ul>



<p>Vertical streets generally represent high-rise buildings, where one location in 2D space may be associated with multiple postcodes. Vertical streets are also a serious pain: not only may one vertical street be associated with many postcodes, but one postcode may be associated with many vertical streets <em>and</em> with non-vertical-street locations too. </p>

<h2>Import the data files</h2>

<p>Download and unzip the Code-Point with Polygons data, in <span class="caps">ESRI</span> .shp format, for the regions you want (where indicative query timings are provided later, these are for whole-UK data &#8212; 120 postcode areas &#8212; on a 2Ghz Intel iMac).</p>

<p>Dump everything in the same directory. For each postcode area XX you should have the following five files:</p>


<ul>
<li><span class="caps">XX.</span>shp, <span class="caps">XX.</span>shx and <span class="caps">XX.</span>dbf</li>
<li>XX_vstreet_lookup.txt</li>
<li>XX_discard.txt</li>
</ul>



<p>If you don&#8217;t already have one you want to use for this purpose, create a PostGIS-enabled PostgreSQL database (in this post, the database is named <code>geo</code>). If you&#8217;re not running PostgreSQL 8.4 or later you may need to fiddle with some fsm_ settings in the Postgres .conf file in order to cope with a data set this large.</p>

<p>Execute the following <span class="caps">SQL </span>to create the tables for discards and vertical streets (e.g. from within pgAdmin):</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">create</span> <span style="color: #005500;">table</span> cpp_vertical_streets <span style="color: #66cc66;">&#40;</span>
  postcode <span style="color: #993333;">character</span> varying<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span>,
  vstreet <span style="color: #993333;">character</span> varying<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">table</span> cpp_discards <span style="color: #66cc66;">&#40;</span>
  postcode <span style="color: #993333;">character</span> varying<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span>,
  reason <span style="color: #993333;">character</span> varying<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">7</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span>;</pre></div></div>




<p>Next we need to create the table for the .shp-file polygons. We <strong>switch to Ruby</strong> for this &#8212; you can just enter the commands in an <span class="caps">IRB </span>terminal session:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">path = <span style="color:#996600;">'/path/to/CodePoint polygons'</span>
<span style="color:#996600;">`/usr/local/pgsql/bin/shp2pgsql -p -D -s 27700 &quot;#{path}/ab.shp&quot; cpp_polygons | /usr/local/pgsql/bin/psql -d geo -U postgres`</span></pre></div></div>




<p>The -p flag to <code>shp2pgsql</code> just creates a table structure, and the -s 27700 gives it the <span class="caps">EPSG </span>code to tell it we&#8217;re using the <span class="caps">OSGB36 </span>datum. You can use any of the .shp files you&#8217;ve downloaded &#8212; it need not be the AB area one.</p>

<p><strong>Now to do the import</strong> into the three tables. Still in Ruby, execute the following loop:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC00FF; font-weight:bold;">Dir</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;#{path}/*.shp&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> f
  <span style="color:#996600;">`/usr/local/pgsql/bin/shp2pgsql -a -D -s 27700 &quot;#{f}&quot; cpp_polygons | /usr/local/pgsql/bin/psql -d geo -U postgres`</span>
  <span style="color:#996600;">`echo &quot;copy cpp_vertical_streets from '#{f.sub(/<span style="color:#000099;">\.</span>shp$/, '_vstreet_lookup.txt')}' csv;&quot; | /usr/local/pgsql/bin/psql geo postgres`</span>
  <span style="color:#996600;">`echo &quot;copy cpp_discards from '#{f.sub(/<span style="color:#000099;">\.</span>shp$/, '_discard.txt')}' csv;&quot; | /usr/local/pgsql/bin/psql geo postgres`</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>




<p>Back in <span class="caps">SQL, </span>add some boolean flags we&#8217;ll use later on, then create an index on the postcode column, which will save a <strong>lot</strong> of time later:</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">alter</span> <span style="color: #005500;">table</span> cpp_polygons <span style="color: #005500;">add</span> <span style="color: #005500;">column</span> <span style="color: #005500;">discard</span> <span style="color: #993333;">boolean</span>;
<span style="color: #005500;">alter</span> <span style="color: #005500;">table</span> cpp_polygons <span style="color: #005500;">add</span> <span style="color: #005500;">column</span> vstreet <span style="color: #993333;">boolean</span>;
<span style="color: #005500;">alter</span> <span style="color: #005500;">table</span> cpp_polygons <span style="color: #005500;">add</span> <span style="color: #005500;">column</span> vstreet_and_std <span style="color: #993333;">boolean</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">index</span> pc_index <span style="color: #005500;">on</span> cpp_polygons <span style="color: #66cc66;">&#40;</span>postcode<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">vacuum</span> <span style="color: #005500;">analyze</span> cpp_polygons;</pre></div></div>




<p>If you like, you can confirm here that there&#8217;s only one row per postcode &#8212; this query <strong>should return nothing</strong>:</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">select</span> * 
<span style="color: #005500;">from</span> cpp_polygons a 
<span style="color: #005500;">inner</span> <span style="color: #005500;">join</span> cpp_polygons b 
<span style="color: #005500;">on</span> a.postcode <span style="color: #66cc66;">=</span> b.postcode 
<span style="color: #005500;">where</span> a.gid <span style="color: #66cc66;">&lt;&gt;</span> b.gid;</pre></div></div>




<p>So, we now have all the OS data held in three separate tables. In the rest of the post, we&#8217;ll be merging the data in the discards and vertical streets tables into the main table, cpp_polygons.</p>

<h2>Discards</h2>

<p>We&#8217;re going to create a new table, with the same structure as cpp_polygons, to hold the discarded postcode data. These postcodes will have a <span class="caps">NULL </span>geometry column, and a <span class="caps">TRUE </span>discard column (one of the booleans we added earlier). Later, we&#8217;ll insert the contents of this table into cpp_polygons.</p>

<p>Run the following <span class="caps">SQL</span>:</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">create</span> <span style="color: #005500;">sequence</span> cpp_discard_seq <span style="color: #005500;">start</span> <span style="color: #005500;">with</span> <span style="color: #cc66cc;">2000000</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">table</span> cpp_discard_polys <span style="color: #005500;">as</span> <span style="color: #66cc66;">&#40;</span>
<span style="color: #005500;">select</span> 
  <span style="color: #333399;">nextval</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'cpp_discard_seq'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> gid, 
  postcode,
  cast<span style="color: #66cc66;">&#40;</span><span style="color: #005500;">null</span> <span style="color: #005500;">as</span> <span style="color: #993333;">character</span> varying<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> upp, 
  <span style="color: #333399;">substring</span><span style="color: #66cc66;">&#40;</span>postcode <span style="color: #005500;">from</span> <span style="color: #ff0000;">'^[A-Z][A-Z]?'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> pc_area, 
  cast<span style="color: #66cc66;">&#40;</span><span style="color: #005500;">null</span> <span style="color: #005500;">as</span> <span style="color: #993333;">geometry</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> the_geom, 
  <span style="color: #005500;">true</span> <span style="color: #005500;">as</span> <span style="color: #005500;">discard</span>, 
  <span style="color: #005500;">false</span> <span style="color: #005500;">as</span> vstreet,
  <span style="color: #005500;">false</span> <span style="color: #005500;">as</span> vstreet_and_std
<span style="color: #005500;">from</span> cpp_discards
<span style="color: #66cc66;">&#41;</span>;</pre></div></div>




<h2>Vertical streets</h2>

<p>Similarly, we&#8217;re now going to create a new table with the same structure as cpp_polygons to map vertical street postcodes to the right polygons. This requires a left join of the vertical streets data with some of the geometry data in cpp_polygons.</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">set</span> enable_seqscan <span style="color: #66cc66;">=</span> <span style="color: #005500;">false</span>; 
<span style="color: #808080; font-style: italic;">-- (otherwise pg sometimes fails to use the index)</span>
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">sequence</span> cpp_vstreet_seq <span style="color: #005500;">start</span> <span style="color: #005500;">with</span> <span style="color: #cc66cc;">3000000</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">table</span> cpp_vstreet_polys <span style="color: #005500;">as</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #005500;">select</span> 
    <span style="color: #333399;">nextval</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'cpp_vstreet_seq'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> gid, 
    <span style="color: #333399;">max</span><span style="color: #66cc66;">&#40;</span>v.postcode<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> postcode, 
    cast<span style="color: #66cc66;">&#40;</span><span style="color: #005500;">null</span> <span style="color: #005500;">as</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> upp, 
    <span style="color: #333399;">max</span><span style="color: #66cc66;">&#40;</span>pc_area<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> pc_area, 
    st_union<span style="color: #66cc66;">&#40;</span>the_geom<span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> the_geom, 
    <span style="color: #005500;">false</span> <span style="color: #005500;">as</span> <span style="color: #005500;">discard</span>,
    <span style="color: #005500;">true</span> <span style="color: #005500;">as</span> vstreet,
    <span style="color: #005500;">false</span> <span style="color: #005500;">as</span> vstreet_and_std
  <span style="color: #005500;">from</span> cpp_vertical_streets v 
  <span style="color: #005500;">left</span> <span style="color: #005500;">join</span> cpp_polygons p 
  <span style="color: #005500;">on</span> v.vstreet <span style="color: #66cc66;">=</span> p.postcode
  <span style="color: #005500;">group</span> <span style="color: #005500;">by</span> v.postcode
<span style="color: #66cc66;">&#41;</span>;</pre></div></div>




<p>Our last new table is for postcodes that are associated with both standard polygons <strong>and</strong> vertical street polygons.</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">create</span> <span style="color: #005500;">sequence</span> cpp_vstreet_and_std_seq <span style="color: #005500;">start</span> <span style="color: #005500;">with</span> <span style="color: #cc66cc;">4000000</span>;
&nbsp;
<span style="color: #005500;">create</span> <span style="color: #005500;">table</span> cpp_vstreet_and_std_polys <span style="color: #005500;">as</span> <span style="color: #66cc66;">&#40;</span>
<span style="color: #005500;">select</span> 
  <span style="color: #333399;">nextval</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'cpp_vstreet_and_std_seq'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> gid, 
  p.postcode <span style="color: #005500;">as</span> postcode,
  cast<span style="color: #66cc66;">&#40;</span><span style="color: #005500;">null</span> <span style="color: #005500;">as</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> upp, 
  p.pc_area <span style="color: #005500;">as</span> pc_area,
  st_multi<span style="color: #66cc66;">&#40;</span>st_union<span style="color: #66cc66;">&#40;</span>p.the_geom, v.the_geom<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> the_geom, 
  <span style="color: #005500;">false</span> <span style="color: #005500;">as</span> <span style="color: #005500;">discard</span>, 
  <span style="color: #005500;">false</span> <span style="color: #005500;">as</span> vstreet,
  <span style="color: #005500;">true</span> <span style="color: #005500;">as</span> vstreet_and_std
<span style="color: #005500;">from</span> cpp_polygons p
<span style="color: #005500;">inner</span> <span style="color: #005500;">join</span> cpp_vstreet_polys v
<span style="color: #005500;">on</span> p.postcode <span style="color: #66cc66;">=</span> v.postcode
<span style="color: #66cc66;">&#41;</span>;</pre></div></div>




<h2>Cleaning and merging</h2>

<p>Now we need to remove the vertical streets and polygons we just merged into a new table from their respective source tables.</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">delete</span> <span style="color: #005500;">from</span> cpp_polygons <span style="color: #005500;">where</span> postcode <span style="color: #005500;">in</span> <span style="color: #66cc66;">&#40;</span><span style="color: #005500;">select</span> postcode <span style="color: #005500;">from</span> cpp_vstreet_and_std_polys<span style="color: #66cc66;">&#41;</span>;
<span style="color: #808080; font-style: italic;">-- the above could take around 25 mins</span>
<span style="color: #005500;">delete</span> <span style="color: #005500;">from</span> cpp_vstreet_polys <span style="color: #005500;">where</span> postcode <span style="color: #005500;">in</span> <span style="color: #66cc66;">&#40;</span><span style="color: #005500;">select</span> postcode <span style="color: #005500;">from</span> cpp_vstreet_and_std_polys<span style="color: #66cc66;">&#41;</span>;</pre></div></div>




<p>And, finally, to merge our three new tables into the main table.</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">insert</span> <span style="color: #005500;">into</span> cpp_polygons <span style="color: #005500;">select</span> * <span style="color: #005500;">from</span> cpp_discard_polys;
<span style="color: #005500;">insert</span> <span style="color: #005500;">into</span> cpp_polygons <span style="color: #005500;">select</span> * <span style="color: #005500;">from</span> cpp_vstreet_polys;
<span style="color: #005500;">insert</span> <span style="color: #005500;">into</span> cpp_polygons <span style="color: #005500;">select</span> * <span style="color: #005500;">from</span> cpp_vstreet_and_std_polys;</pre></div></div>




<p>In order to join my own data with this data, I find it easiest to format the postcodes on which the join is made with no spaces. So I add and index the following extra column.</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">alter</span> <span style="color: #005500;">table</span> cpp_polygons <span style="color: #005500;">add</span> <span style="color: #005500;">column</span> postcode_no_sp <span style="color: #993333;">character</span> varying<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #005500;">update</span> cpp_polygons <span style="color: #005500;">set</span> postcode_no_sp <span style="color: #66cc66;">=</span> replace<span style="color: #66cc66;">&#40;</span>postcode, <span style="color: #ff0000;">' '</span>, <span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span>; 
<span style="color: #808080; font-style: italic;">-- the above could take 10 - 15 mins</span>
<span style="color: #005500;">create</span> <span style="color: #005500;">index</span> pcns_index <span style="color: #005500;">on</span> cpp_polygons <span style="color: #66cc66;">&#40;</span>postcode_no_sp<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">vacuum</span> <span style="color: #005500;">analyze</span> cpp_polygons;</pre></div></div>




<p>You might also want to remove the original vertical street rows, where the postcode column begins with a &#8216;V&#8217;, from the cpp_polygons table &#8212; I didn&#8217;t have any need for this.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2009/11/14/code-point-polygons-postgis/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Importing the National Statistics Postcode Directory into PostGIS</title>
		<link>http://blog.mackerron.com/2009/05/05/nspd-into-postgis/</link>
		<comments>http://blog.mackerron.com/2009/05/05/nspd-into-postgis/#comments</comments>
		<pubDate>Tue, 05 May 2009 10:19:45 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[GIS]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://gmackerron.wordpress.com/?p=6</guid>
		<description><![CDATA[This isn&#8217;t a very difficult task, but creating the table is somewhat laborious, so perhaps you&#8217;ll find the following SQL helpful. Step 1 The first step is to create an appropriate table, and pull everything in as character data. create table nspd_2008_11 &#40; postcode_7 char&#40;7&#41;, postcode_8 char&#40;8&#41;, postcode_egif char&#40;8&#41;, intro_date_string char&#40;6&#41;, termination_date_string char&#40;6&#41;, county char&#40;2&#41;, [...]]]></description>
			<content:encoded><![CDATA[<p>This isn&#8217;t a very difficult task, but creating the table is somewhat laborious, so perhaps you&#8217;ll find the following <span class="caps">SQL </span>helpful.</p>

<p><span id="more-6"></span></p>

<h3>Step 1</h3>

<p>The first step is to create an appropriate table, and pull everything in as character data.</p>


<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">create</span> <span style="color: #005500;">table</span> nspd_2008_11 <span style="color: #66cc66;">&#40;</span>
 postcode_7 char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">7</span><span style="color: #66cc66;">&#41;</span>,
 postcode_8 char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span>,
 postcode_egif char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span>,
 intro_date_string char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span>,
 termination_date_string char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span>,
 county char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>,
 la char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>,
 ward char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>,
 large_user char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 grid_easting char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span>,
 grid_northing char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">7</span><span style="color: #66cc66;">&#41;</span>,
 grid_ref_quality char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 health_authority char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 pan_sha char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 country char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 non_geo char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 in_paf char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 go_region char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 ssr char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 parl_const char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 eer char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>,
 tecr char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 ttwa char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 pct char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span>,
 nuts char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span>,
 ed_1991_ogss char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span>,
 ed_1991 char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span>,
 ed_quality char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 address_count char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">&#41;</span>,
 delivery_point_count char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">&#41;</span>,
 multiple_occupancy_count char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">&#41;</span>,
 small_business_count char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">&#41;</span>,
 previous_sha char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 lea char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 ha char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 ward_1991 char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span>,
 ward_1991_ogss char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span>,
 ward_1998 char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span>,
 stat_ward_2005 char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span>,
 oa char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span>,
 oa_indicator char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 cas_ward char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">&#41;</span>,
 national_park char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>,
 lsoa char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">9</span><span style="color: #66cc66;">&#41;</span>,
 scottish_dzone char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">9</span><span style="color: #66cc66;">&#41;</span>,
 msoa char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">9</span><span style="color: #66cc66;">&#41;</span>,
 urban_rural_ew char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 urban_rural_scot char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 urban_rural_ni char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>,
 scottish_izone char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">9</span><span style="color: #66cc66;">&#41;</span>,
 soa_ni char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span>,
 oa_class char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>,
 old_pct char<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">copy</span> nspd_2008_11 <span style="color: #005500;">from</span> <span style="color: #ff0000;">'/path/to/nspd/file.csv'</span> <span style="color: #005500;">csv</span>;</pre></div></div>




<h3>Step 2</h3>

<p>Since we&#8217;re going to the trouble of bringing it into PostGIS, likelihood is we&#8217;re going to want to use the spatial data. So let&#8217;s create a new table to hold the point geometries.</p>

<p><strong>Notes:</strong></p>


<ul>
<li>If necessary, we can join this table with our original table, on a postcode column, in future queries. We&#8217;ll index the relevant postcode columns in each table (as primary keys) to speed this up.</li>
<li>We include <span class="caps">OIDS, </span>even though they are deprecated, as an easy way to permit access to the data for visualisation using qGIS.</li>
<li>We exclude postcodes with the quality code &#8217;9&#8242;, because this code means there is no grid reference available.</li>
<li>We set the <span class="caps">SRID </span>of the point data to 27700, which is the appropriate value for the <span class="caps">OSGB36 </span>projection here.</li>
</ul>




<div class="wp_syntax"><div class="code"><pre class="postgresql" style="font-family:monospace;"><span style="color: #005500;">create</span> <span style="color: #005500;">table</span> nspd_2008_11_geometry <span style="color: #005500;">with</span> <span style="color: #66cc66;">&#40;</span><span style="color: #005500;">oids</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #005500;">select</span> postcode_7,
         grid_ref_quality,
         st_setsrid<span style="color: #66cc66;">&#40;</span>st_makepoint<span style="color: #66cc66;">&#40;</span>
           <span style="color: #005500;">cast</span> <span style="color: #66cc66;">&#40;</span>grid_easting <span style="color: #005500;">as</span> <span style="color: #993333;">integer</span><span style="color: #66cc66;">&#41;</span>,
           <span style="color: #005500;">cast</span> <span style="color: #66cc66;">&#40;</span>grid_northing <span style="color: #005500;">as</span> <span style="color: #993333;">integer</span><span style="color: #66cc66;">&#41;</span>
         <span style="color: #66cc66;">&#41;</span>, <span style="color: #cc66cc;">27700</span><span style="color: #66cc66;">&#41;</span> <span style="color: #005500;">as</span> <span style="color: #993333;">point</span>
  <span style="color: #005500;">from</span> nspd_2008_11
  <span style="color: #005500;">where</span> grid_ref_quality !<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'9'</span>
<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">alter</span> <span style="color: #005500;">table</span> nspd_2008_11
<span style="color: #005500;">add</span> <span style="color: #005500;">constraint</span> postcode_7_key <span style="color: #005500;">primary</span> <span style="color: #005500;">key</span> <span style="color: #66cc66;">&#40;</span>postcode_7<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">alter</span> <span style="color: #005500;">table</span> nspd_2008_11_geometry
<span style="color: #005500;">add</span> <span style="color: #005500;">constraint</span> postcode_7_geometry_key <span style="color: #005500;">primary</span> <span style="color: #005500;">key</span> <span style="color: #66cc66;">&#40;</span>postcode_7<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #005500;">vacuum</span> <span style="color: #005500;">analyze</span>;</pre></div></div>




<p>Now we can connect to the geometry table from qGIS to see the rough shape of Britain in postcode points. In a future post, I may look at creating polygons to represent postcode sectors using the data we&#8217;ve just imported.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2009/05/05/nspd-into-postgis/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  blog.mackerron.com/category/gis/feed/ ) in 1.50994 seconds, on Feb 5th, 2012 at 2:53 am UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on Feb 5th, 2012 at 3:53 am UTC -->
