Nadesłany przez Tomasz Lubiński, 27 lipca 2005 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
Boidy C++/Unit2.cpp:
//www.algorytm.org
//Boidy
//(c) 2003 Tomasz Lubinski
#include <vcl.h>
#include "unit1.h"
#include <math.h>
#pragma hdrstop
#include "Unit2.h"
#pragma package(smart_init)
__fastcall Watek::Watek(bool CreateSuspended)
: TThread(CreateSuspended){ }
struct boid
{
float x,y; //polozenie
float vx,vy; //skladowa pionowa i pozioma predkosci
float srednia_vx, srednia_vy, srednia_odleglosc;//srednie sasiadow
int l; //liczba sąsiadow+1
};
int n;
boid b[100];
float r,odl,k,min,kat,w_predkosci,w_odleglosci,w_minimum,w_zaklucen,v_max;
Graphics::TBitmap *tmp = new Graphics::TBitmap();
void __fastcall Watek::Rysowanie()
{
//ruch i rysowanie
tmp->Canvas->Rectangle(0,0,450,400);
for (int i=0; i<n; i++)
{
b[i].x+=b[i].vx;
b[i].y+=b[i].vy;
if (b[i].vx==0) b[i].vx=v_max/1000;
if (b[i].vy==0) b[i].vy=v_max/1000;
if (b[i].vx<0)
{
tmp->Canvas->MoveTo(b[i].x,b[i].y);
tmp->Canvas->LineTo(b[i].x-8*cos(atan(b[i].vy/b[i].vx)),b[i].y-8*sin(atan(b[i].vy/b[i].vx)));
tmp->Canvas->MoveTo(b[i].x,b[i].y);
tmp->Canvas->LineTo(b[i].x-3*cos(atan(b[i].vy/b[i].vx)+M_PI/2),b[i].y-3*sin(atan(b[i].vy/b[i].vx)+M_PI/2));
tmp->Canvas->LineTo(b[i].x-7*cos(atan(b[i].vy/b[i].vx)),b[i].y-7*sin(atan(b[i].vy/b[i].vx)));
tmp->Canvas->MoveTo(b[i].x,b[i].y);
tmp->Canvas->LineTo(b[i].x-3*cos(atan(b[i].vy/b[i].vx)-M_PI/2),b[i].y-3*sin(atan(b[i].vy/b[i].vx)-M_PI/2));
tmp->Canvas->LineTo(b[i].x-7*cos(atan(b[i].vy/b[i].vx)),b[i].y-7*sin(atan(b[i].vy/b[i].vx)));
}
else
{
tmp->Canvas->MoveTo(b[i].x,b[i].y);
tmp->Canvas->LineTo(b[i].x+8*cos(atan(b[i].vy/b[i].vx)),b[i].y+8*sin(atan(b[i].vy/b[i].vx)));
tmp->Canvas->MoveTo(b[i].x,b[i].y);
tmp->Canvas->LineTo(b[i].x+3*cos(atan(b[i].vy/b[i].vx)+M_PI/2),b[i].y+3*sin(atan(b[i].vy/b[i].vx)+M_PI/2));
tmp->Canvas->LineTo(b[i].x+7*cos(atan(b[i].vy/b[i].vx)),b[i].y+7*sin(atan(b[i].vy/b[i].vx)));
tmp->Canvas->MoveTo(b[i].x,b[i].y);
tmp->Canvas->LineTo(b[i].x+3*cos(atan(b[i].vy/b[i].vx)-M_PI/2),b[i].y+3*sin(atan(b[i].vy/b[i].vx)-M_PI/2));
tmp->Canvas->LineTo(b[i].x+7*cos(atan(b[i].vy/b[i].vx)),b[i].y+7*sin(atan(b[i].vy/b[i].vx)));
}
}
Form1->Canvas->Draw(185,10,tmp);
}
void __fastcall Watek::Execute()
{
tmp->Width=450;
tmp->Height=400;
tmp->Canvas->Brush->Color=clSkyBlue;
n=StrToInt(Form1->LabeledEdit1->Text);
for (int i=0; i<n; i++)
{
b[i].x=random(400); b[i].y=random(400); b[i].vx=random(40)/10.0-2; b[i].vy=random(40)/10.0-2;
}
while (1==1)
{
//odczytanie parametrow z formularza
r=StrToFloat(Form1->LabeledEdit2->Text);
kat=StrToFloat(Form1->LabeledEdit3->Text);
min=StrToFloat(Form1->LabeledEdit4->Text);
w_predkosci=StrToFloat(Form1->LabeledEdit5->Text)/100;
w_odleglosci=StrToFloat(Form1->LabeledEdit6->Text)/100;
w_minimum=StrToFloat(Form1->LabeledEdit7->Text)/100;
w_zaklucen=StrToFloat(Form1->LabeledEdit8->Text)/100;
v_max=StrToFloat(Form1->LabeledEdit9->Text);
//ruch i rysowanie
Synchronize(Rysowanie);
Sleep(20);
//obliczenia
for (int i=0; i<n; i++)
{
b[i].srednia_vx=b[i].vx;
b[i].srednia_vy=b[i].vy;
b[i].srednia_odleglosc=0;
b[i].l=1;
for (int j=0; j<n; j++)
{
if (j==i) continue;
odl=sqrt(pow(b[i].x-b[j].x,2)+pow(b[i].y-b[j].y,2));
k = b[i].vx/sqrt(b[i].vx*b[i].vx+b[i].vy*b[i].vy) *
((b[j].x-b[i].x)/odl) +
b[i].vy/sqrt(b[i].vx*b[i].vx+b[i].vy*b[i].vy) *
((b[j].y-b[i].y)/odl);
if (k < -1) k = -1;
else if (k > 1) k = 1;
k = fabs((180.0*acos(k))/M_PI);
if (odl<r&&k<kat)
{
b[i].l++;
b[i].srednia_vx+=b[j].vx;
b[i].srednia_vy+=b[j].vy;
b[i].srednia_odleglosc+=odl;
}
}
}
for (int i=0; i<n; i++)
{ //dostosuj do srednich predkosci sasiadow
b[i].vx+=(w_predkosci*((b[i].srednia_vx/b[i].l)-b[i].vx));
b[i].vy+=(w_predkosci*((b[i].srednia_vy/b[i].l)-b[i].vy));
//zaklucenia
b[i].vx+=(w_zaklucen*((random(100)/100.0-0.5)*v_max));
b[i].vy+=(w_zaklucen*((random(100)/100.0-0.5)*v_max));
if (b[i].l>1) b[i].srednia_odleglosc/=(b[i].l-1);
for (int j=0; j<n; j++)
{
if (j==i) continue;
odl=sqrt(pow(b[i].x-b[j].x,2)+pow(b[i].y-b[j].y,2));
k = b[i].vx/sqrt(b[i].vx*b[i].vx+b[i].vy*b[i].vy) *
((b[j].x-b[i].x)/odl) +
b[i].vy/sqrt(b[i].vx*b[i].vx+b[i].vy*b[i].vy) *
((b[j].y-b[i].y)/odl);
if (k < -1) k = -1;
else if (k > 1) k = 1;
k = fabs((180.0*acos(k))/M_PI);
if (odl<r&&k<kat)
{
if (abs(b[j].x-b[i].x)>min)
{
b[i].vx+=(w_odleglosci/b[i].l)*(((b[j].x-b[i].x)*(odl-b[i].srednia_odleglosc))/odl);
b[i].vy+=(w_odleglosci/b[i].l)*(((b[j].y-b[i].y)*(odl-b[i].srednia_odleglosc))/odl);
}
else //jeżeli sąsiedzi są za blisko
{
b[i].vx-=(w_minimum/b[i].l)*((((b[j].x-b[i].x)*(min))/odl)-(b[j].x-b[i].x));
b[i].vy-=(w_minimum/b[i].l)*((((b[j].y-b[i].y)*(min))/odl)-(b[j].y-b[i].y));
}
}
}
if (sqrt(b[i].vx*b[i].vx+b[i].vy*b[i].vy)>v_max)
{
b[i].vx=0.75*b[i].vx;
b[i].vy=0.75*b[i].vy;
}
}
//przepisanie boidow znajdujacych sie za plansza
for (int i=0; i<n; i++)
{
if (b[i].x<0) b[i].x+=450;
if (b[i].y<0) b[i].y+=400;
if (b[i].x>450) b[i].x-=450;
if (b[i].y>400) b[i].y-=400;
}
}
}
//---------------------------------------------------------------------------

