Содержание

 

Содержание. 2

ЗАДАНИЕ 1. Простой алгоритм двумерного отсечения. 3

Листинг программы.. 7

ЗАДАНИЕ 3. Рисование линий по алгоритму Брезенхема. 8

Листинг программы.. 8

Задание 4 Рисование блок-схемы.. 9

ЛИСТИНГ ПРОГРАММЫ РАЗБИЕНИЯ МНОГОУГОЛЬНИКОВ.. 13

Список литературы.. 17

ЗАДАНИЕ 1. Простой алгоритм двумерного отсечения.

Р1 , Р2 - концевые точки отрезка

Р1' , Р2'- концевые точки видимой части отрезка

xл, xп , yв , y н - координаты левой, правой, верхней и нижней сторон окна

Флаг - признак видимости, равный: 0, видимость; - 1, невидимость

вычисление кодов концевых точек

занесение этих кодов в два массива Т1код и Т2код, размерностью 1 х 4 каждый

для первого конца: Р1

if x1 < xл then Т1код(4) = 1 else Т1код(4) = 0

lf x1 > xп then Т1код(3) = 1 else Т1код(3) = 0

If y1 < yн then Т1код(2) = 1 else Т1код(2) = 0

If y1 > yв then Т1код(1) = 1 else Т1код(1) = 0

для второго конца: Р2

if x2 < xл then Т2код(4) = 1 else Т2код(4) = 0

lf x2 > xп then Т2код(3) = 1 else Т2код(3) = 0

If y2 < yн then Т2код(2) = 1 else Т2код(2) = 0

If y2 > yв then Т2код(1) = 1 else Т2код(1) = 0

инициализация признака видимости и видимых концевых точек

инициализация т очень большим числом, имитирующим бесконечный наклон

Флаг = 0

Р1' = Р1

Р2' = Р2'

m = Большое число

проверка полной видимости отрезка

Сумма1 = 0

Сумма2 = 0

for i = 1 to 4

Сумма1 = Сумма1 + Т1код(i)

Сумма2 = Сумма2 + Т2код(i)

next i

if Сумма1 = 0 and Сумма2 = 0 then 7

отрезок не является полностью видимым

проверка случая тривиальной невидимости

вычисление логического произведения (Произвед) кодов концевых точек отрезка

Произвед = 0

for i = 1 to 4

Произвед = Произвед + Целая часть ((Т1код(i)) + Т2код(i)/2)

If Произвед < > 0 then

Флаг = - 1

go to 7

end if

next i

отрезок может быть частично видимым проверка попадания первой точки внутрь окна

if Сумма1 = 0 then

Номер = 1

Р1' = Р1

P = Р2

go to 2

end if

проверка попадания второй точки внутрь окна

if Сумма2 = 0 then

Номер = 2

Р1' = Р2

P = Р1

go to 2

end if

внутри окна нет концов отрезка

инициализация номера конца отрезка

Номер == 0

1 if Номер < > 0 then Р'номер = Р

Номер = Номер + 1

if Номер > 2 then 7

P = Рномер

проверка пересечения с левым краем проверка вертикальности отрезка

2 if (x2 - x1 ) = 0 then 4

m = (y2 - y1 )/ (x2 - x1 )

if xл < Px then 3

у = m * (xл - Px) + Py

if y < yв then 3

if y < yн then 3

обнаружено корректное пересечение

Py = y

Px = xл

to 1

проверка пересечения с правым краем

3 if xп > Рx then 4

у = m * (хп - Рx) + Рy

if y < yв then 4

if y < yн then 4

обнаружено корректное пересечение

Py = y

Px = xп

to 1

проверка пересечения с верхним краем проверка горизонтальности отрезка

4 if m = 0 then 1

if yв > Рy then 5

x = (1/m) * (ув - Ру) + Рx

if x < xл then 5

if x < xп then 5

обнаружено корректное пересечение

Px = x

Py = yв

gо to 1

проверка пересечения с нижним краем

5 if yн > Рy then ошибка

х = (1/m) * (yн - Ру) + Рx

if x < xл then 6

if x < xп then 6

обнаружено корректное пересечение

Px = x

Py = yн

gо to 1

отрезок невидим

6 Флаг = - 1

завершение работы и вызов процедуры черчения

7 If Флаг = - 1 then 8

Draw P1'P2'

перейти к обработке следующего отрезка

8 finish

Листинг программы

int x1, x2, y1, y2;

void __fastcall TForm1::FormPaint(TObject *Sender)

{

 Canvas->Pen->Color = clBlue; // устанавливаем цвет отсеченных отрезков

 Canvas->Pen->Width = 1; // устанавливаем ширину отрезков

 randomize();

 for (int i = 0; i < 100; i++) //рисуем произвольные отрезки

  {

   Canvas->MoveTo(random(Form1->Width),random(Form1->Height));

   Canvas->LineTo(random(Form1->Width),random(Form1->Height));

  }

 Canvas->Pen->Color = clBlack; // устанавливаем цвет отсекающего окна

 Canvas->Rectangle(x1,y1,x2,y2); // рисуем отксекающее окно

 }

void __fastcall TForm1::FormCreate(TObject *Sender)

{

x1 = StrToInt(InputBox("Введите координаты","Введите x1 отсекающего окна",0));

x2 = StrToInt(InputBox("Введите координаты","Введите x2 отсекающего окна",0));

y1 = StrToInt(InputBox("Введите координаты","Введите y1 отсекающего окна",0));

y2 = StrToInt(InputBox("Введите координаты","Введите y2 отсекающего окна",0));

}

ЗАДАНИЕ 3. Рисование линий по алгоритму Брезенхема.

Основная идея алгоритма состоит в том, что если угловой коэффициент прямой < 1/2, то следующую точку поставить в позицию (1,0), а если угловой коэффициент > 1/2, то - в позицию (1,1). Для того чтобы принять решение, куда заносить очередной пиксел вводится величина отклонения D точной позиции от середины между двумя возможными растровыми точками в направлении наименьшей относительной координаты. Знак D используется как критерий для выбора ближайшей растровой точки. Если D < 0, то точное Y-значение округляется до меньшего последнего целочисленного значения Y, т.е. Y-координата не меняется по сравнению с предыдущей точкой. В противном случае Y увеличивается на 1.

Листинг программы

dx = abs(x2-x1);

dy = abs(y2-y1);

sx = x2 >= x1 ? 1:-1;

sy = y2 >= y1 ? 1:-1;

    if(dy <= dx)                     //проверка угла наклона линии

    {

 d=(dy<<1)-dx;                       //деление на два для определения углового коэффициента

 d1=dy<<1;

 d2=(dy-dx)<<1;

 Canvas->Pixels[x1][y1] = color;                   //вывод первой точки на экране

    for(int x=x1+sx, y=y1, i=1; i<=dx; i++, x+=sx) // цикл вывода линии на экран

    {

      if(d>0)            / * Если d < 0 значение y не меняется по сравнению с предыдущей точкой, иначе y увеличивается * /

      {

        d+=d2;

        y+=sy;

      }

        else d+=d1;

   Canvas->Pixels[x][y]=color;                    //вывод на экран очередной точки линии

    }

    }

    else

    {

        d=(dx<<1)-dy;

        d1=dx<<1;

        d2=(dx-dy)<<1;

        Canvas->Pixels[x1][y1] = color;

        for(int x=x1,y=y1+sy,i=1;i<=dy;i++,y+=sy)

        {

            if(d>0)

            {

                d+=d2;

                x+=sx;

            }

            else d+=d1;

            Canvas->Pixels[x][y] = color;

    }

 

 

Задание 4 Рисование блок-схемы

1.     Нарисуйте детальную блок-схему данного алгоритма и реализуйте его на языке программирования. Программа должна выводить исходный многоугольник на экран, а затем, если многоугольник не выпуклый, то при нажатии любой из клавиш он должен разбиваться на n выпуклых многоугольников и результаты разбиения должны выводиться на экран. Координаты исходного многоугольника должны содержаться в файле на диске.

2.     Выясните, будет ли работать ваша программа с многоугольником, изображенном на рисунке 3.

3.     Скорректируйте вашу программу так, чтобы она работала с любыми невыпуклыми многоугольниками.

 

Рис. 1

Алгоритм разбиения невыпуклых многоугольников для отдельных случаев может быть представлен в следующей последовательностью:

1.     найти вогнутую вершину.

2.     соединить вогнутую вершину с предыдущей через одну.

   3.  проанализировать каждый из вновь образованных многоугольников (п.1,2,3)

Рис. 2                           Рис. 3

Для уменьшения размеров алгоритма  все последовательные операции были перечислены виде информационных блоков, все выражения и функции подробно указаны в листинге программы.

Данная программа выводит исходный многоугольник, взяв координаты вершин из заранее подготовленного файла, автоматически производит его анализ и построение на экране. Если многоугольник выпуклый, то его разбиения не  происходит. В противном случае, программа находит вогнутую вершину и соединяет её с предыдущей через одну. В программе исходный многоугольник отображён красным цветом, а результат его разбиения синим.

Достоинство данной программы заключается в том, что она (программа) позволяет строить многоугольники с произвольным (любым количеством) вершин.

Программа работает с различными видами многоугольников, независимо от их сложности и количества вершин.

ПОРЯДОК РАБОТЫ С ПРОГРАММОЙ

1. Для ввода исходных данных необходимо открыть текстовый файл “text” ввести построчно координаты Х , Y таким образом, чтобы координаты X ,Y одной вершины были расположены на одной строке и разделены пробелом.

2. Закрыть файл, сохранив изменения.

3. Запустить файл   Project1.ехе

4. Кликнуть два раза по открывшейся форме.

5. Во вновь появившемся меню выбрать файл “text”.

6. Нажать кнопку «ОТКРЫТЬ» и программа автоматически произведёт построение фигуры с заданными вершинами. Исходный многоугольник отображён красным цветом, а результат его разбиения синим

ЛИСТИНГ ПРОГРАММЫ РАЗБИЕНИЯ МНОГОУГОЛЬНИКОВ

unit Unit1;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, ExtCtrls;

type

  TForm1 = class(TForm)

    Image1: TImage;

    OpenDialog1: TOpenDialog;

    procedure Image1Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

    procedure Razb(X,Y:TStringList);

  end;

  TLine = record  //для хранения уравнения линии

    K,

    B : Real;

  end;

var

  Form1: TForm1;

  X,Y:TStringList;

  function GetUrLine(sx1,sy1, sx2,sy2:String):TLine;

  function Sravnit(zUrLine:TLine; X,Y:String):Boolean;

implementation

uses StrUtils;

{$R *.dfm}

//------------------------------------------------------------------------------

//Проверяет лежит ли точка выше прямой, задоваемой уравнением

function Sravnit(zUrLine:TLine; X,Y:String):Boolean;

begin

  Result:=(zUrLine.K*StrToInt(X)+zUrLine.B)>StrToInt(Y);

end;

//------------------------------------------------------------------------------

//Возвращает уравнение прямой

function GetUrLine(sx1,sy1, sx2,sy2:String):TLine;

var x1,y1, x2,y2:Integer;

begin

  x1:=StrToInt(sx1);

  y1:=StrToInt(sy1);

  x2:=StrToInt(sx2);

  y2:=StrToInt(sy2);

  if x1=x2 then Result.K:=100000

           else Result.K:=(y2-y1)/(x2-x1);

  Result.B:=y1-Result.K*x1;

end;

//------------------------------------------------------------------------------

//Процедура разбиения многогранника на выпуклые...

procedure TForm1.Razb(X,Y:TStringList);

var i, j, k, ks, f:Integer;

    Pr, PrLine:Boolean;

    UrLine:TLine;

    X1,Y1 : TStringList;

begin

 

  //поиск точки старта поиска

  f:=0;

  pr:=True;

  while Pr do

  begin

    if f+1>X.Count-1 then k:=f+1-X.Count else k:=f+1;

    UrLine:=GetUrLine(X[f],Y[f], X[k],Y[k]);

    if f+2>X.Count-1 then k:=f+2-X.Count else k:=f+2;

    PrLine:=Sravnit(UrLine, X[k],Y[k]);

    ks:=0;

    for j:=2 to X.Count-1 do

    begin

      if f+j>X.Count-1 then k:=f+j-X.Count else k:=f+j;

      if PrLine=Sravnit(UrLine, X[k],Y[k]) then Inc(ks);

    end;

    pr:=not(ks=X.Count-2);

    f:=f+1;

  end;

  f:=f-1;

  //Проверяем выпуклый ли многоугольник....

  Pr:=True;

  i:=0;

  while Pr and (i<X.Count) do

  begin

    if i+1+f>X.Count-1 then k:=i+1+f-X.Count else k:=i+f+1;

    UrLine:=GetUrLine(X[i+f],Y[i+f], X[k],Y[k]);

    if i+2+f>X.Count-1 then k:=i+f+2-X.Count else k:=i+f+2;

    PrLine:=Sravnit(UrLine, X[k],Y[k]);

    ks:=0;

    for j:=2 to X.Count-1 do

    begin

      if i+f+j>X.Count-1 then k:=i+f+j-X.Count else k:=i+f+j;

      if PrLine=Sravnit(UrLine, X[k],Y[k]) then Inc(ks);

    end;

    pr:=(ks=X.Count-2);

    i:=i+1;

  end;

  if not(Pr) then  //многоугольник не выпуклый

  begin

    //Рисуем доп. линию (треугольник)

   

    with Image1.Canvas do

    begin

      Pen.Color:=clBlue;   //синим цветом

      Pen.Width:=3;        //толщиной 3 пикселя

      if i+f>x.Count-1 then k:=i-X.Count+f else k:=i+f;

      MoveTo(StrToInt(X[k]), StrToInt(Y[k]));

      if i-2+f<0 then k:=X.Count-2+f else k:=i-2+f;

      LineTo(StrToInt(X[k]), StrToInt(Y[k]));

    end;

    X1:=TStringList.Create;

    Y1:=TStringList.Create;

    if X.Count>4 then

    begin

      for j:=0 to X.Count-2 do

      begin

        if i+j+f>X.Count-1 then k:=i+j+f-X.Count else k:=i+f+j;

        X1.Add(X[k]);

        Y1.Add(Y[k]);

      end;

      Razb(X1,Y1);

    end;

  end;

end;

//------------------------------------------------------------------------------

//Открытие файла

procedure TForm1.Image1Click(Sender: TObject);

var zList:TStringList;

    i,j:Integer;

begin

  if OpenDialog1.Execute then

  begin

    X:=TStringList.Create;

    Y:=TStringList.Create;

    zList:=TStringList.Create;

    zList.LoadFromFile(OpenDialog1.FileName);

    for i:=0 to zList.Count-1 do

    begin

      j:=PosEx(' ',zList[i]);

      X.Add(copy(zList[i],1,j-1));

      Y.Add(copy(zList[i],j+1,length(zList[i])-j))

    end;

    //Нарисовать исходный многогранник

    with Image1.Canvas do

    begin

      Pen.Color:=clRed;    //красным цветом

      Pen.Width:=4;        //ширина линии - 4

      MoveTo(StrToInt(X[0]), StrToInt(Y[0]));

      for i:=1 to X.Count-1 do

        LineTo(StrToInt(X[i]), StrToInt(Y[i]));

      LineTo(StrToInt(X[0]), StrToInt(Y[0]));

    end;

    Razb(X,Y);           //процедура разбиения

  end;

end;

end.

Список литературы

1.           Багриновский К.А., Хрусталев Е.Ю. Программирование на зыках высокого уровня. - М.: “ЭКО”. 2004.

2.           Белинов С.В., Зайцев А.А. Современные информационные технологии. – М.: Инфра-М, 2003.

3.           Шафрин Ю. А. Программирование на языке С++. - М.: АБФ, 2005.

4.           Lavel. Graphics. Растровая и векторная графика: http://win-www.klax.tula.ru/~level/graphics/predgrph.html

5.           Векторная графика на языках С++ и Delphi: электронный учебник– http://imped.vgts.ru/polygraph/vektor.html

6.           Семенов Р.Ж. О векторной и растровой графике // Компьютера, №3, 2003.  http://flashmaker.8m.com/help/html/02basics2.html