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
 
     <para>
      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.
     </para>
 
     <para>
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
 --