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

📄 geo_ops.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 5 页
字号:
	LSEG		lseg,				seg;	Point		point;	double		dist,			   *d;	if (on_pb(pt, box))		return pt;	/* pairwise check lseg distances */	point.x = box->low.x;	point.y = box->high.y;	statlseg_construct(&lseg, &box->low, &point);	dist = *(d = dist_ps(pt, &lseg));	pfree(d);	statlseg_construct(&seg, &box->high, &point);	if (*(d = dist_ps(pt, &seg)) < dist)	{		dist = *d;		memcpy(&lseg, &seg, sizeof(lseg));	}	pfree(d);	point.x = box->high.x;	point.y = box->low.y;	statlseg_construct(&seg, &box->low, &point);	if (*(d = dist_ps(pt, &seg)) < dist)	{		dist = *d;		memcpy(&lseg, &seg, sizeof(lseg));	}	pfree(d);	statlseg_construct(&seg, &box->high, &point);	if (*(d = dist_ps(pt, &seg)) < dist)	{		dist = *d;		memcpy(&lseg, &seg, sizeof(lseg));	}	pfree(d);	return close_ps(pt, &lseg);}	/* close_pb() *//* close_sl() * Closest point on line to line segment. * * XXX THIS CODE IS WRONG * The code is actually calculating the point on the line segment *	which is backwards from the routine naming convention. * Copied code to new routine close_ls() but haven't fixed this one yet. * - thomas 1998-01-31 */Point *close_sl(LSEG *lseg, LINE *line){	Point	   *result;	double	   *d1,			   *d2;	result = interpt_sl(lseg, line);	if (result)		return result;	d1 = dist_pl(&lseg->p[0], line);	d2 = dist_pl(&lseg->p[1], line);	if (d1 < d2)		result = point_copy(&lseg->p[0]);	else		result = point_copy(&lseg->p[1]);	pfree(d1);	pfree(d2);	return result;}/* close_ls() * Closest point on line segment to line. */Point *close_ls(LINE *line, LSEG *lseg){	Point	   *result;	double	   *d1,			   *d2;	result = interpt_sl(lseg, line);	if (result)		return result;	d1 = dist_pl(&lseg->p[0], line);	d2 = dist_pl(&lseg->p[1], line);	if (d1 < d2)		result = point_copy(&lseg->p[0]);	else		result = point_copy(&lseg->p[1]);	pfree(d1);	pfree(d2);	return result;}	/* close_ls() *//* close_sb() * Closest point on or in box to line segment. */Point *close_sb(LSEG *lseg, BOX *box){	Point	   *result;	Point	   *pt;	Point		point;	LSEG		bseg,				seg;	double		dist,				d;	/* segment intersects box? then just return closest point to center */	if (inter_sb(lseg, box))	{		pt = box_center(box);		result = close_ps(pt, lseg);		pfree(pt);		return result;	}	/* pairwise check lseg distances */	point.x = box->low.x;	point.y = box->high.y;	statlseg_construct(&bseg, &box->low, &point);	dist = lseg_dt(lseg, &bseg);	statlseg_construct(&seg, &box->high, &point);	if ((d = lseg_dt(lseg, &seg)) < dist)	{		dist = d;		memcpy(&bseg, &seg, sizeof(bseg));	}	point.x = box->high.x;	point.y = box->low.y;	statlseg_construct(&seg, &box->low, &point);	if ((d = lseg_dt(lseg, &seg)) < dist)	{		dist = d;		memcpy(&bseg, &seg, sizeof(bseg));	}	statlseg_construct(&seg, &box->high, &point);	if ((d = lseg_dt(lseg, &seg)) < dist)	{		dist = d;		memcpy(&bseg, &seg, sizeof(bseg));	}	/* OK, we now have the closest line segment on the box boundary */	return close_lseg(lseg, &bseg);}	/* close_sb() */Point *close_lb(LINE *line, BOX *box){	/* think about this one for a while */	elog(ERROR, "close_lb not implemented", NULL);	return NULL;}/*--------------------------------------------------------------------- *		on_ *				Whether one object lies completely within another. *-------------------------------------------------------------------*//* on_pl - *		Does the point satisfy the equation? */boolon_pl(Point *pt, LINE *line){	if (!PointerIsValid(pt) || !PointerIsValid(line))		return FALSE;	return FPzero(line->A * pt->x + line->B * pt->y + line->C);}/* on_ps - *		Determine colinearity by detecting a triangle inequality. * This algorithm seems to behave nicely even with lsb residues - tgl 1997-07-09 */boolon_ps(Point *pt, LSEG *lseg){	if (!PointerIsValid(pt) || !PointerIsValid(lseg))		return FALSE;	return (FPeq(point_dt(pt, &lseg->p[0]) + point_dt(pt, &lseg->p[1]),				 point_dt(&lseg->p[0], &lseg->p[1])));}boolon_pb(Point *pt, BOX *box){	if (!PointerIsValid(pt) || !PointerIsValid(box))		return FALSE;	return (pt->x <= box->high.x && pt->x >= box->low.x &&			pt->y <= box->high.y && pt->y >= box->low.y);}/* on_ppath - *		Whether a point lies within (on) a polyline. *		If open, we have to (groan) check each segment. * (uses same algorithm as for point intersecting segment - tgl 1997-07-09) *		If closed, we use the old O(n) ray method for point-in-polygon. *				The ray is horizontal, from pt out to the right. *				Each segment that crosses the ray counts as an *				intersection; note that an endpoint or edge may touch *				but not cross. *				(we can do p-in-p in lg(n), but it takes preprocessing) */#define NEXT(A) ((A+1) % path->npts)	/* cyclic "i+1" */boolon_ppath(Point *pt, PATH *path){	int			i,				n;	double		a,				b;	if (!PointerIsValid(pt) || !PointerIsValid(path))		return FALSE;	/*-- OPEN --*/	if (!path->closed)	{		n = path->npts - 1;		a = point_dt(pt, &path->p[0]);		for (i = 0; i < n; i++)		{			b = point_dt(pt, &path->p[i + 1]);			if (FPeq(a + b,					 point_dt(&path->p[i], &path->p[i + 1])))				return TRUE;			a = b;		}		return FALSE;	}	/*-- CLOSED --*/	return point_inside(pt, path->npts, path->p);}	/* on_ppath() */boolon_sl(LSEG *lseg, LINE *line){	if (!PointerIsValid(lseg) || !PointerIsValid(line))		return FALSE;	return on_pl(&lseg->p[0], line) && on_pl(&lseg->p[1], line);}	/* on_sl() */boolon_sb(LSEG *lseg, BOX *box){	if (!PointerIsValid(lseg) || !PointerIsValid(box))		return FALSE;	return on_pb(&lseg->p[0], box) && on_pb(&lseg->p[1], box);}	/* on_sb() *//*--------------------------------------------------------------------- *		inter_ *				Whether one object intersects another. *-------------------------------------------------------------------*/boolinter_sl(LSEG *lseg, LINE *line){	Point	   *tmp;	if (!PointerIsValid(lseg) || !PointerIsValid(line))		return FALSE;	tmp = interpt_sl(lseg, line);	if (tmp)	{		pfree(tmp);		return TRUE;	}	return FALSE;}/* inter_sb() * Do line segment and box intersect? * * Segment completely inside box counts as intersection. * If you want only segments crossing box boundaries, *	try converting box to path first. * * Optimize for non-intersection by checking for box intersection first. * - thomas 1998-01-30 */boolinter_sb(LSEG *lseg, BOX *box){	BOX			lbox;	LSEG		bseg;	Point		point;	if (!PointerIsValid(lseg) || !PointerIsValid(box))		return FALSE;	lbox.low.x = Min(lseg->p[0].x, lseg->p[1].x);	lbox.low.y = Min(lseg->p[0].y, lseg->p[1].y);	lbox.high.x = Max(lseg->p[0].x, lseg->p[1].x);	lbox.high.y = Max(lseg->p[0].y, lseg->p[1].y);	/* nothing close to overlap? then not going to intersect */	if (!box_overlap(&lbox, box))		return FALSE;	/* an endpoint of segment is inside box? then clearly intersects */	if (on_pb(&lseg->p[0], box) || on_pb(&lseg->p[1], box))		return TRUE;	/* pairwise check lseg intersections */	point.x = box->low.x;	point.y = box->high.y;	statlseg_construct(&bseg, &box->low, &point);	if (lseg_intersect(&bseg, lseg))		return TRUE;	statlseg_construct(&bseg, &box->high, &point);	if (lseg_intersect(&bseg, lseg))		return TRUE;	point.x = box->high.x;	point.y = box->low.y;	statlseg_construct(&bseg, &box->low, &point);	if (lseg_intersect(&bseg, lseg))		return TRUE;	statlseg_construct(&bseg, &box->high, &point);	if (lseg_intersect(&bseg, lseg))		return TRUE;	/* if we dropped through, no two segs intersected */	return FALSE;}	/* inter_sb() *//* inter_lb() * Do line and box intersect? */boolinter_lb(LINE *line, BOX *box){	LSEG		bseg;	Point		p1,				p2;	if (!PointerIsValid(line) || !PointerIsValid(box))		return FALSE;	/* pairwise check lseg intersections */	p1.x = box->low.x;	p1.y = box->low.y;	p2.x = box->low.x;	p2.y = box->high.y;	statlseg_construct(&bseg, &p1, &p2);	if (inter_sl(&bseg, line))		return TRUE;	p1.x = box->high.x;	p1.y = box->high.y;	statlseg_construct(&bseg, &p1, &p2);	if (inter_sl(&bseg, line))		return TRUE;	p2.x = box->high.x;	p2.y = box->low.y;	statlseg_construct(&bseg, &p1, &p2);	if (inter_sl(&bseg, line))		return TRUE;	p1.x = box->low.x;	p1.y = box->low.y;	statlseg_construct(&bseg, &p1, &p2);	if (inter_sl(&bseg, line))		return TRUE;	/* if we dropped through, no intersection */	return FALSE;}/*------------------------------------------------------------------ * The following routines define a data type and operator class for * POLYGONS .... Part of which (the polygon's bounding box) is built on * top of the BOX data type. * * make_bound_box - create the bounding box for the input polygon *------------------------------------------------------------------*//*--------------------------------------------------------------------- * Make the smallest bounding box for the given polygon. *---------------------------------------------------------------------*/static voidmake_bound_box(POLYGON *poly){	int			i;	double		x1,				y1,				x2,				y2;	if (poly->npts > 0)	{		x2 = x1 = poly->p[0].x;		y2 = y1 = poly->p[0].y;		for (i = 1; i < poly->npts; i++)		{			if (poly->p[i].x < x1)				x1 = poly->p[i].x;			if (poly->p[i].x > x2)				x2 = poly->p[i].x;			if (poly->p[i].y < y1)				y1 = poly->p[i].y;			if (poly->p[i].y > y2)				y2 = poly->p[i].y;		}		box_fill(&(poly->boundbox), x1, x2, y1, y2);	}	else		elog(ERROR, "Unable to create bounding box for empty polygon", NULL);}/*------------------------------------------------------------------ * poly_in - read in the polygon from a string specification * *		External format: *				"((x0,y0),...,(xn,yn))" *				"x0,y0,...,xn,yn" *				also supports the older style "(x1,...,xn,y1,...yn)" *------------------------------------------------------------------*/POLYGON    *poly_in(char *str){	POLYGON    *poly;	int			npts;	int			size;	int			isopen;	char	   *s;	if (!PointerIsValid(str))		elog(ERROR, " Bad (null) polygon external representation");	if ((npts = pair_count(str, ',')) <= 0)		elog(ERROR, "Bad polygon external representation '%s'", str);	size = offsetof(POLYGON, p[0]) +(sizeof(poly->p[0]) * npts);	poly = palloc(size);	MemSet((char *) poly, 0, size);		/* zero any holes */	poly->size = size;	poly->npts = npts;	if ((!path_decode(FALSE, npts, str, &isopen, &s, &(poly->p[0])))		|| (*s != '\0'))		elog(ERROR, "Bad polygon external representation '%s'", str);	make_bound_box(poly);	return poly;}	/* poly_in() *//*--------------------------------------------------------------- * poly_out - convert internal POLYGON representation to the *			  character string format "((f8,f8),...,(f8,f8))" *			  also support old format "(f8,f8,...,f8,f8)" *---------------------------------------------------------------*/char *poly_out(POLYGON *poly){	if (!PointerIsValid(poly))		return NULL;	return path_encode(TRUE, poly->npts, &(poly->p[0]));}	/* poly_out() *//*------------------------------------------------------- * Is polygon A strictly left of polygon B? i.e. is * the right most point of A left of the left most point * of B? *-------------------------------------------------------*/boolpoly_left(POLYGON *polya, POLYGON *polyb){	return polya->boundbox.high.x < polyb->boundbox.low.x;}/*------------------------------------------------------- * Is polygon A overlapping or left of polygon B? i.e. is * the left most point of A left of the right most point * of B? *-------------------------------------------------------*/boolpoly_overleft(POLYGON *polya, POLYGON *polyb){	return polya->boundbox.low.x <= polyb->boundbox.high.x;}/*------------------------------------------------------- * Is polygon A strictly right of polygon B? i.e. is * the left most point of A right of the right most point * of B? *-------------------------------------------------------*/boolpoly_right(POLYGON *polya, POLYGON *polyb){	return polya->boundbox.low.x > polyb->boundbox.high.x;}/*------------------------------------------------------- * Is polygon A overlapping or right of polygon B? i.e. is * the right most point of A right of the left most point * of B? *-------------------------------------------------------*/boolpoly_overright(POLYGON *polya, POLYGON *polyb){	return polya->boundbox.high.x > polyb->boundbox.low.x;}/*------------------------------------------------------- * Is polygon A the same as polygon B? i.e. are all the * points the same? * Check all points for matches in both forward and reverse *	direction since polygons are non-directional and are *	closed shapes. *-------------------------------------------------------*/boolpoly_same(POLYGON *polya, POLYGON *polyb){	if (!PointerIsValid(polya) || !PointerIsValid(polyb))		return FALSE;	if (polya->npts != polyb->npts)		return FALSE;	return plist_same(polya->npts, polya->p, polyb->p);#ifdef NOT_USED	for (i = 0; i < polya->npts; i++)	{		if ((polya->p[i].x != polyb->p[i].x)			|| (polya->p[i].y != polyb->p[i].y))			return FALSE;	}	return TRUE;#endif}	/* poly_same() *//*----------------------------------------------------------------- * Determine if polygon A overlaps polygon B by determining if * their bounding boxes overlap. *-----------------------------------------------------------------*/boolpoly_overlap(POLYGON *polya, POLYGON *polyb){	return box_overlap(&(polya->boundbox), &(polyb->boundbox));}/*----------------------------------------------------------------- * Determine if polygon A contains polygon B by determining if A's * bounding box contains B's bounding box. *-----------------------------------------------------------------*/#ifdef NOT_USEDboolpoly_contain(POLYGON *polya, POLYGON *polyb){	return box_contain(&(polya->boundbox), &(polyb->boundbox));}#endifboolpoly_contain(POLYGON *polya, POLYGON *polyb){	int			i;	if (!PointerIsValid(polya) || !PointerIsValid(polyb))		return FALSE;	if (box_contain(&(polya->boundbox), &(polyb->boundbox)))	{		for (i = 0; i < polyb->npts; i++)		{			if (point_inside(&(polyb->p[i]), polya->npts, &(polya->p[0])) == 0)			{#if GEODEBUG				printf("poly_contain- point (%f,%f) not in polygon\n", polyb->p[i].x, polyb->p[i].y);#endif				return FALSE;			}		}		for (i = 0; i < polya->npts; i++)		{			if (point_inside(&(polya->p[i]), polyb->npts, &(polyb->p[0])) == 1)			{#if GEODEBUG				printf("poly_contain- point (%f,%f) in polygon\n", polya->p[i].x, polya->p[i].y);#endif				return FALSE;			}		}		return TRUE;	}#if GEODEBUG	printf("poly_contain- bound box ((%f,%f),(%f,%f)) not insid

⌨️ 快捷键说明

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