<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:p="urn:schemas-microsoft-com:office:powerpoint" xmlns:a="urn:schemas-microsoft-com:office:access" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns:b="urn:schemas-microsoft-com:office:publisher" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:odc="urn:schemas-microsoft-com:office:odc" xmlns:oa="urn:schemas-microsoft-com:office:activation" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:q="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rtc="http://microsoft.com/officenet/conferencing" xmlns:D="DAV:" xmlns:Repl="http://schemas.microsoft.com/repl/" xmlns:mt="http://schemas.microsoft.com/sharepoint/soap/meetings/" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:ppda="http://www.passport.com/NameSpace.xsd" xmlns:ois="http://schemas.microsoft.com/sharepoint/soap/ois/" xmlns:dir="http://schemas.microsoft.com/sharepoint/soap/directory/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:dsp="http://schemas.microsoft.com/sharepoint/dsp" xmlns:udc="http://schemas.microsoft.com/data/udc" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sub="http://schemas.microsoft.com/sharepoint/soap/2002/1/alerts/" xmlns:ec="http://www.w3.org/2001/04/xmlenc#" xmlns:sp="http://schemas.microsoft.com/sharepoint/" xmlns:sps="http://schemas.microsoft.com/sharepoint/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:udcs="http://schemas.microsoft.com/data/udc/soap" xmlns:udcxf="http://schemas.microsoft.com/data/udc/xmlfile" xmlns:udcp2p="http://schemas.microsoft.com/data/udc/parttopart" xmlns:wf="http://schemas.microsoft.com/sharepoint/soap/workflow/" xmlns:dsss="http://schemas.microsoft.com/office/2006/digsig-setup" xmlns:dssi="http://schemas.microsoft.com/office/2006/digsig" xmlns:mdssi="http://schemas.openxmlformats.org/package/2006/digital-signature" xmlns:mver="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns:mrels="http://schemas.openxmlformats.org/package/2006/relationships" xmlns:spwp="http://microsoft.com/sharepoint/webpartpages" xmlns:ex12t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:ex12m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:pptsl="http://schemas.microsoft.com/sharepoint/soap/SlideLibrary/" xmlns:spsl="http://microsoft.com/webservices/SharePointPortalServer/PublishedLinksService" xmlns:Z="urn:schemas-microsoft-com:" xmlns:st="" xmlns="http://www.w3.org/TR/REC-html40">

<head>
<meta http-equiv=Content-Type content="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
 /* Font Definitions */
 @font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
        {mso-style-priority:99;
        mso-style-link:"Balloon Text Char";
        margin:0cm;
        margin-bottom:.0001pt;
        font-size:8.0pt;
        font-family:"Tahoma","sans-serif";}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Arial","sans-serif";
        color:windowtext;}
span.BalloonTextChar
        {mso-style-name:"Balloon Text Char";
        mso-style-priority:99;
        mso-style-link:"Balloon Text";
        font-family:"Tahoma","sans-serif";}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.Section1
        {page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
 <o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
 <o:shapelayout v:ext="edit">
  <o:idmap v:ext="edit" data="1" />
 </o:shapelayout></xml><![endif]-->
</head>

<body lang=EN-AU link=blue vlink=purple>

<div class=Section1>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>Hi
All,<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>I
have a requirement to split large polygons into smaller pieces which can’t
have any interior rings.<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>I
started writing a plpgsql function for my solution with limited spatial experience
and less postgis experience and want some tips on how it can be improved.<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>I
pass the function two parameters, the geometry and the size I want the smaller polygons
to be. It then returns a setof geometries with the results.<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>If
the split of polygon has an rings in it, the function recursively calls itself
with pdp_size / 2 until all objects have no interior rings..<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>The
function works well with larger values in pdp_size (ie 1.0) but is quite slow
when using smaller values (ie 0.002).<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>To
give you an idea of the data I am working with, it is Oceans around the Australian
mainland and Lakes/Rivers/Catchments in Australia. Ocean’s I split up using
a size of 1.0 and Lakes/Rives/Catchments using a size of 0.002.<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>My
postgres/Postgis versions are<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>SELECT
version(), postgis_full_version();<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>PostgreSQL
8.3.6 on x86_64-redhat-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20071124 (Red
Hat 4.1.2-42),POSTGIS="1.3.5" GEOS="2.2.3-CAPI-1.1.1"
PROJ="Rel. 4.6.0, 21 Dec 2007" USE_STATS<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>Regards,<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>Josh</span><span
style='font-size:7.5pt;font-family:"Arial","sans-serif";color:#A6A6A6'><o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>--
Function: principal_gis.denonut_primitive(geometry, double precision)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>--
DROP FUNCTION principal_gis.denonut_primitive(geometry, double precision);<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>CREATE
OR REPLACE FUNCTION principal_gis.denonut_primitive(pgeom_obj geometry,
pdp_size double precision)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
RETURNS SETOF geometry AS<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>$BODY$<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>DECLARE<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vrec_ring record;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Bounding box extents<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_xmin double precision;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_xmax double precision;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_ymin double precision;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_ymax double precision;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Cursors<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_xpos double precision;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_ypos double precision;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Stepping<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_xstep double precision;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_ystep double precision;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Variables to hold different versions of the geometry<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vgeom_orig geometry;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vgeom_test geometry;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vgeom_cut  geometry;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vgeom_coll geometry;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vgeom_dump geometry;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Variable to hold SRID<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vi_srid integer;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>BEGIN<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
/******************************************************<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
Do split<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
******************************************************/<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Get Bounding box extents<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_xmin := ST_XMin(ST_Envelope(pgeom_obj));<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_xmax := ST_XMax(ST_Envelope(pgeom_obj));<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_ymin := ST_YMin(ST_Envelope(pgeom_obj));<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vdp_ymax := ST_YMax(ST_Envelope(pgeom_obj));<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vi_srid := ST_SRID(pgeom_obj);<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Setup xmin, xmax as xstep so they go east to west.<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
IF vdp_xmax < 0 THEN<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_xpos := vdp_xmax;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_xmax := vdp_xmin;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_xmin := vdp_xpos;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_xstep := 0 - pdp_size;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
ELSE<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>--   
vdp_xpos := vdp_xmin;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_xstep := pdp_size;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
END IF;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Setup ymin, ymax as ystep so they go north to south.<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
IF vdp_ymax < 0 THEN<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_ypos := vdp_ymax;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_ymax := vdp_ymin;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_ymin := vdp_ypos;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_ystep := 0 - pdp_size;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
ELSE <o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>--   
vdp_ypos := vdp_ymin;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
vdp_ystep := pdp_size;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
END IF;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Make Test Polgon for Intersection<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
vgeom_orig := ST_GeomFromText('POLYGON((' ||
vdp_xmin            || '
' || vdp_ymin || ',' <o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>                                          
|| vdp_xmin + vdp_xstep || ' ' || vdp_ymin || ',' <o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>                    
                      ||
vdp_xmin + vdp_xstep || ' ' || vdp_ymin + vdp_ystep || ','<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>                                          
||
vdp_xmin            
|| ' ' || vdp_ymin + vdp_ystep || ','<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>                                          
||
vdp_xmin            
|| ' ' || vdp_ymin || '))', vi_srid);<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- Check geometry <o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
IF ST_Area(pgeom_obj) < (ST_Area(vgeom_orig) / 2) AND<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>    
ST_Area(ST_Envelope(pgeom_obj)) < (ST_Area(ST_Envelope(vgeom_orig)) * 2) AND<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>    
NumInteriorRings(pgeom_obj) = 0<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>  
THEN<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>    
-- Regardless of the shape, the object is small enough to pass.<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>    
--   That is, the actual area of the geometry is less than half the
split area AND<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>    
--   the bounding box of the geometry is not double the split area
AND<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>    
--   the geometry has no inner rings<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>    
RETURN NEXT pgeom_obj;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
ELSE<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
-- While we have not gone past the original polygon (To the east)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
WHILE NOT pgeom_obj << vgeom_orig LOOP<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>     
-- Initalise Test Polygon (Y axis)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>     
vgeom_test := vgeom_orig;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>     
--While we have not gone below the original polygon (To the south)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>     
WHILE NOT pgeom_obj |>> vgeom_test LOOP<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>       
-- Get the intersection<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>       
vgeom_cut := SetSRID(ST_Intersection(AsText(pgeom_obj),
SetSRID(vgeom_test,-1)), vi_srid);<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>/*<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>EXPLANATION
OF ABOVE QUERY<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> --
In our version of postgis (or more precisely GEOS), there is a bug with
precision of geometeries.<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> --
The AsText function has some precision reduction which makes the error go way.
This bug has been<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> --
fixed in later versions.<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> --
Info at<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> --
http://geos.refractions.net/pipermail/geos-devel/2005-May/001441.html<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>*/<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>       
-- Did anything intersect?<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>       
IF ST_IsEmpty(vgeom_cut) THEN<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>         
-- No, do nothing<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>         
NULL;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>       
ELSE<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>         
-- Yes, check what turned out in the results<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>         
IF GeometryType(vgeom_cut) = 'POLYGON' THEN<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>           
-- Was there rings?<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>           
IF NumInteriorRings(vgeom_cut) > 0 THEN<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>             
-- Yes Rings, Dump each polygon through this function again<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>             
RETURN QUERY SELECT denonut_primitive FROM
principal_gis.denonut_primitive(vgeom_cut, pdp_size / 2);<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>           
ELSE<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>             
RETURN NEXT vgeom_cut;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>           
END IF;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>         
ELSE<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>           
-- Not a polygon (linestring, point, multi*something* or geometrycollection)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>           
FOR vgeom_dump IN SELECT geom FROM ST_Dump(vgeom_cut) LOOP<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>             
IF ST_IsValid(vgeom_dump) THEN<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>               
vgeom_coll := ST_BuildArea(vgeom_dump);<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>               
IF NumInteriorRings(vgeom_coll) > 0 THEN<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>                 
RETURN QUERY SELECT denonut_primitive FROM
principal_gis.denonut_primitive(vgeom_coll, pdp_size / 2);<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>               
ELSE<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>                 
RETURN NEXT vgeom_coll;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>               
END IF;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>             
ELSE<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>               
-- Yes, skip it<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>               
CONTINUE;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>             
END IF;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>           
END LOOP;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>         
END IF;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>       
END IF; /* ST_IsEmpty */<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>       
-- Move the Test Polygon (Y Axis)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>       
vgeom_test := ST_Translate(vgeom_test, 0, vdp_ystep);<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>     
END LOOP;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>     
-- Move the Test Polygon (X Axis)<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>     
vgeom_orig := ST_Translate(vgeom_orig, vdp_xstep, 0);<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>   
END LOOP;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
END IF;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
-- We are finished, return the result set now<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
RETURN;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>END;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>$BODY$<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
LANGUAGE 'plpgsql' STABLE STRICT<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
COST 100<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'> 
ROWS 1000;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>ALTER
FUNCTION principal_gis.denonut_primitive(geometry, double precision) OWNER TO
postgres;<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'><o:p> </o:p></span></p>

<p class=MsoNormal><o:p> </o:p></p>

</div>

</body>

</html>