Модель полёта материальной точки

Модель полёта материальной точки

Программа основана на задачи движения тела брошенного под углом. Сама модель была реализована на языке программирования Си в ОС GNU/Linux на дистрибутиве Ubuntu 9.10 Karmic Koala. Используемый компилятор GCC (GNU Compiler Collection). Сама программа написана в свободной кроcсплатформенной среде разработки Code::Blocks.

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

Рассмотрим движение материальной точки, брошенного под углом α к горизонту с начальной скоростью v0. Спроецируем начальную скорость v0 и ускорение a тела на оси X и Y. Проекция начальной скорости на ось X равна
v0x= v0cos α. Проекция ускорения ax = 0, поскольку вектор g
перпендикулярен оси X. Поэтому движение материальной точки вдоль оси X будет равномерным. Проекция скорости vx и координата x летящей материальной точки определяются соотношениями:
v0x= v0 cos α, x = x0 + v0 t cos α
Проекция начальной скорости на ось Y равна v0y = v0 sinα. Проекция
ускорения ay = −g, поскольку вектор g направлен противоположно оси Y.
Поэтому вдоль оси Y движение тела равнопеременное. В этом случае
проекция скорости vy и координата y летящего тела задаются формулами:
v0y= v0 sin α , y = y0 + v0 t sin α

Отсюда получается, что положение тела в заданный момент времени определяется системой уравнений:

где
t – независимый параметр времени;
v0 – начальная скорость;
α – угол наклона дула ;
g – гравитационная поставная равная 9,8;

Вычисления по этой системе производятся в процедуре
gint shut (GtkWidget * widget), которая вызывается каждых 4 милисекунды

x=t*V*cos(ang*M_PI/180);
y=-(t*V*sin(ang*M_PI/180)-9.8*t*t/2);

После чего были получены «реальные» координаты объекта, которые переводились в экранные:

xe = x0e+xe0+(x1e-x0e)/(x1r-x0r)*(x-x0r);
ye = y0e+ye0+(y1e-y0e)/(y1r-y0r)*(y-y0r)-4;

#include <stdlib.h>
#include <gtk/gtk.h>
#include <math.h>
 
GtkWidget   *edit_angle=NULL,//поле ввода угла
            *edit_speed=NULL,//поле ввода скорости
            *edit_metrs=NULL;//поле ввода дистанции
 
double ang, //угол
       V,   //начальная скорость
       metr,//растояние до мишени
        t;  //время полёта
 
int xe0, ye0;//начальные координаты материальной точки
 
gboolean on_draw (GtkWidget *widget, GdkEventExpose *event){
 
    //Окно
    GdkGC * gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
    GdkColor *clr = malloc(sizeof(GdkColor));
 
    gdk_color_parse("black", clr);
    gdk_gc_set_rgb_fg_color( gc, clr );
    gdk_draw_rectangle(widget->window, gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height);
 
    //прямая относительно которой происходит выстрел
    gdk_color_parse("blue", clr);
    gdk_gc_set_rgb_fg_color( gc, clr );
    gdk_draw_line(widget->window, gc, 0, widget->allocation.height*4/5, widget->allocation.width, widget->allocation.height*4/5);
 
    //дуло
    //находим координаты конца дула
    xe0=40*cos((M_PI/2-ang*M_PI/180)-M_PI/2);
    ye0=40*sin((M_PI/2-ang*M_PI/180)-M_PI/2);
 
    int ye2=ye0+widget->allocation.height*4/5;
 
    gdk_color_parse("red", clr);
    gdk_gc_set_rgb_fg_color( gc, clr );
    gdk_draw_line(widget->window, gc, 0,widget->allocation.height*4/5,xe0,ye2);
 
    //мешень
    gdk_gc_set_rgb_fg_color( gc, clr );
    gdk_draw_rectangle(widget->window,gc, TRUE, widget->allocation.width-22, widget->allocation.height*4/5 - 145, 22 ,  145);
 
    gdk_color_parse("white", clr);
    gdk_gc_set_rgb_fg_color( gc, clr );
    gdk_draw_rectangle(widget->window,gc, TRUE, widget->allocation.width-20, widget->allocation.height*4/5 - 105, 18 ,  25);
    gdk_draw_rectangle(widget->window,gc, TRUE, widget->allocation.width-20, widget->allocation.height*4/5 - 65, 18 ,  25);
 
        //цифры на мишени
        GdkScreen *screen = gdk_drawable_get_screen (widget->window);
        PangoContext *context = gdk_pango_context_get_for_screen (screen);
        PangoLayout *layout = pango_layout_new (context);
        pango_layout_set_text (layout, "1", -1);
        PangoFontDescription *desc = pango_font_description_from_string ("DS Goose 10");
        pango_layout_set_font_description (layout, desc);
        pango_font_description_free (desc);
 
            pango_layout_set_text(layout, "10", -1);
            gdk_draw_layout(widget->window, gc, widget->allocation.width-18, widget->allocation.height*4/5 - 135, layout);
 
            pango_layout_set_text(layout, "10", -1);
            gdk_draw_layout(widget->window, gc, widget->allocation.width-18, widget->allocation.height*4/5 - 30, layout);
 
            pango_layout_set_text(layout, "50", -1);
            gdk_draw_layout(widget->window, gc, widget->allocation.width-18, widget->allocation.height*4/5 - 81, layout);
 
            gdk_color_parse("black", clr);
            gdk_gc_set_rgb_fg_color( gc, clr );
 
            pango_layout_set_text(layout, "20", -1);
            gdk_draw_layout(widget->window, gc, widget->allocation.width-18, widget->allocation.height*4/5 - 102, layout);
 
            pango_layout_set_text(layout, "20", -1);
            gdk_draw_layout(widget->window, gc, widget->allocation.width-18, widget->allocation.height*4/5 - 62, layout);
 
    g_object_unref (layout);
    g_object_unref (context);
 
  return TRUE;
}
 
 
gint shut (GtkWidget * widget){
    // координаты области рисования
    int x0e=0;
    int y0e=0;
    int x1e=widget->allocation.width;
    int y1e=widget->allocation.height;
    //координаты которые ограничат полют мат. точки
    int yi=widget->allocation.height*4/5;
    int xi= widget->allocation.width-22;
 
    //кооррдинаты реально опбласти
    float x0r=0;
    float y0r=-metr;
    float x1r=metr;
    float y1r=metr/4;
 
    //задаём цвета траектори, мат.тчки
    GdkGC *line = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
    GdkColor *bullet= malloc(sizeof(GdkColor));
    GdkColor *fon = malloc(sizeof(GdkColor));
    GdkColor *traectory = malloc(sizeof(GdkColor));
 
    gdk_color_parse("blue", bullet);
    gdk_color_parse("black", fon);
    gdk_color_parse("green", traectory);
 
	float x, y;
 	int xe, ye, xe2, ye2;
     //вычисляем координаты положения материальной точки
    //вычислени реальных координат
    x=t*V*cos(ang*M_PI/180);
    y=-(t*V*sin(ang*M_PI/180)-9.8*t*t/2);
 
	//отоброжение реальных координат в экраные
	xe2 = x0e+xe0+(x1e-x0e)/(x1r-x0r)*(x-x0r);
	ye2 = y0e+ye0+(y1e-y0e)/(y1r-y0r)*(y-y0r)-4;
 
    //зарисовка старого положения мат. точки
    gdk_gc_set_rgb_fg_color( line, fon );
    gdk_draw_arc(widget->window, line, TRUE, xe2, ye2, 8, 8, 0, 64 * 360 );
 
    // траектория полёта
    gdk_gc_set_rgb_fg_color( line, traectory );
    gdk_draw_point(widget->window, line, xe2, ye2+=4);
 
    t+=0.001;
    // аналогично вычсляем и рисуем текущее положение мат. точки
    x=t*V*cos(ang*M_PI/180);
    y=-(t*V*sin(ang*M_PI/180)-9.8*t*t/2);
	xe = x0e+xe0+(x1e-x0e)/(x1r-x0r)*(x-x0r);
	ye = y0e+ye0+(y1e-y0e)/(y1r-y0r)*(y-y0r)-4;
 
    gdk_gc_set_rgb_fg_color( line, bullet);
    gdk_draw_arc(widget->window, line, TRUE, xe, ye, 8, 8, 0, 64 * 360 );
 
    //проверяем на вылет из вычисляемой области
    if (ye > yi || (xe > xi-5 && ye > widget->allocation.height*4/5 - 135) ) return 0;
    g_signal_connect (G_OBJECT (widget), "destroy", G_CALLBACK(gtk_main_quit), NULL);
   return 1;
}
 
 
static void show (){
    char *angle_c=NULL, //временая переменя содержащая информацию с поля "угол"
         *metr_c=NULL,  //временая переменя содержащая информацию с поля "расстояние"
         *speed=NULL;   //временая переменя содержащая информацию с поля "скорость"
 
    //обрабатываем информацию с полей ввода
    angle_c = (char*)gtk_entry_get_text(GTK_ENTRY(edit_angle));
    ang= atof(angle_c);
 
    metr_c = (char*)gtk_entry_get_text(GTK_ENTRY(edit_metrs));
    metr= atof(metr_c );
 
    speed = (char*)gtk_entry_get_text(GTK_ENTRY(edit_speed));
    V= atof(speed);
 
    //окно с моделью выстрела
 
    GtkWidget *win1=NULL;
    win1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_resize(GTK_WINDOW(win1), 500, 500);
 
    gtk_window_set_position(GTK_WINDOW(win1), GTK_WIN_POS_CENTER);
    gtk_window_set_title (GTK_WINDOW (win1), "Cтрельба по мишени");
    gtk_container_set_border_width (GTK_CONTAINER (win1), 28);
 
    t=0;// счётчик времени сброшен
    g_signal_connect (G_OBJECT (win1), "expose_event", G_CALLBACK (on_draw), NULL);
    g_timeout_add(4, (GSourceFunc) shut, (gpointer) win1);
 
    gtk_widget_show_all(win1);
}
 
int main (int argc, char *argv[]){
  GtkWidget *window=NULL,//окно для ввода
            *hbox=NULL,//контейнер хранящий поля ввода, подписи и кнопку
            *button=NULL, //кнопка
            *label_angle=NULL,// подпись для угла
            *label_speed=NULL,//подпись для начальной скорости
            *label_metrs=NULL;//подпись для растояния до мишени
 
  gtk_init(&argc, &argv);
 
  //окно полей ввода
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_resize(GTK_WINDOW(window), 300, 100);
  gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_title (GTK_WINDOW (window), "Входные даные:");
  gtk_container_set_border_width (GTK_CONTAINER (window), 20);
 
  //кнопка
  button = gtk_button_new_with_label (("ОГОНЬ"));
 
  //поля ввода
  edit_angle=gtk_entry_new();
  edit_speed=gtk_entry_new();
  edit_metrs=gtk_entry_new();
  //метки
  label_angle = gtk_label_new ("Угол от 0 до 90(градусов)");
  label_speed = gtk_label_new ("Скорость (м/c)");
  label_metrs = gtk_label_new ("Расстояние (м)");
 
  //"контейнер" содержащий объекты
 
  hbox = gtk_vbox_new(FALSE, 9);
  gtk_container_add(GTK_CONTAINER (window), hbox);
 
//----------------------------------------------------------
  gtk_container_add(GTK_CONTAINER (hbox), label_angle);
  gtk_container_add(GTK_CONTAINER (hbox), edit_angle);
 
  gtk_container_add(GTK_CONTAINER (hbox), label_speed);
  gtk_container_add(GTK_CONTAINER (hbox), edit_speed);
 
  gtk_container_add(GTK_CONTAINER (hbox), label_metrs);
  gtk_container_add(GTK_CONTAINER (hbox), edit_metrs);
 
  gtk_container_add(GTK_CONTAINER (hbox), button);
 
  //при нажатии кнопки
  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (show), NULL);
 
  g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
  gtk_widget_show_all(window);
  gtk_main();
 
  return 0;
}

Ключевые слова: 
модель полёта материальной точки стрельба