Achieving a noodle shape

I’d like to achieve shapes like this, to simulate flowing “noodles” and I’d like to be able to control fill and stroke, so I’d assume it needs to be a shape, but I have no idea how to do it.

My initial thinking was to just move a circle through a path and “unite” the shapes like what you would do in a vector program, but haven’t been able to find out how to do this.


How would you achieve a shape like this, where you’d be able to control, fill, stroke and direction?

Hi! Welcome to the forum!

I don’t know if there is a easy way to do this, but I think if you want to do it “properly”, you need to use trigonometry - basically you calculate a vector orthogonal to a small segment on each side and connect them. And if you want to do it even better, you can connect these points with curveVertex to make it smooth. If I feel doing so maybe I can make an example later (maybe not :slight_smile:).

1 Like

Thank you @micuat
Certainly, it will be easier for me to try and find out just by having some direction.

something like this - it needs smoothing etc to make it nicer and an edge case literally for the edges. Now I wonder if there is a library to do this easier, maybe exists in toxiclibs or geomerative??

ArrayList<PVector> points = new ArrayList<PVector>();

void setup() {
  size(800, 800, P2D);
}

void draw() {
  float thickness = 10;
  ArrayList<Float> angles = new ArrayList<Float>();
  for (int i = 0; i < points.size() - 1; i++ ) {
    PVector v0 = points.get(i);
    PVector v1 = points.get(i+1).copy();
    v1.sub(v0);
    float angle = v1.heading();
    angles.add(angle);
  }
  
  background(255);
  stroke(100, 20, 200);
  strokeWeight(3);
  fill(20, 100, 230);
  beginShape();
  for (int i = 0; i < points.size() - 1; i++ ) {
    PVector v0 = points.get(i);
    float angle = angles.get(i);
    angle += PI/2;
    float x = cos(angle) * thickness;
    float y = sin(angle) * thickness;
    vertex(v0.x + x, v0.y + y);
  }
  for (int i = points.size() - 2; i >= 0; i-- ) {
    PVector v0 = points.get(i);
    float angle = angles.get(i);
    angle -= PI/2;
    float x = cos(angle) * thickness;
    float y = sin(angle) * thickness;
    vertex(v0.x + x, v0.y + y);
  }
  endShape(CLOSE);
}

void addPoint() {
  PVector v = new PVector(mouseX, mouseY);
  points.add(v);
}

void mousePressed() {
  points.clear();
  addPoint();
}

void mouseDragged() {
  addPoint();
}

This works differently by drawing the line twice

  1. use border colour for full line width
  2. use line colour to replace ‘inside’ of line drawn in (1)

Works well for slow-ish mouse movement, would need some additional points added in mouseDragged for rapid mouse movement.

ArrayList<PVector> points = new ArrayList<PVector>();

float sWeight = 2;
int sCol =  0xFF0000AA;
float lWeight = 20;
int lCol = 0xFFC0C000;

void setup() {
  size(800, 800, P2D);
}

void draw() {
  background(255);
  noStroke();
  fill(sCol);
  for (PVector p : points) ellipse(p.x, p.y, 2 * lWeight, 2 * lWeight);
  fill(lCol);
  float fWeight = lWeight - 2 * sWeight;
  for (PVector p : points) ellipse(p.x, p.y, 2 * fWeight, 2 * fWeight);
}

void addPoint(float x, float y) {
  points.add(new PVector(x, y));
}

void mousePressed() {
  points.clear();
  addPoint(mouseX, mouseY);
}

void mouseDragged() {
  addPoint(mouseX, mouseY);
}
2 Likes

Hello,

I created a simple shape with curveVertex() and overlaid them to show an outline.

A line is a shape. :)

My first version for testing:

Code
// Worm
// v1.0.0
// GLV 2021-03-28

float amp;

void setup() 
	{
  size(640, 360);
	}

void draw() 
	{
  amp = map(mouseX, 0, width, 3*height/4, height/4);
  
  background(255);
  strokeWeight(20);
  noFill();
  stroke(0);
  myShape();

  strokeWeight(15);
  stroke(255);
  myShape();
	}

void myShape()
  {
  beginShape();
  curveVertex(width/8,  height/2);
  curveVertex(width/8,  height/2);;
  curveVertex(width/8 + 7*width/32,  amp);
  curveVertex(3*width/4 - 3*width/32,  height -amp);  
  curveVertex(7*width/8,  height/2);
  curveVertex(7*width/8,  height/2);
  endShape();
  }

image

I then replaced all the fixed co-ordinates with variables and manipulated them (algebra and trigonometry) with code.

Not quite there yet but a work in progress:
canvas

:)

2 Likes

@thesandrobrito,

This has inspired me and had noodles of fun with this!
I am doing an event later in the year and may use something similar to engage the guests.

Update:
This can replace the mouse movement and animate it in my previous post.

amp = height/2 + 100*sin(frameCount*TAU/360);

:)