# Follow vector path

**URL:** <https://discourse.processing.org/t/follow-vector-path/9189>\
**Category:** Libraries\
**Created:** [March 11, 2019, 11:22am UTC](https://discourse.processing.org/t/follow-vector-path/9189 "2019-03-11T11:22:17Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![matyas](https://avatars.discourse-cdn.com/v4/letter/m/e19b73/32.png) [@matyas](https://discourse.processing.org/u/matyas)\
**Post date:** [March 11, 2019, 11:22am UTC](https://discourse.processing.org/t/follow-vector-path/9189/1 "2019-03-11T11:22:17Z")

</div>

Hi Everyone,

I am searching for a solution to move objects along vector paths (ex.: svg). I thought is a simple thing as the AE Lottie plugin is using something similar (AE animations converted to SVG - JSON to reproduce animation in Javascript)

lottie.loadAnimation({  
container: element, // the dom element that will contain the animation  
renderer: ‘svg’,  
loop: true,  
autoplay: true,  
path: ‘data.json’ // the path to the animation json  
});

Maybe someone has a simple solution?

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [March 11, 2019, 8:34pm UTC](https://discourse.processing.org/t/follow-vector-path/9189/2 "2019-03-11T20:34:00Z")

</div>

can you show a simple example sketch that shows the data? Preferable not svg but an ArrayList of Vectors e.g.?

---

<div class="post-metadata">

**Author:** ![matyas](https://avatars.discourse-cdn.com/v4/letter/m/e19b73/32.png) [@matyas](https://discourse.processing.org/u/matyas)\
**Post date:** [March 11, 2019, 9:12pm UTC](https://discourse.processing.org/t/follow-vector-path/9189/3 "2019-03-11T21:12:26Z")

</div>

Thanks for the reply Chrisir.

A very simple path .json data in Lottie looks like this:

{“v”:“4.5.5”,“fr”:60,“ip”:0,“op”:65,“w”:500,“h”:500,“ddd”:0,“assets”:[],“layers”:[{“ddd”:0,“ind”:0,“ty”:4,“nm”:“doneIcon contornos”,“ks”:{“o”:{“a”:0,“k”:100},“r”:{“a”:0,“k”:0},“p”:{“a”:0,“k”:[250,250,0]},“a”:{“a”:0,“k”:[250,250,0]},“s”:{“a”:0,“k”:[100,100,100]}},“ao”:0,“shapes”:[{“ty”:“gr”,“it”:[{“ind”:0,“ty”:“sh”,“ks”:{“a”:0,“k”:{“i”:[[0,0],[0,0],[0,0]],“o”:[[0,0],[0,0],[0,0]],“v”:[[-167.614,16.761],[-68.75,116.193],[167.614,-116.193]],“c”:false}},“nm”:“Trazado 1”,“mn”:“ADBE Vector Shape - Group”},{“ty”:“tm”,“s”:{“a”:1,“k”:[{“i”:{“x”:[0.667],“y”:[1]},“o”:{“x”:[0.333],“y”:[0]},“n”:[“0p667\_1\_0p333\_0”],“t”:0,“s”:[0],“e”:[100]},{“t”:24}],“ix”:1},“e”:{“a”:0,“k”:0,“ix”:2},“o”:{“a”:0,“k”:0,“ix”:3},“m”:1,“ix”:2,“nm”:“Recortar trazados 1”,“mn”:“ADBE Vector Filter - Trim”},{“ty”:“st”,“c”:{“a”:0,“k”:[0.3,0.91,0.02,1]},“o”:{“a”:0,“k”:100},“w”:{“a”:0,“k”:42},“lc”:1,“lj”:1,“ml”:10,“nm”:“Trazo 1”,“mn”:“ADBE Vector Graphic - Stroke”},{“ty”:“tr”,“p”:{“a”:0,“k”:[253.614,247.648],“ix”:2},“a”:{“a”:0,“k”:[0,0],“ix”:1},“s”:{“a”:0,“k”:[100,100],“ix”:3},“r”:{“a”:0,“k”:0,“ix”:6},“o”:{“a”:0,“k”:100,“ix”:7},“sk”:{“a”:0,“k”:0,“ix”:4},“sa”:{“a”:0,“k”:0,“ix”:5},“nm”:“Transformar”}],“nm”:“Grupo 1”,“np”:3,“mn”:“ADBE Vector Group”}],“ip”:0,“op”:66,“st”:0,“bm”:0,“sr”:1}]}

I am testing a few things here: [https://codepen.io/czelmatyas/pen/PLJGVG](https://codepen.io/czelmatyas/pen/PLJGVG) (sorry for the super messy code). I would like to achieve more complex movements of the ellipse I am animating, preferably following a vector path.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [March 11, 2019, 9:38pm UTC](https://discourse.processing.org/t/follow-vector-path/9189/4 "2019-03-11T21:38:48Z")

</div>

Thanks

here is a simple movement using curvepoint (comparable to lerp)

> [@Bezier Curve move weight points](https://discourse.processing.org/t/bezier-curve-move-weight-points/8872/3):
>
> In addition to my post (that has been linked above) a small sketch. Chrisir ArrayList\<SimplePoint\> bList = new ArrayList(); boolean runPoints=false; float t; // drag with mouse SimplePoint holding; boolean hold=false; void setup() { size(800, 800); bList = new ArrayList(); background(0); } void draw() { background(0); // Run green ball if (runPoints&&bList.size()==4) { displayRunningBall(); } // decoration and showing curve --------- // show points int i\_sho…

**A more complex sketch**

here is a more complex sketch:

The `ArrayList<PointMy> listPointMy` are the vectors (I my sketch this is a track for a rollercoaster);  
you want to look at function `rollerCoaster()`

Chrisir

```auto

// Track for the rollercoaster: 
// holding the curveVertex points in 3D - the core data. Here you add and edit your points. 
ArrayList<PointMy> listPointMy = new ArrayList();

// move a sphere along the curve (Rollercoaster) 
boolean showRollercoasterFlag = false; 
int showRollercoaster_i; // current number of sphere on track for the Rollercoaster CAR 
int i2=0; // counter for the taken steps between 2 single points of track for rollercoaster  
boolean firstTime=true;
PVector camPV=new PVector();

// ---------------------------------------------------------------------
// CORE functions 

void setup() {
  size(1440, 880, P3D);
  background(255);

  makeArrayList(); // the track
}// func 

void draw() {
  drawForNormal();
}//draw

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

void drawForNormal() {

  background(255);
  lights();

  // show ArrayList
  showArrayList(); 

  if (true) {
    rollerCoaster();
  }//if
}// func 

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

void makeArrayList() {
  // http://de.wikipedia.org/wiki/Ellipse#Ellipsengleichung_.28Parameterform.29

  float radiusX=300; 
  float radiusY=110;

  float centerX=0;
  float centerZ=0; 

  for (int angleStar = 0; angleStar <= 360; angleStar += 4) {

    float starX = centerX + (cos (radians(angleStar)) * radiusX);
    float starY = 0;
    float starZ = centerZ + (sin (radians(angleStar)) * radiusY);

    // the part on the right gets elevated 
    if (starX>220) {
      starY=map(starX-220, 0, 310, -10, -420);
    }

    PVector newPVector = new PVector(starX, starY, starZ);
    listPointMy.add ( new PointMy ( newPVector, false) ); // 3D
  }//for
  listPointMy.get(65).p.y -= 155;
}//func 

void showArrayList() {
  // show the curve 

  noFill();
  stroke(0);
  beginShape();
  int i=0;
  if (listPointMy.size()>0) {
    listPointMy.get(i).useAsCurveVertexPVector();
    for ( i = 0; i < listPointMy.size(); i++) {
      listPointMy.get(i).useAsCurveVertexPVector();
    }
    i=listPointMy.size()-1;
    listPointMy.get(i).useAsCurveVertexPVector();
  }//if
  endShape();

  //show the points (additionally)
  noStroke();
  float rad=3;
  for ( i = 0; i < listPointMy.size(); i++) {
    PointMy pm = listPointMy.get(i);
    PVector pv=pm.p;
    // if we are close to the mouse, color green, else red
    if (dist(mouseX, mouseY, pv.x, pv.y)<11 || pm.selected) {
      // near to mouse 
      fill( 0, 255, 0); // green
      rad=7;
    } else {
      // normal 
      fill(255, 0, 0); // red
      rad=3;
    }
    pm.showAsSphere(rad);
  }//for
}//func

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

// interprete the spline as a rollercoaster track with a CAR on it

void rollerCoaster() {

  ellipseMode(CENTER);

  // get two points between which the CAR currently is running  
  PointMy pm1=listPointMy.get( showRollercoaster_i );
  PointMy pm2=listPointMy.get( showRollercoaster_i+1 ); 

  // get dist between 2 points 
  float dist1 = pm1.p.dist(pm2.p);
  // calculate the steps between the 2 points depending on dist1 between them (smooth running) 
  int steps; // = 9;
  steps = int(dist1 / 2);

  // calc t (can be seen as amt in lerp() / curvePoint) 
  float t = i2 / float(steps);

  // similar to lerp() wth amt:  
  float x = curvePoint(pm1.p.x, pm1.p.x, pm2.p.x, pm2.p.x, t);
  float y = curvePoint(pm1.p.y, pm1.p.y, pm2.p.y, pm2.p.y, t);
  float z = curvePoint(pm1.p.z, pm1.p.z, pm2.p.z, pm2.p.z, t);

  // different camera view for rollercoaster view
  setRollerCoasterCamera(x, y, z, t); 

  // show ball&box [the rollercoaster car] 
  if (true) { 
    fill(255, 2, 244);
    noStroke(); 
    pushMatrix(); 
    translate(x, y, z);
    box(9);
    translate(0, -5, 0);
    sphere(7); 
    popMatrix();
  }

  i2++; 
  if (i2>steps) {
    showRollercoaster_i++; 
    if (showRollercoaster_i>listPointMy.size()-2) { // little rough management at the end of arraylist... ??? 
      showRollercoaster_i=0;
    }//if
    i2=0;
  }//if
}//func

void setRollerCoasterCamera(float x, float y, float z, 
  float t) {
  // camera view for rollercoaster view 
  camPV = getCameraPositionFromBall(x, y, z); 
  camera(camPV.x, camPV.y-4, camPV.z, 
    0, 0, 0, 
    0, 1, 0);
}//func 

PVector getCameraPositionFromBall(float bx, float by, float bz) {

  // leading to a result that has the points nicely on a circle. 

  // Usage: centerPV is at the center of a virtual circle, outsidePV on its circumference. 
  // Function returns the point (new PVector(x1, y1, z1)) with the radius radius1 that prolongs the Radius 
  // from centerPV over outsidePV (further out) to the resulting PVector new PVector(x1, y1, z1).

  PVector centerPV = new PVector(0, 0, 0); 
  PVector outsidePV = new PVector(bx, by, bz);

  float angle1 = atan2(outsidePV.z-centerPV.z, outsidePV.x-centerPV.x);

  float radius1 = 0;// pre-init
  // adjust : we calculate the radius here
  // radius1 = 700/2 + 120;

  float d0 = centerPV.dist(outsidePV);
  // d0 = dist(centerPV.x, centerPV.y, outsidePV.x, outsidePV.y);
  float d1 = map (d0, 10, 1000, 140, 1450); // float d1 = map (d0, 10, 1000, 40, 1350);
  radius1 = d1; 

  float x1 = cos(angle1) * radius1 + centerPV.x;
  float y1 = 0;
  //y1 = lerp(centerPV.y, outsidePV.y, map (d0, 10, 1000, 1.5, 1.9));
  //y1 = lerp(centerPV.y, outsidePV.y, 1.3);
  y1 = outsidePV.y-26;
  float z1 = sin(angle1) * radius1 + centerPV.y;

  return new PVector(x1, y1, z1);
} // method 

// ==================================================================

class PointMy {

  // one point one the track 

  PVector p; // position 
  boolean selected=false; // selected y/n

  float theX, theY; // screenX and screenY

  // constructor 
  PointMy( PVector p_, boolean selected_ ) {
    p = p_.copy();
    selected = selected_;
  } // constructor

  void showAsSphere( float rad ) {
    pushMatrix();
    translate(p.x, p.y, p.z);

    theX = screenX(0, 0, 0); // monitor and store screen position 
    theY = screenY(0, 0, 0);

    noStroke();
    sphere(rad); 
    popMatrix();
  } // method

  void useAsCurveVertexPVector() {
    // like curveVertex but gets a PVector as input  
    // (just an easy way to use vectors for curveVertex)
    curveVertex(p.x, p.y, p.z);
  } // method 
  //
}//class
//

```

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [April 9, 2019, 3:18pm UTC](https://discourse.processing.org/t/follow-vector-path/9189/5 "2019-04-09T15:18:09Z")

</div>

2 posts were split to a new topic: [Can p5.js export lottie files?](https://discourse.processing.org/t/can-p5-js-export-lottie-files/10134)
