Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
language: node_js
dist: bionic
node_js:
- "0.10"
- 10
sudo: false
services:
- postgresql
addons:
postgresql: 9.3
before_install:
postgresql: 10
apt:
packages:
- postgresql-10-postgis-2.4
before_script:
- psql -U postgres -c "create database testing_postgis_vt_util"
- psql -U postgres -d testing_postgis_vt_util -c "create extension postgis"
script:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ Filters small rings (both inner and outer) from a multipolygon based on area.
__Parameters:__

- `geometry` g - A multipolygon
- `float` area_threshold - the minimum ring area to keep.
- `anyelement` area_threshold - the minimum ring area to keep. Type must be either `float` or `integer`.

__Returns:__ `geometry` - a polygon or multipolygon

Expand Down
77 changes: 39 additions & 38 deletions postgis-vt-util.sql
Original file line number Diff line number Diff line change
Expand Up @@ -428,51 +428,52 @@ Filters small rings (both inner and outer) from a multipolygon based on area.
__Parameters:__

- `geometry` g - A multipolygon
- `float` area_threshold - the minimum ring area to keep.
- `anyelement` area_threshold - the minimum ring area to keep. Type must be either `float` or `integer`.

__Returns:__ `geometry` - a polygon or multipolygon
******************************************************************************/
create or replace function Sieve (g geometry, area_threshold float)
create or replace function Sieve (g geometry, area_threshold anyelement)
returns geometry
language sql immutable as
$func$
with exploded as (
-- First use ST_Dump to explode the input multipolygon
-- to individual polygons.
select (ST_Dump(g)).geom
), rings as (
-- Next use ST_DumpRings to turn all of the inner and outer rings
-- into their own separate polygons.
select (ST_DumpRings(geom)).geom from exploded
) select
-- Finally, build the multipolygon back up using only the rings
-- that are larger than the specified threshold area.
ST_SetSRID(ST_BuildArea(ST_Collect(geom)), ST_SRID(g))
from rings
where ST_Area(geom) > area_threshold;
$func$;

create or replace function Sieve (g geometry, area_threshold integer)
returns geometry
language sql immutable as
language plpgsql immutable as
$func$
with exploded as (
-- First use ST_Dump to explode the input multipolygon
-- to individual polygons.
select (ST_Dump(g)).geom
), rings as (
-- Next use ST_DumpRings to turn all of the inner and outer rings
-- into their own separate polygons.
select (ST_DumpRings(geom)).geom from exploded
) select
-- Finally, build the multipolygon back up using only the rings
-- that are larger than the specified threshold area.
ST_SetSRID(ST_BuildArea(ST_Collect(geom)), ST_SRID(g))
from rings
where ST_Area(geom) > area_threshold;
$func$;
begin

-- DRY up code by defining one function for both integer and float inputs
-- define an empty polygon for the error detail to maintain geometry return type for any
-- functions that wrap this and expect a geometry to come back when we raise an exception
if pg_typeof(area_threshold) != all(array['integer', 'float']::regtype[]) then
raise exception using
errcode='INVAL',
message='Invalid parameter input in sieve- area_threshold must be either integer or float.',
detail=ST_GeomFromText('POLYGON EMPTY', ST_SRID(g));
end if;

if not st_isvalid(g) then
raise exception using
errcode='INVAL',
message='Invalid input geometry in sieve- will return null. See exception detail for location.',
detail=ST_SetSRID(location(ST_IsValidDetail(g)), ST_SRID(g));
end if;

return (
with exploded as (
-- First use ST_Dump to explode the input multipolygon
-- to individual polygons.
select (ST_Dump(g)).geom
), rings as (
-- Next use ST_DumpRings to turn all of the inner and outer rings
-- into their own separate polygons.
select (ST_DumpRings(geom)).geom from exploded
) select
-- Finally, build the multipolygon back up using only the rings
-- that are larger than the specified threshold area.
ST_SetSRID(ST_BuildArea(ST_Collect(geom)), ST_SRID(g))
from rings
where ST_Area(geom) > area_threshold
);

end;
$func$;
/******************************************************************************
### SmartShrink ###

Expand Down
75 changes: 38 additions & 37 deletions src/Sieve.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,49 @@ Filters small rings (both inner and outer) from a multipolygon based on area.
__Parameters:__

- `geometry` g - A multipolygon
- `float` area_threshold - the minimum ring area to keep.
- `anyelement` area_threshold - the minimum ring area to keep. Type must be either `float` or `integer`.

__Returns:__ `geometry` - a polygon or multipolygon
******************************************************************************/
create or replace function Sieve (g geometry, area_threshold float)
create or replace function Sieve (g geometry, area_threshold anyelement)
returns geometry
language sql immutable as
language plpgsql immutable as
$func$
with exploded as (
-- First use ST_Dump to explode the input multipolygon
-- to individual polygons.
select (ST_Dump(g)).geom
), rings as (
-- Next use ST_DumpRings to turn all of the inner and outer rings
-- into their own separate polygons.
select (ST_DumpRings(geom)).geom from exploded
) select
-- Finally, build the multipolygon back up using only the rings
-- that are larger than the specified threshold area.
ST_SetSRID(ST_BuildArea(ST_Collect(geom)), ST_SRID(g))
from rings
where ST_Area(geom) > area_threshold;
$func$;
begin

create or replace function Sieve (g geometry, area_threshold integer)
returns geometry
language sql immutable as
$func$
with exploded as (
-- First use ST_Dump to explode the input multipolygon
-- to individual polygons.
select (ST_Dump(g)).geom
), rings as (
-- Next use ST_DumpRings to turn all of the inner and outer rings
-- into their own separate polygons.
select (ST_DumpRings(geom)).geom from exploded
) select
-- Finally, build the multipolygon back up using only the rings
-- that are larger than the specified threshold area.
ST_SetSRID(ST_BuildArea(ST_Collect(geom)), ST_SRID(g))
from rings
where ST_Area(geom) > area_threshold;
$func$;
-- DRY up code by defining one function for both integer and float inputs
-- define an empty polygon for the error detail to maintain geometry return type for any
-- functions that wrap this and expect a geometry to come back when we raise an exception
if pg_typeof(area_threshold) != all(array['integer', 'float']::regtype[]) then
raise exception using
errcode='INVAL',
message='Invalid parameter input in sieve- area_threshold must be either integer or float.',
detail=ST_GeomFromText('POLYGON EMPTY', ST_SRID(g));
end if;

if not st_isvalid(g) then
raise exception using
errcode='INVAL',
message='Invalid input geometry in sieve- will return null. See exception detail for location.',
detail=ST_SetSRID(location(ST_IsValidDetail(g)), ST_SRID(g));
end if;

return (
with exploded as (
-- First use ST_Dump to explode the input multipolygon
-- to individual polygons.
select (ST_Dump(g)).geom
), rings as (
-- Next use ST_DumpRings to turn all of the inner and outer rings
-- into their own separate polygons.
select (ST_DumpRings(geom)).geom from exploded
) select
-- Finally, build the multipolygon back up using only the rings
-- that are larger than the specified threshold area.
ST_SetSRID(ST_BuildArea(ST_Collect(geom)), ST_SRID(g))
from rings
where ST_Area(geom) > area_threshold
);

end;
$func$;
2 changes: 1 addition & 1 deletion test/sql-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ tf ToPoint "ST_GeomFromText('MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)))',9009
tf ToPoint "ST_GeomFromText('MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)), ((20 20, 30 20, 30 30, 20 30, 20 20)))',900913)" \
"010100002031BF0D0000000000000014400000000000001440"
tf ST_AsText "ToPoint(ST_GeomFromText('POLYGON((50 5,10 8,10 10,100 190,150 30,150 10,50 5))',900913))" \
"POINT(91.328125 97.5)"
"POINT(92.5 110)"


# Z
Expand Down