Skip to content

Instantly share code, notes, and snippets.

@geozelot
Last active January 7, 2022 20:08
Show Gist options
  • Save geozelot/33b3f92f45039db8dea6bb2c9e2d8b46 to your computer and use it in GitHub Desktop.
Save geozelot/33b3f92f45039db8dea6bb2c9e2d8b46 to your computer and use it in GitHub Desktop.
PostgreSQL/PostGIS - Create a wedge of a buffer around a point, with optional inner radius
/*
* @params
* pnt - center POINT geometry
* sdeg - wedge sector start value; in degrees
* edeg - wedge sector end value; in degrees
* irad - radius around @pnt for the inner extend of the wedge; in meter
* orad - radius around @pnt for the outer extend of the wedge; in meter
* qsegs - vertices per full quarter circle; at least two vertices will be created
*
* The function will calculate the angular difference in clockwise direction, from @sdeg to @edeg.
* @irad defaults to 0 to get a wedge including the center POINT geometry (full wedge)
*/
CREATE OR REPLACE FUNCTION ST_PointBufferWedge(
pnt GEOMETRY(POINT),
sdeg FLOAT,
edeg FLOAT,
orad FLOAT,
irad FLOAT DEFAULT 0,
qsegs INT DEFAULT 8
) RETURNS GEOMETRY(POLYGON) AS
$$
DECLARE
srid INT;
tdelta FLOAT;
otvert INT;
otstep FLOAT;
itvert INT;
itstep FLOAT;
wedge GEOMETRY(POINT)[];
BEGIN
srid := ST_SRID($1);
tdelta := CASE ($2 <= $3) WHEN TRUE THEN $3-$2 ELSE 360.0-$2+$3 END;
otvert := GREATEST($6 * (FLOOR(tdelta)/90), 2);
otstep := tdelta/otvert;
itvert := CASE irad > 0 WHEN TRUE THEN GREATEST((otvert * ($5/$4))::INT, $6/2) ELSE 1 END;
itstep := COALESCE(NULLIF(tdelta/itvert, tdelta), 0);
FOR n IN 0..itvert
LOOP
wedge := wedge || ST_Project($1::GEOGRAPHY, $5, RADIANS(MOD($3::NUMERIC-(n*itstep)::NUMERIC, 360.0::NUMERIC)))::GEOMETRY;
END LOOP
;
FOR n IN 0..otvert
LOOP
wedge := wedge || ST_Project($1::GEOGRAPHY, $4, RADIANS(MOD($2::NUMERIC+(n*otstep)::NUMERIC, 360.0::NUMERIC)))::GEOMETRY;
END LOOP
;
wedge := wedge || wedge[1];
RETURN ST_MakePolygon(ST_SetSRID(ST_MakeLine(wedge), srid));
END;
$$
LANGUAGE 'plpgsql';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment