Scrolling shape not closing

Hi everyone!

I’m fighting with a problem with shapes that i can’t solve.
I want to draw scrolling shapes based on external data i receive through OSC (imagine this like some kind of data oscilloscope). I’m simulating this with the mouse in my example code here. When the mouse is at the left edge of the screen, shape should close, and start a new once once mouse is removed from the left edge.

Everything works more or less ok, but every new shape gets connected to the previous one. The first vertex of the new shape gets connected to the last vertex of the previous shape. I’m doing something wrong with the endShape() command, but i can’t find what.

I asked ChatGPT for some help, and it’s been very useful along the whole process, but we both are struggling with this particular problem.

Does any of the Natural Intelligences we have here have a clue of what could be happening? Any help would be very much appreciated!

float[] ampHistory = new float[600]; // array to store the amplitude history
float[] yHistory = new float[600]; // array to store the y history
float yCenter = height/2; // set the initial y center to the middle of the screen
float ampScale = 20; // set the scaling factor for amplitude
int historyIndex = 0; // index to keep track of the current history position

void setup() {
  size(600, 400);
  background(255);
  stroke(0);
}

void draw() {
  background(255);
  // update the latest amplitude and y values here
  float latestAmp = map(mouseX, 0, width, 0, 255); // replace this with your actual amplitude data
  float latestY = map(mouseY, 0, height, 0, height); // replace this with your actual y data
  
  // add the latest amplitude and y values to the history
  ampHistory[historyIndex] = latestAmp;
  yHistory[historyIndex] = latestY;
  
  // draw the graph
  strokeWeight(2);
  fill(255,0,0);
  boolean drawShape = false;
  beginShape();
  for (int i = 0; i < width; i++) {
    // calculate the amplitude and y position for this history index
    float amp = ampHistory[(historyIndex + i) % ampHistory.length];
    float y = yHistory[(historyIndex + i) % yHistory.length];
    
    if (amp >= 1) { // check if amp is greater than or equal to 1
      // calculate the top and bottom of the graph
      float halfAmp = amp/2;
      float topY = y - halfAmp;
      
      // add the vertex for the top of the graph
      curveVertex(i, topY);
      drawShape = true;
    }
  }
  for (int i = width - 1; i >= 0; i--) {
    // calculate the amplitude and y position for this history index
    float amp = ampHistory[(historyIndex + i) % ampHistory.length];
    float y = yHistory[(historyIndex + i) % yHistory.length];
    
    if (amp >= 1) { // check if amp is greater than or equal to 1
      // calculate the top and bottom of the graph
      float halfAmp = amp/2;
      float bottomY = y + halfAmp;
      
      // add the vertex for the bottom of the graph
      curveVertex(i, bottomY);
    }
  }
  if (drawShape) {
    curveVertex(0, yHistory[historyIndex % yHistory.length]); // close the shape
    endShape(CLOSE);
  }
  
  // increment the history index
  historyIndex = (historyIndex + 1) % ampHistory.length;
}

Hi @eltrem,

can’t test atm, but your Shape is only closed inside drawShape, but beginShape needs always an endShape()

Cheers
— mnse

3 Likes

Thanks @mnse!

I tried your suggestion,
but even with that additional endShape() on the else statement,
the result is the same… the shapes dont get closed. Whenever a new shape is drawn, its first vertex gets connected to the last vertex of the previous shape…

I’m really puzzled with this issue… i tried many different things with no results.
Maybe i have to forget about using vectorial shapes and go the bitmap route… but then many other issues appear…

for a little context, if that helps, what i’m trying to do is a refinement of the application i described in this twitter thread of mine. The idea is to move from bitmap graphics to shapes, to make it easier to have zoom levels without pixelation:

Again, thank you everyone for your help.
Any suggestion is welcome!

Hi @eltrem,

Sorry, I’m quite busy at the moment, but I’ve managed to find a few minutes to review your code. I’m doubtful that it will work the way you intended, as it leads to inconsistencies with regards to the shape. Additionally, the unwanted linking of a shape to another shape depends on your buffer and how it is handled, which could cause further issues.

Unfortunately, I won’t be able to fix your code to make it work the way you want it to. However, I’ve created a quick example that demonstrates how it can be done. It may not be the most efficient method, but due to lack of time it is done quickly.

Cheers
— mnse


ArrayList<Float> ampHistory;
ArrayList<Float> yHistory;
ArrayList<ArrayList<PVector>> allShapes;

void setup() {
  size(600, 400);
  allShapes = new ArrayList<>();
  ampHistory=new ArrayList<>();
  yHistory=new ArrayList<>();
  for (int i = 0; i < width; i++) {
    ampHistory.add(0.);
    yHistory.add(0.);
  }

  strokeWeight(2);
  fill(255, 0, 0);
  stroke(0);
}

void draw() {
  background(255);
  // update the latest amplitude and y values here
  float latestAmp = map(mouseX, 0, width, 0, 255); // replace this with your actual amplitude data
  float latestY = map(mouseY, 0, height, 0, height); // replace this with your actual y data

  // add the latest amplitude and y values to the history
  ampHistory.add(latestAmp);
  yHistory.add(latestY);
  ampHistory.remove(0);
  yHistory.remove(0);

  allShapes.clear();
  ArrayList<PVector> shape = null;
  for (int ampIdx=ampHistory.size()-1; ampIdx >= 0; ampIdx--) {
    float amp = ampHistory.get(ampIdx);
    float y = yHistory.get(ampIdx);
    if (amp > 1 && ampIdx > 0) {
      if (shape == null) {
        shape=new ArrayList<>();
      }
      shape.add(new PVector(ampIdx, y, amp));
    } else {
      if (shape != null) {
        allShapes.add(shape);
        shape=null;
      }
    }
  }

  for (ArrayList<PVector> s : allShapes) {
    beginShape();
    for (int i = 0; i < s.size(); i++) {
      PVector p = s.get(i);
      curveVertex(p.x, p.y-p.z/2);
    }
    for (int i = s.size()-1; i >= 0; i--) {
      PVector p = s.get(i);
      curveVertex(p.x, p.y+p.z/2);
    }
    endShape(CLOSE);
  }
}

example:
ezgif.com-resize

1 Like