aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/utils/adt/geo_ops.c77
1 files changed, 67 insertions, 10 deletions
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 9484dbc2273..e9c347cb8c6 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -3798,11 +3798,9 @@ poly_same(PG_FUNCTION_ARGS)
/*-----------------------------------------------------------------
* Determine if polygon A overlaps polygon B
*-----------------------------------------------------------------*/
-Datum
-poly_overlap(PG_FUNCTION_ARGS)
+static bool
+poly_overlap_internal(POLYGON *polya, POLYGON *polyb)
{
- POLYGON *polya = PG_GETARG_POLYGON_P(0);
- POLYGON *polyb = PG_GETARG_POLYGON_P(1);
bool result;
Assert(polya->npts > 0 && polyb->npts > 0);
@@ -3854,6 +3852,18 @@ poly_overlap(PG_FUNCTION_ARGS)
}
}
+ return result;
+}
+
+Datum
+poly_overlap(PG_FUNCTION_ARGS)
+{
+ POLYGON *polya = PG_GETARG_POLYGON_P(0);
+ POLYGON *polyb = PG_GETARG_POLYGON_P(1);
+ bool result;
+
+ result = poly_overlap_internal(polya, polyb);
+
/*
* Avoid leaking memory for toasted inputs ... needed for rtree indexes
*/
@@ -4071,16 +4081,63 @@ pt_contained_poly(PG_FUNCTION_ARGS)
Datum
poly_distance(PG_FUNCTION_ARGS)
{
-#ifdef NOT_USED
POLYGON *polya = PG_GETARG_POLYGON_P(0);
POLYGON *polyb = PG_GETARG_POLYGON_P(1);
-#endif
+ float8 min = 0.0; /* initialize to keep compiler quiet */
+ bool have_min = false;
+ float8 tmp;
+ int i,
+ j;
+ LSEG seg1,
+ seg2;
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("function \"poly_distance\" not implemented")));
+ /*
+ * Distance is zero if polygons overlap. We must check this because the
+ * path distance will not give the right answer if one poly is entirely
+ * within the other.
+ */
+ if (poly_overlap_internal(polya, polyb))
+ PG_RETURN_FLOAT8(0.0);
- PG_RETURN_NULL();
+ /*
+ * When they don't overlap, the distance calculation is identical to that
+ * for closed paths (i.e., we needn't care about the fact that polygons
+ * include their contained areas). See path_distance().
+ */
+ for (i = 0; i < polya->npts; i++)
+ {
+ int iprev;
+
+ if (i > 0)
+ iprev = i - 1;
+ else
+ iprev = polya->npts - 1;
+
+ for (j = 0; j < polyb->npts; j++)
+ {
+ int jprev;
+
+ if (j > 0)
+ jprev = j - 1;
+ else
+ jprev = polyb->npts - 1;
+
+ statlseg_construct(&seg1, &polya->p[iprev], &polya->p[i]);
+ statlseg_construct(&seg2, &polyb->p[jprev], &polyb->p[j]);
+
+ tmp = lseg_closept_lseg(NULL, &seg1, &seg2);
+ if (!have_min || float8_lt(tmp, min))
+ {
+ min = tmp;
+ have_min = true;
+ }
+ }
+ }
+
+ if (!have_min)
+ PG_RETURN_NULL();
+
+ PG_RETURN_FLOAT8(min);
}