Модель Солнечной системы

Скриншот

Задача: отобразить солнечную систему;
Использованный API: GTK/GDK;
Среда разработки: Visual Studio 2008;

В этой картинке 9 анимированых объектов, 10 статический и 5 статических полей с информацией:
1. Планеты
2. Солнце
3. Орбиты планет
4. Поля с информацией о планетах

Изменение координат планет происходит при помощи функций sin и cos, делая круговые движения. Координаты планет системы вычисляются по формулам:

x[i]=a[i]*cos(t[i])+WIDTH/2;
y[i]=b[i]*sin(t[i])+HEIGHT/2;

где i - номер планеты по создаваемой базе данных
t - параметр, касательно которого изменяются координаты
WIDTH, HEIGHT - стандартные, минимальные размеры экрана
a,b - значение малой и большой полуосей.

Очевидно что орбиты планет имеют эллиптическую форму, которая зависит от эксцентриситета орбит. Но при попытки использовать масштабирование для создания модели, я столкнулся с невозможностью использования такого метода т.к. размеры некоторых планет во много раз превосходят другие. Поэтому пришлось использовать схематическую модель, базирующаяся на реальных характеристиках планет и их орбит. Скорость движения планет вычисляется относительно их реальных скоростей, уменьшив их в 1000 раз.

//Необходимые строки для подключения gtk в VS
#pragma comment(lib,"gthread-2.0.lib")
#pragma comment(lib,"gtk-win32-2.0.lib")
#pragma comment(lib,"glib-2.0.lib")
#pragma comment(lib,"gobject-2.0.lib")
#pragma comment(lib,"gdk-win32-2.0.lib")
#pragma comment(lib,"gdk_pixbuf-2.0.lib")
#pragma comment(lib,"pango-1.0.lib")
#pragma comment(lib,"pangowin32-1.0.lib")
#pragma comment(lib,"intl.lib")
 
#include <gtk/gtk.h>
#include <math.h>//для вычисления синусов и косинусов
#include <stdlib.h>
//Размеры окна
#define WIDTH 1000
#define HEIGHT 700
#define M_PI 3.14
#define OTSTUP 10
#define lim_planet 9
#define lim_name 15
#define interval 25//Интервал вызова ф-ии рисования солнечной системы
#define speed_change_t 0.001 //На сколько изменяется параметр t
 
char name[lim_planet][lim_name],change_num[50],type_name[lim_planet][2*lim_name],ch_num[lim_planet];
float e[lim_planet],r_e[lim_planet],t[9],k,v[lim_planet],r_v[lim_planet];
int d[lim_planet],r_d[lim_planet],a[lim_planet],r_a[lim_planet],b[lim_planet],x[lim_planet],y[lim_planet],i,me=77777,xs=5,ys=20;
int timer[lim_planet],xt[lim_planet],yt[lim_planet],num_change_t[lim_planet];
 
FILE *info=fopen("other_information.txt","rt");//файл с используемыми характеристиками планет
FILE *r_info=fopen("information.txt","rt");//файл с реальными характеристиками планет
 
GdkColor fclrs,bclr,clr;
GdkGC *gc;
 
gboolean destroy(GtkWidget *widget);
gint delete_event(GtkWidget *widget);
 
gboolean information(GtkWidget *widget);//ф-ия создавания полей с информацией о планетах
gboolean run_planet(GtkWidget *widget);//ф-ия рисования слнечной системы
 
 
 
 
int main(int arge, char **argv)
{
	xt[0]=0;yt[0]=240;
	for(i=1;i<lim_planet;i++) {yt[i]=yt[i-1]+33;xt[i]=0;}
	//Создание базы с информацией
	for(i=0;i<5;i++)
	{fscanf(r_info,"%s",type_name[i]);}
	for(i=0;i<lim_planet;i++)
	{
		fscanf(r_info,"%f",&r_e[i]);
		fscanf(r_info,"%d",&r_a[i]);
		fscanf(r_info,"%d",&r_d[i]);
		fscanf(r_info,"%f",&r_v[i]);
	}fclose(r_info);
	for(i=0;i<lim_planet;i++)
	{
		fscanf(info,"%s",name[i]);
		fscanf(info,"%f",&e[i]);
		fscanf(info,"%d",&a[i]);
		fscanf(info,"%d",&d[i]);
		fscanf(info,"%f",&v[i]);
 
	}fclose(info);
 
	//Увеличение эксцентриситета планет для зрелещности изображения
	for(i=0;i<lim_planet;i++) e[i]*=1.2;
 
	//Вычисление максимального значения оси относительно экрана
	b[8]=HEIGHT/2-OTSTUP;
 
	//k=b(плутона максимальное компьютерное)/b(плутона реальное)
	k=b[8]/(a[8]*sqrt(1-(e[8]*e[8])));
 
	//Уменьшение значений полуосей и диаметров планет согласно экрана и масштабирования
	for(i=0;i<lim_planet;i++) 
	{	
		a[i]*=k;
		b[i]=a[i]*sqrt(1-e[i]*e[i]);
		d[i]/=200;
	}
 
 
 
	gtk_init(&arge,&argv);
	GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_widget_set_size_request(window,WIDTH,HEIGHT);
	g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL);
	g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL);
	gdk_color_parse("black",&clr);
	gtk_widget_modify_bg(window,GTK_STATE_NORMAL,&clr);
	g_signal_connect(G_OBJECT(window),"expose_event",G_CALLBACK(run_planet),NULL);
 
	g_timeout_add(interval,(GSourceFunc)run_planet,(gpointer)window);
	g_timeout_add(interval,(GSourceFunc)information,(gpointer)window);
 
	gtk_widget_show_all(window);
	gtk_main();
 
	return 0;
}
 
gboolean destroy(GtkWidget *widget)
{
	return FALSE;
}
 
gint delete_event(GtkWidget *widget)
{
	gtk_main_quit();
	return 1;
}
 
 
gboolean information(GtkWidget *widget)
{
	gc = widget->style->fg_gc[GTK_WIDGET_STATE(widget)];
	GdkFont *font=gdk_fontset_load("Lucida Console");
 
	for(i=0;i<lim_planet;i++)
	{
		gdk_gc_set_rgb_fg_color(gc,&clr);
		sprintf(ch_num,"%d",timer[i]);
		gdk_draw_string(widget->window,font,gc,xt[i],yt[i],ch_num);
		//проверка на изменение времени на планете, если число изменений(вычесленных в ручную) совпадает с данным числом, то год прошёл 
		switch(i)
		{
		case 0:
			{
				if(num_change_t[0]==131) 
				{
					num_change_t[0]=0; 
					timer[0]++;
				}break;
			}
		case 1:
			{
				if(num_change_t[1]==179) 
				{
					num_change_t[1]=0; 
					timer[1]++;
				}break;
			}
		case 2:
			{
				if(num_change_t[2]==210) 
				{
					num_change_t[2]=0; 
					timer[2]++;
				}break;
			}
		case 3:
			{
				if(num_change_t[3]==261) 
				{
					num_change_t[3]=0; 
					timer[3]++;
				}break;
			}
		case 4:
			{
				if(num_change_t[4]==479) 
				{
					num_change_t[4]=0; 
					timer[4]++;
				}break;
			}
		case 5:
			{
				if(num_change_t[5]==654) 
				{
					num_change_t[5]=0; 
					timer[5]++;
				}break;
			}
		case 6:
			{
				if(num_change_t[6]==924) 
				{
					num_change_t[6]=0; 
					timer[6]++;
				}break;
			}
		case 7:
			{
				if(num_change_t[7]==1162) 
				{
					num_change_t[7]=0; 
					timer[7]++;
				}break;
			}
		case 8:
			{
				if(num_change_t[8]==1281) 
				{
					num_change_t[8]=0; 
					timer[8]++;
				}break;
			}
		}
		//Создание поля с годами на планетах
		fclrs.pixel = 0;
		fclrs.red = 0;
		fclrs.green = 0;
		fclrs.blue = 0xFFFF;
		gdk_gc_set_rgb_fg_color(gc,&fclrs);
		gdk_draw_string(widget->window,font,gc,xt[i],yt[i]-20,"Years ");
		gdk_draw_string(widget->window,font,gc,xt[i]+70,yt[i]-20,name[i]);
		sprintf(ch_num,"%d",timer[i]);
		fclrs.pixel = 0;
		fclrs.red = 0xFFFF;
		fclrs.green = 0;
		fclrs.blue = 0;
		gdk_gc_set_rgb_fg_color(gc,&fclrs);
		gdk_draw_string(widget->window,font,gc,xt[i],yt[i],ch_num);
	}
	//создание лэйбочки с информацией о хозяине проекта
	fclrs.pixel = 0;
	fclrs.red = 0;
	fclrs.green = 0xFFFF;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_line(widget->window,gc,862,255,997,255);
	gdk_draw_line(widget->window,gc,862,450,997,450);
	gdk_draw_line(widget->window,gc,862,255,862,450);
	gdk_draw_line(widget->window,gc,997,255,997,450);
	fclrs.pixel = 0;fclrs.red = 0xFA00;fclrs.green = 0xFD00;fclrs.blue = 0;gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_string(widget->window,font,gc,865,272,"The project");
	gdk_draw_string(widget->window,font,gc,865,292,"of the second");
	gdk_draw_string(widget->window,font,gc,865,312,"year student");
	gdk_draw_string(widget->window,font,gc,865,332,"Groups 201-p");
	gdk_draw_string(widget->window,font,gc,865,352,"Specialities");
	gdk_draw_string(widget->window,font,gc,865,372,"the applied");
	gdk_draw_string(widget->window,font,gc,865,392,"mathematics");
	gdk_draw_string(widget->window,font,gc,865,412,"by Kiseris");
	gdk_draw_string(widget->window,font,gc,865,432,"   Arthur");
//Вывод первого поля, к-ое содержит информацию о эксцентриситете планет
	fclrs.pixel = 0;
	fclrs.red = 0xFFFF;
	fclrs.green = 0;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	xs=5;ys=20;
	gdk_draw_string(widget->window,font,gc,xs,ys,type_name[0]);
	xs+=80;
	gdk_draw_string(widget->window,font,gc,xs,ys,type_name[1]);
	xs=5;ys+=20;
	fclrs.pixel = 0;
	fclrs.red = 0;
	fclrs.green = 0xFFFF;
	fclrs.blue = 0x00FF;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	for(i=0,xs=5;i<9;i++,xs=5)
	{
		gdk_draw_string(widget->window,font,gc,xs,ys,name[i]);
		xs+=80;
		sprintf(change_num, "%3.3f",r_e[i]);
		gdk_draw_string(widget->window,font,gc,xs,ys,change_num);
		ys+=20;
	}
//Вывод второго поля, к-ое содержит информацию о среднем расстоянии планет от солнца
	fclrs.pixel = 0;
	fclrs.red = 0xFFFF;
	fclrs.green = 0;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	xs=5;ys=520;
	gdk_draw_string(widget->window,font,gc,xs,ys,type_name[0]);
	xs+=80;
	gdk_draw_string(widget->window,font,gc,xs,ys,type_name[2]);
	xs=5;ys+=20;
	fclrs.pixel = 0;
	fclrs.red = 0;
	fclrs.green = 0xFFFF;
	fclrs.blue = 0x00FF;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	for(i=0,xs=5;i<9;i++,xs=5)
	{
		gdk_draw_string(widget->window,font,gc,xs,ys,name[i]);
		xs+=80;
		sprintf(change_num, "%d",r_a[i]);
		gdk_draw_string(widget->window,font,gc,xs,ys,change_num);
		gdk_draw_string(widget->window,font,gc,xs+45,ys,"mln.km");
		ys+=20;
	}
//Вывод третего поля, к-ое содержит информацию о диаметре планет
	fclrs.pixel = 0;
	fclrs.red = 0xFFFF;
	fclrs.green = 0;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	xs=830;ys=20;
	gdk_draw_string(widget->window,font,gc,xs,ys,type_name[0]);
	xs+=80;
	gdk_draw_string(widget->window,font,gc,xs,ys,type_name[3]);
	xs=830;ys+=20;
	fclrs.pixel = 0;
	fclrs.red = 0;
	fclrs.green = 0xFFFF;
	fclrs.blue = 0x00FF;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	for(i=0,xs=830;i<9;i++,xs=830)
	{
		gdk_draw_string(widget->window,font,gc,xs,ys,name[i]);
		xs+=80;
		sprintf(change_num, "%d",r_d[i]);
		gdk_draw_string(widget->window,font,gc,xs,ys,change_num);
		gdk_draw_string(widget->window,font,gc,xs+40,ys,"   km");
		ys+=20;
	}
//Вывод четвёртого поля, к-ое содержит информацию о диаметре планет
	fclrs.pixel = 0;
	fclrs.red = 0xFFFF;
	fclrs.green = 0;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	xs=830;ys=520;
	gdk_draw_string(widget->window,font,gc,xs,ys,type_name[0]);
	xs+=80;
	gdk_draw_string(widget->window,font,gc,xs,ys,type_name[4]);
	xs=830;ys+=20;
	fclrs.pixel = 0;
	fclrs.red = 0;
	fclrs.green = 0xFFFF;
	fclrs.blue = 0x00FF;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	for(i=0,xs=830;i<9;i++,xs=830)
	{
		gdk_draw_string(widget->window,font,gc,xs,ys,name[i]);
		xs+=80;
		sprintf(change_num, "%3.1f",r_v[i]);
		gdk_draw_string(widget->window,font,gc,xs,ys,change_num);
		gdk_draw_string(widget->window,font,gc,xs+40,ys," km/s");
		ys+=20;
	}
 
	return TRUE;
}
 
gboolean run_planet(GtkWidget *widget)
{
	gc = widget->style->fg_gc[GTK_WIDGET_STATE(widget)];
	GdkFont *font=gdk_fontset_load("Lucida Console");
 
//Стерание предыдущих планет и названия используя цвет фона(чёрный)
	fclrs.pixel = 0;
	fclrs.red = 0;
	fclrs.green = 0;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
 
	gdk_draw_arc(widget->window,gc,TRUE,x[8]-d[8],y[8]-d[8],2*d[8],2*d[8],0,360*64);
	gdk_draw_string(widget->window,font,gc,x[8]-25,y[8]-10,name[8]);
	gdk_draw_arc(widget->window,gc,TRUE,x[7]-(d[7]/2),y[7]-(d[7]/2),d[7],d[7],0,360*64);	
	gdk_draw_string(widget->window,font,gc,x[7]-30,y[7]-16,name[7]);
	gdk_draw_arc(widget->window,gc,TRUE,x[6]-(d[6]/2),y[6]-(d[6]/2),d[6],d[6],0,360*64);	
	gdk_draw_string(widget->window,font,gc,x[6]-20,y[6]-13,name[6]);
	gdk_draw_arc(widget->window,gc,TRUE,x[5]-(d[5]/2),y[5]-(d[5]/2),d[5],d[5],0,360*64);
	gdk_draw_rectangle(widget->window,gc,TRUE,x[5]-(d[5]/2)-5,y[5]-3,d[5]+8,3);
	gdk_draw_string(widget->window,font,gc,x[5]-30,y[5]-20,name[5]);
	gdk_draw_arc(widget->window,gc,TRUE,x[4]-(d[4]/2),y[4]-(d[4]/2),d[4],d[4],0,360*64);	
	gdk_draw_string(widget->window,font,gc,x[4]-30,y[4]-20,name[4]);
	gdk_draw_arc(widget->window,gc,TRUE,x[3]-(d[3]/2),y[3]-(d[3]/2),d[3],d[3],0,360*64);
	gdk_draw_string(widget->window,font,gc,x[3]-20,y[3]-13,name[3]);
	gdk_draw_arc(widget->window,gc,TRUE,x[2]-(d[2]/2),y[2]-(d[2]/2),d[2],d[2],0,360*64);	
	gdk_draw_string(widget->window,font,gc,x[2]-20,y[2]-13,name[2]);
	gdk_draw_arc(widget->window,gc,TRUE,x[1]-(d[1]/2),y[1]-(d[1]/2),d[1],d[1],0,360*64);	
	gdk_draw_string(widget->window,font,gc,x[1]-30,y[1]-20,name[1]);
	gdk_draw_arc(widget->window,gc,TRUE,x[0]-(d[0]/2),y[0]-(d[0]/2),d[0],d[0],0,360*64);	
	gdk_draw_string(widget->window,font,gc,x[0]-30,y[0]-20,name[0]);
 
//Изменение координат 
	for(i=0;i<9;i++)
	{
		x[i]=a[i]*cos(t[i])+WIDTH/2;
		y[i]=b[i]*sin(t[i])+HEIGHT/2;
	}
 
//Отображение граней для осей СС
	fclrs.pixel = 0;
	fclrs.red = 0;
	fclrs.green = 0xFFFF;
	fclrs.blue = 0x00FF;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
 
	for(i=0;i<9;i++)
	{
		gdk_draw_arc(widget->window,gc,FALSE,WIDTH/2-a[i],HEIGHT/2-b[i],2*a[i],2*b[i],0,360*64);
	}
 
//Рисование новых рисунков с новыми координатами 
	fclrs.pixel = 0;
	fclrs.red = 0;
	fclrs.green = 0;
	fclrs.blue = 0xFFFF;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,x[8]-(d[8]/2),y[8]-(d[8]/2),d[8],d[8],0,360*64);
 
	fclrs.pixel = 0;
	fclrs.red = 0x0B00;
	fclrs.green = 0x2700;
	fclrs.blue = 0xB500;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,x[7]-(d[7]/2),y[7]-(d[7]/2),d[7],d[7],0,360*64);
 
	fclrs.pixel = 0;
	fclrs.red = 0x7900;
	fclrs.green = 0x8C00;
	fclrs.blue = 0xFF00;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,x[6]-(d[6]/2),y[6]-(d[6]/2),d[6],d[6],0,360*64);
 
	fclrs.pixel = 0;
	fclrs.red = 0xFC00;
	fclrs.green = 0xE400;
	fclrs.blue = 0xAC00;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,x[5]-(d[5]/2),y[5]-(d[5]/2),d[5],d[5],0,360*64);
	fclrs.pixel = 0;
	fclrs.red = 0x8F00;
	fclrs.green = 0x6500;
	fclrs.blue = 0x0200;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_rectangle(widget->window,gc,TRUE,x[5]-(d[5]/2)-5,y[5]-3,d[5]+8,3);
 
	fclrs.pixel = 0;
	fclrs.red = 0x9700;
	fclrs.green = 0x8000;
	fclrs.blue = 0x4900;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,x[4]-(d[4]/2),y[4]-(d[4]/2),d[4],d[4],0,360*64);
 
 
	fclrs.pixel = 0;
	fclrs.red = 0xDDDD;
	fclrs.green = 0;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,x[3]-(d[3]/2),y[3]-(d[3]/2),d[3],d[3],0,360*64);
 
	fclrs.pixel = 0;
	fclrs.red = 0;
	fclrs.green = 0xFFFF;
	fclrs.blue = 0x00DD;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,x[2]-(d[2]/2),y[2]-(d[2]/2),d[2],d[2],0,360*64);
 
	fclrs.pixel = 0;
	fclrs.red = 0xFFFF;
	fclrs.green = 0xCCCC;
	fclrs.blue = 0xCCCC;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,x[1]-(d[1]/2),y[1]-(d[1]/2),d[1],d[1],0,360*64);
 
	fclrs.pixel = 0;
	fclrs.red = 0xFFFF;
	fclrs.green = 0xA5AA;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,x[0]-(d[0]/2),y[0]-(d[0]/2),d[0],d[0],0,360*64);
 
//Рисование солнца
	fclrs.pixel = 0;
	fclrs.red = 0xFA00;
	fclrs.green = 0xFD00;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
	gdk_draw_arc(widget->window,gc,TRUE,e[8]*a[8]+a[8]+20,HEIGHT/2-20,40,40,0,360*64);
 
//Создания надписей
	fclrs.pixel = 0;
	fclrs.red = 0xFFFF;
	fclrs.green = 0;
	fclrs.blue = 0;
	gdk_gc_set_rgb_fg_color(gc,&fclrs);
 
	gdk_draw_string(widget->window,font,gc,x[8]-25,y[8]-10,name[8]);
	gdk_draw_string(widget->window,font,gc,x[7]-30,y[7]-16,name[7]);
	gdk_draw_string(widget->window,font,gc,x[6]-20,y[6]-13,name[6]);
	gdk_draw_string(widget->window,font,gc,x[5]-30,y[5]-20,name[5]);	
	gdk_draw_string(widget->window,font,gc,x[4]-30,y[4]-20,name[4]);
	gdk_draw_string(widget->window,font,gc,x[3]-20,y[3]-13,name[3]);
	gdk_draw_string(widget->window,font,gc,x[2]-20,y[2]-13,name[2]);
	gdk_draw_string(widget->window,font,gc,x[1]-30,y[1]-20,name[1]);
	gdk_draw_string(widget->window,font,gc,x[0]-30,y[0]-20,name[0]);
//Создания надписи	солнца	
	gdk_draw_string(widget->window,font,gc,e[8]*a[8]+a[8]+25,HEIGHT/2+5,"Sun");
	//увеличить счётчик изменений параметра у каждой планеты
	for(i=0;i<9;i++)
	{
		num_change_t[i]++;
	}
	//увеличение параметра согласно произведения реальной скорости планеты на опр. коофициент 
	for(i=0;i<9;i++)
	{
		t[i]+=speed_change_t*v[i];
	}
 
	return TRUE;
}

Ключевые слова: 
Солнечная система
ВложениеРазмер
солнечной системы.rar1.26 Мб