Tutorials | (back to the list of tutorials) |
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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)); } } } } }
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(ArrayListagents){ 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)); } } } } }
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(ArrayListagents){ 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)); } } } } }
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)); } } } } }