Skip to content

Commit

Permalink
Merge pull request #96 from esabol/add-spoly-array-constructor
Browse files Browse the repository at this point in the history
Add function to create spoly from an array of numbers in radians
  • Loading branch information
vitcpp authored Nov 3, 2023
2 parents 126ad72 + 0fcfa36 commit 81939cf
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 29 deletions.
26 changes: 26 additions & 0 deletions expected/poly.out
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,18 @@ SELECT spoly '{(10d,0d),(10d,1d),(15d,0d)}';
{(10d , 0d),(10d , 1d),(15d , 0d)}
(1 row)

SELECT spoly(ARRAY[0.017453292519943295, 0.03490658503988659, 0.05235987755982988, 0.06981317007977318, 0.08726646259971647, 0.10471975511965977]);
spoly
---------------------------------
{(1d , 2d),(3d , 4d),(5d , 6d)}
(1 row)

SELECT spoly(ARRAY[0.17453292519943295, 0.0, 0.17453292519943295, 0.017453292519943295, 0.2617993877991494, 0.0]);
spoly
------------------------------------
{(10d , 0d),(10d , 1d),(15d , 0d)}
(1 row)

SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
spoly_deg
---------------------------------
Expand All @@ -335,8 +347,22 @@ SELECT spoly '{(10d,0d),(10d,1d)}';
ERROR: spherepoly_in: more than two points needed
LINE 1: SELECT spoly '{(10d,0d),(10d,1d)}';
^
SELECT spoly(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0]);
ERROR: spherepoly_rad: invalid number of arguments (must be even and >= 6)
SELECT spoly(ARRAY[1.0, 2.0, 3.0, NULL, 5.0, 6.0]);
ERROR: spherepoly_rad: input array is invalid because it has null values
SELECT spoly(ARRAY[]::float8[]);
ERROR: spherepoly_rad: invalid number of arguments (must be even and >= 6)
SELECT spoly(NULL::float8[]);
spoly
-------

(1 row)

SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0]);
ERROR: spherepoly_deg: invalid number of arguments (must be even and >= 6)
SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, NULL, 5.0, 6.0]);
ERROR: spherepoly_deg: input array is invalid because it has null values
SELECT spoly_deg(ARRAY[]::float8[]);
ERROR: spherepoly_deg: invalid number of arguments (must be even and >= 6)
SELECT spoly_deg(NULL::float8[]);
Expand Down
41 changes: 27 additions & 14 deletions pgs_polygon.sql.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

-- **************************
--
-- spherical polygon functions

--
-- **************************

CREATE FUNCTION npoints(spoly)
RETURNS INT4
Expand Down Expand Up @@ -933,6 +935,29 @@ COMMENT ON OPERATOR !&& (sellipse, spoly) IS
'true if spherical ellipse does not overlap spherical polygon';


--
-- Functions to create a polygon from arrays
--

CREATE FUNCTION spoly(float8[])
RETURNS spoly
AS 'MODULE_PATHNAME', 'spherepoly_rad'
LANGUAGE 'c'
IMMUTABLE STRICT PARALLEL SAFE;

COMMENT ON FUNCTION spoly(float8[]) IS
'creates spoly from array of numbers in radians';

CREATE FUNCTION spoly_deg(float8[])
RETURNS spoly
AS 'MODULE_PATHNAME', 'spherepoly_deg'
LANGUAGE 'c'
IMMUTABLE STRICT PARALLEL SAFE;

COMMENT ON FUNCTION spoly_deg(float8[]) IS
'creates spoly from array of numbers in degrees';


--
-- Aggregate functions to add points to polygon
--
Expand All @@ -946,18 +971,6 @@ CREATE FUNCTION spoly_add_point_aggr (spoly, spoint)
COMMENT ON FUNCTION spoly_add_point_aggr (spoly, spoint) IS
'adds a spherical point to spherical polygon. Do not use it standalone!';

CREATE FUNCTION spoly_deg(float8[])
RETURNS spoly
AS 'MODULE_PATHNAME', 'spherepoly_deg'
LANGUAGE 'c'
IMMUTABLE STRICT;

COMMENT ON FUNCTION spoly_deg(float8[]) IS
' Create spoly from array of points.
Two consecutive numbers among those present
refer to the same occurrence and cover its
latitude and longitude, respectively.';

CREATE FUNCTION spoly_add_points_fin_aggr (spoly)
RETURNS spoly
AS 'MODULE_PATHNAME', 'spherepoly_add_points_finalize'
Expand Down
14 changes: 14 additions & 0 deletions sql/poly.sql
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ SELECT spoly '{(359d,0d),(359d,1d),(4d,0d)}';

SELECT spoly '{(10d,0d),(10d,1d),(15d,0d)}';

SELECT spoly(ARRAY[0.017453292519943295, 0.03490658503988659, 0.05235987755982988, 0.06981317007977318, 0.08726646259971647, 0.10471975511965977]);

SELECT spoly(ARRAY[0.17453292519943295, 0.0, 0.17453292519943295, 0.017453292519943295, 0.2617993877991494, 0.0]);

SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);

SELECT spoly_deg(ARRAY[10.0, 0.0, 10.0, 1.0, 15.0, 0.0]);
Expand All @@ -86,8 +90,18 @@ SELECT spoly_deg(ARRAY[10.0, 0.0, 10.0, 1.0, 15.0, 0.0]);

SELECT spoly '{(10d,0d),(10d,1d)}';

SELECT spoly(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0]);

SELECT spoly(ARRAY[1.0, 2.0, 3.0, NULL, 5.0, 6.0]);

SELECT spoly(ARRAY[]::float8[]);

SELECT spoly(NULL::float8[]);

SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0]);

SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, NULL, 5.0, 6.0]);

SELECT spoly_deg(ARRAY[]::float8[]);

SELECT spoly_deg(NULL::float8[]);
Expand Down
82 changes: 69 additions & 13 deletions src/polygon.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

PG_FUNCTION_INFO_V1(spherepoly_in);
PG_FUNCTION_INFO_V1(spherepoly_deg);
PG_FUNCTION_INFO_V1(spherepoly_rad);
PG_FUNCTION_INFO_V1(spherepoly_equal);
PG_FUNCTION_INFO_V1(spherepoly_equal_neg);
PG_FUNCTION_INFO_V1(spherepoly_circ);
Expand Down Expand Up @@ -906,6 +907,56 @@ spherepoly_in(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(poly);
}

Datum
spherepoly_rad(PG_FUNCTION_ARGS)
{
int i,
np;
ArrayType *float_vector = PG_GETARG_ARRAYTYPE_P(0);
float8 *array_data;
SPoint *points;

np = ArrayGetNItems(ARR_NDIM(float_vector), ARR_DIMS(float_vector));

if (ARR_HASNULL(float_vector))
{
elog(ERROR,
"spherepoly_rad: input array is invalid because it has null values"
);
PG_RETURN_NULL();
}

if (np < 6 || np % 2 != 0)
{
elog(ERROR,
"spherepoly_rad: invalid number of arguments (must be even and >= 6)"
);
PG_RETURN_NULL();
}

np /= 2;

points = (SPoint *) palloc(np * sizeof(SPoint));
if (points == NULL)
{
elog(ERROR,
"spherepoly_rad: failed to allocate memory for points array"
);
PG_RETURN_NULL();
}

array_data = (float8 *) ARR_DATA_PTR(float_vector);

for (i = 0; i < np; i++)
{
create_spherepoint_from_long_lat(&points[i],
array_data[2 * i],
array_data[2 * i + 1]
);
}
PG_RETURN_POINTER(spherepoly_from_array(points, np));
}

Datum
spherepoly_deg(PG_FUNCTION_ARGS)
{
Expand All @@ -917,12 +968,19 @@ spherepoly_deg(PG_FUNCTION_ARGS)

np = ArrayGetNItems(ARR_NDIM(float_vector), ARR_DIMS(float_vector));

if (ARR_HASNULL(float_vector))
{
elog(ERROR,
"spherepoly_deg: input array is invalid because it has null values"
);
PG_RETURN_NULL();
}

if (np < 6 || np % 2 != 0)
{
elog(
ERROR,
"spherepoly_deg: invalid number of arguments (must be even and >= 6)"
);
elog(ERROR,
"spherepoly_deg: invalid number of arguments (must be even and >= 6)"
);
PG_RETURN_NULL();
}

Expand All @@ -931,22 +989,20 @@ spherepoly_deg(PG_FUNCTION_ARGS)
points = (SPoint *) palloc(np * sizeof(SPoint));
if (points == NULL)
{
elog(
ERROR,
"spherepoly_deg: failed for allocate memory for points array"
);
elog(ERROR,
"spherepoly_deg: failed to allocate memory for points array"
);
PG_RETURN_NULL();
}

array_data = (float8 *) ARR_DATA_PTR(float_vector);

for (i = 0; i < np; i++)
{
create_spherepoint_from_long_lat(
&points[i],
deg_to_rad(array_data[2 * i]),
deg_to_rad(array_data[2 * i + 1])
);
create_spherepoint_from_long_lat(&points[i],
deg_to_rad(array_data[2 * i]),
deg_to_rad(array_data[2 * i + 1])
);
}
PG_RETURN_POINTER(spherepoly_from_array(points, np));
}
Expand Down
9 changes: 7 additions & 2 deletions src/polygon.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,14 @@ Datum spherepoly_get_point(PG_FUNCTION_ARGS);
int8 poly_line_pos(const SPOLY *poly, const SLine *line);

/*
* Input of a spherical from sequence of pairconsecutive numbers(lng, lat).
* Input of a spherical from array of pair-consecutive numbers (lng, lat), in radians.
*/
Datum spherepoly_deg(PG_FUNCTION_ARGS);
Datum spherepoly_rad(PG_FUNCTION_ARGS);

/*
* Input of a spherical from array of pair-consecutive numbers (lng, lat), in degrees.
*/
Datum spherepoly_deg(PG_FUNCTION_ARGS);

/*
* Input of a spherical polygon.
Expand Down
17 changes: 17 additions & 0 deletions upgrade_scripts/pg_sphere--1.3.1--1.3.2.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,20 @@ $$;
-- remove legacy spellings of operators
DROP OPERATOR IF EXISTS @(bigint, smoc);
DROP OPERATOR IF EXISTS @(spoint, smoc);

-- add spoly function that takes an array of float8 values in radians
CREATE FUNCTION spoly(float8[])
RETURNS spoly
AS 'MODULE_PATHNAME', 'spherepoly_rad'
LANGUAGE 'c'
IMMUTABLE STRICT PARALLEL SAFE;

COMMENT ON FUNCTION spoly(float8[]) IS
'creates spoly from array of numbers in radians';

-- add PARALLEL SAFE to spoly_deg(float8[])
ALTER FUNCTION spoly_deg(float8[]) IMMUTABLE STRICT PARALLEL SAFE;

-- update comment on spoly_deg function
COMMENT ON FUNCTION spoly_deg(float8[]) IS
'creates spoly from array of numbers in degrees';

0 comments on commit 81939cf

Please sign in to comment.