We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I want to have rounded corners for my path segments (straight lines). Doing it with right angles is quite easy, but I have a problem with different angles. I know that the angle of the line joints must somehow be related to the radius of the arc() function, but can’t figure out in which way (after all, I wasn’t very good in math). The more obtuse the angle, the bigger the radius, the more acute, the smaller, I suppose. But then there is also the position of the arc that must change in some (other) way.
I appreciate any ideas. I'm sure someone already wrote a function that solves exactly this kind of problem, it may be a trigonometry kind of solution. Sorry if my code example appears strange to you. I want to do something with L-Systems, so I have to make sure it works with that approach. The rounded corners always appear before the next line drawing inside the F-case and the lines have to make room for the corners, hence all the if-statements.
String todo = "F+F-F-F"; // this is the path in Lindenmayer-grammar
float len = 100; // length of a line
float theta; // the angle between the current line direction and the next one
float edgeRad; // radius of the rounded edge (arc()-function)
float edgeAngle; // angle of the rounded edge
void setup() {
size(400, 400);
}
void draw() {
background(255);
noFill();
// I played around with these variables to figure out their relationship
theta = map(mouseX, 0, width, 0, PI);
edgeAngle = map(mouseY, 0, width, 0, TWO_PI);
edgeRad = len/8; // maybe this has to change with theta
pushMatrix();
translate(10, height/2);
render();
popMatrix();
fill(0);
println(theta);
text("angle: "+round(degrees(theta))+"°", 20, 20);
}
void render() {
// here we draw the lines
for (int i=0; i<todo.length (); i++) {
char c = todo.charAt(i); // look up each char and apply the replacement command
if (c == 'F') { // F is the replacement char for a straight line and translation call
// the if's here are just there to make sure everything applies correctly inside the String order
float startEdgeRad = 0;
float endEdgeRad = 0;
if (todo.length() > 1) { // if at least 2 chars & we're not at the first one
if (i < todo.length()-2) { // if we're not at the last char
// check if a direction change coming up, so we can subtract the radius of the edge
if (todo.charAt(i+1) == '+' || todo.charAt(i+1) == '-') {
endEdgeRad = edgeRad;
}
}
// if there was a direction change before, draw a round corner at start
if (i > 0 && todo.charAt(i-1) == '+') startEdgeRad = drawRoundCorner('+');
else if (i > 0 && todo.charAt(i-1) == '-') startEdgeRad = drawRoundCorner('-');
}
line(startEdgeRad, 0, len-endEdgeRad, 0); // the radius of the round edges affect the line position and length
translate(len, 0);
} else if (c == '+') { // + is the replacement for left rotation
rotate(-theta);
} else if (c == '-') { // - is the replacement for right rotation
rotate(theta);
}
}
}
float drawRoundCorner(char dir) {
// This draws the rounded corners
// Maybe I have to completely rewrite this, I just wrote it by intuition
pushMatrix();
if (dir == '+') translate(edgeRad, -edgeRad);
else if (dir == '-') translate(edgeRad, edgeRad);
noFill();
float aStart = PI;
float aStop = aStart+edgeAngle/2;
if (dir == '+') {
aStart = PI/2;
aStop = aStart+edgeAngle/2;
}
fill(255, 0, 0, 40);
arc(0, 0, edgeRad*2, edgeRad*2, aStart, aStop);
stroke(255, 0, 0);
strokeWeight(3);
point(0, 0);
stroke(0);
popMatrix();
strokeWeight(1);
return edgeRad;
}
Answers
https://www.processing.org/reference/curve_.html