I really enjoy playing with algorithms so I decided to start at first principles based on your problem description and came up with a solution that could be adapted to suit other user needs.
So here is my diagram for a main branch with a single sub-branch
The horizontal line represents the main branch. The dotted line represents the limit for any sub-branch and is the mid point between two main branches. For 6-fold symmetery the angle between main branches is 60
o so the angle
a1
will be 30
o.
sbAngle
is the angle between the sub branch and the main branch (i.e. J in the original drawing)
Using this information I created a basic sketch to draw the branh with this result
Repeating this six times to make a snowflake gives
The blue lines represent the area available to each branch.
The sketch code is below and should be self explanatory when read in conjunction with the diagram above
public void setup() {
size(320, 320);
}
void draw() {
background(0);
translate(width/2, height/2);
// Select single branch or snowflake
branch(new PVector(), 0, 100, 5, PI/3, PI/6);
// snowflake(new PVector(), 100, 5, PI/3 + PI/2, PI/6);
}
void snowflake(PVector centre, float mbLength, int nbrSBs, float sbAngle, float a1) {
translate(centre.x, centre.y);
pushMatrix();
for (int i = 0; i < 6; i++) {
branch(centre, i * PI / 3, mbLength, nbrSBs, sbAngle, a1);
}
popMatrix();
}
/**
* This draws a single branch of the snow flake. To prevent interactions between
* neighbouring branches the last parameter is the angular limit for all sub branches.
* For 6-fold symmetry the angle between main branches is PI/3 so the angular limit
* is PI/6
* @param start the global position for the start of the branch
* @param rotAngle the global angle the main branch makes with the x-axis
* @param mbLength the length of the main branch
* @param nbrSBs the number of sub-branches from the main branch
* @param sbAngle the angle between the sub branch makes along length of the main branch
* @param a1 the limit angle.
*/
public void branch(PVector start, float rotAngle, float mbLength, int nbrSBs,
float sbAngle, float a1) {
pushMatrix();
// Transform the graphics context so the main branch starts at [0,0] and lies
// along x-axis
translate(start.x, start.y, rotAngle);
rotate(rotAngle);
stroke(255);
strokeWeight(2.5f);
float spacing = mbLength / (nbrSBs + 1);
float a2 = PI - sbAngle; // triangle internal angle
float a3 = PI - a2 - a1; // calculate third internal angle
line(0, 0, mbLength, 0);
float d1, d2, d3, p3X, p3Y;
for (int i = 1; i <= nbrSBs; i++) {
// Find position on main branch to start sub-branch
d3 = i * spacing;
// Use the Sine Law to calculate other two side lengths
d1 = d3 * sin(a1) / sin(a3); // length of the sub branch
d2 = d3 * sin(a2) / sin(a3); // d2 is not used in this sketch
// Before drawing the sub branch we have the opportunity to change
// the length of the sub branch if we wish
// Using Pythagorus calculate the coordinates for end of
// the sub branch (p3) based on the length of the sub-branch
p3X = d3 + d1 * cos(PI - a2);
p3Y = d1 * sin(PI - a2);
line(d3, 0, p3X, p3Y);
line(d3, 0, p3X, -p3Y);
}
// Show limit angle (blue lines
PVector limit = new PVector(cos(a1), sin(a1));
limit.mult(300);
stroke(120, 220, 220);
strokeWeight(1.5f);
line(0, 0, limit.x, limit.y);
line(0, 0, limit.x, -limit.y);
popMatrix();
}
void mouseClicked() {
save("sn" + frameCount + ".png");
}