| 1 | == This is an area to put utility functions or wrappers around PostGIS == |
| 2 | |
| 3 | * '''Find UTM (WGS84) SRID for a point (in any SRID)''' |
| 4 | |
| 5 | {{{ |
| 6 | -- Function: utmzone(geometry) |
| 7 | -- DROP FUNCTION utmzone(geometry); |
| 8 | |
| 9 | CREATE OR REPLACE FUNCTION utmzone(geometry) |
| 10 | RETURNS integer AS |
| 11 | $BODY$ |
| 12 | DECLARE |
| 13 | geomgeog geometry; |
| 14 | zone int; |
| 15 | pref int; |
| 16 | |
| 17 | BEGIN |
| 18 | geomgeog:=transform($1,4326); |
| 19 | |
| 20 | IF (y(geomgeog))>0 THEN |
| 21 | pref:=32600; |
| 22 | ELSE |
| 23 | pref:=32700; |
| 24 | END IF; |
| 25 | |
| 26 | zone:=floor((x(geomgeog)+180)/6)+1; |
| 27 | |
| 28 | RETURN zone+pref; |
| 29 | END; |
| 30 | $BODY$ LANGUAGE 'plpgsql' IMMUTABLE |
| 31 | COST 100; |
| 32 | }}} |
| 33 | |
| 34 | * '''Find Length of Day for a given location and date''' |
| 35 | {{{ |
| 36 | CREATE OR REPLACE FUNCTION daylength(geometry, date) |
| 37 | RETURNS double precision AS 'select 24*(ACOS(1-(1-TAN(radians(Y(transform($1,4326))))*TAN(.409088 * COS(.0172024 * extract(doy from $2)))))/PI());' |
| 38 | LANGUAGE 'sql'; |
| 39 | }}} |
| 40 | |
| 41 | * '''Rotate Geometry around a point(geom,x,y)''' |
| 42 | {{{ |
| 43 | CREATE OR REPLACE FUNCTION RotateAtPoint(geometry, double precision, double precision, double precision) |
| 44 | RETURNS geometry AS 'SELECT translate( rotate( translate( $1, -1*$2, -1*$3), $4), $2, $3)' |
| 45 | LANGUAGE 'sql'; |
| 46 | }}} |
| 47 | |
| 48 | * '''Create Ellipse (x,y,rx,ry,rotation,#of segments in 1/4 of ellipse)''' |
| 49 | {{{ |
| 50 | CREATE OR REPLACE FUNCTION Ellipse(double precision, double precision, double precision, double precision, double precision, integer) |
| 51 | RETURNS geometry AS |
| 52 | 'SELECT translate( rotate( scale( buffer(makepoint(0,0), 0.5, $6), $3, $4), $5), $1, $2)' |
| 53 | LANGUAGE 'sql'; |
| 54 | }}} |
| 55 | |
| 56 | * '''Return a multilinestring consisting of the interior and exterior rings of a polygon/multipolygon''' |
| 57 | |
| 58 | ''This already exists in PostGIS: see ST_Boundary(geometry)'' |
| 59 | |
| 60 | {{{ |
| 61 | Example use: - where the_geom is a multipolygon |
| 62 | SELECT fnpoly_to_rings(the_geom) |
| 63 | FROM sometable |
| 64 | |
| 65 | CREATE OR REPLACE FUNCTION fnpoly_to_rings(geometry) |
| 66 | RETURNS geometry AS |
| 67 | $$ |
| 68 | SELECT collect(the_line) as multiline |
| 69 | FROM (SELECT ST_ExteriorRing(the_poly) as the_line |
| 70 | FROM (SELECT ST_GeometryN($1, g.n) As the_poly |
| 71 | FROM |
| 72 | generate_series(1, ST_NumGeometries($1)) As g(n) ) As polys |
| 73 | UNION ALL |
| 74 | SELECT ST_InteriorRingN(the_poly, |
| 75 | generate_series(1, ST_NumInteriorRings(the_poly))) as the_line |
| 76 | FROM (SELECT ST_GeometryN($1, g.n) As the_poly |
| 77 | FROM generate_series(1, ST_NumGeometries($1)) As g(n) ) As polys |
| 78 | ) As all_lines |
| 79 | $$ |
| 80 | LANGUAGE 'sql' IMMUTABLE; |
| 81 | COMMENT ON FUNCTION fnpoly_to_rings(geometry) IS 'Takes as argument a multipolygon or polygon and returns a multilinestring consisting of the interior and exterior rings of the polygon/multipolygon'; |
| 82 | |
| 83 | CREATE OR REPLACE FUNCTION upgis_!lineshift(centerline geometry, dist double precision) |
| 84 | RETURNS geometry AS |
| 85 | $$ |
| 86 | DECLARE |
| 87 | delx float; |
| 88 | dely float; |
| 89 | x0 float; |
| 90 | y0 float; |
| 91 | x1 float; |
| 92 | y1 float; |
| 93 | az float; |
| 94 | dir integer; |
| 95 | line geometry; |
| 96 | BEGIN |
| 97 | az := ST_Azimuth (ST_!StartPoint(centerline), ST_!EndPoint(centerline)); |
| 98 | dir := CASE WHEN az < pi() THEN -1 ELSE 1 END; |
| 99 | delx := ABS(COS(az)) * dist * dir; |
| 100 | dely := ABS(SIN(az)) * dist * dir; |
| 101 | |
| 102 | IF az > pi()/2 AND az < pi() OR az > 3 * pi()/2 THEN |
| 103 | line := ST_Translate(centerline, delx, dely) ; |
| 104 | ELSE |
| 105 | line := ST_Translate(centerline, -delx, dely); |
| 106 | END IF; |
| 107 | |
| 108 | RETURN line; |
| 109 | END; |
| 110 | $$ |
| 111 | LANGUAGE 'plpgsql' IMMUTABLE; |
| 112 | COMMENT ON FUNCTION upgis_lineshift(geometry, double precision) IS 'Takes a 2D line string and shifts it dist units along |
| 113 | the perpendicular defined by the straight line between the start and end point |
| 114 | Convention: (right is positive and left is negative. right being defined as to right of observer |
| 115 | standing at start point and looking down the end point)'; |
| 116 | }}} |
| 117 | |