class Branch { int startX; int startY; int endX; int endY; int parent; int order; int id; int bifurs = 0; // number of bifurcations at this branch int age = 0; int voltage = 10; int[] children = new int[maxBifurs]; // tracks the children of this branch float angle = -1.0; float len = -1.0; int distance = 0; // distance from soma - NEEDS IMPLEMENTATION, use for setting pBranch or something boolean filo = true; double probB; // probability of branching double probE; // probability of extending double probR; // probability of shrinking //--------------------------------------------------------------------------------- //----- CONSTRUCTORS -------------------------------------------------------------- //--------------------------------------------------------------------------------- // using start/end points... Branch(int sx, int sy, int ex, int ey, int p, int i) { startX = sx; startY = sy; endX = ex; endY = ey; parent = p; order = Bs[p].order+1; id = i; getLength(); getAngle(); getDistance(); } // using start point and angle/length... Branch(int sx, int sy, float a, float l, int p, int i) { startX = sx; startY = sy; //endX = sx; //endY = sy; parent = p; order = Bs[p].order+1; angle = a; len = l; id = i; angleToEndPt(l); getDistance(); } // using start point and angle/length, specifying order (esp for initial branch)... Branch(int sx, int sy, float a, float l, int p, int o, int i) { startX = sx; startY = sy; endX = sx; endY = sy; parent = p; order = o; angle = a; len = l; id = i; angleToEndPt(l); //getDistance(); } //--------------------------------------------------------------------------------- //--------------------------------------------------------------------------------- //------------------------------------------------------------------------------- void drawBranch() { line(startX, startY, endX, endY); // add non-straight branches later } //------------------------------------------------------------------------------- // redraw branch in a more obvious manner void highlight() { stroke(220, 220, 220, 140); ellipse(endX, endY, endField*2, endField*2); line(startX, startY, endX, endY); } //------------------------------------------------------------------------------- void extend() { float newLength = getLength() + random(minExt, maxExt); angleToEndPt(newLength); len = newLength; /* int newEX = int(cos(getAngle()) * newLength); int newEY = int(sin(getAngle()) * newLength); endX = endX + newEX; endY = endY + newEY; */ } //------------------------------------------------------------------------------- void retract() { float newLength = len - random(min(minRetract, len), min(maxRetract, len+1)); if(newLength < delThresh){ killBranch(id); Bs[parent].bifurs = Bs[parent].bifurs-1; if(Bs[parent].bifurs == 0){ Bs[parent].filo = true; } } else{ angleToEndPt(newLength); len = newLength; } } //------------------------------------------------------------------------------- void angleToEndPt() { endX = startX + int(cos(getAngle()) * getLength()); endY = startY + int(sin(getAngle()) * getLength()); } //------------------------------------------------------------------------------- void angleToEndPt(float ln) { endX = startX + int(cos(getAngle()) * ln); endY = startY + int(sin(getAngle()) * ln); } //------------------------------------------------------------------------------- void getDistance(){ distance = int(len + Bs[parent].distance); if(distance > maxDistance){ maxDistance = distance; // not really max, as if a long branch is subsequently eliminated, it's record is not expunged //println("new max distance: " + distance); } } //------------------------------------------------------------------------------- void avoidTest() { loadPixels(); get(); } //------------------------------------------------------------------------------- // Bud new branch off termination of this branch. BTW, is bifurcate a good word if a branch // can split more than once? Branch bifurcate() { //if(bifurs < maxBifurs){ //println("number of branches: " + numBranches); float angleChange = radians(random(minBifurA, maxBifurA)); if(random(2)>1.0){ angleChange = angleChange*-1; } float angle = getAngle(); float newAngle = angle + angleChange; // HERE CAN TEST FOR SIMILARITY TO CURRENT ANGLES // while(!angleSpacingTest(newAngle)){ // } //println("current (" + id + ") angle: " + int(degrees(angle)) + ", change: " + // int(degrees(angleChange)) + ", new (" + numBranches + "): " + int(degrees(newAngle))); float extension = random(minExt, maxExt); int newEX = endX + int(cos(newAngle) * extension); int newEY = endY + int(sin(newAngle) * extension); Branch newB = new Branch(endX, endY, newEX, newEY, id, numBranches); // numBranches is the highest branch id not yet used children[bifurs] = numBranches; bifurs++; numBranches++; filo = false; // once branched, no longer a filopodia (can't extend, but can still branch) return newB; /*} else { println("Branch " + id + " has already reached the " + maxBifurs + " bifurcation limit"); return 0; }*/ } /* boolean angleSpacingTest(float a){ for(int i=0; i children(i).a && a+minBifurA < children(i).a){ return true; } else { return false; } } } */ //------------------------------------------------------------------------------- // return 2 if mouse is over end (1 if over start?) and 0 if over nothing int over() { float dToEnd = dist(endX, endY, mouseX, mouseY); if(dToEnd < endField){ return 2; } else { return 0; } } //------------------------------------------------------------------------------- float getAngle() { if(angle < 0){ angle = atan2(startY-endY, startX-endX)+PI; } return angle; } //------------------------------------------------------------------------------- float getSlope() { float dx = startX-endX; float dy = startY-endY; float slope = dy/dx; return slope; } //------------------------------------------------------------------------------- float getLength() { len = dist(startX, startY, endX, endY); return len; } }