Transition from one vector array to another

Hi, I’m trying to create a smooth transition from one array of numbers to another but the numbers in question are all floating point numbers between 1 and -1, most of which below 0, so it’s been tricky. The arrays in question are also both 512 long which makes it even more confusing.
This is what I’ve done so far.

I calculated the difference between the two arrays (to give an idea I’ll type the first 10 numbers in each array):

    let array1 = [0.07622419629758599,0.05842459339422927,0.024668672017524977,-0.09559310702036261,-0.0024750374544100775,-0.13594952209716252,-0.018044980746120338,-0.0084552654890587,-0.06651388597692996,0.07836719933304802];
    let array2 = [-0.012255011871074164,0.030888419399735884,-0.06349531322375797,0.06757607476700675,0.06706755973946725,0.16300976540477416,-0.04452763179099016,0.022317034418650683,0.00980828811903469,0.05458174891305839];
    let arraySub = [];

    for(var i = 0; i < array1.length; i++){
        arraySub[i] = array2[i] - array1[i];
    }

so at this point the first 10 numbers of arraySub are:

arraySub = [-0.08847920816866016, -0.027536173994493388, -0.08816398524128294, 0.16316918178736936, 0.06954259719387733, 0.2989592875019367, -0.026482651044869823, 0.030772299907709383, 0.07632217409596465, -0.023785450419989626, -0.18150830247924366];

I’m finding it hard to understand how to increment each number so that the first array moves smoothly to become the second, especially since for looping with floating points is imprecise.

Any help on how to pull this off would be much appreciated :sunny:

I don’t fully understand but I made a program which transitions between two vectors (one is random, the other isn’t)

PVector v1 = new PVector(0,250); //0 = dir, 100 = power
PVector v2 = new PVector(random(TWO_PI),random(50,300));
float age = 0, maxAge = 100, cx = 300, cy = 300;
void setup() {
  size(600,600);
}
void draw() {
  background(0);
  if(mousePressed) age+=0.5;
  if(age > maxAge) {
    age = 0;
    v2 = new PVector(random(TWO_PI),random(50,300));
  }
  PVector displayV = transition(v1,v2,age,maxAge);
  stroke(255);
  line(cx,cy, cx + cos(displayV.x)*displayV.y, cy + sin(displayV.x)*displayV.y);
  stroke(255,0,0);
  line(cx,cy, cx + cos(v1.x)*v1.y, cy + sin(v1.x)*v1.y);
  stroke(0,0,255);
  line(cx,cy, cx + cos(v2.x)*v2.y, cy + sin(v2.x)*v2.y);
}
PVector transition(PVector start, PVector end, float step, float steps) {
  return( new PVector( map(step,0,steps,start.x,end.x), map(step, 0, steps, start.y, end.y) ));
}
1 Like

This is the sample idea I’ve come up w/: :woozy_face:

'use strict';

var counter = 0;

const
  STEPS = 10, DELAY = 1000,
  begin = Float64Array.of(.0762242, .0584246, .0246687),
  final = Float64Array.of(-.012255, .030888, -.063495),
  steps = final.map((val, idx) => (val - begin[idx]) / STEPS),
  transition = begin.slice();

function stepIncrease() {
  for (var i = 0; i < steps.length; transition[i] += steps[i++]);
  ++counter >= STEPS && clearInterval(id);
  console.log(counter, transition);
}

console.table(begin);
console.table(final);
console.table(steps);

const id = setInterval(stepIncrease, DELAY);

BtW, the code above can be copied & pasted on any browser console and even on Node.js! :innocent:

1 Like

Hello @fbrie002 ,

It helps to visualize the data:

Example
let y = 50;

function setup() 
  {
  createCanvas(400, 400);  
  translate(width/2, 0);
    let array1 = [0.07622419629758599,0.05842459339422927,0.024668672017524977,-0.09559310702036261,-0.0024750374544100775,-0.13594952209716252,-0.018044980746120338,-0.0084552654890587,-0.06651388597692996,0.07836719933304802];
    let array2 = [-0.012255011871074164,0.030888419399735884,-0.06349531322375797,0.06757607476700675,0.06706755973946725,0.16300976540477416,-0.04452763179099016,0.022317034418650683,0.00980828811903469,0.05458174891305839];

  let arraySub = [];

  
  strokeWeight(5);
      
  for(var i = 0; i < array1.length; i++)
    {
    arraySub[i] = array2[i] - array1[i];
    stroke(255, 0, 0);
    point(1000*array1[i], y); 
    point (1000*array2[i], y);
    stroke(0, 255, 0);
    let pTemp = arraySub[i];  // You need to modify this
    point(1000*(pTemp), y); 
    print(1000*arraySub[i]); 
    y+= 20;  
    }
  noLoop();  
  }

function draw() 
  {
  //background(220);
  }

This is what your code (modified) is doing:
image

Modified to plot midpoint:
image

Hint:
let pTemp = arraySub[i]/2 + array1[i];

I modified your code and you can improve on the hint; see the midpoint reference or do the math. :)

I can use the hint to plot anywhere between the two points; this is what the lerp() function does under the hood.

References:

Consider doing it without the lerp() function first.

:)

1 Like

Hello,

Some examples to explore:

// Linear Interpolation Examples
// v1.0.0
// GLV 2021-01-03

float x1, y1;
float x2, y2;

PVector v1, v2, v3;

float xInc, yInc;

PVector start;
PVector end;
PVector middle;

void setup() 
	{
  size(600, 200);
  x1 = -50;
  y1 = -50;
  x2 =  50;
  y2 =  50;
  
  v1 = new PVector(x1, y1);
  v2 = new PVector(x2, y2);
  
  start = new PVector(-50, -50);
  end = new PVector(50, 50);
  middle = new PVector(0, 0);
  
  strokeWeight(3);
	}

void draw() 
	{
  background(255);
  
// Counter for below
  
  float steps = 100;
  float step = frameCount%steps; 
  
//******************************************
// x, y coordinates

  translate(width/5, height/2);
  //line(x1, y1, x2, y2);
  
  xInc = (x2-x1)/steps;
  yInc = (y2-y1)/steps;

  stroke(255, 0, 0);
	line(x1, y1, x1+step*xInc, y1+step*yInc);

  //Just for fun!
  line(-50, 50, x1+step*xInc, y1+step*yInc);


//******************************************
// Vectors  
  
  translate(width/5, 0);
  
  v3 = v2.copy();
  v3.sub(v1);
  float mag = v3.mag();
  v3.normalize().mult(step*mag/100).add(v1);
  stroke(0, 255, 0);
  line(v1.x, v1.y, v3.x, v3.y);
  line(-50, 50, v3.x, v3.y);
  
//******************************************
// Vectors + co-ordinates 
  
  translate(width/5, 0);
  
  stroke(0, 0, 255);
  line(v1.x, v1.y, v1.x + step*xInc, v1.y + step*yInc);
  line(-50, 50, v3.x, v3.y);  
 
//******************************************
// PVector LERP

  translate(width/5, 0);
  
  stroke(255, 0, 255);
  middle = PVector.lerp(start, end, step/100);
  line(start.x, start.y, middle.x, middle.y);
  line(-50, 50, middle.x, middle.y);
  }

And I am sure there are more…

They are for Processing JAVA version.

image

References:

Enjoy the journey!

:)

2 Likes

Wow thank you so much for all your suggestions and references @glv ! I adapted part of your first code and combined it with some of the suggestions from the lerp() and midpoint documentation you mentioned.

This is what I ended up doing:

    let array1 = [0.07622419629758599,0.05842459339422927,0.024668672017524977,-0.09559310702036261,-0.0024750374544100775,-0.13594952209716252,-0.018044980746120338,-0.0084552654890587,-0.06651388597692996,0.07836719933304802];
    let array2 = [-0.012255011871074164,0.030888419399735884,-0.06349531322375797,0.06757607476700675,0.06706755973946725,0.16300976540477416,-0.04452763179099016,0.022317034418650683,0.00980828811903469,0.05458174891305839];

    let arraySub = [];

    let pTemp = [];

    let step = 0.1;
    let amount = 0;
    let difference = 0;

function draw(){

    if (amount > 1 || amount < 0){
        step *= -1;   
    }
    amount += step;
    
    difference = (difference + 0.1)%4;

    for (var i = 0; i < array1.length; i++) {
        arraySub[i] = array2[i] - array1[i];
        pTemp[i] = arraySub[i]/difference + array1[i];
    }
}

Definitely also gonna check out the last links you posted for future reference.

Thank you!! :cat2:

1 Like