Skip to content

Commit 1364bd7

Browse files
committed
Added calculation of the distance between a line and a point
1 parent 612f06b commit 1364bd7

File tree

8 files changed

+206
-12
lines changed

8 files changed

+206
-12
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

+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:8590: 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:8597: NOTICE: argument type spherekey is only a shell
30+
psql:pg_sphere.test.sql:8611: 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:8618: NOTICE: argument type pointkey is only a shell
33+
psql:pg_sphere.test.sql:8624: NOTICE: argument type pointkey is only a shell
34+
psql:pg_sphere.test.sql:8630: NOTICE: argument type pointkey is only a shell
35+
psql:pg_sphere.test.sql:8636: 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:9203: NOTICE: return type smoc is only a shell
2+
psql:pg_sphere.test.sql:9209: NOTICE: argument type smoc is only a shell

Diff for: expected/line.out

+32-1
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,35 @@ SELECT sline ( spoint '(0, 0d)', spoint '(0.000001d, 0d)' ) #
134134
f
135135
(1 row)
136136

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

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

+15-1
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,18 @@ SELECT sline ( spoint '(0, 0d)', spoint '(0.000001d, 0d)' ) #
6666

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

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+
660+
if (spoint_at_sline(p, sl))
661+
{
662+
return 0.0;
663+
}
664+
665+
sline_vector_begin(&v_beg, sl);
666+
sline_vector_end(&v_end, sl);
667+
spoint_vector3d(&v, p);
668+
669+
/* normal1 to the plane passing through the line and the center of the sphere */
670+
vector3d_cross(&normal1, &v_beg, &v_end);
671+
if (vector3d_eq(&normal1, &v))
672+
{
673+
return PIH;
674+
}
675+
676+
/* normal2 to the plane perpendicular to the given line. */
677+
vector3d_cross(&normal2, &normal1, &v);
678+
vector3d_cross(&line, &normal2, &normal1);
679+
norma = sqrt(line.x * line.x + line.y * line.y + line.z * line.z);
680+
681+
first_p.x = line.x / norma;
682+
first_p.y = line.y / norma;
683+
first_p.z = line.z / norma;
684+
vector3d_spoint(&fp, &first_p);
685+
686+
if (spoint_at_sline(&fp, sl))
687+
{
688+
return spoint_dist(&fp, p);
689+
}
690+
691+
vector3d_spoint(&fp, &v_beg);
692+
vector3d_spoint(&sp, &v_end);
693+
if (FPle(spoint_dist(p, &fp), spoint_dist(p, &sp)))
694+
{
695+
return spoint_dist(p, &fp);
696+
}
697+
return spoint_dist(p, &sp);
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+
SLine *s = (SLine *) PG_GETARG_POINTER(0);
1114+
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+
SPoint *p = (SPoint *) PG_GETARG_POINTER(0);
1122+
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)