# Cascading Curves Rotated By Angle

Hello,

I am trying to create a cascade of expanding curves that go in any direction based on an input angle. At the moment I have it working using ofDrawCurve, but only along the y-axis. The function takes in an x and y coordinate (xpos, ypos) and builds the curve from that point.

I have been able to rotate the x & y endpoints of the curve, but have been unable to figure out how to rotate the control points, px & py.

The test output looks like this. Essentially I’d like to have these curves shoot off in any arbitrary direction. I have a feeling there’s a simpler or easier way to do this, but I’m still new to oF so any pointers would be appreciated!

``````void ofApp::drawWaves (float xpos, float ypos, float pitch, float angle) {

// Define starting wave width
float curveWidth = ofGetWindowWidth() / widthDivisor;

// Iterator value to keep track of where the loop is
int curveNum = 0;

// For loop that iterates through y values to create cascading curves
// Goes through the height of the window
for (int y = 0; y < ofGetWindowHeight(); y += pitch) {
// Increment iterator value.
curveNum += 1;

// Define beginning and end coordinates of curve, Test points only along y-axis
//float x1 = xpos - curveWidth;
//float y1 = ypos + y;
//float x2 = xpos + curveWidth;
//float y2 = ypos + y;

// Control points to determine the depth of the curve, Test points only along y-axis
//float px1 = x1;
//float py1 = ypos + y - curveDepth;
//float px2 = x2;
//float py2 = ypos + y - curveDepth;

// Define beginning and end coordinates of curve
float x1 = xpos - cos(angle)*curveWidth;
float y1 = ypos - sin(angle)*curveWidth;
float x2 = xpos + cos(angle)*curveWidth;
float y2 = ypos + sin(angle)*curveWidth;

// Control points to determine the depth of the curve
float px1 = x1 - 2*curveDepth*sin(angle/2);
float py1 = y1 + cos(angle)*curveDepth;
float px2 = x2 - 2*curveDepth*sin(angle/2);
float py2 = y2 + cos(angle)*curveDepth;

// Define color. Cascade through RGB.
if (curveNum % 3  == 0) {
ofSetColor(0, 0, 255);
}
else if (curveNum % 3 == 1) {
ofSetColor(255, 0, 0);
}
else {
ofSetColor(0, 255, 0);
}

// Draw curve without fill
ofNoFill();
ofSetCurveResolution(curveResolution);
ofDrawCurve(px1, py1, x1, y1, x2, y2, px2, py2);

// Increase the width of the curve for the next iteration
curveWidth += widthIncrementer;;
}
}
``````

Thank you for any help!

Hey I could not get your code to run and im not entirely sure what you mean by rotating the control points. I’d suggest using vectors and get things working with lines and then curves should be an extension. Something like this works for me.

``````void ofApp::drawLines (float xpos, float ypos, float pitch, float angle)
{
glm::vec2 p1, p2, rotDir, pr;

glm::vec2 origin(xpos, ypos);

rotDir = glm::vec2(cos(angle), sin(angle));

ofSetColor(255);

for (int i = 0; i < 5; i++) {

//point from the origin in the direction of angle
pr = origin + radialOffset * rotDir;
ofSetColor(255, 0, 0);

//get the vector perpendicular to our rotation direction
glm::vec2 pv = glm::vec2(rotDir.y, -rotDir.x);

ofSetColor(255);

//get 2 points either size of pr
float halfWidth = radialOffset * 0.5;
p1 = pr - halfWidth * pv;
p2 = pr + halfWidth * pv;
ofDrawLine(p1, p2);

}
}
``````

It basically draws a series of points (the `pv` variable) further and further away from some origin (xpos, ypos), using `radialOffset` as a distance from the origin.

Then for each point, it finds a normal perpendicular to the rotation angle and gets 2 points either side of `pv` to draw a line. Those points would be the x1/y1 x2/y2 endpoints, and for the control points I think you could scale them out as you like.

Hope this helps

1 Like

This is very helpful! Thank you!

1 Like

As a bit more info what is going on math wise, the example is using points in polar coordinates where their location in a 2d plane is defined by a radius and angle, vs cartesian coords which uses the x/y.

You convert from polar to cartesian using

``````x = radius * cos(angle)