Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.04.2013, 14:20   #1
Braun1408
 
Регистрация: 06.04.2013
Сообщений: 3
По умолчанию Растеризация кривой Безье.

Привожу здесь свой алгоритм рисования кривой Безье средствами Glut. Среда Visual Studio 2012, C++ проект.

Проблема в том, что растеризует кривую он как-то неадекватно, хотя закрашиваемые пиксели вроде бы считает как нужно. Растеризую с помощью алгоритма DDA.

вот код:

Код:
void CurveBezier( ) {
        //строим кривую по 4 точкам
	point p1 = P[0], p2 = P[1], p3 = P[2], p4 = P[3];
	double x,y;
	glColor3f(1,0,0);
    glPointSize(0);
    glBegin(GL_POINTS);

	tx = p1.x; ty = p1.y;

	for(float t = 0.001; t <= 1.0; t += 0.001){
        x = p1.x*(pow(-t,3)+3*pow(t,2)-3*t+1)
                +3*p2.x*t*(pow(t,2)-2*t+1)
                +3*p3.x*pow(t,2)*(1-t)+p4.x*pow(t,3);
        y = p1.y*(pow(-t,3)+3*pow(t,2)-3*t+1)
                +3*p2.y*t*(pow(t,2)-2*t+1)
                +3*p3.y*pow(t,2)*(1-t)+p4.y*pow(t,3);

		

		
		DDA(tx, ty, x, y);
		tx = x; ty = y;
	}
	glEnd();
}
//-------------------------------------------------------------------------------
double round (double x) {
	return x < 0 ? ceil (x - 0.5) : floor (x + 0.5);
}
//-------------------------------------------------------------------------------
int max(int a, int b){
	if(a >= b)return a;
	else return b;
}
//-------------------------------------------------------------------------------
void DDA(float x1, float y1, float x2, float y2)
{
	// Целочисленные значения координат начала и конца отрезка,
	// округленные до ближайшего целого
	int iX1 = round(x1);
	int iY1 = round(y1);
	int iX2 = round(x2);
	int iY2 = round(y2);
 
	// Длина и высота линии
	int deltaX = abs(iX1 - iX2);
	int deltaY = abs(iY1 - iY2);
 
	// Считаем минимальное количество итераций, необходимое
	// для отрисовки отрезка. Выбирая максимум из длины и высоты
	// линии, обеспечиваем связность линии
	int length = max(deltaX, deltaY);
 
	// особый случай, на экране закрашивается ровно один пиксел
	if (length == 0)
	{
		glVertex3f(iX1, iY1, 0);
		return;
	}
	// Вычисляем приращения на каждом шаге по осям абсцисс и ординат
	double dX = (x2 - x1) / length;
	double dY = (y2 - y1) / length;
 
	// Начальные значения
	double x = x1;
	double y = y1;
 
	if(fabs(dX) > 0.5 && fabs(dY) < 0.5){
		if(dX < 0)
		x -= ceil(fabs(dX));
		else x += ceil(dX);
	}
	else if(fabs(dX) < 0.5 && fabs(dY) > 0.5){
		if(dY < 0)
		y -= ceil(fabs(dY));
		else y += ceil(dY);
	}
	else if(fabs(dX) > 0.5 && fabs(dY) > 0.5){
		if(dX < 0)
		x -= ceil(fabs(dX));
		else x += ceil(dX);
		if(dY < 0)
		y -= ceil(fabs(dY));
		else y += ceil(dY);
	}
		glVertex3f(x, y, 0);
}
вот результат:
причем когда кривую рисую широкую, наблюдаются разрывы как на скрине, а когда в четверть экрана, пиксели сжимаются плотнее и получается наложение, и как следствие утолщение линии.


Подскажите как это вообще делается для кривых, как исправить алгоритм, или может быть стоит взять другой? в интернете инфы по этому вопросу раз два и обчелся.

Последний раз редактировалось Braun1408; 06.04.2013 в 14:24.
Braun1408 вне форума Ответить с цитированием
Старый 06.04.2013, 14:35   #2
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

1. Вертексы Вы используете как отдельные точки, причем располагаете их по вещественным координатам. Вполне естественно, что при Растянутом графике у Вас возникают разрывы. Выход - используйте вертексы как узлы ломаной.

2. У Вас шаг построения кривой не зависит от ее длины в пикселях. Поэтому при мелких масштабах точки налезают одна на другую - их просто слишком много. Выход - корректировать шаг в зависимости от масштаба.

3. Компромиссное решение: 1000 узлов на кривой - слишком много. Достаточно будет и 30.
s-andriano вне форума Ответить с цитированием
Старый 06.04.2013, 15:41   #3
Braun1408
 
Регистрация: 06.04.2013
Сообщений: 3
По умолчанию

Цитата:
Сообщение от s-andriano Посмотреть сообщение
1. Вертексы Вы используете как отдельные точки, причем располагаете их по вещественным координатам. Вполне естественно, что при Растянутом графике у Вас возникают разрывы. Выход - используйте вертексы как узлы ломаной.

2. У Вас шаг построения кривой не зависит от ее длины в пикселях. Поэтому при мелких масштабах точки налезают одна на другую - их просто слишком много. Выход - корректировать шаг в зависимости от масштаба.

3. Компромиссное решение: 1000 узлов на кривой - слишком много. Достаточно будет и 30.
сделал 30 узлов + замена
Код:
glBegin(GL_POINTS);
на
Код:
glBegin(GL_LINE_LOOP);
результат приемлемый



Но будет ли это растеризацией как таковой?
Braun1408 вне форума Ответить с цитированием
Старый 06.04.2013, 17:04   #4
Braun1408
 
Регистрация: 06.04.2013
Сообщений: 3
По умолчанию

кстати, так все рисуется и без функции ДДА. похоже это не то совсем. надо как то попиксельно нарисовать
Braun1408 вне форума Ответить с цитированием
Старый 06.04.2013, 18:01   #5
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Цитата:
Сообщение от Braun1408 Посмотреть сообщение
кстати, так все рисуется и без функции ДДА. похоже это не то совсем. надо как то попиксельно нарисовать
Боюсь, для попиксельной графики OpenGL не самый подходящий вариант.
Собственно, посмотрите, у Вас везде фигурируют целые числа. Только потом результат округляется до целых. А в OpenGL размер поля по умолчанию составляет от -1 до +1, причем не зависит от размеров окна.
Вы, конечно, можете переопределить масштаб, но тогда у Вас "полывут" координаты всех 4-х точек.
В общем, слишком много геморроя, пока учтешь все нюансы.
Да и стоит ли овчинка выделки, если самое главное, ради чего подключают OpenGL - аппаратное ускорение графики, Вы совершенно не используете, просчитывая все центральным процессором?
s-andriano вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[C++] Растеризация изображения oneMoreWood Помощь студентам 0 02.01.2012 23:20
Кривая Безье. Muaxaxa Общие вопросы Delphi 2 28.11.2011 01:03
Direct3D9, программная растеризация _-Re@l-_ Gamedev - cоздание игр: Unity, OpenGL, DirectX 6 01.09.2011 19:21
Построение кривой безье. faustinus Помощь студентам 1 26.12.2010 18:02
Кривая Безье ELL Помощь студентам 4 20.05.2008 22:56