diff --git a/Makefile b/Makefile index dca3b7d..4e0f826 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,8 @@ DATA_built = $(RELEASE_SQL) \ pg_sphere--1.1.5beta4gavo--1.2.0.sql \ pg_sphere--1.2.0--1.2.1.sql \ pg_sphere--1.2.1--1.2.2.sql \ - pg_sphere--1.2.2--1.2.3.sql + pg_sphere--1.2.2--1.2.3.sql \ + pg_sphere--1.2.3--1.3.0.sql DOCS = README.pg_sphere COPYRIGHT.pg_sphere REGRESS = init tables points euler circle line ellipse poly path box index \ @@ -260,6 +261,9 @@ endif pg_sphere--1.2.2--1.2.3.sql: cat upgrade_scripts/$@.in > $@ +pg_sphere--1.2.3--1.3.0.sql: + cat upgrade_scripts/$@.in > $@ + # end of local stuff src/sscan.o : src/sparse.c diff --git a/doc/functions.sgm b/doc/functions.sgm index 30118bf..5cdc3aa 100644 --- a/doc/functions.sgm +++ b/doc/functions.sgm @@ -463,7 +463,7 @@ Positions at a path </title> <para> - <application>pgSphere</application> provides two functions to + <application>pgSphere</application> provides three functions to get points at a path. </para> <funcsynopsis> @@ -477,6 +477,10 @@ <paramdef>spath <parameter>path</parameter></paramdef> <paramdef>float8 <parameter>f</parameter></paramdef> </funcprototype> + <funcprototype> + <funcdef><function>spath_as_array</function></funcdef> + <paramdef>spath <parameter>path</parameter></paramdef> + </funcprototype> </funcsynopsis> <para> The first function returns the <parameter>i</parameter>-th @@ -495,6 +499,36 @@ <![CDATA[ spoint]]> <![CDATA[------------]]> <![CDATA[ (15d , 0d)]]> +<![CDATA[(1 row)]]> + </programlisting> + </example> + <example> + <title> + Get i-th point of a path + </title> + <programlisting> +<![CDATA[sql> SELECT spoint( spath '{(0, 0),(1, 1)}', 1 );]]> +<![CDATA[ spoint ]]> +<![CDATA[------------]]> +<![CDATA[ (0 , 0) ]]> +<![CDATA[(1 row)]]> +<![CDATA[]]> +<![CDATA[sql> SELECT spoint( spath '{(0, 0),(1, 1)}', 2 );]]> +<![CDATA[ spoint ]]> +<![CDATA[------------]]> +<![CDATA[ (1 , 1) ]]> +<![CDATA[(1 row)]]> + </programlisting> + </example> + <example> + <title> + Get array representation of points + </title> + <programlisting> +<![CDATA[sql> SELECT spath_as_array( spath '{(0, 0),(1, 1)}');]]> +<![CDATA[ spath_as_array ]]> +<![CDATA[-----------------------]]> +<![CDATA[ {"(0 , 0)","(1 , 1)"}]]> <![CDATA[(1 row)]]> </programlisting> </example> @@ -532,7 +566,58 @@ </example> </sect3> - + <sect3 id="funcs.spoly.pos"> + <title> + Positions at a polygon + </title> + <para> + <application>pgSphere</application> provides two functions to + get points at a path. + </para> + <funcsynopsis> + <funcprototype> + <funcdef><function>spoint</function></funcdef> + <paramdef>spoly <parameter>path</parameter></paramdef> + <paramdef>int4 <parameter>i</parameter></paramdef> + </funcprototype> + <funcprototype> + <funcdef><function>spoly_as_array</function></funcdef> + <paramdef>spath <parameter>path</parameter></paramdef> + </funcprototype> + </funcsynopsis> + <example> + <title>Get by index</title> + <programlisting> +<![CDATA[sql> SELECT spoint( spoly '{(0,0),(1,0),(1,1)}', 1 );]]> +<![CDATA[ spoint ]]> +<![CDATA[---------]]> +<![CDATA[ (0 , 0)]]> +<![CDATA[ (1 row)]]> +<![CDATA[]]> +<![CDATA[sql> SELECT spoint( spoly '{(0,0),(1,0),(1,1)}', 2 );]]> +<![CDATA[ spoint ]]> +<![CDATA[---------]]> +<![CDATA[ (1 , 0)]]> +<![CDATA[ (1 row)]]> +<![CDATA[]]> +<![CDATA[sql> SELECT spoint( spoly '{(0,0),(1,0),(1,1)}', 3 );]]> +<![CDATA[ spoint ]]> +<![CDATA[---------]]> +<![CDATA[ (1 , 1)]]> +<![CDATA[ (1 row)]]> + </programlisting> + </example> + <example> + <title>Represent points as array</title> + <programlisting> +<![CDATA[sql> SELECT spoly_as_array( spoly '{(0,0),(1,0),(1,1)}' );]]> +<![CDATA[ spoly_as_array ]]> +<![CDATA[---------------------------------]]> +<![CDATA[ {"(0 , 0)","(1 , 0)","(1 , 1)"}]]> +<![CDATA[(1 row)]]> + </programlisting> + </example> + </sect3> </sect2> <sect2 id="funcs.sbox"> diff --git a/expected/init_test.out.in b/expected/init_test.out.in index 129283c..30c1e9b 100644 --- a/expected/init_test.out.in +++ b/expected/init_test.out.in @@ -24,12 +24,12 @@ psql:pg_sphere.test.sql:159: NOTICE: argument type spath is only a shell psql:pg_sphere.test.sql:178: NOTICE: type "sbox" is not yet defined DETAIL: Creating a shell type definition. psql:pg_sphere.test.sql:185: NOTICE: argument type sbox is only a shell -psql:pg_sphere.test.sql:8540: NOTICE: type "spherekey" is not yet defined +psql:pg_sphere.test.sql:8566: NOTICE: type "spherekey" is not yet defined DETAIL: Creating a shell type definition. -psql:pg_sphere.test.sql:8547: NOTICE: argument type spherekey is only a shell -psql:pg_sphere.test.sql:8561: NOTICE: type "pointkey" is not yet defined +psql:pg_sphere.test.sql:8573: NOTICE: argument type spherekey is only a shell +psql:pg_sphere.test.sql:8587: NOTICE: type "pointkey" is not yet defined DETAIL: Creating a shell type definition. -psql:pg_sphere.test.sql:8568: NOTICE: argument type pointkey is only a shell -psql:pg_sphere.test.sql:8574: NOTICE: argument type pointkey is only a shell -psql:pg_sphere.test.sql:8580: NOTICE: argument type pointkey is only a shell -psql:pg_sphere.test.sql:8586: NOTICE: argument type pointkey is only a shell +psql:pg_sphere.test.sql:8594: NOTICE: argument type pointkey is only a shell +psql:pg_sphere.test.sql:8600: NOTICE: argument type pointkey is only a shell +psql:pg_sphere.test.sql:8606: NOTICE: argument type pointkey is only a shell +psql:pg_sphere.test.sql:8612: NOTICE: argument type pointkey is only a shell diff --git a/expected/init_test_healpix.out.in b/expected/init_test_healpix.out.in index 330dc68..e3445b1 100644 --- a/expected/init_test_healpix.out.in +++ b/expected/init_test_healpix.out.in @@ -1,2 +1,2 @@ -psql:pg_sphere.test.sql:9153: NOTICE: return type smoc is only a shell -psql:pg_sphere.test.sql:9159: NOTICE: argument type smoc is only a shell +psql:pg_sphere.test.sql:9179: NOTICE: return type smoc is only a shell +psql:pg_sphere.test.sql:9185: NOTICE: argument type smoc is only a shell diff --git a/expected/path.out b/expected/path.out index 1734d8c..9f62534 100644 --- a/expected/path.out +++ b/expected/path.out @@ -468,3 +468,28 @@ SELECT spoint(p,2) FROM spheretmp6 WHERE id=2; (1d , -5d) (1 row) +SELECT set_sphere_output( 'RAD' ); + set_sphere_output +------------------- + SET RAD +(1 row) + +-- get n-th point and array representation path points tests +SELECT spoint( spath '{(0, 0),(1, 1)}', 1 ); + spoint +--------- + (0 , 0) +(1 row) + +SELECT spoint( spath '{(0, 0),(1, 1)}', 2 ); + spoint +--------- + (1 , 1) +(1 row) + +SELECT spath_as_array( spath '{(0, 0),(1, 1)}'); + spath_as_array +----------------------- + {"(0 , 0)","(1 , 1)"} +(1 row) + diff --git a/expected/poly.out b/expected/poly.out index 201b9be..cf53bc5 100644 --- a/expected/poly.out +++ b/expected/poly.out @@ -1738,3 +1738,33 @@ SELECT npoints( spoly '{ 4 (1 row) +SELECT set_sphere_output( 'RAD' ); + set_sphere_output +------------------- + SET RAD +(1 row) + +SELECT spoint( spoly '{(0,0),(1,0),(1,1)}', 1 ); + spoint +--------- + (0 , 0) +(1 row) + +SELECT spoint( spoly '{(0,0),(1,0),(1,1)}', 2 ); + spoint +--------- + (1 , 0) +(1 row) + +SELECT spoint( spoly '{(0,0),(1,0),(1,1)}', 3 ); + spoint +--------- + (1 , 1) +(1 row) + +SELECT spoly_as_array( spoly '{(0,0),(1,0),(1,1)}' ); + spoly_as_array +--------------------------------- + {"(0 , 0)","(1 , 0)","(1 , 1)"} +(1 row) + diff --git a/pgs_path.sql.in b/pgs_path.sql.in index 94f3222..58268d4 100644 --- a/pgs_path.sql.in +++ b/pgs_path.sql.in @@ -34,6 +34,14 @@ CREATE FUNCTION spoint(spath, float8) COMMENT ON FUNCTION spoint(spath, float8) IS 'returns n-th point of spherical path using linear interpolation'; +CREATE FUNCTION spath_as_array(spath) + RETURNS spoint[] + AS 'MODULE_PATHNAME', 'spherepath_get_array' + LANGUAGE 'c' + IMMUTABLE STRICT PARALLEL SAFE; + +COMMENT ON FUNCTION spath_as_array(spath) IS + 'returns spath as array of points'; -- ****************************** -- diff --git a/pgs_polygon.sql.in b/pgs_polygon.sql.in index 701c860..6a85742 100644 --- a/pgs_polygon.sql.in +++ b/pgs_polygon.sql.in @@ -11,6 +11,24 @@ CREATE FUNCTION npoints(spoly) COMMENT ON FUNCTION npoints(spoly) IS 'returns number of points of spherical polygon'; +CREATE FUNCTION spoint(spoly, int4) + RETURNS spoint + AS 'MODULE_PATHNAME', 'spherepoly_get_point' + LANGUAGE 'c' + IMMUTABLE STRICT PARALLEL SAFE; + +COMMENT ON FUNCTION spoint(spoly, int4) IS + 'returns n-th point of spherical polygon'; + +CREATE FUNCTION spoly_as_array(spoly) + RETURNS spoint[] + AS 'MODULE_PATHNAME', 'spherepoly_get_array' + LANGUAGE 'c' + IMMUTABLE STRICT PARALLEL SAFE; + +COMMENT ON FUNCTION spoly_as_array(spoly) IS + 'returns spoly as array of points'; + CREATE FUNCTION area(spoly) RETURNS FLOAT8 AS 'MODULE_PATHNAME', 'spherepoly_area' diff --git a/sql/path.sql b/sql/path.sql index fef5c1f..85fb3ff 100644 --- a/sql/path.sql +++ b/sql/path.sql @@ -104,3 +104,9 @@ SELECT set_sphere_output( 'DEG' ); -- test stored data SELECT spoint(p,2) FROM spheretmp6 WHERE id=2; +SELECT set_sphere_output( 'RAD' ); + +-- get n-th point and array representation path points tests +SELECT spoint( spath '{(0, 0),(1, 1)}', 1 ); +SELECT spoint( spath '{(0, 0),(1, 1)}', 2 ); +SELECT spath_as_array( spath '{(0, 0),(1, 1)}'); diff --git a/sql/poly.sql b/sql/poly.sql index 4168024..57dd3b2 100644 --- a/sql/poly.sql +++ b/sql/poly.sql @@ -593,3 +593,10 @@ SELECT npoints( spoly '{ (1.5121581120647 , -1.93925472462553e-05), (1.51214841579108 , -1.93925472462553e-05) }'); + +SELECT set_sphere_output( 'RAD' ); + +SELECT spoint( spoly '{(0,0),(1,0),(1,1)}', 1 ); +SELECT spoint( spoly '{(0,0),(1,0),(1,1)}', 2 ); +SELECT spoint( spoly '{(0,0),(1,0),(1,1)}', 3 ); +SELECT spoly_as_array( spoly '{(0,0),(1,0),(1,1)}' ); diff --git a/src/path.c b/src/path.c index b72a753..198d9a0 100644 --- a/src/path.c +++ b/src/path.c @@ -1,4 +1,6 @@ #include "path.h" +#include "point.h" +#include <catalog/namespace.h> /* * Path functions @@ -50,6 +52,7 @@ PG_FUNCTION_INFO_V1(spheretrans_path); PG_FUNCTION_INFO_V1(spheretrans_path_inverse); PG_FUNCTION_INFO_V1(spherepath_add_point); PG_FUNCTION_INFO_V1(spherepath_add_points_finalize); +PG_FUNCTION_INFO_V1(spherepath_get_array); /* @@ -555,6 +558,31 @@ spherepath_get_point(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } +Datum +spherepath_get_array(PG_FUNCTION_ARGS) +{ + SPATH *path = PG_GETARG_SPATH(0); + Datum *datum_arr = (Datum *) palloc(sizeof(Datum) * path->npts); + ArrayType *res; + SPoint *p = (SPoint *) palloc(sizeof(SPoint) * path->npts); + for (size_t i = 0; i < path->npts; i++) + { + if (!spath_get_point(&p[i], path, i)) + { + // Clean up and return NULL + for (size_t j = 0; j < i; j++) + pfree(DatumGetPointer(datum_arr[j])); + pfree(datum_arr); + PG_RETURN_NULL(); + } + datum_arr[i] = PointerGetDatum(&p[i]); + } + + res = construct_array(datum_arr, path->npts, get_point_id(), sizeof(SPoint), false, 'd'); + + PG_RETURN_ARRAYTYPE_P(res); +} + Datum spherepath_point(PG_FUNCTION_ARGS) { diff --git a/src/path.h b/src/path.h index 1d0fc35..55aa096 100644 --- a/src/path.h +++ b/src/path.h @@ -71,6 +71,11 @@ Datum spherepath_in(PG_FUNCTION_ARGS); */ Datum spherepath_get_point(PG_FUNCTION_ARGS); +/* +* Returns spath as array of points +*/ +Datum spherepath_get_array(PG_FUNCTION_ARGS); + /* * This function interpolates between points of path. Returns the * n-th point of a path where n is a float. diff --git a/src/point.c b/src/point.c index 5132835..ccead71 100644 --- a/src/point.c +++ b/src/point.c @@ -13,6 +13,13 @@ PG_FUNCTION_INFO_V1(spherepoint_z); PG_FUNCTION_INFO_V1(spherepoint_xyz); PG_FUNCTION_INFO_V1(spherepoint_equal); +Oid get_point_id(void){ + if(POINT_ID == InvalidOid){ + POINT_ID = TypenameGetTypid("spoint"); + } + return POINT_ID; +} + bool spoint_eq(const SPoint *p1, const SPoint *p2) { diff --git a/src/point.h b/src/point.h index 76c2202..bb7df9a 100644 --- a/src/point.h +++ b/src/point.h @@ -3,6 +3,8 @@ #include "vector3d.h" #include "sbuffer.h" +#include <catalog/namespace.h> +#include <utils/resowner.h> /* This file contains declarations for spherical point and functions. */ @@ -15,6 +17,11 @@ typedef struct float8 lat; /* latitude value in radians */ } SPoint; +__attribute__((unused)) +static Oid POINT_ID = InvalidOid; + +Oid get_point_id(void); + /* * Calculate the distance between two spherical points in radians. */ diff --git a/src/polygon.c b/src/polygon.c index 8ae3fe8..79f3a3e 100644 --- a/src/polygon.c +++ b/src/polygon.c @@ -1,4 +1,5 @@ #include "polygon.h" +#include "point.h" /* Polygon functions */ @@ -9,6 +10,8 @@ PG_FUNCTION_INFO_V1(spherepoly_equal_neg); PG_FUNCTION_INFO_V1(spherepoly_circ); PG_FUNCTION_INFO_V1(spherepoly_npts); PG_FUNCTION_INFO_V1(spherepoly_area); +PG_FUNCTION_INFO_V1(spherepoly_get_point); +PG_FUNCTION_INFO_V1(spherepoly_get_array); PG_FUNCTION_INFO_V1(spherepoly_cont_point); PG_FUNCTION_INFO_V1(spherepoly_cont_point_neg); PG_FUNCTION_INFO_V1(spherepoly_cont_point_com); @@ -554,6 +557,58 @@ spoly_segment(SLine *sl, const SPOLY *poly, int32 i) } } +static bool +poly_get_point(SPoint *sp, const SPOLY *poly, int32 i) +{ + if (i >= 0 && i < poly->npts) + { + memcpy((void *) sp, (void *) &poly->p[i], sizeof(SPoint)); + return true; + } + return false; +} + +Datum +spherepoly_get_point(PG_FUNCTION_ARGS) +{ + int32 i; + SPOLY *poly = PG_GETARG_SPOLY(0); + SPoint *sp = (SPoint *) palloc(sizeof(SPoint)); + + i = PG_GETARG_INT32(1); + if (poly_get_point(sp, poly, i - 1)) + { + PG_RETURN_POINTER(sp); + } + pfree(sp); + PG_RETURN_NULL(); +} + +Datum +spherepoly_get_array(PG_FUNCTION_ARGS) +{ + SPOLY *poly = PG_GETARG_SPOLY(0); + Datum *datum_arr = (Datum *) palloc(sizeof(Datum) * poly->npts); + ArrayType *res; + SPoint *p = (SPoint *) palloc(sizeof(SPoint) * poly->npts); + for (size_t i = 0; i < poly->npts; i++) + { + if (!poly_get_point(&p[i], poly, i)) + { + // Clean up and return NULL + for (size_t j = 0; j < i; j++) + pfree(DatumGetPointer(datum_arr[j])); + pfree(datum_arr); + PG_RETURN_NULL(); + } + datum_arr[i] = PointerGetDatum(&p[i]); + } + + res = construct_array(datum_arr, poly->npts, get_point_id(), sizeof(SPoint), false, 'd'); + + PG_RETURN_ARRAYTYPE_P(res); +} + /* * Checks whether a polygon contains a point. * diff --git a/src/polygon.h b/src/polygon.h index 7f2aa80..48ed04c 100644 --- a/src/polygon.h +++ b/src/polygon.h @@ -72,6 +72,11 @@ bool spoly_segment(SLine *sl, const SPOLY *poly, int32 i); */ bool spoly_contains_point(const SPOLY *pg, const SPoint *sp); +/* + * Returns the n-th point of a spoly. +*/ +Datum spoly_get_point(PG_FUNCTION_ARGS); + /* * Returns the relationship between a polygon and a line as * PGS_LINE_POLY_REL int8 value. @@ -343,4 +348,9 @@ Datum spherepoly_add_point(PG_FUNCTION_ARGS); */ Datum spherepoly_add_points_finalize(PG_FUNCTION_ARGS); +/* +* Returns spoly as array of points +*/ +Datum spherepoly_get_array(PG_FUNCTION_ARGS); + #endif diff --git a/upgrade_scripts/pg_sphere--1.2.3--1.3.0.sql.in b/upgrade_scripts/pg_sphere--1.2.3--1.3.0.sql.in new file mode 100644 index 0000000..2705a58 --- /dev/null +++ b/upgrade_scripts/pg_sphere--1.2.3--1.3.0.sql.in @@ -0,0 +1,26 @@ +CREATE FUNCTION spath_as_array(spath) + RETURNS spoint[] + AS 'MODULE_PATHNAME', 'spherepath_get_array' + LANGUAGE 'c' + IMMUTABLE STRICT PARALLEL SAFE; + +COMMENT ON FUNCTION spath_as_array(spath) IS + 'returns spath as array of points'; + +CREATE FUNCTION spoint(spoly, int4) + RETURNS spoint + AS 'MODULE_PATHNAME', 'spherepoly_get_point' + LANGUAGE 'c' + IMMUTABLE STRICT PARALLEL SAFE; + +COMMENT ON FUNCTION spoint(spoly, int4) IS + 'returns n-th point of spherical polygon'; + +CREATE FUNCTION spoly_as_array(spoly) + RETURNS spoint[] + AS 'MODULE_PATHNAME', 'spherepoly_get_array' + LANGUAGE 'c' + IMMUTABLE STRICT PARALLEL SAFE; + +COMMENT ON FUNCTION spoly_as_array(spoly) IS + 'returns spoly as array of points';