Отсечение (Основы)

  В этой статье я объясню как делать отсечения элементарных примитивов - точки и прямоугольника.
  Для начала необходимо условится, что имеются такие типы струкур данных:
	

typedef struct	_C_Vector_2D	// Для хранения отдельной вершины
{
	int	x;
	int	y;
}		C_Vector_2D;

typedef struct	_C_Rect_2D	// Для хранения двух вершин
{
	C_Vector_2D	v[2];
}		C_Rect_2D;
Теперь представим, что существует такая структура типа C_Rect_2D, в которой хранятся координаты двух углов прямоугольной области отсечения, и условно называтся она будет clRect, которую я назвал в честь двух слов Clipping Rectangle. Отсечение точки Несомненно отсечение точки по какой-либо области является наиболее простым.

void DrawPointClip(C_Vector_2D v)
{
	// Далее идет проверка вхождения точки в прямоугольную область
	if((v.x>clRect.v[0].x)&&(v.x<clRect.v[1].x)&&	// Проверка по x
	   (v.y>clRect.v[0].y)&&(v.y<clRect.v[1].y))	// Проверка по y
		b_Surface[v.y*scrWidth+v.x]=curColor;	// Запись в буфер
}
Теперь необходимо разобраться в некоторых обозначениях. curColor - это переменная, в которой содержится текущий цвет, так же ее размер должен совпадать с размером данных для хранения цвета пиксела экрана. Например, если работа осуществляется в 32 битном режиме, то curColor должен быть типа int или DWORD, либо другим 4-байтовым типом. scrWidth - это ширина экрана. Самое главное это конечно массив данных b_Surface, который должен состоять из переменных размер которых равен количеству байт на пиксел. Отсечение прямоугольника Я приведу два случая отсечения прямоугольника. Первый случай: Нужно отрисовать треугольник, только если x0,y0 меньше чем x1,y1, то есть вершины не упорядочиваются по возрастанию. В таком случае нагрузка процессора будет много меньше.

void DrawFillRectFastClip(C_Rect_2D r)
{
	if((r.v[0].x!=r.v[1].x)&&(r.v[0].y!=r.v[1].y))
	{
		// Создаем переменную для хранения изменных вершин, хотя в данном случае это и не нужно, 
		// но обязательно создавать переменные, при передачи данных через указатели, иначе 
		// меняются глобальные данные.
		C_Rect_2D	rr=r;
		int		ys;	Для оптимизации

		// Собственно, нижеследующие 4 условия и есть само отсечение
		if(r.v[0].x<clRect.v[0].x)
			rr.v[0].x=clRect.v[0].x;

		if(r.v[0].y<clRect.v[0].y)
			rr.v[0].y=clRect.v[0].y;

		if(r.v[1].x>clRect.v[1].x)
			rr.v[1].x=clRect.v[1].x;

		if(r.v[1].y>clRect.v[1].y)
			rr.v[1].y=clRect.v[1].y;

		if((rr.v[0].x!=rr.v[1].x)&&(rr.v[0].y!=rr.v[1].y))	// Рисовать ли прямоугольник
		{
			for(int y=rr.v[0].y;y<rr.v[1].y;y++)
			{
				// На новых процессорах можно использовть умножение без опасения 
				// снижения скорости
				ys=y*1024;

				for(int x=rr.v[0].x;x<rr.v[1].x;x++)
					b_Surface[ys+x]=curColor;
			}
		}
	}
}
Второй случай: В этом случае необходимо упорядочивать координаты вершин и поэтому прямоугольник рисуется всегда. Код изменится лишь немного, и поэтому я не буду приводить полную верию, а приведу лишь места, где произошли изменения.

void DrawFillRectClip(C_Rect_2D r)
{
	if((r.v[0].x!=r.v[1].x)&&(r.v[0].y!=r.v[1].y))	// Здесь не было изменений
	{
		...			// Те же переменные 		
		int		temp;	// Переменная для сортировки

		// Упорядочивание
		if(r.v[0].x>r.v[1].x)
		{
			temp=rr.v[1].x;
			rr.v[1].x=rr.v[0].x;
			rr.v[0].x=temp;
		}

		if(r.v[0].y>r.v[1].y)
		{
			temp=rr.v[1].y;
			rr.v[1].y=rr.v[0].y;
			rr.v[0].y=temp;
		}

		// Уже 8 условий
		if(r.v[0].x<clRect.v[0].x)
			rr.v[0].x=clRect.v[0].x;
		if(r.v[0].x>clRect.v[1].x)		// Новое
			rr.v[0].x=clRect.v[1].x;

		if(r.v[0].y<clRect.v[0].y)
			rr.v[0].y=clRect.v[0].y;
		if(r.v[0].y>clRect.v[1].y)		// Новое
			rr.v[0].y=clRect.v[1].y;

		if(r.v[1].x>clRect.v[1].x)
			rr.v[1].x=clRect.v[1].x;
		if(r.v[1].x<clRect.v[0].x)		// Новое
			rr.v[1].x=clRect.v[0].x;

		if(r.v[1].y>clRect.v[1].y)
			rr.v[1].y=clRect.v[1].y;
		if(r.v[1].y<clRect.v[0].y)		// Новое
			rr.v[1].y=clRect.v[0].y;

		...		// Отрисовка прямоугольника
	}
}
Вот, пожалуй, все, что необходимо знать об основах отсечения, быть может в дальнейшем будут написаны статьи про отсечение, но более сложных примитивов.
Статью написал faceH0r 6.09.2005
Используются технологии uCoz