Skip to content

Commit 1fc4378

Browse files
author
stepan-neretin7
committed
Implemeted SQL function centroid() that calculates the gravity center of spoint's array.
1 parent 612f06b commit 1fc4378

12 files changed

+309
-13
lines changed

Diff for: Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ DATA_built = $(RELEASE_SQL) \
3131

3232
DOCS = README.pg_sphere COPYRIGHT.pg_sphere
3333
REGRESS = init tables points euler circle line ellipse poly path box index \
34-
contains_ops contains_ops_compat bounding_box_gist gnomo epochprop
34+
contains_ops contains_ops_compat bounding_box_gist gnomo epochprop \
35+
spherepoint_array_center
3536

3637
ifneq ($(USE_HEALPIX),0)
3738
REGRESS += healpix moc mocautocast

Diff for: doc/functions.sgm

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@
143143
</sect3>
144144

145145
</sect2>
146-
146+
147147
<sect2 id="funcs.strans">
148148
<title>
149149
<type>strans</type> functions

Diff for: doc/operators.sgm

+71-2
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,10 @@
393393
The center operator <literal>@@</literal> is a non-boolean
394394
unary operator returning the center of an object. In the
395395
current implementation of <application>pgSphere</application>,
396-
only centers of circles and ellipses are supported. Instead
397-
of using the operator, you can use the function
396+
only centers of circles, ellipses, points, arrays of points are
397+
</para>
398+
<para>
399+
supported. Instead of using the operator, you can use the function
398400
<literal>center(object)</literal>.
399401
</para>
400402
<example>
@@ -403,6 +405,73 @@
403405
<![CDATA[sql> SELECT @@ scircle '<(0d,20d),30d>';]]>
404406
</programlisting>
405407
</example>
408+
<example>
409+
<title>Center array of points</title>
410+
<programlisting>
411+
<![CDATA[sql> SELECT @@ ARRAY[
412+
spoint(40.7128, -74.0060),
413+
spoint(34.0522, -118.2437),
414+
spoint(37.7749, -122.4194)
415+
] AS center;]]>
416+
<![CDATA[ center ]]>
417+
<![CDATA[----------------------------------------]]>
418+
<![CDATA[ (3.04366980631979 , 0.858938068921891)]]>
419+
<![CDATA[(1 row)]]>
420+
</programlisting>
421+
</example>
422+
423+
<example>
424+
<title>Center of a spoint</title>
425+
<para>
426+
For the completeness of the interface, the function returns the point itself
427+
</para>
428+
<programlisting>
429+
<![CDATA[sql> select @@ spoint(0,0) AS spoint;]]>
430+
<![CDATA[ spoint ]]>
431+
<![CDATA[---------]]>
432+
<![CDATA[ (0 , 0) ]]>
433+
<![CDATA[(1 row)]]>
434+
</programlisting>
435+
</example>
436+
437+
<example>
438+
<title>Basic example array of points</title>
439+
<programlisting>
440+
<![CDATA[sql> SELECT center(ARRAY[
441+
spoint(40.7128, -74.0060),
442+
spoint(34.0522, -118.2437),
443+
spoint(37.7749, -122.4194)
444+
]);]]>
445+
<![CDATA[ center ]]>
446+
<![CDATA[----------------------------------------]]>
447+
<![CDATA[ (3.04366980631979 , 0.858938068921891)]]>
448+
<![CDATA[ (1 row) ]]>
449+
</programlisting>
450+
</example>
451+
452+
<example>
453+
<title>Behavior with empty array of points</title>
454+
<programlisting>
455+
<![CDATA[sql> SELECT center('{}');]]>
456+
<![CDATA[ center ]]>
457+
<![CDATA[ ----------------------------- ]]>
458+
459+
<![CDATA[ (1 row) ]]>
460+
</programlisting>
461+
</example>
462+
<example>
463+
<title>Example with opposite array points(poles)</title>
464+
<programlisting>
465+
<![CDATA[sql> SELECT center(ARRAY[
466+
spoint(0, 10),
467+
spoint(0, -10),
468+
]);]]>
469+
<![CDATA[ center ]]>
470+
<![CDATA[----------------------------------------]]>
471+
<![CDATA[ (0, 0) ]]>
472+
<![CDATA[ (1 row) ]]>
473+
</programlisting>
474+
</example>
406475
</sect2>
407476

408477
<sect2 id="op.direction">

Diff for: expected/init_test.out.in

+7-7
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ psql:pg_sphere.test.sql:159: NOTICE: argument type spath is only a shell
2424
psql:pg_sphere.test.sql:178: NOTICE: type "sbox" is not yet defined
2525
DETAIL: Creating a shell type definition.
2626
psql:pg_sphere.test.sql:185: NOTICE: argument type sbox is only a shell
27-
psql:pg_sphere.test.sql:8540: NOTICE: type "spherekey" is not yet defined
27+
psql:pg_sphere.test.sql:8570: NOTICE: type "spherekey" is not yet defined
2828
DETAIL: Creating a shell type definition.
29-
psql:pg_sphere.test.sql:8547: NOTICE: argument type spherekey is only a shell
30-
psql:pg_sphere.test.sql:8561: NOTICE: type "pointkey" is not yet defined
29+
psql:pg_sphere.test.sql:8577: NOTICE: argument type spherekey is only a shell
30+
psql:pg_sphere.test.sql:8591: NOTICE: type "pointkey" is not yet defined
3131
DETAIL: Creating a shell type definition.
32-
psql:pg_sphere.test.sql:8568: NOTICE: argument type pointkey is only a shell
33-
psql:pg_sphere.test.sql:8574: NOTICE: argument type pointkey is only a shell
34-
psql:pg_sphere.test.sql:8580: NOTICE: argument type pointkey is only a shell
35-
psql:pg_sphere.test.sql:8586: NOTICE: argument type pointkey is only a shell
32+
psql:pg_sphere.test.sql:8598: NOTICE: argument type pointkey is only a shell
33+
psql:pg_sphere.test.sql:8604: NOTICE: argument type pointkey is only a shell
34+
psql:pg_sphere.test.sql:8610: NOTICE: argument type pointkey is only a shell
35+
psql:pg_sphere.test.sql:8616: NOTICE: argument type pointkey is only a shell

Diff for: expected/init_test_healpix.out.in

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
psql:pg_sphere.test.sql:9153: NOTICE: return type smoc is only a shell
2-
psql:pg_sphere.test.sql:9159: NOTICE: argument type smoc is only a shell
1+
psql:pg_sphere.test.sql:9183: NOTICE: return type smoc is only a shell
2+
psql:pg_sphere.test.sql:9189: NOTICE: argument type smoc is only a shell

Diff for: expected/points.out

+7
Original file line numberDiff line numberDiff line change
@@ -648,3 +648,10 @@ SELECT '( 0h 2m 30s , -90d 0m 0s)'::spoint<->'( 12h 2m 30s , -90d 0m 0s)'::spoin
648648
0
649649
(1 row)
650650

651+
-- Center operator -------------------
652+
select @@ spoint(0,0) AS spoint;
653+
spoint
654+
---------
655+
(0 , 0)
656+
(1 row)
657+

Diff for: expected/spherepoint_array_center.out

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
SELECT center(ARRAY[
2+
spoint(40.7128, -74.0060),
3+
spoint(34.0522, -118.2437),
4+
spoint(37.7749, -122.4194)
5+
]);
6+
center
7+
----------------------------------------
8+
(3.04366980631979 , 0.858938068921891)
9+
(1 row)
10+
11+
SELECT center('{}'::SPoint[]);
12+
center
13+
--------
14+
15+
(1 row)
16+
17+
CREATE FUNCTION spoint_from_xyz(FLOAT8, FLOAT8, FLOAT8)
18+
RETURNS spoint
19+
AS 'pg_sphere', 'spoint_from_xyz'
20+
LANGUAGE 'c'
21+
IMMUTABLE STRICT PARALLEL SAFE;
22+
SELECT spoint_from_xyz(1, 0, 0);
23+
spoint_from_xyz
24+
-----------------
25+
(0 , 0)
26+
(1 row)
27+
28+
SELECT spoint_from_xyz(0, 0, 0);
29+
spoint_from_xyz
30+
-----------------
31+
(0 , 0)
32+
(1 row)
33+
34+
SELECT center(ARRAY[
35+
spoint_from_xyz(1, 0, 0),
36+
spoint_from_xyz(-1, 0, 0)
37+
]);
38+
center
39+
-----------------------
40+
(1.5707963267949 , 0)
41+
(1 row)
42+
43+
SELECT center(NULL::SPoint[]);
44+
center
45+
--------
46+
47+
(1 row)
48+
49+
SELECT @@ ARRAY[
50+
spoint(40.7128, -74.0060),
51+
spoint(34.0522, -118.2437),
52+
spoint(37.7749, -122.4194)
53+
] AS center;
54+
center
55+
----------------------------------------
56+
(3.04366980631979 , 0.858938068921891)
57+
(1 row)
58+
59+
SELECT @@ ARRAY[]::spoint[] AS center;
60+
center
61+
--------
62+
63+
(1 row)
64+
65+
SELECT @@ ARRAY[
66+
spoint_from_xyz(1, 0, 0),
67+
spoint_from_xyz(-1, 0, 0)
68+
] AS center;
69+
center
70+
-----------------------
71+
(1.5707963267949 , 0)
72+
(1 row)
73+

Diff for: pgs_point.sql.in

+30
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,33 @@ CREATE OPERATOR <-> (
167167
COMMENT ON OPERATOR <-> (spoint, spoint) IS
168168
'distance between spherical points';
169169

170+
CREATE FUNCTION center(dots_vector SPoint[])
171+
RETURNS spoint
172+
AS 'MODULE_PATHNAME', 'center'
173+
LANGUAGE 'c'
174+
IMMUTABLE STRICT PARALLEL SAFE;
175+
176+
CREATE OPERATOR @@ (
177+
RIGHTARG = SPoint[],
178+
PROCEDURE = center
179+
);
180+
181+
COMMENT ON OPERATOR @@ (NONE , SPoint[]) IS
182+
'Return gravity center from array of spherical points';
183+
184+
CREATE FUNCTION center(spoint)
185+
RETURNS spoint
186+
AS 'MODULE_PATHNAME', 'spherepoint_center'
187+
LANGUAGE 'c'
188+
IMMUTABLE STRICT PARALLEL SAFE;
189+
190+
COMMENT ON FUNCTION center(spoint) IS
191+
'For the correctness of the interface, the function returns the spoint itself';
192+
193+
CREATE OPERATOR @@ (
194+
RIGHTARG = SPoint,
195+
PROCEDURE = center
196+
);
197+
198+
COMMENT ON OPERATOR @@ (NONE , SPoint) IS
199+
'For the correctness of the interface, the function returns the spoint itself';

Diff for: sql/points.sql

+2
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,5 @@ SELECT '( 0h 2m 30s , 90d 0m 0s)'::spoint<->'( 12h 2m 30s , 90d 0m 0s)'::spoint;
234234

235235
SELECT '( 0h 2m 30s , -90d 0m 0s)'::spoint<->'( 12h 2m 30s , -90d 0m 0s)'::spoint;
236236

237+
-- Center operator -------------------
238+
select @@ spoint(0,0) AS spoint;

Diff for: sql/spherepoint_array_center.sql

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
SELECT center(ARRAY[
2+
spoint(40.7128, -74.0060),
3+
spoint(34.0522, -118.2437),
4+
spoint(37.7749, -122.4194)
5+
]);
6+
7+
SELECT center('{}'::SPoint[]);
8+
9+
CREATE FUNCTION spoint_from_xyz(FLOAT8, FLOAT8, FLOAT8)
10+
RETURNS spoint
11+
AS 'pg_sphere', 'spoint_from_xyz'
12+
LANGUAGE 'c'
13+
IMMUTABLE STRICT PARALLEL SAFE;
14+
15+
SELECT spoint_from_xyz(1, 0, 0);
16+
17+
SELECT spoint_from_xyz(0, 0, 0);
18+
19+
SELECT center(ARRAY[
20+
spoint_from_xyz(1, 0, 0),
21+
spoint_from_xyz(-1, 0, 0)
22+
]);
23+
24+
SELECT center(NULL::SPoint[]);
25+
26+
SELECT @@ ARRAY[
27+
spoint(40.7128, -74.0060),
28+
spoint(34.0522, -118.2437),
29+
spoint(37.7749, -122.4194)
30+
] AS center;
31+
32+
SELECT @@ ARRAY[]::spoint[] AS center;
33+
34+
SELECT @@ ARRAY[
35+
spoint_from_xyz(1, 0, 0),
36+
spoint_from_xyz(-1, 0, 0)
37+
] AS center;

Diff for: src/point.c

+67
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
PG_FUNCTION_INFO_V1(spherepoint_in);
66
PG_FUNCTION_INFO_V1(spherepoint_from_long_lat);
77
PG_FUNCTION_INFO_V1(spherepoint_distance);
8+
PG_FUNCTION_INFO_V1(spherepoint_center);
89
PG_FUNCTION_INFO_V1(spherepoint_long);
910
PG_FUNCTION_INFO_V1(spherepoint_lat);
1011
PG_FUNCTION_INFO_V1(spherepoint_x);
1112
PG_FUNCTION_INFO_V1(spherepoint_y);
1213
PG_FUNCTION_INFO_V1(spherepoint_z);
1314
PG_FUNCTION_INFO_V1(spherepoint_xyz);
1415
PG_FUNCTION_INFO_V1(spherepoint_equal);
16+
PG_FUNCTION_INFO_V1(spoint_from_xyz);
17+
PG_FUNCTION_INFO_V1(center);
18+
1519

1620
bool
1721
spoint_eq(const SPoint *p1, const SPoint *p2)
@@ -179,6 +183,13 @@ spoint_dist(const SPoint *p1, const SPoint *p2)
179183
}
180184
}
181185

186+
Datum
187+
spherepoint_center(PG_FUNCTION_ARGS)
188+
{
189+
SPoint *p = (SPoint *) PG_GETARG_POINTER(0);
190+
PG_RETURN_POINTER(p);
191+
}
192+
182193
Datum
183194
spherepoint_distance(PG_FUNCTION_ARGS)
184195
{
@@ -263,3 +274,59 @@ spherepoint_equal(PG_FUNCTION_ARGS)
263274

264275
PG_RETURN_BOOL(spoint_eq(p1, p2));
265276
}
277+
278+
Datum spoint_from_xyz(PG_FUNCTION_ARGS)
279+
{
280+
Vector3D point_coords;
281+
SPoint *p = (SPoint *) palloc(sizeof(SPoint));
282+
283+
point_coords.x = PG_GETARG_FLOAT8(0);
284+
point_coords.y = PG_GETARG_FLOAT8(1);
285+
point_coords.z = PG_GETARG_FLOAT8(2);
286+
vector3d_spoint(p, &point_coords);
287+
288+
if (p == NULL)
289+
{
290+
PG_RETURN_NULL();
291+
}
292+
293+
spoint_check(p);
294+
PG_RETURN_POINTER(p);
295+
}
296+
297+
Datum center(PG_FUNCTION_ARGS)
298+
{
299+
int num_elements, i;
300+
SPoint * p = (SPoint *) palloc(sizeof(SPoint));
301+
SPoint * array_data;
302+
Vector3D v;
303+
Vector3D point_coords = {0,0,0};
304+
ArrayType *dots_vector;
305+
306+
dots_vector = PG_GETARG_ARRAYTYPE_P(0);
307+
num_elements = ArrayGetNItems(ARR_NDIM(dots_vector), ARR_DIMS(dots_vector));
308+
if (num_elements <= 0)
309+
{
310+
PG_RETURN_NULL();
311+
}
312+
313+
array_data = (SPoint *) ARR_DATA_PTR(dots_vector);
314+
315+
for (i = 0; i < num_elements; i++)
316+
{
317+
spoint_vector3d(&v, &array_data[i]);
318+
point_coords.x += v.x;
319+
point_coords.y += v.y;
320+
point_coords.z += v.z;
321+
}
322+
323+
point_coords.x /= num_elements;
324+
point_coords.y /= num_elements;
325+
point_coords.z /= num_elements;
326+
327+
vector3d_spoint(p, &point_coords);
328+
329+
spoint_check(p);
330+
331+
PG_RETURN_POINTER(p);
332+
}

0 commit comments

Comments
 (0)