Merge branch 'add-boundary-bbox-functions' into eliminate-quotes-in-ids
This commit is contained in:
@@ -185,7 +185,7 @@ $$ LANGUAGE plpgsql;
|
||||
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetBoundaryById(
|
||||
geometry_id text, -- ex: '36047'
|
||||
boundary_id text, -- ex: 'us.census.tiger.county'
|
||||
time_span text DEFAULT NULL --ex: '2009'
|
||||
time_span text DEFAULT NULL -- ex: '2009'
|
||||
)
|
||||
RETURNS geometry(geometry, 4326)
|
||||
AS $$
|
||||
@@ -196,29 +196,8 @@ DECLARE
|
||||
geom_colname text;
|
||||
BEGIN
|
||||
|
||||
EXECUTE
|
||||
format(
|
||||
$string$
|
||||
SELECT geoid_ct.colname As geoid_colname,
|
||||
tablename,
|
||||
geom_ct.colname As geom_colname
|
||||
FROM observatory.obs_column_table As geoid_ct,
|
||||
observatory.obs_table As geom_t,
|
||||
observatory.obs_column_table As geom_ct,
|
||||
observatory.obs_column As geom_c
|
||||
WHERE geoid_ct.column_id
|
||||
IN (
|
||||
SELECT source_id
|
||||
FROM observatory.obs_column_to_column
|
||||
WHERE reltype = 'geom_ref'
|
||||
AND target_id = '%s'
|
||||
)
|
||||
AND geoid_ct.table_id = geom_t.id and
|
||||
geom_t.id = geom_ct.table_id and
|
||||
geom_ct.column_id = geom_c.id and
|
||||
geom_c.type ILIKE 'geometry'
|
||||
$string$, boundary_id
|
||||
) INTO geoid_colname, target_table, geom_colname;
|
||||
SELECT * INTO geoid_colname, target_table, geom_colname
|
||||
FROM cdb_observatory._OBS_GetGeometryMetadata(boundary_id);
|
||||
|
||||
RAISE NOTICE '%', target_table;
|
||||
|
||||
@@ -242,3 +221,332 @@ BEGIN
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- _OBS_GetBoundariesByGeometry
|
||||
-- internal function for retrieving geometries based on an input geometry
|
||||
-- see OBS_GetBoundariesByGeometry or OBS_GetBoundariesByPointAndRadius for
|
||||
-- more information
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_observatory._OBS_GetBoundariesByGeometry(
|
||||
geom geometry(Geometry, 4326),
|
||||
boundary_id text,
|
||||
time_span text DEFAULT NULL,
|
||||
overlap_type text DEFAULT 'intersects')
|
||||
RETURNS TABLE(the_geom geometry, geom_refs text)
|
||||
AS $$
|
||||
DECLARE
|
||||
boundary geometry(Geometry, 4326);
|
||||
geom_colname text;
|
||||
geoid_colname text;
|
||||
target_table text;
|
||||
BEGIN
|
||||
|
||||
-- check inputs
|
||||
IF lower(overlap_type) NOT IN ('contains', 'intersects', 'within')
|
||||
THEN
|
||||
-- recognized overlap type (map to ST_Contains, ST_Intersects, and ST_Within)
|
||||
RAISE EXCEPTION 'Overlap type ''%'' is not an accepted type (choose intersects, within, or contains)', overlap_type;
|
||||
ELSIF ST_GeometryType(geom) NOT IN ('ST_Polygon', 'ST_MultiPolygon')
|
||||
THEN
|
||||
RAISE EXCEPTION 'Invalid geometry type (%), expecting ''ST_MultiPolygon'' or ''ST_Polygon''', ST_GeometryType(geom);
|
||||
END IF;
|
||||
|
||||
-- TODO: add timespan in search
|
||||
-- TODO: add overlap info in search
|
||||
SELECT * INTO geoid_colname, target_table, geom_colname
|
||||
FROM cdb_observatory._OBS_GetGeometryMetadata(boundary_id);
|
||||
|
||||
-- if no tables are found, raise notice and return null
|
||||
IF target_table IS NULL
|
||||
THEN
|
||||
RAISE NOTICE 'No boundaries found for bounding box ''%'' in ''%''', ST_AsText(geom), boundary_id;
|
||||
RETURN QUERY SELECT NULL::geometry, NULL::text;
|
||||
END IF;
|
||||
|
||||
RAISE NOTICE 'target_table: %', target_table;
|
||||
|
||||
-- return first boundary in intersections
|
||||
RETURN QUERY
|
||||
EXECUTE format(
|
||||
'SELECT t.%s, t.%s
|
||||
FROM observatory.%s As t
|
||||
WHERE ST_%s($1, t.the_geom)
|
||||
', geom_colname, geoid_colname, target_table, overlap_type)
|
||||
USING geom;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- OBS_GetBoundariesByGeometry
|
||||
--
|
||||
-- Given a bounding box (or a polygon), and it's geometry level (see
|
||||
-- OBS_ListGeomColumns() for all available boundary ids), give back the
|
||||
-- boundaries that are contained within the bounding box polygon and the
|
||||
-- associated geometry ids
|
||||
|
||||
-- Inputs:
|
||||
-- geom geometry: bounding box (or polygon) of the region of interest
|
||||
-- boundary_id text: source id of boundaries (e.g., us.census.tiger.county)
|
||||
-- see function OBS_ListGeomColumns for all avaiable
|
||||
-- boundary ids
|
||||
-- time_span text: time span that the geometries were collected (optional)
|
||||
--
|
||||
-- Output:
|
||||
-- table with the following columns
|
||||
-- boundary geometry: geometry boundary that is contained within the input
|
||||
-- bounding box at the requested geometry level
|
||||
-- with boundary_id, and time_span
|
||||
-- geom_refs text: geometry identifiers (e.g., geoid for the US Census)
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetBoundariesByGeometry(
|
||||
geom geometry(Geometry, 4326),
|
||||
boundary_id text,
|
||||
time_span text DEFAULT NULL,
|
||||
overlap_type text DEFAULT 'intersects')
|
||||
RETURNS TABLE(the_geom geometry, geom_refs text)
|
||||
AS $$
|
||||
BEGIN
|
||||
|
||||
RETURN QUERY SELECT *
|
||||
FROM cdb_observatory._OBS_GetBoundariesByGeometry(
|
||||
geom,
|
||||
boundary_id,
|
||||
time_span,
|
||||
overlap_type
|
||||
);
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- OBS_GetBoundariesByPointAndRadius
|
||||
--
|
||||
-- Given a point and radius, and it's geometry level (see
|
||||
-- OBS_ListGeomColumns() for all available boundary ids), give back the
|
||||
-- boundaries that are contained within the point buffered by radius meters and
|
||||
-- the associated geometry ids
|
||||
|
||||
-- Inputs:
|
||||
-- geom geometry: point geometry centered on area of interest
|
||||
-- radius numeric: radius (in meters) of a circle centered on geom for
|
||||
-- selecting polygons
|
||||
-- boundary_id text: source id of boundaries (e.g., us.census.tiger.county)
|
||||
-- see function OBS_ListGeomColumns for all avaiable
|
||||
-- boundary ids
|
||||
-- time_span text: time span that the geometries were collected (optional)
|
||||
--
|
||||
-- Output:
|
||||
-- table with the following columns
|
||||
-- boundary geometry: geometry boundary that is contained within the input
|
||||
-- bounding box at the requested geometry level
|
||||
-- with boundary_id, and time_span
|
||||
-- geom_refs text: geometry identifiers (e.g., geoid for the US Census)
|
||||
--
|
||||
-- TODO: move to ST_DWithin instead of buffer + intersects?
|
||||
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetBoundariesByPointAndRadius(
|
||||
geom geometry(Geometry, 4326), -- point
|
||||
radius numeric, -- radius in meters
|
||||
boundary_id text,
|
||||
time_span text DEFAULT NULL,
|
||||
overlap_type text DEFAULT 'intersects')
|
||||
RETURNS TABLE(the_geom geometry, geom_refs text)
|
||||
AS $$
|
||||
DECLARE
|
||||
circle_boundary geometry(Geometry, 4326);
|
||||
BEGIN
|
||||
|
||||
IF ST_GeometryType(geom) != 'ST_Point'
|
||||
THEN
|
||||
RAISE EXCEPTION 'Input geometry ''%'' is not a point', ST_AsText(geom);
|
||||
ELSE
|
||||
circle_boundary := ST_Buffer(geom::geography, radius)::geometry;
|
||||
END IF;
|
||||
|
||||
RETURN QUERY SELECT *
|
||||
FROM cdb_observatory._OBS_GetBoundariesByGeometry(
|
||||
circle_boundary,
|
||||
boundary_id,
|
||||
time_span);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- _OBS_GetPointsByGeometry
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_observatory._OBS_GetPointsByGeometry(
|
||||
geom geometry(Geometry, 4326),
|
||||
boundary_id text,
|
||||
time_span text DEFAULT NULL,
|
||||
overlap_type text DEFAULT 'intersects')
|
||||
RETURNS TABLE(the_geom geometry, geom_refs text)
|
||||
AS $$
|
||||
DECLARE
|
||||
boundary geometry(Geometry, 4326);
|
||||
geom_colname text;
|
||||
geoid_colname text;
|
||||
target_table text;
|
||||
BEGIN
|
||||
|
||||
IF lower(overlap_type) NOT IN ('contains', 'within', 'intersects')
|
||||
THEN
|
||||
RAISE EXCEPTION 'Overlap type ''%'' is not an accepted type (choose intersects, within, or contains)', overlap_type;
|
||||
ELSIF ST_GeometryType(geom) NOT IN ('ST_Polygon', 'ST_MultiPolygon')
|
||||
THEN
|
||||
RAISE EXCEPTION 'Invalid geometry type (%), expecting ''ST_MultiPolygon'' or ''ST_Polygon''', ST_GeometryType(geom);
|
||||
END IF;
|
||||
|
||||
SELECT * INTO geoid_colname, target_table, geom_colname
|
||||
FROM cdb_observatory._OBS_GetGeometryMetadata(boundary_id);
|
||||
|
||||
-- if no tables are found, raise notice and return null
|
||||
IF target_table IS NULL
|
||||
THEN
|
||||
RAISE NOTICE 'No boundaries found for bounding box ''%'' in ''%''', ST_AsText(geom), boundary_id;
|
||||
RETURN QUERY SELECT NULL::geometry, NULL::text;
|
||||
END IF;
|
||||
|
||||
RAISE NOTICE 'target_table: %', target_table;
|
||||
|
||||
-- return first boundary in intersections
|
||||
RETURN QUERY
|
||||
EXECUTE format(
|
||||
'SELECT ST_PointOnSurface(t.%s) As %s, t.%s
|
||||
FROM observatory.%s As t
|
||||
WHERE ST_%s($1, t.the_geom)
|
||||
', geom_colname, geom_colname, geoid_colname, target_table, overlap_type)
|
||||
USING geom;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- OBS_GetPointsByGeometry
|
||||
--
|
||||
-- Given a polygon, and it's geometry level (see
|
||||
-- OBS_ListGeomColumns() for all available boundary ids), give back a point
|
||||
-- which lies in a boundary from the requested geometry level that is contained
|
||||
-- within the bounding box polygon and the associated geometry ids
|
||||
--
|
||||
-- Inputs:
|
||||
-- geom geometry: bounding box (or polygon) of the region of interest
|
||||
-- boundary_id text: source id of boundaries (e.g., us.census.tiger.county)
|
||||
-- see function OBS_ListGeomColumns for all avaiable
|
||||
-- boundary ids
|
||||
-- time_span text: time span that the geometries were collected (optional)
|
||||
--
|
||||
-- Output:
|
||||
-- table with the following columns
|
||||
-- boundary geometry: point that lies on a boundary that is contained within
|
||||
-- the input bounding box at the requested geometry
|
||||
-- level with boundary_id, and time_span
|
||||
-- geom_refs text: geometry identifiers (e.g., geoid for the US Census)
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetPointsByGeometry(
|
||||
geom geometry(Geometry, 4326),
|
||||
boundary_id text,
|
||||
time_span text DEFAULT NULL,
|
||||
overlap_type text DEFAULT 'intersects')
|
||||
RETURNS TABLE(the_geom geometry, geom_refs text)
|
||||
AS $$
|
||||
BEGIN
|
||||
|
||||
RETURN QUERY SELECT *
|
||||
FROM cdb_observatory._OBS_GetPointsByGeometry(
|
||||
geom,
|
||||
boundary_id,
|
||||
time_span,
|
||||
overlap_type);
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- OBS_GetBoundariesByPointAndRadius
|
||||
--
|
||||
-- Given a point and radius, and it's geometry level (see
|
||||
-- OBS_ListGeomColumns() for all available boundary ids), give back the
|
||||
-- boundaries that are contained within the point buffered by radius meters and
|
||||
-- the associated geometry ids
|
||||
|
||||
-- Inputs:
|
||||
-- geom geometry: point geometry centered on area of interest
|
||||
-- radius numeric: radius (in meters) of a circle centered on geom for
|
||||
-- selecting polygons
|
||||
-- boundary_id text: source id of boundaries (e.g., us.census.tiger.county)
|
||||
-- see function OBS_ListGeomColumns for all avaiable
|
||||
-- boundary ids
|
||||
-- time_span text: time span that the geometries were collected (optional)
|
||||
--
|
||||
-- Output:
|
||||
-- table with the following columns
|
||||
-- boundary geometry: geometry boundary that is contained within the input
|
||||
-- bounding box at the requested geometry level
|
||||
-- with boundary_id, and time_span
|
||||
-- geom_refs text: geometry identifiers (e.g., geoid for the US Census)
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetPointsByPointAndRadius(
|
||||
geom geometry(Geometry, 4326), -- point
|
||||
radius numeric, -- radius in meters
|
||||
boundary_id text,
|
||||
time_span text DEFAULT NULL,
|
||||
overlap_type text DEFAULT 'intersects')
|
||||
RETURNS TABLE(the_geom geometry, geom_refs text)
|
||||
AS $$
|
||||
DECLARE
|
||||
circle_boundary geometry(Geometry, 4326);
|
||||
BEGIN
|
||||
|
||||
IF ST_GeometryType(geom) != 'ST_Point'
|
||||
THEN
|
||||
RAISE EXCEPTION 'Input geometry ''%'' is not a point', ST_AsText(geom);
|
||||
ELSE
|
||||
circle_boundary := ST_Buffer(geom::geography, radius)::geometry;
|
||||
END IF;
|
||||
|
||||
RETURN QUERY SELECT *
|
||||
FROM cdb_observatory._OBS_GetPointsByGeometry(
|
||||
ST_Buffer(geom::geography, radius)::geometry,
|
||||
boundary_id,
|
||||
time_span,
|
||||
overlap_type);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
-- _OBS_GetGeometryMetadata()
|
||||
-- TODO: add timespan in search
|
||||
-- TODO: add choice of clipped versus not clipped
|
||||
CREATE OR REPLACE FUNCTION cdb_observatory._OBS_GetGeometryMetadata(boundary_id text)
|
||||
RETURNS table(geoid_colname text, target_table text, geom_colname text)
|
||||
AS $$
|
||||
BEGIN
|
||||
|
||||
RETURN QUERY
|
||||
EXECUTE
|
||||
format($string$
|
||||
SELECT geoid_ct.colname As geoid_colname,
|
||||
tablename,
|
||||
geom_ct.colname As geom_colname
|
||||
FROM observatory.obs_column_table As geoid_ct,
|
||||
observatory.obs_table As geom_t,
|
||||
observatory.obs_column_table As geom_ct,
|
||||
observatory.obs_column As geom_c
|
||||
WHERE geoid_ct.column_id
|
||||
IN (
|
||||
SELECT source_id
|
||||
FROM observatory.obs_column_to_column
|
||||
WHERE reltype = 'geom_ref'
|
||||
AND target_id = '%s'
|
||||
)
|
||||
AND geoid_ct.table_id = geom_t.id AND
|
||||
geom_t.id = geom_ct.table_id AND
|
||||
geom_ct.column_id = geom_c.id AND
|
||||
geom_c.type ILIKE 'geometry'
|
||||
LIMIT 1
|
||||
$string$, boundary_id);
|
||||
-- AND geom_t.timespan = '%s' <-- put in requested year
|
||||
-- TODO: filter by clipped vs. not so appropriate tablename are unique
|
||||
-- so the limit 1 can be removed
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
Reference in New Issue
Block a user