Tutorials | (back to the list of tutorials) |
The first code below has the swarm agent class MyBoid inheriting IBoid class. This adds a behavior to stay in the range from 0.0 to 1.0 in X and Y. In the update() method the position of the agent is checked and if it's out of the range, it adds or subtracts 1.0 to X or Y to jump to the other end of the range. To avoid drawing a line from one end to the other end, boolean variable jump is defined to check if it's jumping and if so it doesn't create a line. In setup() method, IG.top() method turns iGeo to show only top view instead of 4 views and IG.focus() method adjusts the view to zoom into the existing geometries.
import igeo.*; import processing.opengl.*; void setup() { size(480, 360, IG.GL); IG.duration(800); for(int i=0; i < 200; i++){ new MyBoid(IRand.pt(1,1,0), IRand.pt(-0.01,-0.01,0,0.01,0.01,0)); } IG.top(); //only showing the top view IG.focus(); //focusing into existing geometries } class MyBoid extends IBoid { IVec prevPos; MyBoid(IVec pos, IVec vel) { super(pos, vel); cohesionDist(0.03); cohesionRatio(1); separationDist(0.04); separationRatio(2); alignmentDist(0.03); alignmentRatio(0); } void update() { boolean jump=false; if (pos().x() < 0.0 ) { pos().add(1, 0, 0); jump=true; } else if (pos().x() > 1.0) { pos().sub(1, 0, 0); jump=true; } if (pos().y() < 0.0 ) { pos().add(0, 1, 0); jump=true; } else if (pos().y() > 1.0) { pos().sub(0, 1, 0); jump=true; } IVec curPos = pos().cp(); if(prevPos!=null && !jump){ new ICurve(prevPos, curPos).clr(0); } prevPos = curPos; } }
This second code keeps movements of the swarm agents same but
drawing lines in different locations.
Whereas the previous code draws lines on the trace of the movement,
this code draws lines between two agents when two agents
are closer than a certain distance.
These two lines calculates a distance between two agents and
limit the condition when the distance is smaller than 0.08
(note that the whole range is from 0.0 to 1.0).
       
double dist = pos().dist( b.pos() );
           
if ( dist < 0.08 ) {
Another if-condition of
if ( IG.time()%15==0 ) {
is added to control the density of lines.
import igeo.*; import processing.opengl.*; void setup() { size(480, 360, IG.GL); IG.duration(800); for(int i=0; i < 200; i++){ new MyBoid(IRand.pt(1,1,0), IRand.pt(-0.01,-0.01,0,0.01,0.01,0)); } IG.top(); //only showing the top view IG.focus(); //focusing into existing geometries } class MyBoid extends IBoid { MyBoid(IVec pos, IVec vel) { super(pos, vel); cohesionDist(0.03); cohesionRatio(1); separationDist(0.04); separationRatio(2); alignmentDist(0.03); alignmentRatio(0); } void interact(ArrayList < IDynamics > agents){ super.interact(agents); for(int i=0; i < agents.size() && agents.get(i)!=this; i++){ if(agents.get(i) instanceof MyBoid){ MyBoid b = (MyBoid)agents.get(i); double dist = pos().dist(b.pos()); if ( dist < 0.08 ) { if ( IG.time()%15==0 ) { new ICurve(pos().cp(), b.pos().cp()).clr(0); } } } } } void update() { if (pos().x() < 0.0 ) { pos().add(1, 0, 0); } else if (pos().x() > 1.0) { pos().sub(1, 0, 0); } if (pos().y() < 0.0 ) { pos().add(0, 1, 0); } else if (pos().y() > 1.0) { pos().sub(0, 1, 0); } } }
The next code only changes the color of line drawing.
The background color is changed by the method IG.bg(0)
to black.
When you put one number into this method ( IG.bg(double) )
it's gray scale color and when you put three numbers
(IG.bg(double,double,double) ) it's RGB color.
The color of the lines is changed to transparent white color at this line
by setting the alpha value of the color to 0.2.
       
new ICurve(pos().cp(), b.pos().cp()).clr(1.0,0.2); //transparent white
The points of agents are also hidden by the agent's method hide().
       
if ( time()==0 ) { hide(); } //hiding a point of boid
import igeo.*; import processing.opengl.*; void setup() { size(480, 360, IG.GL); IG.duration(800); for(int i=0; i < 200; i++){ new MyBoid(IRand.pt(1,1,0), IRand.pt(-0.01,-0.01,0,0.01,0.01,0)); } IG.bg(0); //black background IG.top(); //only showing the top view IG.focus(); //focusing into existing geometries } class MyBoid extends IBoid { MyBoid(IVec pos, IVec vel) { super(pos, vel); cohesionDist(0.03); cohesionRatio(1); separationDist(0.04); separationRatio(2); alignmentDist(0.03); alignmentRatio(0); } void interact(ArrayList < IDynamics > agents){ super.interact(agents); for(int i=0; i < agents.size() && agents.get(i)!=this; i++){ if(agents.get(i) instanceof MyBoid){ MyBoid b = (MyBoid)agents.get(i); double dist = pos().dist(b.pos()); if ( dist < 0.08 ) { if ( IG.time()%15==0 ) { new ICurve(pos().cp(), b.pos().cp()).clr(1.0,0.2); //transparent white } } } } } void update() { if ( time()==0 ) { hide(); } //hiding a point of boid if (pos().x() < 0.0 ) { pos().add(1, 0, 0); } else if (pos().x() > 1.0) { pos().sub(1, 0, 0); } if (pos().y() < 0.0 ) { pos().add(0, 1, 0); } else if (pos().y() > 1.0) { pos().sub(0, 1, 0); } } }
The code below maps the swarm agents onto a surface.
It reads an input Rhino file and
takes one surface out to put it into an agent of MyBoidOnSurface class.
MyBoidOnSurface class contains two data fields.
       
ISurface surface;
       
IVec surfPt;
With those fields, the agent keeps the information of a surface to map onto
and mapped vector location on the surface.
The original position information on the agent pos()
is used as U-V coordinates.
Although the original position is interpreted as U-V coordinates,
the actual point of the agent still exists in X-Y-Z coordinates.
To hide this point, the method hide() is called inside the
constructor. If you don't hide the point, it floats somewhere on X-Y plane
within (0.0, 0.0) - (1.0, 1.0).
This agent's original position pos() is then mapped onto the position
on the surface by this line inside the constructor and also inside
update() method to keep the field surfPt updated.
       
surfPt = surface.pt(pos);
Then this surfPt is used to
measure the distance and to
create a line in 3D X-Y-Z coordinates.
The input Rhino file used in the example is this one below.
import igeo.*; import processing.opengl.*; void setup() { size(480, 360, IG.GL); IG.duration(800); IG.open("surface13.3dm"); ISurface surf = IG.surface(0); for(int i=0; i < 300; i++){ new MyBoidOnSurface(surf, IRand.pt(1,1,0), IRand.pt(-0.01,-0.01,0,0.01,0.01,0)); } surf.del(); } class MyBoidOnSurface extends IBoid { ISurface surface; IVec surfPt; MyBoidOnSurface(ISurface srf, IVec pos, IVec vel) { super(pos, vel); surface = srf; surfPt = surface.pt(pos); hide(); //hiding a point of boid cohesionDist(0.03); cohesionRatio(1); separationDist(0.04); separationRatio(2); alignmentDist(0.03); alignmentRatio(0); } void interact(ArrayList < IDynamics > agents){ super.interact(agents); for(int i=0; i < agents.size() && agents.get(i)!=this; i++){ if(agents.get(i) instanceof MyBoidOnSurface){ MyBoidOnSurface b = (MyBoidOnSurface)agents.get(i); double dist = surfPt.dist(b.surfPt); if ( dist < 5.0 ) { if ( IG.time()%15==0 ){ new ICurve(surfPt.cp(), b.surfPt.cp()).clr(0); } } } } } void update() { if ( pos().x() < 0.0 ) { pos().add(1, 0, 0); } else if ( pos().x() > 1.0 ) { pos().sub(1, 0, 0); } if ( pos().y() < 0.0 ){ pos().add(0, 1, 0); } else if ( pos().y() > 1.0 ) { pos().sub(0, 1, 0); } surfPt = surface.pt(pos()); //update surface point } }
import igeo.*; import processing.opengl.*; void setup() { size(480, 360, IG.GL); IG.duration(800); IG.open("surface13.3dm"); ISurface surf = IG.surface(0); for(int i=0; i < 300; i++){ new MyBoidOnSurface(surf, IRand.pt(1,1,0), IRand.pt(-0.01,-0.01,0,0.01,0.01,0)); } surf.del(); } class MyBoidOnSurface extends IBoid { ISurface surface; IVec surfPt; MyBoidOnSurface(ISurface srf, IVec pos, IVec vel) { super(pos, vel); surface=srf; surfPt = surface.pt(pos); hide(); //hiding a point of boid cohesionDist(0.03); cohesionRatio(1); separationDist(0.04); separationRatio(2); alignmentDist(0.03); alignmentRatio(0); } void interact(ArrayList < IDynamics > agents){ super.interact(agents); for(int i=0; i < agents.size() && agents.get(i) != this; i++){ if ( agents.get(i) instanceof MyBoidOnSurface ) { MyBoidOnSurface b = (MyBoidOnSurface)agents.get(i); double dist = surfPt.dist(b.surfPt); if ( dist < 5.0 && dist > 2.0 ) { if ( IG.time()%15==0 ) { //controlling depth double depth = sin(IG.time()*0.01)*1.5; IVec pt1 = surface.pt(pos().x, pos().y, depth); IVec pt2 = b.surface.pt(b.pos().x, b.pos().y, depth); double gray = sin(IG.time()*0.01)*0.5+0.5; IG.meshSquareStick(pt1,pt2,0.4).clr(gray); } } } } } void update() { if ( pos().x() < 0.0 ) { pos().add(1, 0, 0); } else if ( pos().x() > 1.0 ) { pos().sub(1, 0, 0); } if ( pos().y() < 0.0 ){ pos().add(0, 1, 0); } else if ( pos().y() > 1.0 ) { pos().sub(0, 1, 0); } surfPt = surface.pt(pos()); //update surface point } }