예제 #1
0
/**
* Returns LW_TRUE if b is on the arc formed by a1/a2/a3, but not within
* that portion already described by a1/a2/a3
*/
static int pt_continues_arc(const POINT4D *a1, const POINT4D *a2, const POINT4D *a3, const POINT4D *b)
{
	POINT4D center;
	POINT4D *centerptr=&center;
	double radius = lwcircle_center(a1, a2, a3, &center);
	double b_distance, diff;

	/* Co-linear a1/a2/a3 */
	if ( radius < 0.0 )
		return LW_FALSE;

	b_distance = distance2d_pt_pt((POINT2D*)b, (POINT2D*)centerptr);
	diff = fabs(radius - b_distance);
	LWDEBUGF(4, "circle_radius=%g, b_distance=%g, diff=%g, percentage=%g", radius, b_distance, diff, diff/radius);
	
	/* Is the point b on the circle? */
	if ( diff < EPSILON_SQLMM ) 
	{
		int a2_side = signum(lw_segment_side((POINT2D*)a1, (POINT2D*)a3, (POINT2D*)a2));
		int b_side = signum(lw_segment_side((POINT2D*)a1, (POINT2D*)a3, (POINT2D*)b));
		
		/* Is the point b on the same side of a1/a3 as the mid-point a2 is? */
		/* If not, it's in the unbounded part of the circle, so it continues the arc, return true. */
		if ( b_side != a2_side )
			return LW_TRUE;
	}
	return LW_FALSE;
}
예제 #2
0
static POINTARRAY *
lwcircle_segmentize(POINT4D *p1, POINT4D *p2, POINT4D *p3, uint32_t perQuad)
{
	POINT4D center;
	POINT4D pt;
	int p2_side = 0;
	int clockwise = LW_TRUE;
	double radius; /* Arc radius */
	double increment; /* Angle per segment */
	double a1, a2, a3, angle;
	POINTARRAY *pa;
	int result;
	int is_circle = LW_FALSE;

	LWDEBUG(2, "lwcircle_calculate_gbox called.");

	radius = lwcircle_center(p1, p2, p3, &center);
	p2_side = signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, (POINT2D*)p2));

	/* Matched start/end points imply circle */
	if ( p1->x == p3->x && p1->y == p3->y )
		is_circle = LW_TRUE;
	
	/* Negative radius signals straight line, p1/p2/p3 are colinear */
	if ( radius < 0.0 || p2_side == 0 )
	    return NULL;
		
	/* The side of the p1/p3 line that p2 falls on dictates the sweep  
	   direction from p1 to p3. */
	if ( p2_side == -1 )
		clockwise = LW_TRUE;
	else
		clockwise = LW_FALSE;
		
	increment = fabs(M_PI_2 / perQuad);
	
	/* Angles of each point that defines the arc section */
	a1 = atan2(p1->y - center.y, p1->x - center.x);
	a2 = atan2(p2->y - center.y, p2->x - center.x);
	a3 = atan2(p3->y - center.y, p3->x - center.x);

	/* p2 on left side => clockwise sweep */
	if ( clockwise )
	{
		increment *= -1;
		/* Adjust a3 down so we can decrement from a1 to a3 cleanly */
		if ( a3 > a1 )
			a3 -= 2.0 * M_PI;
		if ( a2 > a1 )
			a2 -= 2.0 * M_PI;
	}
	/* p2 on right side => counter-clockwise sweep */
	else
	{
		/* Adjust a3 up so we can increment from a1 to a3 cleanly */
		if ( a3 < a1 )
			a3 += 2.0 * M_PI;
		if ( a2 < a1 )
			a2 += 2.0 * M_PI;
	}
	
	/* Override angles for circle case */
	if( is_circle )
	{
		a3 = a1 + 2.0 * M_PI;
		a2 = a1 + M_PI;
		increment = fabs(increment);
		clockwise = LW_FALSE;
	}
	
	/* Initialize point array */
	pa = ptarray_construct_empty(1, 1, 32);

	/* Sweep from a1 to a3 */
	for ( angle = a1; clockwise ? angle > a3 : angle < a3; angle += increment ) 
	{
		pt.x = center.x + radius * cos(angle);
		pt.y = center.y + radius * sin(angle);
		pt.z = interpolate_arc(angle, a1, a2, a3, p1->z, p2->z, p3->z);
		pt.m = interpolate_arc(angle, a1, a2, a3, p1->m, p2->m, p3->m);
		result = ptarray_append_point(pa, &pt, LW_FALSE);
	}	
	return pa;
}
예제 #3
0
BOX3D *
lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
{
	double x1, x2, y1, y2, z1, z2;
	double angle, radius, sweep;
	/* angles from center */
	double a1, a2, a3;
	/* angles from center once a1 is rotated to zero */
	double r2, r3;
	double xe = 0.0, ye = 0.0;
	POINT4D *center;
	int i;
	BOX3D *box;

	LWDEBUG(2, "lwcircle_compute_box3d called.");

	radius = lwcircle_center(p1, p2, p3, &center);
	if (radius < 0.0) 
	{
		LWDEBUG(3, "lwcircle_compute_box3d: zero radius");

		/* 
		 * We've got a straight line here.  Look to the end points for extents. 
		 * It's worth noting that when lwcircle_center returns < 0, center hasn't been allocated.
		 */

		x1 = (FP_LT(p1->x, p3->x)) ? p1->x : p3->x;
		x2 = (FP_GT(p1->x, p3->x)) ? p1->x : p3->x;
		y1 = (FP_LT(p1->y, p3->y)) ? p1->y : p3->y;
		y2 = (FP_GT(p1->y, p3->y)) ? p1->y : p3->y;
		z1 = (FP_LT(p1->z, p2->z)) ? p1->z : p2->z;
		z1 = (FP_LT(z1, p3->z)) ? z1 : p3->z;
		z2 = (FP_GT(p1->z, p2->z)) ? p1->z : p2->z;
		z2 = (FP_GT(z2, p3->z)) ? z2 : p3->z;

		box = lwalloc(sizeof(BOX3D));
		box->xmin = x1;
		box->xmax = x2;
		box->ymin = y1;
		box->ymax = y2;
		box->zmin = z1;
		box->zmax = z2;

		LWDEBUGF(3, "lwcircle_compute_box3d: extents %.16f %.16f %.16f, %.16f %.16f %.16f", x1, y1, z1, x2, y2, z2);

		return box;
	}

	/*
	top = center->y + radius;
	left = center->x - radius;

	LWDEBUGF(3, "lwcircle_compute_box3d: center (%.16f, %.16f)", center->x, center->y);
	*/

	x1 = MAXFLOAT;
	x2 = -1 * MAXFLOAT;
	y1 = MAXFLOAT;
	y2 = -1 * MAXFLOAT;

	a1 = atan2(p1->y - center->y, p1->x - center->x);
	a2 = atan2(p2->y - center->y, p2->x - center->x);
	a3 = atan2(p3->y - center->y, p3->x - center->x);

	/* Rotate a2 and a3 such that a1 = 0 */
	r2 = a2 - a1;
	r3 = a3 - a1;

	LWDEBUGF(4, "a1 %.16f, a2 %.16f, a3 %.16f", a1, a2, a3);
	LWDEBUGF(4, "r2 %.16f, r3 %.16f", r2, r3);

	/*
	 * There are six cases here I'm interested in
	 * Clockwise:
	 *   1. a1-a2 < 180 == r2 < 0 && (r3 > 0 || r3 < r2)
	 *   2. a1-a2 > 180 == r2 > 0 && (r3 > 0 && r3 < r2)
	 *   3. a1-a2 > 180 == r2 > 0 && (r3 > r2 || r3 < 0)
	 * Counter-clockwise:
	 *   4. a1-a2 < 180 == r2 > 0 && (r3 < 0 || r3 > r2)
	 *   5. a1-a2 > 180 == r2 < 0 && (r3 < 0 && r3 > r2)
	 *   6. a1-a2 > 180 == r2 < 0 && (r3 < r2 || r3 > 0)
	 * 3 and 6 are invalid cases where a3 is the midpoint.
	 * BBOX is fundamental, so these cannot error out and will instead
	 * calculate the sweep using a3 as the middle point.
	 */

	/* clockwise 1 */
	if (FP_LT(r2, 0) && (FP_GT(r3, 0) || FP_LT(r3, r2)))
	{
		sweep = (FP_GT(r3, 0)) ? (r3 - 2 * M_PI) : r3;
	}
	/* clockwise 2 */
	else if (FP_GT(r2, 0) && FP_GT(r3, 0) && FP_LT(r3, r2))
	{
		sweep = (FP_GT(r3, 0)) ? (r3 - 2 * M_PI) : r3;
	}
	/* counter-clockwise 4 */
	else if (FP_GT(r2, 0) && (FP_LT(r3, 0) || FP_GT(r3, r2)))
	{
		sweep = (FP_LT(r3, 0)) ? (r3 + 2 * M_PI) : r3;
	}
	/* counter-clockwise 5 */
	else if (FP_LT(r2, 0) && FP_LT(r3, 0) && FP_GT(r3, r2))
	{
		sweep = (FP_LT(r3, 0)) ? (r3 + 2 * M_PI) : r3;
	}
	/* clockwise invalid 3 */
	else if (FP_GT(r2, 0) && (FP_GT(r3, r2) || FP_LT(r3, 0)))
	{
		sweep = (FP_GT(r2, 0)) ? (r2 - 2 * M_PI) : r2;
	}
	/* clockwise invalid 6 */
	else
	{
		sweep = (FP_LT(r2, 0)) ? (r2 + 2 * M_PI) : r2;
	}

	LWDEBUGF(3, "a1 %.16f, a2 %.16f, a3 %.16f, sweep %.16f", a1, a2, a3, sweep);

	angle = 0.0;
	for (i=0; i < 6; i++)
	{
		switch (i)
		{
			/* right extent */
		case 0:
			angle = 0.0;
			xe = center->x + radius;
			ye = center->y;
			break;
			/* top extent */
		case 1:
			angle = M_PI_2;
			xe = center->x;
			ye = center->y + radius;
			break;
			/* left extent */
		case 2:
			angle = M_PI;
			xe = center->x - radius;
			ye = center->y;
			break;
			/* bottom extent */
		case 3:
			angle = -1 * M_PI_2;
			xe = center->x;
			ye = center->y - radius;
			break;
			/* first point */
		case 4:
			angle = a1;
			xe = p1->x;
			ye = p1->y;
			break;
			/* last point */
		case 5:
			angle = a3;
			xe = p3->x;
			ye = p3->y;
			break;
		}
		/* determine if the extents are outside the arc */
		if (i < 4)
		{
			if (FP_GT(sweep, 0.0))
			{
				if (FP_LT(a3, a1))
				{
					if (FP_GT(angle, (a3 + 2 * M_PI)) || FP_LT(angle, a1)) continue;
				}
				else
				{
					if (FP_GT(angle, a3) || FP_LT(angle, a1)) continue;
				}
			}
			else
			{
				if (FP_GT(a3, a1))
				{
					if (FP_LT(angle, (a3 - 2 * M_PI)) || FP_GT(angle, a1)) continue;
				}
				else
				{
					if (FP_LT(angle, a3) || FP_GT(angle, a1)) continue;
				}
			}
		}

		LWDEBUGF(3, "lwcircle_compute_box3d: potential extreame %d (%.16f, %.16f)", i, xe, ye);

		x1 = (FP_LT(x1, xe)) ? x1 : xe;
		y1 = (FP_LT(y1, ye)) ? y1 : ye;
		x2 = (FP_GT(x2, xe)) ? x2 : xe;
		y2 = (FP_GT(y2, ye)) ? y2 : ye;
	}

	LWDEBUGF(3, "lwcircle_compute_box3d: extreames found (%.16f %.16f, %.16f %.16f)", x1, y1, x2, y2);

	/*
	x1 = center->x + x1 * radius;
	x2 = center->x + x2 * radius;
	y1 = center->y + y1 * radius;
	y2 = center->y + y2 * radius;
	*/
	z1 = (FP_LT(p1->z, p2->z)) ? p1->z : p2->z;
	z1 = (FP_LT(z1, p3->z)) ? z1 : p3->z;
	z2 = (FP_GT(p1->z, p2->z)) ? p1->z : p2->z;
	z2 = (FP_GT(z2, p3->z)) ? z2 : p3->z;

	box = lwalloc(sizeof(BOX3D));
	box->xmin = x1;
	box->xmax = x2;
	box->ymin = y1;
	box->ymax = y2;
	box->zmin = z1;
	box->zmax = z2;

	lwfree(center);

	return box;
}
예제 #4
0
/*
static int lwcircle_calculate_gbox_cartesian(const POINT4D *p1, const POINT4D *p2, const POINT4D *p3, GBOX *gbox)
*/
BOX3D *
lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
{
	POINT2D xmin, ymin, xmax, ymax;
	POINT4D *center = NULL;
	int p2_side = 0;
	double radius = 0.0;

	LWDEBUG(2, "lwcircle_compute_box3d called.");

	radius = lwcircle_center(p1, p2, p3, &center);
	BOX3D *box = lwalloc(sizeof(BOX3D));
	
	/* Negative radius signals straight line, p1/p2/p3 are colinear */
	if (radius < 0.0)
	{
		if ( center ) lwfree(center);
        box->xmin = FP_MIN(p1->x, p3->x);
        box->ymin = FP_MIN(p1->y, p3->y);
        box->zmin = FP_MIN(p1->z, p3->z);
        box->xmax = FP_MAX(p1->x, p3->x);
        box->ymax = FP_MAX(p1->y, p3->y);
        box->zmax = FP_MAX(p1->z, p3->z);
	    return box;
	}
	
	/* Matched start/end points imply circle */
	if ( p1->x == p3->x && p1->y == p3->y )
	{
		box->xmin = center->x - radius;
		box->ymin = center->y - radius;
		box->zmin = FP_MIN(p1->z,p2->z);
		box->xmax = center->x + radius;
		box->ymax = center->y + radius;
		box->zmax = FP_MAX(p1->z,p2->z);
		lwfree(center);
		return box;
	}

	/* First approximation, bounds of start/end points */
    box->xmin = FP_MIN(p1->x, p3->x);
    box->ymin = FP_MIN(p1->y, p3->y);
    box->zmin = FP_MIN(p1->z, p3->z);
    box->xmax = FP_MAX(p1->x, p3->x);
    box->ymax = FP_MAX(p1->y, p3->y);
    box->zmax = FP_MAX(p1->z, p3->z);

	/* Create points for the possible extrema */
	xmin.x = center->x - radius;
	xmin.y = center->y;
	ymin.x = center->x;
	ymin.y = center->y - radius;
	xmax.x = center->x + radius;
	xmax.y = center->y;
	ymax.x = center->x;
	ymax.y = center->y + radius;
	
	/* Divide the circle into two parts, one on each side of a line
	   joining p1 and p3. The circle extrema on the same side of that line
	   as p2 is on, are also the extrema of the bbox. */
	
	p2_side = signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, (POINT2D*)p2));

	if ( p2_side == signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, &xmin)) )
		box->xmin = xmin.x;

	if ( p2_side == signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, &ymin)) )
		box->ymin = ymin.y;

	if ( p2_side == signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, &xmax)) )
		box->xmax = xmax.x;

	if ( p2_side == signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, &ymax)) )
		box->ymax = ymax.y;

	lwfree(center);
	return box;
}
예제 #5
0
파일: g_box.c 프로젝트: Vlczech/vtapi
static int lwcircle_calculate_gbox(POINT4D p1, POINT4D p2, POINT4D p3, GBOX *gbox)
{
	double x1, x2, y1, y2, z1, z2, m1, m2;
	double angle, radius, sweep;
	/* angles from center */
	double a1, a2, a3;
	/* angles from center once a1 is rotated to zero */
	double r2, r3;
	double xe = 0.0, ye = 0.0;
	POINT4D *center;
	int i;

	LWDEBUG(2, "lwcircle_calculate_gbox called.");

	radius = lwcircle_center(&p1, &p2, &p3, &center);
	if (radius < 0.0) return G_FAILURE;

	x1 = MAXFLOAT;
	x2 = -1 * MAXFLOAT;
	y1 = MAXFLOAT;
	y2 = -1 * MAXFLOAT;

	a1 = atan2(p1.y - center->y, p1.x - center->x);
	a2 = atan2(p2.y - center->y, p2.x - center->x);
	a3 = atan2(p3.y - center->y, p3.x - center->x);

	/* Rotate a2 and a3 such that a1 = 0 */
	r2 = a2 - a1;
	r3 = a3 - a1;

	/*
	 * There are six cases here I'm interested in
	 * Clockwise:
	 *   1. a1-a2 < 180 == r2 < 0 && (r3 > 0 || r3 < r2)
	 *   2. a1-a2 > 180 == r2 > 0 && (r3 > 0 && r3 < r2)
	 *   3. a1-a2 > 180 == r2 > 0 && (r3 > r2 || r3 < 0)
	 * Counter-clockwise:
	 *   4. a1-a2 < 180 == r2 > 0 && (r3 < 0 || r3 > r2)
	 *   5. a1-a2 > 180 == r2 < 0 && (r3 < 0 && r3 > r2)
	 *   6. a1-a2 > 180 == r2 < 0 && (r3 < r2 || r3 > 0)
	 * 3 and 6 are invalid cases where a3 is the midpoint.
	 * BBOX is fundamental, so these cannot error out and will instead
	 * calculate the sweep using a3 as the middle point.
	 */

	/* clockwise 1 */
	if (FP_LT(r2, 0) && (FP_GT(r3, 0) || FP_LT(r3, r2)))
	{
		sweep = (FP_GT(r3, 0)) ? (r3 - 2 * M_PI) : r3;
	}
	/* clockwise 2 */
	else if (FP_GT(r2, 0) && FP_GT(r3, 0) && FP_LT(r3, r2))
	{
		sweep = (FP_GT(r3, 0)) ? (r3 - 2 * M_PI) : r3;
	}
	/* counter-clockwise 4 */
	else if (FP_GT(r2, 0) && (FP_LT(r3, 0) || FP_GT(r3, r2)))
	{
		sweep = (FP_LT(r3, 0)) ? (r3 + 2 * M_PI) : r3;
	}
	/* counter-clockwise 5 */
	else if (FP_LT(r2, 0) && FP_LT(r3, 0) && FP_GT(r3, r2))
	{
		sweep = (FP_LT(r3, 0)) ? (r3 + 2 * M_PI) : r3;
	}
	/* clockwise invalid 3 */
	else if (FP_GT(r2, 0) && (FP_GT(r3, r2) || FP_LT(r3, 0)))
	{
		sweep = (FP_GT(r2, 0)) ? (r2 - 2 * M_PI) : r2;
	}
	/* clockwise invalid 6 */
	else
	{
		sweep = (FP_LT(r2, 0)) ? (r2 + 2 * M_PI) : r2;
	}

	LWDEBUGF(3, "a1 %.16f, a2 %.16f, a3 %.16f, sweep %.16f", a1, a2, a3, sweep);

	angle = 0.0;
	for (i=0; i < 6; i++)
	{
		switch (i)
		{
			/* right extent */
		case 0:
			angle = 0.0;
			xe = center->x + radius;
			ye = center->y;
			break;
			/* top extent */
		case 1:
			angle = M_PI_2;
			xe = center->x;
			ye = center->y + radius;
			break;
			/* left extent */
		case 2:
			angle = M_PI;
			xe = center->x - radius;
			ye = center->y;
			break;
			/* bottom extent */
		case 3:
			angle = -1 * M_PI_2;
			xe = center->x;
			ye = center->y - radius;
			break;
			/* first point */
		case 4:
			angle = a1;
			xe = p1.x;
			ye = p1.y;
			break;
			/* last point */
		case 5:
			angle = a3;
			xe = p3.x;
			ye = p3.y;
			break;
		}
		/* determine if the extents are outside the arc */
		if (i < 4)
		{
			if (FP_GT(sweep, 0.0))
			{
				if (FP_LT(a3, a1))
				{
					if (FP_GT(angle, (a3 + 2 * M_PI)) || FP_LT(angle, a1)) continue;
				}
				else
				{
					if (FP_GT(angle, a3) || FP_LT(angle, a1)) continue;
				}
			}
			else
			{
				if (FP_GT(a3, a1))
				{
					if (FP_LT(angle, (a3 - 2 * M_PI)) || FP_GT(angle, a1)) continue;
				}
				else
				{
					if (FP_LT(angle, a3) || FP_GT(angle, a1)) continue;
				}
			}
		}

		LWDEBUGF(3, "lwcircle_calculate_gbox: potential extreame %d (%.16f, %.16f)", i, xe, ye);

		x1 = (FP_LT(x1, xe)) ? x1 : xe;
		y1 = (FP_LT(y1, ye)) ? y1 : ye;
		x2 = (FP_GT(x2, xe)) ? x2 : xe;
		y2 = (FP_GT(y2, ye)) ? y2 : ye;
	}

	LWDEBUGF(3, "lwcircle_calculate_gbox: extreames found (%.16f %.16f, %.16f %.16f)", x1, y1, x2, y2);

	z1 = FP_MIN(p1.z, p2.z);
	z1 = FP_MIN(z1, p3.z);
	z2 = FP_MAX(p1.z, p2.z);
	z2 = FP_MAX(z2, p3.z);

	m1 = FP_MIN(p1.m, p2.m);
	m1 = FP_MIN(m1, p3.m);
	m2 = FP_MAX(p1.m, p2.m);
	m2 = FP_MAX(m2, p3.m);

	gbox->xmin = x1;
	gbox->xmax = x2;
	gbox->ymin = y1;
	gbox->ymax = y2;

	if ( FLAGS_GET_Z(gbox->flags) )
	{
		gbox->zmin = z1;
		gbox->zmax = z2;
	}
	if ( FLAGS_GET_M(gbox->flags) )
	{
		gbox->mmin = m1;
		gbox->mmax = m2;
	}

	return G_SUCCESS;
}
예제 #6
0
static int lwcircle_calculate_gbox_cartesian(const POINT4D *p1, const POINT4D *p2, const POINT4D *p3, GBOX *gbox)
{
	POINT2D xmin, ymin, xmax, ymax;
	POINT4D center;
	int p2_side;
	double radius;

	LWDEBUG(2, "lwcircle_calculate_gbox called.");

	radius = lwcircle_center(p1, p2, p3, &center);
	
	/* Negative radius signals straight line, p1/p2/p3 are colinear */
	if (radius < 0.0)
	{
        gbox->xmin = FP_MIN(p1->x, p3->x);
        gbox->ymin = FP_MIN(p1->y, p3->y);
        gbox->zmin = FP_MIN(p1->z, p3->z);
        gbox->xmax = FP_MAX(p1->x, p3->x);
        gbox->ymax = FP_MAX(p1->y, p3->y);
        gbox->zmax = FP_MAX(p1->z, p3->z);
	    return LW_SUCCESS;
	}
	
	/* Matched start/end points imply circle */
	if ( p1->x == p3->x && p1->y == p3->y )
	{
		gbox->xmin = center.x - radius;
		gbox->ymin = center.y - radius;
		gbox->zmin = FP_MIN(p1->z,p2->z);
		gbox->mmin = FP_MIN(p1->m,p2->m);
		gbox->xmax = center.x + radius;
		gbox->ymax = center.y + radius;
		gbox->zmax = FP_MAX(p1->z,p2->z);
		gbox->mmax = FP_MAX(p1->m,p2->m);
		return LW_SUCCESS;
	}

	/* First approximation, bounds of start/end points */
    gbox->xmin = FP_MIN(p1->x, p3->x);
    gbox->ymin = FP_MIN(p1->y, p3->y);
    gbox->zmin = FP_MIN(p1->z, p3->z);
    gbox->mmin = FP_MIN(p1->m, p3->m);
    gbox->xmax = FP_MAX(p1->x, p3->x);
    gbox->ymax = FP_MAX(p1->y, p3->y);
    gbox->zmax = FP_MAX(p1->z, p3->z);
    gbox->mmax = FP_MAX(p1->m, p3->m);

	/* Create points for the possible extrema */
	xmin.x = center.x - radius;
	xmin.y = center.y;
	ymin.x = center.x;
	ymin.y = center.y - radius;
	xmax.x = center.x + radius;
	xmax.y = center.y;
	ymax.x = center.x;
	ymax.y = center.y + radius;
	
	
	/* Divide the circle into two parts, one on each side of a line
	   joining p1 and p3. The circle extrema on the same side of that line
	   as p2 is on, are also the extrema of the bbox. */
	
	p2_side = signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, (POINT2D*)p2));

	if ( p2_side == signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, &xmin)) )
		gbox->xmin = xmin.x;

	if ( p2_side == signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, &ymin)) )
		gbox->ymin = ymin.y;

	if ( p2_side == signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, &xmax)) )
		gbox->xmax = xmax.x;

	if ( p2_side == signum(lw_segment_side((POINT2D*)p1, (POINT2D*)p3, &ymax)) )
		gbox->ymax = ymax.y;

	return LW_SUCCESS;
}