Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП / Лабы / Lab5C.doc
Скачиваний:
27
Добавлен:
18.02.2017
Размер:
972.29 Кб
Скачать

Блок1. Представление динамических процессов в динамике

Задача 1. Вычисление свертки комплексных Chirp-сигналов.

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

Рис. 3. Пример программы со сверткой Chirp-сигналом (показан момент движения сигнала)

Обратите внимание, что сигнал вычисляется как sin- и cos-составляющие. COS-составляющая неподвижного сигнала совпадает с cos-составляющей, а SIN- имеет противоположный знак по отношению к sin-составляющей.

Вынесите на форму органы управления процессом синтеза сигнала и его обработки:

  • параметр для построения параболы для sin и cos;

  • количество отсчетов сигнала;

  • скорость движения сигнала.

Задача 2. Вычисление свертки комплексных Chirp-сигналов со взвешиванием.

Аналогична Задаче 1, но неподвижный сигнал (обе комплексные составляющие – COS и SIN) нужно взвесить по амплитуде так, как показано на рис. 4. Для этого используется фрагмент синусоиды, взятой с амплитудой 0,92 и поднятой на пьедестал высотой 0,08. Сравните результат работы программы аналогичным в Задаче 1. На рис. 5 – окно программы. Необходимо осуществить перемещение сигнала (как в Задаче 1).

Рис. 4. Огибающая неподвижного сигнала (и для COS, и для SIN)

Рис. 5. Окно программы

Задача 3. Свертка сигналов типа М-последовательность

Сигнал состоит из чередующихся отсчетов +1 и –1. Для его генерации используется следующий алгоритм (рис. 6).

В примере показан случай N=8 разрядов. Длина последовательности составит 2N-1=255 чисел. В квадратах заданы разряды фазы, в кружках – разряды маски. Если разряд маски равен «0», то соответствующий разряд фазы игнорируется. Если разряд маски равен «1», то разряд фазы учитывается. Далее все прошедшие через маску разряды фазы суммируются по модулю 2 (берется остаток от деления суммы на 2, т.е. могут получится только «0» или «1»). Затем эта сумма (0 или 1) поступает в левый разряд фазы, остальные сдвигаются вправо (крайний правый разряд уничтожается). Таким образом, обеспечивается цикл из 2N-1 шагов. В генераторе циркулируют только «0» и «1».

Выходной сигнал формируется на основе получаемого в каждом такте работы генератора значения суммы по модулю 2. При этом «1» кодируется символом «1», а «0» – символом «–1».

В качестве органов управления генератором (для задания разрядов фазы и маски) используйте компоненты Edit.

Рис. 6. Генератор для сигнала типа М-последовательность

Аналогично Задачам 1 и 2 необходимо осуществить операцию свертки получившейся М-последовательности. Рабочее окно программы приведено на рис. 7. Необходимо осуществить перемещение сигнала (как в Задаче 1).

Р ис. 7. Результат работы программы с сигналом типа М-последовательности

Блок 2. Многодокументное приложение (MultiDocumentInterface).

Создайте новый проект (File/New/Projects/MDI) и сохраните его в новой папке. В результате высветится главное окно (рис. 8).

Изучите состав файлов, включенных в проект (View/Unit).

Рис. 8. Главное окно MDI-приложения

Откройте файл «childwin.cpp», входящий в проект. Убедитесь, что на форме «childwin.dfm» размещен Memo1, причем его свойство Align= alClient. Это означает, что при изменении размера окна Memo1 будет занимать все доступное клиентское пространство. Установите Align= alNone. Запустите приложение. Выполните команды File/Open и File/New. Убедитесь, что приложение открывает текстовые файлы и отображает их в Memo1. Измените размеры дочерних окон, убедитесь, что размер Memo1 не изменяется при изменении окна.

Вернитесь в среду разработки и разберите файл «main.cpp», а именно:

– создание нового дочернего окна и загрузка его содержимого (void __fastcall TMainForm::CreateMDIChild(String Name)).

Далее кликните по компоненту ActionList1 на главной форме (рис. 8). Он связывает все команды, поступающие от горячих клавиш, меню и кнопок на панели инструментов текущего приложения. В появившемся окне в категории File выделите действие FileNew1 (рис. 9). Изучите его свойтва в Object Inspector, рассмотрите обработчик события OnExecute.

Рис. 9. Работа с компонентом ActionList1

Таким образом, все команды, осуществляемые в программе, сведены в ActionList1.

Изучите остальные функции в программе «main.cpp».

Добавьте новую команду «SetProperties» в ActionList1. Создайте категорию «SetProperties» и поместите в нее созданную команду.

Назначьте команде «SetProperties» горячую клавишу HotKey= «Ctrl+T».

Найдите на главной форме приложения компонент ImageList1, откройте его и найдите картинку с №10. Вернитесь к команде «SetProperties» в ActionList1. Установите свойство ImageIndex=10.

Задайте команде «SetProperties» свойство Hint= «Свойства|Свойства окна».

С помощью компонента MainMenu1 добавьте в главное меню программы категорию «Настройка», в него добавьте команду «Свойства». Для этого используйте созданную команду «SetProperties» из ActionList1: установите свойство Action= SetProperties для команды меню.

Добавьте кнопку «Свойства» на панель инструментов (с помощью правой кн. мыши). Задайте кнопке свойство Action= SetProperties.

Добавьте в проект еще одну форму (Form1). На ней разместите все органы управления для генерации сигнала (см. свою задачу из первого блока). Разместите кнопки «Ок» и «Применить». Расставьте #include в соответствующих местах MainForm и Form1 так, чтобы они были «видны» друг другу.

Необходимо по команде «Свойства» вывести эту форму на экран в модальном режиме, для чего в команде «SetProperties» из ActionList1 добавьте обработчик:

Form1->ShowModal();

При появлении формы Form1 на экране органы управления должны принять текущие значения из активного дочернего окна (обработчик OnActivate для Form1):

if (MainForm->MDIChildCount)

Edit1->Text=((TMDIChild *) MainForm->MDIChildren[0])-> …

Здесь: MDIChildCount – количество открытых дочерних окон (стандартная переменная).

MDIChildren[0] – активное дочернее окно.

Для кнопки «Применить» нужно сделать обратную операцию – скопировать значения из формы в активное дочернее окно.

Обработчик кнопки «Ок» аналогичен обработчику кнопки «Применить», но в нем нужно выполнить ModalResult=mrOk.

Запрограммируйте команды Save и Load так, чтобы во внешний файл записывались и читались параметры сигналов из текущего дочернего окна. Используйте алгоритм «Сохранить поверх?» из лабораторной работы №2.

Блок 3. Механизм наследования и динамические списки.

Рассмотрите приведенный ниже листинг динамического списка, базовый класс для которого – TImage. Обратите внимание на статические элементы класса и передачу параметров в конструктор базового класса. Оптимизируйте код.

//Mans.h

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

#ifndef Unit2H

#define Unit2H

class TMan : public TImage

{

__published:

__property OnMouseDown;

__property OnMouseMove;

__property OnMouseUp;

private:

void _fastcall MouseDown

(TMouseButton Button, Classes::TShiftState Shift, int X, int Y);

void _fastcall MouseMove

(Classes::TShiftState Shift, int X, int Y);

void _fastcall MouseUp

(TMouseButton Button, Classes::TShiftState Shift, int X, int Y);

int X0, Y0; //каждому-свое

bool Moved; //каждому-свое

TMan* Next; //каждому-свое

int Num; //каждому-свое

public:

//***************

String sName;

int iIQ;

//***************

static TMan* ManHead;

static int Active;

TComponent* own;

int ManCNT;

static void __fastcall SetHead(TMan* H)

{

ManHead = H;

}

static TMan* __fastcall GetHead(void)

{

return ManHead;

}

__fastcall TMan (Classes::TComponent *Owner):TImage(Owner)

{

own = Owner;

SetHead(NULL);

ManCNT=0;

}

__fastcall TMan (Classes::TComponent *Owner, int smth):TImage(Owner)

{

}

int GetAbsNum(int n)

{

int ret = 0;

TMan *p = GetHead();

while ((p!=NULL) && (n!=p->Num))

{

ret++;

p = p->Next;

}

return ret;

}

static void __fastcall SetActive(int n)//TMan* pM)

{

TMan *p = GetHead();

while (p!=NULL)

{

if (p->Num==n)

{

p->Border(clWhite); //активный

}

else p->Border(clGray); //сбросить активность

p = p->Next;

}

Active = n;

}

TMan* __fastcall GetItem(int n)

{

TMan *p = GetHead(),

*ret=NULL;

while (p!=NULL)

{

if (p->Num==n) ret=p;

p = p->Next;

}

return ret;

}

void __fastcall Add(String Name, int x,int y, String sN="Unknown", int iI=100)

{

TMan *Im= new TMan(own,10);

Im->Parent = (TWinControl*) own; //предок для объектов TMan

Im->Num=TMan::ManCNT;

Im->Active = false;

Im->sName = sN;

Im->iIQ = iI;

Im->Canvas->TextOut(1,1,IntToStr(Im->Num));

if(GetHead()==NULL)

{

SetHead(Im);

GetHead()->Next=NULL;

}

else

{

Im->Next=GetHead();

SetHead(Im);

}

ManCNT++;

Im->AutoSize = true;

Im->Moved = false;

SetPhoto(Im->Num,Name);

SetActive(Im->Num);

Im->Border (clGray);

Im->Left=x;

Im->Top=y;

}

void _fastcall Delete(int IDman);

void Border (TColor cl)

{

Picture->Bitmap->Canvas->Pen->Color = cl;

Picture->Bitmap->Canvas->MoveTo(0,0);

Picture->Bitmap->Canvas->LineTo(Width-1,0);

Picture->Bitmap->Canvas->LineTo(Width-1,Height-1);

Picture->Bitmap->Canvas->LineTo(0,Height-1);

Picture->Bitmap->Canvas->LineTo(0,0);

}

void SetPhoto(int n, String Name)

{

TMan *p = GetHead();

while (p!=NULL)

{

if (p->Num==n) p->Picture->LoadFromFile(Name);

p = p->Next;

}

}

};

TMan* TMan::ManHead = NULL;

int TMan::Active = -1;

//------------------------------------------------------*********************************

#endif

//Mans.cpp

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

#include <vcl.h>

#pragma hdrstop

#include "mans.h"

#include "unit1.h"

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

#pragma package(smart_init)

//************

void _fastcall TMan::Delete(int IDman)

{

TMan *p = GetHead();

if (GetHead()!=NULL)

{

if (p->Num == IDman) //удаляем первый элемент

{

SetHead(GetHead() -> Next);

delete p;

p = NULL;

}

else

{ //ищем и удаляем не-первый элемент

while (p!=NULL)

{

if (p->Next!=NULL)

{

if ( (p->Next)-> Num == IDman)

{

TMan *del = p->Next;

p->Next = p->Next->Next;

delete del;

p = NULL;

}

else

p = p->Next;

}

else p=NULL;

}

}

}

SetActive(-1);

}

//************************************

void _fastcall TMan::MouseDown

(TMouseButton Button, Classes::TShiftState Shift, int X, int Y)

{

X0=X;

Y0=Y;

Moved=true;

SetActive(this->Num);

BringToFront();

Form1->Edit1->Text = sName;

Form1->Edit2->Text = IntToStr(iIQ);

}

//************************************

void _fastcall TMan::MouseMove

(Classes::TShiftState Shift, int X, int Y)

{

if (Moved)

{

Left += -X0 + X;

Top += -Y0 + Y;

}

}

//************************************

void _fastcall TMan::MouseUp

(TMouseButton Button, Classes::TShiftState Shift, int X, int Y)

{

Moved=false;

}

//************************************

Задача 1. Создайте приложение, содержащее компонент TScrollBox. Создайте свой класс, являющийся наследником класса TLabel и хранящий список элементов TLabel. Обеспечьте добавление элементов списка, его перемещение, редактирование текста в элементах (по двойному щелчку) и удаление элементов.

Задача 2. Аналогично Задаче 1, но используйте компонент TShape. По двойному щелчку обеспечьте смену его формы (свойство Shape).

Задача 3. Аналогично Задаче 1, но используйте компонент TBevel. По двойному щелчку обеспечьте смену его формы (свойство Shape).

Соседние файлы в папке Лабы