mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
path_inter, path_distance, path_length, dist_ppath now do the right
things with closed paths --- ie, include the closing line segment in their calculations. Per bug report from Curtis Barrett 9-Oct-01.
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.58 2001/03/22 03:59:50 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.59 2001/10/13 17:40:24 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -948,7 +948,7 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2)
|
|||||||
}
|
}
|
||||||
else if (FPeq(pt1->y, pt2->y))
|
else if (FPeq(pt1->y, pt2->y))
|
||||||
{ /* horizontal */
|
{ /* horizontal */
|
||||||
/* use "x = C" */
|
/* use "y = C" */
|
||||||
line->A = 0;
|
line->A = 0;
|
||||||
line->B = -1;
|
line->B = -1;
|
||||||
line->C = pt1->y;
|
line->C = pt1->y;
|
||||||
@ -1376,6 +1376,9 @@ path_inter(PG_FUNCTION_ARGS)
|
|||||||
LSEG seg1,
|
LSEG seg1,
|
||||||
seg2;
|
seg2;
|
||||||
|
|
||||||
|
if (p1->npts <= 0 || p2->npts <= 0)
|
||||||
|
PG_RETURN_BOOL(false);
|
||||||
|
|
||||||
b1.high.x = b1.low.x = p1->p[0].x;
|
b1.high.x = b1.low.x = p1->p[0].x;
|
||||||
b1.high.y = b1.low.y = p1->p[0].y;
|
b1.high.y = b1.low.y = p1->p[0].y;
|
||||||
for (i = 1; i < p1->npts; i++)
|
for (i = 1; i < p1->npts; i++)
|
||||||
@ -1398,12 +1401,34 @@ path_inter(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_BOOL(false);
|
PG_RETURN_BOOL(false);
|
||||||
|
|
||||||
/* pairwise check lseg intersections */
|
/* pairwise check lseg intersections */
|
||||||
for (i = 0; i < p1->npts - 1; i++)
|
for (i = 0; i < p1->npts; i++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < p2->npts - 1; j++)
|
int iprev;
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
iprev = i-1;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
statlseg_construct(&seg1, &p1->p[i], &p1->p[i + 1]);
|
if (!p1->closed)
|
||||||
statlseg_construct(&seg2, &p2->p[j], &p2->p[j + 1]);
|
continue;
|
||||||
|
iprev = p1->npts-1; /* include the closure segment */
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < p2->npts; j++)
|
||||||
|
{
|
||||||
|
int jprev;
|
||||||
|
|
||||||
|
if (j > 0)
|
||||||
|
jprev = j-1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!p2->closed)
|
||||||
|
continue;
|
||||||
|
jprev = p2->npts-1; /* include the closure segment */
|
||||||
|
}
|
||||||
|
|
||||||
|
statlseg_construct(&seg1, &p1->p[iprev], &p1->p[i]);
|
||||||
|
statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
|
||||||
if (lseg_intersect_internal(&seg1, &seg2))
|
if (lseg_intersect_internal(&seg1, &seg2))
|
||||||
PG_RETURN_BOOL(true);
|
PG_RETURN_BOOL(true);
|
||||||
}
|
}
|
||||||
@ -1422,20 +1447,42 @@ path_distance(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
PATH *p1 = PG_GETARG_PATH_P(0);
|
PATH *p1 = PG_GETARG_PATH_P(0);
|
||||||
PATH *p2 = PG_GETARG_PATH_P(1);
|
PATH *p2 = PG_GETARG_PATH_P(1);
|
||||||
bool have_min = false;
|
|
||||||
float8 min = 0.0; /* initialize to keep compiler quiet */
|
float8 min = 0.0; /* initialize to keep compiler quiet */
|
||||||
|
bool have_min = false;
|
||||||
float8 tmp;
|
float8 tmp;
|
||||||
int i,
|
int i,
|
||||||
j;
|
j;
|
||||||
LSEG seg1,
|
LSEG seg1,
|
||||||
seg2;
|
seg2;
|
||||||
|
|
||||||
for (i = 0; i < p1->npts - 1; i++)
|
for (i = 0; i < p1->npts; i++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < p2->npts - 1; j++)
|
int iprev;
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
iprev = i-1;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
statlseg_construct(&seg1, &p1->p[i], &p1->p[i + 1]);
|
if (!p1->closed)
|
||||||
statlseg_construct(&seg2, &p2->p[j], &p2->p[j + 1]);
|
continue;
|
||||||
|
iprev = p1->npts-1; /* include the closure segment */
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < p2->npts; j++)
|
||||||
|
{
|
||||||
|
int jprev;
|
||||||
|
|
||||||
|
if (j > 0)
|
||||||
|
jprev = j-1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!p2->closed)
|
||||||
|
continue;
|
||||||
|
jprev = p2->npts-1; /* include the closure segment */
|
||||||
|
}
|
||||||
|
|
||||||
|
statlseg_construct(&seg1, &p1->p[iprev], &p1->p[i]);
|
||||||
|
statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
|
||||||
|
|
||||||
tmp = DatumGetFloat8(DirectFunctionCall2(lseg_distance,
|
tmp = DatumGetFloat8(DirectFunctionCall2(lseg_distance,
|
||||||
LsegPGetDatum(&seg1),
|
LsegPGetDatum(&seg1),
|
||||||
@ -1463,12 +1510,24 @@ Datum
|
|||||||
path_length(PG_FUNCTION_ARGS)
|
path_length(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
PATH *path = PG_GETARG_PATH_P(0);
|
PATH *path = PG_GETARG_PATH_P(0);
|
||||||
float8 result;
|
float8 result = 0.0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
result = 0.0;
|
for (i = 0; i < path->npts; i++)
|
||||||
for (i = 0; i < (path->npts - 1); i++)
|
{
|
||||||
result += point_dt(&path->p[i], &path->p[i + 1]);
|
int iprev;
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
iprev = i-1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!path->closed)
|
||||||
|
continue;
|
||||||
|
iprev = path->npts-1; /* include the closure segment */
|
||||||
|
}
|
||||||
|
|
||||||
|
result += point_dt(&path->p[iprev], &path->p[i]);
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_FLOAT8(result);
|
PG_RETURN_FLOAT8(result);
|
||||||
}
|
}
|
||||||
@ -2133,17 +2192,18 @@ dist_ppath(PG_FUNCTION_ARGS)
|
|||||||
Point *pt = PG_GETARG_POINT_P(0);
|
Point *pt = PG_GETARG_POINT_P(0);
|
||||||
PATH *path = PG_GETARG_PATH_P(1);
|
PATH *path = PG_GETARG_PATH_P(1);
|
||||||
float8 result = 0.0; /* keep compiler quiet */
|
float8 result = 0.0; /* keep compiler quiet */
|
||||||
|
bool have_min = false;
|
||||||
float8 tmp;
|
float8 tmp;
|
||||||
int i;
|
int i;
|
||||||
LSEG lseg;
|
LSEG lseg;
|
||||||
|
|
||||||
switch (path->npts)
|
switch (path->npts)
|
||||||
{
|
{
|
||||||
/* no points in path? then result is undefined... */
|
|
||||||
case 0:
|
case 0:
|
||||||
|
/* no points in path? then result is undefined... */
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
/* one point in path? then get distance between two points... */
|
|
||||||
case 1:
|
case 1:
|
||||||
|
/* one point in path? then get distance between two points... */
|
||||||
result = point_dt(pt, &path->p[0]);
|
result = point_dt(pt, &path->p[0]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2154,12 +2214,26 @@ dist_ppath(PG_FUNCTION_ARGS)
|
|||||||
* the distance from a point to a path is the smallest
|
* the distance from a point to a path is the smallest
|
||||||
* distance from the point to any of its constituent segments.
|
* distance from the point to any of its constituent segments.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < path->npts - 1; i++)
|
for (i = 0; i < path->npts; i++)
|
||||||
{
|
{
|
||||||
statlseg_construct(&lseg, &path->p[i], &path->p[i + 1]);
|
int iprev;
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
iprev = i-1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!path->closed)
|
||||||
|
continue;
|
||||||
|
iprev = path->npts-1; /* include the closure segment */
|
||||||
|
}
|
||||||
|
|
||||||
|
statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
|
||||||
tmp = dist_ps_internal(pt, &lseg);
|
tmp = dist_ps_internal(pt, &lseg);
|
||||||
if (i == 0 || tmp < result)
|
if (!have_min || tmp < result)
|
||||||
|
{
|
||||||
result = tmp;
|
result = tmp;
|
||||||
|
have_min = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2824,8 +2898,6 @@ on_pb(PG_FUNCTION_ARGS)
|
|||||||
* but not cross.
|
* but not cross.
|
||||||
* (we can do p-in-p in lg(n), but it takes preprocessing)
|
* (we can do p-in-p in lg(n), but it takes preprocessing)
|
||||||
*/
|
*/
|
||||||
#define NEXT(A) (((A)+1) % path->npts) /* cyclic "i+1" */
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
on_ppath(PG_FUNCTION_ARGS)
|
on_ppath(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user