<div>I have been around that question to.</div><div><br></div><div><a href="http://gis.stackexchange.com/questions/24456/nearest-neighbor-problem-in-postgis-2-0-using-gist-index-function">http://gis.stackexchange.com/questions/24456/nearest-neighbor-problem-in-postgis-2-0-using-gist-index-function</a> </div>
<div><br></div><div>You have to do it in two steps, like is explained in the operator <a href="http://postgis.refractions.net/docs/geometry_distance_centroid.html">page</a>. One faster step to reduce the candidates (by using <-> or <#>) and second one to get the real distances with ST_Distance.</div>
<br><div class="gmail_quote">The problem in finding the KNN for each row in a table is the fact that the gist index <-> operator only works if one of the geometries is constant. The workaround would be to create a SQL function to apply to each of the rows using table.the_geom as a parameter.</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">Something like this:</div><div class="gmail_quote"><br></div><div class="gmail_quote">----</div><div class="gmail_quote"><div class="gmail_quote" style>CREATE OR REPLACE FUNCTION _enn2 (geometry) RETURNS double precision AS $$</div>
<div class="gmail_quote" style><br></div><div class="gmail_quote" style>WITH index_query as</div><div class="gmail_quote" style><span style="white-space:pre-wrap">   </span>(SELECT ST_Distance($1,f.the_geom) as dist</div><div class="gmail_quote" style>
<span style="white-space:pre-wrap">     </span>FROM "grelha5m" As f</div><div class="gmail_quote" style><span style="white-space:pre-wrap">       </span>ORDER BY $1 <#> g1.the_geom limit 1000)</div><div class="gmail_quote" style>
SELECT dist</div><div class="gmail_quote" style><span style="white-space:pre-wrap">       </span>FROM index_query</div><div class="gmail_quote" style><span style="white-space:pre-wrap">     </span>ORDER BY dist;</div><div class="gmail_quote" style>
<br></div><div class="gmail_quote" style>$$ LANGUAGE SQL;</div><div class="gmail_quote" style>---</div><div class="gmail_quote" style><br></div><div class="gmail_quote" style>and I call it like this: </div><div class="gmail_quote" style>
<br></div><div class="gmail_quote" style>---</div><div class="gmail_quote" style>Select c.gid as gid, _enn2(c.the_geom) as enn</div><div class="gmail_quote" style>From cosn1 as c</div><div class="gmail_quote" style>Order by c.gid</div>
</div><div class="gmail_quote">---</div><div class="gmail_quote"><br></div><div class="gmail_quote">In this case the function returned the smallest distance, but you can choose any other column.</div><div class="gmail_quote">
<br></div><div class="gmail_quote">Hope it helps</div><div class="gmail_quote"><br></div><div class="gmail_quote">Alexandre Neto</div><div class="gmail_quote"><br></div><div class="gmail_quote">On Tue, May 15, 2012 at 5:37 PM, Stephen V. Mather <span dir="ltr"><<a href="mailto:svm@clevelandmetroparks.com" target="_blank">svm@clevelandmetroparks.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">









<div lang="EN-US" link="blue" vlink="purple">

<div>

<p class="MsoNormal">Hi All,<u></u><u></u></p>

<p class="MsoNormal">                Pretty
excited by the new operators <-> and <#>, but a bit confused as to
how to use them in a query.  The two examples from P. Ramsey back in late
2011 ( <a href="http://blog.opengeo.org/2011/09/28/indexed-nearest-neighbour-search-in-postgis/" target="_blank">http://blog.opengeo.org/2011/09/28/indexed-nearest-neighbour-search-in-postgis/</a>
) included doing a KNN on a single point to a cloud of points, i.e. <u></u><u></u></p>

<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New"">SELECT
name, gid<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New"">FROM
geonames<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New"">ORDER
BY geom <-> st_setsrid(st_makepoint(-90,40),4326)<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier New"">LIMIT
10;<u></u><u></u></span></p>

<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal">or doing KNN on non-point different geometries, where the
first neighbor by <-> or <#> might not be truly the first i.e.<u></u><u></u></p>

<p class="MsoNormal"><u></u> <u></u></p>

<pre>with index_query as (<u></u><u></u></pre><pre>  select<u></u><u></u></pre><pre>    st_distance(geom, 'SRID=3005;POINT(1011102 450541)') as distance,<u></u><u></u></pre><pre>    parcel_id, address<u></u><u></u></pre>
<pre>  from parcels<u></u><u></u></pre><pre>  order by geom <#> 'SRID=3005;POINT(1011102 450541)' limit 100<u></u><u></u></pre><pre>)<u></u><u></u></pre><pre>select * from index_query order by distance limit 10;<u></u><u></u></pre>


<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal">So, how would one grab the first nearest neighbor for all
points in a dataset?  This is how I used to do it:<u></u><u></u></p>

<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal"><span style="font-family:"Courier New"">CREATE TABLE
n2180_560_height AS <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-family:"Courier New"">SELECT x, y, height
FROM <u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-family:"Courier New"">(SELECT DISTINCT
ON(veg.gid) veg.gid as gid, ground.gid as gid_ground, veg.x as x, veg.y as y,
ground.z as z, veg.z - ground.z as height, veg.the_geom as geometry, veg.class
as class<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-family:"Courier New"">FROM (SELECT * FROM
n2180_560 WHERE class = 5) As veg, (SELECT * FROM n2180_560 WHERE class = 2) As
ground<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-family:"Courier New"">WHERE veg.class = 5
AND veg.gid <> ground.gid AND ST_DWithin(veg.the_geom, ground.the_geom,
10)<u></u><u></u></span></p>

<p class="MsoNormal"><span style="font-family:"Courier New"">ORDER BY veg.gid,
ST_Distance(veg.the_geom,ground.the_geom)) AS vegpoints;<u></u><u></u></span></p>

<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal">ST_DWithin prevents a full cross join, but is a sloppy way
to do this, as it requires a priori knowledge of the end cases.  I’m
hoping there’s a subquery or some such magic that would allow me to use
the distance operator to a similar end… .<u></u><u></u></p>

<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal">Thanks,<u></u><u></u></p>

<p class="MsoNormal">Best,<u></u><u></u></p>

<p class="MsoNormal">Steve<u></u><u></u></p>

<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal"><u></u><img width="90" height="122" src="cid:image001.png@01CD3297.76FAA280" align="left" hspace="12" alt="http://www.clemetparks.com/images/esig/cmp-ms-90x122.png"><u></u><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"><a href="tel:%28216%29%20635-3243" value="+12166353243" target="_blank">(216) 635-3243</a><u></u><u></u></span></p>

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

<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal"><u></u> <u></u></p>

<p class="MsoNormal"><u></u> <u></u></p>

</div>

</div>


<br>_______________________________________________<br>
postgis-users mailing list<br>
<a href="mailto:postgis-users@postgis.refractions.net">postgis-users@postgis.refractions.net</a><br>
<a href="http://postgis.refractions.net/mailman/listinfo/postgis-users" target="_blank">http://postgis.refractions.net/mailman/listinfo/postgis-users</a><br>
<br></blockquote></div><br>