<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:m="http://schemas.microsoft.com/office/2004/12/omml" 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)">
<!--[if !mso]>
<style>
v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style>
<![endif]-->
<style>
<!--
 /* Font Definitions */
 @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:0in;
        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:0in;
        margin-bottom:.0001pt;
        font-size:8.0pt;
        font-family:"Tahoma","sans-serif";}
span.BalloonTextChar
        {mso-style-name:"Balloon Text Char";
        mso-style-priority:99;
        mso-style-link:"Balloon Text";
        font-family:"Tahoma","sans-serif";}
span.EmailStyle19
        {mso-style-type:personal;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
span.EmailStyle20
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page Section1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.Section1
        {page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
 <o:shapedefaults v:ext="edit" spidmax="3074" />
</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-US link=blue vlink=purple>

<div class=Section1>

<p class=MsoNormal><span style='color:#1F497D'>Ah, never mind this question.  I
don’t have the function exit if it can’t find a point to place, but have it
raise a notice, place the point and move on.  Of course I occasionally get
points that don’t qualify… .<o:p></o:p></span></p>

<p class=MsoNormal><span style='color:#1F497D'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='color:#1F497D'><o:p> </o:p></span></p>

<div>

<p class=MsoNormal><!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" 
 o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" 
 stroked="f">
 <v:stroke joinstyle="miter" />
 <v:formulas>
  <v:f eqn="if lineDrawn pixelLineWidth 0" />
  <v:f eqn="sum @0 1 0" />
  <v:f eqn="sum 0 0 @1" />
  <v:f eqn="prod @2 1 2" />
  <v:f eqn="prod @3 21600 pixelWidth" />
  <v:f eqn="prod @3 21600 pixelHeight" />
  <v:f eqn="sum @0 0 1" />
  <v:f eqn="prod @6 1 2" />
  <v:f eqn="prod @7 21600 pixelWidth" />
  <v:f eqn="sum @8 21600 0" />
  <v:f eqn="prod @7 21600 pixelHeight" />
  <v:f eqn="sum @10 21600 0" />
 </v:formulas>
 <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" />
 <o:lock v:ext="edit" aspectratio="t" />
</v:shapetype><v:shape id="_x0000_s1027" type="#_x0000_t75" alt="http://www.clemetparks.com/images/esig/cmp-ms-90x122.png" 
 style='position:absolute;margin-left:1.5pt;margin-top:0;width:67.5pt;height:91.5pt;
 z-index:2;visibility:visible;mso-wrap-style:square;mso-wrap-distance-left:9pt;
 mso-wrap-distance-top:0;mso-wrap-distance-right:9pt;
 mso-wrap-distance-bottom:0;mso-position-horizontal:absolute;
 mso-position-horizontal-relative:text;mso-position-vertical:absolute;
 mso-position-vertical-relative:text'>
 <v:imagedata src="cid:image003.png@01CC954F.E49ED030" o:href="http://www.clemetparks.com/images/esig/cmp-ms-90x122.png" />
 <w:wrap type="square"/>
</v:shape><![endif]--><![if !vml]><img width=90 height=122
src="cid:image003.png@01CC954F.E49ED030" align=left hspace=12
alt="http://www.clemetparks.com/images/esig/cmp-ms-90x122.png" v:shapes="_x0000_s1027"><![endif]><span
style='font-size:14.0pt;font-family:"Arial","sans-serif";color:#006C56'>Stephen
Mather<br>
</span><span style='font-family:"Arial","sans-serif";color:#006C56'>Geographic
Information Systems (GIS) Manager<br>
</span><span style='font-size:9.0pt;font-family:"Arial","sans-serif";
color:#006C56'>(216) 635-3243<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Arial","sans-serif";
color:#006C56'>svm@clevelandmetroparks.com<br>
</span><span style='color:#1F497D'><a href="http://www.clemetparks.com/"><span
style='font-size:9.0pt;font-family:"Arial","sans-serif";color:blue'>clevelandmetroparks.com</span></a><o:p></o:p></span></p>

<p class=MsoNormal><span style='color:#1F497D'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='color:#1F497D'><o:p> </o:p></span></p>

<p class=MsoNormal><span style='color:#1F497D'><o:p> </o:p></span></p>

</div>

<p class=MsoNormal><span style='color:#1F497D'><o:p> </o:p></span></p>

<div>

<div style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in'>

<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>From:</span></b><span
style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'> postgis-users-bounces@postgis.refractions.net
[mailto:postgis-users-bounces@postgis.refractions.net] <b>On Behalf Of </b>Stephen
V. Mather<br>
<b>Sent:</b> Wednesday, October 26, 2011 10:28 AM<br>
<b>To:</b> postgis-users@postgis.refractions.net<br>
<b>Subject:</b> [postgis-users] Placing a random point within a range of
distances from existing point, ST_DWithin and ST_Intersects<o:p></o:p></span></p>

</div>

</div>

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

<p class=MsoNormal>Hi All,<o:p></o:p></p>

<p class=MsoNormal>               
I’m trying to find the problem with my logic in the following query.  I
want to randomize a point, and neither place it too close or too far from the
initial point.  I’d like to further constrain the placement of that point
so that it stays within certain bounds.  Imagine, if you will sensitive
point data that might need a little fuzzing—1) I don’t want to fuzz it too much
(outer circle), 2) I don’t want it too close to the original point (inner
circle) 3) but I want it to also stay within certain boundaries in order to
retain some verisimilitude, e.g. must stay within forest boundaries.<o:p></o:p></p>

<p class=MsoNormal style='text-indent:.5in'>I’ve tested this in PostGIS 1.3.5
on a Windows Server 2003 machine (postgres 8.3), and in PostGIS 2.0 on Debian
(with postgres 8.4).<o:p></o:p></p>

<p class=MsoNormal style='text-indent:.5in'>In general, it works really
well.  Occasionally, I get a point that seems to meet my first to criteria
but not my third<o:p></o:p></p>

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

<p class=MsoNormal><b>Here’s a few hundred of the same point fuzzed:<o:p></o:p></b></p>

<p class=MsoNormal><img border=0 width=347 height=248 id="Picture_x0020_1"
src="cid:image004.png@01CC954F.E49ED030"><o:p></o:p></p>

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

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

<p class=MsoNormal>CREATE OR REPLACE FUNCTION ST_Donut<o:p></o:p></p>

<p class=MsoNormal>               
( geom GEOMETRY,                                                       
-- GEOMETRY point to be processed<o:p></o:p></p>

<p class=MsoNormal>               
dough DOUBLE
PRECISION,                                        
-- Outside ring<o:p></o:p></p>

<p class=MsoNormal>               
nut DOUBLE
PRECISION,                                              
-- Inside ring<o:p></o:p></p>

<p class=MsoNormal>               
itermax
INTEGER,                                                           
-- Maximum number of iterations<o:p></o:p></p>

<p class=MsoNormal>               
bite
GEOMETRY)                                                                             
--POLYGON that randomized point must intersect<o:p></o:p></p>

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

<p class=MsoNormal>               
RETURNS
GEOMETRY                                                    
-- Returns the randomized point<o:p></o:p></p>

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

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

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

<p class=MsoNormal>                               
xmin DOUBLE
PRECISION;           
                               
-- xmin for envelope of donut<o:p></o:p></p>

<p class=MsoNormal>                               
ymin DOUBLE PRECISION;                                           
-- ymin for envelope of donut<o:p></o:p></p>

<p class=MsoNormal>                               
delta DOUBLE
PRECISION;                                           
-- difference between xmax and xmin<o:p></o:p></p>

<p class=MsoNormal>                               
pointx DOUBLE PRECISION;                        
-- output point x<o:p></o:p></p>

<p class=MsoNormal>                               
pointy DOUBLE PRECISION;                        
-- output point y<o:p></o:p></p>

<p class=MsoNormal>                               
returnpoint GEOMETRY;<o:p></o:p></p>

<p class=MsoNormal>                               
i INTEGER := 0;                                                                  
-- index integer for while loop<o:p></o:p></p>

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

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

<p class=MsoNormal>                               
xmin = ST_X( geom ) - dough;    -- find min x, min y for
resulting envelope<o:p></o:p></p>

<p class=MsoNormal>                               
ymin = ST_Y( geom ) - dough;     -- in which to place
initial points<o:p></o:p></p>

<p class=MsoNormal>                               
delta =
dough*2;                                                             
-- for calculating max extent for envelope<o:p></o:p></p>

<p class=MsoNormal>               
WHILE i < itermax LOOP<o:p></o:p></p>

<p class=MsoNormal>                               
i = i + 1;<o:p></o:p></p>

<p class=MsoNormal>                               
pointx = xmin + delta *
random();                                                           
-- generate random point value<o:p></o:p></p>

<p class=MsoNormal>                               
pointy = ymin + delta * random();<o:p></o:p></p>

<p class=MsoNormal>                               
returnpoint = ST_SetSRID( ST_MakePoint( pointx, pointy ), ST_SRID( geom ) );<o:p></o:p></p>

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

<p class=MsoNormal>                               
ST_DWithin( returnpoint, geom, dough )                                             
-- test to see if inside outer ring<o:p></o:p></p>

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

<p class=MsoNormal>                               
ST_DWithin( returnpoint, geom, nut )                                   
-- test to see if outside inner ring<o:p></o:p></p>

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

<p class=MsoNormal>                               
ST_Intersects( returnpoint, bite
)                                                            
--test to see if inside inclusion polygon<o:p></o:p></p>

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

<p class=MsoNormal>               
END LOOP;<o:p></o:p></p>

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

<p class=MsoNormal>               
IF i > itermax THEN<o:p></o:p></p>

<p class=MsoNormal>                               
RAISE NOTICE 'Reached maximum iterations without placing point inside donut.';<o:p></o:p></p>

<p class=MsoNormal>               
END IF;<o:p></o:p></p>

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

<p class=MsoNormal>               
RETURN returnpoint;     -- return the GEOMETRY<o:p></o:p></p>

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

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

<p class=MsoNormal>$$ LANGUAGE plpgsql;<o:p></o:p></p>

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

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

<p class=MsoNormal><b>To run:<o:p></o:p></b></p>

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

<p class=MsoNormal>CREATE TABLE donut_bite_test1 AS<o:p></o:p></p>

<p class=MsoNormal style='text-indent:.5in'>SELECT ST_Donut(ST_MakePoint(0, 0),
40, 60, 1000, ST_Buffer(ST_MakePoint(-60, -60), 60))<o:p></o:p></p>

<p class=MsoNormal style='margin-left:.5in;text-indent:.5in'>UNION ALL<o:p></o:p></p>

<p class=MsoNormal style='text-indent:.5in'>SELECT ST_Donut(ST_MakePoint(0, 0),
60, 40, 1000, ST_Buffer(ST_MakePoint(-60, -60), 60))<o:p></o:p></p>

<p class=MsoNormal style='margin-left:.5in;text-indent:.5in'>UNION ALL<o:p></o:p></p>

<p class=MsoNormal style='text-indent:.5in'><i>Etc. etc.<o:p></o:p></i></p>

<p class=MsoNormal style='text-indent:.5in'>SELECT ST_Donut(ST_MakePoint(0, 0),
60, 40, 1000, ST_Buffer(ST_MakePoint(-60, -60), 60))<o:p></o:p></p>

<p class=MsoNormal style='text-indent:.5in'>;<o:p></o:p></p>

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

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

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

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

<p class=MsoNormal><!--[if gte vml 1]><v:shape id="cmp-ms-90x122.png" o:spid="_x0000_s1026" 
 type="#_x0000_t75" alt="http://www.clemetparks.com/images/esig/cmp-ms-90x122.png" 
 style='position:absolute;margin-left:1.5pt;margin-top:0;width:67.5pt;height:91.5pt;
 z-index:1;visibility:visible'>
 <v:imagedata src="cid:image003.png@01CC954F.E49ED030" o:title="cmp-ms-90x122" />
 <w:wrap type="square"/>
</v:shape><![endif]--><![if !vml]><img width=90 height=122
src="cid:image003.png@01CC954F.E49ED030" align=left hspace=12
alt="http://www.clemetparks.com/images/esig/cmp-ms-90x122.png" v:shapes="cmp-ms-90x122.png"><![endif]><span
style='font-size:14.0pt;font-family:"Arial","sans-serif";color:#006C56'>Stephen
Mather<br>
</span><span style='font-family:"Arial","sans-serif";color:#006C56'>Geographic
Information Systems (GIS) Manager<br>
</span><span style='font-size:9.0pt;font-family:"Arial","sans-serif";
color:#006C56'>(216) 635-3243<o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Arial","sans-serif";
color:#006C56'>svm@clevelandmetroparks.com<br>
</span><a href="http://www.clemetparks.com/"><span style='font-size:9.0pt;
font-family:"Arial","sans-serif"'>clevelandmetroparks.com</span></a><o:p></o:p></p>

</div>

</body>

</html>