Alexander Korotkov, reviewed by Emre Hasegeli.
index 54391fd7aba7d6ef67aedaca3a80a8ac906d67dd..946dc2893d5fa904b8711ee3d9b6eaec7da51d2e 100644 (file)
@@ -73,6 +73,7 @@ static double dist_ps_internal(Point *pt, LSEG *lseg);
static Point *line_interpt_internal(LINE *l1, LINE *l2);
static bool lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start);
static Point *lseg_interpt_internal(LSEG *l1, LSEG *l2);
+static double dist_ppoly_internal(Point *pt, POLYGON *poly);
/*
* Minimum distance from one object to another.
*-------------------------------------------------------------------*/
+/*
+ * Distance from a point to a line
+ */
Datum
dist_pl(PG_FUNCTION_ARGS)
{
HYPOT(line->A, line->B));
}
+/*
+ * Distance from a point to a lseg
+ */
Datum
dist_ps(PG_FUNCTION_ARGS)
{
}
/*
- ** Distance from a point to a path
+ * Distance from a point to a path
*/
Datum
dist_ppath(PG_FUNCTION_ARGS)
PG_RETURN_FLOAT8(result);
}
+/*
+ * Distance from a point to a box
+ */
Datum
dist_pb(PG_FUNCTION_ARGS)
{
PG_RETURN_FLOAT8(result);
}
-
+/*
+ * Distance from a lseg to a line
+ */
Datum
dist_sl(PG_FUNCTION_ARGS)
{
PG_RETURN_FLOAT8(result);
}
-
+/*
+ * Distance from a lseg to a box
+ */
Datum
dist_sb(PG_FUNCTION_ARGS)
{
PG_RETURN_DATUM(result);
}
-
+/*
+ * Distance from a line to a box
+ */
Datum
dist_lb(PG_FUNCTION_ARGS)
{
PG_RETURN_NULL();
}
-
+/*
+ * Distance from a circle to a polygon
+ */
Datum
dist_cpoly(PG_FUNCTION_ARGS)
{
CIRCLE *circle = PG_GETARG_CIRCLE_P(0);
POLYGON *poly = PG_GETARG_POLYGON_P(1);
float8 result;
+
+ /* calculate distance to center, and subtract radius */
+ result = dist_ppoly_internal(&circle->center, poly);
+
+ result -= circle->radius;
+ if (result < 0)
+ result = 0;
+
+ PG_RETURN_FLOAT8(result);
+}
+
+/*
+ * Distance from a point to a polygon
+ */
+Datum
+dist_ppoly(PG_FUNCTION_ARGS)
+{
+ Point *point = PG_GETARG_POINT_P(0);
+ POLYGON *poly = PG_GETARG_POLYGON_P(1);
+ float8 result;
+
+ result = dist_ppoly_internal(point, poly);
+
+ PG_RETURN_FLOAT8(result);
+}
+
+static double
+dist_ppoly_internal(Point *pt, POLYGON *poly)
+{
+ float8 result;
float8 d;
int i;
LSEG seg;
- if (point_inside(&(circle->center), poly->npts, poly->p) != 0)
+ if (point_inside(pt, poly->npts, poly->p) != 0)
{
#ifdef GEODEBUG
- printf("dist_cpoly- center inside of polygon\n");
+ printf("dist_ppoly_internal- point inside of polygon\n");
#endif
PG_RETURN_FLOAT8(0.0);
}
seg.p[0].y = poly->p[0].y;
seg.p[1].x = poly->p[poly->npts - 1].x;
seg.p[1].y = poly->p[poly->npts - 1].y;
- result = dist_ps_internal(&circle->center, &seg);
+ result = dist_ps_internal(pt, &seg);
#ifdef GEODEBUG
- printf("dist_cpoly- segment 0/n distance is %f\n", result);
+ printf("dist_ppoly_internal- segment 0/n distance is %f\n", result);
#endif
/* check distances for other segments */
seg.p[0].y = poly->p[i].y;
seg.p[1].x = poly->p[i + 1].x;
seg.p[1].y = poly->p[i + 1].y;
- d = dist_ps_internal(&circle->center, &seg);
+ d = dist_ps_internal(pt, &seg);
#ifdef GEODEBUG
- printf("dist_cpoly- segment %d distance is %f\n", (i + 1), d);
+ printf("dist_ppoly_internal- segment %d distance is %f\n", (i + 1), d);
#endif
if (d < result)
result = d;
}
- result -= circle->radius;
- if (result < 0)
- result = 0;
-
- PG_RETURN_FLOAT8(result);
+ return result;
}
index 3b827fca53235443e6d12132bb72e73bbce2f106..88c737b82986b5b26b6630c6f58e5391c73a8186 100644 (file)
@@ -1016,6 +1016,8 @@ DATA(insert OID = 1521 ( "#" PGNSP PGUID l f f 0 604 23 0 0 poly_npo
DESCR("number of points");
DATA(insert OID = 1522 ( "<->" PGNSP PGUID b f f 600 718 701 0 0 dist_pc - - ));
DESCR("distance between");
+DATA(insert OID = 3276 ( "<->" PGNSP PGUID b f f 600 604 701 0 0 dist_ppoly - - ));
+DESCR("distance between");
DATA(insert OID = 1523 ( "<->" PGNSP PGUID b f f 718 604 701 0 0 dist_cpoly - - ));
DESCR("distance between");
index e5912ea8fa7c85165571368a5c94e2afa984515d..eace352ec0fdbf46f2bfc3ffcb38a89afb77867f 100644 (file)
@@ -844,6 +844,7 @@ DATA(insert OID = 726 ( dist_lb PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 70
DATA(insert OID = 727 ( dist_sl PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "601 628" _null_ _null_ _null_ _null_ dist_sl _null_ _null_ _null_ ));
DATA(insert OID = 728 ( dist_cpoly PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "718 604" _null_ _null_ _null_ _null_ dist_cpoly _null_ _null_ _null_ ));
DATA(insert OID = 729 ( poly_distance PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "604 604" _null_ _null_ _null_ _null_ poly_distance _null_ _null_ _null_ ));
+DATA(insert OID = 3275 ( dist_ppoly PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "600 604" _null_ _null_ _null_ _null_ dist_ppoly _null_ _null_ _null_ ));
DATA(insert OID = 740 ( text_lt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ text_lt _null_ _null_ _null_ ));
DATA(insert OID = 741 ( text_le PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ text_le _null_ _null_ _null_ ));
index 60b5d0192997d8a095c3cfc39c10b7bd43d657e5..91610d85471e6b8f1b30e2be9b1c75347e472730 100644 (file)
@@ -395,6 +395,7 @@ extern Datum circle_radius(PG_FUNCTION_ARGS);
extern Datum circle_distance(PG_FUNCTION_ARGS);
extern Datum dist_pc(PG_FUNCTION_ARGS);
extern Datum dist_cpoly(PG_FUNCTION_ARGS);
+extern Datum dist_ppoly(PG_FUNCTION_ARGS);
extern Datum circle_center(PG_FUNCTION_ARGS);
extern Datum cr_circle(PG_FUNCTION_ARGS);
extern Datum box_circle(PG_FUNCTION_ARGS);
index 33388eb909314bcd82bf4735ef6609359af43afc..9d3e07708b18e232de5f8eeb1dee57f93f38d9a0 100644 (file)
@@ -279,3 +279,14 @@ SELECT '((200,800),(800,800),(800,200),(200,200))' && '(1000,1000,0,0)'::polygo
t
(1 row)
+-- distance from a point
+SELECT '(0,0)'::point <-> '((0,0),(1,2),(2,1))'::polygon as on_corner,
+ '(1,1)'::point <-> '((0,0),(2,2),(1,3))'::polygon as on_segment,
+ '(2,2)'::point <-> '((0,0),(1,4),(3,1))'::polygon as inside,
+ '(3,3)'::point <-> '((0,2),(2,0),(2,2))'::polygon as near_corner,
+ '(4,4)'::point <-> '((0,0),(0,3),(4,0))'::polygon as near_segment;
+ on_corner | on_segment | inside | near_corner | near_segment
+-----------+------------+--------+-----------------+--------------
+ 0 | 0 | 0 | 1.4142135623731 | 3.2
+(1 row)
+
index d95fa9644762155129e3d3822bfef68cfa75e17a..b4d9539347568aa7a230daba65d1cefc20b745bf 100644 (file)
@@ -172,3 +172,10 @@ SELECT '((0,4),(6,4),(1,2),(6,0),(0,0))'::polygon && '((2,1),(2,3),(3,3),(3,1))'
-- +-------+
SELECT '((1,4),(1,1),(4,1),(4,2),(2,2),(2,4),(1,4))'::polygon && '((3,3),(4,3),(4,4),(3,4),(3,3))'::polygon AS "false";
SELECT '((200,800),(800,800),(800,200),(200,200))' && '(1000,1000,0,0)'::polygon AS "true";
+
+-- distance from a point
+SELECT '(0,0)'::point <-> '((0,0),(1,2),(2,1))'::polygon as on_corner,
+ '(1,1)'::point <-> '((0,0),(2,2),(1,3))'::polygon as on_segment,
+ '(2,2)'::point <-> '((0,0),(1,4),(3,1))'::polygon as inside,
+ '(3,3)'::point <-> '((0,2),(2,0),(2,2))'::polygon as near_corner,
+ '(4,4)'::point <-> '((0,0),(0,3),(4,0))'::polygon as near_segment;