diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 6929f3bb18..0932c812da 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -3562,8 +3562,9 @@ SELECT person.name, holidays.num_weeks FROM person, holidays Polygons are represented by lists of points (the vertexes of the - polygon). Polygons are very similar to closed paths, but are - stored differently and have their own set of support routines. + polygon). Polygons are very similar to closed paths; the essential + difference is that a polygon is considered to include the area + within it, while a path is not. diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 9484dbc227..e9c347cb8c 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); } diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out index 974e2ec43a..eb717d3643 100644 --- a/src/test/regress/expected/geometry.out +++ b/src/test/regress/expected/geometry.out @@ -4189,7 +4189,59 @@ SELECT p1.f1, p2.f1 FROM POLYGON_TBL p1, POLYGON_TBL p2 WHERE p1.f1 |&> p2.f1; -- Distance to polygon SELECT p1.f1, p2.f1, p1.f1 <-> p2.f1 FROM POLYGON_TBL p1, POLYGON_TBL p2; -ERROR: function "poly_distance" not implemented + f1 | f1 | ?column? +----------------------------+----------------------------+---------------- + ((2,0),(2,4),(0,0)) | ((2,0),(2,4),(0,0)) | 0 + ((2,0),(2,4),(0,0)) | ((3,1),(3,3),(1,0)) | 0 + ((2,0),(2,4),(0,0)) | ((1,2),(3,4),(5,6),(7,8)) | 0 + ((2,0),(2,4),(0,0)) | ((7,8),(5,6),(3,4),(1,2)) | 0 + ((2,0),(2,4),(0,0)) | ((1,2),(7,8),(5,6),(3,-4)) | 0 + ((2,0),(2,4),(0,0)) | ((0,0)) | 0 + ((2,0),(2,4),(0,0)) | ((0,1),(0,1)) | 0.4472135955 + ((3,1),(3,3),(1,0)) | ((2,0),(2,4),(0,0)) | 0 + ((3,1),(3,3),(1,0)) | ((3,1),(3,3),(1,0)) | 0 + ((3,1),(3,3),(1,0)) | ((1,2),(3,4),(5,6),(7,8)) | 0.707106781187 + ((3,1),(3,3),(1,0)) | ((7,8),(5,6),(3,4),(1,2)) | 0.707106781187 + ((3,1),(3,3),(1,0)) | ((1,2),(7,8),(5,6),(3,-4)) | 0 + ((3,1),(3,3),(1,0)) | ((0,0)) | 1 + ((3,1),(3,3),(1,0)) | ((0,1),(0,1)) | 1.38675049056 + ((1,2),(3,4),(5,6),(7,8)) | ((2,0),(2,4),(0,0)) | 0 + ((1,2),(3,4),(5,6),(7,8)) | ((3,1),(3,3),(1,0)) | 0.707106781187 + ((1,2),(3,4),(5,6),(7,8)) | ((1,2),(3,4),(5,6),(7,8)) | 0 + ((1,2),(3,4),(5,6),(7,8)) | ((7,8),(5,6),(3,4),(1,2)) | 0 + ((1,2),(3,4),(5,6),(7,8)) | ((1,2),(7,8),(5,6),(3,-4)) | 0 + ((1,2),(3,4),(5,6),(7,8)) | ((0,0)) | 2.2360679775 + ((1,2),(3,4),(5,6),(7,8)) | ((0,1),(0,1)) | 1.41421356237 + ((7,8),(5,6),(3,4),(1,2)) | ((2,0),(2,4),(0,0)) | 0 + ((7,8),(5,6),(3,4),(1,2)) | ((3,1),(3,3),(1,0)) | 0.707106781187 + ((7,8),(5,6),(3,4),(1,2)) | ((1,2),(3,4),(5,6),(7,8)) | 0 + ((7,8),(5,6),(3,4),(1,2)) | ((7,8),(5,6),(3,4),(1,2)) | 0 + ((7,8),(5,6),(3,4),(1,2)) | ((1,2),(7,8),(5,6),(3,-4)) | 0 + ((7,8),(5,6),(3,4),(1,2)) | ((0,0)) | 2.2360679775 + ((7,8),(5,6),(3,4),(1,2)) | ((0,1),(0,1)) | 1.41421356237 + ((1,2),(7,8),(5,6),(3,-4)) | ((2,0),(2,4),(0,0)) | 0 + ((1,2),(7,8),(5,6),(3,-4)) | ((3,1),(3,3),(1,0)) | 0 + ((1,2),(7,8),(5,6),(3,-4)) | ((1,2),(3,4),(5,6),(7,8)) | 0 + ((1,2),(7,8),(5,6),(3,-4)) | ((7,8),(5,6),(3,4),(1,2)) | 0 + ((1,2),(7,8),(5,6),(3,-4)) | ((1,2),(7,8),(5,6),(3,-4)) | 0 + ((1,2),(7,8),(5,6),(3,-4)) | ((0,0)) | 1.58113883008 + ((1,2),(7,8),(5,6),(3,-4)) | ((0,1),(0,1)) | 1.26491106407 + ((0,0)) | ((2,0),(2,4),(0,0)) | 0 + ((0,0)) | ((3,1),(3,3),(1,0)) | 1 + ((0,0)) | ((1,2),(3,4),(5,6),(7,8)) | 2.2360679775 + ((0,0)) | ((7,8),(5,6),(3,4),(1,2)) | 2.2360679775 + ((0,0)) | ((1,2),(7,8),(5,6),(3,-4)) | 1.58113883008 + ((0,0)) | ((0,0)) | 0 + ((0,0)) | ((0,1),(0,1)) | 1 + ((0,1),(0,1)) | ((2,0),(2,4),(0,0)) | 0.4472135955 + ((0,1),(0,1)) | ((3,1),(3,3),(1,0)) | 1.38675049056 + ((0,1),(0,1)) | ((1,2),(3,4),(5,6),(7,8)) | 1.41421356237 + ((0,1),(0,1)) | ((7,8),(5,6),(3,4),(1,2)) | 1.41421356237 + ((0,1),(0,1)) | ((1,2),(7,8),(5,6),(3,-4)) | 1.26491106407 + ((0,1),(0,1)) | ((0,0)) | 1 + ((0,1),(0,1)) | ((0,1),(0,1)) | 0 +(49 rows) + -- -- Circles --