Skip to content

Commit

Permalink
[ISSUE postgrespro#22] Created spoint_deg, scircle_deg functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
dura0ok committed Aug 4, 2023
1 parent 612f06b commit 118fe52
Show file tree
Hide file tree
Showing 21 changed files with 271 additions and 20 deletions.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions expected/circle.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@
(1 row)

-- Input/Output ---
SELECT scircle_deg(spoint(10,10), 90);
scircle_deg
------------------------------------------
<(0.57522204 , -0.57522204) , 1.5707963>
(1 row)

SELECT scircle_deg(spoint(10,10), 91);
ERROR: radius must not be greater than 90 degrees or less than 0
SELECT scircle_deg(spoint(0,0), 0);
scircle_deg
---------------
<(0 , 0) , 0>
(1 row)

SELECT scircle_deg(spoint(10,10), -1);
ERROR: radius must not be greater than 90 degrees or less than 0
SELECT set_sphere_output( 'RAD' );
set_sphere_output
-------------------
Expand Down
22 changes: 11 additions & 11 deletions expected/init_test.out.in
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ psql:pg_sphere.test.sql:108: NOTICE: argument type sellipse is only a shell
psql:pg_sphere.test.sql:126: NOTICE: type "spoly" is not yet defined
DETAIL: Creating a shell type definition.
psql:pg_sphere.test.sql:133: NOTICE: argument type spoly is only a shell
psql:pg_sphere.test.sql:152: NOTICE: type "spath" is not yet defined
psql:pg_sphere.test.sql:151: NOTICE: type "spath" is not yet defined
DETAIL: Creating a shell type definition.
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
psql:pg_sphere.test.sql:158: NOTICE: argument type spath is only a shell
psql:pg_sphere.test.sql:177: 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:184: NOTICE: argument type sbox is only a shell
psql:pg_sphere.test.sql:8568: 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:8575: NOTICE: argument type spherekey is only a shell
psql:pg_sphere.test.sql:8589: 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:8596: NOTICE: argument type pointkey is only a shell
psql:pg_sphere.test.sql:8602: NOTICE: argument type pointkey is only a shell
psql:pg_sphere.test.sql:8608: NOTICE: argument type pointkey is only a shell
psql:pg_sphere.test.sql:8614: NOTICE: argument type pointkey is only a shell
4 changes: 2 additions & 2 deletions expected/init_test_healpix.out.in
Original file line number Diff line number Diff line change
@@ -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:9181: NOTICE: return type smoc is only a shell
psql:pg_sphere.test.sql:9187: NOTICE: argument type smoc is only a shell
18 changes: 18 additions & 0 deletions expected/points.out
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,24 @@ SELECT spoint(0.0109083078249646 , -0.000727220521664407);
(0.625d , -0.041666667d)
(1 row)

SELECT spoint_deg(57.2958, 57.2958);
spoint_deg
-----------------------
(57.2958d , 57.2958d)
(1 row)

SELECT spoint_deg(0, 0);
spoint_deg
------------
(0d , 0d)
(1 row)

SELECT spoint_deg(114.5916, 0);
spoint_deg
------------------
(114.5916d , 0d)
(1 row)

SELECT set_sphere_output( 'RAD' );
set_sphere_output
-------------------
Expand Down
22 changes: 22 additions & 0 deletions expected/poly.out
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,33 @@ SELECT spoly '{(10d,0d),(10d,1d),(15d,0d)}';
{(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
---------------------------------
{(1d , 2d),(3d , 4d),(5d , 6d)}
(1 row)

SELECT spoly_deg(ARRAY[10.0, 0.0, 10.0, 1.0, 15.0, 0.0]);
spoly_deg
------------------------------------
{(10d , 0d),(10d , 1d),(15d , 0d)}
(1 row)

-- incorrect input -----
SELECT spoly '{(10d,0d),(10d,1d)}';
ERROR: spherepoly_in: more than two points needed
LINE 1: SELECT spoly '{(10d,0d),(10d,1d)}';
^
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[]::float8[]);
ERROR: spherepoly_deg: invalid number of arguments (must be even and >= 6)
SELECT spoly_deg(NULL::float8[]);
spoly_deg
-----------

(1 row)

--- self-crossing input -----
SELECT spoly '{(0d,0d),(10d,10d),(0d,10d),(10d,0d)}';
ERROR: spherepoly_from_array: a line segment overlaps or polygon too large
Expand Down
8 changes: 8 additions & 0 deletions pgs_circle.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ CREATE FUNCTION scircle(spoint, float8)
COMMENT ON FUNCTION scircle(spoint, float8) IS
'spherical circle with spherical point as center and float8 as radius in radians';

CREATE FUNCTION scircle_deg(spoint, float8)
RETURNS scircle
AS 'MODULE_PATHNAME' , 'spherecircle_by_center_deg'
LANGUAGE 'c'
IMMUTABLE STRICT PARALLEL SAFE;

COMMENT ON FUNCTION scircle_deg(spoint, float8) IS
'spherical circle with spherical point as center and float8 as radius in degrees';

--
-- Casting point as circle
Expand Down
9 changes: 9 additions & 0 deletions pgs_point.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ CREATE FUNCTION spoint(FLOAT8, FLOAT8)
LANGUAGE 'c'
IMMUTABLE STRICT PARALLEL SAFE;

CREATE FUNCTION spoint_deg(FLOAT8, FLOAT8)
RETURNS spoint
AS 'MODULE_PATHNAME', 'spherepoint_from_long_lat_deg'
LANGUAGE 'c'
IMMUTABLE STRICT PARALLEL SAFE;

CREATE FUNCTION set_sphere_output_precision(INT4)
RETURNS CSTRING
AS 'MODULE_PATHNAME', 'set_sphere_output_precision'
Expand All @@ -28,6 +34,9 @@ CREATE FUNCTION set_sphere_output(CSTRING)
COMMENT ON FUNCTION spoint(FLOAT8, FLOAT8) IS
'returns a spherical point from longitude (arg1), latitude (arg2)';

COMMENT ON FUNCTION spoint_deg(FLOAT8, FLOAT8) IS
'returns a spherical point from longitude (arg1, in degrees), latitude (arg2, in degrees)';

CREATE FUNCTION long(spoint)
RETURNS FLOAT8
AS 'MODULE_PATHNAME', 'spherepoint_long'
Expand Down
12 changes: 12 additions & 0 deletions pgs_polygon.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,18 @@ 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
1 change: 0 additions & 1 deletion pgs_types.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ CREATE FUNCTION spoly_out(spoly)
LANGUAGE 'c'
IMMUTABLE STRICT;


CREATE TYPE spoly (
internallength = VARIABLE,
input = spoly_in,
Expand Down
8 changes: 8 additions & 0 deletions sql/circle.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ SET extra_float_digits = 0;

-- Input/Output ---

SELECT scircle_deg(spoint(10,10), 90);

SELECT scircle_deg(spoint(10,10), 91);

SELECT scircle_deg(spoint(0,0), 0);

SELECT scircle_deg(spoint(10,10), -1);

SELECT set_sphere_output( 'RAD' );

SELECT '< (1h 2m 30s , +1d 2m 30s), 1.0d >'::scircle;
Expand Down
6 changes: 6 additions & 0 deletions sql/points.sql
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ SELECT '(0.0109083078249646 , -0.000727220521664407)'::spoint;

SELECT spoint(0.0109083078249646 , -0.000727220521664407);

SELECT spoint_deg(57.2958, 57.2958);

SELECT spoint_deg(0, 0);

SELECT spoint_deg(114.5916, 0);

SELECT set_sphere_output( 'RAD' );

SELECT spoint(7.28318530717958623 , 0.00);
Expand Down
10 changes: 10 additions & 0 deletions sql/poly.sql
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,20 @@ SELECT spoly '{(359d,0d),(359d,1d),(4d,0d)}';

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

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]);

-- incorrect input -----

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

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

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

SELECT spoly_deg(NULL::float8[]);

--- self-crossing input -----

SELECT spoly '{(0d,0d),(10d,10d),(0d,10d),(10d,0d)}';
Expand Down
20 changes: 18 additions & 2 deletions src/circle.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "circle.h"
#include "pgs_util.h"

/* Circle functions */

Expand All @@ -22,6 +23,7 @@ PG_FUNCTION_INFO_V1(spherecircle_center);
PG_FUNCTION_INFO_V1(spherecircle_radius);
PG_FUNCTION_INFO_V1(spherepoint_to_circle);
PG_FUNCTION_INFO_V1(spherecircle_by_center);
PG_FUNCTION_INFO_V1(spherecircle_by_center_deg);
PG_FUNCTION_INFO_V1(spherecircle_area);
PG_FUNCTION_INFO_V1(spherecircle_circ);
PG_FUNCTION_INFO_V1(spheretrans_circle);
Expand Down Expand Up @@ -79,7 +81,7 @@ spherecircle_in(PG_FUNCTION_ARGS)
{
pfree(c);
c = NULL;
elog(ERROR, "spherecircle_in: radius must be not greater than 90 degrees");
elog(ERROR, "spherecircle_in: radius must not be greater than 90 degrees or less than 0");
}
else if (FPeq(c->radius, PIH))
{
Expand Down Expand Up @@ -361,7 +363,7 @@ spherecircle_by_center(PG_FUNCTION_ARGS)

if (FPgt(rad, PIH) || FPlt(rad, 0.0))
{
elog(ERROR, "radius must be not greater than 90 degrees or less than 0");
elog(ERROR, "radius must not be greater than 90 degrees or less than 0");
PG_RETURN_NULL();
}
c = (SCIRCLE *) palloc(sizeof(SCIRCLE));
Expand All @@ -370,6 +372,20 @@ spherecircle_by_center(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(c);
}

Datum
spherecircle_by_center_deg(PG_FUNCTION_ARGS)
{
Datum res;
SPoint *p = (SPoint *) PG_GETARG_POINTER(0);
const float8 rad = deg_to_rad(PG_GETARG_FLOAT8(1));
res = DirectFunctionCall2(
spherecircle_by_center,
PointerGetDatum(p),
Float8GetDatum(rad)
);
PG_RETURN_DATUM(res);
}

Datum
spherecircle_area(PG_FUNCTION_ARGS)
{
Expand Down
5 changes: 5 additions & 0 deletions src/circle.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ Datum spherepoint_to_circle(PG_FUNCTION_ARGS);
*/
Datum spherecircle_by_center(PG_FUNCTION_ARGS);

/*
* Creates a circle from center and radius(in degrees).
*/
Datum spherecircle_by_center_deg(PG_FUNCTION_ARGS);

/*
* Calculates the area of a circle in square radians.
*/
Expand Down
5 changes: 5 additions & 0 deletions src/pgs_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@ conv_theta(double x)
return y;
}

static inline double deg_to_rad(double in)
{
return in * PI / 180;
}

#endif
28 changes: 25 additions & 3 deletions src/point.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include "point.h"
#include "pgs_util.h"

/* This file contains definitions for spherical point functions. */

PG_FUNCTION_INFO_V1(spherepoint_in);
PG_FUNCTION_INFO_V1(spherepoint_from_long_lat);
PG_FUNCTION_INFO_V1(spherepoint_from_long_lat_deg);
PG_FUNCTION_INFO_V1(spherepoint_distance);
PG_FUNCTION_INFO_V1(spherepoint_long);
PG_FUNCTION_INFO_V1(spherepoint_lat);
Expand Down Expand Up @@ -141,18 +143,38 @@ spherepoint_in(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(sp);
}

void create_spherepoint_from_long_lat(SPoint *p, float8 lng, float8 lat)
{
p->lat = lat;
p->lng = lng;
spoint_check(p);
}

Datum
spherepoint_from_long_lat(PG_FUNCTION_ARGS)
{
SPoint *p = (SPoint *) palloc(sizeof(SPoint));

p->lng = PG_GETARG_FLOAT8(0);
p->lat = PG_GETARG_FLOAT8(1);
spoint_check(p);
const float8 lng = PG_GETARG_FLOAT8(0);
const float8 lat = PG_GETARG_FLOAT8(1);
create_spherepoint_from_long_lat(p, lng, lat);
PG_RETURN_POINTER(p);
}

Datum
spherepoint_from_long_lat_deg(PG_FUNCTION_ARGS)
{
Datum res;
const float8 lng = deg_to_rad(PG_GETARG_FLOAT8(0));
const float8 lat = deg_to_rad(PG_GETARG_FLOAT8(1));
res = DirectFunctionCall2(
spherepoint_from_long_lat,
Float8GetDatum(lng),
Float8GetDatum(lat)
);
PG_RETURN_DATUM(res);
}

static double
norm2(double a, double b)
{
Expand Down
Loading

0 comments on commit 118fe52

Please sign in to comment.