- •Московский государственный институт электроники и математики (Технический университет)
- •"Преобразования на плоскости. Вычерчивание линий и окружностей"
- •2. 1. Преобразования на плоскости (2d преобразования)
- •2.2. Разложение в растр
- •2.2.1 Вычерчивание отрезков
- •2.2.1.1. Алгоритм Брезенхема вычерчивания отрезков для первого октанта.
- •2. 2. 1. 2. Обобщенный алгоритм Брезенхема вычерчивания отрезков
- •2.2.2. Вычерчивание окружностей
- •3. Практическая часть
- •4. Требования к отчету
4. Требования к отчету
Отчет по выполнению лабораторной работы оформляется в рукописном или печатном виде на листах бумаги формата А4.
Отчет должен содержать:
Цель работы;
Постановка задачи;
Используемые в лабораторной работе алгоритмы:
а) словесное описание основной идеи алгоритма,
б) алгоритм на псевдокоде или блок-схема алгоритма;
Текст программы;
Полученные результаты;
Выводы по работе и рекомендации по улучшению.
Список используемой литературы
"Начала компьютерной графики". Шикин Е. В., Боресков А. В., Зайцев А. А.
"Диалог-Мифи", Москва, 1993.
"Компьютерная графика. Динамика, реалистические изображения".
Шикин Е. В., Боресков А. В. "Диалог-Мифи", Москва, 1998.
"Алгоритмические основы машинной графики" . Д. Роджерс. "Мир",
Москва, 1989.
Приложение
Примеры решения типовых задач.
Постановка задачи
Начертить квадрат со стороной 90, выполнить поворот относительно его центра на 45. Выполнить масштабирование полученного квадрата с коэффициентами kx = 2, ky = 2 так, чтобы центр квадрата остался на месте.
Программа на языке Паскаль
program Rectangle;
uses crt,graph;
var
driver,mode:integer;
x,y:integer; {координаты левого верхнего угла квадрата}
i:integer;
xc,yc:integer; {координаты центра квадрата}
procedure DrawLine(x1,y1,x2,y2,Color:integer); {рисование линии }
var
i,x,y,dx,dy,sx,sy,e,tmp,flag:integer;
begin
x:=x1; {инициализация переменных}
y:=y1;
dx:=abs(x2-x1);
dy:=abs(y2-y1);
if x2-x1>0 then sx:=1 else sx:=-1;
if y2-y1>0 then sy:=1 else sy:=-1;
if dy>dx then {обмен значений dx и dy}
begin
tmp:=dx;
dx:=dy;
dy:=tmp;
flag:=1;
end
else
flag:=0;
e:=2*dy-dx; {инициализация ошибки} for i:=1 to dx do
begin
PutPixel(x,y,Color);
if e>=0 then {изменение дополнительной}
begin {координаты}
if flag=1 then x:=x+sx
else y:=y+sy;
e:=e-2*dx; {коррекция ошибки}
end;
if flag=1 then y:=y+sy {изменение основной}
else x:=x+sx; {координаты}
e:=e+2*dy; {накопление ошибки}
end;
end;
procedure Rotation(angle:real;color:integer); {поворот}
var
x1,y1,xr,yr:integer;
begin
x1:=x-xc; {поместить в начало координат}
y1:=y-yc;
xr:=round(x1*cos(angle)-y1*sin(angle)); {повернуть}
yr:=round(x1*sin(angle)+y1*cos(angle));
xr:=xr+xc; {вернуть в начальное положение}
yr:=yr+yc;
DrawLine(x,y,round(xr),round(yr),color);
x:=xr;
y:=yr;
end;
procedure DrawRectangle(angle:real;Color:integer); {рисование квадрата}
begin
for i:=1 to 4 do {поворот точки 4 раза на 90 вокруг центра}
Rotation(angle,Color);
end;
begin
driver:=Detect; {инициализация}
initgraph(driver,mode,'d:\tp'); {графического режима }
xc:=255;
yc:=175;
x:=xc-45; {определение координат}y:=yc-45;{верхнего левого угла}
DrawRectangle(pi/2,13); {рисование квадрата }
PutPixel(xc,yc,13);
readkey;
DrawRectangle(pi/2,0); {рисование старого квадрата черным цветом}
Rotation(pi/4,0); {поворот верхнего левого угла на 45}
DrawRectangle(pi/2,13);
readkey;
{масштабирование}
DrawRectangle(pi/2,0); {рисование старого квадрата черным цветом}
y:=yс-2*45; {увеличение диагонали квадрата}
DrawRectangle(pi/2,13); {рисование увеличенного квадрата}
readkey;
end.
Программа на языке Си
# include<stdio.h>
# include<conio.h>
# include<graphics.h>
# include<stdlib.h>
# include<math.h>
# define pi 3.1415926
int x,y; //координаты левого верхнего угла квадрата
int i;
int xc,yc; //координаты центра квадрата
void DrawLine (int x1,int y1,int x2,int y2,int Color) //рисование линии
{
int i,x,y,dx,dy,sx,sy,e,tmp,flag;
x=x1; //инициализация переменных
y=y1;
dx=abs(x2-x1);
dy=abs(y2-y1);
if (x2-x1>0)
sx=1;
else
sx=-1;
if (y2-y1>0)
sy=1;
else
sy=-1;
if (dy>dx) // обмен значений dx и dy
{
tmp=dx;
dx=dy;
dy=tmp;
flag=1;
}
else
flag=0;
e=2*dy-dx; // инициализация ошибки
for (i=0; i<dx; i++)
{
putpixel(x,y,Color);
if (e>=0) //изменение дополнительной координаты
{
if (flag=1)
x=x+sx;
else
y=y+sy;
e=e-2*dx; // коррекция ошибки
}
if (flag=1) // изменение основной координаты
y=y+sy;
else
x=x+sx;
e=e+2*dy; // накопление ошибки
}
}
void Rotation(float angle,int color) // поворот
{ int
x1,y1,xr,yr;
x1=x-xc; // поместить в начало координат
y1=y-yc;
xr=ceil(x1*cos(angle)-y1*sin(angle)); // повернуть относительно
yr=ceil(x1*sin(angle)+y1*cos(angle)); // начала координат
xr=xr+xc; // вернуть в исходное положение
yr=yr+yc;
DrawLine(x,y,ceil(xr),ceil(yr),color);
x=xr;
y=yr;
}
void DrawRectangle(float angle, int Color) // рисование квадрата
{
for (i=0;i<4;i++) // поворот точки 4 раза на 90 вокруг центра
Rotation(angle,Color);
}
main ()
{
int Driver, Mode;
Driver=DETECT; // инициализация графического режима
initgraph(&Driver,&Mode,"");
xc=255;
yc=175;
x=xc-45; // определение координат верхнего
y=yc-45; // левого угла квадрата
DrawRectangle(pi/2,13);
putpixel(xc,yc,13);
getch();
DrawRectangle(pi/2,0); // рисование старого квадрата черным
Rotation(pi/4,0); // поворот верхнего левого угла на 45
DrawRectangle(pi/2,13);
getch();
DrawRectangle(pi/2,0); // рисование старого квадрата черным
y=y-45; // увеличение диагонали квадрата
DrawRectangle(pi/2,13); // рисование увеличенного квадрата
getch();
return 0;
}
Рисование квадрата осуществляется последовательным рисованием четырех отрезков, причем координаты каждой следующей вершины вычисляются при помощи поворота предыдущей на 90 вокруг центра квадрата.
2. Постановка задачи
Начертить окружность с центром в точке (220, 200) и радиусом 40. Выполнить поворот окружности на 90 относительно точки (220, 100).
Программа на языке Паскаль
program Circle;
uses crt,graph;
var
driver,mode:integer;
xc,yc:integer; {координаты центра}
R:integer;
xp,yp:integer; {координаты точки, относительно которой} {выполняется поворот}
procedure DrawCircle (color:integer);
label 1,2,3,4,10,20,30;
var
lim,x,y,di,s1,s2:integer;
begin {инициализация переменных}
x:=0;
y:=R;
lim:=0;
di:=2*(1-R);
1: PutPixel (x+xc,y+yc,color);
PutPixel (x+xc,-y+yc,color);
PutPixel (-x+xc,y+yc,color);
PutPixel (-x+xc,-y+yc,color);
if y<=lim then goto 4; {выделение случаев1 или 2, 3 или 4, 5}
if di<0 then goto 2;
if di>0 then goto 3;
if di=0 then goto 20;
2: s1:=2*di+2*y-1 ; {определение случая 1 или 2}
if s1<=0 then goto 10;
if s1>0 then goto 20;
3: s2:=2*di-2*x-1; {определение случая 3 или4}
if s2<=0 then goto 20;
if s2>0 then goto 30;
10: x:=x+1; {горизонтальный шаг}
di:=di+2*x+1;
goto 1;
20: x:=x+1; {диагональный шаг}
y:=y-1;
di:=di+2*x-2*y+2;
goto 1;
30: y:=y-1; {вертикальный шаг}
di:=di-2*y+1;
goto 1;
4: end;
procedure Rotation(x,y:integer); {поворот}
var
x1,y1,xr,yr:integer;
begin
x1:=x-xp; {поместить в начало координат}
y1:=y-yp;
xr:=round(x1*cos(-pi/2)-y1*sin(-pi/2)); {повернуть относительно начала}
yr:=round(x1*sin(-pi/2)+y1*cos(-pi/2));
xc:=xr+xp; {вернуть в начальное положение}
yc:=yr+yp;
end;
begin
driver:=Detect;{инициализация графического режима}
initgraph (driver,mode, 'd:\tp');
xc:=220;
yc:=200;
xp:=220;
yp:=100;
R:=40;
PutPixel(xc,yc,2);
PutPixel(xp,yp,13);
DrawCircle(2); {нарисовать окружность}
readkey;
Rotation(xc,yc); {повернуть окружность}
PutPixel(xc,yc,2);
DrawCircle(2);
readkey;
end.
Программа на языке Си
#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <graphics.h>
#define pi 3.1415926
int Driver,Mode;
int xc,yc; //координаты центра
int R;
int xp,yp; // координаты точки, относительно // которой выполняется поворот
void DrawCircle (int color)
{
int lim,x,y,di,s1,s2;
// инициализация переменных
x=0;
y=R;
lim=0;
di=2*(1-R);
lab1: putpixel (x+xc,y+yc,color);
putpixel (x+xc,-y+yc,color);
putpixel (-x+xc,y+yc,color);
putpixel (-x+xc,-y+yc,color);
if (y<=lim) goto lab4;
//выделение случаев 1 или 2, 3 или 4, 5
if (di<0) goto lab2;
if (di>0) goto lab3;
if (di==0) goto lab20;
lab2: s1=2*di+2*y-1 ; // определение случая 1 или 2
if (s1<=0) goto lab10;
if (s1>0) goto lab20;
lab3: s2=2*di-2*x-1; // определение случая 3 или 4
if (s2<=0) goto lab20;
if (s2>0) goto lab30;
lab10: x=x+1; // горизонтальный шаг
di=di+2*x+1;
goto lab1;
lab20: x=x+1; // диагональный шаг
y=y-1;
di=di+2*x-2*y+2;
goto lab1;
lab30: y=y-1; // вертикальный шаг
di=di-2*y+1;
goto lab1;
lab4: ;
}
void Rotation (int x, int y) // поворот
{
int x1,y1,xr,yr;
x1=x-xp; // переместить в начало координат
y1=y-yp;
xr=ceil(x1*cos(-pi/2)-y1*sin(-pi/2)); // поворот
yr=ceil(x1*sin(-pi/2)+y1*cos(-pi/2));
xc=xr+xp; // вернуть в исходное положение
yc=yr+yp;
}
void main()
{
clrscr;
driver=DETECT; // инициализация графического режима
initgraph (&driver,&mode, "C:\BC45\SI");
xc=220;
yc=200;
xp=220;
yp=100;
R=40;
putpixel(xc,yc,2);
putpixel(xp,yp,13);
DrawCircle(2);
getch();
Rotation(xc,yc);
putpixel(xc,yc,2);
DrawCircle(2);
getch();
}