We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hey there, I'm working with some code in which ellipses are drawn onto the screen simulating leaf/root structure. I'm looking to add some rule which reduces the size of the ellipses when they 'branch off' from the main (original) branches, so each new branch has a proportionally smaller radius than the one in which it came from.
The term in the code I'd need to write the rule for is '_veinNodeRadius'. I'm pretty sure that the rule would have to take place in the 'void placeVeinNode' section too but I'm not 100%.
Would appreciate if someone was able to offer some advice of how I'd go about doing this.
Thanks,
Ross
PAGE 1
VenationAlgorithm va;
VenationPlotter vp;
void setup() {
size(1000,500);
background(30);
scale(0.2);
va = new VenationAlgorithm();
vp = new VenationPlotter(va, this.g, width);
reset();
redraw();
}
void draw() {
scale(0.2);
}
void reset() {
va = new VenationAlgorithm();
vp = new VenationPlotter(va, this.g, width);
}
void redraw() {
background(30);
vp.draw();
}
void keyReleased() {
switch (key) {
case 'r':
reset();
redraw();
break;
case ' ':
va.step();
redraw();
break;
}
}
PAGE 2
class VenationAlgorithm {
ArrayList<PVector> _auxins;
float _auxinRadius;
ArrayList<PVector> _veinNodes;
float _veinNodeRadius;
float _killRadius;
float _neighborhoodRadius;
VenationAlgorithm() {
_auxins = new ArrayList<PVector>();
_auxinRadius = 0.025;
_veinNodes = new ArrayList<PVector>();
_veinNodeRadius = 0.008;
_killRadius = 0.055;
_neighborhoodRadius = 0.1;
seedVeinNodes();
seedAuxins();
}
float getAuxinRadius() {
return _auxinRadius;
}
float getVeinNodeRadius() {
return _veinNodeRadius;
}
float getKillRadius() {
return _killRadius;
}
ArrayList<PVector> getAuxins() {
return _auxins;
}
int numAuxins() {
return _auxins.size();
}
ArrayList<PVector> getVeinNodes() {
return _veinNodes;
}
int numVeinNodes() {
return _veinNodes.size();
}
PVector getVeinNode(int veinNodeIndex) {
return _veinNodes.get(veinNodeIndex);
}
ArrayList<PVector> getNeighborAuxins(int veinNodeIndex) {
ArrayList<Integer> neighborAuxinIndices = getNeighborAuxinIndices(veinNodeIndex);
ArrayList<PVector> neighborAuxins = new ArrayList<PVector>();
for (int i : neighborAuxinIndices) {
neighborAuxins.add(_auxins.get(i));
}
return neighborAuxins;
}
ArrayList<PVector> getInfluencerAuxins(int veinNodeIndex) {
ArrayList<Integer> influencerAuxinIndices = getInfluencerAuxinIndices(veinNodeIndex);
ArrayList<PVector> influencerAuxins = new ArrayList<PVector>();
for (int i : influencerAuxinIndices) {
influencerAuxins.add(_auxins.get(i));
}
return influencerAuxins;
}
PVector getAuxinInfluenceDirection(PVector veinNode, ArrayList<PVector> auxinInfluencers) {
PVector result = null;
for (PVector p : auxinInfluencers) {
p = p.get();
p.sub(veinNode);
p.normalize();
if (result == null) {
result = new PVector();
}
result.add(p);
}
if (result != null) {
result.normalize();
}
return result;
}
private ArrayList<Integer> getNeighborAuxinIndices(int veinNodeIndex) {
float dx, dy, r = 4.0 * _neighborhoodRadius * _neighborhoodRadius;
PVector p, veinNode = _veinNodes.get(veinNodeIndex);
ArrayList<Integer> neighborAuxinIndices = new ArrayList<Integer>();
for (int i = 0; i < _auxins.size(); i++) {
p = _auxins.get(i);
dx = p.x - veinNode.x;
dy = p.y - veinNode.y;
if ((dx * dx) + (dy * dy) < r) {
neighborAuxinIndices.add(i);
}
}
return neighborAuxinIndices;
}
private ArrayList<Integer> getInfluencerAuxinIndices(int veinNodeIndex) {
ArrayList<Integer> neighborAuxinIndices = getNeighborAuxinIndices(veinNodeIndex);
ArrayList<Integer> influencerAuxinIndices = new ArrayList<Integer>();
for (int auxinIndex : neighborAuxinIndices) {
if (veinNodeIndex == getInfluencedVeinNodeIndex(auxinIndex)) {
influencerAuxinIndices.add(auxinIndex);
}
}
return influencerAuxinIndices;
}
int getInfluencedVeinNodeIndex(int auxinIndex){
PVector auxin = _auxins.get(auxinIndex);
return getNearestVeinNodeIndex(auxin.x, auxin.y);
}
int getNearestVeinNodeIndex(float x, float y) {
int candidateIndex = -1;
PVector p;
float dx, dy, distSq, candidateDistSq = 0;
for (int i = 0; i < _veinNodes.size(); i++) {
p = _veinNodes.get(i);
dx = p.x - x;
dy = p.y - y;
distSq = dx * dx + dy * dy;
if (candidateIndex < 0 || distSq < candidateDistSq) {
candidateIndex = i;
candidateDistSq = distSq;
}
}
return candidateIndex;
}
void step() {
placeVeinNodes();
killAuxins();
}
void seedVeinNodes() {
float x, y;
for (int i = 0; i < 3; i++) {
x = random(1);
y = random(1);
_veinNodes.add(new PVector(x, y));
}
}
void seedAuxins() {
float x, y;
for (int i = 0; i < 5000 && _auxins.size() < 2000; i++) {
x = random(5);
y = random(5);
if (!hitTestPotentialAuxin(x, y)) {
_auxins.add(new PVector(x, y));
}
}
}
void placeVeinNodes(){
int count = _veinNodes.size();
for (int i = 0; i < count; i++) {
placeVeinNode(i);
}
}
void placeVeinNode(int seedVeinNodeIndex) {
PVector veinNode = _veinNodes.get(seedVeinNodeIndex);
ArrayList<PVector> influencerAuxins = getInfluencerAuxins(seedVeinNodeIndex);
PVector p = getAuxinInfluenceDirection(veinNode, influencerAuxins);
if (p != null) {
if (p.mag() <= 0) {
p.x = 1;
p.y = 0;
p.rotate(random(1) * 2 * PI);
}
p.mult(2 * _veinNodeRadius);
p.add(veinNode);
_veinNodes.add(p);
}
}
void killAuxins() {
PVector p;
for (int i = 0; i < _auxins.size(); i++) {
p = _auxins.get(i);
if (hitTestExistingAuxin(p.x, p.y)) {
_auxins.remove(i);
i--;
}
}
}
private boolean hitTestExistingAuxin(float x, float y){
float dx, dy, r;
r = _killRadius * _killRadius;
for (PVector p : _veinNodes) {
dx = p.x - x;
dy = p.y - y;
if ((dx * dx) + (dy * dy) < r) {
return true;
}
}
return false;
}
private boolean hitTestPotentialAuxin(float x, float y) {
float dx, dy, r;
r = 4.0 * _auxinRadius * _auxinRadius;
for (PVector p : _auxins) {
dx = p.x - x;
dy = p.y - y;
if ((dx * dx) + (dy * dy) < r) {
return true;
}
}
r = _killRadius * _killRadius;
for (PVector p : _veinNodes) {
dx = p.x - x;
dy = p.y - y;
if ((dx * dx) + (dy * dy) < r) {
return true;
}
}
return false;
}
}
PAGE 3
class VenationPlotter {
VenationAlgorithm _va;
PGraphics _g;
int _size;
VenationPlotter(VenationAlgorithm va, PGraphics g, int size) {
_va = va;
_g = g;
_size = size;
}
void draw() {
drawVeinNodes();
}
void drawVeinNodes() {
float r = _va.getVeinNodeRadius() * _size;
_g.fill(220);
ArrayList<PVector> veinNodes = _va.getVeinNodes();
for (PVector p : veinNodes) {
_g.ellipse(_size * p.x, _size * p.y, 2*r, 2*r);
}
}
}