-- This function given a point try to determine the approximate street address (norm_addy form)\r
-- and array of cross streets, as well as interpolated points along the streets\r
-- Use case example an address at the intersection of 3 streets: SELECT pprint_addy(r.addy[1]) As st1, pprint_addy(r.addy[2]) As st2, pprint_addy(r.addy[3]) As st3, array_to_string(r.street, ',') FROM reverse_geocode(ST_GeomFromText('POINT(-71.057811 42.358274)',4269)) As r;\r
---set search_path=tiger,public;\r
+set search_path=tiger,public;\r
CREATE OR REPLACE FUNCTION reverse_geocode(\r
IN pt geometry,\r
IN include_strnum_range boolean,\r
var_strnum varchar;\r
var_primary_line geometry := NULL;\r
var_primary_dist numeric(10,2) ;\r
+ var_pt geometry;\r
BEGIN\r
IF pt IS NULL THEN\r
RETURN;\r
+ ELSE\r
+ IF ST_SRID(pt) = 4269 THEN\r
+ var_pt := pt;\r
+ ELSE\r
+ var_pt := ST_Transform(pt, 4269);\r
+ END IF;\r
END IF;\r
-- Determine state tables to check \r
-- this is needed to take advantage of constraint exclusion\r
- var_states := ARRAY(SELECT statefp FROM state WHERE ST_Intersects(the_geom, pt) );\r
+ var_states := ARRAY(SELECT statefp FROM state WHERE ST_Intersects(the_geom, var_pt) );\r
IF array_upper(var_states, 1) IS NULL THEN\r
-- We don't have any data for this state\r
RETURN;\r
(SELECT z.place FROM zip_state_loc AS z WHERE z.zip = foo.zip and z.statefp = foo.statefp LIMIT 1) As place, foo.intpt,\r
side, to_number(fromhn, '999999') As fromhn, to_number(tohn, '999999') As tohn, ST_GeometryN(ST_Multi(line),1) As line, foo.dist\r
FROM \r
- (SELECT e.the_geom As line, e.fullname, a.zip, s.stusps, ST_ClosestPoint(e.the_geom, pt) As intpt, e.statefp, a.side, a.fromhn, a.tohn, ST_Distance_Sphere(e.the_geom, pt) As dist\r
+ (SELECT e.the_geom As line, e.fullname, a.zip, s.stusps, ST_ClosestPoint(e.the_geom, var_pt) As intpt, e.statefp, a.side, a.fromhn, a.tohn, ST_Distance_Sphere(e.the_geom, var_pt) As dist\r
FROM edges AS e INNER JOIN state As s ON (e.statefp = s.statefp AND s.statefp = ANY(var_states) )\r
INNER JOIN faces As fl ON (e.tfidl = fl.tfid AND e.statefp = fl.statefp)\r
INNER JOIN faces As fr ON (e.tfidr = fr.tfid AND e.statefp = fr.statefp)\r
INNER JOIN addr As a ON ( e.tlid = a.tlid AND e.statefp = a.statefp AND \r
- ( ( ST_Contains(fl.the_geom, pt) AND a.side = 'L') OR ( ST_Contains(fr.the_geom, pt) AND a.side = 'R' ) ) )\r
+ ( ( ST_Contains(fl.the_geom, var_pt) AND a.side = 'L') OR ( ST_Contains(fr.the_geom, var_pt) AND a.side = 'R' ) ) )\r
-- INNER JOIN zip_state_loc As z ON (a.statefp = z.statefp AND a.zip = z.zip) /** really slow with this join **/\r
- WHERE e.statefp = ANY(var_states) AND a.statefp = ANY(var_states) AND ST_DWithin(e.the_geom, pt, 0.005)\r
- ORDER BY ST_Distance_Sphere(e.the_geom, pt) LIMIT 4) As foo \r
+ WHERE e.statefp = ANY(var_states) AND a.statefp = ANY(var_states) AND ST_DWithin(e.the_geom, var_pt, 0.005)\r
+ ORDER BY ST_Distance_Sphere(e.the_geom, var_pt) LIMIT 4) As foo \r
WHERE dist < 150 --less than 150 m\r
ORDER BY foo.fullname, foo.dist) As f ORDER BY f.dist LOOP\r
IF var_primary_line IS NULL THEN --this is the first time in the loop and our primary guess\r
--interploate the number -- note that if fromhn > tohn we will be subtracting which is what we want\r
-- We only consider differential distances are reeally close from our primary pt\r
IF var_redge.dist < var_primary_dist*1.1 THEN \r
- var_strnum := (var_redge.fromhn + ST_Line_Locate_Point(var_redge.line, pt)*(var_redge.tohn - var_redge.fromhn))::numeric(10)::varchar;\r
+ var_strnum := (var_redge.fromhn + ST_Line_Locate_Point(var_redge.line, var_pt)*(var_redge.tohn - var_redge.fromhn))::numeric(10)::varchar;\r
var_addy := normalize_address( COALESCE(var_strnum::varchar || ' ', '') || var_redge.fullname || ', ' || var_redge.place || ', ' || var_redge.stusps || ' ' || var_redge.zip);\r
addy := array_append(addy, var_addy);\r
END IF;\r