Create an intermediate point

I wrote this println ( " lastDataOfTheSample " + list.get(list.size()-1);
but I have syntax error.
Could you please put your lines of code in my code?

1 Like

here is an example

see last paragraph in draw() pls

you need to click two points with the mouse into my program



ArrayList<PVector> points = new ArrayList ();

boolean runPoints=false;

float x, y;
float startX, startY, endX, endY;
float timeSpan;

int i=0;

float amt;

void setup() {
  size(800, 800);
  startX = width/2;
  startY = height/2;
  endX = 100;
  endY = 100;
  timeSpan = 2000.0;
}

void draw() {

  if (runPoints) {
    // PLAY Mode

    // background(255);

    //   frameRate(1) ;
    fill(255, 0, 0);
    text("PLAY Mode - press any key to edit ", 19, 19);

    PVector pv1 = points.get(i);
    PVector pv2 = points.get(i+1);

    /// lerp !!!!!


    //for (int i2 = 0; i2 <= 10; i2++) {
    float x = lerp(pv1.x, pv2.x, amt/10.0);
    float y = lerp(pv1.y, pv2.y, amt/10.0);
    point(x, y);
    // }

    // line(pv1.x, pv1.y, pv2.x, pv2.y);

    amt+=0.1;
    if (amt>10) {
      amt=0;
      i++;
    }


    if (i>points.size()-2) {
      i=0;
      runPoints=false;
    }
  }//if
  else {
    // Edit mode
    background(255);

    fill(255, 0, 0);
    text("Edit Mode - click mouse points and press any key to play ", 19, 19);

    for (int i = 0; i<points.size(); i++) {
      PVector pv1 = points.get(i);
      ellipse(pv1.x, pv1.y, 4, 4);
    }
  }//else

  //-------
  // show first and last point
  if (points.size()>1) {
    fill(0);
    text("0", points.get(0).x, points.get(0).y-3);
    PVector pv = points.get(points.size()-1).copy();
    text("last", pv.x, pv.y-3);
  }//if
  //
}// function draw()

//-------------------------------------------------------------------

void mousePressed() {
  points.add(new PVector(mouseX, mouseY));
  runPoints=false;
}

void keyPressed () {
  // toggle runPoints
  runPoints =
    ! runPoints;
  if (runPoints) {
    background(255);
  }
}

your arraylist is called samples, not list

you also have a missing ) at the end

I am sure you can apply it to your code.

new version with println:



ArrayList<PVector> points = new ArrayList ();

boolean runPoints=false;

float x, y;
float startX, startY, endX, endY;
float timeSpan;

int i=0;

float amt;

void setup() {
  size(800, 800);
  startX = width/2;
  startY = height/2;
  endX = 100;
  endY = 100;
  timeSpan = 2000.0;
}

void draw() {

  if (runPoints) {
    // PLAY Mode

    // background(255);

    //   frameRate(1) ;
    fill(255, 0, 0);
    text("PLAY Mode - press any key to edit ", 19, 19);

    PVector pv1 = points.get(i);
    PVector pv2 = points.get(i+1);

    /// lerp !!!!!


    //for (int i2 = 0; i2 <= 10; i2++) {
    float x = lerp(pv1.x, pv2.x, amt/10.0);
    float y = lerp(pv1.y, pv2.y, amt/10.0);
    point(x, y);
    // }

    // line(pv1.x, pv1.y, pv2.x, pv2.y);

    amt+=0.1;
    if (amt>10) {
      amt=0;
      i++;
    }


    if (i>points.size()-2) {
      i=0;
      runPoints=false;
    }
  }//if
  else {
    // Edit mode
    background(255);

    fill(255, 0, 0);
    text("Edit Mode - click mouse points and press any key to play ", 19, 19);

    for (int i = 0; i<points.size(); i++) {
      PVector pv1 = points.get(i);
      ellipse(pv1.x, pv1.y, 4, 4);
    }
  }//else

  //-------
  // show first and last point
  if (points.size()>1) {
    fill(0);
    text("0", points.get(0).x, points.get(0).y-3);
    PVector pv = points.get(points.size()-1).copy();

    println(pv);
    println ( "lastDataOfTheSample "
      + points.get(points.size()-1) ) ;

    text("last", pv.x, pv.y-3);
  }//if
  //
}// function draw()

//-------------------------------------------------------------------

void mousePressed() {
  points.add(new PVector(mouseX, mouseY));
  runPoints=false;
}

void keyPressed () {
  // toggle runPoints
  runPoints =
    ! runPoints;
  if (runPoints) {
    background(255);
  }
}

2 Likes

Thanks. An engineer found a solution for me.
Here it is!
`But now I have to map this interpolation, just the interpolation of y, in order to have a variable from 0 to TWO to see a ball turning always in the same way! I hope you can keep to try to help me!

int actualSec,lastSec,measure,measureToStartRecording;
boolean bRecording = false;
boolean mouseRecorded =  true;

int nbBalls=1;

float movementInterpolated;


class Sample {
  int t, x, y;
  Sample( int t, int x, int y ) {
    this.t = t;  this.x = x;  this.y = y;
  }
}

class Sampler {
  
  ArrayList<Sample> samples;
  ArrayList<Sample> samplesModified;
  int startTime;
  int playbackFrame;
  
  Sampler() {
    samples = new ArrayList<Sample>();
        samplesModified = new ArrayList<Sample>();
    startTime = 0;
  }
  void beginRecording() {   
    samples = new ArrayList<Sample>();
    samplesModified = new ArrayList<Sample>();
    playbackFrame = 0;
  }
  void addSample( int x, int y ) {  // add sample when bRecording
    int now = millis();
    if( samples.size() == 0 ) startTime = now;
    samples.add( new Sample( now - startTime, x, y ) );
  }
  int fullTime() {
    return ( samples.size() > 1 ) ? 
    samples.get( samples.size()-1 ).t : 0;
  }
  void beginPlaying() {
    startTime = millis();
    playbackFrame = 0;
    println( samples.size(), "samples over", fullTime(), "milliseconds" );
    if(samples.size() > 0){
      int deltax = samples.get(0).x - samples.get(samples.size()-1).x;
      int deltay = samples.get(0).y - samples.get(samples.size()-1).y;
      float sumdist = 0;
      
      for(int i = 0; i < samples.size() - 1; i++) {
        sumdist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
      }
      
      samplesModified.add( new Sample(samples.get(0).t, samples.get(0).x , samples.get(0).y ) );
      float dist = 0;
      for(int i = 0; i < samples.size() - 1; i++) {
        dist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
        samplesModified.add( new Sample(samples.get(i+1).t, (int) (samples.get(i +1).x + (dist * deltax) / sumdist), (int) (samples.get(i+1).y +( dist * deltay )/ sumdist)) );
        print(samples.get(i).x);
        print(",");
        print(samples.get(i).y);
        print(",");
        print( " good data x " + samplesModified.get(i).x);
        print(",");
        print( " good data y " + samplesModified.get(i).y);
        println("");      
      }
    }
  }
 
 
  void draw() {
    stroke( 255 );
    
    //**RECORD
    beginShape(LINES);
    for( int i=1; i<samples.size(); i++) {
      vertex( samplesModified.get(i-1).x, samplesModified.get(i-1).y ); // replace vertex with Pvector
      vertex( samplesModified.get(i).x, samplesModified.get(i).y );
    }
    endShape();
    //**ENDRECORD
    
    //**REPEAT
    int now = (millis() - startTime) % fullTime();
    if( now < samplesModified.get( playbackFrame ).t ) playbackFrame = 0;
    while( samplesModified.get( playbackFrame+1).t < now )
      playbackFrame = (playbackFrame+1) % (samples.size()-1);
    Sample s0 = samplesModified.get( playbackFrame );
    Sample s1 = samplesModified.get( playbackFrame+1 );
    float t0 = s0.t;
    float t1 = s1.t;
    float dt = (now - t0) / (t1 - t0);
    float x = lerp( s0.x, s1.x, dt );
    float y = lerp( s0.y, s1.y, dt );
    circle( x, y, 10 );
      println( " good data y " + y);
    movementInterpolated=map (y, 0, 400, 0, TWO_PI);
  }
 } 

Sampler sampler;

void setup() {  
  size( 800, 800, P3D );
  frameRate( 30 );  
  sampler = new Sampler();
}

void draw() {
  background( 0 );
  activeSampling();
  stopSampling();
  
  if( actualSec!=lastSec){
       lastSec=actualSec;
       measure++;
       textSize (100);
       text (measure, 100, 100 );
     }
       actualSec =(int) (millis()*0.001);  // 
 
  if( bRecording) { // draw circle
    circle( mouseX, mouseY, 10 );
    sampler.addSample( mouseX, mouseY );
  }
  
  else {    
  if( sampler.fullTime() > 0 )
        sampler.draw();
  }
   
  drawBall( 1, movementInterpolated);
}

void mousePressed() {
  bRecording = true;   // draw circle
  mouseRecorded = true;
  measure=0;
}
  
void activeSampling() { 
   if (measure<=1 && measure>=1 &&actualSec!=lastSec && mouseRecorded == true) {
  sampler.beginRecording();
  }
}

void stopSampling() { 
   if (measure<=3 && measure>=3  && actualSec!=lastSec) {  
  mouseRecorded = false;
     //**REPEAT
  bRecording = false;
  sampler.beginPlaying();
  }
}

 void drawBall(int n, float phase) 
  { 
        pushMatrix();
        translate(-400, -400, -2000);
        noStroke();
        float side = height*0.15*1/this.nbBalls;
        float rayon = width/2; 
        float x = rayon*cos(phase);
        float y = rayon*sin(phase);
        translate (x, y, 200+(50*5*n));  
        colorMode(RGB, 255, 255, 255);
        fill( 0, 255, 0 ); 
        sphere(side*3);
        popMatrix();
    }

1 Like

Okay, the line I’ve drawn is shown in white.

A green ball follows the line.

But why is the big green ball still there in this case?

I don’t think this is true. He’s recording throughout - or what do you mean?

not sure, but measure can’t be < 1 AND > 1 at the same time. Hence you mean measure==1?


movementInterpolated

not clear. Maybe you can communicate what your final goal is?

You are referring to
movementInterpolated=map (y, 0, 400, 0, TWO_PI);

(it’s TWO_PI, not TWO)
(always nice when you tell us the code line you are referring to )

here is what you can do with movementInterpolated:

    // see y as 0 to TWO_PI
    movementInterpolated=map (y,
      0, 400,
      0, TWO_PI);
    // show 2 circles at right screen border
    circle( width-11, movementInterpolated+55, 12); // minimal movement
    circle( width-11, movementInterpolated*100+255, 12);  // movement enhanced by *100

    // calc circle pos x1,y1 with movementInterpolated as an angle
    float x1=cos(movementInterpolated) * 100 + (width-120);
    float y1=sin(movementInterpolated) * 100 + (255);
    fill(0, 0, 255);
    circle(x1, y1, 9);   // show point on circle with movementInterpolated as angle
    circle((width-120), 255, 9); // show center of circle

Remark

By the way in processing the order is (mostly (it’s only by convention))

  • global vars and objects
  • setup and draw
  • other functions
  • classes

It is unwise to name a method in a class draw(), just use display() instead


Full Sketch


int actualSec, lastSec, measure, measureToStartRecording;
boolean bRecording = false;
boolean mouseRecorded =  true;

int nbBalls=1;

float movementInterpolated;

Sampler sampler;

// ------------------------------------------------------------------------------------------------------
// Two core functions

void setup() {
  size( 800, 800, P3D );

  frameRate( 30 );
  sampler = new Sampler();
}//setup()

void draw() {
  background( 0 );
  activeSampling();
  stopSampling();

  if (actualSec!=lastSec) {
    lastSec=actualSec;
    measure++;
  }
  textSize(100);
  text(measure, 100, 100 );

  actualSec = (int) (millis()*0.001);  //

  if (bRecording) {
    // draw circle
    circle(mouseX, mouseY, 10 );
    sampler.addSample( mouseX, mouseY );
  } else {
    if (sampler.fullTime() > 0 )
      sampler.display();
  }

  drawBall(1, movementInterpolated);
}//draw()

// ------------------------------------------------------------------------------------------------------
// Inputs

void mousePressed() {
  bRecording = true;   // draw circle
  mouseRecorded = true;
  measure=0;
}

// ------------------------------------------------------------------------------------------------------
// other functions

void activeSampling() {
  if (measure<=1 && measure>=1 &&actualSec!=lastSec && mouseRecorded == true) {
    sampler.beginRecording();
    println ("here 18");
  }
}

void stopSampling() {
  if (measure<=3 && measure>=3  && actualSec!=lastSec) {
    mouseRecorded = false;
    //**REPEAT
    bRecording = false;
    sampler.beginPlaying();
  }
}

void drawBall(int n, float phase) {
  pushMatrix();
  translate(-400, -400, -2000);
  noStroke();
  float side = height*0.15*1/this.nbBalls;
  float rayon = width/2;
  float x = rayon*cos(phase);
  float y = rayon*sin(phase);
  translate (x, y, 200+(50*5*n));
  colorMode(RGB, 255, 255, 255);
  fill( 0, 255, 0 );
  sphere(side*3);
  popMatrix();
}

// ====================================================================
// Two classes

class Sample {
  int t, x, y;

  //constr
  Sample( int t, int x, int y ) {
    this.t = t;
    this.x = x;
    this.y = y;
  }//constr
  //
}//class

// ----

class Sampler {

  ArrayList<Sample> samples;
  ArrayList<Sample> samplesModified;

  int startTime;
  int playbackFrame;

  //constr
  Sampler() {
    samples = new ArrayList<Sample>();
    samplesModified = new ArrayList<Sample>();
    startTime = 0;
  }//constr

  void beginRecording() {
    samples = new ArrayList<Sample>();
    samplesModified = new ArrayList<Sample>();
    playbackFrame = 0;
  }

  void addSample( int x, int y ) {  // add sample when bRecording
    int now = millis();
    if ( samples.size() == 0 ) startTime = now;
    samples.add( new Sample( now - startTime, x, y ) );
  }

  int fullTime() {
    return
      samples.size() > 1  ?
      samples.get( samples.size()-1 ).t : 0;
  }

  void beginPlaying() {
    // called only once
    println("here 12");
    startTime = millis();
    playbackFrame = 0;
    println( samples.size(), "samples over", fullTime(), "milliseconds" );
    if (samples.size() > 0) {
      int deltax = samples.get(0).x - samples.get(samples.size()-1).x;
      int deltay = samples.get(0).y - samples.get(samples.size()-1).y;
      float sumdist = 0;

      for (int i = 0; i < samples.size() - 1; i++) {
        sumdist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
      }

      samplesModified.add( new Sample(samples.get(0).t, samples.get(0).x, samples.get(0).y ) );
      float dist = 0;
      for (int i = 0; i < samples.size() - 1; i++) {
        dist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
        samplesModified.add( new Sample(samples.get(i+1).t, (int) (samples.get(i +1).x + (dist * deltax) / sumdist), (int) (samples.get(i+1).y +( dist * deltay )/ sumdist)) );
        print(samples.get(i).x);
        print(",");
        print(samples.get(i).y);
        print(",");
        print( " good data x " + samplesModified.get(i).x);
        print(",");
        print( " good data y " + samplesModified.get(i).y);
        println("");
      }
    }
  }

  void display() {
    stroke( 255 );

    //**RECORD
    beginShape(LINES);
    for ( int i=1; i<samples.size(); i++) {
      vertex( samplesModified.get(i-1).x, samplesModified.get(i-1).y ); // replace vertex with Pvector
      vertex( samplesModified.get(i).x, samplesModified.get(i).y );
    }
    endShape();
    //**ENDRECORD

    //**REPEAT
    int now = (millis() - startTime) % fullTime();
    if ( now < samplesModified.get( playbackFrame ).t ) playbackFrame = 0;
    while ( samplesModified.get( playbackFrame+1).t < now )
      playbackFrame = (playbackFrame+1) % (samples.size()-1);
    Sample s0 = samplesModified.get( playbackFrame );
    Sample s1 = samplesModified.get( playbackFrame+1 );
    float t0 = s0.t;
    float t1 = s1.t;
    float dt = (now - t0) / (t1 - t0);
    float x = lerp( s0.x, s1.x, dt );
    float y = lerp( s0.y, s1.y, dt );
    circle( x, y, 10 );
    println( " good data y " + y);

    // see y as 0 to TWO_PI
    movementInterpolated=map (y,
      0, 400,
      0, TWO_PI);
    // show 2 circles at right screen border
    circle( width-11, movementInterpolated+55, 12); // minimal movement
    circle( width-11, movementInterpolated*100+255, 12);  // movement enhanced by *100

    // calc circle pos x1,y1 with movementInterpolated as an angle
    float x1=cos(movementInterpolated) * 100 + (width-120);
    float y1=sin(movementInterpolated) * 100 + (255);
    fill(0, 0, 255);
    circle(x1, y1, 9);   // show point on circle with movementInterpolated as angle
    circle((width-120), 255, 9); // show center of circle

    //
  }//method
  //
}//class
//

2 Likes

Hi Mister,
Thank for helping me :wink:

I wanted to say, I want to follow the movement drawn in white color doing a loop.
If you try to record a big circle with the mouse you will see that your circle an my green ball turn in the same way. But sometimes, depending of the movement drawn in white color we have some jumps, glitches in the movement made by your circle and my ball.
I think it is possible to fix this bug by mapping the interpolatedmovement with better method.
I wrote at line 206 a possible method.
I will explain my final goal a bit later.

Thank you so much


int actualSec, lastSec, measure, measureToStartRecording;
boolean bRecording = false;
boolean mouseRecorded =  true;
int nbBalls=1;

float movementInterpolated;
float formerInterpolatedY,interpolatedY;

Sampler sampler;

// ------------------------------------------------------------------------------------------------------
// Two core functions

void setup() {
  size( 800, 800, P3D );

  frameRate( 30 );
  sampler = new Sampler();
}//setup()

void draw() {
  background( 0 );
  activeSampling();
  stopSampling();

  if (actualSec!=lastSec) {
    lastSec=actualSec;
    measure++;
  }
  textSize(100);
  text(measure, 100, 100 );

  actualSec = (int) (millis()*0.001);  //

  if (bRecording) {
    // draw circle
    circle(mouseX, mouseY, 10 );
    sampler.addSample( mouseX, mouseY );
  } else {
    if (sampler.fullTime() > 0 )
      sampler.display();
  }

  drawBall(1, movementInterpolated);
}//draw()

// ------------------------------------------------------------------------------------------------------
// Inputs

void mousePressed() {
  bRecording = true;   // draw circle
  mouseRecorded = true;
  measure=0;
}

// ------------------------------------------------------------------------------------------------------
// other functions

void activeSampling() {
  if (measure==1 && actualSec!=lastSec && mouseRecorded == true) {
    sampler.beginRecording();
    println ("here 18");
  }
}

void stopSampling() {
  if (measure==3  && actualSec!=lastSec) {
    mouseRecorded = false;
    //**REPEAT
    bRecording = false;
    sampler.beginPlaying();
  }
}

void drawBall(int n, float phase) {
  pushMatrix();
  translate(-400, -400, -2000);
  noStroke();
  float side = height*0.15*1/this.nbBalls;
  float rayon = width/2;
  float x = rayon*cos(phase);
  float y = rayon*sin(phase);
  translate (x, y, 200+(50*5*n));
  colorMode(RGB, 255, 255, 255);
  fill( 0, 255, 0 );
  sphere(side*3);
  popMatrix();
}

// ====================================================================
// Two classes

class Sample {
  int t, x, y;

  //constr
  Sample( int t, int x, int y ) {
    this.t = t;
    this.x = x;
    this.y = y;
  }//constr
  //
}//class

// ----

class Sampler {

  ArrayList<Sample> samples;
  ArrayList<Sample> samplesModified;

  int startTime;
  int playbackFrame;

  //constr
  Sampler() {
    samples = new ArrayList<Sample>();
    samplesModified = new ArrayList<Sample>();
    startTime = 0;
  }//constr

  void beginRecording() {
    samples = new ArrayList<Sample>();
    samplesModified = new ArrayList<Sample>();
    playbackFrame = 0;
  }

  void addSample( int x, int y ) {  // add sample when bRecording
    int now = millis();
    if ( samples.size() == 0 ) startTime = now;
    samples.add( new Sample( now - startTime, x, y ) );
  }

  int fullTime() {
    return
      samples.size() > 1  ?
      samples.get( samples.size()-1 ).t : 0;
  }

  void beginPlaying() {
    // called only once
    println("here 12");
    startTime = millis();
    playbackFrame = 0;
    println( samples.size(), "samples over", fullTime(), "milliseconds" );
    if (samples.size() > 0) {
      int deltax = samples.get(0).x - samples.get(samples.size()-1).x;
      int deltay = samples.get(0).y - samples.get(samples.size()-1).y;
      float sumdist = 0;

      for (int i = 0; i < samples.size() - 1; i++) {
        sumdist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
      }

      samplesModified.add( new Sample(samples.get(0).t, samples.get(0).x, samples.get(0).y ) );
      float dist = 0;
      for (int i = 0; i < samples.size() - 1; i++) {
        dist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
        samplesModified.add( new Sample(samples.get(i+1).t, (int) (samples.get(i +1).x + (dist * deltax) / sumdist), (int) (samples.get(i+1).y +( dist * deltay )/ sumdist)) );
        print(samples.get(i).x);
        print(",");
        print(samples.get(i).y);
        print(",");
        print( " good data x " + samplesModified.get(i).x);
        print(",");
        print( " good data y " + samplesModified.get(i).y);
        println("");
      }
    }
  }

  void display() {
    stroke( 255 );

    //**RECORD
    beginShape(LINES);
    for ( int i=1; i<samples.size(); i++) {
      vertex( samplesModified.get(i-1).x, samplesModified.get(i-1).y ); // replace vertex with Pvector
      vertex( samplesModified.get(i).x, samplesModified.get(i).y );
    }
    endShape();
    //**ENDRECORD

    //**REPEAT
    int now = (millis() - startTime) % fullTime();
    if ( now < samplesModified.get( playbackFrame ).t ) playbackFrame = 0;
    while ( samplesModified.get( playbackFrame+1).t < now )
      playbackFrame = (playbackFrame+1) % (samples.size()-1);
    Sample s0 = samplesModified.get( playbackFrame );
    Sample s1 = samplesModified.get( playbackFrame+1 );
    float t0 = s0.t;
    float t1 = s1.t;
    float dt = (now - t0) / (t1 - t0);
    float x = lerp( s0.x, s1.x, dt );
    float y = lerp( s0.y, s1.y, dt );
    circle( x, y, 10 );
    println( " good data y " + y);
    
    //my modification
     formerInterpolatedY=interpolatedY;
     interpolatedY= constrain ( lerp( s0.y, s1.y, dt ), 0, 800);
     
     // a possible to have movement in the same way
       if (formerInterpolatedY<=interpolatedY){
       movementInterpolated= map (interpolatedY, 800, 0, 0, TWO_PI);  // map from the highest interpolated point to lowest interpolated point
       }
       else
       {
       movementInterpolated=map (interpolatedY, 0, 800, 0, TWO_PI);  // map from the lowest interpolated point to highest interpolated point
      }
    
    
    // former modification
   
    // see y as 0 to TWO_PI
    // movementInterpolated=map (y,
    //  0, 400,
    //  0, TWO_PI);   
      
    // show VerticalMovement 2 circles at right screen border
    circle( width-11, movementInterpolated+55, 12); // minimal movement
    circle( width-11, movementInterpolated*100+255, 12);  // movement enhanced by *100

    // calc circle pos x1,y1 with movementInterpolated as an angle
    float x1=cos(movementInterpolated) * 100 + (width-120);
    float y1=sin(movementInterpolated) * 100 + (255);
    fill(0, 0, 255);
    circle(x1, y1, 9);   // show point on circle with movementInterpolated as angle
    circle((width-120), 255, 9); // show center of circle

    //
  }//method
  //
}//class
//
1 Like

Hello super Mister.

I changed the program.
Now, i have perfect angle to interpolate, not a shape drawn with the mouse.

I think you will have solution, quite easy.
I will try make a video tomorow in order to see what i’m trying to do.

Take care of you.
Benjamin

1 Like

Hello!

you can also just record a circle based on the angle between mouse and screen center (core idea is using atan2() here).

This circle would have a fixed radius.

Remark

When you have a real circle and know its center and radius, you can of course calc the intermediate points (not only one but all):

  • calc the angle from last point a1
  • calc the angle from first point a2
  • for loop a_intermediate from a1 to a2; lots of ways to do this;
    for(int a_intermediate = degree(a1); a_intermediate <= degree(a2); a_intermediate++) {
    or use lerp() between the angles a1 and a2 (not between the points obviously).
  • calc x and y based on a_intermediate and cos and sin (and r and center) like here:
float x=cos(a_intermediate) * r + centerX; 
float y=sin(a_intermediate) * r + centerY;

Warm regards,

Chrisir


Full Sketch

(without the remark above)



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

void draw() {
  background(204);

  float a = calcAngle();

  //----------------------------------------

  pushMatrix();
  translate(width/2, height/2);
  rotate(a);
  translate(28, 0);
  rect(-30, -5, 60, 10);
  popMatrix();

  //----------------------------------------

  ellipse(width/2, height/2, 5, 5);
  text(degrees(a), 22, 22);
}

//----------------------------------------------------------------------

float calcAngle() {

  // calc angle between mouse and screen center

  float a = atan2(mouseY-height/2, mouseX-width/2);

  if (a<0) {
    a=map(a, -PI, 0,
      PI, TWO_PI);
  }

  return a;
}
//

new version where the points on the circle are shown separately using :

  stroke(255, 0, 0);
  ellipse(
    cos(a) * 150 + width/2.0,
    sin(a) * 150 + height/2.0,
    4,
    4
    );

Full Sketch



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

void draw() {
  // background(204);

  float a = calcAngle();

  //----------------------------------------

  pushMatrix();
  translate(width/2, height/2);
  rotate(a);
  translate(28, 0);
  stroke(0);
  rect(-30, -5, 60, 10);
  popMatrix();

  //----------------------------------------

  stroke(255, 0, 0);
  ellipse(
    cos(a) * 150 + width/2.0,
    sin(a) * 150 + height/2.0,
    4,
    4
    );

  stroke(0);
  ellipse(width/2, height/2, 5, 5);
  text(degrees(a), 22, 22);
}

//----------------------------------------------------------------------

float calcAngle() {

  // calc angle between mouse and screen center

  float a = atan2(mouseY-height/2, mouseX-width/2);

  if (a<0) {
    a=map(a, -PI, 0,
      PI, TWO_PI);
  }

  return a;
}
//

1 Like

Hi,

I changed the program with yours remarks.
It 's totatlly better to record position of the ball like that. :slightly_smiling_face:
As you said :

That’s i’m tring to do but i do not retreive the first and the last datas sampled :cold_face:

Here my changes

int actualSec;
int lastSec;

int virtualV2;

float mlerp(float x0, float x1, float t, float M ){
   float dx = (x1 - x0 + 1.5*M) % M - 0.5*M;
   return (x0 + t * dx + M) % M;
}
float interpolatedAngle;
float angleToInterpolate;

boolean bRecording = false;
boolean mouseRecorded;
float currTime;
float nextSamplePeriod = 2.0;
int measure;

class Sample {
  float t, y;
  Sample( float t, float y ) {
    this.t = t;  this.y = y;
  }
}
class Sampler {
  ArrayList<Sample> samples;
  float startTime;
  float sampleLengthTime;
  float period;
  int playbackFrame;
  
 //**** SCULDY COMPUTATION TO PUT HERE ??

  Sampler( float newPeriod, float now,  float y ) {
    samples = new ArrayList<Sample>();
    startTime = now;
    addSample( now, y );
    playbackFrame = 0;
    period = newPeriod;
  }
  void addSample( float now, float y ) {
    samples.add( new Sample( now - startTime, y ) );
    sampleLengthTime = now - startTime;
    if( sampleLengthTime > period )
      bRecording = false;
      mouseRecorded = false;
    // round up the period to the next power of 2
    //period = sampleLengthTime < 1 ? 1 :
    //  pow( 2, max( 0, ceil( log( sampleLengthTime ) / log(2) ) ) );
  }
  void drawRecordingWithVertexes( float now ){
    if( samples.size() < 2 ) return;
    
    // draw the sample trail
    stroke( 200 );
    beginShape(LINES);
    for( int i=1; i<samples.size(); i++) {
      vertex( samples.get(i-1).y, samples.get(i).y );  // replace vertex with Pvector ???
  
    }
    endShape();

    // draw the current sample point
    //float st = (now - startTime) % period;
    float st = now % period;
    if( st > sampleLengthTime ) return;
    if( st < samples.get( playbackFrame ).t ) playbackFrame = 0;
    while( samples.get( playbackFrame+1).t < st )
      playbackFrame = (playbackFrame+1) % (samples.size()-1);

    Sample s0 = samples.get( playbackFrame );
    Sample s1 = samples.get( playbackFrame+1 );
    float t0 = s0.t;
    float t1 = s1.t;
    float dt = (st - t0) / (t1 - t0);
 
 // float x = mlerp( s0.x, s1.x, dt, 400 ); // interpolation with 'continious datas'
    float y = mlerp( s0.y, s1.y, dt, TWO_PI ); // interpolation with 'radian datas'
    
    interpolatedAngle = y;  // angle between themselves not from the first and the last!
    
    for( int i=1; i<samples.size(); i++) {
      
    print ( " interpolatedAngle "  + interpolatedAngle + " first angle " + samples.get(0) +  " last angle "  +  samples.get(samples.size()-1)); 
     }
      
    noStroke();
    fill( 255, 40, 40 );
    circle ( 100* cos ( interpolatedAngle)+400, 100*sin ( interpolatedAngle)+200, 20);
  }
}

Sampler sampler;
ArrayList<Sampler> samplers;

void setup() {
  size( 800, 800, P3D );
  frameRate( 30 );
  samplers = new ArrayList<Sampler>();
}

void draw() {
   println ( " measure " + measure );
     if  (actualSec<lastSec){         
         measure=measure+1;        
     }
         lastSec=actualSec; 
         actualSec = millis()%1000;  // Values from 0 - 2
  
  activeSamplingSecond();
  samplingMovementPro();  

  angleToInterpolate = calcAngle();
 
  
  fill( 100, 0, 0);
  circle ( 100* cos (angleToInterpolate)+200, 100*sin (angleToInterpolate)+200, 20);
   
  //----------------------------------------

  pushMatrix();
  translate(width/2, height/2);
  rotate(angleToInterpolate);
  translate(28, 0);
  rect(-30, -5, 60, 10);
  popMatrix();

  //----------------------------------------
  ellipse(width/2, height/2, 5, 5);
  text(degrees(angleToInterpolate), 22, 22);
  
  }
  
  //----------------------------------------------------------------------

float calcAngle() {


  float a = atan2(mouseY-height/2, mouseX-width/2);

  if (a<0) {
    a=map(a, -PI, 0,
      PI, TWO_PI);
  }
  return a;
}
    
 
void samplingMovementPro() {
  
  currTime = millis() * 0.001;  // seconds since app started
  background( 0 );
  for( int i=0; i<3; i++ ) {
    float p = pow( 2, i );
    stroke( 64, p == nextSamplePeriod ? 255 : 64, 64 );
    rect( (currTime % p) / p * width, i*10, 2, 8 );
  }

  if( bRecording ) {
      samplers.get(samplers.size()-1).addSample( currTime, angleToInterpolate ); // 
  }
  
  for( Sampler s : samplers )
    s.drawRecordingWithVertexes( currTime );
}

void mousePressed() {  
   mouseRecorded = true;
   measure=0;
   }


void activeSamplingSecond() { 
   if (measure==0 && actualSec!=lastSec && mouseRecorded == true) {
  bRecording = true;
  samplers.add( new Sampler( nextSamplePeriod, currTime, angleToInterpolate ) );// work almost with mouseY=v1 
  }
}

void keyPressed() {
  if( key == '1' )
    nextSamplePeriod = 1.0;
  else if( key == '2' )
    nextSamplePeriod = 2.0;
  else if( key == '4' )
    nextSamplePeriod = 4.0;
  else if( key == '8' )
    nextSamplePeriod = 8.0;
  else if( key == 'X' ) {
  if( samplers.size() > 0 )
      samplers.remove( samplers.size() - 1 );
  }
}

lerp() is an in-built function, see reference

Did you use it?

yes.
Here for 40 point between the first and last point.
for (int i = 0; i <= 40; i++) {
float x = lerp(x1, x2, i/40.0) + 40;
// float y = lerp(y1, y2, i/40.0);
point(x, 100);
}
But my little question is just how can i retreive the fist and the last data of my sample i tried this

for( int i=1; i<samples.size(); i++) {      
    print ( " interpolatedAngle "  + interpolatedAngle + " first angle " + samples.get(0) +  " last angle "  +  samples.get(samples.size()-1)); 
     }

but i read this

interpolatedAngle 3.626964 first angle scudly_sample_chisir_Tangente$Sample@654c74e9 last angle scudly_sample_chisir_Tangente$Sample@5638b99

Ok.
I retreive first and last data like that.

    print ( " interpolatedAngle "  + interpolatedAngle + " first angle " + samples.get(0).y +  " last angle "  +  samples.get(samples.size()-1).y); 

I’m going tot try to interpolate.

retrieve last point x,y - and then its angle a1

retrieve first point x,y - and then its angle a2

then lerp an angle between a1 and a2 in a for loop

calc points from lerp anglle

I think I found the solution with 2 interpolated point! Thank a lot!

int actualSec;
int lastSec;

float mlerp(float x0, float x1, float t, float M ){
float dx = (x1 - x0 + 1.5*M) % M - 0.5*M;
return (x0 + t * dx + M) % M;
}

float firstAngle, lastAngle;

float interpolatedAngle;
float angleToInterpolate;

boolean bRecording = false;
boolean mouseRecorded;
float currTime;
float nextSamplePeriod = 2.0;
int measure;

class Sample {
float t, y;
Sample( float t, float y ) {
this.t = t; this.y = y;
}
}
class Sampler {
ArrayList<Sample> samples;
float startTime;
float sampleLengthTime;
float period;
int playbackFrame;

//**** SCULDY COMPUTATION TO PUT HERE ??

Sampler( float newPeriod, float now, float y ) {
samples = new ArrayList<Sample>();
startTime = now;
addSample( now, y );
playbackFrame = 0;
period = newPeriod;
}
void addSample( float now, float y ) {
samples.add( new Sample( now - startTime, y ) );
sampleLengthTime = now - startTime;
if( sampleLengthTime > period )
bRecording = false;
mouseRecorded = false;
// round up the period to the next power of 2
//period = sampleLengthTime < 1 ? 1 :
// pow( 2, max( 0, ceil( log( sampleLengthTime ) / log(2) ) ) );
}
void drawRecordingWithVertexes( float now ){
if( samples.size() < 2 ) return;

// draw the sample trail
stroke( 200 );
beginShape(LINES);
for( int i=1; i<samples.size(); i++) {
vertex( samples.get(i-1).y, samples.get(i).y ); // replace vertex with Pvector ???

}
endShape();

// draw the current sample point
//float st = (now - startTime) % period;
float st = now % period;
if( st > sampleLengthTime ) return;
if( st < samples.get( playbackFrame ).t ) playbackFrame = 0;
while( samples.get( playbackFrame+1).t < st )
playbackFrame = (playbackFrame+1) % (samples.size()-1);

Sample s0 = samples.get( playbackFrame );
Sample s1 = samples.get( playbackFrame+1 );
float t0 = s0.t;
float t1 = s1.t;
float dt = (st - t0) / (t1 - t0);

// float x = mlerp( s0.x, s1.x, dt, 400 ); // interpolation with 'continious datas'
// float y = mlerp( s0.y, s1.y, dt, TWO_PI ); // interpolation with 'radian datas'

float y = mlerp( s0.y, s1.y, dt, TWO_PI ); // interpolation with 'radian datas' // angle interpolated between themselves not from the first and the last!

print ( " y " + y + " first angle " + samples.get(0).y + " last angle " + samples.get(samples.size()-1).y);

firstAngle = samples.get(0).y ;
lastAngle = samples.get(samples.size()-1).y ;

noStroke();
fill( 255, 40, 40 );
circle ( 100* cos ( y)+400, 100*sin ( y)+200, 20);

for (int i = 0; i <= 2; i++) {
interpolatedAngle = lerp(firstAngle, lastAngle, i/2.0);
fill( 255, 127*i, 127*i );
circle ( 100* cos ( interpolatedAngle)+400, 100*sin ( interpolatedAngle)+200, 20);
}
}

}

Sampler sampler;
ArrayList<Sampler> samplers;

void setup() {
size( 800, 800, P3D );
frameRate( 30 );
samplers = new ArrayList<Sampler>();
}

void draw() {
println ( " measure " + measure );
if (actualSec<lastSec){
measure=measure+1;
}
lastSec=actualSec;
actualSec = millis()%1000; // Values from 0 - 2

activeSamplingSecond();
samplingMovementPro();

angleToInterpolate = calcAngle();

fill( 100, 0, 0);
circle ( 100* cos (angleToInterpolate)+200, 100*sin (angleToInterpolate)+200, 20);

//----------------------------------------

pushMatrix();
translate(width/2, height/2);
rotate(angleToInterpolate);
translate(28, 0);
rect(-30, -5, 60, 10);
popMatrix();

//----------------------------------------
ellipse(width/2, height/2, 5, 5);
text(degrees(angleToInterpolate), 22, 22);

}

//----------------------------------------------------------------------

float calcAngle() {

float a = atan2(mouseY-height/2, mouseX-width/2);

if (a<0) {
a=map(a, -PI, 0,
PI, TWO_PI);
}
return a;
}

void samplingMovementPro() {

currTime = millis() * 0.001; // seconds since app started
background( 0 );
for( int i=0; i<3; i++ ) {
float p = pow( 2, i );
stroke( 64, p == nextSamplePeriod ? 255 : 64, 64 );
rect( (currTime % p) / p * width, i*10, 2, 8 );
}

if( bRecording ) {
samplers.get(samplers.size()-1).addSample( currTime, angleToInterpolate ); //
}

for( Sampler s : samplers )
s.drawRecordingWithVertexes( currTime );
}

void mousePressed() {
mouseRecorded = true;
measure=0;
}

void activeSamplingSecond() {
if (measure==0 && actualSec!=lastSec && mouseRecorded == true) {
bRecording = true;
samplers.add( new Sampler( nextSamplePeriod, currTime, angleToInterpolate ) );// work almost with mouseY=v1
}
}

void keyPressed() {
if( key == '1' )
nextSamplePeriod = 1.0;
else if( key == '2' )
nextSamplePeriod = 2.0;
else if( key == '4' )
nextSamplePeriod = 4.0;
else if( key == '8' )
nextSamplePeriod = 8.0;
else if( key == 'X' ) {
if( samplers.size() > 0 )
samplers.remove( samplers.size() - 1 );
}
}

But when I play back the mouvement, the circle doesn’t follow interpolated point.
How can I put them in the play back ?
How can I keep the play back movement for 2 seconds?

you have to add the new found points to the samples ArrayList?

Tricky.

Is it too fast or too slow at the moment?

maybe get rid of this. Then work with a timer,

  • When (2 * 1000 / number of points) milliseconds have passed, move to the next point in your animation.

Yes It’s totally my question, but i will never can do that by myself!

Should i post a new request?

1 Like

it’s a good idea to do this

Hi again !
I tried to mix your program with one made by an engineer.
The goal is the same, to create an intermediate point. An an other option if the movement pass through the first point.
But it saves data with another method, so I have a little bug when I press the mouse.
Could you have a glance please?

int actualSec,lastSec,measure,measureToStartRecording;;
boolean bRecording = false;
boolean mouseRecorded =  true;

float firstAngle, lastAngle;

float interpolatedAngle;
float angleToInterpolate;


float currTime;
float nextSamplePeriod = 2.0;



class Sample {
  int t;
  float  x, y;
  Sample( int t, float x, float y ) {
    this.t = t;  this.x = x;  this.y = y;
  }
}

class Sampler {
  
  ArrayList<Sample> samples;
  ArrayList<Sample> samplesModified;
  int startTime;
  int playbackFrame;
  
  Sampler() {
    samples = new ArrayList<Sample>();
        samplesModified = new ArrayList<Sample>();
    startTime = 0;
  }
  
  void beginRecording() {   
    samples = new ArrayList<Sample>();
    samplesModified = new ArrayList<Sample>();
    playbackFrame = 0;
  }
  
  
  void addSample( float x, float y ) {  // add radian sample when bRecording
    int now = millis();
    if( samples.size() == 0 ) startTime = now;
    samples.add( new Sample( now - startTime, x, y ) );
  }
  
  int fullTime() {
    return ( samples.size() > 1 ) ? 
    samples.get( samples.size()-1 ).t : 0;
  }
  
    void beginPlaying() {
    startTime = millis();
    playbackFrame = 0;
    println( samples.size(), "samples over", fullTime(), "milliseconds" );
    if(samples.size() > 0){
      float deltax = samples.get(0).x - samples.get(samples.size()-1).x;
      float deltay = samples.get(0).y - samples.get(samples.size()-1).y;
      float sumdist = 0;
      
      for(int i = 0; i < samples.size() - 1; i++) {
        sumdist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
      }
      
      samplesModified.add( new Sample(samples.get(0).t, samples.get(0).x , samples.get(0).y ) );
      float dist = 0;
      for(int i = 0; i < samples.size() - 1; i++) {
        dist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
        samplesModified.add( new Sample(samples.get(i+1).t, (int) (samples.get(i +1).x + (dist * deltax) / sumdist), (int) (samples.get(i+1).y +( dist * deltay )/ sumdist)) );
        print(samples.get(i).x);
        print(",");
        print(samples.get(i).y);
        print(",");
        print(samplesModified.get(i).x);
        print(",");
        print(samplesModified.get(i).y);
        println("");      
      }
    }
  }
  
 
  void draw() {
    stroke( 255 );
    
    //**RECORD
    beginShape(LINES);
    for( int i=1; i<samples.size(); i++) {
      vertex( samplesModified.get(i-1).x, samplesModified.get(i-1).y ); // replace vertex with Pvector
      vertex( samplesModified.get(i).x, samplesModified.get(i).y );
    }
    endShape();
    //**ENDRECORD
    
    //**REPEAT
    int now = (millis() - startTime) % fullTime();
    if( now < samplesModified.get( playbackFrame ).t ) playbackFrame = 0;
    while( samplesModified.get( playbackFrame+1).t < now )
      playbackFrame = (playbackFrame+1) % (samples.size()-1);
    Sample s0 = samplesModified.get( playbackFrame );
    Sample s1 = samplesModified.get( playbackFrame+1 );
    float t0 = s0.t;
    float t1 = s1.t;
    float dt = (now - t0) / (t1 - t0);
    float x = lerp( s0.x, s1.x, dt );
    float y = lerp( s0.y, s1.y, dt );
    circle( x, y, 10 );
  }
  
}

Sampler sampler;
ArrayList<Sampler> samplers;

void setup() {  
  size( 800, 800, P3D );
  frameRate(30); // when size is set as P3D (3 dimension) we have 27 or 28 frame (loop) per seconde
  sampler = new Sampler();
}

void draw() {
  background( 0 );
  activeSampling();
  stopSampling();
  
  if  (actualSec!=lastSec){
       lastSec=actualSec;
       measure++;
       textSize (100);
       text (measure, 100, 100 );
     }
     actualSec =(int) (millis()*0.001);  // 
  
   samplingMovementPro();
   
   angleToInterpolate = calcAngle();
 
  
  fill( 100, 0, 0);
  circle ( 100* cos (angleToInterpolate)+200, 100*sin (angleToInterpolate)+200, 20);
   
  //----------------------------------------

  pushMatrix();
  translate(width/2, height/2);
  rotate(angleToInterpolate);
  translate(28, 0);
  rect(-30, -5, 60, 10);
  popMatrix();

  //----------------------------------------
  ellipse(width/2, height/2, 5, 5);
  text(degrees(angleToInterpolate), 22, 22);
 
}


float calcAngle() {

 float a = atan2(mouseY-height/2, mouseX-width/2);

  if (a<0) {
    a=map(a, -PI, 0,
      PI, TWO_PI);
  }
  return a;
}


void samplingMovementPro(){
    currTime = millis() * 0.001;  // seconds since app started
  background( 0 );
  for( int i=0; i<3; i++ ) {
    float p = pow( 2, i );
    stroke( 64, p == nextSamplePeriod ? 255 : 64, 64 );
    rect( (currTime % p) / p * width, i*10, 2, 8 );
  }
  
  if( bRecording) { // recole radian
    samplers.get(samplers.size()-1).addSample( angleToInterpolate, angleToInterpolate ); // 
  }
  
  else {    
  if( sampler.fullTime() > 0 )
        sampler.draw();
  }
  }

void mousePressed() {
  bRecording = true;   // draw circle
  mouseRecorded = true;
  measure=0;
}
  
void activeSampling() { 
   if (measure==1 && actualSec!=lastSec && mouseRecorded == true) {
  sampler.beginRecording();
  }
}

void stopSampling() { 
   if (measure==3  && actualSec!=lastSec) {  
  mouseRecorded = false;
     //**REPEAT
  bRecording = false;
  sampler.beginPlaying();
  }
}
1 Like

really I don’t have time

you need to understand the principles at work and then apply them

it’s your program.