Skip to content

Commit 81939cf

Browse files
authored
Merge pull request #96 from esabol/add-spoly-array-constructor
Add function to create spoly from an array of numbers in radians
2 parents 126ad72 + 0fcfa36 commit 81939cf

File tree

6 files changed

+160
-29
lines changed

6 files changed

+160
-29
lines changed

Diff for: expected/poly.out

+26
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,18 @@ SELECT spoly '{(10d,0d),(10d,1d),(15d,0d)}';
318318
{(10d , 0d),(10d , 1d),(15d , 0d)}
319319
(1 row)
320320

321+
SELECT spoly(ARRAY[0.017453292519943295, 0.03490658503988659, 0.05235987755982988, 0.06981317007977318, 0.08726646259971647, 0.10471975511965977]);
322+
spoly
323+
---------------------------------
324+
{(1d , 2d),(3d , 4d),(5d , 6d)}
325+
(1 row)
326+
327+
SELECT spoly(ARRAY[0.17453292519943295, 0.0, 0.17453292519943295, 0.017453292519943295, 0.2617993877991494, 0.0]);
328+
spoly
329+
------------------------------------
330+
{(10d , 0d),(10d , 1d),(15d , 0d)}
331+
(1 row)
332+
321333
SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
322334
spoly_deg
323335
---------------------------------
@@ -335,8 +347,22 @@ SELECT spoly '{(10d,0d),(10d,1d)}';
335347
ERROR: spherepoly_in: more than two points needed
336348
LINE 1: SELECT spoly '{(10d,0d),(10d,1d)}';
337349
^
350+
SELECT spoly(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0]);
351+
ERROR: spherepoly_rad: invalid number of arguments (must be even and >= 6)
352+
SELECT spoly(ARRAY[1.0, 2.0, 3.0, NULL, 5.0, 6.0]);
353+
ERROR: spherepoly_rad: input array is invalid because it has null values
354+
SELECT spoly(ARRAY[]::float8[]);
355+
ERROR: spherepoly_rad: invalid number of arguments (must be even and >= 6)
356+
SELECT spoly(NULL::float8[]);
357+
spoly
358+
-------
359+
360+
(1 row)
361+
338362
SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0]);
339363
ERROR: spherepoly_deg: invalid number of arguments (must be even and >= 6)
364+
SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, NULL, 5.0, 6.0]);
365+
ERROR: spherepoly_deg: input array is invalid because it has null values
340366
SELECT spoly_deg(ARRAY[]::float8[]);
341367
ERROR: spherepoly_deg: invalid number of arguments (must be even and >= 6)
342368
SELECT spoly_deg(NULL::float8[]);

Diff for: pgs_polygon.sql.in

+27-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
1+
-- **************************
2+
--
23
-- spherical polygon functions
3-
4+
--
5+
-- **************************
46

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

935937

938+
--
939+
-- Functions to create a polygon from arrays
940+
--
941+
942+
CREATE FUNCTION spoly(float8[])
943+
RETURNS spoly
944+
AS 'MODULE_PATHNAME', 'spherepoly_rad'
945+
LANGUAGE 'c'
946+
IMMUTABLE STRICT PARALLEL SAFE;
947+
948+
COMMENT ON FUNCTION spoly(float8[]) IS
949+
'creates spoly from array of numbers in radians';
950+
951+
CREATE FUNCTION spoly_deg(float8[])
952+
RETURNS spoly
953+
AS 'MODULE_PATHNAME', 'spherepoly_deg'
954+
LANGUAGE 'c'
955+
IMMUTABLE STRICT PARALLEL SAFE;
956+
957+
COMMENT ON FUNCTION spoly_deg(float8[]) IS
958+
'creates spoly from array of numbers in degrees';
959+
960+
936961
--
937962
-- Aggregate functions to add points to polygon
938963
--
@@ -946,18 +971,6 @@ CREATE FUNCTION spoly_add_point_aggr (spoly, spoint)
946971
COMMENT ON FUNCTION spoly_add_point_aggr (spoly, spoint) IS
947972
'adds a spherical point to spherical polygon. Do not use it standalone!';
948973

949-
CREATE FUNCTION spoly_deg(float8[])
950-
RETURNS spoly
951-
AS 'MODULE_PATHNAME', 'spherepoly_deg'
952-
LANGUAGE 'c'
953-
IMMUTABLE STRICT;
954-
955-
COMMENT ON FUNCTION spoly_deg(float8[]) IS
956-
' Create spoly from array of points.
957-
Two consecutive numbers among those present
958-
refer to the same occurrence and cover its
959-
latitude and longitude, respectively.';
960-
961974
CREATE FUNCTION spoly_add_points_fin_aggr (spoly)
962975
RETURNS spoly
963976
AS 'MODULE_PATHNAME', 'spherepoly_add_points_finalize'

Diff for: sql/poly.sql

+14
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ SELECT spoly '{(359d,0d),(359d,1d),(4d,0d)}';
7878

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

81+
SELECT spoly(ARRAY[0.017453292519943295, 0.03490658503988659, 0.05235987755982988, 0.06981317007977318, 0.08726646259971647, 0.10471975511965977]);
82+
83+
SELECT spoly(ARRAY[0.17453292519943295, 0.0, 0.17453292519943295, 0.017453292519943295, 0.2617993877991494, 0.0]);
84+
8185
SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
8286

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

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

93+
SELECT spoly(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0]);
94+
95+
SELECT spoly(ARRAY[1.0, 2.0, 3.0, NULL, 5.0, 6.0]);
96+
97+
SELECT spoly(ARRAY[]::float8[]);
98+
99+
SELECT spoly(NULL::float8[]);
100+
89101
SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, 4.0, 5.0]);
90102

103+
SELECT spoly_deg(ARRAY[1.0, 2.0, 3.0, NULL, 5.0, 6.0]);
104+
91105
SELECT spoly_deg(ARRAY[]::float8[]);
92106

93107
SELECT spoly_deg(NULL::float8[]);

Diff for: src/polygon.c

+69-13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
PG_FUNCTION_INFO_V1(spherepoly_in);
88
PG_FUNCTION_INFO_V1(spherepoly_deg);
9+
PG_FUNCTION_INFO_V1(spherepoly_rad);
910
PG_FUNCTION_INFO_V1(spherepoly_equal);
1011
PG_FUNCTION_INFO_V1(spherepoly_equal_neg);
1112
PG_FUNCTION_INFO_V1(spherepoly_circ);
@@ -906,6 +907,56 @@ spherepoly_in(PG_FUNCTION_ARGS)
906907
PG_RETURN_POINTER(poly);
907908
}
908909

910+
Datum
911+
spherepoly_rad(PG_FUNCTION_ARGS)
912+
{
913+
int i,
914+
np;
915+
ArrayType *float_vector = PG_GETARG_ARRAYTYPE_P(0);
916+
float8 *array_data;
917+
SPoint *points;
918+
919+
np = ArrayGetNItems(ARR_NDIM(float_vector), ARR_DIMS(float_vector));
920+
921+
if (ARR_HASNULL(float_vector))
922+
{
923+
elog(ERROR,
924+
"spherepoly_rad: input array is invalid because it has null values"
925+
);
926+
PG_RETURN_NULL();
927+
}
928+
929+
if (np < 6 || np % 2 != 0)
930+
{
931+
elog(ERROR,
932+
"spherepoly_rad: invalid number of arguments (must be even and >= 6)"
933+
);
934+
PG_RETURN_NULL();
935+
}
936+
937+
np /= 2;
938+
939+
points = (SPoint *) palloc(np * sizeof(SPoint));
940+
if (points == NULL)
941+
{
942+
elog(ERROR,
943+
"spherepoly_rad: failed to allocate memory for points array"
944+
);
945+
PG_RETURN_NULL();
946+
}
947+
948+
array_data = (float8 *) ARR_DATA_PTR(float_vector);
949+
950+
for (i = 0; i < np; i++)
951+
{
952+
create_spherepoint_from_long_lat(&points[i],
953+
array_data[2 * i],
954+
array_data[2 * i + 1]
955+
);
956+
}
957+
PG_RETURN_POINTER(spherepoly_from_array(points, np));
958+
}
959+
909960
Datum
910961
spherepoly_deg(PG_FUNCTION_ARGS)
911962
{
@@ -917,12 +968,19 @@ spherepoly_deg(PG_FUNCTION_ARGS)
917968

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

971+
if (ARR_HASNULL(float_vector))
972+
{
973+
elog(ERROR,
974+
"spherepoly_deg: input array is invalid because it has null values"
975+
);
976+
PG_RETURN_NULL();
977+
}
978+
920979
if (np < 6 || np % 2 != 0)
921980
{
922-
elog(
923-
ERROR,
924-
"spherepoly_deg: invalid number of arguments (must be even and >= 6)"
925-
);
981+
elog(ERROR,
982+
"spherepoly_deg: invalid number of arguments (must be even and >= 6)"
983+
);
926984
PG_RETURN_NULL();
927985
}
928986

@@ -931,22 +989,20 @@ spherepoly_deg(PG_FUNCTION_ARGS)
931989
points = (SPoint *) palloc(np * sizeof(SPoint));
932990
if (points == NULL)
933991
{
934-
elog(
935-
ERROR,
936-
"spherepoly_deg: failed for allocate memory for points array"
937-
);
992+
elog(ERROR,
993+
"spherepoly_deg: failed to allocate memory for points array"
994+
);
938995
PG_RETURN_NULL();
939996
}
940997

941998
array_data = (float8 *) ARR_DATA_PTR(float_vector);
942999

9431000
for (i = 0; i < np; i++)
9441001
{
945-
create_spherepoint_from_long_lat(
946-
&points[i],
947-
deg_to_rad(array_data[2 * i]),
948-
deg_to_rad(array_data[2 * i + 1])
949-
);
1002+
create_spherepoint_from_long_lat(&points[i],
1003+
deg_to_rad(array_data[2 * i]),
1004+
deg_to_rad(array_data[2 * i + 1])
1005+
);
9501006
}
9511007
PG_RETURN_POINTER(spherepoly_from_array(points, np));
9521008
}

Diff for: src/polygon.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,14 @@ Datum spherepoly_get_point(PG_FUNCTION_ARGS);
8787
int8 poly_line_pos(const SPOLY *poly, const SLine *line);
8888

8989
/*
90-
* Input of a spherical from sequence of pairconsecutive numbers(lng, lat).
90+
* Input of a spherical from array of pair-consecutive numbers (lng, lat), in radians.
9191
*/
92-
Datum spherepoly_deg(PG_FUNCTION_ARGS);
92+
Datum spherepoly_rad(PG_FUNCTION_ARGS);
93+
94+
/*
95+
* Input of a spherical from array of pair-consecutive numbers (lng, lat), in degrees.
96+
*/
97+
Datum spherepoly_deg(PG_FUNCTION_ARGS);
9398

9499
/*
95100
* Input of a spherical polygon.

Diff for: upgrade_scripts/pg_sphere--1.3.1--1.3.2.sql.in

+17
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,20 @@ $$;
1616
-- remove legacy spellings of operators
1717
DROP OPERATOR IF EXISTS @(bigint, smoc);
1818
DROP OPERATOR IF EXISTS @(spoint, smoc);
19+
20+
-- add spoly function that takes an array of float8 values in radians
21+
CREATE FUNCTION spoly(float8[])
22+
RETURNS spoly
23+
AS 'MODULE_PATHNAME', 'spherepoly_rad'
24+
LANGUAGE 'c'
25+
IMMUTABLE STRICT PARALLEL SAFE;
26+
27+
COMMENT ON FUNCTION spoly(float8[]) IS
28+
'creates spoly from array of numbers in radians';
29+
30+
-- add PARALLEL SAFE to spoly_deg(float8[])
31+
ALTER FUNCTION spoly_deg(float8[]) IMMUTABLE STRICT PARALLEL SAFE;
32+
33+
-- update comment on spoly_deg function
34+
COMMENT ON FUNCTION spoly_deg(float8[]) IS
35+
'creates spoly from array of numbers in degrees';

0 commit comments

Comments
 (0)