Здавалка
Главная | Обратная связь

Тема: Расчет траектории движения



Задание: Создание модели движения тел по определенной траектории.

(http://programmersforum.ru/showthread.php?t=25052&highlight=%F1%EE%EB%ED%E5%F7%ED%E0%FF+%F1%E8%F1%F2%E5%EC%E0)

Рассмотрим способы моделтрования движения простых тел на примере модели солнечной системы.

1) Параметры модели:

· солнечная система представляет собой солнце и вращающиеся вокруг него 9 планет. Каждая из них имеет свою орбиту, свою скорость, массу и т.д.

На заметку: планет всего 8, а 9-я - это астероид прилетевший с астероидного пояса ), но мы же не астрономы J.

· размеры планет будут отрисовываться не в масштабе, но так, чтобы все планеты были различимы.

· орбиты планет будут представлену упрочено – окружностями

· параметры планет: http://www.astronet.ru/db/msg/eid/FK86/planets

Параметр Меркурий Венера Земля Марс Юпитер Сатурн Уран Нептун Плутон
Среднее расстояние от Солнца, а.е. 0,387 0,723 1,000 1,524 5,20 9,54 19,18 30,07 39,44
Сидерический период обращения 88,0 сут 224,7 сут 365,3 сут 687,0 сут 11,86 лет 29,46 лет 84,01 лет 164,8 лет 247,7 лет
Масса, кг 3,28e23 4,88e24 5,98e24 6,40e23 1,90e27 5,68e26 8,70e25 1,03e26 1,0e22
Масса (в единицах земной массы) 0,005 0,816 1,000 0,107 95,1 14,6 17,2 0,0017

2) Создайте проект File->New->VCL Forms Application C++ Builder

· Свойствам формы в инспекторе объектов задайте значения:

Left: 0

Top: 0

ClientWidth: 800

ClientHeight: 600

· На Tool Pallete во вкладке System выберите инструмент TTimer и перенесите его на форму. Задайте интервал таймера равным 20 мс.

Interval=20

· Определяем параметры планет.

Создадим структуру TPlanet с полями содержащими свойства планеты в файле Unit1.h

Код:

struct TPlanet {

int x; int y;//это для удобства, координаты всегда будут "под рукой"

int period; //период обращения вокруг солнца (в сутках)

int orbit; //расстояние орбиты от солнца

int angle; //текущее положение планеты на орбите

byte radius; //радиус планеты

TColor color; //цвет планеты

string name; //имя планеты

}

В разделе public конструктора TForm1 объявим ссылки на переменные, понадобятся два битмапа, один для фона — cosmos, второй для буфера — buffer ( в буфере будет строиться изображение перед выводом его на экран). Еще нам понадобится массив планет — planets.

Код (Unit1.h):

public: // User declarations

TPlanet *planets;

Graphics::TBitmap *cosmos;

Graphics::TBitmap *buffer;.

 

· Теперь создадим небо и звезды. Щелкните дважды по форме, среда создаст при этом обработчик создания формы FormCreate. Заполним его.

Код:

#include <stdlib.h>

#include <stdio.h>

#include <time.h>

 

void __fastcall TForm1::FormCreate(TObject *Sender)

{

randomize(); // инициализируем генератор случайных чисел.

cosmos=new Graphics::TBitmap(); // это у нас фон

buffer=new Graphics::TBitmap();// создаем буфер.

 

// Задаем ширину меньшую на 200, чем ширина формы, в правой части формы у нас будут несколько элементов управления, но это потом.

cosmos->Width=ClientWidth-200; cosmos->Height=ClientHeight;

 

// Заливаем фон целиком черным цветом.

cosmos->Canvas->Brush->Color=0;

cosmos->Canvas->FillRect(cosmos->Canvas->ClipRect);

 

// это будут звезды

for (int i=0; i<99; i++)

cosmos->Canvas->Pixels[Random(ClientWidth-200)][Random(ClientHeight)]=clWhite;

 

// Вместо того, чтобы писать несколько строк кода, просто скопируем его функцией Assign. Она копирует не только изображение, но и все другие свойства битмапа, делает полную его копию.

buffer->Assign(cosmos);

}

 

· Осталось немного, и наш космос можно будет увидеть. В обработчике событий таймера вставляем процедуру рисования планет:

void __fastcall TForm1::Timer1Timer(TObject *Sender)

{DrawSystem();

}

теперь напишите саму процедуру DrawSystem, в ней мы копируем фон (космос со звездами) в буфер. И второй строкой выводим буфер на канву формы, т.е. на экран. Спросите, зачем нужен буфер? Потом узнаете.

·

Код:

void __fastcall TForm1::DrawSystem(TObject *Sender)

{

buffer->Canvas->Draw(0,0,cosmos);

Canvas->Draw(0,0,buffer);

}

Теперь жмите F9. На форме должен появиться космос со звездами, и справа свободное место.

· Космос мы уже создали. Теперь займемся планетами. Нам нужно позаполнять свойства у всех планет. Запишем их в константы.

Код:

TColor colors[9]={11713464, 2985931, 15571305, 1928136, 8304062, 5288427, 16178350, 13074777, 11713464};

byte radiuses[9]={3, 5, 6, 4, 12, 10, 8, 7, 2};

String names[9]= {"Меркурий", "Венера", "Земля", "Марс", "Юпитер", "Сатурн",

"Нептун", "Уран", "Плутон"};

int orbits[9] = { 20, 35, 50, 70, 100, 145, 190, 240, 290};

//единственный реальный параметр

int periods[9]={ 88, 225, 365, 687, 4332, 10762, 30689, 60201, 90485};

int SUN_RADIUS = 10;

int CX = 300; //это координаты цетра нашей системы, вокруг него все и будет вращаться.

int CY = 300;

· Теперь напишем процедуру TForm1::InitPlanets() заполнения этих данных в массив, и добавим вызов процедуры InitPlanets() в FormCreate, в самый конец.

Код (не забудьте объявить функцию!):

void __fastcall TForm1::InitPlanets()

{planets=new TPlanet[9];

for (int i=0; i<9;i++)

{ planets[i].radius=radiuses[i];

planets[i].name=names[i];

planets[i].color=colors[i];

planets[i].orbit=orbits[i];

planets[i].period=periods[i];

planets[i].angle=double(Random(628))/100.;

}

}

· Пора поговорить про анимацию. У нас будет предельно простая, но все же анимация. Будет движение объектов, а именно планет, по окружности.

Для начала рассмотрим принцип прямолинейного движения. При прямолинейном движении координаты объекта меняются обычным прибавлением или вычитанием. Например при горизонтальном движении Y координата остается неизменной, а X меняется с определенным шагом, если меняется в большую сторону, объект движется вправо, в меньшую – влево. Шаг изменения определяет скорость перемещения наравне с интервалом таймера, нужно подбирать их так, чтобы движение выглядело “мягче”.

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

Теперь допишем процедуру DrawSystem, напомню, в ней происходит отрисовка. Первая и последняя строки вам знакомы, между ними теперь есть отрисовка солнца, и планет в цикле.

Код:

void __fastcall TForm1::DrawSystem()

{

buffer->Canvas->Draw(0,0,cosmos);

buffer->Canvas->Brush->Color=clYellow; buffer->Canvas->Pen->Color=clYellow;

buffer->Canvas->Ellipse(cX-SUN_RADIUS, cY-SUN_RADIUS, cX+SUN_RADIUS, cY+SUN_RADIUS);

for(int i=0; i<9; i++)

{

planets[i].x=planets[i].orbit*cos(planets[i].angle)+cX;

planets[i].y=planets[i].orbit*sin(planets[i].angle)+cY;

buffer->Canvas->Brush->Color=planets[i].color; buffer->Canvas->Pen->Color=planets[i].color;

buffer->Canvas->Ellipse(planets[i].x-planets[i].radius, planets[i].y - planets[i].radius,

planets[i].x+planets[i].radius, planets[i].y + planets[i].radius);

}

Canvas->Draw(0,0,buffer);

};

· Теперь приступаем к моделированию движения по окружности.

Пусть земля в модели будет совершать один оборот за 1 секунду.

void __fastcall TForm1::Move()

{double dt=1e-3*M_PI*2*Timer1->Interval*planets[2].period;

for(int i=0; i<9; i++)

{planets[i].angle+=dt/planets[i].period;

if(planets[i].angle>M_PI*2)planets[i].angle-=M_PI*2;

planets[i].x=planets[i].orbit*cos(planets[i].angle)+cX;

planets[i].y=planets[i].orbit*sin(planets[i].angle)+cY;

}

};

· Теперь допишем процедуру Move() в таймер

void __fastcall TForm1::Timer1Timer(TObject *Sender)

{Move();DrawSystem();}

Результат







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.