📄 geo_ops.c
字号:
PG_RETURN_POINT_P(point);}Datumpoint_out(PG_FUNCTION_ARGS){ Point *pt = PG_GETARG_POINT_P(0); PG_RETURN_CSTRING(path_encode(-1, 1, pt));}/* * point_recv - converts external binary format to point */Datumpoint_recv(PG_FUNCTION_ARGS){ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); Point *point; point = (Point *) palloc(sizeof(Point)); point->x = pq_getmsgfloat8(buf); point->y = pq_getmsgfloat8(buf); PG_RETURN_POINT_P(point);}/* * point_send - converts point to binary format */Datumpoint_send(PG_FUNCTION_ARGS){ Point *pt = PG_GETARG_POINT_P(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendfloat8(&buf, pt->x); pq_sendfloat8(&buf, pt->y); PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}static Point *point_construct(double x, double y){ Point *result = (Point *) palloc(sizeof(Point)); result->x = x; result->y = y; return result;}static Point *point_copy(Point *pt){ Point *result; if (!PointerIsValid(pt)) return NULL; result = (Point *) palloc(sizeof(Point)); result->x = pt->x; result->y = pt->y; return result;}/*---------------------------------------------------------- * Relational operators for Points. * Since we do have a sense of coordinates being * "equal" to a given accuracy (point_vert, point_horiz), * the other ops must preserve that sense. This means * that results may, strictly speaking, be a lie (unless * EPSILON = 0.0). *---------------------------------------------------------*/Datumpoint_left(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_BOOL(FPlt(pt1->x, pt2->x));}Datumpoint_right(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_BOOL(FPgt(pt1->x, pt2->x));}Datumpoint_above(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_BOOL(FPgt(pt1->y, pt2->y));}Datumpoint_below(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_BOOL(FPlt(pt1->y, pt2->y));}Datumpoint_vert(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_BOOL(FPeq(pt1->x, pt2->x));}Datumpoint_horiz(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_BOOL(FPeq(pt1->y, pt2->y));}Datumpoint_eq(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_BOOL(FPeq(pt1->x, pt2->x) && FPeq(pt1->y, pt2->y));}Datumpoint_ne(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_BOOL(FPne(pt1->x, pt2->x) || FPne(pt1->y, pt2->y));}/*---------------------------------------------------------- * "Arithmetic" operators on points. *---------------------------------------------------------*/Datumpoint_distance(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_FLOAT8(HYPOT(pt1->x - pt2->x, pt1->y - pt2->y));}doublepoint_dt(Point *pt1, Point *pt2){#ifdef GEODEBUG printf("point_dt- segment (%f,%f),(%f,%f) length is %f\n", pt1->x, pt1->y, pt2->x, pt2->y, HYPOT(pt1->x - pt2->x, pt1->y - pt2->y));#endif return HYPOT(pt1->x - pt2->x, pt1->y - pt2->y);}Datumpoint_slope(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); PG_RETURN_FLOAT8(point_sl(pt1, pt2));}doublepoint_sl(Point *pt1, Point *pt2){ return (FPeq(pt1->x, pt2->x) ? (double) DBL_MAX : (pt1->y - pt2->y) / (pt1->x - pt2->x));}/*********************************************************************** ** ** Routines for 2D line segments. ** ***********************************************************************//*---------------------------------------------------------- * String to lseg, lseg to string conversion. * External forms: "[(x1, y1), (x2, y2)]" * "(x1, y1), (x2, y2)" * "x1, y1, x2, y2" * closed form ok "((x1, y1), (x2, y2))" * (old form) "(x1, y1, x2, y2)" *---------------------------------------------------------*/Datumlseg_in(PG_FUNCTION_ARGS){ char *str = PG_GETARG_CSTRING(0); LSEG *lseg; int isopen; char *s; lseg = (LSEG *) palloc(sizeof(LSEG)); if ((!path_decode(TRUE, 2, str, &isopen, &s, &(lseg->p[0]))) || (*s != '\0')) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type lseg: \"%s\"", str)));#ifdef NOT_USED lseg->m = point_sl(&lseg->p[0], &lseg->p[1]);#endif PG_RETURN_LSEG_P(lseg);}Datumlseg_out(PG_FUNCTION_ARGS){ LSEG *ls = PG_GETARG_LSEG_P(0); PG_RETURN_CSTRING(path_encode(FALSE, 2, (Point *) &(ls->p[0])));}/* * lseg_recv - converts external binary format to lseg */Datumlseg_recv(PG_FUNCTION_ARGS){ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); LSEG *lseg; lseg = (LSEG *) palloc(sizeof(LSEG)); lseg->p[0].x = pq_getmsgfloat8(buf); lseg->p[0].y = pq_getmsgfloat8(buf); lseg->p[1].x = pq_getmsgfloat8(buf); lseg->p[1].y = pq_getmsgfloat8(buf);#ifdef NOT_USED lseg->m = point_sl(&lseg->p[0], &lseg->p[1]);#endif PG_RETURN_LSEG_P(lseg);}/* * lseg_send - converts lseg to binary format */Datumlseg_send(PG_FUNCTION_ARGS){ LSEG *ls = PG_GETARG_LSEG_P(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendfloat8(&buf, ls->p[0].x); pq_sendfloat8(&buf, ls->p[0].y); pq_sendfloat8(&buf, ls->p[1].x); pq_sendfloat8(&buf, ls->p[1].y); PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* lseg_construct - * form a LSEG from two Points. */Datumlseg_construct(PG_FUNCTION_ARGS){ Point *pt1 = PG_GETARG_POINT_P(0); Point *pt2 = PG_GETARG_POINT_P(1); LSEG *result = (LSEG *) palloc(sizeof(LSEG)); result->p[0].x = pt1->x; result->p[0].y = pt1->y; result->p[1].x = pt2->x; result->p[1].y = pt2->y;#ifdef NOT_USED result->m = point_sl(pt1, pt2);#endif PG_RETURN_LSEG_P(result);}/* like lseg_construct, but assume space already allocated */static voidstatlseg_construct(LSEG *lseg, Point *pt1, Point *pt2){ lseg->p[0].x = pt1->x; lseg->p[0].y = pt1->y; lseg->p[1].x = pt2->x; lseg->p[1].y = pt2->y;#ifdef NOT_USED lseg->m = point_sl(pt1, pt2);#endif}Datumlseg_length(PG_FUNCTION_ARGS){ LSEG *lseg = PG_GETARG_LSEG_P(0); PG_RETURN_FLOAT8(point_dt(&lseg->p[0], &lseg->p[1]));}/*---------------------------------------------------------- * Relative position routines. *---------------------------------------------------------*//* ** find intersection of the two lines, and see if it falls on ** both segments. */Datumlseg_intersect(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); PG_RETURN_BOOL(lseg_intersect_internal(l1, l2));}static boollseg_intersect_internal(LSEG *l1, LSEG *l2){ LINE ln; Point *interpt; bool retval; line_construct_pts(&ln, &l2->p[0], &l2->p[1]); interpt = interpt_sl(l1, &ln); if (interpt != NULL && on_ps_internal(interpt, l2)) retval = true; /* interpt on l1 and l2 */ else retval = false; return retval;}Datumlseg_parallel(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1);#ifdef NOT_USED PG_RETURN_BOOL(FPeq(l1->m, l2->m));#endif PG_RETURN_BOOL(FPeq(point_sl(&l1->p[0], &l1->p[1]), point_sl(&l2->p[0], &l2->p[1])));}/* lseg_perp() * Determine if two line segments are perpendicular. * * This code did not get the correct answer for * '((0,0),(0,1))'::lseg ?-| '((0,0),(1,0))'::lseg * So, modified it to check explicitly for slope of vertical line * returned by point_sl() and the results seem better. * - thomas 1998-01-31 */Datumlseg_perp(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); double m1, m2; m1 = point_sl(&(l1->p[0]), &(l1->p[1])); m2 = point_sl(&(l2->p[0]), &(l2->p[1]));#ifdef GEODEBUG printf("lseg_perp- slopes are %g and %g\n", m1, m2);#endif if (FPzero(m1)) PG_RETURN_BOOL(FPeq(m2, DBL_MAX)); else if (FPzero(m2)) PG_RETURN_BOOL(FPeq(m1, DBL_MAX)); PG_RETURN_BOOL(FPeq(m1 / m2, -1.0));}Datumlseg_vertical(PG_FUNCTION_ARGS){ LSEG *lseg = PG_GETARG_LSEG_P(0); PG_RETURN_BOOL(FPeq(lseg->p[0].x, lseg->p[1].x));}Datumlseg_horizontal(PG_FUNCTION_ARGS){ LSEG *lseg = PG_GETARG_LSEG_P(0); PG_RETURN_BOOL(FPeq(lseg->p[0].y, lseg->p[1].y));}Datumlseg_eq(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); PG_RETURN_BOOL(FPeq(l1->p[0].x, l2->p[0].x) && FPeq(l1->p[0].y, l2->p[0].y) && FPeq(l1->p[1].x, l2->p[1].x) && FPeq(l1->p[1].y, l2->p[1].y));}Datumlseg_ne(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); PG_RETURN_BOOL(!FPeq(l1->p[0].x, l2->p[0].x) || !FPeq(l1->p[0].y, l2->p[0].y) || !FPeq(l1->p[1].x, l2->p[1].x) || !FPeq(l1->p[1].y, l2->p[1].y));}Datumlseg_lt(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); PG_RETURN_BOOL(FPlt(point_dt(&l1->p[0], &l1->p[1]), point_dt(&l2->p[0], &l2->p[1])));}Datumlseg_le(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); PG_RETURN_BOOL(FPle(point_dt(&l1->p[0], &l1->p[1]), point_dt(&l2->p[0], &l2->p[1])));}Datumlseg_gt(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); PG_RETURN_BOOL(FPgt(point_dt(&l1->p[0], &l1->p[1]), point_dt(&l2->p[0], &l2->p[1])));}Datumlseg_ge(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); PG_RETURN_BOOL(FPge(point_dt(&l1->p[0], &l1->p[1]), point_dt(&l2->p[0], &l2->p[1])));}/*---------------------------------------------------------- * Line arithmetic routines. *---------------------------------------------------------*//* lseg_distance - * If two segments don't intersect, then the closest * point will be from one of the endpoints to the other * segment. */Datumlseg_distance(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); PG_RETURN_FLOAT8(lseg_dt(l1, l2));}/* lseg_dt() * Distance between two line segments. * Must check both sets of endpoints to ensure minimum distance is found. * - thomas 1998-02-01 */static doublelseg_dt(LSEG *l1, LSEG *l2){ double result, d; if (lseg_intersect_internal(l1, l2)) return 0.0; d = dist_ps_internal(&l1->p[0], l2); result = d; d = dist_ps_internal(&l1->p[1], l2); result = Min(result, d); d = dist_ps_internal(&l2->p[0], l1); result = Min(result, d); d = dist_ps_internal(&l2->p[1], l1); result = Min(result, d); return result;}Datumlseg_center(PG_FUNCTION_ARGS){ LSEG *lseg = PG_GETARG_LSEG_P(0); Point *result; result = (Point *) palloc(sizeof(Point)); result->x = (lseg->p[0].x + lseg->p[1].x) / 2.0; result->y = (lseg->p[0].y + lseg->p[1].y) / 2.0; PG_RETURN_POINT_P(result);}/* lseg_interpt - * Find the intersection point of two segments (if any). */Datumlseg_interpt(PG_FUNCTION_ARGS){ LSEG *l1 = PG_GETARG_LSEG_P(0); LSEG *l2 = PG_GETARG_LSEG_P(1); Point *result; LINE tmp1, tmp2; /* * Find the intersection of the appropriate lines, if any. */ line_construct_pts(&tmp1, &l1->p[0], &l1->p[1]); line_construct_pts(&tmp2, &l2->p[0], &l2->p[1]); result = line_interpt_internal(&tmp1, &tmp2); if (!PointerIsValid(result)) PG_RETURN_NULL(); /* * If the line intersection point isn't within l1 (or equivalently l2), * there is no valid segment intersection point at all. */ if (!on_ps_internal(result, l1) || !on_ps_internal(result, l2)) PG_RETURN_NULL(); /* * If there is an intersection, then check explicitly for matching * endpoints since there may be rounding effects with annoying lsb * residue. - tgl 1997-07-09 */ if ((FPeq(l1->p[0].x, l2->p[0].x) && FPeq(l1->p[0].y, l2->p[0].y)) || (FPeq(l1->p[0].x, l2->p[1].x) && FPeq(l1->p[0].y, l2->p[1].y))) { result->x = l1->p[0].x; result->y = l1->p[0].y; } else if ((FPeq(l1->p[1].x, l2->p[0].x) && FPeq(l1->p[1].y, l2->p[0].y)) || (FPeq(l1->p[1].x, l2->p[1].x) && FPeq(l1->p[1].y, l2->p[1].y))) { result->x = l1->p[1].x; result->y = l1->p[1].y; } PG_RETURN_POINT_P(result);}/*********************************************************************** ** ** Routines for position comparisons of differently-typed ** 2D objects. ** ***********************************************************************//*--------------------------------------------------------------------- * dist_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -