Beispiel #1
0
void cohen_sutherland (double x1, double y1, double x2, double y2, double xmin, double ymin, double xmax, double
ymax)
{
int accept;
int done;
outcode outcode1, outcode2;
accept = FALSE;
done = FALSE;
outcode1 = compute_outcode (x1, y1, xmin, ymin, xmax, ymax);
outcode2 = compute_outcode (x2, y2, xmin, ymin, xmax, ymax);
do
{
if (outcode1 == 0 && outcode2 == 0)
{
accept = TRUE;
done = TRUE;
}
else if (outcode1 & outcode2)
done = TRUE;
else
{
double x, y;
int outcode_ex = outcode1 ? outcode1 : outcode2;
if (outcode_ex & top)
{
x = x1 + (x2 - x1) * (ymax - y1) / (y2 - y1);
y = ymax;
}
else if (outcode_ex & bottom)
{
x = x1 + (x2 - x1) * (ymin - y1) / (y2 - y1);
y = ymin;
}
else if (outcode_ex & right)
{
y = y1 + (y2 - y1) * (xmax - x1) / (x2 - x1);
x = xmax;
}
else
{
y = y1 + (y2 - y1) * (xmin - x1) / (x2 - x1);
x = xmin;
}
if (outcode_ex == outcode1)
{
x1 = x;
y1 = y;
outcode1 = compute_outcode (x1, y1, xmin, ymin, xmax, ymax);
}
else
{
x2 = x;
y2 = y;
outcode2 = compute_outcode (x2, y2, xmin, ymin, xmax, ymax);
}
}
} while (done == FALSE);
if (accept == TRUE)
line (x1, y1, x2, y2);
}
Beispiel #2
0
/*
 * Calculate the intersection of a rectangle and line segment.
 * return TRUE if there is an intersection, FALSE otherwise.
 */
bool_t rect_intersect_with_line(const struct rect_t * r, s32_t * x1, s32_t * y1, s32_t * x2, s32_t * y2)
{
	s32_t x = 0;
	s32_t y = 0;
	s32_t _x1, _y1;
	s32_t _x2, _y2;
	s32_t rectx1;
	s32_t recty1;
	s32_t rectx2;
	s32_t recty2;
	int outcode1, outcode2;

	if (!r || !x1 || !y1 || !x2 || !y2)
	{
		return FALSE;
	}

	_x1 = *x1;
	_y1 = *y1;
	_x2 = *x2;
	_y2 = *y2;
	rectx1 = r->x;
	recty1 = r->y;
	rectx2 = r->x + r->w - 1;
	recty2 = r->y + r->h - 1;

	/* Check to see if entire line is inside rect */
	if (_x1 >= rectx1 && _x1 <= rectx2 && _x2 >= rectx1 && _x2 <= rectx2 && _y1
			>= recty1 && _y1 <= recty2 && _y2 >= recty1 && _y2 <= recty2)
	{
		return TRUE;
	}

	/* Check to see if entire line is to one side of rect */
	if ((_x1 < rectx1 && _x2 < rectx1) || (_x1 > rectx2 && _x2 > rectx2) || (_y1
			< recty1 && _y2 < recty1) || (_y1 > recty2 && _y2 > recty2))
	{
		return FALSE;
	}

	if (_y1 == _y2)
	{
		/* Horizontal line, easy to clip */
		if (_x1 < rectx1)
		{
			*x1 = rectx1;
		}
		else if (_x1 > rectx2)
		{
			*x1 = rectx2;
		}
		if (_x2 < rectx1)
		{
			*x2 = rectx1;
		}
		else if (_x2 > rectx2)
		{
			*x2 = rectx2;
		}
		return TRUE;
	}

	if (_x1 == _x2)
	{
		/* Vertical line, easy to clip */
		if (_y1 < recty1)
		{
			*y1 = recty1;
		}
		else if (_y1 > recty2)
		{
			*y1 = recty2;
		}
		if (_y2 < recty1)
		{
			*y2 = recty1;
		}
		else if (_y2 > recty2)
		{
			*y2 = recty2;
		}
		return TRUE;
	}

	/* More complicated Cohen-Sutherland algorithm */
	outcode1 = compute_outcode(r, _x1, _y1);
	outcode2 = compute_outcode(r, _x2, _y2);

	while (outcode1 || outcode2)
	{
		if (outcode1 & outcode2)
		{
			return FALSE;
		}

		if (outcode1)
		{
			if (outcode1 & CODE_TOP)
			{
				y = recty1;
				x = _x1 + ((_x2 - _x1) * (y - _y1)) / (_y2 - _y1);
			}
			else if (outcode1 & CODE_BOTTOM)
			{
				y = recty2;
				x = _x1 + ((_x2 - _x1) * (y - _y1)) / (_y2 - _y1);
			}
			else if (outcode1 & CODE_LEFT)
			{
				x = rectx1;
				y = _y1 + ((_y2 - _y1) * (x - _x1)) / (_x2 - _x1);
			}
			else if (outcode1 & CODE_RIGHT)
			{
				x = rectx2;
				y = _y1 + ((_y2 - _y1) * (x - _x1)) / (_x2 - _x1);
			}
			_x1 = x;
			_y1 = y;
			outcode1 = compute_outcode(r, x, y);
		}
		else
		{
			if (outcode2 & CODE_TOP)
			{
				y = recty1;
				x = _x1 + ((_x2 - _x1) * (y - _y1)) / (_y2 - _y1);
			}
			else if (outcode2 & CODE_BOTTOM)
			{
				y = recty2;
				x = _x1 + ((_x2 - _x1) * (y - _y1)) / (_y2 - _y1);
			}
			else if (outcode2 & CODE_LEFT)
			{
				x = rectx1;
				y = _y1 + ((_y2 - _y1) * (x - _x1)) / (_x2 - _x1);
			}
			else if (outcode2 & CODE_RIGHT)
			{
				x = rectx2;
				y = _y1 + ((_y2 - _y1) * (x - _x1)) / (_x2 - _x1);
			}
			_x2 = x;
			_y2 = y;
			outcode2 = compute_outcode(r, x, y);
		}
	}

	*x1 = _x1;
	*y1 = _y1;
	*x2 = _x2;
	*y2 = _y2;

	return TRUE;
}
Beispiel #3
0
static int
clip_line (double *x0_p, double *y0_p, double *x1_p, double *y1_p, double x_min_clip, double x_max_clip, double y_min_clip, double y_max_clip, bool spec_min_x, bool spec_min_y, bool spec_max_x, bool spec_max_y)
{
  double x0 = *x0_p;
  double y0 = *y0_p;
  double x1 = *x1_p;
  double y1 = *y1_p;
  int outcode0, outcode1;
  bool accepted;
  int clipval = 0;
  
  outcode0 = compute_outcode (x0, y0, x_min_clip, x_max_clip, y_min_clip, y_max_clip, spec_min_x, spec_min_y, spec_max_x, spec_max_y);
  outcode1 = compute_outcode (x1, y1, x_min_clip, x_max_clip, y_min_clip, y_max_clip, spec_min_x, spec_min_y, spec_max_x, spec_max_y);  

  for ( ; ; )
    {
      if (!(outcode0 | outcode1)) /* accept */
	{
	  accepted = true;
	  break;
	}
      else if (outcode0 & outcode1) /* reject */
	{
	  accepted = false;
	  break;
	}
      else
	{
	  /* at least one endpoint is outside; choose one that is */
	  int outcode_out = (outcode0 ? outcode0 : outcode1);
	  double x, y;		/* intersection with clip edge */
	  
	  if (outcode_out & RIGHT)
	    {
	      x = x_max_clip;
	      y = y0 + (y1 - y0) * (x_max_clip - x0) / (x1 - x0);
	    }
	  else if (outcode_out & LEFT)
	    {
	      x = x_min_clip;
	      y = y0 + (y1 - y0) * (x_min_clip - x0) / (x1 - x0);
	    }
	  else if (outcode_out & TOP)
	    {
	      x = x0 + (x1 - x0) * (y_max_clip - y0) / (y1 - y0);
	      y = y_max_clip;
	    }
	  else			/* BOTTOM bit must be set */
	    {
	      x = x0 + (x1 - x0) * (y_min_clip - y0) / (y1 - y0);
	      y = y_min_clip;
	    }
	  
	  if (outcode_out == outcode0)
	    {
	      x0 = x;
	      y0 = y;
	      outcode0 = compute_outcode (x0, y0, x_min_clip, x_max_clip, y_min_clip, y_max_clip, spec_min_x, spec_min_y, spec_max_x, spec_max_y);
	    }
	  else
	    {
	      x1 = x; 
	      y1 = y;
	      outcode1 = compute_outcode (x1, y1, x_min_clip, x_max_clip, y_min_clip, y_max_clip, spec_min_x, spec_min_y, spec_max_x, spec_max_y);
	    }
	}
    }

  if (accepted)
    {
      clipval |= ACCEPTED;
      if ((x0 != *x0_p) || (y0 != *y0_p))
	clipval |= CLIPPED_FIRST;
      if ((x1 != *x1_p) || (y1 != *y1_p))
	clipval |= CLIPPED_SECOND;
      *x0_p = x0;
      *y0_p = y0;
      *x1_p = x1;
      *y1_p = y1;
    }

  return clipval;
}