Reputation: 61
I have written the code with the constructor which passes in the variables to Lsystem.
This should allow me to create numerous 'Trees', messing around with the parameters each time.
However, I'm getting a NullPointerException with the line
for (int i=0; i < m_state.length(); i++) {
I understand that I need to use this. somewhere (having read all I can), but am stuck as to how to make my code work.
If someone can show me what the correct code should look like, I'd be much obliged.
Thank you in advance.
class Tree {
// member variables
int m_lineLength; // turtle line length
int m_x; // initial x position
int m_y; // initial y position
float m_branchAngle; // turtle rotation at branch
float m_initOrientation; // initial orientation
String m_state; // initial state
float m_scaleFactor; // branch scale factor
String m_F_rule; // F-rule substitution
String m_H_rule; // H-rule substitution
String m_f_rule; // f-rule substitution
int m_numIterations; // number of times to substitute
// constructor
// (d = line length, x & y = start position of drawing)
Tree(int d, int x, int y, float m_branchAngle, float m_initOrientation, String m_state, float m_scaleFactor, String m_F_rule, String m_H_rule, String m_f_rule, int m_numIterations) {
m_lineLength = d;
m_x = x;
m_y = y;
m_branchAngle = (25.7/180.0)*PI;
m_initOrientation = -HALF_PI;
m_scaleFactor = 1;
m_state = "F";
m_F_rule = "F[+F]F[-F]F";
m_H_rule = "";
m_f_rule = "";
m_numIterations = 5;
// Perform L rounds of substitutions on the initial state
for (int k=0; k < m_numIterations; k++) {
m_state = substitute(m_state);
}
}
void draw() {
pushMatrix();
pushStyle();
stroke(0);
translate(m_x, m_y); // initial position
rotate(m_initOrientation); // initial rotation
// now walk along the state string, executing the
// corresponding turtle command for each character
for (int i=0; i < m_state.length(); i++) {
turtle(m_state.charAt(i));
}
popStyle();
popMatrix();
}
// Turtle command definitions for each character in our alphabet
void turtle(char c) {
switch(c) {
case 'F': // drop through to next case
case 'H':
line(0, 0, m_lineLength, 0);
translate(m_lineLength, 0);
break;
case 'f':
translate(m_lineLength, 0);
break;
case 's':
scale(m_scaleFactor);
break;
case '-':
rotate(m_branchAngle);
break;
case '+':
rotate(-m_branchAngle);
break;
case '[':
pushMatrix();
break;
case ']':
popMatrix();
break;
default:
println("Bad character: " + c);
exit();
}
}
// apply substitution rules to string s and return the resulting string
String substitute(String s) {
String newState = new String();
for (int j=0; j < s.length(); j++) {
switch (s.charAt(j)) {
case 'F':
newState += m_F_rule;
break;
case 'H':
newState += m_F_rule;
break;
case 'f':
newState += m_f_rule;
break;
default:
newState += s.charAt(j);
}
}
return newState;
}
}
and
Tree tree;
void setup() {
int SZ = 512; // screen size
int d = 2;
int x = SZ/2;
int y = SZ;
float m_branchAngle = (25.7/180.0)*PI;
float m_initOrientation = -HALF_PI;
String m_state = "F";
float m_scaleFactor = 1;
String m_F_rule = "F[+F]F[-F]F";
String m_H_rule = "";
String m_f_rule = "";
int m_numIterations = 5;
size(SZ,SZ);
background(255);
noLoop();
tree = new Tree(d, x, y, m_branchAngle, m_initOrientation, m_state, m_scaleFactor, m_F_rule, m_H_rule, m_f_rule, m_numIterations);
}
void draw() {
tree.draw();
}
Upvotes: 0
Views: 119
Reputation: 42174
Let's take a look at a simplified version of your Tree constructor:
String m_state;
Tree(String m_state) {
m_state = "F";
for (int k=0; k < m_numIterations; k++) {
m_state = substitute(m_state);
}
}
Notice that you have two variables named m_state: one class-level instance variable, and one argument into the constructor. That means the constructor-level variable is hiding the class-level variable. Anything you do with the m_state variable inside your constructor is referring to the constructor-level variable, not the class-level variable.
Then later you use the class-level variable, which you've never actually initialized. That's what's causing your NullPointerException.
One way to fix the problem is to use the this keyword to specifically refer to the class-level variable:
String m_state;
Tree(String m_state) {
this.m_state = "F";
for (int k=0; k < m_numIterations; k++) {
this.m_state = substitute(this.m_state);
}
}
But then, if you aren't using the constructor-level m_state variable for anything, why do you bother with it at all? So you might be able to eliminate the parameter altogether, if you're just going to set it equal to "F" anyway.
Upvotes: 2