Compare commits

...

13 Commits

Author SHA1 Message Date
mehak-sachdeva
e479f84cf9 syntax 2017-02-10 16:32:05 -05:00
mehak-sachdeva
f9c1b57dfd added the deprecated function signature as a wrapper to the new function 2017-02-10 15:27:56 -05:00
Andy Eschbacher
4c175c9565 correct srid in final argument 2017-01-06 14:12:42 -05:00
Mario de Frutos
de6f228e72 Remove old configuration for postgresql 9.5 in travis 2016-12-02 13:08:45 +01:00
Mario de Frutos
87f9b2c787 Merge branch 'develop' into better_dot_density 2016-12-02 12:48:31 +01:00
Stuart Lynn
fda5d93cf4 Adding geometry types to function signature 2016-12-01 11:09:55 -05:00
Mario de Frutos
0748212610 Fixing travis config 2016-12-01 14:58:22 +01:00
Mario de Frutos
27b18f5e1c Merge branch 'develop' into better_dot_density 2016-12-01 13:02:11 +01:00
Mario de Frutos
3649f958c8 Update travis yml to the new postgres-9.5 package 2016-12-01 13:00:28 +01:00
Stuart Lynn
faaf5e419a Merge branch 'master' into better_dot_density 2016-11-30 22:35:00 +00:00
Stuart Lynn
1f3b74e54f dot density fixes for geom's with holes and equal area 2016-11-30 22:34:46 +00:00
Javier Villar
2bc6b0782a Adding requirements.txt to master branch 2016-10-21 16:28:17 +02:00
Stuart Lynn
b8fe05b388 CDB_DasymetricDotDensity and fixed for basic DD 2016-10-03 21:22:40 +00:00
4 changed files with 190 additions and 68 deletions

View File

@@ -36,7 +36,10 @@ before_install:
- sudo apt-get -y remove --purge postgresql-9.3
- sudo apt-get -y remove --purge postgresql-9.4
- sudo apt-get -y remove --purge postgresql-9.5
- sudo apt-get -y remove --purge postgis
- sudo rm -rf /var/lib/postgresql/
- sudo rm -rf /var/log/postgresql/
- sudo rm -rf /etc/postgresql/
- sudo apt-get -y remove --purge postgis-2.2
- sudo apt-get -y autoremove
- sudo apt-get -y install postgresql-9.5=9.5.2-3cdb2

View File

@@ -10,45 +10,192 @@
-- misses per point the funciton accepts before giving up.
--
-- Returns: Multipoint with the requested points
CREATE OR REPLACE FUNCTION cdb_dot_density(geom geometry , no_points Integer, max_iter_per_point Integer DEFAULT 1000)
RETURNS GEOMETRY AS $$
DECLARE
extent GEOMETRY;
test_point Geometry;
width NUMERIC;
height NUMERIC;
x0 NUMERIC;
y0 NUMERIC;
xp NUMERIC;
yp NUMERIC;
no_left INTEGER;
remaining_iterations INTEGER;
points GEOMETRY[];
bbox_line GEOMETRY;
intersection_line GEOMETRY;
BEGIN
extent := ST_Envelope(geom);
width := ST_XMax(extent) - ST_XMIN(extent);
height := ST_YMax(extent) - ST_YMIN(extent);
x0 := ST_XMin(extent);
y0 := ST_YMin(extent);
no_left := no_points;
LOOP
if(no_left=0) THEN
EXIT;
END IF;
yp = y0 + height*random();
bbox_line = ST_MakeLine(
ST_SetSRID(ST_MakePoint(yp, x0),4326),
ST_SetSRID(ST_MakePoint(yp, x0+width),4326)
);
intersection_line = ST_Intersection(bbox_line,geom);
test_point = ST_LineInterpolatePoint(st_makeline(st_linemerge(intersection_line)),random());
points := points || test_point;
no_left = no_left - 1 ;
END LOOP;
RETURN ST_Collect(points);
CREATE OR REPLACE FUNCTION CDB_DotDensity(g geometry(Polygon, 4326), no_points integer, max_iter integer DEFAULT 1000)
RETURNS SETOF geometry(Point, 4326)
AS $$
DECLARE
extent GEOMETRY;
eq_area_geom GEOMETRY;
test_point Geometry;
iter NUMERIC;
width NUMERIC;
height NUMERIC;
x0 NUMERIC;
y0 NUMERIC;
no_left INTEGER;
sample_points GEOMETRY[];
points GEOMETRY[];
BEGIN
eq_area_geom := ST_TRANSFORM(g, 2163);
extent := ST_Envelope(eq_area_geom);
iter := 0;
width := ST_XMax(extent) - ST_XMIN(extent);
height := ST_YMax(extent) - ST_YMIN(extent);
x0 := ST_XMin(extent);
y0 := ST_YMin(extent);
no_left := no_points;
LOOP
IF(no_left <= 0 or iter >= max_iter) THEN
RETURN;
END IF;
with random_points as(
SELECT ST_SetSRID(ST_MAKEPOINT( x0 + width*random(), y0 + height*random()), 2163) as p
FROM generate_series(1,no_left)
)
SELECT array_agg(p) from random_points
WHERE ST_WITHIN(p, eq_area_geom)
into sample_points;
RETURN QUERY select ST_TRANSFORM(a, 4326) from unnest(sample_points) as a;
IF sample_points IS NOT null THEN
no_left := no_left - array_length(sample_points, 1);
END IF;
iter = iter + 1;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
-- DEPRECATED
CREATE OR REPLACE FUNCTION cdb_dot_density(geom geometry, no_points Integer, max_iter_per_point Integer DEFAULT 1000)
RETURNS GEOMETRY
AS $$
DECLARE
final_points GEOMETRY;
BEGIN
with new_points as(
SELECT * FROM CDB_DotDensity(geom, no_points, max_iter_per_point) as a
)
SELECT ST_Collect(a) FROM new_points
into final_points;
RETURN final_points;
END;
$$ LANGUAGE plpgsql;
--
-- Creates N points randomly distributed in the specified secondary polygons
--
-- @param g - array of the geometries to be turned in to points
--
-- @param no_points - the number of points to generate
--
-- @params max_iter_per_point - the function generates points in the polygon's bounding box
-- and discards points which don't lie in the polygon. max_iter_per_point specifies how many
-- misses per point the funciton accepts before giving up.
--
-- Returns: Multipoint with the requested points
--
-- Generate a random response based on the weights given
--
-- @param array_ids an array of ids representing the category to return
--
-- @param weights an array of weights for each category
--
-- Returns : The randomly selected ID.
CREATE OR REPLACE function _cdb_SelectRandomWeights(array_ids numeric[], weights numeric[]) returns NUMERIC
as $$
DECLARE
result NUMERIC;
BEGIN
WITH idw as (
select unnest(array_ids) as id, unnest(weights) as percent
),
CTE AS (
SELECT random() * (SELECT SUM(percent) FROM idw) R
)
SELECT *
FROM (
SELECT id, SUM(percent) OVER (ORDER BY id) S, R
FROM idw as percent CROSS JOIN CTE
) Q
WHERE S >= R
ORDER BY id
LIMIT 1
into result;
return result;
END
$$ LANGUAGE plpgsql;
--
-- Weighted Dot Density
--
-- @param no_points the number of points to generate
--
-- @param geoms the target geometries to place the points in
--
-- @param weights the weight for each of the target polygons
--
-- RETURNS set of points
CREATE OR REPLACE FUNCTION _cdb_WeightedDD(no_points numeric, geoms geometry[], weights numeric[])
RETURNS SETOF geometry
AS $$
DECLARE
i NUMERIC;
ids NUMERIC[];
perGeom NUMERIC[];
selected_poly NUMERIC;
BEGIN
with idseries as (
select generate_series(1,array_upper(geoms,1)) as id
)
select array_agg(id) from idseries into ids;
FOR i in 1..no_points
LOOP
select cdb_crankshaft._cdb_SelectRandomWeights(ids, weights) INTO selected_poly;
perGeom[selected_poly] = coalesce(perGeom[selected_poly] + 1, 0 );
END LOOP;
raise notice 'pergeom %', perGeom;
FOR i in 1..array_length(ids,1)
LOOP
return QUERY
select cdb_crankshaft.CDB_DotDensity(geoms[i], coalesce(perGeom[i],0)::INTEGER);
END LOOP;
END
$$
LANGUAGE plpgsql VOLATILE;
LANGUAGE plpgsql;
--
-- Daysymetric Dot Density
--
-- @param geom: the geometry that has the
--
-- @param no_points: the total number of points to create
--
-- @param targetGeoms: the geometry that has the
--
-- @param weights: targetGeom weights
--
-- RETURNS setof points
CREATE OR REPLACE FUNCTION CDB_DasymetricDotDensity(geom GEOMETRY, no_points NUMERIC, targetGeoms GEOMETRY[], weights numeric [])
RETURNS setof GEOMETRY
AS $$
BEGIN
RAISE NOTICE 'running Dasymetric';
RETURN QUERY
SELECT cdb_crankshaft._CDB_WeightedDD(no_points, array_agg( ST_INTERSECTION(geom,g)), array_agg(ST_AREA(ST_INTERSECTION(geom,g))*w)::NUMERIC[])
FROM unnest(targetGeoms) as g , unnest(weights) as w
WHERE geom && g;
END
$$
LANGUAGE plpgsql;

View File

@@ -1,16 +0,0 @@
WITH g AS (
SELECT ST_Buffer(ST_SetSRID(ST_MakePoint(0,0),4326)::geometry, 1000)::geometry AS g
),
points AS(
SELECT (
ST_Dump(
cdb_crankshaft.cdb_dot_density(g.g, 100)
)
).geom AS p FROM g
)
SELECT count(*), sum(CASE WHEN ST_Contains(g,p) THEN 1 ELSE 0 END) FROM points, g
count | sum
-------+-----
100 | 100
(1 row)

View File

@@ -1,12 +0,0 @@
WITH g AS (
SELECT ST_Buffer(ST_SetSRID(ST_MakePoint(0,0),4326)::geometry, 1000)::geometry AS g
),
points AS(
SELECT (
ST_Dump(
cdb_crankshaft.cdb_dot_density(g.g, 100)
)
).geom AS p FROM g
)
SELECT count(*), sum(CASE WHEN ST_Contains(g,p) THEN 1 ELSE 0 END) FROM points, g