Skip to content

Added calculation of the distance between a line and a point #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion doc/operators.sgm
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@
a non-boolean operator returning the distance between two
objects in radians. Currently,
<application>pgSphere</application> 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).
</para>
Expand All @@ -343,6 +344,17 @@
<![CDATA[ dist]]>
<![CDATA[------]]>
<![CDATA[ 16]]>
<![CDATA[(1 row)]]>
</programlisting>
</example>
<example>
<title>Distance between point and line</title>
<programlisting>
<![CDATA[sql> SELECT 180 * (sline '( 0d, 0d, 0d, XYZ ), 40d ' <-> spoint '( 0d, 90d )')]]>
<![CDATA[ / pi() AS dist ;]]>
<![CDATA[ dist]]>
<![CDATA[------]]>
<![CDATA[ 90]]>
<![CDATA[(1 row)]]>
</programlisting>
</example>
Expand Down
14 changes: 7 additions & 7 deletions expected/init_test.out.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
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: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
34 changes: 33 additions & 1 deletion expected/line.out
Original file line number Diff line number Diff line change
Expand Up @@ -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)' ) ;
Expand Down Expand Up @@ -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)

50 changes: 50 additions & 0 deletions pgs_line.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -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';

17 changes: 16 additions & 1 deletion sql/line.sql
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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)' ) ;



-- 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 )';
72 changes: 72 additions & 0 deletions src/line.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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));
}

15 changes: 15 additions & 0 deletions src/line.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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
39 changes: 39 additions & 0 deletions upgrade_scripts/pg_sphere--1.2.3--1.3.0.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -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';