⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 geo_ops.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
}Datumline_horizontal(PG_FUNCTION_ARGS){	LINE	   *line = PG_GETARG_LINE_P(0);	PG_RETURN_BOOL(FPzero(line->A));}Datumline_eq(PG_FUNCTION_ARGS){	LINE	   *l1 = PG_GETARG_LINE_P(0);	LINE	   *l2 = PG_GETARG_LINE_P(1);	double		k;	if (!FPzero(l2->A))		k = l1->A / l2->A;	else if (!FPzero(l2->B))		k = l1->B / l2->B;	else if (!FPzero(l2->C))		k = l1->C / l2->C;	else		k = 1.0;	PG_RETURN_BOOL(FPeq(l1->A, k * l2->A) &&				   FPeq(l1->B, k * l2->B) &&				   FPeq(l1->C, k * l2->C));}/*---------------------------------------------------------- *	Line arithmetic routines. *---------------------------------------------------------*//* line_distance() * Distance between two lines. */Datumline_distance(PG_FUNCTION_ARGS){	LINE	   *l1 = PG_GETARG_LINE_P(0);	LINE	   *l2 = PG_GETARG_LINE_P(1);	float8		result;	Point	   *tmp;	if (!DatumGetBool(DirectFunctionCall2(line_parallel,										  LinePGetDatum(l1),										  LinePGetDatum(l2))))		PG_RETURN_FLOAT8(0.0);	if (FPzero(l1->B))			/* vertical? */		PG_RETURN_FLOAT8(fabs(l1->C - l2->C));	tmp = point_construct(0.0, l1->C);	result = dist_pl_internal(tmp, l2);	PG_RETURN_FLOAT8(result);}/* line_interpt() * Point where two lines l1, l2 intersect (if any) */Datumline_interpt(PG_FUNCTION_ARGS){	LINE	   *l1 = PG_GETARG_LINE_P(0);	LINE	   *l2 = PG_GETARG_LINE_P(1);	Point	   *result;	result = line_interpt_internal(l1, l2);	if (result == NULL)		PG_RETURN_NULL();	PG_RETURN_POINT_P(result);}/* * Internal version of line_interpt * * returns a NULL pointer if no intersection point */static Point *line_interpt_internal(LINE *l1, LINE *l2){	Point	   *result;	double		x,				y;	/*	 * NOTE: if the lines are identical then we will find they are parallel	 * and report "no intersection".  This is a little weird, but since	 * there's no *unique* intersection, maybe it's appropriate behavior.	 */	if (DatumGetBool(DirectFunctionCall2(line_parallel,										 LinePGetDatum(l1),										 LinePGetDatum(l2))))		return NULL;#ifdef NOT_USED	if (FPzero(l1->B))			/* l1 vertical? */		result = point_construct(l2->m * l1->C + l2->C, l1->C);	else if (FPzero(l2->B))		/* l2 vertical? */		result = point_construct(l1->m * l2->C + l1->C, l2->C);	else	{		x = (l1->C - l2->C) / (l2->A - l1->A);		result = point_construct(x, l1->m * x + l1->C);	}#endif	if (FPzero(l1->B))			/* l1 vertical? */	{		x = l1->C;		y = (l2->A * x + l2->C);	}	else if (FPzero(l2->B))		/* l2 vertical? */	{		x = l2->C;		y = (l1->A * x + l1->C);	}	else	{		x = (l1->C - l2->C) / (l2->A - l1->A);		y = (l1->A * x + l1->C);	}	result = point_construct(x, y);#ifdef GEODEBUG	printf("line_interpt- lines are A=%.*g, B=%.*g, C=%.*g, A=%.*g, B=%.*g, C=%.*g\n",		   DBL_DIG, l1->A, DBL_DIG, l1->B, DBL_DIG, l1->C, DBL_DIG, l2->A, DBL_DIG, l2->B, DBL_DIG, l2->C);	printf("line_interpt- lines intersect at (%.*g,%.*g)\n", DBL_DIG, x, DBL_DIG, y);#endif	return result;}/*********************************************************************** ** **		Routines for 2D paths (sequences of line segments, also **				called `polylines'). ** **				This is not a general package for geometric paths, **				which of course include polygons; the emphasis here **				is on (for example) usefulness in wire layout. ** ***********************************************************************//*---------------------------------------------------------- *	String to path / path to string conversion. *		External format: *				"((xcoord, ycoord),... )" *				"[(xcoord, ycoord),... ]" *				"(xcoord, ycoord),... " *				"[xcoord, ycoord,... ]" *		Also support older format: *				"(closed, npts, xcoord, ycoord,... )" *---------------------------------------------------------*/Datumpath_area(PG_FUNCTION_ARGS){	PATH	   *path = PG_GETARG_PATH_P(0);	double		area = 0.0;	int			i,				j;	if (!path->closed)		PG_RETURN_NULL();	for (i = 0; i < path->npts; i++)	{		j = (i + 1) % path->npts;		area += path->p[i].x * path->p[j].y;		area -= path->p[i].y * path->p[j].x;	}	area *= 0.5;	PG_RETURN_FLOAT8(area < 0.0 ? -area : area);}Datumpath_in(PG_FUNCTION_ARGS){	char	   *str = PG_GETARG_CSTRING(0);	PATH	   *path;	int			isopen;	char	   *s;	int			npts;	int			size;	int			depth = 0;	if ((npts = pair_count(str, ',')) <= 0)		ereport(ERROR,				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),				 errmsg("invalid input syntax for type path: \"%s\"", str)));	s = str;	while (isspace((unsigned char) *s))		s++;	/* skip single leading paren */	if ((*s == LDELIM) && (strrchr(s, LDELIM) == s))	{		s++;		depth++;	}	size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts;	path = (PATH *) palloc(size);	path->size = size;	path->npts = npts;	if ((!path_decode(TRUE, npts, s, &isopen, &s, &(path->p[0])))	&& (!((depth == 0) && (*s == '\0'))) && !((depth >= 1) && (*s == RDELIM)))		ereport(ERROR,				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),				 errmsg("invalid input syntax for type path: \"%s\"", str)));	path->closed = (!isopen);	PG_RETURN_PATH_P(path);}Datumpath_out(PG_FUNCTION_ARGS){	PATH	   *path = PG_GETARG_PATH_P(0);	PG_RETURN_CSTRING(path_encode(path->closed, path->npts, path->p));}/* *		path_recv			- converts external binary format to path * * External representation is closed flag (a boolean byte), int32 number * of points, and the points. */Datumpath_recv(PG_FUNCTION_ARGS){	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);	PATH	   *path;	int			closed;	int32		npts;	int32		i;	int			size;	closed = pq_getmsgbyte(buf);	npts = pq_getmsgint(buf, sizeof(int32));	if (npts < 0 || npts >= (int32) ((INT_MAX - offsetof(PATH, p[0])) / sizeof(Point)))		ereport(ERROR,				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),			 errmsg("invalid number of points in external \"path\" value")));	size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts;	path = (PATH *) palloc(size);	path->size = size;	path->npts = npts;	path->closed = (closed ? 1 : 0);	for (i = 0; i < npts; i++)	{		path->p[i].x = pq_getmsgfloat8(buf);		path->p[i].y = pq_getmsgfloat8(buf);	}	PG_RETURN_PATH_P(path);}/* *		path_send			- converts path to binary format */Datumpath_send(PG_FUNCTION_ARGS){	PATH	   *path = PG_GETARG_PATH_P(0);	StringInfoData buf;	int32		i;	pq_begintypsend(&buf);	pq_sendbyte(&buf, path->closed ? 1 : 0);	pq_sendint(&buf, path->npts, sizeof(int32));	for (i = 0; i < path->npts; i++)	{		pq_sendfloat8(&buf, path->p[i].x);		pq_sendfloat8(&buf, path->p[i].y);	}	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/*---------------------------------------------------------- *	Relational operators. *		These are based on the path cardinality, *		as stupid as that sounds. * *		Better relops and access methods coming soon. *---------------------------------------------------------*/Datumpath_n_lt(PG_FUNCTION_ARGS){	PATH	   *p1 = PG_GETARG_PATH_P(0);	PATH	   *p2 = PG_GETARG_PATH_P(1);	PG_RETURN_BOOL(p1->npts < p2->npts);}Datumpath_n_gt(PG_FUNCTION_ARGS){	PATH	   *p1 = PG_GETARG_PATH_P(0);	PATH	   *p2 = PG_GETARG_PATH_P(1);	PG_RETURN_BOOL(p1->npts > p2->npts);}Datumpath_n_eq(PG_FUNCTION_ARGS){	PATH	   *p1 = PG_GETARG_PATH_P(0);	PATH	   *p2 = PG_GETARG_PATH_P(1);	PG_RETURN_BOOL(p1->npts == p2->npts);}Datumpath_n_le(PG_FUNCTION_ARGS){	PATH	   *p1 = PG_GETARG_PATH_P(0);	PATH	   *p2 = PG_GETARG_PATH_P(1);	PG_RETURN_BOOL(p1->npts <= p2->npts);}Datumpath_n_ge(PG_FUNCTION_ARGS){	PATH	   *p1 = PG_GETARG_PATH_P(0);	PATH	   *p2 = PG_GETARG_PATH_P(1);	PG_RETURN_BOOL(p1->npts >= p2->npts);}/*---------------------------------------------------------- * Conversion operators. *---------------------------------------------------------*/Datumpath_isclosed(PG_FUNCTION_ARGS){	PATH	   *path = PG_GETARG_PATH_P(0);	PG_RETURN_BOOL(path->closed);}Datumpath_isopen(PG_FUNCTION_ARGS){	PATH	   *path = PG_GETARG_PATH_P(0);	PG_RETURN_BOOL(!path->closed);}Datumpath_npoints(PG_FUNCTION_ARGS){	PATH	   *path = PG_GETARG_PATH_P(0);	PG_RETURN_INT32(path->npts);}Datumpath_close(PG_FUNCTION_ARGS){	PATH	   *path = PG_GETARG_PATH_P_COPY(0);	path->closed = TRUE;	PG_RETURN_PATH_P(path);}Datumpath_open(PG_FUNCTION_ARGS){	PATH	   *path = PG_GETARG_PATH_P_COPY(0);	path->closed = FALSE;	PG_RETURN_PATH_P(path);}/* path_inter - *		Does p1 intersect p2 at any point? *		Use bounding boxes for a quick (O(n)) check, then do a *		O(n^2) iterative edge check. */Datumpath_inter(PG_FUNCTION_ARGS){	PATH	   *p1 = PG_GETARG_PATH_P(0);	PATH	   *p2 = PG_GETARG_PATH_P(1);	BOX			b1,				b2;	int			i,				j;	LSEG		seg1,				seg2;	if (p1->npts <= 0 || p2->npts <= 0)		PG_RETURN_BOOL(false);	b1.high.x = b1.low.x = p1->p[0].x;	b1.high.y = b1.low.y = p1->p[0].y;	for (i = 1; i < p1->npts; i++)	{		b1.high.x = Max(p1->p[i].x, b1.high.x);		b1.high.y = Max(p1->p[i].y, b1.high.y);		b1.low.x = Min(p1->p[i].x, b1.low.x);		b1.low.y = Min(p1->p[i].y, b1.low.y);	}	b2.high.x = b2.low.x = p2->p[0].x;	b2.high.y = b2.low.y = p2->p[0].y;	for (i = 1; i < p2->npts; i++)	{		b2.high.x = Max(p2->p[i].x, b2.high.x);		b2.high.y = Max(p2->p[i].y, b2.high.y);		b2.low.x = Min(p2->p[i].x, b2.low.x);		b2.low.y = Min(p2->p[i].y, b2.low.y);	}	if (!box_ov(&b1, &b2))		PG_RETURN_BOOL(false);	/* pairwise check lseg intersections */	for (i = 0; i < p1->npts; i++)	{		int			iprev;		if (i > 0)			iprev = i - 1;		else		{			if (!p1->closed)				continue;			iprev = p1->npts - 1;		/* include the closure segment */		}		for (j = 0; j < p2->npts; j++)		{			int			jprev;			if (j > 0)				jprev = j - 1;			else			{				if (!p2->closed)					continue;				jprev = p2->npts - 1;	/* include the closure segment */			}			statlseg_construct(&seg1, &p1->p[iprev], &p1->p[i]);			statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);			if (lseg_intersect_internal(&seg1, &seg2))				PG_RETURN_BOOL(true);		}	}	/* if we dropped through, no two segs intersected */	PG_RETURN_BOOL(false);}/* path_distance() * This essentially does a cartesian product of the lsegs in the *	two paths, and finds the min distance between any two lsegs */Datumpath_distance(PG_FUNCTION_ARGS){	PATH	   *p1 = PG_GETARG_PATH_P(0);	PATH	   *p2 = PG_GETARG_PATH_P(1);	float8		min = 0.0;		/* initialize to keep compiler quiet */	bool		have_min = false;	float8		tmp;	int			i,				j;	LSEG		seg1,				seg2;	for (i = 0; i < p1->npts; i++)	{		int			iprev;		if (i > 0)			iprev = i - 1;		else		{			if (!p1->closed)				continue;			iprev = p1->npts - 1;		/* include the closure segment */		}		for (j = 0; j < p2->npts; j++)		{			int			jprev;			if (j > 0)				jprev = j - 1;			else			{				if (!p2->closed)					continue;				jprev = p2->npts - 1;	/* include the closure segment */			}			statlseg_construct(&seg1, &p1->p[iprev], &p1->p[i]);			statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);			tmp = DatumGetFloat8(DirectFunctionCall2(lseg_distance,													 LsegPGetDatum(&seg1),													 LsegPGetDatum(&seg2)));			if (!have_min || tmp < min)			{				min = tmp;				have_min = true;			}		}	}	if (!have_min)		PG_RETURN_NULL();	PG_RETURN_FLOAT8(min);}/*---------------------------------------------------------- *	"Arithmetic" operations. *---------------------------------------------------------*/Datumpath_length(PG_FUNCTION_ARGS){	PATH	   *path = PG_GETARG_PATH_P(0);	float8		result = 0.0;	int			i;	for (i = 0; i < path->npts; i++)	{		int			iprev;		if (i > 0)			iprev = i - 1;		else		{			if (!path->closed)				continue;			iprev = path->npts - 1;		/* include the closure segment */		}		result += point_dt(&path->p[iprev], &path->p[i]);	}	PG_RETURN_FLOAT8(result);}/*********************************************************************** ** **		Routines for 2D points. ** ***********************************************************************//*---------------------------------------------------------- *	String to point, point to string conversion. *		External format: *				"(x,y)" *				"x,y" *---------------------------------------------------------*/Datumpoint_in(PG_FUNCTION_ARGS){	char	   *str = PG_GETARG_CSTRING(0);	Point	   *point;	double		x,				y;	char	   *s;	if (!pair_decode(str, &x, &y, &s) || (*s != '\0'))		ereport(ERROR,				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),				 errmsg("invalid input syntax for type point: \"%s\"", str)));	point = (Point *) palloc(sizeof(Point));	point->x = x;	point->y = y;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -