Tutorials | (back to the list of tutorials) |
1![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60);
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 60;
int vdiv = 30;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 5;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; //1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
double ratio = shiftRatio();
IVec p1 = pt(0, 0);
IVec p2 = pt(ratio, 0);
IVec p3 = pt(ratio, 1);
IVec p4 = pt(0, 1);
ISurface rect = new ISurface(p1,p2,p3,p4);
addGeom(rect);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
2![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 60;
int vdiv = 30;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 5;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; //1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
double ratio = shiftRatio();
IVec p1 = pt(0, 0);
IVec p2 = pt(ratio, 0);
IVec p3 = pt(ratio, 1-ratio);
IVec p4 = pt(0, 1-ratio);
ISurface rect = new ISurface(p1,p2,p3,p4);
addGeom(rect);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
3![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 20;
int vdiv = 30;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 5;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; //1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
double ratio = shiftRatio();
IVec p1 = pt(0, 0);
IVec p2 = pt(1, 0);
IVec p3 = pt(1, 1);
IVec p4 = pt(0, 1);
IVec axis = uvec();
p1.rot(p3, axis, ratio * -PI/2);
p2.rot(p3, axis, ratio * -PI/2);
ISurface rect = new ISurface(p1,p2,p3,p4);
rect.clr(0, 0, ratio);
addGeom(rect);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
4![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
//IG.open("srf1.3dm");
//ISurface s = IG.surface(0);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 20;
int vdiv = 30;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 5;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; //1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
double ratio = shiftRatio();
IVec p1 = pt(0, 0);
IVec p2 = pt(1, 0);
IVec p3 = pt(1, 1);
IVec p4 = pt(0, 1);
IVec axis = uvec();
p1.rot(p3, axis, ratio * -PI/2);
p2.rot(p3, axis, ratio * -PI/2);
ISurface rect = new ISurface(p1,p2,p3,p4);
rect.clr(0, 0, ratio);
addGeom(rect);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
5![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 20;
int vdiv = 30;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 5;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; // 1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
double ratio = shiftRatio();
IVec[][] pts = new IVec[4][2];
pts[0][0] = pt(0, 0);
pts[0][1] = pt(0, 1);
pts[1][0] = pt(1.0/3, 0);
pts[1][1] = pt(1.0/3, 1);
pts[2][0] = pt(2.0/3, 0);
pts[2][1] = pt(2.0/3, 1);
pts[3][0] = pt(1, 0);
pts[3][1] = pt(1, 1);
IVec axis = uvec();
// rotating around the center pts[1][2] and the axis rotAxis
pts[2][0].rot(pts[0][1], axis, ratio * -PI/2);
// rotating around the center pts[1][3] and the axis rotAxis
pts[3][0].rot(pts[0][1], axis, ratio * -PI/2);
ISurface rect = new ISurface(pts, 3, 1);
rect.clr(0, ratio*0.5 + 0.5, 0);
addGeom(rect);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry > ();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
6![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60);
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 40;
int vdiv = 20;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 5;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec p1 = pt(0, 0);
IVec p2 = pt(1, 0);
IVec p3 = pt(1, 1);
IVec p4 = pt(0, 1);
shiftScale(0.1);
double ratio = shiftRatio()*0.9 + 0.1; // 0 - 1 + 0.1
IVec center = center();
IVec[] pts = new IVec[]{ p1, p2, p3, p4 };
ICurve rect = new ICurve(pts, true);
ICurve rect2 = rect.cp();
rect2.scale(center, ratio);
ISurface srf = IG.loft(rect2, rect);
addGeom(srf);
rect.del();
rect2.del();
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r>1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot>ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot>vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot>maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
7![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
//IG.open("srf1.3dm");
//ISurface s = IG.surface(0);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60);
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 40;
int vdiv = 20;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 10;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; // 1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec center = pt(0.5, 0.5);
IVec shift = shift();
ICurve line = new ICurve(center, center.cp().add(shift));
line.clr(1.0,0,0);
panelGeom.add(line);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r>1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot>ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot>vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){ return nshift(-1,-1); }
IVec nshift(double maxLen){ return nshift(maxLen,-1); }
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot>maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot>0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot>0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
8![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 40;
int vdiv = 20;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 10;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; // 1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec p1 = pt(0,0);
IVec p2 = pt(1,0);
IVec p3 = pt(1,1);
IVec p4 = pt(0,1);
double u = uratio();
double v = vratio();
double n = nratio();
IVec center = pt(0.5 + u, 0.5 + v, n);
ISurface s1 = new ISurface(p1,p2,center).clr(u+0.5, v+0.5, n);
ISurface s2 = new ISurface(p2,p3,center).clr(u+0.5, v+0.5, n);
ISurface s3 = new ISurface(p3,p4,center).clr(u+0.5, v+0.5, n);
ISurface s4 = new ISurface(p4,p1,center).clr(u+0.5, v+0.5, n);
panelGeom.add(s1);
panelGeom.add(s2);
panelGeom.add(s3);
panelGeom.add(s4);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){ return nshift(-1,-1); }
IVec nshift(double maxLen){ return nshift(maxLen,-1); }
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
9![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60);
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 40;
int vdiv = 20;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 10;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; // 1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
double u = uratio();
double v = vratio();
if(Math.abs(u) > 0.01 && Math.abs(v) > 0.01){
IVec p1 = pt(0.5 + u, 0.5 - v);
IVec p2 = pt(0.5 + u, 0.5 + v);
IVec p3 = pt(0.5 - u, 0.5 + v);
IVec p4 = pt(0.5 - u, 0.5);
IVec p5 = pt(0.5, 0.5);
IVec p6 = pt(0.5, 0.5 - v);
ICurve outline = new ICurve(new IVec[]{ p1,p2,p3,p4,p5,p6 }, true);
panelGeom.add(new ISurface(outline));
outline.del();
}
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot<-ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){ return nshift(-1,-1); }
IVec nshift(double maxLen){ return nshift(maxLen,-1); }
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i<0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
10![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60);
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 40;
int vdiv = 20;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
//nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int j=0; j < vdiv; j++){
if(j%2==0){
for(int i=0; i < udiv-1; i+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+2][j], nodes[i+2][j+1], nodes[i][j+1] });
}
}
else{
for(int i=1; i < udiv-1; i+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+2][j], nodes[i+2][j+1], nodes[i][j+1] });
}
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 10;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; // 1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec p1 = pt(0,0);
IVec p2 = pt(1,0);
IVec p3 = pt(1,1);
IVec p4 = pt(0,1);
double u = uratio();
if(u==0){
panelGeom.add(new ISurface(p1,p2,p3,p4));
}
else if(u>0){
IVec q1 = pt(0.5, 0.6, -2);
IVec q2 = pt(0.5+u, 0.6, -2);
IVec q3 = pt(0.5+u, 0.8, -2);
IVec q4 = pt(0.5, 0.8, -2);
ICurve rect1 = new ICurve(new IVec[]{ p1,p2,p3,p4 }, true);
ICurve rect2 = new ICurve(new IVec[]{ q1,q2,q3,q4 }, true);
ISurface srf = IG.loft(rect2,rect1).clr(u+0.5,0.5,0.5);
rect1.del();
rect2.del();
addGeom(srf);
}
else{ // u<0
IVec q1 = pt(0.5+u, 0.6, -2);
IVec q2 = pt(0.5, 0.6, -2);
IVec q3 = pt(0.5, 0.8, -2);
IVec q4 = pt(0.5+u, 0.8, -2);
ICurve rect1 = new ICurve(new IVec[]{ p1,p2,p3,p4 }, true);
ICurve rect2 = new ICurve(new IVec[]{ q1,q2,q3,q4 }, true);
ISurface srf = IG.loft(rect2,rect1).clr(0.5,0.5,-u+0.5);
rect1.del();
rect2.del();
addGeom(srf);
}
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r>1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot>ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot>vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){ return nshift(-1,-1); }
IVec nshift(double maxLen){ return nshift(maxLen,-1); }
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot>maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot>0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
11![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
IG.open("srf3.3dm");
ISurface s = IG.surface(0);
//ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 80;
int vdiv = 16;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
if(i%2==0){
for(int j=0; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+2], nodes[i][j+2] });
}
}
else{
for(int j=1; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+2], nodes[i][j+2] });
}
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 20;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; //1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec p1 = pt(0,0);
IVec p2 = pt(1,0);
IVec p3 = pt(1,1);
IVec p4 = pt(0,1);
double u = uratio();
double v = vratio();
double n = nratio();
if(n < 0.5) n = 0.5;
panelGeom.add(new ISurface(p1,p2,p3,p4).clr(0.5,1,1,0.5));
IVec[][] pts = new IVec[3][2];
pts[0][1] = pt(0,0);
pts[0][0] = pt(1,0);
pts[1][1] = pt(0.4 + u, 0.5 + v, n);
pts[1][0] = pt(0.6 + u, 0.5 + v, n);
pts[2][1] = pt(0.5,1);
pts[2][0] = pt(1, 1);
panelGeom.add(new ISurface(pts));
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r>1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot>ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot>vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot>maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot>0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
12![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
IG.open("srf2.3dm");
ISurface s = IG.surface(0);
//ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 60;
int vdiv = 24;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
//nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
if(i%2==0){
for(int j=0; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+2], nodes[i][j+2] });
}
}
else{
for(int j=1; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+2], nodes[i][j+2] });
}
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 20;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; //1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec p1 = pt(0,0);
IVec p2 = pt(1,0);
IVec p3 = pt(1,1);
IVec p4 = pt(0,1);
double u = uratio();
double v = vratio();
double n = nratio() * 2;
addGeom(new ISurface(p1,p2,p3,p4).clr(0.5,1,1,0.5));
if(n < 1) n = 1;
IVec p5 = pt(0.5+u, 0.5+v, n);
ISurface srf1 = new ISurface(p1,p5,p4).hsb(u*0.2, 1-v, 1.0);
ISurface srf2 = new ISurface(p3,p4,p5).hsb(u*0.2, 1-v, 1.0);
addGeom(srf1);
addGeom(srf2);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r>1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot>ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot>vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot>maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot>0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot>0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
13![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
IG.open("srf2.3dm");
ISurface s = IG.surface(0);
//ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 30;
int vdiv = 24;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[(i+3)%udiv][j+1], nodes[(i+2)%udiv][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 20;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; //1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec p1 = pt(0,0);
IVec p2 = pt(0,1);
double u = uratio();
IVec axis = vvec();
IVec widthVec = axis.cross(nml());
widthVec.unit();
widthVec.mul(widthVec.dot(uvec()));
widthVec.rot(axis, -(-u+0.5)*PI);
ISurface srf = new ISurface(p1,p1.cp().add(widthVec),p2.cp().add(widthVec),p2);
srf.hsb(u, u, 1);
addGeom(srf);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
14![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
//IG.open("srf2.3dm");
//ISurface s = IG.surface(0);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 70;
int vdiv = 20;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
//nodes[i][j].fixU();
//nodes[i][j].fixV();
}
}
for(int i=0; i < udiv-2; i++){
for(int j=0; j < vdiv; j++){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[(i+2)%udiv][j+1], nodes[(i+1)%udiv][j+1] });
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 5;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; //1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec p1 = pt(0,0);
IVec p2 = pt(0,1);
double u = uratio();
IVec axis = vvec();
IVec widthVec = axis.cross(nml());
widthVec.unit();
widthVec.mul(widthVec.dot(uvec()) * 0.5);
widthVec.rot(axis, -(-u+0.5)*PI);
addGeom(new ISurface(p1,p1.cp().add(widthVec),p2.cp().add(widthVec),p2));
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
15![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
//IG.open("srf1.3dm");
//ISurface s = IG.surface(0);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 30;
int vdiv = 40;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
nodes[i][j] = new PanelNode(s, i*uinc, j*vinc );
nodes[i][j].fixU();
//nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
if(i%2==0){
for(int j=0; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+2], nodes[i][j+2] });
}
}
else{
for(int j=1; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+2], nodes[i][j+2] });
}
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 10;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; //1.0;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
double v = vratio() * 1.5;
double n = nratio();
if(n < 0) n=0;
IVec p1 = pt(0, 0.15);
IVec p2 = pt(1, 0.35 + v);
IVec p3 = pt(1, 0.65 + v);
IVec p4 = pt(0, 0.85);
IVec p5 = pt(1, 0.5 + v, n);
ISurface srf1 = new ISurface(p1,p2,p5);
ISurface srf2 = new ISurface(p1,p5,p4);
ISurface srf3 = new ISurface(p4,p5,p3);
srf1.clr(v*0.25+0.5);
srf2.clr(v*0.25+0.5);
srf3.clr(v*0.25+0.5);
addGeom(srf1);
addGeom(srf2);
addGeom(srf3);
}
IVec pt(double u, double v){
IVec upt1 = nodes[0].pos().sum(nodes[1], u);
IVec upt2 = nodes[3].pos().sum(nodes[2], u);
return upt1.sum(upt2, v);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[1].pos().mid(nodes[2]).dif(nodes[0].pos().mid(nodes[3]));
}
IVec vvec(){
return nodes[2].pos().mid(nodes[3]).dif(nodes[0].pos().mid(nodes[1]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r>1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot>ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot>vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot>maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot>0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot>0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
16![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
//IG.open("srf1.3dm");
//ISurface s = IG.surface(0);
ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 70;
int vdiv = 20;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
double ushift = ((i+j)%2 - 0.5)*2*0.2;
nodes[i][j] = new PanelNode(s, (i-ushift)*uinc, j*vinc );
//nodes[i][j].fixU();
//nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
if(i%2==0){
for(int j=0; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i+1][j+2], nodes[i][j+2], nodes[i][j+1] });
}
}
else{
for(int j=1; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i+1][j+2], nodes[i][j+2], nodes[i][j+1] });
}
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 10;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1;
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec p1 = node(0);
IVec p2 = node(1);
IVec p3 = node(2);
IVec p4 = node(3);
IVec p5 = node(4);
IVec p6 = node(5);
double u = uratio() * 0.8;
double v = uratio() * 0.8;
double n = nratio() * -2;
double ratio = shiftRatio() * 0.8;
if(n>0) n=0;
IVec center = pt(u + 0.5, v + 0.5);
p1.scale(center, 1 - ratio);
p3.scale(center, 1 - ratio);
p5.scale(center, 1 - ratio);
IVec c2 = pt(u + 0.5, v + 0.5, n );
IVec[][] pts = new IVec[][]{ new IVec[]{ p1,p2,p3,p4,p5,p6 }, new IVec[]{ c2,c2,c2,c2,c2,c2 } };
ISurface srf = new ISurface(pts, false, true);
srf.clr(u+0.5,v+0.5,1.0);
addGeom(srf);
}
IVec pt(double u, double v){
IVec center = center();
IVec uvec = uvec().mul(u-0.5);
IVec vvec = vvec().mul(v-0.5);
return center.add(uvec).add(vvec);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[2].pos().dif(nodes[5]);
}
IVec vvec(){
return nodes[0].pos().mid(nodes[1]).dif(nodes[3].pos().mid(nodes[4]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r>1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
17![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
IConfig.syncDrawAndDynamics = true;
size(480,360,IG.GL);
IG.open("srf1.3dm");
ISurface s = IG.surface(0);
//ISurface s = new ISurface(0,0,0, 200,0,0, 200,0,60, 0,0,60); //
IPoint[] pts = IG.points();
for(int i=0; i < pts.length; i++){
new IAttractor(pts[i], 1).target(Swarm.class).clr(1.0,0,0).gauss(100);
}
new ISurfaceAttractorField(s).target(Swarm.class).intensity(100);
int udiv = 70;
int vdiv = 20;
double uinc = 1./udiv;
double vinc = 1./vdiv;
PanelNode[][] nodes = new PanelNode[udiv+1][vdiv+1];
for(int i=0; i <= udiv; i++){
for(int j=0; j <= vdiv; j++){
double ushift = ((i+j)%2 - 0.5)*2*0.2;
nodes[i][j] = new PanelNode(s, (i-ushift)*uinc, j*vinc );
nodes[i][j].fixU();
nodes[i][j].fixV();
}
}
for(int i=0; i < udiv; i++){
if(i%2==0){
for(int j=0; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i+1][j+2], nodes[i][j+2], nodes[i][j+1] });
}
}
else{
for(int j=1; j < vdiv-1; j+=2){
new PanelAgent(new PanelNode[]{ nodes[i][j], nodes[i+1][j], nodes[i+1][j+1], nodes[i+1][j+2], nodes[i][j+2], nodes[i][j+1] });
}
}
}
// distance threshold for swarm to influence panels
Swarm.panelReachDist = 10;
for(int i=0; i < 50; i++){
new Swarm(s.pt(IRand.pt(0,0,-5,1,1,5)), IRand.dir(10)).clr(1.0);
}
s.del();
IG.pers();
}
class PanelAgent extends IAgent{
PanelNode[] nodes;
IVec pos;
IVec dir;
double dirScale = 0.1; // 1.0
boolean needUpdate;
ArrayList < IGeometry > panelGeom;
PanelAgent(PanelNode[] n){
nodes = n;
dir = new IVec();
needUpdate = true;
}
void makePanel(){
IVec p1 = node(0);
IVec p2 = node(1);
IVec p3 = node(2);
IVec p4 = node(3);
IVec p5 = node(4);
IVec p6 = node(5);
IVec center = center();
ICurve hex1 = new ICurve(new IVec[]{ p1,p2,p3,p4,p5,p6 }, true);
ICurve hex2 = hex1.cp().scale(center, 0.66);
ICurve hex3 = hex1.cp().scale(center, 0.33);
IVec shift = shift();
double max = 2;
if(shift.len() > max) shift.len(max);
hex3.add(shift);
ISurface srf = IG.loft(new ICurve[]{ hex3, hex2, hex1 } );
srf.clr(uratio()*0.5, vratio()*0.5+0.5, 0.5);
addGeom(srf);
hex1.del();
hex2.del();
hex3.del();
}
IVec pt(double u, double v){
IVec center = center();
IVec uvec = uvec().mul(u-0.5);
IVec vvec = vvec().mul(v-0.5);
return center.add(uvec).add(vvec);
}
IVec pt(double u, double v, double n){
return pt(u,v).add(nml().mul(n));
}
void addGeom(IGeometry g){
panelGeom.add(g);
}
void addForce(IVec frc){
needUpdate = true;
dir.add(frc, 0.1);
}
void interact(ArrayList < IDynamics > agents){
pos = center();
for(int i=0;i < agents.size(); i++){
if(agents.get(i) instanceof PanelNode){
PanelNode n = (PanelNode)agents.get(i);
double threshold = 10;
double dist = n.pos().dist(pos);
if(dist < threshold){
n.push(dir.cp().mul((threshold-dist)/threshold*0.1));
}
}
}
}
IVec uvec(){
return nodes[2].pos().dif(nodes[5]);
}
IVec vvec(){
return nodes[0].pos().mid(nodes[1]).dif(nodes[3].pos().mid(nodes[4]));
}
IVec nml(){
return uvec().cross(vvec()).unit();
}
IVec center(){
IVec cnt = nodes[0].pos().cp();
for(int i=1; i < nodes.length; i++){
cnt.add(nodes[i].pos());
}
return cnt.div(nodes.length);
}
double shiftAmount(){
return dir.len()*dirScale;
}
double shiftRatio(){ // returns 0 - 1
double r = shiftAmount();
if(r > 1) r=1;
return r;
}
void shiftScale(double ratio){
dirScale = ratio;
}
IVec shift(){
return dir.cp().mul(dirScale);
}
IVec ushift(){
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/ulen;
if(dot > ulen/2) dot = ulen/2; // half is limit
else if(dot < -ulen/2) dot = -ulen/2;
return uv.mul(dot/ulen);
}
IVec vshift(){
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/vlen;
if(dot > vlen/2) dot = vlen/2; // half is limit
else if(dot < -vlen/2) dot = -vlen/2;
return vv.mul(dot/vlen);
}
IVec nshift(){
return nshift(-1,-1);
}
IVec nshift(double maxLen){
return nshift(maxLen,-1);
}
IVec nshift(double maxLen, double minLen){
IVec n = nml();
double dot = dir.dot(n)*dirScale;
if(maxLen!=-1){
if(dot > maxLen) dot = maxLen;
if(minLen!=-1){
if(dot < minLen) dot = minLen;
}
}
return n.mul(dot);
}
double uratio(){ // returns -0.5 to 0.5
IVec uv = uvec();
double ulen = uv.len();
double dot = dir.dot(uv)*dirScale/(ulen*ulen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double vratio(){ // returns -0.5 to 0.5
IVec vv = vvec();
double vlen = vv.len();
double dot = dir.dot(vv)*dirScale/(vlen*vlen);
if(dot > 0.5) dot = 0.5; // half is limit
else if(dot < -0.5) dot = -0.5;
return dot;
}
double nratio(){ // no limit
return dir.dot(nml())*dirScale;
}
IVec node(int i){
if(i < 0 || i >= nodes.length) return new IVec();
return nodes[i].pos().cp();
}
void update(){
needUpdate = true; // every time
if(needUpdate){
if(panelGeom!=null){
for(int i=0; i < panelGeom.size(); i++){
panelGeom.get(i).del();
}
}
panelGeom = new ArrayList < IGeometry >();
makePanel();
needUpdate = false;
}
}
}
class PanelNode extends IParticleOnSurface{
ISurface surf;
PanelNode(ISurface s, double u, double v){
super(s,u,v);
fric(0.1);
IParticle origPt = new IParticle(s.pt(u,v)).fix();
new ITension(origPt, this).tension(4);
origPt.hide();
hide();
}
}
static class Swarm extends IBoid{
static double panelReachDist = 10;
Swarm(IVec p, IVec v){
super(p,v);
cohesionRatio(10);
cohesionDist(10);
separationRatio(10);
separationDist(10);
alignmentRatio(0);
alignmentDist(0);
}
void interact(ArrayList < IDynamics > agents){
for(int i=0; i < agents.size(); i++){
if(agents.get(i) instanceof PanelAgent){
PanelAgent panel = (PanelAgent)agents.get(i);
double dist = panel.center().dist(pos());
if(dist < panelReachDist){
panel.addForce(vel().cp().mul((panelReachDist-dist)/panelReachDist));
}
}
}
}
}
HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java /
Python)
GALLERY
SOURCE CODE(GitHub)
PRIVACY POLICY
ABOUT/CONTACT