Alexander Korotkov, reviewed by Emre Hasegeli.
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;
}
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");
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_ ));
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);
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)
+
-- +-------+
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;