void particle_initialize()
{
int i;
for (i = 0; i<particlenumber; i++)
{
Pu[i]=0;
}
return; }
void forceon_particle()
{
for (i = 0; i<particlenumber; i++)
{
FDx[i]=(U[i]-Pu[i])/taup;
FDy[i]=(V[i]-Pv[i])/taup;
}
return; }
void particle_motion()
{
int i;
for (i = 0; i<particlenumber; i++)
{
Pu[i]=Pu[i]+FDx[i]*tp;
Px[i]=Px[i]+Pu[i]*tp;}
return;
}
Hi Everyone, I'm unable to understand why I'm getting segmentation error in the function particle_motion.
The error comes only when I try assigning Px[i]=Px[i]+Pu[i]*tp; Py[i]=Py[i]+Pv[i]*tp;. Kindly help.
/*Developing flow in a Two Dimensional channel*/
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define NX 101
#define NY 101
#define Q 9
#define T 300001
#define u_in 0.01
#define omega 1
#define kvisc 1/6
#define W0 4.0/9.0
#define W1 1.0/9.0
#define W2 1.0/36.0
#define rho0 1.0
#define particlenumber 10000
#define dp 0.01
#define rhop 2
#define tp 1/omega
#define pi 3.14
int cx [Q]={0,1,0,-1,0,1,-1,-1,1};
int cy [Q]={0,0,1,0,-1,1,1,-1,-1};
double t [Q]={W0,W1,W1,W1,W1,W2,W2,W2,W2};
int next_x [NX][Q];
int next_y [NY][Q];
double f1 [NX][NY][Q];
double f2 [NX][NY][Q];
double ux [NX][NY];
double uy [NX][NY];
double uxeq [NX][NY];//eq velocity for effect of particle
double uyeq [NX][NY];
double ustar [NX][NY];//forcing term added to ueq
double vstar [NX][NY];
double rho [NX][NY];
double Px [particlenumber];//location of particles
double Py [particlenumber];
double Pu [particlenumber];//velocity of particles
double Pv [particlenumber];
double FDx [particlenumber];// drag force
double FDy [particlenumber];
double U [particlenumber];//velocity of particle
double V [particlenumber];
double FPx [particlenumber];//force on fluid due to particle
double FPy [particlenumber];
double uforcing [particlenumber];
double rhoatpar [particlenumber];
double vforcing [particlenumber];
void tables();
void initialise();
void cal_obs();
void streaming();
void collision();
void density_data();
void particle_initialize();
void forceon_particle();
void intrapolation_velocity();
void particle_motion();
void forceon_fluid();
void intrapolation_density();
void reverse_intrapolation();
int main()
{
int count=0, k;
tables();
initialise();
particle_initialize();
for(k=0;k<T;k++)
{
//printf("k=%d\t",k);
cal_obs();
collision();
streaming();
if (k % 10000 ==0)
{
density_data(count, k);
}
intrapolation_velocity();
forceon_particle();
intrapolation_density();
forceon_fluid();
reverse_intrapolation();
particle_motion();
}
return 0;
}
void tables()
{
int x,y,i;
for(x=0; x<NX; x++)
{
for (y=0; y<NY; y++)
{
for (i=0; i<Q; i++)
{
next_x[x][i] = x + cx[i];
if (next_x[x][i]>NX-1)
next_x[x][i] = 0;
if (next_x[x][i]<0)
next_x[x][i] = NX-1;
next_y[y][i] = y + cy[i];
if (next_y[y][i]>NY-1)
next_y[y][i] = 0;
if (next_y[y][i]<0)
next_y[y][i] = NY-1;
}
}
}
return;
}
void initialise()
{
int x,y,i;
for(x=0; x<NX; x++)
{
for (y=0; y<NY; y++)
{
ustar[x][y]=0;//initialize forcing term zero
vstar[x][y]=0;
for (i=0; i<Q; i++)
{
f1[x][y][i]=rho0*t[i];
}
}
}
return;
}
void cal_obs()
{
int x,y,i;
double dense;
for(x=0; x<NX; x++)
{
for (y=0; y<NY; y++)
{
dense=ux[x][y]=uy[x][y]=0.0;
for (i=0; i<Q; i++)
{
dense += f1[x][y][i];
ux[x][y] += f1[x][y][i]*cx[i];
uy[x][y] += f1[x][y][i]*cy[i];
}
if(dense != 0.0)
{
rho[x][y] = dense;
ux[x][y] = ux[x][y]/rho[x][y];
uy[x][y] = uy[x][y]/rho[x][y];
}
else
{
rho[x][y] = 0.0;
ux[x][y] = 0.0;
uy[x][y] = 0.0;
}
}
}
for(x=0; x<NX; x++)
{
ux[x][0]=u_in;
ux[x][NY-1]=-u_in;
}
return;
}
void collision()
{
int x,y,i;
double udotc,u2,feq;
for(x=0; x<NX; x++)
{
for (y=0; y<NY; y++)
{
for (i=0; i<Q; i++)
{
uxeq[x][y]=ustar[x][y]+ux[x][y];
uyeq[x][y]=vstar[x][y]+uy[x][y];
udotc = uxeq[x][y]*cx[i]+uyeq[x][y]*cy[i];
u2=uxeq[x][y]*uxeq[x][y] + uyeq[x][y]*uyeq[x][y];
feq = t[i]*rho[x][y]*(1+3*udotc+4.5*udotc*udotc-1.5*u2);
f1[x][y][i]=f1[x][y][i]*(1-omega)+feq*omega;
}
}
}
return;
}
void streaming()
{
int x,y,i,newx,newy;
double rho_w;
for(x=0; x<NX; x++)
{
for (y=0; y<NY; y++)
{
for (i=0; i<Q; i++)
{
newx=next_x [x][i];
newy=next_y[y][i];
f2[newx][newy][i] = f1[x][y][i];
}
}
}
for(x=0; x<NX; x++)
{
for (y=0; y<NY; y++)
{
for (i=0; i<Q; i++)
{
f1[x][y][i]=f2[x][y][i];
}
}
}
return;
}
void density_data(int data_counter, int id)
{
int x, y;
FILE *f3;
char phase [100];
/* Data for Tecplot*/
sprintf ( phase,"phaseVelocity2D_%d.csv",id);
f3 = fopen(phase, "w");
fprintf(f3," X,Y,Rho,U,V\n");
for (y =0; y < NY; y++)
{ for (x = 0; x < NX; x++)
fprintf(f3,"%d%c%d%c%lf%c%lf%c%lf\n",x,',',y,',',rho[x][y],',',ux[x][y],',',uy[x][y]);
}
fflush(f3);
fclose(f3);
int i;
FILE *f4;
char particle [100];
sprintf ( particle,"particle_%d.csv",id);
f4 = fopen(particle, "w");
fprintf(f4," Id,X,Y\n");
for (i =0; i < particlenumber; i++)
{
fprintf(f4,"%d%c%lf%c%lf\n",i,',',Px[i],',',Py[i]);
}
fflush(f4);
fclose(f4);
return;
}
void particle_initialize()
{
int i;
srand(time(0));
float randomx;
for (i = 0; i<particlenumber; i++)
{
randomx=(float)rand()/RAND_MAX;
Px[i]=randomx*NX;
Pu[i]=0;
}
float randomy;
for (i = 0; i<particlenumber; i++)
{
randomy=(float)rand()/RAND_MAX;
Py[i]=randomy*NY;
Pv[i]=0;
}
return;
}
void forceon_particle()
{
int i;
double taup;
taup=(rhop*dp*dp)/(18*kvisc*rho0);
for (i = 0; i<particlenumber; i++)
{
FDx[i]=(U[i]-Pu[i])/taup;
FDy[i]=(V[i]-Pv[i])/taup;
}
return;
}
void intrapolation_velocity()
{
int i;
int node1x, node1y, node2x, node2y,node3x, node3y,node4x, node4y;
double w1,w2,w3,w4;
for (i = 0; i<particlenumber; i++)
{
node1x=trunc(Px[i]);
node1y=trunc(Py[i]);
node2x=node1x;
node2y=node1y+1;
node3x=node1x+1;
node3y=node1y+1;
node4x=node1x+1;
node4y=node1y;
w1=(Px[i]-node1x)*(Px[i]-node1x)+(Py[i]-node1y)*(Py[i]-node1y);
w1=sqrt(w1);
w2=(Px[i]-node2x)*(Px[i]-node2x)+(Py[i]-node2y)*(Py[i]-node2y);
w2=sqrt(w2);
w3=(Px[i]-node3x)*(Px[i]-node3x)+(Py[i]-node3y)*(Py[i]-node3y);
w3=sqrt(w3);
w4=(Px[i]-node4x)*(Px[i]-node4x)+(Py[i]-node4y)*(Py[i]-node4y);
w4=sqrt(w4);
U[i]=w1*ux[node1x][node1y]+w2*ux[node2x][node2y]+w3*ux[node3x][node3y]+w4*ux[node4x][node4y];
U[i]=U[i]/(w1+w2+w3+w4);
V[i]=w1*uy[node1x][node1y]+w2*uy[node2x][node2y]+w3*uy[node3x][node3y]+w4*uy[node4x][node4y];
V[i]=V[i]/(w1+w2+w3+w4);
}
return;
}
void particle_motion()
{
int i;
double A,B;
for (i = 0; i<particlenumber; i++)
{
Pu[i]=Pu[i]+FDx[i]*tp;//Pu[i] added so that it adds previous velocity
Pv[i]=Pv[i]+FDy[i]*tp;
}
for (i = 0; i<particlenumber; i++)
{
Px[i]=Px[i]+Pu[i]*tp;
Py[i]=Py[i]+Pv[i]*tp;
//if particle goes out of bound we r introducing periodic BC
if(Px[i]<0||Px[i]>(NX-1))
{
if(Px[i]<0)
{Px[i]=Px[i]+NX-1;}
else if(Px[i]>(NX-1))
{Px[i]=Px[i]-NX+1;}
}
if(Py[i]<0||Py[i]>(NY-1))
{
if(Py[i]<0)
{Py[i]=Py[i]+NY-1;}
else if(Py[i]>(NY-1))
{Py[i]=Py[i]-NY+1;}
}
}
return;
}
void forceon_fluid()
{
int i;
double taup;
long double mp;
mp=(1/6)*(pi)*rhop*dp*dp*dp;
taup=(rhop*dp*dp)/(18*kvisc*rho0);
for (i = 0; i<particlenumber; i++)
{
FPx[i]=mp*(U[i]-Pu[i]);
FPx[i]=FPx[i]/taup;
FPy[i]=mp*(V[i]-Pv[i]);
FPy[i]=FPy[i]/taup;
uforcing[i]=(FPx[i])/(rhoatpar[i]*omega);
vforcing[i]=(FPy[i])/(rhoatpar[i]*omega);
}
return;
}
void intrapolation_density()
{
int i;
int node1x, node1y, node2x, node2y,node3x, node3y,node4x, node4y;
double w1,w2,w3,w4;
for (i = 0; i<particlenumber; i++)
{
node1x=trunc(Px[i]);
node1y=trunc(Py[i]);
node2x=node1x;
node2y=node1y+1;
node3x=node1x+1;
node3y=node1y+1;
node4x=node1x+1;
node4y=node1y;
w1=(Px[i]-node1x)*(Px[i]-node1x)+(Py[i]-node1y)*(Py[i]-node1y);
w1=sqrt(w1);
w2=(Px[i]-node2x)*(Px[i]-node2x)+(Py[i]-node2y)*(Py[i]-node2y);
w2=sqrt(w2);
w3=(Px[i]-node3x)*(Px[i]-node3x)+(Py[i]-node3y)*(Py[i]-node3y);
w3=sqrt(w3);
w4=(Px[i]-node4x)*(Px[i]-node4x)+(Py[i]-node4y)*(Py[i]-node4y);
w4=sqrt(w4);
rhoatpar[i]=w1*rho[node1x][node1y]+w2*rho[node2x][node2y]+w3*rho[node3x][node3y]+w4*rho[node4x][node4y];
rhoatpar[i]=rhoatpar[i]/(w1+w2+w3+w4);
}
return;
}
void reverse_intrapolation()
{
int i;
int node1x, node1y, node2x, node2y,node3x, node3y,node4x, node4y;
double w1,w2,w3,w4;
int x,y;
for(x=0; x<NX; x++)
{
for (y=0; y<NY; y++)
{
ustar[x][y]=0;//initialize forcing term zero
vstar[x][y]=0;
}
}
for (i = 0; i<particlenumber; i++)
{
node1x=trunc(Px[i]);
node1y=trunc(Py[i]);
node2x=node1x;
node2y=node1y+1;
node3x=node1x+1;
node3y=node1y+1;
node4x=node1x+1;
node4y=node1y;
w1=(Px[i]-node1x)*(Px[i]-node1x)+(Py[i]-node1y)*(Py[i]-node1y);
w1=sqrt(w1);
w2=(Px[i]-node2x)*(Px[i]-node2x)+(Py[i]-node2y)*(Py[i]-node2y);
w2=sqrt(w2);
w3=(Px[i]-node3x)*(Px[i]-node3x)+(Py[i]-node3y)*(Py[i]-node3y);
w3=sqrt(w3);
w4=(Px[i]-node4x)*(Px[i]-node4x)+(Py[i]-node4y)*(Py[i]-node4y);
w4=sqrt(w4);
ustar[node1x][node1y]=ustar[node1x][node1y]+(w1*uforcing[i])/(w1+w2+w3+w4);
vstar[node1x][node1y]=vstar[node1x][node1y]+(w1*vforcing[i])/(w1+w2+w3+w4);
ustar[node2x][node2y]=ustar[node2x][node2y]+(w1*uforcing[i])/(w1+w2+w3+w4);
vstar[node2x][node2y]=vstar[node2x][node2y]+(w1*vforcing[i])/(w1+w2+w3+w4);
ustar[node3x][node3y]=ustar[node3x][node3y]+(w1*uforcing[i])/(w1+w2+w3+w4);
vstar[node3x][node3y]=vstar[node3x][node3y]+(w1*vforcing[i])/(w1+w2+w3+w4);
ustar[node4x][node4y]=ustar[node4x][node4y]+(w1*uforcing[i])/(w1+w2+w3+w4);
vstar[node4x][node4y]=vstar[node4x][node4y]+(w1*vforcing[i])/(w1+w2+w3+w4);
}
return;
}
I have added the whole code as the error may be due to other functions which might also access the arrays.
The issue is at this statement.
V[i] = w1* uy[node1x][node1y] + w2* uy[node2x][node2y] + w3 * uy[node3x][node3y] + w4*uy[node4x][node4y];
Here,the arrays are uy[101][101], ux[101][101]. Look at the values of node1x and node1y:
node1x=trunc(Px[i]);
node1y=trunc(Py[i]);
See the values of Px[i] and Py[i] :
Px[i]=randomx*NX; // NX=101. randomx ranges from 0 to 1. randomx=(float)rand()/RAND_MAX
Py[i]=randomy*NY; // NY=101. randomy ranges from 0 to 1. randomy=(float)rand()/RAND_MAX
I think at some point of time randomx = 1, then Px[i] = 101, then node1x = 101 then you are accessing uy[101][node1y]. This causes segmentation fault because the array is uy[101][101] , and you cannot access uy[101][node1y]element.
Good day,
I'm working on a C library (for myself, code: https://github.com/BattlestarSC/matrixLibrary.git) to handle matrix functions. This is mostly a learning/practice activity. One of my challenges is to take the determinant of a matrix efficiently. As my current attempts have failed, I wanted to take a different approach. I was reading though this method from MIT docs: http://web.mit.edu/18.06/www/Spring17/Determinants.pdf and it made a lot of sense. The issue I'm having is how to get to said point. As the Gaussian elimination method is good for multi-variable systems of equations, my matricies are not built from equations, and therefor are not part of a system. As in, each equation has no set result and does not fit into the form from this paper here:https://math.oregonstate.edu/home/programs/undergrad/CalculusQuestStudyGuides/vcalc/gauss/gauss.html
From this point, I'm at a loss as far as how to proceed with this method.
It makes a lot of sense to take the pivot point from each set of equations as described in the MIT paper, but how should I set up my matricies to make said result valid?
When you perform a Gaussian elimination, you swap rows and repeatedly subtract a multiple of one row from another to produce an upper triangular form.
When you do this on a system of equations or an "augmented matrix", you do not use any information from the result column. The decisions about which rows to swap and which to subtract with what multiplier would be exactly the same no matter what numbers are in the result column.
Because the "result column" is not used, you can perform the same procedure on a normal square matrix. Since the operations don't change the determinant (if you negate one row whenever you swap), you end up with an upper triangular matrix with the same det as the original.
The MIT author calls a function lu to do this in the example near the start. This does L-U decomposition on the matrix, which returns the Gaussian-eliminated matrix in the 'U' part: https://en.wikipedia.org/wiki/LU_decomposition.
L-U decomposition is pretty cool. It's like doing Gaussian elimination to solve all systems with the same "matrix part" all at once, which again you can do because the process doesn't need to see the result column at all.
Starting with a matrix M, you get L and U such that LU = M. That means, if you want to solve:
Mx = y
... where (x an y are column vectors), you have:
LUx = y
Solve Lv=y, which is easy (just substitution) because L is lower-triangular. Then you have:
Ux = v
... which is easy to solve because U is upper-triangular.
GEM is not very good for computers as it needs to reorder the rows so the algo leads to a valid result that adds relatively big overhead and potential instability (if ordered badly). The GEM is much better suited for humans and paper/pencil as we instinctively reorder/chose rows ...
So you should go with the (sub)Determinant approach as you wanted in the first place. Is faster and safer. I know its a bit tricky to learn it from papers. If it helps this is mine ancient matrix.h class (but in C++) I wrote when I was still a rookie (so there might be some hidden bugs I do not know of haven't use this for ages):
//--- matrix ver: 2.1 -------------------------------------------------------
#ifndef _matrix_h
#define _matrix_h
//---------------------------------------------------------------------------
double fabs(double x)
{
if (x<0) x=-x;
return x;
}
//---------------------------------------------------------------------------
class matrix
{
private:double **p;
int xs,ys;
double zeroacc;
public: matrix() { p=NULL; xs=0; ys=0; resize(1,1); zeroacc=1e-10; }
~matrix() { free(); }
void free();
int resize(int _xs,int _ys);
matrix& operator=(const matrix &b);
matrix& operator+();
matrix& operator-();
matrix& operator+(matrix &b);
matrix& operator-(matrix &b);
matrix& operator*(matrix &b);
matrix& operator+=(matrix &b);
matrix& operator-=(matrix &b);
matrix& operator*=(matrix &b);
matrix& operator!();
double& operator()(int y,int x);
double* operator[](int y) { return p[y]; }
void one();
int get_xs() { return xs; }
int get_ys() { return ys; }
double get_zeroacc() { return zeroacc; }
void set_zeroacc(double _zeroacc) { zeroacc=_zeroacc; if (zeroacc<0) zeroacc=-zeroacc; }
void ld(int y,double x0=0.0,double x1=0.0,double x2=0.0,double x3=0.0,double x4=0.0,double x5=0.0,double x6=0.0,double x7=0.0,double x8=0.0,double x9=0.0);
void prn(TCanvas *scr,int x0,int y0);
void lxch(int y1,int y2);
void lcom(int y1,int y2,double k);
void lmul(int y,double k);
void ldiv(int y,double k);
int gaus(matrix &b);
matrix& matrix::submatrix(int _x,int _y);
double determinant();
double subdeterminant();
matrix& inv_det();
matrix& inv_gaus();
};
//---------------------------------------------------------------------------
void matrix::free()
{
int y;
if (p!=NULL)
for (y=0;y<ys;y++)
delete[] p[y];
delete[] p;
p=NULL;
xs=0;
ys=0;
}
//---------------------------------------------------------------------------
int matrix::resize(int _xs,int _ys)
{
int y;
free();
if (_xs<1) _xs=1;
if (_ys<1) _ys=1;
xs=_xs;
ys=_ys;
p=new double*[ys];
if (p==NULL)
{
xs=0;
ys=0;
return 0;
}
for (y=0;y<ys;y++)
{
p[y]=new double[xs];
if (p[y]==NULL)
{
if (y>0)
for (y--;y>=0;y--)
delete p[y];
delete p;
p=NULL;
xs=0;
ys=0;
return 0;
}
}
return 1;
}
//---------------------------------------------------------------------------
matrix& matrix::operator=(const matrix &b)
{
int x,y;
if (!resize(b.get_xs(),b.get_ys())) return *this;
if (b.p)
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
p[y][x]=b.p[y][x];
return *this;
}
//---------------------------------------------------------------------------
matrix& matrix::operator+()
{
static matrix c;
int x,y;
c.resize(xs,ys);
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
c.p[y][x]= p[y][x];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator-()
{
static matrix c;
int x,y;
c.resize(xs,ys);
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
c.p[y][x]=-p[y][x];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator+(matrix &b)
{
static matrix c;
int x,y;
c.free();
if (xs!=b.get_xs()) return c;
if (ys!=b.get_ys()) return c;
c.resize(xs,ys);
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
c.p[y][x]=p[y][x]+b.p[y][x];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator-(matrix &b)
{
static matrix c;
int x,y;
c.free();
if (xs!=b.get_xs()) return c;
if (ys!=b.get_ys()) return c;
c.resize(xs,ys);
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
c.p[y][x]=p[y][x]-b.p[y][x];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator*(matrix &b)
{
static matrix c;
int i,j,k,ii,jj,kk;
c.free();
ii=ys;
jj=b.get_xs();
kk=b.get_ys();
if (kk!=xs) return c;
if (!c.resize(jj,ii)) return c;
for (i=0;i<ii;i++)
for (j=0;j<jj;j++)
c.p[i][j]=0.0;
for (i=0;i<ii;i++)
for (j=0;j<jj;j++)
for (k=0;k<kk;k++)
c.p[i][j]+=p[i][k]*b.p[k][j];
return c;
}
//---------------------------------------------------------------------------
matrix& matrix::operator+=(matrix &b)
{
int x,y;
if (xs!=b.get_xs()) { free(); return *this; }
if (ys!=b.get_ys()) { free(); return *this; }
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
p[y][x]+=b.p[y][x];
return *this;
}
//---------------------------------------------------------------------------
matrix& matrix::operator-=(matrix &b)
{
int x,y;
if (xs!=b.get_xs()) { free(); return *this; }
if (ys!=b.get_ys()) { free(); return *this; }
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
p[y][x]-=b.p[y][x];
return *this;
}
//---------------------------------------------------------------------------
matrix& matrix::operator*=(matrix &b)
{
matrix c;
int i,j,k,ii,jj,kk;
c.free();
ii=ys;
jj=b.get_xs();
kk=b.get_ys();
if (kk!=xs) { *this=c; return *this; }
if (!c.resize(jj,ii)) { *this=c; return *this; }
for (i=0;i<ii;i++)
for (j=0;j<jj;j++)
c.p[i][j]=0.0;
for (i=0;i<ii;i++)
for (j=0;j<jj;j++)
for (k=0;k<kk;k++)
c.p[i][j]+=p[i][k]*b.p[k][j];
*this=c; return *this;
}
//---------------------------------------------------------------------------
matrix& matrix::operator!()
{
// return inv_det();
return inv_gaus();
}
//---------------------------------------------------------------------------
double& matrix::operator()(int y,int x)
{
static double _null;
if (x<0) return _null;
if (y<0) return _null;
if (x>=xs) return _null;
if (y>=ys) return _null;
return p[y][x];
}
//---------------------------------------------------------------------------
void matrix::one()
{
int x,y;
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
if (x!=y) p[y][x]=0.0;
else p[y][x]=1.0;
}
//---------------------------------------------------------------------------
void matrix::ld(int y,double x0,double x1,double x2,double x3,double x4,double x5,double x6,double x7,double x8,double x9)
{
int x;
if (y<0) return;
if (y>=ys) return;
x=0;
if (x<xs) p[y][x]=x0; x++;
if (x<xs) p[y][x]=x1; x++;
if (x<xs) p[y][x]=x2; x++;
if (x<xs) p[y][x]=x3; x++;
if (x<xs) p[y][x]=x4; x++;
if (x<xs) p[y][x]=x5; x++;
if (x<xs) p[y][x]=x6; x++;
if (x<xs) p[y][x]=x7; x++;
if (x<xs) p[y][x]=x8; x++;
if (x<xs) p[y][x]=x9; x++;
}
//---------------------------------------------------------------------------
void matrix::prn(TCanvas *scr,int x0,int y0)
{
int x,y,xx,yy,dx,dy;
dx=50;
dy=13;
yy=y0;
for (y=0;y<ys;y++)
{
xx=x0;
for (x=0;x<xs;x++)
{
scr->TextOutA(xx,yy,AnsiString().sprintf("%.4lf",p[y][x]));
xx+=dx;
}
yy+=dy;
}
}
//---------------------------------------------------------------------------
void matrix::lxch(int y1,int y2)
{
int x;
double a;
if (y1<0) return;
if (y2<0) return;
if (y1>=ys) return;
if (y2>=ys) return;
for (x=0;x<xs;x++) { a=p[y1][x]; p[y1][x]=p[y2][x]; p[y2][x]=a; }
}
//---------------------------------------------------------------------------
void matrix::lcom(int y1,int y2,double k)
{
int x;
if (y1<0) return;
if (y2<0) return;
if (y1>=ys) return;
if (y2>=ys) return;
for (x=0;x<xs;x++) p[y1][x]+=p[y2][x]*k;
}
//---------------------------------------------------------------------------
void matrix::lmul(int y,double k)
{
int x;
if (y<0) return;
if (y>=ys) return;
for (x=0;x<xs;x++) p[y][x]*=k;
}
//---------------------------------------------------------------------------
void matrix::ldiv(int y,double k)
{
int x;
if (y<0) return;
if (y>=ys) return;
if ((k> zeroacc)||(k<-zeroacc)) k=1.0/k; else k=0.0;
for (x=0;x<xs;x++) p[y][x]*=k;
}
//---------------------------------------------------------------------------
int matrix::gaus(matrix &b)
{
int x,y;
double a;
if (xs!=ys) return 0;
if (ys!=b.ys) return 0;
for (x=0;x<xs;x++)
{
a=p[x][x]; // je aktualny prvok (x,x) na diagonale = 0 ?
if (a<0) a=-a;
if (a<=zeroacc)
for (y=0;y<ys;y++) // ak hej najdi nejaky nenulovy riadok v aktualnom stlpci (x)
if (x!=y)
{
a=p[y][x];
if (a<0) a=-a;
if (a>=zeroacc) // ak sa nasiel tak ho pripocitaj k aktualnemu riadku co zrusi tu nulu
{
b.lcom(x,y,1.0);
lcom(x,y,1.0);
break;
}
}
a=p[x][x]; // este raz otestuj ci na diagonale neni nula
if (a<0) a=-a;
if (a<=zeroacc) return 0; // ak je tak koniec
b.ldiv(x,p[x][x]); // sprav na diagonale 1-tku
ldiv(x,p[x][x]);
for (y=0;y<ys;y++) // a vynuluj zvysne riadky v stlpci(x)
if (y!=x)
{
b.lcom(y,x,-p[y][x]);
lcom(y,x,-p[y][x]);
}
}
return 1;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
matrix& matrix::submatrix(int _x,int _y)
{
static matrix c;
int x,y,xx,yy;
c.resize(xs-1,ys-1);
yy=0; for (y=0;y<ys;y++)
if (y!=_y)
{
xx=0; for (x=0;x<xs;x++)
if (x!=_x)
{
c.p[yy][xx]=p[y][x];
xx++;
}
yy++;
}
return c;
}
//---------------------------------------------------------------------------
double matrix::determinant()
{
double D;
matrix a;
int x,y,s;
D=0;
if (xs!=ys) return D;
if (xs==1) { D=p[0][0]; return D; }
y=0;
s=y&1;
for (x=0;x<xs;x++)
{
a=submatrix(x,y);
if (s) D-=a.determinant()*p[y][x];
else D+=a.determinant()*p[y][x];
s=!s;
}
return D;
}
//---------------------------------------------------------------------------
double matrix::subdeterminant()
{
double D;
matrix a,b;
int x,y,s;
D=0;
if (xs!=ys) return D;
if (xs==1) { D=p[0][0]; return D; }
b=this[0];
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
{
a=b.submatrix(x,y);
p[y][x]=a.determinant();
}
y=0;
s=y&1;
for (x=0;x<xs;x++)
{
if (s) D-=p[y][x]*b.p[y][x];
else D+=p[y][x]*b.p[y][x];
s=!s;
}
return D;
}
//---------------------------------------------------------------------------
matrix& matrix::inv_det()
{
int x,y,s;
double D;
static matrix a,b;
a=this[0];
b=this[0];
D=b.subdeterminant();
if (fabs(D)>zeroacc) D=1.0/D;
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
{
s=(x+y)&1;
if (s) a.p[y][x]=-b.p[x][y]*D;
else a.p[y][x]= b.p[x][y]*D;
}
return a;
}
//---------------------------------------------------------------------------
matrix& matrix::inv_gaus()
{
static matrix a,b;
a=*this;
b.resize(xs,ys);
b.one();
a.gaus(b);
return b;
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
Both GEM inv_gaus and (sub)determinant inv_det approaches are present so just extract/compare from it what you need.
BTW lately I needed some math stuff for N-dimensional space and once I was at it I also coded a square matrix as template where the (sub)Determinant approach is done as recursive template nd_math.h:
//--- N-Dimensional math ver: 1.002 -----------------------------------------
#ifndef _ND_math_h
#define _ND_math_h
//---------------------------------------------------------------------------
#include <math.h>
//---------------------------------------------------------------------------
#ifndef _rep4d_h
double divide(double a,double b) { if (fabs(b)<1e-30) return 0.0; return a/b; }
#endif
//---------------------------------------------------------------------------
template <const DWORD N> class vector
{
public:
double a[N];
vector() {}
vector(vector& a) { *this=a; }
~vector() {}
vector* operator = (const vector<N> *a) { *this=*a; return this; }
//vector* operator = (vector<N> &a) { ...copy... return this; }
double& operator [](const int i) { return a[i]; }
vector<N> operator + () { return *this; } // =+v0
vector<N> operator - () { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]= -a[i]; return q; } // =-v0
vector<N> operator + (vector<N> &v) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]+v.a[i]; return q; } // =v0+v1
vector<N> operator - (vector<N> &v) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]-v.a[i]; return q; } // =v0-v1
double operator * (vector<N> &v) { int i; double q; for (q=0.0,i=0;i<N;i++) q +=a[i]*v.a[i]; return q; } // =(v0.v1) dot product
vector<N> operator + (const double &c) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]+c; return q; } // =v0+(c,c,c,c,...)
vector<N> operator - (const double &c) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]-c; return q; } // =v0-(c,c,c,c,...)
vector<N> operator * (const double &c) { int i; vector<N> q; for ( i=0;i<N;i++) q.a[i]=a[i]*c; return q; } // =v0*c
vector<N> operator / ( double c) { int i; vector<N> q; c=divide(1.0,c); for ( i=0;i<N;i++) q.a[i]=a[i]*c; return q; } // =v0/c
vector<N> operator +=(vector<N> &v) { this[0]=this[0]+v; return *this; }; // v0+=v1
vector<N> operator -=(vector<N> &v) { this[0]=this[0]-v; return *this; }; // v0-=v1
vector<N> operator +=(const double &c) { this[0]=this[0]+c; return *this; }; // v0+=(c,c,c,c,...)
vector<N> operator -=(const double &c) { this[0]=this[0]-c; return *this; }; // v0-=(c,c,c,c,...)
vector<N> operator *=(const double &c) { this[0]=this[0]*c; return *this; }; // v0*=c
vector<N> operator /=(const double &c) { this[0]=this[0]/c; return *this; }; // v0/=c
AnsiString str() { int i; AnsiString q; for (q="( ",i=0;i<N;i++) q+=AnsiString().sprintf("%6.3lf ",a[i]); q+=")"; return q; }
double len() { int i; double l; for (l=0.0,i=0;i<N;i++) l+=a[i]*a[i]; return sqrt(l); } // get size
double len2() { int i; double l; for (l=0.0,i=0;i<N;i++) l+=a[i]*a[i]; return l; } // get size^2
void len(double l) { int i; l=divide(l,len()); for (i=0;i<N;i++) a[i]*=l; } // set size
void unit() { len(1.0); } // set unit size
void zero() { int i; for (i=0;i<N;i++) a[i]=0.0; } // set zero vector
void rnd() { int i; for (i=0;i<N;i++) a[i]=(2.0*Random())-1.0; } // set random unit vector
void set(double c) { int i; for (i=0;i<N;i++) a[i]=c; } // (c,c,c,c,...)
// i x j = k | | i j k |
// j x k = i | a x b = det | a0 a1 a2 | = + i*det | a1 a2 | - j*det | a0 a2 | + k*det | a0 a1 |
// k x i = j | | b0 b1 b2 | | b1 b2 | | b0 b2 | | b0 b1 |
void cross(const vector<N> *v)
{
int i,j;
matrix<N> m0;
matrix<N-1> m;
for (i=1;i<N;i++)
for (j=0;j<N;j++)
m0.a[i][j]=v[i-1].a[j];
for (j=0;j<N;j++)
{
m=m0.submatrix(0,j);
if (int(j&1)==0) a[j]=+m.det();
else a[j]=-m.det();
}
}
void cross(vector<N> **v)
{
int i,j;
matrix<N> m0;
matrix<N-1> m;
for (i=1;i<N;i++)
for (j=0;j<N;j++)
m0.a[i][j]=v[i-1]->a[j];
for (j=0;j<N;j++)
{
m=m0.submatrix(0,j);
if (int(j&1)==0) a[j]=+m.det();
else a[j]=-m.det();
}
}
void cross(vector<N> &v0) { vector<N> *v[ 1]={&v0}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1) { vector<N> *v[ 2]={&v0,&v1}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2) { vector<N> *v[ 3]={&v0,&v1,&v2}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3) { vector<N> *v[ 4]={&v0,&v1,&v2,&v3}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4) { vector<N> *v[ 5]={&v0,&v1,&v2,&v3,&v4}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5) { vector<N> *v[ 6]={&v0,&v1,&v2,&v3,&v4,&v5}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5,vector<N> &v6) { vector<N> *v[ 7]={&v0,&v1,&v2,&v3,&v4,&v5,&v6}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5,vector<N> &v6,vector<N> &v7) { vector<N> *v[ 8]={&v0,&v1,&v2,&v3,&v4,&v5,&v6,&v7}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5,vector<N> &v6,vector<N> &v7,vector<N> &v8) { vector<N> *v[ 9]={&v0,&v1,&v2,&v3,&v4,&v5,&v6,&v7,v8}; cross(v); }
void cross(vector<N> &v0,vector<N> &v1,vector<N> &v2,vector<N> &v3,vector<N> &v4,vector<N> &v5,vector<N> &v6,vector<N> &v7,vector<N> &v8,vector<N> &v9) { vector<N> *v[10]={&v0,&v1,&v2,&v3,&v4,&v5,&v6,&v7,v8,v9}; cross(v); }
void ld(const double &a0) { a[0]=a0; }
void ld(const double &a0,const double &a1) { a[0]=a0; a[1]=a1; }
void ld(const double &a0,const double &a1,const double &a2) { a[0]=a0; a[1]=a1; a[2]=a2; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5,const double &a6) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; a[6]=a6; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5,const double &a6,const double &a7) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; a[6]=a6; a[7]=a7; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5,const double &a6,const double &a7,const double &a8) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; a[6]=a6; a[7]=a7; a[8]=a8; }
void ld(const double &a0,const double &a1,const double &a2,const double &a3,const double &a4,const double &a5,const double &a6,const double &a7,const double &a8,const double &a9) { a[0]=a0; a[1]=a1; a[2]=a2; a[3]=a3; a[4]=a4; a[5]=a5; a[6]=a6; a[7]=a7; a[8]=a8; a[9]=a9; }
};
//---------------------------------------------------------------------------
template <DWORD N> class matrix // square matrix
{
public:
vector<N> a[N];
matrix() {}
matrix(matrix& a) { *this=a; }
~matrix() {}
matrix* operator = (const matrix<N> *a) { *this=*a; return this; }
//matrix* operator = (matrix<N> &a) { ...copy... return this; }
vector<N>& operator [](const int i) { return a[i]; }
matrix<N> operator + () { return *this; }
matrix<N> operator - () { matrix<N> q; int i,j; for (i=0;i<M;i++) for (j=0;j<N;j++) q[i][j]=-a[i][j]; return q; } // = -m0
matrix<N> operator * (const matrix &m)
{
matrix<N> q;
int i,j,k;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
for (q.a[i][j]=0.0,k=0;k<N;k++)
q.a[i].a[j]+=a[i].a[k]*m.a[k].a[j];
return q;
}
vector<N> operator * (vector<N> &v)
{
vector<N> q;
int i,j;
for (i=0;i<N;i++)
for (q.a[i]=0.0,j=0;j<N;j++)
q.a[i]+=a[i][j]*v.a[j];
return q;
}
matrix<N> operator * (const double &c)
{
matrix<N> q;
int i,j;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
q.a[i].a[j]=a[i].a[j]*c;
return q;
}
matrix<N> operator / (const double &c)
{
return this[0]*divide(1.0,c);
}
matrix<N> operator *=(matrix<N> &m) { this[0]=this[0]*m; return *this; };
vector<N> operator *=(vector<N> &v) { this[0]=this[0]*v; return *this; };
matrix<N> operator *=(const double &c) { this[0]=this[0]*c; return *this; };
matrix<N> operator /=(const double &c) { this[0]=this[0]/c; return *this; };
AnsiString str() { int i,j; AnsiString q; for (q="",i=0;i<N;i++,q+="\r\n") { for (q+="( ",j=0;j<N;j++) q+=AnsiString().sprintf("%6.3lf ",a[i][j]); q+=")"; } return q; }
void unit() { int i,j; for (i=0;i<N;a[i][i]=1.0,i++) for (j=0;j<N;j++) a[i][j]=0.0; } // set unit matrix
void zero() { int i,j; for (i=0;i<N;i++) for (j=0;j<N;j++) a[i][j]=0.0; } // set zero matrix
void rnd() { int i,j; for (i=0;i<N;i++) for (j=0;j<N;j++) a[i][j]=(2.0*Random())-1.0; } // set random <-1,+1> matrix
void set(double c) { int i,j; for (i=0;i<N;i++) for (j=0;j<N;j++) a[i][j]=c; } // (c,c,c,c,...)
void orthonormal() // convert to orthonormal matrix
{
int i,j;
vector<N> *pV[N],*pp;
for (i=0;i<N;i++) { a[i].unit(); pV[i]=a+i; }
for (i=1;i<N;i++)
{
pV[0]->cross(pV+1);
pp=pV[0]; for (j=1;j<N;j++) pV[j-1]=pV[j]; pV[N-1]=pp;
}
}
matrix<N> transpose()
{
int i,j;
matrix<N> M;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
M[i][j]=a[j][i];
return M;
}
matrix<N> inverse()
{
return adjugate()/det();
}
matrix<N> adjugate()
{
matrix<N> C;
double s;
int i,j;
for (i=0;i<N;i++)
for ((i&1)?s=-1.0:s=+1.0,j=0;j<N;j++,s=-s)
C[j][i]=minor(i,j)*s;
return C;
}
matrix<N> cofactor()
{
matrix<N> C;
double s;
int i,j;
for (i=0;i<N;i++)
for ((i&1)?s=+1.0:s=-1.0,j=0;j<N;j++,s=-s)
C[i][j]=minor(i,j)*s;
return C;
}
double minor(int i,int j)
{
return submatrix(i,j).det();
}
matrix<N-1> submatrix(int i,int j)
{
matrix<N-1> m;
int i0,i1,j0,j1;
for (i0=0,i1=0;i1<N;i1++)
if (i1!=i){ for (j0=0,j1=0;j1<N;j1++)
if (j1!=j){ m.a[i0][j0]=a[i1][j1]; j0++; } i0++; }
return m;
}
double det();
};
//---------------------------------------------------------------------------
double matrix<1>::det() { return a[0][0]; }
double matrix<2>::det() { return (a[0][0]*a[1][1])-(a[0][1]*a[1][0]); }
template <DWORD N> double matrix<N>::det()
{
double d=0.0; int j;
matrix<N-1> m;
for (j=0;j<N;j++)
{
m=submatrix(0,j);
if (int(j&1)==0) d+=a[0][j]*m.det();
else d-=a[0][j]*m.det();
}
return d;
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
But as you can see that code is a bit more complicated to follow as I am in a different coding level now (look for inverse)...
If you need also results then compute it as matrix equation:
A*X = Y
X = inv(A)*Y
Where X are unknowns (vector) , Y are knowns (vector) and A is the matrix.
I'm working on a boids flocking project.
My goal is to have several draggable objects which have to be avoided by the boids.
There are several different flocks with a different starting position.
I managed to get the boids to avoid one draggable object. But I can't seem to make them avoid all. (using a for loop)
I really can't figure out why this won't do the trick..
I hope you could give me some suggestions.
the code:
int initBoidNum = 100; //amount of boids to start the program with
BoidList flock1, flock2, flock3;
Draggable draggable;
NullDraggableObject nullDraggableObject;
ArrayList draggables;
int id;
float[] xposs= new float[10];
float[] yposs= new float[10];
String turn;
void setup() {
size(1000, 700);
//create and fill the list of boids
flock1 = new BoidList(150, 0, 10, 100);
flock2 = new BoidList(150, 255, 10, 200);
flock3 = new BoidList(150, 150, 10, 300);
turn = "turn";
nullDraggableObject = new NullDraggableObject();
draggables = new ArrayList();
for (int i = 0; i < 10; i++) {
draggables.add(new DraggableObject(random(width), random(height/2)));
}
}
void draw() {
background(100, 60);
flock1.run();
flock2.run();
flock3.run();
stroke(255);
noFill();
draggable = nullDraggableObject;
for (id = 0; id < draggables.size (); id++) {
Draggable d = (Draggable)draggables.get(id);
d.draw();
if (d.isBeingMouseHovered()) {
draggable = d;
}
}
}
void mousePressed() {
draggable.mousePressed();
}
void mouseDragged() {
draggable.mouseDragged();
}
void mouseReleased() {
draggable.mouseReleased();
}
interface Draggable {
boolean isBeingMouseHovered();
boolean inside(float ix, float iy);
void draw();
void mousePressed();
void mouseDragged();
void mouseReleased();
}
class NullDraggableObject implements Draggable {
boolean isBeingMouseHovered() {
return false;
}
boolean inside(float ix, float iy) {
return false;
}
void draw() {
}
void mousePressed() {
}
void mouseDragged() {
}
void mouseReleased() {
}
}
public class DraggableObject implements Draggable {
float XX, YY;
float radius;
boolean drag;
float dragX, dragY;
DraggableObject(float _x, float _y) {
XX = _x;
YY = _y;
radius = 50;
drag = false;
dragX = 0;
dragY = 0;
}
boolean isBeingMouseHovered() {
return inside(mouseX, mouseY);
}
boolean inside(float ix, float iy) {
return (dist(XX, YY, ix, iy) < radius);
}
void draw() {
ellipseMode(CENTER);
ellipse(XX, YY, 2*radius, 2*radius);
String space = "__";
println(id);
println(XX);
println(YY);
xposs[id] = XX;
yposs[id] = YY;
}
void mousePressed() {
drag = inside(mouseX, mouseY);
if (drag) {
dragX = mouseX - XX;
dragY = mouseY - YY;
}
}
void mouseDragged() {
if (drag) {
XX = mouseX - dragX;
YY = mouseY - dragY;
}
}
void mouseReleased() {
drag = false;
}
}
class Boid {
//fields
PVector pos, vel, acc, ali, coh, sep; //pos, velocity, and acceleration in a vector datatype
float neighborhoodRadius; //radius in which it looks for fellow boids
float maxSpeed = 1; //maximum magnitude for the velocity vector
float maxSteerForce = .05; //maximum magnitude of the steering vector
float sMod, aMod, cMod; //modifiers for the three forces on the boid
float h; //hue
Boid(PVector inPos) {
pos = new PVector();
pos.set(inPos);
vel = new PVector(random(-1, 1), random(-1, 1));
acc = new PVector(0, 0);
neighborhoodRadius = 20;
sMod = 1;
aMod = 1;
cMod = 4;
}
Boid(PVector inPos, PVector inVel, float r) {
pos = new PVector();
pos.set(inPos);
vel = new PVector();
vel.set(inVel);
acc = new PVector(0, 0);
neighborhoodRadius = r;
}
void run(ArrayList bl) {
for (int i =0; i < 10; i++) {
acc.add(attract(new PVector(width/2, height/2), true));
acc.add(avoid(new PVector(xposs[i], yposs[i]), true));
if (i == 10) i = 0;
}
if (pos.x>width-10)acc.add(bounce(new PVector(width, pos.y), true));
if (pos.x<10) acc.add(bounce(new PVector(0, pos.y), true));
if (pos.y>height-10) acc.add(bounce(new PVector(pos.x, height), true));
if (pos.y<10) acc.add(bounce(new PVector(pos.x, 0), true));
ali = alignment(bl);
coh = cohesion(bl);
sep = seperation(bl);
for (int i =0; i < 10; i++) {
if (PVector.dist(new PVector(xposs[i], yposs[i]), pos)>180) {
acc.add(PVector.mult(ali, aMod));
acc.add(PVector.mult(coh, cMod));
acc.add(PVector.mult(sep, sMod));
}
if (PVector.dist(new PVector(xposs[i], yposs[i]), pos)<80) maxSpeed = 1000;
if (i == 10) i = 0;
}
if (PVector.dist(new PVector(width, height), pos)<60) maxSpeed = 1000;
if (PVector.dist(new PVector(0, 0), pos)<50) {
maxSpeed = 1000;
} else {
maxSpeed = 1;
}
move();
checkBounds();
render();
}
void move() {
vel.add(acc); //add acceleration to velocity
vel.limit(maxSpeed); //make sure the velocity vector magnitude does not exceed maxSpeed
pos.add(vel); //add velocity to position
acc.mult(0); //reset acceleration
}
void checkBounds() {
}
void render() {
pushMatrix();
translate(pos.x, pos.y);
rotate(atan2(vel.y, vel.x)); //rotate drawing matrix to direction of velocity
stroke(0);
noFill();
ellipse(0, 0, neighborhoodRadius/2, neighborhoodRadius/2);
noStroke();
fill(h);
//draw triangle
beginShape(TRIANGLES);
rect(0, 0, 6, 2);
endShape();
popMatrix();
}
//steering. If arrival==true, the boid slows to meet the target. Credit to Craig Reynolds
PVector steer(PVector target, boolean arrival) {
PVector steer = new PVector(); //creates vector for steering
if (!arrival) {
steer.set(PVector.sub(target, pos)); //steering vector points towards target (switch target and pos for avoiding)
steer.limit(maxSteerForce); //limits the steering force to maxSteerForce
} else {
PVector targetOffset = PVector.sub(target, pos);
float distance=targetOffset.mag();
float rampedSpeed = maxSpeed*(distance/100);
float clippedSpeed = min(rampedSpeed, maxSpeed);
PVector desiredVelocity = PVector.mult(targetOffset, (clippedSpeed/distance));
steer.set(PVector.sub(desiredVelocity, vel));
}
return steer;
}
//avoid. If weight == true avoidance vector is larger the closer the boid is to the target
PVector avoid(PVector target, boolean weight) {
PVector steer = new PVector(); //creates vector for steering
steer.set(PVector.sub(pos, target)); //steering vector points away from target
if (weight) steer.mult(1/sq(PVector.dist(pos, target)));
//steer.limit(maxSteerForce); //limits the steering force to maxSteerForce
return steer;
}
PVector attract(PVector target, boolean weight) {
PVector steer = new PVector(); //creates vector for steering
steer.set(PVector.sub(target, pos)); //steering vector points away from target
if (weight) steer.mult(1/sq(PVector.dist(target, pos)));
//steer.limit(maxSteerForce); //limits the steering force to maxSteerForce
return steer;
}
PVector bounce(PVector target, boolean weight) {
PVector steer = new PVector(); //creates vector for steering
steer.set(PVector.sub(pos, target)); //steering vector points away from target
if (weight) steer.mult(1/sq(PVector.dist(pos, target)));
//steer.limit(maxSteerForce); //limits the steering force to maxSteerForce
return steer;
}
PVector seperation(ArrayList boids) {
PVector posSum = new PVector(0, 0);
PVector repulse;
for (int i=0; i<boids.size (); i++) {
Boid b = (Boid)boids.get(i);
float d = PVector.dist(pos, b.pos);
if (d>0&&d<=neighborhoodRadius) {
repulse = PVector.sub(pos, b.pos);
repulse.normalize();
repulse.div(d);
posSum.add(repulse);
}
}
return posSum;
}
PVector alignment(ArrayList boids) {
PVector velSum = new PVector(0, 0);
int count = 0;
for (int i=0; i<boids.size (); i++) {
Boid b = (Boid)boids.get(i);
float d = PVector.dist(pos, b.pos);
if (d>0&&d<=neighborhoodRadius) {
velSum.add(b.vel);
count++;
}
}
if (count>0) {
velSum.div((float)count);
velSum.limit(maxSteerForce);
}
return velSum;
}
PVector cohesion(ArrayList boids) {
PVector posSum = new PVector(0, 0);
PVector steer = new PVector(0, 0);
int count = 0;
for (int i=0; i<boids.size (); i++) {
Boid b = (Boid)boids.get(i);
float d = dist(pos.x, pos.y, b.pos.x, b.pos.y);
if (d>0&&d<=neighborhoodRadius) {
posSum.add(b.pos);
count++;
}
}
if (count>0) posSum.div((float)count);
steer = PVector.sub(posSum, pos);
steer.limit(maxSteerForce);
return steer;
}
}
class BoidList {
ArrayList boids; //will hold the boids in this BoidList
float h; //for color
BoidList(int n, float ih, int xstart, int ystart) {
boids = new ArrayList();
h = ih;
for (int i=0; i<n; i++) {
boids.add(new Boid(new PVector(xstart, ystart)));
}
}
void run() {
for (int i=0; i<boids.size (); i++) {
Boid tempBoid = (Boid)boids.get(i); //create a temporary boid to process and make it the current boid in the list
tempBoid.h = h;
tempBoid.run(boids); //tell the temporary boid to execute its run method
}
}
}