#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# Draw a curve line using random points on the sketch.

edited January 2014

Ok, this is kinda difficult to explain with words so I decided to come up with some graphics to explain what I'm trying to achieve:

01.- Randomly divide the sketch horizontally in uneven parts (red lines). I will use hem as x coordinates. 02.- Randomly divide the sketch vertically in uneven parts (cyan lines). I will use them as y coordinates. 03.- Connect the x and y coordinates using lines 04.- This is my goal, instead of lines, I want to create a continuous curve. It that possible or am I daydreaming? Is there a better way to do what I want? Thanks in advance for taking your time to review this thing.

Tagged:

• This is what I have at the moment:

``````int numberOfSegments = 6;
int numberOfPoints = numberOfSegments+1;

PVector[] pointsArray;

void setup() {
size(800, 300);
frameRate(30);
smooth();

pointsArray = new PVector[numberOfPoints];
float segmentWidth = width/numberOfSegments;
float segmentOffset = segmentWidth/4;

//Set the segment position
for (int i=0; i< numberOfPoints; i++) {
float pointPos=segmentWidth*i;

float xPos;
if (i==0) {
xPos = 0;
}
else if (i==numberOfPoints-1) {
xPos = width;
}
else {
xPos = random(pointPos-segmentOffset, pointPos+segmentOffset);
}
pointsArray[i] = new PVector(xPos, int(random(0, height)));
}
}

void draw() {
background(100);
noFill();
println(pointsArray);

//Draw the lines
for (int i=0; i< numberOfPoints-1; i++) {
line(pointsArray[i].x, pointsArray[i].y, pointsArray[i+1].x, pointsArray[i+1].y);
}
}
``````
• You can use the Shapes3D library (get using Sketch > Import Library > Add Library menu) to create a 2D Bezier spline from a set of points. The code below created this image. ``````import shapes3d.utils.*;
import shapes3d.animation.*;
import shapes3d.*;

P_BezierSpline curve;
PVector[] points;

int[] x = {
0, 110, 270, 350, 390, 530, 600
};
int[] y = {
70, 370, 40, 380, 250, 340, 230
};

public void setup() {
size(600, 400);
makeCurveFromPoints();

background(255, 255, 240);
stroke(0);
strokeWeight(1.2);

drawCurve(curve, 1000);
save("curve.png");
}

public void drawCurve(P_BezierSpline c, int nbrSegs) {
float t = 0, dt = 1.0 / nbrSegs;
PVector curr, last = c.point(t);
while (t < 1.0) {
t += dt;
curr = c.point(t);
line(last.x, last.y, curr.x, curr.y);
last = curr;
}
}

public void makeCurveFromPoints() {
points = new PVector[x.length];
for (int i = 0; i < x.length; i ++) {
points[i] = new PVector(x[i], y[i]);
}
curve = new P_BezierSpline(points);
}
``````
• Alternatively, add the following function:

``````final int delta = 25;
void drawBezier(float x1, float y1, float x2, float y2)
{
bezier(x1, y1,
x1 + delta, y1,
x2 - delta, y2,
x2, y2);
}
``````

and in your code, replace line() with drawBezier(). Not perfect (°), but a step forward.

° for simple inflexion points, ie. two successive descending or ascending lines.
For these, the control points should be aligned on a line average of the two lines.

• Wow, that was fantastic! Thanks you all for your help. I'll be expanding the script and I'll come back if I have more questions.

• OK, here's the deal. A friend helped me to modify the sketch and use a function to create a line so the other parallel lines could be created easily. I am wondering if it's possible to shift the x position of the new lines to create a more interesting effect. This is the code at the moment:

``````int numberOfSegments = 5;
int numberOfPoints = numberOfSegments+1;

PVector[] pointsArray;

void setup() {
size(800, 600);
frameRate(30);
smooth();

pointsArray = new PVector[numberOfPoints];
float segmentWidth = width/numberOfSegments;
float segmentOffset = segmentWidth/4;

//Set the segment position
for (int i=0; i<numberOfPoints; i++) {
float pointPos=segmentWidth*i;
float xPos;
//Condition to indicate that the first x must be "0", and the last "width"
if (i==0) {
xPos = 0;
}
else if (i==numberOfPoints-1) {
xPos = width;
}
else {
xPos = random(pointPos-segmentOffset, pointPos+segmentOffset);
}
pointsArray[i] = new PVector(xPos, int(random(0, height/2)));
}
}

void draw() {
background(100);
noFill();

float lineDistance = 40;
float parallelLines = 3;

for (float i=0; i<parallelLines; i++) {
createLine(i*lineDistance);
}
}

//Function to create a line using a loop
void createLine(float parallelOffsetY) {
for (int i=0; i< numberOfPoints-1; i++) {
drawBesize(pointsArray[i].x, pointsArray[i].y+parallelOffsetY, pointsArray[i+1].x, pointsArray[i+1].y+parallelOffsetY);
}
}

//Function to draw a bezier line
final int delta = 25;
void drawBesize(float x1, float y1, float x2, float y2)
{
bezier(x1, y1,
x1 + delta, y1,
x2 - delta, y2,
x2, y2);
}
``````
• Yes, call drawBezier() (there was a typo in my function definition, sorry) with an offset on x1 and x2. The offset can be an additional parameter to createLine(), for example.

• Sorry, I didn't get that. What I want it the parallel lines to have different x position, or at least shifted a bit forward or backward. Is there any way to introduce that variant in that sketch?

• I would make an array of offsets of same size than pointsArray. In createLine(), I would fill the array with random numbers, eg. between -3 and 3. Then, in the loop, call drawBezier() by adding pointsArray[i].x (or i+1) with the offset of same index.

• Hmmm, I think I'm doing something wrong:

``````int numberOfSegments = 5;
int numberOfPoints = numberOfSegments+1;

PVector[] pointsArray;
PVector[] offsetArray;

void setup() {
size(800, 600);
frameRate(30);
smooth();

pointsArray = new PVector[numberOfPoints];
offsetArray = new PVector[numberOfPoints];

float segmentWidth = width/numberOfSegments;
float segmentOffset = segmentWidth/4;

//Set the segment position
for (int i=0; i<numberOfPoints; i++) {
float pointPos=segmentWidth*i;
float xPos;
//Condition to indicate that the first x must be "0", and the last "width"
if (i==0) {
xPos = 0;
}
else if (i==numberOfPoints-1) {
xPos = width;
}
else {
xPos = random(pointPos-segmentOffset, pointPos+segmentOffset);
}
pointsArray[i] = new PVector(xPos, int(random(0, height/2)));
}

//Set the offset position
for (int i=0; i<numberOfPoints; i++) {
float offsetPointPos=segmentWidth*i;
float offsetXPos;
//Condition to indicate that the first x must be "0", and the last "width"
if (i==0) {
offsetXPos = 0;
}
else if (i==numberOfPoints-1) {
offsetXPos = width;
}
else {
offsetXPos = random(-3,3);
}
offsetArray[i] = new PVector(offsetXPos, int(random(0, height/2)));
}
}

void draw() {
background(100);
noFill();

float lineDistance = 40;
float parallelLines = 3;

for (float i=0; i<parallelLines; i++) {
createLine(i*lineDistance);
}
}

//Function to create a line using a loop
void createLine(float parallelOffsetY) {
for (int i=0; i< numberOfPoints-1; i++) {
drawBesize(pointsArray[i].x+offsetArray[i].x, pointsArray[i].y+parallelOffsetY,
pointsArray[i+1].x+offsetArray[i].x, pointsArray[i+1].y+parallelOffsetY);
}
}

//Function to draw a bezier line
final int delta = 25;
void drawBesize(float x1, float y1, float x2, float y2)
{
bezier(x1, y1,
x1 + delta, y1,
x2 - delta, y2,
x2, y2);
}
``````
• ``````int numberOfSegments = 5;
int numberOfPoints = numberOfSegments+1;

PVector[] pointsArray;
float[] offsetArray;

void setup() {
size(800, 600);
frameRate(30);
noLoop();
smooth();

pointsArray = new PVector[numberOfPoints];
offsetArray = new float[numberOfPoints];

float segmentWidth = width/numberOfSegments;
float segmentOffset = segmentWidth/4;

//Set the segment position
for (int i=0; i<numberOfPoints; i++) {
float pointPos=segmentWidth*i;
float xPos;
//Condition to indicate that the first x must be "0", and the last "width"
if (i==0) {
xPos = 0;
}
else if (i==numberOfPoints-1) {
xPos = width;
}
else {
xPos = random(pointPos-segmentOffset, pointPos+segmentOffset);
}
pointsArray[i] = new PVector(xPos, int(random(0, height/2)));
}
}

void draw() {
background(100);
noFill();

float lineDistance = 40;
float parallelLines = 3;

for (float i=0; i<parallelLines; i++) {
createLine(i*lineDistance);
}
}

//Function to create a line using a loop
void createLine(float parallelOffsetY) {
//Set the offset position
for (int i=0; i<numberOfPoints; i++) {
offsetArray[i] = random(-5,5);
}

for (int i=0; i< numberOfPoints-1; i++) {
drawBesize(pointsArray[i].x+offsetArray[i], pointsArray[i].y+parallelOffsetY,
pointsArray[i+1].x+offsetArray[i+1], pointsArray[i+1].y+parallelOffsetY);
}
}

//Function to draw a bezier line
final int delta = 25;
void drawBesize(float x1, float y1, float x2, float y2)
{
bezier(x1, y1,
x1 + delta, y1,
x2 - delta, y2,
x2, y2);
}
``````