From cb3a49594d75db1c01fb7e1ce4b519f8936c7445 Mon Sep 17 00:00:00 2001 From: abelvm Date: Tue, 12 Jul 2016 15:48:38 +0200 Subject: [PATCH 01/16] add PIA, first commit --- doc/09_voronoi.md | 35 ---- doc/13_PIA.md | 30 ++++ src/pg/sql/09_voronoi.sql | 205 ----------------------- src/pg/sql/13_PIA.sql | 125 ++++++++++++++ src/pg/test/expected/09_voronoi_test.out | 5 - src/pg/test/expected/13_pia_test.out | 5 + src/pg/test/sql/09_voronoi_test.sql | 7 - src/pg/test/sql/13_pia_test.sql | 4 + 8 files changed, 164 insertions(+), 252 deletions(-) delete mode 100644 doc/09_voronoi.md create mode 100644 doc/13_PIA.md delete mode 100644 src/pg/sql/09_voronoi.sql create mode 100644 src/pg/sql/13_PIA.sql delete mode 100644 src/pg/test/expected/09_voronoi_test.out create mode 100644 src/pg/test/expected/13_pia_test.out delete mode 100644 src/pg/test/sql/09_voronoi_test.sql create mode 100644 src/pg/test/sql/13_pia_test.sql diff --git a/doc/09_voronoi.md b/doc/09_voronoi.md deleted file mode 100644 index 331f9ea..0000000 --- a/doc/09_voronoi.md +++ /dev/null @@ -1,35 +0,0 @@ -## Spacial interpolation - -Function to construct the [Voronoi Diagram](https://en.wikipedia.org/wiki/Voronoi_diagram) from a dataset of scatter points, clipped to the significant area - -PostGIS wil include this in future versions ([doc for dev branch](http://postgis.net/docs/manual-dev/ST_Voronoi.html)) and will perform faster for sure, but in the meantime... - - -### CDB_Voronoi (geom geometry[], buffer numeric DEFAULT 0.5, tolerance numeric DEFAULT 1e-9) - -#### Arguments - -| Name | Type | Description | -|------|------|-------------| -| geom | geometry[] | Array of points's geometries | -| buffer | numeric | enlargment ratio for the envelope area used for the restraints| -| tolerance | geometry | The target point to calc the value | - -### Returns - -| Column Name | Type | Description | -|-------------|------|-------------| -| geom | geometry collection | Collection of polygons of the Voronoi cells| - - -#### Example Usage - -```sql -WITH a AS ( - SELECT - ARRAY[ST_GeomFromText('POINT(2.1744 41.403)'),ST_GeomFromText('POINT(2.1228 41.380)'),ST_GeomFromText('POINT(2.1511 41.374)'),ST_GeomFromText('POINT(2.1528 41.413)'),ST_GeomFromText('POINT(2.165 41.391)'),ST_GeomFromText('POINT(2.1498 41.371)'),ST_GeomFromText('POINT(2.1533 41.368)'),ST_GeomFromText('POINT(2.131386 41.41399)')] AS geomin -) -SELECT - CDB_voronoi(geomin, 0.2, 1e-9) as result -FROM a; -``` diff --git a/doc/13_PIA.md b/doc/13_PIA.md new file mode 100644 index 0000000..35b980b --- /dev/null +++ b/doc/13_PIA.md @@ -0,0 +1,30 @@ +## Pole of inaccessibility (PIA) + +Function to find the [PIA](https://en.wikipedia.org/wiki/Pole_of_inaccessibility) from a given polygon and tolerance, following the quadtree approach by [Vladimir Agafonkin](https://github.com/mourner) described [here](https://github.com/mapbox/polylabel) + + + +### CDB_PIA (polygon geometry, tolerance numeric DEFAULT 1.0) + +#### Arguments + +| Name | Type | Description | +|------|------|-------------| +| polygon | geometry | Target polygon | +| tolerance | numeric | Threshold to decide to take a cell into account | + +### Returns + +| Column Name | Type | Description | +|-------------|------|-------------| +| point | geometry| Pole of inaccessibility | + + +#### Example Usage + +```sql +with a as( + select st_geomfromtext('POLYGON((-432540.453078056 4949775.20452642,-432329.947920966 4951361.232584,-431245.028163694 4952223.31516671,-429131.071033529 4951768.00415574,-424622.07505895 4952843.13503987,-423688.327170174 4953499.20752423,-424086.294349759 4954968.38274191,-423068.388925945 4954378.63345336,-423387.653225542 4953355.67417084,-420594.869840519 4953781.00230592,-416026.095299382 4951484.06849063,-412483.018546414 4951024.5410983,-410490.399661215 4954502.24032205,-408186.197521284 4956398.91417441,-407627.262358013 4959300.94633864,-406948.770061627 4959874.85407739,-404949.583326472 4959047.74518163,-402570.908447199 4953743.46829807,-400971.358683991 4952193.11680804,-403533.488084088 4949649.89857885,-406335.177028373 4950193.19571096,-407790.456731515 4952391.46015616,-412060.672398345 4950381.2389307,-410716.93482498 4949156.7509561,-408464.162289794 4943912.8940387,-409350.599394983 4942819.84896006,-408087.791091424 4942451.6711778,-407274.045613725 4940572.4807777,-404446.196589102 4939976.71501489,-402422.964843936 4940450.3670813,-401010.654464241 4939054.8061663,-397647.247369412 4940679.80737878,-395658.413346901 4940528.84765185,-395536.852462953 4938829.79565997,-394268.923462818 4938003.7277717,-393388.720249116 4934757.80596815,-392393.301362444 4934326.71675815,-392573.527618037 4932323.40974412,-393464.640141837 4931903.10653605,-393085.597275686 4931094.7353605,-398426.261165985 4929156.87541607,-398261.174361137 4926238.00816416,-394045.059966834 4925765.18668498,-392982.960705174 4926391.81893628,-393090.272694301 4927176.84692181,-391648.240010564 4924626.06386961,-391889.914625075 4923086.14787613,-394345.177314013 4923235.086036,-395550.878718795 4917812.79243978,-399009.463978251 4912927.7157945,-398948.794855767 4911941.91010796,-398092.636652078 4911806.57392519,-401991.601817112 4911722.9204501,-406225.972607907 4914505.47286319,-411104.994569885 4912569.26941163,-412925.513522316 4913030.3608866,-414630.148884835 4914436.69169949,-414207.691417276 4919205.78028405,-418306.141109809 4917994.9580478,-424184.700779621 4918938.12432889,-426816.961458921 4923664.37379373,-420956.324227126 4923381.98014807,-420186.661267781 4924286.48693378,-420943.411166194 4926812.76394433,-419779.45457046 4928527.43466337,-419768.767899344 4930681.94459216,-421911.668097113 4930432.40620397,-423482.386112205 4933451.28047252,-427272.814773717 4934151.56473242,-427144.908678797 4939731.77191996,-428982.125554848 4940522.84445172,-428986.133056516 4942437.17281266,-431237.792396792 4947309.68284815,-432476.889648814 4947791.74800037,-432540.453078056 4949775.20452642))', 3857) as g +) +SELECT st_astext(CDB_PIA(g)) from a; +``` diff --git a/src/pg/sql/09_voronoi.sql b/src/pg/sql/09_voronoi.sql deleted file mode 100644 index 51d22d4..0000000 --- a/src/pg/sql/09_voronoi.sql +++ /dev/null @@ -1,205 +0,0 @@ -CREATE OR REPLACE FUNCTION CDB_voronoi( - IN geomin geometry[], - IN buffer numeric DEFAULT 0.5, - IN tolerance numeric DEFAULT 1e-9 - ) -RETURNS geometry AS $$ -DECLARE - geomout geometry; -BEGIN - WITH - convexhull_1 as ( - SELECT - ST_ConvexHull(ST_Collect(geomin)) as g, - buffer * |/ st_area(ST_ConvexHull(ST_Collect(geomin))) as r - ), - clipper as( - SELECT - st_buffer(ST_MinimumBoundingCircle(a.g), buffer*a.r) as g - FROM convexhull_1 a - ), - env0 as ( - SELECT - (st_dumppoints(st_expand(a.g, buffer*a.r))).geom as e - FROM convexhull_1 a - ), - env as ( - SELECT - array_agg(env0.e) as e - FROM env0 - ), - sample AS ( - SELECT - ST_Collect(geomin || env.e) as geom - FROM env - ), - convexhull as ( - SELECT - ST_ConvexHull(ST_Collect(geomin)) as cg - ), - tin as ( - SELECT - ST_Dump(ST_DelaunayTriangles(geom, tolerance, 0)) as gd - FROM - sample - ), - tin_polygons as ( - SELECT - (gd).Path as id, - (gd).Geom as pg, - ST_Centroid(ST_MinimumBoundingCircle((gd).Geom, 180)) as ct - FROM tin - ), - tin_lines as ( - SELECT - id, - ST_ExteriorRing(pg) as lg - FROM tin_polygons - ), - tin_nodes as ( - SELECT - id, - ST_PointN(lg,1) p1, - ST_PointN(lg,2) p2, - ST_PointN(lg,3) p3 - FROM tin_lines - ), - tin_edges AS ( - SELECT - p.id, - UNNEST(ARRAY[ - ST_MakeLine(n.p1,n.p2) , - ST_MakeLine(n.p2,n.p3) , - ST_MakeLine(n.p3,n.p1)]) as Edge, - ST_Force_2D(_Find_Circle(n.p1,n.p2,n.p3)) as ct , - CASE WHEN st_distance(p.ct, ST_ExteriorRing(p.pg)) < tolerance THEN - TRUE - ELSE FALSE END AS ctx, - p.pg, - ST_within(p.ct, convexhull.cg) as ctin - FROM - tin_polygons p, - tin_nodes n, - convexhull - WHERE p.id = n.id - ), - voro_nodes as ( - SELECT - CASE WHEN x.ctx = TRUE THEN - ST_Centroid(x.edge) - ELSE - x.ct - END as xct, - CASE WHEN y.id is null THEN - CASE WHEN x.ctin = TRUE THEN - ST_SetSRID(ST_MakePoint( - ST_X(x.ct) + ((ST_X(ST_Centroid(x.edge)) - ST_X(x.ct)) * (1+buffer)), - ST_Y(x.ct) + ((ST_Y(ST_Centroid(x.edge)) - ST_Y(x.ct)) * (1+buffer)) - ), ST_SRID(x.ct)) - END - ELSE - y.ct - END as yct - FROM - tin_edges x - LEFT OUTER JOIN - tin_edges y - ON x.id <> y.id AND ST_Equals(x.edge, y.edge) - ), - voro_edges as( - SELECT - ST_LineMerge(ST_Collect(ST_MakeLine(xct, yct))) as v - FROM - voro_nodes - ), - voro_cells as( - SELECT - ST_Polygonize( - ST_Node( - ST_LineMerge( - ST_Union(v, ST_ExteriorRing( - ST_Convexhull(v) - ) - ) - ) - ) - ) as g - FROM - voro_edges - ), - voro_set as( - SELECT - (st_dump(v.g)).geom as g - FROM voro_cells v - ) - SELECT - st_collect(ST_intersection(c.g, v.g)) - -- ST_intersection(c.g, v.g) - INTO geomout - FROM - voro_set v, - clipper c; - RETURN geomout; -END; -$$ language plpgsql IMMUTABLE; - -/** ---------------------------------------------------------------------------------------- - * @function : FindCircle - * @precis : Function that determines if three points form a circle. If so a table containing - * centre and radius is returned. If not, a null table is returned. - * @version : 1.0 - * @param : p_pt1 : First point in curve - * @param : p_pt2 : Second point in curve - * @param : p_pt3 : Third point in curve - * @return : geometry : In which X,Y ordinates are the centre X, Y and the Z being the radius of found circle - * or NULL if three points do not form a circle. - * @history : Simon Greener - Feb 2012 - Original coding. - * @copyright : Simon Greener @ 2012 - * Licensed under a Creative Commons Attribution-Share Alike 2.5 Australia License. (http://creativecommons.org/licenses/by-sa/2.5/au/) -**/ -CREATE OR REPLACE FUNCTION _Find_Circle(p_pt1 geometry, p_pt2 geometry, p_pt3 geometry) - RETURNS geometry AS -$BODY$ -DECLARE - v_Centre geometry; - v_radius NUMERIC; - v_CX NUMERIC; - v_CY NUMERIC; - v_dA NUMERIC; - v_dB NUMERIC; - v_dC NUMERIC; - v_dD NUMERIC; - v_dE NUMERIC; - v_dF NUMERIC; - v_dG NUMERIC; -BEGIN - IF ( p_pt1 IS NULL OR p_pt2 IS NULL OR p_pt3 IS NULL ) THEN - RAISE EXCEPTION 'All supplied points must be not null.'; - RETURN NULL; - END IF; - IF ( ST_GeometryType(p_pt1) <> 'ST_Point' OR - ST_GeometryType(p_pt1) <> 'ST_Point' OR - ST_GeometryType(p_pt1) <> 'ST_Point' ) THEN - RAISE EXCEPTION 'All supplied geometries must be points.'; - RETURN NULL; - END IF; - v_dA := ST_X(p_pt2) - ST_X(p_pt1); - v_dB := ST_Y(p_pt2) - ST_Y(p_pt1); - v_dC := ST_X(p_pt3) - ST_X(p_pt1); - v_dD := ST_Y(p_pt3) - ST_Y(p_pt1); - v_dE := v_dA * (ST_X(p_pt1) + ST_X(p_pt2)) + v_dB * (ST_Y(p_pt1) + ST_Y(p_pt2)); - v_dF := v_dC * (ST_X(p_pt1) + ST_X(p_pt3)) + v_dD * (ST_Y(p_pt1) + ST_Y(p_pt3)); - v_dG := 2.0 * (v_dA * (ST_Y(p_pt3) - ST_Y(p_pt2)) - v_dB * (ST_X(p_pt3) - ST_X(p_pt2))); - -- If v_dG is zero then the three points are collinear and no finite-radius - -- circle through them exists. - IF ( v_dG = 0 ) THEN - RETURN NULL; - ELSE - v_CX := (v_dD * v_dE - v_dB * v_dF) / v_dG; - v_CY := (v_dA * v_dF - v_dC * v_dE) / v_dG; - v_Radius := SQRT(POWER(ST_X(p_pt1) - v_CX,2) + POWER(ST_Y(p_pt1) - v_CY,2) ); - END IF; - RETURN ST_SetSRID(ST_MakePoint(v_CX, v_CY, v_radius),ST_Srid(p_pt1)); -END; -$BODY$ - LANGUAGE plpgsql VOLATILE STRICT; diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql new file mode 100644 index 0000000..7bb5b7b --- /dev/null +++ b/src/pg/sql/13_PIA.sql @@ -0,0 +1,125 @@ +-- Based on: +-- https://github.com/mapbox/polylabel/blob/master/index.js +-- https://sites.google.com/site/polesofinaccessibility/ +-- Requires: https://github.com/CartoDB/cartodb-postgresql + +CREATE OR REPLACE FUNCTION CDB_PIA( + IN polygon geometry, + IN tolerance numeric DEFAULT 1.0 + ) +RETURNS geometry AS $$ +DECLARE + env geometry[]; + cells geometry[]; + best_c geometry; + best_d numeric; + test_d numeric; + test_mx numeric; + test_h numeric; + test_tol numeric; + test_cells geometry[]; + width numeric; + height numeric; + h numeric; + i integer; + n integer; + sqr numeric; + p geometry; +BEGIN + sqr := |/2; + + -- grid #0 cell size + height := ST_YMax(polygon) - ST_YMin(polygon); + width := ST_XMax(polygon) - ST_XMin(polygon); + SELECT 0.5*LEAST(height, width) INTO h; + + -- grid #0 + with c1 as( + SELECT CDB_RectangleGrid(polygon, h, h) as cell + ) + -- ,c2 as( + -- SELECT cell FROM c1 WHERE ST_Intersects(cell, polygon) + -- ) + SELECT array_agg(cell) INTO cells FROM c1; + + -- 1st guess: centroid + SELECT _Signed_Dist(polygon, ST_Centroid(Polygon)) INTO best_d; + + -- looping the loop + n := array_length(cells,1); + i := 1; + LOOP + + EXIT WHEN i > n; + + -- cell side size + SELECT ST_XMax(cells[i]) - ST_XMin(cells[i]) INTO test_h; + + -- check distance + SELECT _Signed_Dist(polygon, ST_Centroid(cells[i])) INTO test_d; + IF test_d > best_d THEN + best_d := test_d; + best_c := cells[i]; + END IF; + + -- longest distance within the cell + SELECT test_d + (test_h * sqr) INTO test_mx; + + -- if the cell has no chance to contains the desired point, continue + SELECT test_mx - best_d INTO test_tol; + IF test_tol <= tolerance THEN + i := i+1; + CONTINUE; + END IF; + + -- resample the cell + with c1 as( + SELECT CDB_RectangleGrid(cells[i], test_h/2, test_h/2) as cell + ) + -- , c2 as( + -- SELECT cell FROM c1 WHERE ST_Intersects(cell, polygon) + -- ) + SELECT array_agg(cell) INTO test_cells FROM c1; + + -- concat the new cells to the former array + cells := cells || test_cells; + + -- prepare next iteration + n := array_length(cells,1); + i := i+1; + + END LOOP; + + RETURN ST_Centroid(best_c); + +END; +$$ language plpgsql IMMUTABLE; + + +-- signed distance point to polygon with holes +-- negative is the point is out the polygon +CREATE OR REPLACE FUNCTION _Signed_Dist( + IN polygon geometry, + IN point geometry + ) +RETURNS numeric AS $$ +DECLARE + i integer; + within integer; + holes integer; + dist numeric; +BEGIN + dist := 1e999; + SELECT LEAST(dist, ST_distance(point, ST_ExteriorRing(polygon))::numeric) INTO dist; + SELECT CASE WHEN ST_Within(point,polygon) THEN 1 ELSE -1 END INTO within; + SELECT ST_NumInteriorRings(polygon) INTO holes; + IF holes > 0 THEN + FOR i IN 1..holes + LOOP + SELECT LEAST(dist, ST_distance(point, ST_InteriorRingN(polygon, i))::numeric) INTO dist; + END LOOP; + END IF; + dist := dist * within::numeric; + RETURN dist; +END; +$$ language plpgsql IMMUTABLE; diff --git a/src/pg/test/expected/09_voronoi_test.out b/src/pg/test/expected/09_voronoi_test.out deleted file mode 100644 index 5d5a1e5..0000000 --- a/src/pg/test/expected/09_voronoi_test.out +++ /dev/null @@ -1,5 +0,0 @@ - result ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 010600000014000000010300000001000000220000000422561581F40040EBF03C9CE6B244401D29CDF9CAF4004061DE46FEFBB24440848FC014D1F4004035F438A1FDB2444020D799D546F5004007ABC8021BB344401C0109CB4DF50040041E4FA21CB344403F4952DDD2F500402AE532C239B344400CDE54ABDAF50040C1CCDB5D3BB34440D68493EA6EF60040DABF173458B34440E6CC058F77F60040C04272CB59B344406F3396D21AF7004066AE1E5076B34440A1AE194B24F700408521BBE277B34440EF5C3A66D6F700400AAE060E94B34440BD6836B0E0F700401AB3769B95B34440A2521472A1F800402D89A865B1B3444055E0B68AACF80040F72C7FEDB2B34440C8C77ABE7BF900408F13F94ECEB344407622B9A287F90040CDEBCAD0CFB34440D813960F65FA0040C55E0BC2EAB34440E1B52DBC71FA004092A76E3DECB344401A9A70255DFB004066E612B706B44440C411E8966AFB00403A9F9F2B08B44440025208BC63FC00405DB3652622B444406F35B0EE71FC004094BBB59323B44440F86B618B78FD0040C1757E083DB44440DE5B557B87FD00409CA82D6E3EB44440130D9A479BFE00409D94FE5557B444409AC5C1F0AAFE0040ACE4AAB358B44440111CFFA0CBFF00401833B00771B4444058940FFFDBFF004023C5F95C72B444409F1A2244090101407E2A88168AB4444006B29E521A010140CC6F11638BB444406B3F740A62010140A30D8BAB90B4444016C7433955FD0040FB1809D6ECB244400422561581F40040EBF03C9CE6B244400103000000010000003D0000009161176DCA000140467D4FCDB8AF444057940FFFDBFF0040AB6D0594CBAF4440111CFFA0CBFF0040B6FF4EE9CCAF44409AC5C1F0AAFE0040224E543DE5AF4440130D9A479BFE0040319E009BE6AF4440DE5B557B87FD0040328AD182FFAF4440F86B618B78FD00400DBD80E800B044406F35B0EE71FC00403A77495D1AB04440025208BC63FC0040717F99CA1BB04440C411E8966AFB004094935FC535B044401A9A70255DFB0040684CEC3937B04440E1B52DBC71FA00403C8B90B351B04440D813960F65FA004009D4F32E53B044407622B9A287F90040014734206EB04440C9C77ABE7BF900403F1F06A26FB0444055E0B68AACF80040D70580038BB04440A1521472A1F80040A1A9568B8CB04440BD6836B0E0F70040B47F8855A8B04440EF5C3A66D6F70040C484F8E2A9B04440A0AE194B24F700404911440EC6B044406E3396D21AF700406884E0A0C7B04440E6CC058F77F600400EF08C25E4B04440D68493EA6EF60040F472E7BCE5B044400CDE54ABDAF500400D66239302B144403F4952DDD2F50040A44DCC2E04B144401C0109CB4DF50040CA14B04E21B1444021D799D546F50040C78736EE22B14440848FC014D1F40040993EC64F40B144401B29CDF9CAF400406D54B8F241B14440DF86ABAA64F40040DD15E68D5FB144402958E06B5FF40040EFF5D03361B14440C92982AA08F400407D117F007FB14440CA4C4F4904F40040A712EFA880B1444033DA7C2DBDF30040F145F29E9EB14440F2A915ABB9F30040320E7349A0B14440812F4D4882F3004037C29460BEB14440C0F3A7A57FF300409B66B10CC0B144404A4A180B58F3004026F0B13CDEB1444009F4ED4856F30040CF14F5E9DFB14440596772813EF300404EF78D2AFEB144401C5E3EA03DF30040A5EF81D8FFB144400FB35BB235F30040EC2168211EB244400FB35BB235F30040E21097CF1FB244401C5E3EA03DF3004029437D183EB24440596772813EF30040803B71C63FB2444009F4ED4856F30040FF1D0A075EB244404A4A180B58F30040A8424DB45FB24440C0F3A7A57FF3004033CC4DE47DB24440812F4D4882F3004097706A907FB24440F2A915ABB9F300409C248CA79DB2444033DA7C2DBDF30040DDEC0C529FB24440CA4C4F4904F4004027201048BDB24440C92982AA08F40040512180F0BEB244402958E06B5FF40040DF3C2EBDDCB24440E086ABAA64F40040F11C1963DEB244400422561581F40040EBF03C9CE6B2444016C7433955FD0040FB1809D6ECB24440BA703922B01F0140157201FC61B24440D83423AD0219014015C2F40C6AB0444025E06E858E14014003F2824594AF44409161176DCA000140467D4FCDB8AF4440010300000001000000200000001B476FC4EF16014083AEB518A6AE4440993DF9654F150140E2378E67B2AE4440B5B9DB48371501408D1DD225B3AE4440408AD43488130140A3EC9FFCC0AE444070FD9F7E70130140C36669C7C1AE44402B105CE4C81101400795FD7DD0AE4440EF82909BB1110140820C1555D1AE4440B7402FEF11100140861067E7E0AE44403EBD2E1AFB0F0140BD8E91CAE1AE4440791AA3CD630E014025A25C34F2AE4440C1ECAF724D0E014024E15B23F3AE4440B42CA1F5BE0C0140382C206004AF4440E22BDC1AA90C0140BFA7B25A05AF44401B4587DA230B0140267DB66517AF44404F24EE850E0B0140AB84976B18AF44409BCE07ED9209014010ADE83F2BAF4440C17973247E0901408676D0502CAF4440C7ED0A9B0C080140AB8B45E93FAF444002EE2D64F80701403D47E90441AF4440A35E904F91060140411E235C55AF4440AE4BF5AF7D060140C70A358256AF4440EB20927221050140162DA0926BAF4440191B9A6F0E05014074ADCFC26CAF444020F6E768BD03014020E0A58682AF4440AB2DC907AB03014050919FC083AF444076BD2B9465020140466AE9319AAF44406104F0D953020140413A57759BAF444006B29E521A01014001C3ED8DB2AF44409D1A224409010140500877DAB3AF44409161176DCA000140467D4FCDB8AF444025E06E858E14014003F2824594AF44401B476FC4EF16014083AEB518A6AE44400103000000010000002F0000006B3F740A62010140A30D8BAB90B444406004F0D9530201408CF8A77BA2B4444077BD2B946502014088C815BFA3B44440AD2DC907AB0301407EA15F30BAB4444020F6E768BD030140AE52596ABBB44440181B9A6F0E0501405A852F2ED1B44440DD20927221050140B7055F5ED2B44440A04BF5AF7D0601400728CA6EE7B44440B15E904F910601408E14DC94E8B4444010EE2D64F807014091EB15ECFCB44440B8ED0A9B0C08014022A7B907FEB44440B37973247E09014048BC2EA011B54440ACCE07ED92090140C08516B112B544406024EE850E0B014024AE678525B544401C4587DA230B0140A8B5488B26B54440E22BDC1AA90C01400F8B4C9638B54440B42CA1F5BE0C01409606DF9039B54440C2ECAF724D0E0140AA51A3CD4AB544407A1AA3CD630E0140A990A2BC4BB544403EBD2E1AFB0F014011A46D265CB54440B7402FEF11100140482298095DB54440EF82909BB11101404C26EA9B6CB544402B105CE4C8110140C79D01736DB5444071FD9F7E701301400BCC95297CB54440418AD434881301402B465FF47CB54440B5B9DB483715014041152DCB8AB54440993DF9654F150140ECFA70898BB544401DA7977D051701406339AD7C98B54440C5E301FB1D1701403F62372E99B54440FC441F9EDA180140DD40553AA5B54440EF951F75F31801409901F5DEA5B544403B5ED829B61A01407E0CA700B1B544401F909F53CF1A014031442F98B1B54440794A669E971C01409A4A68CCBBB54440FB780E14B11C01401C6FAF56BCB5444096AACD777E1E01408859A39AC5B54440E2235C32981E0140D4828317C6B54440419698306A2001405717A868CEB5444031C6FF2884200140F709FFD7CEB544404E33FB415A220140709E0C34D6B5444070901C7174220140D6D4BB95D6B5444074EC9A4DB12301400391B3DCDAB544409AEC9FA7012301409E077767EDB444408D12585F28210140C7A69D936DB24440BA703922B01F0140157201FC61B2444016C7433955FD0040FB1809D6ECB244406B3F740A62010140A30D8BAB90B44440010300000001000000220000006C6873F224290140640589D054AE4440C72CC8DC5928014004E6574656AE4440A5A8BB343F28014008597E7E56AE4440107488D45F26014032803BF05AAE44407D61884D4526014002AE4E365BAE44409AA8A68268240140E89064A260AE44406EA7F8234E240140D44351F660AE44406F901C7174220140F85D435B67AE44404D33FB415A2201405E94F2BC67AE444031C6FF2884200140D72800196FAE4440419698306A200140771B57886FAE4440E2235C32981E0140FAAF7BD977AE444097AACD777E1E014046D95B5678AE4440FB780E14B11C0140B2C34F9A81AE4440784A669E971C014034E8962482AE44401E909F53CF1A01409DEECF588CAE4440395ED829B61A0140502658F08CAE4440278677A0731901403CACA8E794AE444088C82E251F19014014C8BBF200AF4440258677A0731901403CACA8E794AE4440EE951F75F318014035310A1298AE4440FC441F9EDA180140F1F1A9B698AE4440C4E301FB1D1701408FD0C7C2A4AE44401CA7977D051701406BF95174A5AE44401B476FC4EF16014083AEB518A6AE444025E06E858E14014003F2824594AF4440D83423AD0219014015C2F40C6AB04440E43423AD0219014015C2F40C6AB0444032772D211F34014047E17A14AEAF44401B6338B19A390140BCB71C1188AF44400F9C33A2B4370140736891ED7CAF44400B6238B19A390140A8B71C1188AF4440A0ABADD85F3601409EEFA7C64BAF44406C6873F224290140640589D054AE444001030000000100000004000000E43423AD0219014015C2F40C6AB04440D83423AD0219014015C2F40C6AB04440BA703922B01F0140157201FC61B24440E43423AD0219014015C2F40C6AB044400103000000010000000A000000E43423AD0219014015C2F40C6AB04440BA703922B01F0140157201FC61B244408312585F28210140B9A69D936DB2444069DF5D3F49270140A80F6D4D69B244406671FB2ACF5201408029E4EA2FB04440551DBFA9615201407723356D19B044400B6238B19A390140A8B71C1188AF44401B6338B19A390140BCB71C1188AF444032772D211F34014047E17A14AEAF4440E43423AD0219014015C2F40C6AB0444001030000000100000004000000278677A0731901403CACA8E794AE4440258677A0731901403CACA8E794AE444088C82E251F19014014C8BBF200AF4440278677A0731901403CACA8E794AE4440010300000001000000320000009D9022A60E510140E7A48BF4E6AE4440F002F3808E500140BD8E91CAE1AE4440777FF2AB77500140861067E7E0AE44403F3D91FFD74E0140820C1555D1AE444003B0C5B6C04E01400795FD7DD0AE4440BEC2811C194D0140C36669C7C1AE4440EE354D66014D0140A3EC9FFCC0AE44407A064652524B01408D1DD225B3AE4440968228353A4B0140E2378E67B2AE444012198A1D844901406BF95174A5AE44406ADC1FA06B4901408FD0C7C2A4AE4440337B02FDAE470140F1F1A9B698AE4440402A02269647014035310A1298AE4440F4614971D3450140502658F08CAE444010308247BA4501409DEECF588CAE4440B675BBFCF143014034E8962482AE444034471387D8430140B2C34F9A81AE4440991554230B42014046D95B5678AE44404D9CC568F1410140FAAF7BD977AE4440ED29896A1F400140771B57886FAE4440FDF9217205400140D72800196FAE4440E18C26592F3E01405E94F2BC67AE4440BF2F052A153E0140F85D435B67AE4440C01829773B3C0140D44351F660AE444094177B18213C0140E89064A260AE4440B15E994D443A014002AE4E365BAE44401E4C99C6293A014032803BF05AAE4440891766664A38014008597E7E56AE4440679359BE2F38014004E6574656AE44400C533E4C4E3601405D5E2BD052AE4440CE0C748A33360140A10A01A652AE444025746B8A503401400A10582C50AE44409B2939B635340140A66A351050AE4440B001ABAC51320140DBB1BD934EAE44403B7C6BCD363201404771AA854EAE4440C457083F523001409646CC064EAE44406A68195C373001409646CC064EAE4440F443B6CD522E01404771AA854EAE44407FBE76EE372E0140DBB1BD934EAE44409396E8E4532C0140A66A351050AE4440094CB610392C01400A10582C50AE444060B3AD10562A0140A10A01A652AE4440226DE34E3B2A01405D5E2BD052AE44406C6873F224290140640589D054AE4440A0ABADD85F3601409EEFA7C64BAF44400B6238B19A390140A8B71C1188AF4440551DBFA9615201407723356D19B044404E1DBFA9615201407123356D19B044401184E6662B51014014C8BBF200AF44409D9022A60E510140E7A48BF4E6AE4440010300000001000000040000008312585F28210140B9A69D936DB24440BA703922B01F0140157201FC61B244408D12585F28210140C7A69D936DB244408312585F28210140B9A69D936DB244400103000000010000003B00000074EC9A4DB12301400391B3DCDAB544406FA7F8234E240140FAEEADFADCB544409BA8A68268240140E6A19A4EDDB544407E61884D45260140CC84B0BAE2B54440117488D45F2601409CB2C300E3B54440A6A8BB343F280140C6D98072E7B54440C82CC8DC59280140CA4CA7AAE7B54440236DE34E3B2A014071D4D320EBB5444061B3AD10562A01402D28FE4AEBB544400A4CB610392C0140C422A7C4EDB544409496E8E4532C014028C8C9E0EDB544407FBE76EE372E0140F380415DEFB54440F443B6CD522E014087C1546BEFB544406B68195C3730014038EC32EAEFB54440C557083F5230014038EC32EAEFB544403B7C6BCD3632014087C1546BEFB54440B001ABAC51320140F380415DEFB544409C2939B63534014028C8C9E0EDB5444026746B8A50340140C422A7C4EDB54440CE0C748A333601402D28FE4AEBB544400C533E4C4E36014071D4D320EBB54440689359BE2F380140CA4CA7AAE7B544408A1766664A380140C6D98072E7B544401F4C99C6293A01409CB2C300E3B54440B25E994D443A0140CC84B0BAE2B54440F7FB7763483A014006AECBAEE2B54440BC3741C7BA3A0140321ED64C17B54440F8FB7763483A014006AECBAEE2B5444095177B18213C0140E6A19A4EDDB54440C11829773B3C0140FAEEADFADCB54440C02F052A153E0140D6D4BB95D6B54440E28C26592F3E0140709E0C34D6B54440FEF9217205400140F709FFD7CEB54440EE29896A1F4001405717A868CEB544404D9CC568F1410140D4828317C6B54440981554230B4201408859A39AC5B5444034471387D84301401C6FAF56BCB54440B775BBFCF14301409A4A68CCBBB5444011308247BA45014031442F98B1B54440F6614971D34501407E0CA700B1B54440412A0226964701409901F5DEA5B54440337B02FDAE470140DD40553AA5B544406BDC1FA06B4901403F62372E99B5444013198A1D844901406339AD7C98B54440968228353A4B0140ECFA70898BB544407A064652524B014041152DCB8AB54440EF354D66014D01402B465FF47CB54440BFC2811C194D01400BCC95297CB5444004B0C5B6C04E0140C79D01736DB54440403D91FFD74E01404C26EA9B6CB54440F5FFE537095001402251D82C61B54440082885A17E510140453402BC8DB444400AECA544B94A0140EEAAFDBAA3B3444047DE5D3F49270140B70F6D4D69B2444069DF5D3F49270140A80F6D4D69B244408312585F28210140B9A69D936DB244408D12585F28210140C7A69D936DB244409AEC9FA7012301409E077767EDB4444074EC9A4DB12301400391B3DCDAB544400103000000010000001B0000003BC1E63C426D01405C8F2BE4F2B144402DCC3352336D0140D014F5E9DFB14440E2750990316D014026F0B13CDEB1444077CC79F5096D01409B66B10CC0B14440B190D452076D014037C29460BEB144403E160CF0CF6C0140330E7349A0B14440F5E5A46DCC6C0140F245F29E9EB144406F73D251856C0140A712EFA880B1444065969FF0806C01407D117F007FB144400368412F2A6C0140EFF5D03361B144404B3976F0246C0140DD15E68D5FB14440199754A1BE6B01406E54B8F241B144408E5FD20DBE6B0140603F2ECB41B14440A7306186B86B01409A3EC64F40B1444018E987C5426B0140C78736EE22B1444009BF18D03B6B0140CA14B04E21B14440F276CFBDB66A0140A44DCC2E04B144401EE2CCEFAE6A01400D66239302B144405B3B8EB01A6A0140F572E7BCE5B044404AF31B0C126A01400EF08C25E4B0444003A2D519B269014006981D63D3B044406571FB2ACF5201408029E4EA2FB044406EDF5D3F49270140A80F6D4D69B244408104C58F31370140EF7C3F355EB2444049DE5D3F49270140B80F6D4D69B2444010ECA544B94A0140EFAAFDBAA3B344403BC1E63C426D01405C8F2BE4F2B144400103000000010000000400000069DF5D3F49270140A80F6D4D69B2444047DE5D3F49270140B70F6D4D69B244408204C58F31370140EE7C3F355EB2444069DF5D3F49270140A80F6D4D69B244400103000000010000002E000000F9A1D519B269014006981D63D3B04440C08C8BC86E6901406884E0A0C7B044408E110850656901404911440EC6B044403F63E734B3680140C484F8E2A9B044407157EBEAA8680140B47F8855A8B044408D6D0D29E8670140A1A9568B8CB04440D9DF6A10DD670140D70580038BB0444065F8A6DC0D6701403F1F06A26FB04440B89D68F801670140014734206EB0444056AC8B8B2466014009D4F32E53B044404D0AF4DE176601403C8B90B351B044401426B1752C650140684CEC3937B044406AAE39041F65014094935FC535B044402C6E19DF25640140717F99CA1BB04440BF8A71AC176401403A77495D1AB044403654C00F116301400DBD80E800B044405064CC1F02630140328AD182FFAF44401BB38753EE610140319E009BE6AF444094FA5FAADE610140224E543DE5AF44401DA422FABD600140B6FF4EE9CCAF4440D72B129CAD600140AB6D0594CBAF444091A5FF56805F0140500877DAB3AF4440280E83486F5F014001C3ED8DB2AF4440CDBB31C1355E0140413A57759BAF4440B802F606245E0140466AE9319AAF444083925893DE5C014050919FC083AF44400ECA3932CC5C014020E0A58682AF444015A5872B7B5B014074ADCFC26CAF4440439F8F28685B0140162DA0926BAF444080742CEB0B5A0140C70A358256AF44408B61914BF8590140411E235C55AF44402CD2F336915801403D47E90441AF444067D216007D580140AB8B45E93FAF44406D46AE760B5701408676D0502CAF444093F119AEF656014010ADE83F2BAF4440DF9B33157B550140AB84976B18AF4440137B9AC065550140267DB66517AF44404C944580E0530140BFA7B25A05AF44407A9380A5CA530140382C206004AF44406DD371283C52014024E15B23F3AE4440B5A57ECD2552014025A25C34F2AE44409D9022A60E510140E7A48BF4E6AE44401184E6662B51014014C8BBF200AF44404E1DBFA9615201407123356D19B044406671FB2ACF5201408029E4EA2FB04440F9A1D519B269014006981D63D3B044400103000000010000001C000000F5FFE537095001402251D82C61B54440787FF2AB77500140482298095DB54440F102F3808E50014011A46D265CB54440B6A57ECD25520140A990A2BC4BB544406ED371283C520140AA51A3CD4AB544407B9380A5CA5301409606DF9039B544404D944580E05301400F8B4C9638B54440137B9AC065550140A8B5488B26B54440DE9B33157B55014023AE678525B5444093F119AEF6560140BE8516B112B544406E46AE760B57014048BC2EA011B5444068D216007D58014023A7B907FEB444402DD2F3369158014091EB15ECFCB444408C61914BF85901408D14DC94E8B4444081742CEB0B5A01400728CA6EE7B44440449F8F28685B0140B8055F5ED2B4444016A5872B7B5B01405A852F2ED1B444400FCA3932CC5C0140AE52596ABBB4444084925893DE5C01407EA15F30BAB44440B902F606245E014088C815BFA3B44440CFBB31C1355E01408CF8A77BA2B44440290E83486F5F0140CC6F11638BB4444090A5FF56805F01407E2A88168AB44440D72B129CAD60014023C5F95C72B4444028A422FABD6001401733B00771B444404337B5C0D4600140C753561C6FB44440082885A17E510140453402BC8DB44440F5FFE537095001402251D82C61B5444001030000000100000004000000F7FB7763483A014006AECBAEE2B54440F8FB7763483A014006AECBAEE2B54440BC3741C7BA3A0140321ED64C17B54440F7FB7763483A014006AECBAEE2B54440010300000001000000040000001B6338B19A390140BCB71C1188AF44400B6238B19A390140A8B71C1188AF44400F9C33A2B4370140736891ED7CAF44401B6338B19A390140BCB71C1188AF44400103000000010000002F0000001F0DC6E8536D0140E21097CF1FB244401F0DC6E8536D0140EC2168211EB244401262E3FA4B6D0140A5EF81D8FFB14440D558AF194B6D01404EF78D2AFEB1444035C1E63C426D01405B8F2BE4F2B144400AECA544B94A0140EEAAFDBAA3B34440082885A17E510140453402BC8DB444404337B5C0D4600140C753561C6FB444409FFA5FAADE610140AAE4AAB358B4444013B38753EE6101409D94FE5557B444404864CC1F026301409DA82D6E3EB444403754C00F11630140C1757E083DB44440C08A71AC1764014094BBB59323B444402D6E19DF256401405DB3652622B444406BAE39041F6501403A9F9F2B08B444401C26B1752C65014065E612B706B44440540AF4DE1766014090A76E3DECB3444050AC8B8B24660140C45E0BC2EAB34440B39D68F801670140CDEBCAD0CFB3444067F8A6DC0D6701408F13F94ECEB34440DADF6A10DD670140F72C7FEDB2B344408D6D0D29E86701402D89A865B1B344407157EBEAA86801401AB3769B95B344403F63E734B36801400AAE060E94B344408E110850656901408521BBE277B34440C08C8BC86E69014066AE1E5076B3444048F31B0C126A0140C04272CB59B344405A3B8EB01A6A0140D9BF173458B3444024E2CCEFAE6A0140BFCCDB5D3BB34440EF76CFBDB66A014029E532C239B3444013BF18D03B6B0140031E4FA21CB344400DE987C5426B014006ABC8021BB34440A9306186B86B014035F438A1FDB24440139754A1BE6B014061DE46FEFBB244404F3976F0246C0140F11C1963DEB244400568412F2A6C0140DF3C2EBDDCB2444065969FF0806C0140512180F0BEB244406473D251856C014027201048BDB24440FBE5A46DCC6C0140DDEC0C529FB244403C160CF0CF6C01409C248CA79DB24440AE90D452076D014097706A907FB244406FCC79F5096D014033CC4DE47DB24440E5750990316D0140A8424DB45FB2444026CC3352336D0140FF1D0A075EB24440D558AF194B6D0140803B71C63FB244401262E3FA4B6D014029437D183EB244401F0DC6E8536D0140E21097CF1FB24440010300000001000000040000006671FB2ACF5201408029E4EA2FB044404E1DBFA9615201407123356D19B04440551DBFA9615201407723356D19B044406671FB2ACF5201408029E4EA2FB04440010300000001000000040000008B5FD20DBE6B01405F3F2ECB41B14440885FD20DBE6B01405F3F2ECB41B144405C4CEEA3C66601401E9F5F633EB144408B5FD20DBE6B01405F3F2ECB41B14440 -(1 row) - diff --git a/src/pg/test/expected/13_pia_test.out b/src/pg/test/expected/13_pia_test.out new file mode 100644 index 0000000..27e38a6 --- /dev/null +++ b/src/pg/test/expected/13_pia_test.out @@ -0,0 +1,5 @@ + st_astext +------------------------------------------- + POINT(-409081.241940808 4930027.50443989) +(1 row) + diff --git a/src/pg/test/sql/09_voronoi_test.sql b/src/pg/test/sql/09_voronoi_test.sql deleted file mode 100644 index 8e27849..0000000 --- a/src/pg/test/sql/09_voronoi_test.sql +++ /dev/null @@ -1,7 +0,0 @@ -WITH a AS ( - SELECT - ARRAY[ST_GeomFromText('POINT(2.1744 41.403)'),ST_GeomFromText('POINT(2.1228 41.380)'),ST_GeomFromText('POINT(2.1511 41.374)'),ST_GeomFromText('POINT(2.1528 41.413)'),ST_GeomFromText('POINT(2.165 41.391)'),ST_GeomFromText('POINT(2.1498 41.371)'),ST_GeomFromText('POINT(2.1533 41.368)'),ST_GeomFromText('POINT(2.131386 41.41399)')] AS geomin -) -SELECT - CDB_voronoi(geomin, 0.2, 1e-9) as result -FROM a; diff --git a/src/pg/test/sql/13_pia_test.sql b/src/pg/test/sql/13_pia_test.sql new file mode 100644 index 0000000..5d0b6f0 --- /dev/null +++ b/src/pg/test/sql/13_pia_test.sql @@ -0,0 +1,4 @@ +with a as( + select st_geomfromtext('POLYGON((-432540.453078056 4949775.20452642,-432329.947920966 4951361.232584,-431245.028163694 4952223.31516671,-429131.071033529 4951768.00415574,-424622.07505895 4952843.13503987,-423688.327170174 4953499.20752423,-424086.294349759 4954968.38274191,-423068.388925945 4954378.63345336,-423387.653225542 4953355.67417084,-420594.869840519 4953781.00230592,-416026.095299382 4951484.06849063,-412483.018546414 4951024.5410983,-410490.399661215 4954502.24032205,-408186.197521284 4956398.91417441,-407627.262358013 4959300.94633864,-406948.770061627 4959874.85407739,-404949.583326472 4959047.74518163,-402570.908447199 4953743.46829807,-400971.358683991 4952193.11680804,-403533.488084088 4949649.89857885,-406335.177028373 4950193.19571096,-407790.456731515 4952391.46015616,-412060.672398345 4950381.2389307,-410716.93482498 4949156.7509561,-408464.162289794 4943912.8940387,-409350.599394983 4942819.84896006,-408087.791091424 4942451.6711778,-407274.045613725 4940572.4807777,-404446.196589102 4939976.71501489,-402422.964843936 4940450.3670813,-401010.654464241 4939054.8061663,-397647.247369412 4940679.80737878,-395658.413346901 4940528.84765185,-395536.852462953 4938829.79565997,-394268.923462818 4938003.7277717,-393388.720249116 4934757.80596815,-392393.301362444 4934326.71675815,-392573.527618037 4932323.40974412,-393464.640141837 4931903.10653605,-393085.597275686 4931094.7353605,-398426.261165985 4929156.87541607,-398261.174361137 4926238.00816416,-394045.059966834 4925765.18668498,-392982.960705174 4926391.81893628,-393090.272694301 4927176.84692181,-391648.240010564 4924626.06386961,-391889.914625075 4923086.14787613,-394345.177314013 4923235.086036,-395550.878718795 4917812.79243978,-399009.463978251 4912927.7157945,-398948.794855767 4911941.91010796,-398092.636652078 4911806.57392519,-401991.601817112 4911722.9204501,-406225.972607907 4914505.47286319,-411104.994569885 4912569.26941163,-412925.513522316 4913030.3608866,-414630.148884835 4914436.69169949,-414207.691417276 4919205.78028405,-418306.141109809 4917994.9580478,-424184.700779621 4918938.12432889,-426816.961458921 4923664.37379373,-420956.324227126 4923381.98014807,-420186.661267781 4924286.48693378,-420943.411166194 4926812.76394433,-419779.45457046 4928527.43466337,-419768.767899344 4930681.94459216,-421911.668097113 4930432.40620397,-423482.386112205 4933451.28047252,-427272.814773717 4934151.56473242,-427144.908678797 4939731.77191996,-428982.125554848 4940522.84445172,-428986.133056516 4942437.17281266,-431237.792396792 4947309.68284815,-432476.889648814 4947791.74800037,-432540.453078056 4949775.20452642))', 3857) as g +) +SELECT st_astext(CDB_PIA(g)) from a; From 0eca26d515b0720bf05ab73b20af29a0c9f4c43d Mon Sep 17 00:00:00 2001 From: abelvm Date: Thu, 14 Jul 2016 15:07:45 +0200 Subject: [PATCH 02/16] performance x20 --- src/pg/sql/13_PIA.sql | 40 ++++++++++++++-------------- src/pg/test/expected/13_pia_test.out | 4 +-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql index 7bb5b7b..e5e8754 100644 --- a/src/pg/sql/13_PIA.sql +++ b/src/pg/sql/13_PIA.sql @@ -3,6 +3,11 @@ -- https://sites.google.com/site/polesofinaccessibility/ -- Requires: https://github.com/CartoDB/cartodb-postgresql +-- Based on: +-- https://github.com/mapbox/polylabel/blob/master/index.js +-- https://sites.google.com/site/polesofinaccessibility/ +-- Requires: https://github.com/CartoDB/cartodb-postgresql + CREATE OR REPLACE FUNCTION CDB_PIA( IN polygon geometry, IN tolerance numeric DEFAULT 1.0 @@ -11,12 +16,12 @@ RETURNS geometry AS $$ DECLARE env geometry[]; cells geometry[]; + cell geometry; best_c geometry; best_d numeric; test_d numeric; test_mx numeric; test_h numeric; - test_tol numeric; test_cells geometry[]; width numeric; height numeric; @@ -31,19 +36,16 @@ BEGIN -- grid #0 cell size height := ST_YMax(polygon) - ST_YMin(polygon); width := ST_XMax(polygon) - ST_XMin(polygon); - SELECT 0.5*LEAST(height, width) INTO h; + h := 0.5*LEAST(height, width); -- grid #0 with c1 as( - SELECT CDB_RectangleGrid(polygon, h, h) as cell + SELECT CDB_RectangleGrid(polygon, h, h) as c ) - -- ,c2 as( - -- SELECT cell FROM c1 WHERE ST_Intersects(cell, polygon) - -- ) - SELECT array_agg(cell) INTO cells FROM c1; + SELECT array_agg(c) INTO cells FROM c1; -- 1st guess: centroid - SELECT _Signed_Dist(polygon, ST_Centroid(Polygon)) INTO best_d; + best_d := _Signed_Dist(polygon, ST_Centroid(Polygon)); -- looping the loop n := array_length(cells,1); @@ -52,41 +54,39 @@ BEGIN EXIT WHEN i > n; - -- cell side size - SELECT ST_XMax(cells[i]) - ST_XMin(cells[i]) INTO test_h; + cell := cells[i]; + i := i+1; + + -- cell side size, it's square + test_h := ST_XMax(cell) - ST_XMin(cell) ; -- check distance - SELECT _Signed_Dist(polygon, ST_Centroid(cells[i])) INTO test_d; + test_d := _Signed_Dist(polygon, ST_Centroid(cell)); IF test_d > best_d THEN best_d := test_d; best_c := cells[i]; END IF; -- longest distance within the cell - SELECT test_d + (test_h * sqr) INTO test_mx; + test_mx := test_d + (test_h/2 * sqr); -- if the cell has no chance to contains the desired point, continue - SELECT test_mx - best_d INTO test_tol; - IF test_tol <= tolerance THEN - i := i+1; - CONTINUE; - END IF; + CONTINUE WHEN test_mx - best_d <= tolerance; -- resample the cell with c1 as( - SELECT CDB_RectangleGrid(cells[i], test_h/2, test_h/2) as cell + SELECT CDB_RectangleGrid(cell, test_h/2, test_h/2) as c ) -- , c2 as( -- SELECT cell FROM c1 WHERE ST_Intersects(cell, polygon) -- ) - SELECT array_agg(cell) INTO test_cells FROM c1; + SELECT array_agg(c) INTO test_cells FROM c1; -- concat the new cells to the former array cells := cells || test_cells; -- prepare next iteration n := array_length(cells,1); - i := i+1; END LOOP; diff --git a/src/pg/test/expected/13_pia_test.out b/src/pg/test/expected/13_pia_test.out index 27e38a6..037d339 100644 --- a/src/pg/test/expected/13_pia_test.out +++ b/src/pg/test/expected/13_pia_test.out @@ -1,5 +1,5 @@ - st_astext + st_astext ------------------------------------------- - POINT(-409081.241940808 4930027.50443989) + POINT(-409081.865887381 4930017.52075948) (1 row) From 15aad5a695ae97757ee28bf37fd3e85fd4aa9473 Mon Sep 17 00:00:00 2001 From: abelvm Date: Thu, 14 Jul 2016 15:46:09 +0200 Subject: [PATCH 03/16] clean --- src/pg/sql/13_PIA.sql | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql index e5e8754..c395720 100644 --- a/src/pg/sql/13_PIA.sql +++ b/src/pg/sql/13_PIA.sql @@ -77,9 +77,6 @@ BEGIN with c1 as( SELECT CDB_RectangleGrid(cell, test_h/2, test_h/2) as c ) - -- , c2 as( - -- SELECT cell FROM c1 WHERE ST_Intersects(cell, polygon) - -- ) SELECT array_agg(c) INTO test_cells FROM c1; -- concat the new cells to the former array From 3becd449c20b281f4eb9659e68e978ae6ffc8d71 Mon Sep 17 00:00:00 2001 From: abelvm Date: Tue, 9 Aug 2016 13:02:23 -0400 Subject: [PATCH 04/16] check tests --- src/pg/test/sql/13_pia_test.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pg/test/sql/13_pia_test.sql b/src/pg/test/sql/13_pia_test.sql index 5d0b6f0..3af1e7e 100644 --- a/src/pg/test/sql/13_pia_test.sql +++ b/src/pg/test/sql/13_pia_test.sql @@ -1,4 +1,4 @@ with a as( select st_geomfromtext('POLYGON((-432540.453078056 4949775.20452642,-432329.947920966 4951361.232584,-431245.028163694 4952223.31516671,-429131.071033529 4951768.00415574,-424622.07505895 4952843.13503987,-423688.327170174 4953499.20752423,-424086.294349759 4954968.38274191,-423068.388925945 4954378.63345336,-423387.653225542 4953355.67417084,-420594.869840519 4953781.00230592,-416026.095299382 4951484.06849063,-412483.018546414 4951024.5410983,-410490.399661215 4954502.24032205,-408186.197521284 4956398.91417441,-407627.262358013 4959300.94633864,-406948.770061627 4959874.85407739,-404949.583326472 4959047.74518163,-402570.908447199 4953743.46829807,-400971.358683991 4952193.11680804,-403533.488084088 4949649.89857885,-406335.177028373 4950193.19571096,-407790.456731515 4952391.46015616,-412060.672398345 4950381.2389307,-410716.93482498 4949156.7509561,-408464.162289794 4943912.8940387,-409350.599394983 4942819.84896006,-408087.791091424 4942451.6711778,-407274.045613725 4940572.4807777,-404446.196589102 4939976.71501489,-402422.964843936 4940450.3670813,-401010.654464241 4939054.8061663,-397647.247369412 4940679.80737878,-395658.413346901 4940528.84765185,-395536.852462953 4938829.79565997,-394268.923462818 4938003.7277717,-393388.720249116 4934757.80596815,-392393.301362444 4934326.71675815,-392573.527618037 4932323.40974412,-393464.640141837 4931903.10653605,-393085.597275686 4931094.7353605,-398426.261165985 4929156.87541607,-398261.174361137 4926238.00816416,-394045.059966834 4925765.18668498,-392982.960705174 4926391.81893628,-393090.272694301 4927176.84692181,-391648.240010564 4924626.06386961,-391889.914625075 4923086.14787613,-394345.177314013 4923235.086036,-395550.878718795 4917812.79243978,-399009.463978251 4912927.7157945,-398948.794855767 4911941.91010796,-398092.636652078 4911806.57392519,-401991.601817112 4911722.9204501,-406225.972607907 4914505.47286319,-411104.994569885 4912569.26941163,-412925.513522316 4913030.3608866,-414630.148884835 4914436.69169949,-414207.691417276 4919205.78028405,-418306.141109809 4917994.9580478,-424184.700779621 4918938.12432889,-426816.961458921 4923664.37379373,-420956.324227126 4923381.98014807,-420186.661267781 4924286.48693378,-420943.411166194 4926812.76394433,-419779.45457046 4928527.43466337,-419768.767899344 4930681.94459216,-421911.668097113 4930432.40620397,-423482.386112205 4933451.28047252,-427272.814773717 4934151.56473242,-427144.908678797 4939731.77191996,-428982.125554848 4940522.84445172,-428986.133056516 4942437.17281266,-431237.792396792 4947309.68284815,-432476.889648814 4947791.74800037,-432540.453078056 4949775.20452642))', 3857) as g ) -SELECT st_astext(CDB_PIA(g)) from a; +SELECT st_astext(cdb_crankshaft.CDB_PIA(g)) from a; From 667bdb79a2a0c814f9c784843275719379718c67 Mon Sep 17 00:00:00 2001 From: abelvm Date: Wed, 10 Aug 2016 12:16:36 -0400 Subject: [PATCH 05/16] fixed tests --- src/pg/test/expected/13_pia_test.out | 3 +++ src/pg/test/sql/13_pia_test.sql | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/pg/test/expected/13_pia_test.out b/src/pg/test/expected/13_pia_test.out index 037d339..31aa78e 100644 --- a/src/pg/test/expected/13_pia_test.out +++ b/src/pg/test/expected/13_pia_test.out @@ -1,3 +1,6 @@ +SET client_min_messages TO WARNING; +\set ECHO none + st_astext ------------------------------------------- POINT(-409081.865887381 4930017.52075948) diff --git a/src/pg/test/sql/13_pia_test.sql b/src/pg/test/sql/13_pia_test.sql index 3af1e7e..8b37082 100644 --- a/src/pg/test/sql/13_pia_test.sql +++ b/src/pg/test/sql/13_pia_test.sql @@ -1,3 +1,6 @@ +SET client_min_messages TO WARNING; +\set ECHO none + with a as( select st_geomfromtext('POLYGON((-432540.453078056 4949775.20452642,-432329.947920966 4951361.232584,-431245.028163694 4952223.31516671,-429131.071033529 4951768.00415574,-424622.07505895 4952843.13503987,-423688.327170174 4953499.20752423,-424086.294349759 4954968.38274191,-423068.388925945 4954378.63345336,-423387.653225542 4953355.67417084,-420594.869840519 4953781.00230592,-416026.095299382 4951484.06849063,-412483.018546414 4951024.5410983,-410490.399661215 4954502.24032205,-408186.197521284 4956398.91417441,-407627.262358013 4959300.94633864,-406948.770061627 4959874.85407739,-404949.583326472 4959047.74518163,-402570.908447199 4953743.46829807,-400971.358683991 4952193.11680804,-403533.488084088 4949649.89857885,-406335.177028373 4950193.19571096,-407790.456731515 4952391.46015616,-412060.672398345 4950381.2389307,-410716.93482498 4949156.7509561,-408464.162289794 4943912.8940387,-409350.599394983 4942819.84896006,-408087.791091424 4942451.6711778,-407274.045613725 4940572.4807777,-404446.196589102 4939976.71501489,-402422.964843936 4940450.3670813,-401010.654464241 4939054.8061663,-397647.247369412 4940679.80737878,-395658.413346901 4940528.84765185,-395536.852462953 4938829.79565997,-394268.923462818 4938003.7277717,-393388.720249116 4934757.80596815,-392393.301362444 4934326.71675815,-392573.527618037 4932323.40974412,-393464.640141837 4931903.10653605,-393085.597275686 4931094.7353605,-398426.261165985 4929156.87541607,-398261.174361137 4926238.00816416,-394045.059966834 4925765.18668498,-392982.960705174 4926391.81893628,-393090.272694301 4927176.84692181,-391648.240010564 4924626.06386961,-391889.914625075 4923086.14787613,-394345.177314013 4923235.086036,-395550.878718795 4917812.79243978,-399009.463978251 4912927.7157945,-398948.794855767 4911941.91010796,-398092.636652078 4911806.57392519,-401991.601817112 4911722.9204501,-406225.972607907 4914505.47286319,-411104.994569885 4912569.26941163,-412925.513522316 4913030.3608866,-414630.148884835 4914436.69169949,-414207.691417276 4919205.78028405,-418306.141109809 4917994.9580478,-424184.700779621 4918938.12432889,-426816.961458921 4923664.37379373,-420956.324227126 4923381.98014807,-420186.661267781 4924286.48693378,-420943.411166194 4926812.76394433,-419779.45457046 4928527.43466337,-419768.767899344 4930681.94459216,-421911.668097113 4930432.40620397,-423482.386112205 4933451.28047252,-427272.814773717 4934151.56473242,-427144.908678797 4939731.77191996,-428982.125554848 4940522.84445172,-428986.133056516 4942437.17281266,-431237.792396792 4947309.68284815,-432476.889648814 4947791.74800037,-432540.453078056 4949775.20452642))', 3857) as g ) From 01b0efd82b60ee09a9c783cbc2300a18f1ae2ae2 Mon Sep 17 00:00:00 2001 From: abelvm Date: Wed, 10 Aug 2016 13:55:22 -0400 Subject: [PATCH 06/16] tests spaces --- src/pg/test/expected/13_pia_test.out | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pg/test/expected/13_pia_test.out b/src/pg/test/expected/13_pia_test.out index 31aa78e..cff1550 100644 --- a/src/pg/test/expected/13_pia_test.out +++ b/src/pg/test/expected/13_pia_test.out @@ -1,6 +1,5 @@ SET client_min_messages TO WARNING; \set ECHO none - st_astext ------------------------------------------- POINT(-409081.865887381 4930017.52075948) From 7c2d160da0e0dc18218d68818d9c43e41fc08c5c Mon Sep 17 00:00:00 2001 From: abelvm Date: Wed, 10 Aug 2016 13:58:37 -0400 Subject: [PATCH 07/16] tests rectangle grid --- src/pg/sql/13_PIA.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql index c395720..a0ed670 100644 --- a/src/pg/sql/13_PIA.sql +++ b/src/pg/sql/13_PIA.sql @@ -40,7 +40,7 @@ BEGIN -- grid #0 with c1 as( - SELECT CDB_RectangleGrid(polygon, h, h) as c + SELECT CDB_RectangleGrid(polygon, h::float, h::float) as c ) SELECT array_agg(c) INTO cells FROM c1; From b80324c0d17317ade7438ae25c6333b7958aeace Mon Sep 17 00:00:00 2001 From: abelvm Date: Wed, 10 Aug 2016 14:06:28 -0400 Subject: [PATCH 08/16] tests rectangle grid --- src/pg/sql/13_PIA.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql index a0ed670..8ab3532 100644 --- a/src/pg/sql/13_PIA.sql +++ b/src/pg/sql/13_PIA.sql @@ -40,7 +40,7 @@ BEGIN -- grid #0 with c1 as( - SELECT CDB_RectangleGrid(polygon, h::float, h::float) as c + SELECT CDB_RectangleGrid(polygon, h::float8, h::float8) as c ) SELECT array_agg(c) INTO cells FROM c1; From 592eb68d42b716e782e453bb3756b713c8f56aaa Mon Sep 17 00:00:00 2001 From: abelvm Date: Wed, 10 Aug 2016 14:15:22 -0400 Subject: [PATCH 09/16] tests rectangle grid --- src/pg/sql/13_PIA.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql index 8ab3532..c395720 100644 --- a/src/pg/sql/13_PIA.sql +++ b/src/pg/sql/13_PIA.sql @@ -40,7 +40,7 @@ BEGIN -- grid #0 with c1 as( - SELECT CDB_RectangleGrid(polygon, h::float8, h::float8) as c + SELECT CDB_RectangleGrid(polygon, h, h) as c ) SELECT array_agg(c) INTO cells FROM c1; From 8a529fc956cce95b025e562fcc68c6e2b103f010 Mon Sep 17 00:00:00 2001 From: abelvm Date: Tue, 16 Aug 2016 11:16:51 -0400 Subject: [PATCH 10/16] add CDB_dependencies --- src/pg/sql/13_PIA.sql | 103 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 3 deletions(-) diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql index c395720..e59a3b8 100644 --- a/src/pg/sql/13_PIA.sql +++ b/src/pg/sql/13_PIA.sql @@ -40,12 +40,12 @@ BEGIN -- grid #0 with c1 as( - SELECT CDB_RectangleGrid(polygon, h, h) as c + SELECT cdb_crankshaft.CDB_RectangleGrid(polygon, h, h) as c ) SELECT array_agg(c) INTO cells FROM c1; -- 1st guess: centroid - best_d := _Signed_Dist(polygon, ST_Centroid(Polygon)); + best_d := cdb_crankshaft._Signed_Dist(polygon, ST_Centroid(Polygon)); -- looping the loop n := array_length(cells,1); @@ -75,7 +75,7 @@ BEGIN -- resample the cell with c1 as( - SELECT CDB_RectangleGrid(cell, test_h/2, test_h/2) as c + SELECT cdb_crankshaft.CDB_RectangleGrid(cell, test_h/2, test_h/2) as c ) SELECT array_agg(c) INTO test_cells FROM c1; @@ -120,3 +120,100 @@ BEGIN RETURN dist; END; $$ language plpgsql IMMUTABLE; + +-- +-- Fill given extent with a rectangular coverage +-- +-- @param ext Extent to fill. Only rectangles with center point falling +-- inside the extent (or at the lower or leftmost edge) will +-- be emitted. The returned hexagons will have the same SRID +-- as this extent. +-- +-- @param width With of each rectangle +-- +-- @param height Height of each rectangle +-- +-- @param origin Optional origin to allow for exact tiling. +-- If omitted the origin will be 0,0. +-- The parameter is checked for having the same SRID +-- as the extent. +-- +-- +CREATE OR REPLACE FUNCTION CDB_RectangleGrid(ext GEOMETRY, width FLOAT8, height FLOAT8, origin GEOMETRY DEFAULT NULL) +RETURNS SETOF GEOMETRY +AS $$ +DECLARE + h GEOMETRY; -- rectangle cell + hstep FLOAT8; -- horizontal step + vstep FLOAT8; -- vertical step + hw FLOAT8; -- half width + hh FLOAT8; -- half height + vstart FLOAT8; + hstart FLOAT8; + hend FLOAT8; + vend FLOAT8; + xoff FLOAT8; + yoff FLOAT8; + xgrd FLOAT8; + ygrd FLOAT8; + x FLOAT8; + y FLOAT8; + srid INTEGER; +BEGIN + + srid := ST_SRID(ext); + + xoff := 0; + yoff := 0; + + IF origin IS NOT NULL THEN + IF ST_SRID(origin) != srid THEN + RAISE EXCEPTION 'SRID mismatch between extent (%) and origin (%)', srid, ST_SRID(origin); + END IF; + xoff := ST_X(origin); + yoff := ST_Y(origin); + END IF; + + --RAISE DEBUG 'X offset: %', xoff; + --RAISE DEBUG 'Y offset: %', yoff; + + hw := width/2.0; + hh := height/2.0; + + xgrd := hw; + ygrd := hh; + --RAISE DEBUG 'X grid size: %', xgrd; + --RAISE DEBUG 'Y grid size: %', ygrd; + + hstep := width; + vstep := height; + + -- Tweak horizontal start on hstep grid from origin + hstart := xoff + ceil((ST_XMin(ext)-xoff)/hstep)*hstep; + --RAISE DEBUG 'hstart: %', hstart; + + -- Tweak vertical start on vstep grid from origin + vstart := yoff + ceil((ST_Ymin(ext)-yoff)/vstep)*vstep; + --RAISE DEBUG 'vstart: %', vstart; + + hend := ST_XMax(ext); + vend := ST_YMax(ext); + + --RAISE DEBUG 'hend: %', hend; + --RAISE DEBUG 'vend: %', vend; + + x := hstart; + WHILE x < hend LOOP -- over X + y := vstart; + h := ST_MakeEnvelope(x-hw, y-hh, x+hw, y+hh, srid); + WHILE y < vend LOOP -- over Y + RETURN NEXT h; + h := ST_Translate(h, 0, vstep); + y := yoff + round(((y + vstep)-yoff)/ygrd)*ygrd; -- round to grid + END LOOP; + x := xoff + round(((x + hstep)-xoff)/xgrd)*xgrd; -- round to grid + END LOOP; + + RETURN; +END +$$ LANGUAGE 'plpgsql' IMMUTABLE; From 2c373dd9c797662c03992f8aefe0705fe072a70e Mon Sep 17 00:00:00 2001 From: abelvm Date: Tue, 16 Aug 2016 11:28:34 -0400 Subject: [PATCH 11/16] add CDB_dependencies --- src/pg/sql/13_PIA.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql index e59a3b8..be16871 100644 --- a/src/pg/sql/13_PIA.sql +++ b/src/pg/sql/13_PIA.sql @@ -61,7 +61,7 @@ BEGIN test_h := ST_XMax(cell) - ST_XMin(cell) ; -- check distance - test_d := _Signed_Dist(polygon, ST_Centroid(cell)); + test_d := cdb_crankshaft._Signed_Dist(polygon, ST_Centroid(cell)); IF test_d > best_d THEN best_d := test_d; best_c := cells[i]; From 250f932915fe9d3dc7cb735ee827cdb7051f60a6 Mon Sep 17 00:00:00 2001 From: abelvm Date: Tue, 16 Aug 2016 11:35:15 -0400 Subject: [PATCH 12/16] add CDB_dependencies --- src/pg/test/expected/13_pia_test.out | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pg/test/expected/13_pia_test.out b/src/pg/test/expected/13_pia_test.out index cff1550..d51c9c8 100644 --- a/src/pg/test/expected/13_pia_test.out +++ b/src/pg/test/expected/13_pia_test.out @@ -1,6 +1,6 @@ SET client_min_messages TO WARNING; \set ECHO none - st_astext + st_astext ------------------------------------------- POINT(-409081.865887381 4930017.52075948) (1 row) From 605e6e88aeec027b3b729a4ad990d7df0d4c6b43 Mon Sep 17 00:00:00 2001 From: abelvm Date: Tue, 30 Aug 2016 05:47:20 -0400 Subject: [PATCH 13/16] remove redundant function --- src/pg/sql/13_PIA.sql | 97 ------------------------------------------- 1 file changed, 97 deletions(-) diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql index be16871..36682b3 100644 --- a/src/pg/sql/13_PIA.sql +++ b/src/pg/sql/13_PIA.sql @@ -120,100 +120,3 @@ BEGIN RETURN dist; END; $$ language plpgsql IMMUTABLE; - --- --- Fill given extent with a rectangular coverage --- --- @param ext Extent to fill. Only rectangles with center point falling --- inside the extent (or at the lower or leftmost edge) will --- be emitted. The returned hexagons will have the same SRID --- as this extent. --- --- @param width With of each rectangle --- --- @param height Height of each rectangle --- --- @param origin Optional origin to allow for exact tiling. --- If omitted the origin will be 0,0. --- The parameter is checked for having the same SRID --- as the extent. --- --- -CREATE OR REPLACE FUNCTION CDB_RectangleGrid(ext GEOMETRY, width FLOAT8, height FLOAT8, origin GEOMETRY DEFAULT NULL) -RETURNS SETOF GEOMETRY -AS $$ -DECLARE - h GEOMETRY; -- rectangle cell - hstep FLOAT8; -- horizontal step - vstep FLOAT8; -- vertical step - hw FLOAT8; -- half width - hh FLOAT8; -- half height - vstart FLOAT8; - hstart FLOAT8; - hend FLOAT8; - vend FLOAT8; - xoff FLOAT8; - yoff FLOAT8; - xgrd FLOAT8; - ygrd FLOAT8; - x FLOAT8; - y FLOAT8; - srid INTEGER; -BEGIN - - srid := ST_SRID(ext); - - xoff := 0; - yoff := 0; - - IF origin IS NOT NULL THEN - IF ST_SRID(origin) != srid THEN - RAISE EXCEPTION 'SRID mismatch between extent (%) and origin (%)', srid, ST_SRID(origin); - END IF; - xoff := ST_X(origin); - yoff := ST_Y(origin); - END IF; - - --RAISE DEBUG 'X offset: %', xoff; - --RAISE DEBUG 'Y offset: %', yoff; - - hw := width/2.0; - hh := height/2.0; - - xgrd := hw; - ygrd := hh; - --RAISE DEBUG 'X grid size: %', xgrd; - --RAISE DEBUG 'Y grid size: %', ygrd; - - hstep := width; - vstep := height; - - -- Tweak horizontal start on hstep grid from origin - hstart := xoff + ceil((ST_XMin(ext)-xoff)/hstep)*hstep; - --RAISE DEBUG 'hstart: %', hstart; - - -- Tweak vertical start on vstep grid from origin - vstart := yoff + ceil((ST_Ymin(ext)-yoff)/vstep)*vstep; - --RAISE DEBUG 'vstart: %', vstart; - - hend := ST_XMax(ext); - vend := ST_YMax(ext); - - --RAISE DEBUG 'hend: %', hend; - --RAISE DEBUG 'vend: %', vend; - - x := hstart; - WHILE x < hend LOOP -- over X - y := vstart; - h := ST_MakeEnvelope(x-hw, y-hh, x+hw, y+hh, srid); - WHILE y < vend LOOP -- over Y - RETURN NEXT h; - h := ST_Translate(h, 0, vstep); - y := yoff + round(((y + vstep)-yoff)/ygrd)*ygrd; -- round to grid - END LOOP; - x := xoff + round(((x + hstep)-xoff)/xgrd)*xgrd; -- round to grid - END LOOP; - - RETURN; -END -$$ LANGUAGE 'plpgsql' IMMUTABLE; From 72ee1a6d4839d1035ba42fa89547cf16b74ffec3 Mon Sep 17 00:00:00 2001 From: abelvm Date: Tue, 30 Aug 2016 05:50:20 -0400 Subject: [PATCH 14/16] missed files --- doc/09_voronoi.md | 38 ++++ src/pg/sql/09_voronoi.sql | 236 +++++++++++++++++++++++ src/pg/test/expected/09_voronoi_test.out | 7 + src/pg/test/sql/09_voronoi_test.sql | 15 ++ 4 files changed, 296 insertions(+) create mode 100644 doc/09_voronoi.md create mode 100644 src/pg/sql/09_voronoi.sql create mode 100644 src/pg/test/expected/09_voronoi_test.out create mode 100644 src/pg/test/sql/09_voronoi_test.sql diff --git a/doc/09_voronoi.md b/doc/09_voronoi.md new file mode 100644 index 0000000..1a19103 --- /dev/null +++ b/doc/09_voronoi.md @@ -0,0 +1,38 @@ +## Voronoi + +Function to construct the [Voronoi Diagram](https://en.wikipedia.org/wiki/Voronoi_diagram) from a dataset of scatter points, clipped to the significant area + +PostGIS wil include this in future versions ([doc for dev branch](http://postgis.net/docs/manual-dev/ST_Voronoi.html)) and will perform faster for sure, but in the meantime... + + +### CDB_Voronoi (geom geometry[], buffer numeric DEFAULT 0.5, tolerance numeric DEFAULT 1e-9) + +#### Arguments + +| Name | Type | Description | +|------|------|-------------| +| geom | geometry[] | Array of points's geometries | +| buffer | numeric | enlargment ratio for the envelope area used for the restraints| +| tolerance | numeric | Delaunay tolerance, optional | + +### Returns + +| Column Name | Type | Description | +|-------------|------|-------------| +| geom | geometry collection | Collection of polygons of the Voronoi cells| + + +#### Example Usage + +```sql +WITH a AS ( + SELECT + ARRAY[ST_GeomFromText('POINT(2.1744 41.403)', 4326),ST_GeomFromText('POINT(2.1228 41.380)', 4326),ST_GeomFromText('POINT(2.1511 41.374)', 4326),ST_GeomFromText('POINT(2.1528 41.413)', 4326),ST_GeomFromText('POINT(2.165 41.391)', 4326),ST_GeomFromText('POINT(2.1498 41.371)', 4326),ST_GeomFromText('POINT(2.1533 41.368)', 4326),ST_GeomFromText('POINT(2.131386 41.41399)', 4326)] AS geomin +) +SELECT + st_transform( + (st_dump(CDB_voronoi(geomin, 0.2, 1e-9) + )).geom + , 3857) as the_geom_webmercator +FROM a; +``` diff --git a/src/pg/sql/09_voronoi.sql b/src/pg/sql/09_voronoi.sql new file mode 100644 index 0000000..361525c --- /dev/null +++ b/src/pg/sql/09_voronoi.sql @@ -0,0 +1,236 @@ +-- ============================================================================================= +-- +-- CDB_Voronoi +-- +-- ============================================================================================= +CREATE OR REPLACE FUNCTION CDB_voronoi( + IN geomin geometry[], + IN buffer numeric DEFAULT 0.5, + IN tolerance numeric DEFAULT 1e-9 + ) +RETURNS geometry AS $$ +DECLARE + geomout geometry; +BEGIN + -- we need to make the geometry calculations in (pseudo)meters!!! + with a as ( + SELECT unnest(geomin) as g1 + ), + b as( + SELECT st_transform(g1, 3857) g2 from a + ) + SELECT array_agg(g2) INTO geomin from b; + + WITH + convexhull_1 as ( + SELECT + ST_ConvexHull(ST_Collect(geomin)) as g, + buffer * |/ (st_area(ST_ConvexHull(ST_Collect(geomin)))/PI()) as r + ), + clipper as( + SELECT + st_buffer(ST_MinimumBoundingCircle(a.g), buffer*a.r) as g + FROM convexhull_1 a + ), + env0 as ( + SELECT + (st_dumppoints(st_expand(a.g, buffer*a.r))).geom as e + FROM convexhull_1 a + ), + env as ( + SELECT + array_agg(env0.e) as e + FROM env0 + ), + sample AS ( + SELECT + ST_Collect(geomin || env.e) as geom + FROM env + ), + convexhull as ( + SELECT + ST_ConvexHull(ST_Collect(geomin)) as cg + ), + tin as ( + SELECT + ST_Dump(ST_DelaunayTriangles(geom, tolerance, 0)) as gd + FROM + sample + ), + tin_polygons as ( + SELECT + (gd).Path as id, + (gd).Geom as pg, + ST_Centroid(ST_MinimumBoundingCircle((gd).Geom, 180)) as ct + FROM tin + ), + tin_lines as ( + SELECT + id, + ST_ExteriorRing(pg) as lg + FROM tin_polygons + ), + tin_nodes as ( + SELECT + id, + ST_PointN(lg,1) p1, + ST_PointN(lg,2) p2, + ST_PointN(lg,3) p3 + FROM tin_lines + ), + tin_edges AS ( + SELECT + p.id, + UNNEST(ARRAY[ + ST_MakeLine(n.p1,n.p2) , + ST_MakeLine(n.p2,n.p3) , + ST_MakeLine(n.p3,n.p1)]) as Edge, + ST_Force2D(cdb_crankshaft._Find_Circle(n.p1,n.p2,n.p3)) as ct, + CASE WHEN st_distance(p.ct, ST_ExteriorRing(p.pg)) < tolerance THEN + TRUE + ELSE FALSE END AS ctx, + p.pg, + ST_within(p.ct, convexhull.cg) as ctin + FROM + tin_polygons p, + tin_nodes n, + convexhull + WHERE p.id = n.id + ), + voro_nodes as ( + SELECT + CASE WHEN x.ctx = TRUE THEN + ST_Centroid(x.edge) + ELSE + x.ct + END as xct, + CASE WHEN y.id is null THEN + CASE WHEN x.ctin = TRUE THEN + ST_SetSRID(ST_MakePoint( + ST_X(x.ct) + ((ST_X(ST_Centroid(x.edge)) - ST_X(x.ct)) * (1+buffer)), + ST_Y(x.ct) + ((ST_Y(ST_Centroid(x.edge)) - ST_Y(x.ct)) * (1+buffer)) + ), ST_SRID(x.ct)) + END + ELSE + y.ct + END as yct + FROM + tin_edges x + LEFT OUTER JOIN + tin_edges y + ON x.id <> y.id AND ST_Equals(x.edge, y.edge) + ), + voro_edges as( + SELECT + ST_LineMerge(ST_Collect(ST_MakeLine(xct, yct))) as v + FROM + voro_nodes + ), + voro_cells as( + SELECT + ST_Polygonize( + ST_Node( + ST_LineMerge( + ST_Union(v, ST_ExteriorRing( + ST_Convexhull(v) + ) + ) + ) + ) + ) as g + FROM + voro_edges + ), + voro_set as( + SELECT + (st_dump(v.g)).geom as g + FROM voro_cells v + ), + clipped_voro as( + SELECT + ST_intersection(c.g, v.g) as g + FROM + voro_set v, + clipper c + WHERE + ST_GeometryType(v.g) = 'ST_Polygon' + ) + SELECT + st_collect( + ST_Transform( + ST_ConvexHull(g), + 4326 + ) + ) + INTO geomout + FROM + clipped_voro; + RETURN geomout; +END; +$$ language plpgsql IMMUTABLE; + +/** ---------------------------------------------------------------------------------------- + * @function : FindCircle + * @precis : Function that determines if three points form a circle. If so a table containing + * centre and radius is returned. If not, a null table is returned. + * @version : 1.0.1 + * @param : p_pt1 : First point in curve + * @param : p_pt2 : Second point in curve + * @param : p_pt3 : Third point in curve + * @return : geometry : In which X,Y ordinates are the centre X, Y and the Z being the radius of found circle + * or NULL if three points do not form a circle. + * @history : Simon Greener - Feb 2012 - Original coding. + * Rafa de la Torre - Aug 2016 - Small fix for type checking + * @copyright : Simon Greener @ 2012 + * Licensed under a Creative Commons Attribution-Share Alike 2.5 Australia License. (http://creativecommons.org/licenses/by-sa/2.5/au/) +**/ +CREATE OR REPLACE FUNCTION _Find_Circle( + IN p_pt1 geometry, + IN p_pt2 geometry, + IN p_pt3 geometry) + RETURNS geometry AS +$BODY$ +DECLARE + v_Centre geometry; + v_radius NUMERIC; + v_CX NUMERIC; + v_CY NUMERIC; + v_dA NUMERIC; + v_dB NUMERIC; + v_dC NUMERIC; + v_dD NUMERIC; + v_dE NUMERIC; + v_dF NUMERIC; + v_dG NUMERIC; +BEGIN + IF ( p_pt1 IS NULL OR p_pt2 IS NULL OR p_pt3 IS NULL ) THEN + RAISE EXCEPTION 'All supplied points must be not null.'; + RETURN NULL; + END IF; + IF ( ST_GeometryType(p_pt1) <> 'ST_Point' OR + ST_GeometryType(p_pt2) <> 'ST_Point' OR + ST_GeometryType(p_pt3) <> 'ST_Point' ) THEN + RAISE EXCEPTION 'All supplied geometries must be points.'; + RETURN NULL; + END IF; + v_dA := ST_X(p_pt2) - ST_X(p_pt1); + v_dB := ST_Y(p_pt2) - ST_Y(p_pt1); + v_dC := ST_X(p_pt3) - ST_X(p_pt1); + v_dD := ST_Y(p_pt3) - ST_Y(p_pt1); + v_dE := v_dA * (ST_X(p_pt1) + ST_X(p_pt2)) + v_dB * (ST_Y(p_pt1) + ST_Y(p_pt2)); + v_dF := v_dC * (ST_X(p_pt1) + ST_X(p_pt3)) + v_dD * (ST_Y(p_pt1) + ST_Y(p_pt3)); + v_dG := 2.0 * (v_dA * (ST_Y(p_pt3) - ST_Y(p_pt2)) - v_dB * (ST_X(p_pt3) - ST_X(p_pt2))); + -- If v_dG is zero then the three points are collinear and no finite-radius + -- circle through them exists. + IF ( v_dG = 0 ) THEN + RETURN NULL; + ELSE + v_CX := (v_dD * v_dE - v_dB * v_dF) / v_dG; + v_CY := (v_dA * v_dF - v_dC * v_dE) / v_dG; + v_Radius := SQRT(POWER(ST_X(p_pt1) - v_CX,2) + POWER(ST_Y(p_pt1) - v_CY,2) ); + END IF; + RETURN ST_SetSRID(ST_MakePoint(v_CX, v_CY, v_radius),ST_Srid(p_pt1)); +END; +$BODY$ + LANGUAGE plpgsql VOLATILE STRICT; + diff --git a/src/pg/test/expected/09_voronoi_test.out b/src/pg/test/expected/09_voronoi_test.out new file mode 100644 index 0000000..58b9e50 --- /dev/null +++ b/src/pg/test/expected/09_voronoi_test.out @@ -0,0 +1,7 @@ +SET client_min_messages TO WARNING; +\set ECHO none + avg_area +---------------------- + 0.000178661700690617 +(1 row) + diff --git a/src/pg/test/sql/09_voronoi_test.sql b/src/pg/test/sql/09_voronoi_test.sql new file mode 100644 index 0000000..032eeeb --- /dev/null +++ b/src/pg/test/sql/09_voronoi_test.sql @@ -0,0 +1,15 @@ +SET client_min_messages TO WARNING; +\set ECHO none + +WITH a AS ( + SELECT + ARRAY[ST_GeomFromText('POINT(2.1744 41.403)', 4326),ST_GeomFromText('POINT(2.1228 41.380)', 4326),ST_GeomFromText('POINT(2.1511 41.374)', 4326),ST_GeomFromText('POINT(2.1528 41.413)', 4326),ST_GeomFromText('POINT(2.165 41.391)', 4326),ST_GeomFromText('POINT(2.1498 41.371)', 4326),ST_GeomFromText('POINT(2.1533 41.368)', 4326),ST_GeomFromText('POINT(2.131386 41.41399)', 4326)] AS geomin +), +b as( + SELECT + (st_dump(cdb_crankshaft.CDB_voronoi(geomin, 0.2, 1e-9))).geom as result + FROM a +) +SELECT + avg(st_area(result)) as avg_area +FROM b; From 37eb85350d4f5d374cf72674dd254dec324a5735 Mon Sep 17 00:00:00 2001 From: abelvm Date: Tue, 30 Aug 2016 05:55:34 -0400 Subject: [PATCH 15/16] fix projection --- doc/13_PIA.md | 5 ++++- src/pg/sql/13_PIA.sql | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/13_PIA.md b/doc/13_PIA.md index 35b980b..c8986e2 100644 --- a/doc/13_PIA.md +++ b/doc/13_PIA.md @@ -25,6 +25,9 @@ Function to find the [PIA](https://en.wikipedia.org/wiki/Pole_of_inaccessibility ```sql with a as( select st_geomfromtext('POLYGON((-432540.453078056 4949775.20452642,-432329.947920966 4951361.232584,-431245.028163694 4952223.31516671,-429131.071033529 4951768.00415574,-424622.07505895 4952843.13503987,-423688.327170174 4953499.20752423,-424086.294349759 4954968.38274191,-423068.388925945 4954378.63345336,-423387.653225542 4953355.67417084,-420594.869840519 4953781.00230592,-416026.095299382 4951484.06849063,-412483.018546414 4951024.5410983,-410490.399661215 4954502.24032205,-408186.197521284 4956398.91417441,-407627.262358013 4959300.94633864,-406948.770061627 4959874.85407739,-404949.583326472 4959047.74518163,-402570.908447199 4953743.46829807,-400971.358683991 4952193.11680804,-403533.488084088 4949649.89857885,-406335.177028373 4950193.19571096,-407790.456731515 4952391.46015616,-412060.672398345 4950381.2389307,-410716.93482498 4949156.7509561,-408464.162289794 4943912.8940387,-409350.599394983 4942819.84896006,-408087.791091424 4942451.6711778,-407274.045613725 4940572.4807777,-404446.196589102 4939976.71501489,-402422.964843936 4940450.3670813,-401010.654464241 4939054.8061663,-397647.247369412 4940679.80737878,-395658.413346901 4940528.84765185,-395536.852462953 4938829.79565997,-394268.923462818 4938003.7277717,-393388.720249116 4934757.80596815,-392393.301362444 4934326.71675815,-392573.527618037 4932323.40974412,-393464.640141837 4931903.10653605,-393085.597275686 4931094.7353605,-398426.261165985 4929156.87541607,-398261.174361137 4926238.00816416,-394045.059966834 4925765.18668498,-392982.960705174 4926391.81893628,-393090.272694301 4927176.84692181,-391648.240010564 4924626.06386961,-391889.914625075 4923086.14787613,-394345.177314013 4923235.086036,-395550.878718795 4917812.79243978,-399009.463978251 4912927.7157945,-398948.794855767 4911941.91010796,-398092.636652078 4911806.57392519,-401991.601817112 4911722.9204501,-406225.972607907 4914505.47286319,-411104.994569885 4912569.26941163,-412925.513522316 4913030.3608866,-414630.148884835 4914436.69169949,-414207.691417276 4919205.78028405,-418306.141109809 4917994.9580478,-424184.700779621 4918938.12432889,-426816.961458921 4923664.37379373,-420956.324227126 4923381.98014807,-420186.661267781 4924286.48693378,-420943.411166194 4926812.76394433,-419779.45457046 4928527.43466337,-419768.767899344 4930681.94459216,-421911.668097113 4930432.40620397,-423482.386112205 4933451.28047252,-427272.814773717 4934151.56473242,-427144.908678797 4939731.77191996,-428982.125554848 4940522.84445172,-428986.133056516 4942437.17281266,-431237.792396792 4947309.68284815,-432476.889648814 4947791.74800037,-432540.453078056 4949775.20452642))', 3857) as g +), +b as ( + select ST_Transform(g, 4326) as g from a ) -SELECT st_astext(CDB_PIA(g)) from a; +SELECT st_astext(CDB_PIA(g)) from b; ``` diff --git a/src/pg/sql/13_PIA.sql b/src/pg/sql/13_PIA.sql index 36682b3..d9a224d 100644 --- a/src/pg/sql/13_PIA.sql +++ b/src/pg/sql/13_PIA.sql @@ -32,6 +32,7 @@ DECLARE p geometry; BEGIN sqr := |/2; + polygon := ST_Transform(polygon, 3857); -- grid #0 cell size height := ST_YMax(polygon) - ST_YMin(polygon); @@ -87,7 +88,7 @@ BEGIN END LOOP; - RETURN ST_Centroid(best_c); + RETURN ST_transform(ST_Centroid(best_c), 4326); END; $$ language plpgsql IMMUTABLE; From 2b75da1db21232ad4a9435d534460e141a99085b Mon Sep 17 00:00:00 2001 From: abelvm Date: Tue, 30 Aug 2016 06:02:42 -0400 Subject: [PATCH 16/16] fix test --- src/pg/test/expected/13_pia_test.out | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pg/test/expected/13_pia_test.out b/src/pg/test/expected/13_pia_test.out index d51c9c8..2367e20 100644 --- a/src/pg/test/expected/13_pia_test.out +++ b/src/pg/test/expected/13_pia_test.out @@ -2,6 +2,6 @@ SET client_min_messages TO WARNING; \set ECHO none st_astext ------------------------------------------- - POINT(-409081.865887381 4930017.52075948) + POINT(-3.67484492582767 40.4395084885993) (1 row)