Interpolation between two radian angle. Circular movement and Perfect arabesque to reach ;)

Hi !
I’m trying to sample movements on a motor position sensor.

This movement goes more or less quickly and always in the same direction.

The first goal is:
To repeat these circular movements and ensure that there is at least one transition point between the first and the last recorded point.

I manage to create 2 interpolated point but I have to put them back in sampled datas and keeping the mouvement played back for 2 sec. (If i record a movement for 2 second)

The seocnd goal is:
If the recorded circle is too long (the last point exceeds the first point by more than 20°), then the points that exceed will have to be eliminated.

The most complicated, I think, is to repeat this movement so that it lasts two seconds (with the intermediate point), if the recording time is two seconds.

I hope to see you very soon.
Thank you for your kindness and help.

To rec the movement click one.
To change time of recording tap 2 => 2 sec ; 4 => 4 sec …
To erase rec tap X


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 METHOD 
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 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 == '2' )
nextSamplePeriod = 2.0;
else if( key == '4' )
nextSamplePeriod = 4.0;
else if( key == 'X' ) {
if( samplers.size() > 0 )
samplers.remove( samplers.size() - 1 );
}
}