diff --git a/doc/operators.sgm b/doc/operators.sgm
index 7162a01..73ebb83 100644
--- a/doc/operators.sgm
+++ b/doc/operators.sgm
@@ -331,7 +331,8 @@
a non-boolean operator returning the distance between two
objects in radians. Currently,
pgSphere supports only distances
- between points, circles, and between point and circle. If the
+ between points, circles, between point and circle, and
+ between point and line. If the
objects are overlapping, the distance operator returns zero
(0.0).
@@ -343,6 +344,17 @@
+
+
+
+
+ Distance between point and line
+
+ SELECT 180 * (sline '( 0d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )')]]>
+
+
+
+
diff --git a/expected/init_test.out.in b/expected/init_test.out.in
index 1276622..b5ace10 100644
--- a/expected/init_test.out.in
+++ b/expected/init_test.out.in
@@ -24,12 +24,12 @@ 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:184: NOTICE: argument type sbox is only a shell
-psql:pg_sphere.test.sql:8594: NOTICE: type "spherekey" is not yet defined
+psql:pg_sphere.test.sql:8644: NOTICE: type "spherekey" is not yet defined
DETAIL: Creating a shell type definition.
-psql:pg_sphere.test.sql:8601: NOTICE: argument type spherekey is only a shell
-psql:pg_sphere.test.sql:8615: NOTICE: type "pointkey" is not yet defined
+psql:pg_sphere.test.sql:8651: NOTICE: argument type spherekey is only a shell
+psql:pg_sphere.test.sql:8665: NOTICE: type "pointkey" is not yet defined
DETAIL: Creating a shell type definition.
-psql:pg_sphere.test.sql:8622: NOTICE: argument type pointkey is only a shell
-psql:pg_sphere.test.sql:8628: NOTICE: argument type pointkey is only a shell
-psql:pg_sphere.test.sql:8634: NOTICE: argument type pointkey is only a shell
-psql:pg_sphere.test.sql:8640: NOTICE: argument type pointkey is only a shell
+psql:pg_sphere.test.sql:8672: NOTICE: argument type pointkey is only a shell
+psql:pg_sphere.test.sql:8678: NOTICE: argument type pointkey is only a shell
+psql:pg_sphere.test.sql:8684: NOTICE: argument type pointkey is only a shell
+psql:pg_sphere.test.sql:8690: NOTICE: argument type pointkey is only a shell
diff --git a/expected/init_test_healpix.out.in b/expected/init_test_healpix.out.in
index 147d4f9..3b0cfbd 100644
--- a/expected/init_test_healpix.out.in
+++ b/expected/init_test_healpix.out.in
@@ -1,2 +1,2 @@
-psql:pg_sphere.test.sql:9207: NOTICE: return type smoc is only a shell
-psql:pg_sphere.test.sql:9213: NOTICE: argument type smoc is only a shell
+psql:pg_sphere.test.sql:9257: NOTICE: return type smoc is only a shell
+psql:pg_sphere.test.sql:9263: NOTICE: argument type smoc is only a shell
diff --git a/expected/line.out b/expected/line.out
index b05286b..eb4d2ac 100644
--- a/expected/line.out
+++ b/expected/line.out
@@ -4,6 +4,7 @@
SET 8
(1 row)
+SET extra_float_digits TO -3;
-- checking spherical line operators
SELECT sline ( spoint '(0, 90d)', spoint '(0, -89d)' ) =
sline ( spoint '(0, 90d)', spoint '(0, -89d)' ) ;
@@ -134,4 +135,35 @@ SELECT sline ( spoint '(0, 0d)', spoint '(0.000001d, 0d)' ) #
f
(1 row)
-
+-- checking the distance between a line and a point
+SELECT sline '( 90d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )';
+ ?column?
+----------------
+ 0.872664625997
+(1 row)
+
+SELECT sline '( 90d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )' =
+ spoint '( 0d, 90d )' <-> sline '( 90d, 0d, 0d, XYZ ), 40d ';
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT sline '( 0d, 0d, 0d, XYZ ), 0d ' <-> spoint '( 0d, 90d )';
+ ?column?
+---------------
+ 1.57079632679
+(1 row)
+
+SELECT sline '( 0d, 0d, 0d, XYZ ), 0d ' <-> spoint '( 0d, 0d )';
+ ?column?
+----------
+ 0
+(1 row)
+
+SELECT sline '( 0d, 0d, 0d, XYZ ), 30d ' <-> spoint '( 0d, 30d )';
+ ?column?
+----------------
+ 0.523598775598
+(1 row)
+
diff --git a/pgs_line.sql.in b/pgs_line.sql.in
index 9814355..3b51fba 100644
--- a/pgs_line.sql.in
+++ b/pgs_line.sql.in
@@ -593,3 +593,53 @@ COMMENT ON FUNCTION scircle_contains_line_com_neg(sline, scircle) IS
'returns true if spherical circle does not contain spherical line';
+--
+-- distance between line and point
+--
+
+CREATE FUNCTION dist(sline, spoint)
+ RETURNS FLOAT8
+ AS 'MODULE_PATHNAME', 'sphereline_point_distance'
+ LANGUAGE 'c'
+ IMMUTABLE STRICT;
+
+COMMENT ON FUNCTION dist(sline, spoint) IS
+ 'returns the distance between spherical line and spherical point';
+
+
+CREATE OPERATOR <-> (
+ LEFTARG = sline,
+ RIGHTARG = spoint,
+ COMMUTATOR = '<->',
+ PROCEDURE = dist
+);
+
+COMMENT ON OPERATOR <-> (sline, spoint) IS
+ 'returns the distance between spherical line and spherical point';
+
+
+
+--
+-- distance between point and line
+--
+
+CREATE FUNCTION dist(spoint, sline)
+ RETURNS FLOAT8
+ AS 'MODULE_PATHNAME', 'sphereline_point_distance_com'
+ LANGUAGE 'c'
+ IMMUTABLE STRICT;
+
+COMMENT ON FUNCTION dist(spoint, sline) IS
+ 'returns the distance between spherical line and spherical point';
+
+
+CREATE OPERATOR <-> (
+ LEFTARG = spoint,
+ RIGHTARG = sline,
+ COMMUTATOR = '<->',
+ PROCEDURE = dist
+);
+
+COMMENT ON OPERATOR <-> (spoint, sline) IS
+ 'returns the distance between spherical line and spherical point';
+
diff --git a/sql/line.sql b/sql/line.sql
index 7fc6ebf..7a5a2dd 100644
--- a/sql/line.sql
+++ b/sql/line.sql
@@ -1,6 +1,7 @@
\set ECHO none
SELECT set_sphere_output_precision(8);
\set ECHO all
+SET extra_float_digits TO -3;
-- checking spherical line operators
@@ -66,4 +67,18 @@ SELECT sline ( spoint '(0, 0d)', spoint '(0.000001d, 0d)' ) #
SELECT sline ( spoint '(0, 0d)', spoint '(0.000001d, 0d)' ) #
sline ( spoint '(0.000001d, 0d)', spoint '(0.000001d, 0.0000005d)' ) ;
-
\ No newline at end of file
+
+
+-- checking the distance between a line and a point
+
+
+SELECT sline '( 90d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )';
+
+SELECT sline '( 90d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )' =
+ spoint '( 0d, 90d )' <-> sline '( 90d, 0d, 0d, XYZ ), 40d ';
+
+SELECT sline '( 0d, 0d, 0d, XYZ ), 0d ' <-> spoint '( 0d, 90d )';
+
+SELECT sline '( 0d, 0d, 0d, XYZ ), 0d ' <-> spoint '( 0d, 0d )';
+
+SELECT sline '( 0d, 0d, 0d, XYZ ), 30d ' <-> spoint '( 0d, 30d )';
diff --git a/src/line.c b/src/line.c
index b8d1195..6599e64 100644
--- a/src/line.c
+++ b/src/line.c
@@ -33,6 +33,8 @@ PG_FUNCTION_INFO_V1(sphereline_overlap_neg);
PG_FUNCTION_INFO_V1(spheretrans_from_line);
PG_FUNCTION_INFO_V1(spheretrans_line);
PG_FUNCTION_INFO_V1(spheretrans_line_inverse);
+PG_FUNCTION_INFO_V1(sphereline_point_distance);
+PG_FUNCTION_INFO_V1(sphereline_point_distance_com);
/*
* Swaps the beginning and ending of the line.
@@ -642,6 +644,59 @@ sline_center(SPoint *c, const SLine *sl)
euler_spoint_trans(c, &p, &se);
}
+float8 sline_point_dist(const SLine *sl, const SPoint *p)
+{
+ Vector3D v_beg;
+ Vector3D v_end;
+ Vector3D v;
+ Vector3D normal1;
+ Vector3D normal2;
+ Vector3D line;
+ Vector3D first_p;
+ float8 norma;
+ SPoint fp;
+ SPoint sp;
+ float8 fpdist;
+ float8 spdist;
+
+ if (spoint_at_sline(p, sl))
+ {
+ return 0.0;
+ }
+
+ sline_vector_begin(&v_beg, sl);
+ sline_vector_end(&v_end, sl);
+ spoint_vector3d(&v, p);
+
+ /* normal1 to the plane passing through the line and the center of the sphere */
+ vector3d_cross(&normal1, &v_beg, &v_end);
+ if (vector3d_eq(&normal1, &v))
+ {
+ return PIH;
+ }
+
+ /* normal2 to the plane perpendicular to the given line. */
+ vector3d_cross(&normal2, &normal1, &v);
+ vector3d_cross(&line, &normal2, &normal1);
+ norma = sqrt(line.x * line.x + line.y * line.y + line.z * line.z);
+
+ first_p.x = line.x / norma;
+ first_p.y = line.y / norma;
+ first_p.z = line.z / norma;
+ vector3d_spoint(&fp, &first_p);
+
+ if (spoint_at_sline(&fp, sl))
+ {
+ return spoint_dist(&fp, p);
+ }
+
+ vector3d_spoint(&fp, &v_beg);
+ vector3d_spoint(&sp, &v_end);
+ fpdist = spoint_dist(p, &fp);
+ spdist = spoint_dist(p, &sp);
+ return Min(fpdist, spdist);
+}
+
Datum
sphereline_in(PG_FUNCTION_ARGS)
{
@@ -1051,3 +1106,20 @@ spheretrans_from_line(PG_FUNCTION_ARGS)
sphereline_to_euler(e, l);
PG_RETURN_POINTER(e);
}
+
+Datum
+sphereline_point_distance(PG_FUNCTION_ARGS)
+{
+ const SLine *s = (SLine *) PG_GETARG_POINTER(0);
+ const SPoint *p = (SPoint *) PG_GETARG_POINTER(1);
+ PG_RETURN_FLOAT8(sline_point_dist(s, p));
+}
+
+Datum
+sphereline_point_distance_com(PG_FUNCTION_ARGS)
+{
+ const SPoint *p = (SPoint *) PG_GETARG_POINTER(0);
+ const SLine *s = (SLine *) PG_GETARG_POINTER(1);
+ PG_RETURN_FLOAT8(sline_point_dist(s, p));
+}
+
diff --git a/src/line.h b/src/line.h
index 1a41767..002f371 100644
--- a/src/line.h
+++ b/src/line.h
@@ -129,6 +129,11 @@ void euler_sline_trans(SLine *out, const SLine *in, const SEuler *se);
*/
void sline_center(SPoint *c, const SLine *sl);
+/*
+ * Calculates the distance between a line 'sl' and a point 'p'
+ */
+float8 sline_point_dist(const SLine *sl, const SPoint *p);
+
/*
* The input function for spherical line.
*/
@@ -290,4 +295,14 @@ Datum spheretrans_line(PG_FUNCTION_ARGS);
*/
Datum spheretrans_line_inverse(PG_FUNCTION_ARGS);
+/*
+ * Returns the distance between a line and a point.
+ */
+Datum sphereline_point_distance(PG_FUNCTION_ARGS);
+
+/*
+ * Returns the distance between a point and a line.
+ */
+Datum sphereline_point_distance_com(PG_FUNCTION_ARGS);
+
#endif
diff --git a/upgrade_scripts/pg_sphere--1.2.3--1.3.0.sql.in b/upgrade_scripts/pg_sphere--1.2.3--1.3.0.sql.in
index 3791852..6eb9460 100644
--- a/upgrade_scripts/pg_sphere--1.2.3--1.3.0.sql.in
+++ b/upgrade_scripts/pg_sphere--1.2.3--1.3.0.sql.in
@@ -54,3 +54,42 @@ CREATE FUNCTION spoly_as_array(spoly)
COMMENT ON FUNCTION spoly_as_array(spoly) IS
'returns spoly as array of points';
+
+CREATE FUNCTION dist(sline, spoint)
+ RETURNS FLOAT8
+ AS 'MODULE_PATHNAME', 'sphereline_point_distance'
+ LANGUAGE 'c'
+ IMMUTABLE STRICT;
+
+COMMENT ON FUNCTION dist(sline, spoint) IS
+ 'returns the distance between spherical line and spherical point';
+
+CREATE OPERATOR <-> (
+ LEFTARG = sline,
+ RIGHTARG = spoint,
+ COMMUTATOR = '<->',
+ PROCEDURE = dist
+);
+
+COMMENT ON OPERATOR <-> (sline, spoint) IS
+ 'returns the distance between spherical line and spherical point';
+
+CREATE FUNCTION dist(spoint, sline)
+ RETURNS FLOAT8
+ AS 'MODULE_PATHNAME', 'sphereline_point_distance_com'
+ LANGUAGE 'c'
+ IMMUTABLE STRICT;
+
+COMMENT ON FUNCTION dist(spoint, sline) IS
+ 'returns the distance between spherical line and spherical point';
+
+
+CREATE OPERATOR <-> (
+ LEFTARG = spoint,
+ RIGHTARG = sline,
+ COMMUTATOR = '<->',
+ PROCEDURE = dist
+);
+
+COMMENT ON OPERATOR <-> (spoint, sline) IS
+ 'returns the distance between spherical line and spherical point';