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

📄 geo_ops.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * geo_ops.c *	  2D geometric operations * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.91 2005/10/15 02:49:28 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <math.h>#include <limits.h>#include <float.h>#include <ctype.h>#include "libpq/pqformat.h"#include "utils/builtins.h"#include "utils/geo_decls.h"#ifndef M_PI#define M_PI 3.14159265358979323846#endif/* * Internal routines */static int	point_inside(Point *p, int npts, Point *plist);static int	lseg_crossing(double x, double y, double px, double py);static BOX *box_construct(double x1, double x2, double y1, double y2);static BOX *box_copy(BOX *box);static BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2);static bool box_ov(BOX *box1, BOX *box2);static double box_ht(BOX *box);static double box_wd(BOX *box);static double circle_ar(CIRCLE *circle);static CIRCLE *circle_copy(CIRCLE *circle);static LINE *line_construct_pm(Point *pt, double m);static void line_construct_pts(LINE *line, Point *pt1, Point *pt2);static bool lseg_intersect_internal(LSEG *l1, LSEG *l2);static double lseg_dt(LSEG *l1, LSEG *l2);static bool on_ps_internal(Point *pt, LSEG *lseg);static void make_bound_box(POLYGON *poly);static bool plist_same(int npts, Point *p1, Point *p2);static Point *point_construct(double x, double y);static Point *point_copy(Point *pt);static int	single_decode(char *str, float8 *x, char **ss);static int	single_encode(float8 x, char *str);static int	pair_decode(char *str, float8 *x, float8 *y, char **s);static int	pair_encode(float8 x, float8 y, char *str);static int	pair_count(char *s, char delim);static int	path_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p);static char *path_encode(bool closed, int npts, Point *pt);static void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2);static double box_ar(BOX *box);static void box_cn(Point *center, BOX *box);static Point *interpt_sl(LSEG *lseg, LINE *line);static bool has_interpt_sl(LSEG *lseg, LINE *line);static double dist_pl_internal(Point *pt, LINE *line);static double dist_ps_internal(Point *pt, LSEG *lseg);static Point *line_interpt_internal(LINE *l1, LINE *l2);/* * Delimiters for input and output strings. * LDELIM, RDELIM, and DELIM are left, right, and separator delimiters, respectively. * LDELIM_EP, RDELIM_EP are left and right delimiters for paths with endpoints. */#define LDELIM			'('#define RDELIM			')'#define DELIM			','#define LDELIM_EP		'['#define RDELIM_EP		']'#define LDELIM_C		'<'#define RDELIM_C		'>'/* Maximum number of characters printed by pair_encode() *//* ...+2+7 : 2 accounts for extra_float_digits max value */#define P_MAXLEN (2*(DBL_DIG+2+7)+1)/* * Geometric data types are composed of points. * This code tries to support a common format throughout the data types, *	to allow for more predictable usage and data type conversion. * The fundamental unit is the point. Other units are line segments, *	open paths, boxes, closed paths, and polygons (which should be considered *	non-intersecting closed paths). * * Data representation is as follows: *	point:				(x,y) *	line segment:		[(x1,y1),(x2,y2)] *	box:				(x1,y1),(x2,y2) *	open path:			[(x1,y1),...,(xn,yn)] *	closed path:		((x1,y1),...,(xn,yn)) *	polygon:			((x1,y1),...,(xn,yn)) * * For boxes, the points are opposite corners with the first point at the top right. * For closed paths and polygons, the points should be reordered to allow *	fast and correct equality comparisons. * * XXX perhaps points in complex shapes should be reordered internally *	to allow faster internal operations, but should keep track of input order *	and restore that order for text output - tgl 97/01/16 */static intsingle_decode(char *str, float8 *x, char **s){	char	   *cp;	if (!PointerIsValid(str))		return FALSE;	while (isspace((unsigned char) *str))		str++;	*x = strtod(str, &cp);#ifdef GEODEBUG	printf("single_decode- (%x) try decoding %s to %g\n", (cp - str), str, *x);#endif	if (cp <= str)		return FALSE;	while (isspace((unsigned char) *cp))		cp++;	if (s != NULL)		*s = cp;	return TRUE;}	/* single_decode() */static intsingle_encode(float8 x, char *str){	int			ndig = DBL_DIG + extra_float_digits;	if (ndig < 1)		ndig = 1;	sprintf(str, "%.*g", ndig, x);	return TRUE;}	/* single_encode() */static intpair_decode(char *str, float8 *x, float8 *y, char **s){	int			has_delim;	char	   *cp;	if (!PointerIsValid(str))		return FALSE;	while (isspace((unsigned char) *str))		str++;	if ((has_delim = (*str == LDELIM)))		str++;	while (isspace((unsigned char) *str))		str++;	*x = strtod(str, &cp);	if (cp <= str)		return FALSE;	while (isspace((unsigned char) *cp))		cp++;	if (*cp++ != DELIM)		return FALSE;	while (isspace((unsigned char) *cp))		cp++;	*y = strtod(cp, &str);	if (str <= cp)		return FALSE;	while (isspace((unsigned char) *str))		str++;	if (has_delim)	{		if (*str != RDELIM)			return FALSE;		str++;		while (isspace((unsigned char) *str))			str++;	}	if (s != NULL)		*s = str;	return TRUE;}static intpair_encode(float8 x, float8 y, char *str){	int			ndig = DBL_DIG + extra_float_digits;	if (ndig < 1)		ndig = 1;	sprintf(str, "%.*g,%.*g", ndig, x, ndig, y);	return TRUE;}static intpath_decode(int opentype, int npts, char *str, int *isopen, char **ss, Point *p){	int			depth = 0;	char	   *s,			   *cp;	int			i;	s = str;	while (isspace((unsigned char) *s))		s++;	if ((*isopen = (*s == LDELIM_EP)))	{		/* no open delimiter allowed? */		if (!opentype)			return FALSE;		depth++;		s++;		while (isspace((unsigned char) *s))			s++;	}	else if (*s == LDELIM)	{		cp = (s + 1);		while (isspace((unsigned char) *cp))			cp++;		if (*cp == LDELIM)		{#ifdef NOT_USED			/* nested delimiters with only one point? */			if (npts <= 1)				return FALSE;#endif			depth++;			s = cp;		}		else if (strrchr(s, LDELIM) == s)		{			depth++;			s = cp;		}	}	for (i = 0; i < npts; i++)	{		if (!pair_decode(s, &(p->x), &(p->y), &s))			return FALSE;		if (*s == DELIM)			s++;		p++;	}	while (depth > 0)	{		if ((*s == RDELIM)			|| ((*s == RDELIM_EP) && (*isopen) && (depth == 1)))		{			depth--;			s++;			while (isspace((unsigned char) *s))				s++;		}		else			return FALSE;	}	*ss = s;	return TRUE;}	/* path_decode() */static char *path_encode(bool closed, int npts, Point *pt){	int			size = npts * (P_MAXLEN + 3) + 2;	char	   *result;	char	   *cp;	int			i;	/* Check for integer overflow */	if ((size - 2) / npts != (P_MAXLEN + 3))		ereport(ERROR,				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),				 errmsg("too many points requested")));	result = palloc(size);	cp = result;	switch (closed)	{		case TRUE:			*cp++ = LDELIM;			break;		case FALSE:			*cp++ = LDELIM_EP;			break;		default:			break;	}	for (i = 0; i < npts; i++)	{		*cp++ = LDELIM;		if (!pair_encode(pt->x, pt->y, cp))			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("could not format \"path\" value")));		cp += strlen(cp);		*cp++ = RDELIM;		*cp++ = DELIM;		pt++;	}	cp--;	switch (closed)	{		case TRUE:			*cp++ = RDELIM;			break;		case FALSE:			*cp++ = RDELIM_EP;			break;		default:			break;	}	*cp = '\0';	return result;}	/* path_encode() *//*------------------------------------------------------------- * pair_count - count the number of points * allow the following notation: * '((1,2),(3,4))' * '(1,3,2,4)' * require an odd number of delim characters in the string *-------------------------------------------------------------*/static intpair_count(char *s, char delim){	int			ndelim = 0;	while ((s = strchr(s, delim)) != NULL)	{		ndelim++;		s++;	}	return (ndelim % 2) ? ((ndelim + 1) / 2) : -1;}/*********************************************************************** ** **		Routines for two-dimensional boxes. ** ***********************************************************************//*---------------------------------------------------------- * Formatting and conversion routines. *---------------------------------------------------------*//*		box_in	-		convert a string to internal form. * *		External format: (two corners of box) *				"(f8, f8), (f8, f8)" *				also supports the older style "(f8, f8, f8, f8)" */Datumbox_in(PG_FUNCTION_ARGS){	char	   *str = PG_GETARG_CSTRING(0);	BOX		   *box = (BOX *) palloc(sizeof(BOX));	int			isopen;	char	   *s;	double		x,				y;	if ((!path_decode(FALSE, 2, str, &isopen, &s, &(box->high)))		|| (*s != '\0'))		ereport(ERROR,				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),				 errmsg("invalid input syntax for type box: \"%s\"", str)));	/* reorder corners if necessary... */	if (box->high.x < box->low.x)	{		x = box->high.x;		box->high.x = box->low.x;		box->low.x = x;	}	if (box->high.y < box->low.y)	{		y = box->high.y;		box->high.y = box->low.y;		box->low.y = y;	}	PG_RETURN_BOX_P(box);}/*		box_out -		convert a box to external form. */Datumbox_out(PG_FUNCTION_ARGS){	BOX		   *box = PG_GETARG_BOX_P(0);	PG_RETURN_CSTRING(path_encode(-1, 2, &(box->high)));}/* *		box_recv			- converts external binary format to box */Datumbox_recv(PG_FUNCTION_ARGS){	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);	BOX		   *box;	double		x,				y;	box = (BOX *) palloc(sizeof(BOX));	box->high.x = pq_getmsgfloat8(buf);	box->high.y = pq_getmsgfloat8(buf);	box->low.x = pq_getmsgfloat8(buf);	box->low.y = pq_getmsgfloat8(buf);	/* reorder corners if necessary... */	if (box->high.x < box->low.x)	{		x = box->high.x;		box->high.x = box->low.x;		box->low.x = x;	}	if (box->high.y < box->low.y)	{		y = box->high.y;		box->high.y = box->low.y;		box->low.y = y;	}	PG_RETURN_BOX_P(box);}/* *		box_send			- converts box to binary format */Datumbox_send(PG_FUNCTION_ARGS){	BOX		   *box = PG_GETARG_BOX_P(0);	StringInfoData buf;	pq_begintypsend(&buf);	pq_sendfloat8(&buf, box->high.x);	pq_sendfloat8(&buf, box->high.y);	pq_sendfloat8(&buf, box->low.x);	pq_sendfloat8(&buf, box->low.y);	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/*		box_construct	-		fill in a new box. */static BOX *box_construct(double x1, double x2, double y1, double y2){	BOX		   *result = (BOX *) palloc(sizeof(BOX));	return box_fill(result, x1, x2, y1, y2);}/*		box_fill		-		fill in a given box struct */static BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2){	if (x1 > x2)	{		result->high.x = x1;		result->low.x = x2;	}	else	{		result->high.x = x2;		result->low.x = x1;	}	if (y1 > y2)	{		result->high.y = y1;		result->low.y = y2;	}	else	{		result->high.y = y2;		result->low.y = y1;	}	return result;}/*		box_copy		-		copy a box */static BOX *box_copy(BOX *box){	BOX		   *result = (BOX *) palloc(sizeof(BOX));	memcpy((char *) result, (char *) box, sizeof(BOX));	return result;}/*---------------------------------------------------------- *	Relational operators for BOXes. *		<, >, <=, >=, and == are based on box area. *---------------------------------------------------------*//*		box_same		-		are two boxes identical? */Datumbox_same(PG_FUNCTION_ARGS){	BOX		   *box1 = PG_GETARG_BOX_P(0);	BOX		   *box2 = PG_GETARG_BOX_P(1);	PG_RETURN_BOOL(FPeq(box1->high.x, box2->high.x) &&				   FPeq(box1->low.x, box2->low.x) &&				   FPeq(box1->high.y, box2->high.y) &&				   FPeq(box1->low.y, box2->low.y));}/*		box_overlap		-		does box1 overlap box2? */Datumbox_overlap(PG_FUNCTION_ARGS){	BOX		   *box1 = PG_GETARG_BOX_P(0);	BOX		   *box2 = PG_GETARG_BOX_P(1);	PG_RETURN_BOOL(box_ov(box1, box2));}static boolbox_ov(BOX *box1, BOX *box2){	return ((FPge(box1->high.x, box2->high.x) &&			 FPle(box1->low.x, box2->high.x)) ||			(FPge(box2->high.x, box1->high.x) &&			 FPle(box2->low.x, box1->high.x)))		&&		((FPge(box1->high.y, box2->high.y) &&		  FPle(box1->low.y, box2->high.y)) ||		 (FPge(box2->high.y, box1->high.y) &&		  FPle(box2->low.y, box1->high.y)));}/*		box_left		-		is box1 strictly left of box2? */Datumbox_left(PG_FUNCTION_ARGS){	BOX		   *box1 = PG_GETARG_BOX_P(0);	BOX		   *box2 = PG_GETARG_BOX_P(1);	PG_RETURN_BOOL(FPlt(box1->high.x, box2->low.x));}/*		box_overleft	-		is the right edge of box1 at or left of *								the right edge of box2? * *		This is "less than or equal" for the end of a time range, *		when time ranges are stored as rectangles. */Datumbox_overleft(PG_FUNCTION_ARGS){	BOX		   *box1 = PG_GETARG_BOX_P(0);	BOX		   *box2 = PG_GETARG_BOX_P(1);	PG_RETURN_BOOL(FPle(box1->high.x, box2->high.x));}/*		box_right		-		is box1 strictly right of box2? */Datumbox_right(PG_FUNCTION_ARGS){	BOX		   *box1 = PG_GETARG_BOX_P(0);	BOX		   *box2 = PG_GETARG_BOX_P(1);

⌨️ 快捷键说明

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