Skip to content

Commit d201938

Browse files
committed
Added calculation of the distance between a line and a point
1 parent 5228df6 commit d201938

File tree

9 files changed

+238
-42
lines changed

9 files changed

+238
-42
lines changed

Diff for: doc/operators.sgm

+13-1
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,8 @@
331331
a non-boolean operator returning the distance between two
332332
objects in radians. Currently,
333333
<application>pgSphere</application> supports only distances
334-
between points, circles, and between point and circle. If the
334+
between points, circles, between point and circle, and
335+
between point and line. If the
335336
objects are overlapping, the distance operator returns zero
336337
(0.0).
337338
</para>
@@ -343,6 +344,17 @@
343344
<![CDATA[ dist]]>
344345
<![CDATA[------]]>
345346
<![CDATA[ 16]]>
347+
<![CDATA[(1 row)]]>
348+
</programlisting>
349+
</example>
350+
<example>
351+
<title>Distance between point and line</title>
352+
<programlisting>
353+
<![CDATA[sql> SELECT 180 * (sline '( 0d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )')]]>
354+
<![CDATA[ / pi() AS dist ;]]>
355+
<![CDATA[ dist]]>
356+
<![CDATA[------]]>
357+
<![CDATA[ 90]]>
346358
<![CDATA[(1 row)]]>
347359
</programlisting>
348360
</example>

Diff for: expected/init_test.out.in

+9-7
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ psql:pg_sphere.test.sql:158: NOTICE: argument type spath is only a shell
2424
psql:pg_sphere.test.sql:177: NOTICE: type "sbox" is not yet defined
2525
DETAIL: Creating a shell type definition.
2626
psql:pg_sphere.test.sql:184: NOTICE: argument type sbox is only a shell
27-
psql:pg_sphere.test.sql:8594: NOTICE: type "spherekey" is not yet defined
27+
psql:pg_sphere.test.sql:8644: NOTICE: type "spherekey" is not yet defined
2828
DETAIL: Creating a shell type definition.
29-
psql:pg_sphere.test.sql:8601: NOTICE: argument type spherekey is only a shell
30-
psql:pg_sphere.test.sql:8615: NOTICE: type "pointkey" is not yet defined
29+
psql:pg_sphere.test.sql:8651: NOTICE: argument type spherekey is only a shell
30+
psql:pg_sphere.test.sql:8665: NOTICE: type "pointkey" is not yet defined
3131
DETAIL: Creating a shell type definition.
32-
psql:pg_sphere.test.sql:8622: NOTICE: argument type pointkey is only a shell
33-
psql:pg_sphere.test.sql:8628: NOTICE: argument type pointkey is only a shell
34-
psql:pg_sphere.test.sql:8634: NOTICE: argument type pointkey is only a shell
35-
psql:pg_sphere.test.sql:8640: NOTICE: argument type pointkey is only a shell
32+
psql:pg_sphere.test.sql:8672: NOTICE: argument type pointkey is only a shell
33+
psql:pg_sphere.test.sql:8678: NOTICE: argument type pointkey is only a shell
34+
psql:pg_sphere.test.sql:8684: NOTICE: argument type pointkey is only a shell
35+
psql:pg_sphere.test.sql:8690: NOTICE: argument type pointkey is only a shell
36+
psql:pg_sphere.test.sql:9257: NOTICE: return type smoc is only a shell
37+
psql:pg_sphere.test.sql:9263: NOTICE: argument type smoc is only a shell

Diff for: expected/init_test_healpix.out.in

-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +0,0 @@
1-
psql:pg_sphere.test.sql:9207: NOTICE: return type smoc is only a shell
2-
psql:pg_sphere.test.sql:9213: NOTICE: argument type smoc is only a shell

Diff for: expected/line.out

+33-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
SET 8
55
(1 row)
66

7+
SET extra_float_digits TO -3;
78
-- checking spherical line operators
89
SELECT sline ( spoint '(0, 90d)', spoint '(0, -89d)' ) =
910
sline ( spoint '(0, 90d)', spoint '(0, -89d)' ) ;
@@ -134,4 +135,35 @@ SELECT sline ( spoint '(0, 0d)', spoint '(0.000001d, 0d)' ) #
134135
f
135136
(1 row)
136137

137-
138+
-- checking the distance between a line and a point
139+
SELECT sline '( 90d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )';
140+
?column?
141+
----------------
142+
0.872664625997
143+
(1 row)
144+
145+
SELECT sline '( 90d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )' =
146+
spoint '( 0d, 90d )' <-> sline '( 90d, 0d, 0d, XYZ ), 40d ';
147+
?column?
148+
----------
149+
t
150+
(1 row)
151+
152+
SELECT sline '( 0d, 0d, 0d, XYZ ), 0d ' <-> spoint '( 0d, 90d )';
153+
?column?
154+
---------------
155+
1.57079632679
156+
(1 row)
157+
158+
SELECT sline '( 0d, 0d, 0d, XYZ ), 0d ' <-> spoint '( 0d, 0d )';
159+
?column?
160+
----------
161+
0
162+
(1 row)
163+
164+
SELECT sline '( 0d, 0d, 0d, XYZ ), 30d ' <-> spoint '( 0d, 30d )';
165+
?column?
166+
----------------
167+
0.523598775598
168+
(1 row)
169+

Diff for: pgs_line.sql.in

+50
Original file line numberDiff line numberDiff line change
@@ -593,3 +593,53 @@ COMMENT ON FUNCTION scircle_contains_line_com_neg(sline, scircle) IS
593593
'returns true if spherical circle does not contain spherical line';
594594

595595

596+
--
597+
-- distance between line and point
598+
--
599+
600+
CREATE FUNCTION dist(sline, spoint)
601+
RETURNS FLOAT8
602+
AS 'MODULE_PATHNAME', 'sphereline_point_distance'
603+
LANGUAGE 'c'
604+
IMMUTABLE STRICT;
605+
606+
COMMENT ON FUNCTION dist(sline, spoint) IS
607+
'returns the distance between spherical line and spherical point';
608+
609+
610+
CREATE OPERATOR <-> (
611+
LEFTARG = sline,
612+
RIGHTARG = spoint,
613+
COMMUTATOR = '<->',
614+
PROCEDURE = dist
615+
);
616+
617+
COMMENT ON OPERATOR <-> (sline, spoint) IS
618+
'returns the distance between spherical line and spherical point';
619+
620+
621+
622+
--
623+
-- distance between point and line
624+
--
625+
626+
CREATE FUNCTION dist(spoint, sline)
627+
RETURNS FLOAT8
628+
AS 'MODULE_PATHNAME', 'sphereline_point_distance_com'
629+
LANGUAGE 'c'
630+
IMMUTABLE STRICT;
631+
632+
COMMENT ON FUNCTION dist(spoint, sline) IS
633+
'returns the distance between spherical line and spherical point';
634+
635+
636+
CREATE OPERATOR <-> (
637+
LEFTARG = spoint,
638+
RIGHTARG = sline,
639+
COMMUTATOR = '<->',
640+
PROCEDURE = dist
641+
);
642+
643+
COMMENT ON OPERATOR <-> (spoint, sline) IS
644+
'returns the distance between spherical line and spherical point';
645+

Diff for: sql/line.sql

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
\set ECHO none
22
SELECT set_sphere_output_precision(8);
33
\set ECHO all
4+
SET extra_float_digits TO -3;
45

56
-- checking spherical line operators
67

@@ -66,4 +67,18 @@ SELECT sline ( spoint '(0, 0d)', spoint '(0.000001d, 0d)' ) #
6667

6768
SELECT sline ( spoint '(0, 0d)', spoint '(0.000001d, 0d)' ) #
6869
sline ( spoint '(0.000001d, 0d)', spoint '(0.000001d, 0.0000005d)' ) ;
69-
70+
71+
72+
-- checking the distance between a line and a point
73+
74+
75+
SELECT sline '( 90d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )';
76+
77+
SELECT sline '( 90d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )' =
78+
spoint '( 0d, 90d )' <-> sline '( 90d, 0d, 0d, XYZ ), 40d ';
79+
80+
SELECT sline '( 0d, 0d, 0d, XYZ ), 0d ' <-> spoint '( 0d, 90d )';
81+
82+
SELECT sline '( 0d, 0d, 0d, XYZ ), 0d ' <-> spoint '( 0d, 0d )';
83+
84+
SELECT sline '( 0d, 0d, 0d, XYZ ), 30d ' <-> spoint '( 0d, 30d )';

Diff for: src/line.c

+72
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ PG_FUNCTION_INFO_V1(sphereline_overlap_neg);
3333
PG_FUNCTION_INFO_V1(spheretrans_from_line);
3434
PG_FUNCTION_INFO_V1(spheretrans_line);
3535
PG_FUNCTION_INFO_V1(spheretrans_line_inverse);
36+
PG_FUNCTION_INFO_V1(sphereline_point_distance);
37+
PG_FUNCTION_INFO_V1(sphereline_point_distance_com);
3638

3739
/*
3840
* Swaps the beginning and ending of the line.
@@ -642,6 +644,59 @@ sline_center(SPoint *c, const SLine *sl)
642644
euler_spoint_trans(c, &p, &se);
643645
}
644646

647+
float8 sline_point_dist(const SLine *sl, const SPoint *p)
648+
{
649+
Vector3D v_beg;
650+
Vector3D v_end;
651+
Vector3D v;
652+
Vector3D normal1;
653+
Vector3D normal2;
654+
Vector3D line;
655+
Vector3D first_p;
656+
float8 norma;
657+
SPoint fp;
658+
SPoint sp;
659+
float8 fpdist;
660+
float8 spdist;
661+
662+
if (spoint_at_sline(p, sl))
663+
{
664+
return 0.0;
665+
}
666+
667+
sline_vector_begin(&v_beg, sl);
668+
sline_vector_end(&v_end, sl);
669+
spoint_vector3d(&v, p);
670+
671+
/* normal1 to the plane passing through the line and the center of the sphere */
672+
vector3d_cross(&normal1, &v_beg, &v_end);
673+
if (vector3d_eq(&normal1, &v))
674+
{
675+
return PIH;
676+
}
677+
678+
/* normal2 to the plane perpendicular to the given line. */
679+
vector3d_cross(&normal2, &normal1, &v);
680+
vector3d_cross(&line, &normal2, &normal1);
681+
norma = sqrt(line.x * line.x + line.y * line.y + line.z * line.z);
682+
683+
first_p.x = line.x / norma;
684+
first_p.y = line.y / norma;
685+
first_p.z = line.z / norma;
686+
vector3d_spoint(&fp, &first_p);
687+
688+
if (spoint_at_sline(&fp, sl))
689+
{
690+
return spoint_dist(&fp, p);
691+
}
692+
693+
vector3d_spoint(&fp, &v_beg);
694+
vector3d_spoint(&sp, &v_end);
695+
fpdist = spoint_dist(p, &fp);
696+
spdist = spoint_dist(p, &sp);
697+
return Min(fpdist, spdist);
698+
}
699+
645700
Datum
646701
sphereline_in(PG_FUNCTION_ARGS)
647702
{
@@ -1051,3 +1106,20 @@ spheretrans_from_line(PG_FUNCTION_ARGS)
10511106
sphereline_to_euler(e, l);
10521107
PG_RETURN_POINTER(e);
10531108
}
1109+
1110+
Datum
1111+
sphereline_point_distance(PG_FUNCTION_ARGS)
1112+
{
1113+
const SLine *s = (SLine *) PG_GETARG_POINTER(0);
1114+
const SPoint *p = (SPoint *) PG_GETARG_POINTER(1);
1115+
PG_RETURN_FLOAT8(sline_point_dist(s, p));
1116+
}
1117+
1118+
Datum
1119+
sphereline_point_distance_com(PG_FUNCTION_ARGS)
1120+
{
1121+
const SPoint *p = (SPoint *) PG_GETARG_POINTER(0);
1122+
const SLine *s = (SLine *) PG_GETARG_POINTER(1);
1123+
PG_RETURN_FLOAT8(sline_point_dist(s, p));
1124+
}
1125+

Diff for: src/line.h

+15
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ void euler_sline_trans(SLine *out, const SLine *in, const SEuler *se);
129129
*/
130130
void sline_center(SPoint *c, const SLine *sl);
131131

132+
/*
133+
* Calculates the distance between a line 'sl' and a point 'p'
134+
*/
135+
float8 sline_point_dist(const SLine *sl, const SPoint *p);
136+
132137
/*
133138
* The input function for spherical line.
134139
*/
@@ -290,4 +295,14 @@ Datum spheretrans_line(PG_FUNCTION_ARGS);
290295
*/
291296
Datum spheretrans_line_inverse(PG_FUNCTION_ARGS);
292297

298+
/*
299+
* Returns the distance between a line and a point.
300+
*/
301+
Datum sphereline_point_distance(PG_FUNCTION_ARGS);
302+
303+
/*
304+
* Returns the distance between a point and a line.
305+
*/
306+
Datum sphereline_point_distance_com(PG_FUNCTION_ARGS);
307+
293308
#endif

0 commit comments

Comments
 (0)