Программа простейшего варианта имитации движения окружностей
Государственное образовательное
учреждение
Высшего профессионального образования
«Санкт-Петербургский государственный
технологический институт
(технический университет)»
Факультет информационных технологий и
управления
Специальность: 230100 «Автоматизированные
системы обработки информации и управления»
Кафедра систем автоматизированного
Проектирования и управления
Курсовая работа
По дисциплине: «Программирование»
Выполнил: Мордюк Д.О.
Группа № 321
Проверил: Брасов В.Н.
Санкт-Петербург
г.
Постановка
задачи:
Используя библиотеку MFC, необходимо разработать программу, которая
позволит решить следующие задачи:
. Создать 30 окружностей со случайными параметрами (координаты
центра, радиус, цвет) и вывести их на экран.
. Обеспечить интерфейс изменения параметров окружностей.
. Созданные окружности должны перемещаться по определенному закону
в соответствии с вариантами заданий.
Исходные
данные:
Окружности перемещаются слева направо, при достижении правой границы они
перемещаются скачком к левой границе и случайным образом меняется радиус
окружностей в пределах 1 - 30.
Особые
ситуации:
1. При инициализации окружности не должны накладываться друг на
друга.
. В процессе перемещения окружности не должны вылетать за
указанные координаты экранной области.
Алгоритм
решения задачи:
Для реализации движения окружностей был написан алгоритм приводящий к их
перемещению слава направо с последующим появлением окружностей в левой части
экрана, при достижении ими правой границы. Алгоритм представляет собой
простейший вариант имитации движения окружностей.
Структура
программы:
Библиотека MFC (Microsoft Foundation Classes) предлагает поддержку модели
документ/представление, в которой логика работы приложения явным образом
отделяется от кода, ответственного за пользовательский интерфейс.
Разделение происходит как на уровне файлов (этот код содержится в разных
единицах трансляции), так и на уровне классов - за хранение данных приложения и
работу с ними отвечает один класс, а за реализацию пользовательского интерфейса
- другой.
В нашем случае код этих классов размещён в следующих файлах:
Класс
|
Файл
|
Назначение
|
CSpheresDoc
|
SpheresDoc.h
|
Заголовочный файл
документа, хранящего данные приложения.
|
|
SpheresDoc.cpp
|
Исходный файл документа,
хранящего данные приложения.
|
CSpheresView
|
SpheresView.h
|
Заголовочный файл вида.
|
|
SpheresView.cpp
|
Исходный файл вида,
отвечающий за отображение информации.
|
Форматы
представления данных:
В программе использовались следующие константы:
Имя
|
Тип
|
Значение
|
Описание
|
min_radius
|
const int
|
1
|
Минимальный радиус
окружности
|
max_radius
|
const int
|
40
|
Максимальный радиус
окружности
|
nCircles
|
const int
|
30
|
Число создаваемых
окружностей
|
nTries
|
const int
|
1000
|
Число попыток установить
окружность
|
microsoft
foundation classes алгоритм
Для хранения координат точки на экране (точками задаются центры
окружностей), а также, для задания скорости смещения по осям X и Y во время
перемещения используется структура: vec2d.
Для задания параметров окружностей используется структура Circle, в
которой определены:
pos -
структура vec2d, центр окружности (pos.x и pos.y координаты X и Y
соответственно);- радиус окружности;- структура vec2d, скорость перемещения
(velocity.x и velocity.y скорости перемещения по осям);- цвет окружности.
В программе использовались следующие функции:
Имя
|
Описание
|
SpheresDoc.cpp
|
int GetCircleIndex(const
CPoint& pt) const
|
Позволяет по точке в
плоскости получить индекс окружности, которая содержит эту точку
|
Возвращает ссылку на
окружность по её индексу
|
void DrawCircle(CDC *pDC)
|
Отрисовка окружностей
|
bool IsIntersect(Circle)
|
Определение пересечения
окружностей
|
void DoSimulation()
|
Функция содержит алгоритм
движения
|
SpheresView.cpp
|
afx_msg void
OnTimer(UINT_PTR nIDEvent)
|
Функция по таймеру
осуществляет вызов DoSimulation() таким образом реализуя один шаг имитации
движения
|
afx_msg void
OnLButtonDown(UINT nFlags, CPoint point)
|
Отслеживание нажатия левой
кнопки мыши
|
afx_msg void
OnMouseMove(UINT nFlags, CPoint point)
|
Отслеживание перемещения
мыши
|
afx_msg void
OnLButtonUp(UINT nFlags, CPoint point)
|
Отслеживание отпускания
левой кнопки мыши
|
afx_msg void
OnActionStartsimulation()
|
Запустить имитацию движения
окружностей посредством пункта меню или нажатия F5
|
afx_msg void
OnActionStopsimulation()
|
Остановить имитацию
движения окружностей посредством пункта меню или нажатия F6
|
afx_msg void
OnRButtonDown(UINT nFlags, CPoint point)
|
Отслеживание нажатия правой
кнопки мыши для вызова контекстного меню
|
afx_msg void
PopupMenuCircleProps()
|
Вызов окна изменения
радиуса окружностей
|
afx_msg void
PopupMenuCircleColor()
|
Вызов окна изменения цвета
окружностей
|
Результаты
работы программы:
При запуске программы создаются окружности. Их можно перемещать курсором
мыши, изменять радиус и цвет. Запустить/остановить имитацию движения
окружностей можно с помощью соответствующего пункта меню Action или нажатием
функциональных клавиш F5/F6.
Листинг программы
.h
// SpheresDoc.h : interface of the CSpheresDoc class
//
#include<vector>
#pragma oncevec2d {d () {}d (double x, double y) : x(x),
y(y){}d (vec2d const& other) : x(other.x), y(other.y){}
// ACCESSORSlength() const;
// MANIPULATORSd& operator+=(vec2d const&
other);d& operator-=(vec2d const& other);d& operator*=(double
value);d& operator/=(double value);d& normalize();x,y;
};Circle {() : velocity(1,0), color(RGB(0,0,0)) {}
vec2d pos;d velocity;
// Переменная color хранит информацию о цвете окружности
COLORREF color;radius;
};CSpheresDoc : public CDocument
{: // create from serialization
only();_DYNCREATE(CSpheresDoc)
// Attributes:::vector<Circle> m_circles;m_area;
// Operations:GetCircleIndex(const CPoint& pt) const;
Circle& GetCircleById(int id);
// Описание метода DrawCircle для прорисовки окружностей в
окнеDrawCircle(CDC *pDC);
// Проверка на пересечение окружностейIsIntersect(Circle);
// Моделирование движения окружностей
void DoSimulation();
// Overrides:BOOL OnNewDocument();void
Serialize(CArchive& ar);
// Implementation:~CSpheresDoc();
#ifdef _DEBUGvoid AssertValid() const;void
Dump(CDumpContext& dc) const;
#endif:
// Generated message map functions:_MESSAGE_MAP()
};
SpheresDoc.cpp
// SpheresDoc.cpp : implementation of the CSpheresDoc class
//
#include "stdafx.h"
#include "Spheres.h"
#include <sstream>
#include "SpheresDoc.h"
#include <math.h>
#include <algorithm>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSpheresDoc_DYNCREATE(CSpheresDoc,
CDocument)_MESSAGE_MAP(CSpheresDoc, CDocument)_MESSAGE_MAP()
// CSpheresDoc construction/destruction::CSpheresDoc()
{
// TODO: add one-time construction code here
}::~CSpheresDoc(){}int bottom=660,right=660, min_radius=1,
max_radius=40,nCircles = 30,nTries = 1000;CSpheresDoc::OnNewDocument()
// TODO: add reinitialization code here
// (SDI documents will reuse this
document)(!CDocument::OnNewDocument()) return FALSE;
// Размеры виртуальной области
m_area = CRect(0,0,bottom,right);
const int area_width = m_area.right - m_area.left;int
area_high = m_area.bottom - m_area.top;_circles.clear();(int tries=0 ; tries
< nTries && m_circles.size() < nCircles; tries++) {cir;.pos.x =
(int)(rand()%(area_width-2*max_radius)+max_radius);.pos.y =
(int)(rand()%(area_high-2*max_radius)+max_radius);.radius=
rand()%(max_radius-min_radius)+min_radius;.color=RGB(rand()%255,rand()%255,rand()%255);
// Проверка на пересечение с существующими
окружностями(!IsIntersect(cir))_circles.push_back(cir); // Пересечения нет -
ставим окружность
}TRUE;
}
// CSpheresDoc
serializationCSpheresDoc::Serialize(CArchive& ar)
{(ar.IsStoring())
{
// TODO: add storing code here
}
{
// TODO: add loading code here
}
}
// CSpheresDoc diagnostics
#ifdef _DEBUGCSpheresDoc::AssertValid() const
{::AssertValid();
}CSpheresDoc::Dump(CDumpContext& dc) const
{::Dump(dc);
}
#endif //_DEBUG
// CSpheresDoc commandsCSpheresDoc::GetCircleIndex(const
CPoint& pt) const
{(int i=(int)m_circles.size()-1; i >= 0; i--)(
pow(pt.x-m_circles[i].pos.x,2) +(pt.y-m_circles[i].pos.y,2) <
pow(m_circles[i].radius,2))i;-1;
}& CSpheresDoc::GetCircleById(int id)
{m_circles[id];
}
// Проверка на пересечение с существующими окружностями
bool CSpheresDoc::IsIntersect(Circle cir)
{(unsigned int i=0; i<m_circles.size();
i++)(sqrt(pow(cir.pos.x - m_circles[i].pos.x, 2) +(cir.pos.y -
m_circles[i].pos.y, 2)) <=.radius+m_circles[i].radius)true;false;
}CSpheresDoc::DrawCircle(CDC *pDC)
{x, y, r;int min_drawable_radius=2;(unsigned int i=0;
i<m_circles.size(); i++)
{= (int)m_circles[i].pos.x;= (int)m_circles[i].pos.y;=
(int)max(m_circles[i].radius, min_drawable_radius);pen(PS_SOLID,1,m_circles[i].color);>SelectObject(&pen);>Ellipse(x-r,y-r,x+r,y+r);
}
}obn=false;mass[nCircles];CSpheresDoc::DoSimulation()
{ch=1;(!obn)
{(int i=0; i<nCircles; i++)[i]=-1;=true;
}(unsigned int i=0; i<m_circles.size(); i++)
{(mass[i]!=i)
{((m_circles[i].pos.x+m_circles[i].radius)>=bottom)
{[i]=i;_circles[i].color=RGB(rand()%255,rand()%255,rand()%255);_circles[i].pos.x
-=ch;
}_circles[i].pos.x +=ch;
}
{((m_circles[i].pos.x-m_circles[i].radius)<=0)
{[i]=-1;_circles[i].color=RGB(rand()%255,rand()%255,rand()%255);_circles[i].pos.x
+=ch;
}
{_circles[i].pos.x
-=ch+3;_circles[i].radius=rand()%max_radius+min_radius;
}
}
}(NULL);
}
SpheresView.h
// SpheresView.h : interface of the CSpheresView class
//
#pragma onceCSpheresView : public CView
{: // create from serialization
only();_DYNCREATE(CSpheresView)
// Attributes:* GetDocument() const;selected_circle;
// Operations:
// Overrides:void OnDraw(CDC* pDC); // overridden to draw
this viewBOOL PreCreateWindow(CREATESTRUCT& cs);:
// Implementation:~CSpheresView();
#ifdef _DEBUGvoid AssertValid() const;void
Dump(CDumpContext& dc) const;
#endif:
// Generated message map functions:_MESSAGE_MAP():_msg void
OnTimer(UINT_PTR nIDEvent);_msg void OnLButtonDown(UINT nFlags, CPoint point);_msg
void OnMouseMove(UINT nFlags, CPoint point);_msg void OnLButtonUp(UINT nFlags,
CPoint point);_msg void OnActionStartsimulation();_msg void
OnActionStopsimulation();_msg void OnRButtonDown(UINT nFlags, CPoint
point);_msg void PopupMenuCircleProps();_msg void PopupMenuCircleColor();_msg
void OnActionStopsimulaton();
};
#ifndef _DEBUG // debug version in
SpheresView.cppCSpheresDoc* CSpheresView::GetDocument() const
{ return reinterpret_cast<CSpheresDoc*>(m_pDocument); }
#endif
SpheresView.cpp
// SpheresView.cpp : implementation of the CSpheresView class
//
#include "Spheres.h"
#include "SpheresDoc.h"
#include "SpheresView.h"
#include "DlgCircleProps.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSpheresView_DYNCREATE(CSpheresView, CView)_MESSAGE_MAP(CSpheresView,
CView)
//
ON_WM_TIMER()_WM_LBUTTONDOWN()_WM_MOUSEMOVE()_WM_LBUTTONUP()
//ON_WM_CONTEXTMENU()_COMMAND(ID_ACTION_STARTSIMULATION,
&CSpheresView::OnActionStartsimulation)_COMMAND(ID_ACTION_STOPSIMULATION,
&CSpheresView::OnActionStopsimulation)_WM_TIMER()_WM_RBUTTONDOWN()_COMMAND(ID__PROPERTIES,
&CSpheresView::PopupMenuCircleProps)_COMMAND(ID__COLOR,
&CSpheresView::PopupMenuCircleColor)_COMMAND(ID_ACTION_STOPSIMULATON,
&CSpheresView::OnActionStopsimulaton)_MESSAGE_MAP()
// CSpheresView construction/destruction::CSpheresView() :
selected_circle(-1)
{
// TODO: add construction code here
}::~CSpheresView()
{
}CSpheresView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT csCView::PreCreateWindow(cs);
}
// CSpheresView drawingCSpheresView::OnDraw(CDC* pDC)
{
// Получение указателя на документ и проверка его валидности
CSpheresDoc* pDoc = GetDocument();_VALID(pDoc);(!pDoc);
// Рисование окружностей>DrawCircle(pDC);
}
// CSpheresView diagnostics
#ifdef _DEBUGCSpheresView::AssertValid() const
{::AssertValid();
}CSpheresView::Dump(CDumpContext& dc) const
{::Dump(dc);
}* CSpheresView::GetDocument() const // non-debug version is
inline
{(m_pDocument->IsKindOf(RUNTIME_CLASS(CSpheresDoc)));(CSpheresDoc*)m_pDocument;
}
#endif //_DEBUGCSpheresView::OnLButtonDown(UINT nFlags,
CPoint point)
{
// Получение указателя на документ и проверка его валидности
CSpheresDoc* pDoc = GetDocument();_VALID(pDoc);
if (!pDoc);
// Запросить индекс окружности, в которой находится точка
selected_circle =
pDoc->GetCircleIndex(point);::OnLButtonDown(nFlags, point);
}CSpheresView::OnMouseMove(UINT nFlags, CPoint point)
{
// Получение указателя на документ и проверка его валидности
CSpheresDoc* pDoc =
GetDocument();_VALID(pDoc);(!pDoc);(selected_circle != -1){
// Перемещение окружности в точку, указанную мышью
pDoc->GetCircleById(selected_circle).pos.x =
point.x;>GetCircleById(selected_circle).pos.y = point.y;();
}::OnMouseMove(nFlags, point);
}CSpheresView::OnLButtonUp(UINT nFlags, CPoint point)
{_circle = -1;::OnLButtonUp(nFlags, point);
}CSpheresView::OnActionStartsimulation()
{(1,0,NULL);
}CSpheresView::OnActionStopsimulation()
{(1);
}CSpheresView::OnActionStopsimulaton()
{(1);
}CSpheresView::OnTimer(UINT_PTR nIDEvent)
{* pDoc =
GetDocument();_VALID(pDoc);(!pDoc);>DoSimulation();::OnTimer(nIDEvent);
}CSpheresView::OnRButtonDown(UINT nFlags, CPoint point)
{* pDoc =
GetDocument();_VALID(pDoc);(!pDoc);screen_point(point);(&screen_point);_circle
= pDoc->GetCircleIndex(point);(selected_circle != -1) {
// Popup menupopup;.LoadMenu(IDR_MENU_POPUP);*
real_menu=popup.GetSubMenu(0);_menu->TrackPopupMenu(TPM_LEFTALIGN,screen_point.x,screen_point.y,this);
}::OnRButtonDown(nFlags, point);
}CSpheresView::PopupMenuCircleProps()
{* pDoc = GetDocument();_VALID(pDoc);(!pDoc);
// Создание диалогаdlg;
// Инициализация данных
диалога.m_radius=pDoc->GetCircleById(selected_circle).radius;
// Отображение диалога и проверка выхода по нажатию «ОК»(dlg.DoModal() == IDOK)
// Если радиус
был изменён( pDoc->GetCircleById(selected_circle).radius !=
dlg.m_radius ) {
// Обновить радиус>GetCircleById(selected_circle).radius = dlg.m_radius;
// Перерисовать окно();
}CSpheresView::PopupMenuCircleColor()
{* pDoc =
GetDocument();_VALID(pDoc);(!pDoc);dlg;(dlg.DoModal() == IDOK)(
pDoc->GetCircleById(selected_circle).color != dlg.GetColor() )
{>GetCircleById(selected_circle).color = dlg.GetColor();
Invalidate();
}_circle = -1;
}