diff --git a/src/pg/sql/30_dot_density.sql b/src/pg/sql/30_dot_density.sql index e5c4f81..40aafcb 100644 --- a/src/pg/sql/30_dot_density.sql +++ b/src/pg/sql/30_dot_density.sql @@ -25,7 +25,7 @@ AS $$ no_left INTEGER; sample_points GEOMETRY[]; points GEOMETRY[]; - BEGIN + BEGIN eq_area_geom := ST_TRANSFORM(g,2163); extent := ST_Envelope(eq_area_geom); max_iter := 0; @@ -34,29 +34,29 @@ AS $$ x0 := ST_XMin(extent); y0 := ST_YMin(extent); no_left := no_points; - + LOOP IF(no_left<=0 or max_iter=1000) THEN RETURN; END IF; - - with random_points as( + + 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,4236) from unnest(sample_points) as a; - - IF sample_points IS NOT null THEN + + 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; max_iter = max_iter + 1; END LOOP; - + RETURN; END $$ LANGUAGE plpgsql; @@ -67,7 +67,7 @@ $$ LANGUAGE plpgsql; -- @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. @@ -90,7 +90,7 @@ CREATE OR REPLACE function _cdb_SelectRandomWeights(array_ids numeric[], weights DECLARE result NUMERIC; BEGIN - + WITH idw as ( select unnest(array_ids) as id, unnest(weights) as percent ), @@ -110,29 +110,29 @@ CREATE OR REPLACE function _cdb_SelectRandomWeights(array_ids numeric[], weights END $$ LANGUAGE plpgsql; --- +-- -- Weighted Dot Density -- --- @param no_points the number of points to generate +-- @param no_points the number of points to generate -- --- @param geoms the target geometries to place the points in +-- @param geoms the target geometries to place the points in -- -- @param weights the weight for each of the target polygons -- --- RETURNS set of points +-- RETURNS set of points CREATE OR REPLACE FUNCTION _cdb_WeightedDD(no_points numeric, geoms geometry[], weights numeric[]) RETURNS SETOF geometry AS $$ -DECLARE +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 generate_series(1,array_upper(geoms,1)) as id + ) select array_agg(id) from idseries into ids; FOR i in 1..no_points @@ -153,28 +153,28 @@ $$ LANGUAGE plpgsql; --- +-- -- Daysymetric Dot Density -- --- @param geom: the geometry that has the +-- @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 no_points: the total number of points to create +-- +-- @param targetGeoms: the geometry that has the -- -- @param weights: targetGeom weights -- --- RETURNS setof points +-- RETURNS setof points CREATE OR REPLACE FUNCTION CDB_DasymetricDotDensity(geom GEOMETRY, no_points NUMERIC, targetGeoms GEOMETRY[], weights numeric []) -RETURNS setof GEOMETRY +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 + 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;